@estebanforge/pi-slack-me
Slack tools for Pi that act as YOU, not as a bot. Adds 8 LLM-callable tools (slack_*) that read channels, threads, DMs, and search results, plus post, update, and delete messages using a Slack USER token (xoxp-). No bot to invite, no footprint in the work
Package details
Install @estebanforge/pi-slack-me from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@estebanforge/pi-slack-me- Package
@estebanforge/pi-slack-me- Version
1.1.0- Published
- Jul 9, 2026
- Downloads
- 281/mo · 18/wk
- Author
- estebanforge
- License
- MIT
- Types
- extension
- Size
- 143.8 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./extensions"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@estebanforge/pi-slack-me
Slack tools for pi that act as you, not as a bot.
The extension adds 8 LLM-callable tools that read and write Slack using a user token (xoxp-). There is no bot to invite into channels and no visible footprint in the workspace: the Slack app inherits your membership and access, so the agent sees (and posts as) exactly what you do - public channels, private channels you're in, your DMs, and group DMs.
Use it when you want an agent to consume information from Slack (read feedback, follow issues, search past decisions, pull a thread into a coding session) or post on your behalf (send a message, reply in a thread, DM someone, edit or delete your own messages). Every write opens in a review dialog before it touches Slack, so nothing is sent or deleted without your say-so.
Why a user token (and not a bot)
A bot token (xoxb-) can only read channels the bot has been explicitly invited to, and it can never read your DMs. That forces a visible new member into every channel you care about. A user token (xoxp-) speaks as your user, so the app reads anything your user can read, with no /invite step and no bot appearing anywhere. This is a fully supported Slack auth mode - every *:history scope lists User as a supported token type.
The tradeoff, per Slack's docs: the app shows an OAuth consent screen the first time you install it to the workspace, and workspaces requiring admin approval need an admin to approve it once. The app has no bot user, so it won't appear in member lists or channels - the only visible signal is in the workspace's Apps admin panel.
Tools
| Tool | Description |
|---|---|
slack_list_channels |
List conversations you can see (channels, DMs, group DMs) via users.conversations |
slack_read_messages |
Read message history from a channel or DM (conversations.history) |
slack_read_thread |
Read all replies in a thread (conversations.replies) |
slack_search |
Full-text search across the workspace (search.messages) |
slack_download_file |
Download a shared file/image to a temp dir (files.info + download) |
slack_post_message |
Post a message to a channel, group DM, or existing DM as you; DM by user ID (chat.postMessage + conversations.open) |
slack_update_message |
Edit the text of a message you previously posted (chat.update) |
slack_delete_message |
Permanently delete one of your messages; always confirmed (chat.delete) |
User IDs are resolved to display names (cached), so feedback reads as **Esteban**: ... rather than **U12345**: ....
Write tools & review
The three write tools (slack_post_message, slack_update_message, slack_delete_message) post as you. A user token posts as your user natively - no as_user flag, no bot. You can only edit or delete messages you authored.
Before any write reaches Slack, the extension shows it for review:
- post / update open an editable dialog - trim or rewrite the text, then accept or cancel (Esc).
- delete asks yes/no - it is irreversible, so it is always confirmed even when the review flag is off, and it is refused in headless mode rather than running blind.
The editable review is on by default and is governed by the slack-confirm-write flag.
Headless mode (no interactive UI, e.g. an unsupervised/automated run): post and update are refused by default - the extension will not post on your behalf without a human present. Opt in with the slack-allow-headless-write flag if you genuinely want unsupervised writes (e.g. scheduled/automation use). Delete is always blocked in headless mode, no opt-in.
/slack config- settings modal (TUI)/slack confirm on//slack confirm off- toggle the editable review (delete stays guarded regardless)/slack headless on//slack headless off- opt in/out of unsupervised (no-UI) writes
Setup
1. Create a Slack app
Go to api.slack.com/apps → Create New App → From scratch. Give it a name (e.g. pi-slack-me) and select your workspace.
2. Add User Token Scopes
In the left sidebar → OAuth & Permissions → scroll to User Token Scopes (not Bot Token Scopes).
| Scope | Enables |
|---|---|
channels:read |
list public channels |
groups:read |
list private channels |
im:read |
list DMs |
mpim:read |
list group DMs |
channels:history |
read public channel messages |
groups:history |
read private channel messages |
im:history |
read your DMs |
mpim:history |
read group DMs |
users:read |
resolve user IDs to display names |
search:read |
slack_search (optional but recommended) |
files:read |
download shared files (slack_download_file) |
chat:write |
post / update / delete messages as you (slack_post_message, slack_update_message, slack_delete_message) |
im:write |
DM someone via to_user (slack_post_message opens the DM via conversations.open; not needed for posting to an existing channel/group DM) |
No Bot Token Scopes are needed. There is no bot.
Scope at a glance:
chat:writecovers posting, editing, and deleting. Addim:writeonly if you useto_user(DM a user by ID). Reading needs the*:read/*:historyscopes above.
Upgrading from a read-only install (v1.x)
If you installed before write support, your existing token lacks chat:write and write tools will return missing_scope. To add it:
- api.slack.com/apps -> your app -> OAuth & Permissions -> User Token Scopes.
- Add
chat:write(post/update/delete) and, if you will useto_userto DM people,im:write(opens the DM). - Save changes, then click Reinstall to {Workspace} (Slack requires a reinstall for new scopes to take effect).
- Copy the new User OAuth Token (
xoxp-...) - it changes on reinstall. export SLACK_USER_TOKEN=xoxp-...with the new value.
No /invite step is needed at any point.
3. Install to workspace
Still on OAuth & Permissions → click Install to {Workspace-name} → authorize. (If your workspace requires admin approval, an admin must approve it.) The consent screen reflects the user scopes above.
4. Copy the user token
After installing, the same page shows:
- User OAuth Token — starts with
xoxp-→ yourSLACK_USER_TOKEN
export SLACK_USER_TOKEN=xoxp-...
5. Done
No /invite step. No bot in any channel. The token reads as your user.
Install
pi install @estebanforge/pi-slack-me
Commands
| Command | Description |
|---|---|
/slack |
Show token status and usage |
/slack channels [types] |
List conversations (prefills slack_list_channels) |
/slack dms |
List your DMs (prefills slack_list_channels with types=im) |
/slack read <channel> [N] |
Read recent messages (prefills slack_read_messages) |
/slack thread <channel> <ts> |
Read a thread (prefills slack_read_thread) |
/slack search <query> |
Search messages (prefills slack_search) |
/slack post <channel> <text> |
Post a message (prefills slack_post_message) |
/slack dm <user> <text> |
DM a user by ID (prefills slack_post_message with to_user) |
/slack reply <channel> <ts> <text> |
Reply in a thread (prefills slack_post_message with thread_ts) |
/slack edit <channel> <ts> <text> |
Edit your message (prefills slack_update_message) |
/slack delete <channel> <ts> |
Delete your message (prefills slack_delete_message) |
/slack config |
Settings modal (write review gate) |
/slack confirm on|off |
Toggle write review (delete stays guarded) |
Notes
- Session scope: the user token grants workspace-wide read access as you. Treat it like any other credential -
0600on any file it lands in, never commit it, rotate it if leaked. - Token rotation: if Slack invalidates the token (e.g. you revoke the app or change your password), calls return
invalid_auth. Re-install the app and updateSLACK_USER_TOKEN. - Rate limits: Slack returns
429with aRetry-Afterheader on rate limit; this extension surfaces the retry hint in the error text. Bulk reads (hundreds of channels) should page via the returned cursor. Writes (chat.postMessage) are limited to ~1/sec per channel - avoid tight-loop bulk posting. - DM author names: DM message payloads carry the other user's ID; the extension resolves it via
users.info. Your own messages show as your display name.
Development
npm install
npm run typecheck # tsc --noEmit
npm test # vitest run
npm run test:watch
License
MIT