@zksecurity/slack-events
v0.2.4
Published
Pair a terminal with a pi-mom Slack event feed
Readme
Slack Events Client
Requires Node.js 24 or newer. Run on the machine that will consume your events:
npx @zksecurity/slack-events pair https://YOUR-EVENT-HOSTLeave the command running and open its printed link in your laptop's browser
(or any browser with your Slack login). Confirm the matching terminal code and
authorize Slack. The waiting command saves the feed credential on the originating
machine, prints Paired with ..., and exits. No inbound port, SSH forwarding,
or copying a credential back is needed.
Pairing does not start a listener. On the same machine, run:
npx @zksecurity/slack-events listenThe server filters events, including backlog, to conversations you have joined. Membership is cached for one minute, but new events from channels absent from the snapshot trigger a fresh check before filtering. Events without an identifiable joined channel are omitted.
listen retries temporary feed failures with exponential backoff from one to thirty seconds and honors longer Retry-After delays. Retries do not advance the read cursor or ACK events. Invalid or revoked feed credentials stop the listener. Other commands do not retry automatically.
listen stays running and prints one JSON object per event from your personal
feed, including available backlog and new arrivals. It uses the saved credential;
no URL or browser login is needed. Stop with Ctrl+C and run listen again later
without repeating pairing.
Printing events does not acknowledge them. For durable consumption, save all
events through a sequence cursor before acknowledging it:
npx @zksecurity/slack-events ack COMMITTED_CURSORUnacknowledged events replay after restarting the listener, subject to server
retention. Deduplicate by eventId; never ACK merely because an event reached
stdout or a pipe.
Other commands:
npx @zksecurity/slack-events list
npx @zksecurity/slack-events revoke SUBSCRIPTION_IDCredentials are stored with mode 0600 in
$XDG_CONFIG_HOME/slack-events/credentials.json or ~/.config/slack-events/credentials.json.
For existing browser-issued pairing codes, pair SERVER CODE is also supported.
Maintainers
From a pi-mom checkout with development dependencies installed:
npm pack ./packages/slack-eventsThe prepack step compiles only the dependency-free client source. Inspect and
test the tarball before publishing it with npm publish TARBALL under an
authorized npm account. Publishing is independent of the bot's npm package.
Read Slack context and download files
After deploying the matching server and reauthorizing the expanded user scopes:
slack-events users
slack-events channels
slack-events channels --limit 200 --cursor NEXT_CURSOR
slack-events user U012345
slack-events bot B012345
slack-events channel C012345
slack-events message C012345 1788884385.665039
slack-events history C012345 --limit 50 --cursor NEXT_CURSOR
slack-events thread C012345 1788881468.871969 --limit 50
slack-events file F012345
slack-events download F012345 ./attachment.pdf
slack-events listenUse users and channels to discover IDs before making individual reads. They return Slack JSON with members or channels arrays containing IDs and names. channels includes public/private channels and direct/group conversations available to your user grant. Follow response_metadata.next_cursor with --cursor until it is empty; each call returns one page, and --limit accepts 1-200. The existing list command lists feed subscriptions, not Slack conversations.
Slack identifies a thread by its channel ID and root message timestamp, not a separate thread ID. Use history CHANNEL_ID to find a root message's ts, then run thread CHANNEL_ID ROOT_TS. If you have a reply, its thread_ts identifies the root; use message CHANNEL_ID MESSAGE_TS to inspect it when needed. Keep timestamps as strings with all decimal digits.
Read commands return Slack JSON, including pagination cursors. message returns
one target message and its reactions through reactions.get; thread takes the
parent timestamp. Download streams file bytes via the event server using the
subscriber's user grant, refuses to overwrite existing paths, and writes mode
0600. External files without a Slack-hosted download are unsupported. A failed
transfer may leave a partial output file; remove that file before retrying.
listen adds context.users / context.channels name maps while preserving the original event and cursor. The listener waits for the initial user/channel snapshot before polling events, then refreshes it in the background every six hours. Missing names use individual user / bot / channel lookups with a two-second deadline per request. Successful lookups are cached for six hours; failed lookups and directory refreshes retry after a minute. Failed refreshes retain the previous snapshot. Inaccessible names can remain unresolved; original IDs stay in the JSON. Standalone file shares also get context.files metadata, fetched separately with a two-second deadline; failure leaves the original event intact and the files list empty. Use file or download to retry retrieving the file.
Bot-only message authors and thread roots are resolved through bots.info when Slack omits the embedded name. This uses the existing users:read scope. Bot IDs map to names in context.users; slack-events bot BOT_ID returns the bot profile.
No read command changes the ACK cursor. The CLI uses its existing paired feed credential; Slack user tokens stay on the server. No bot credential is used.
The packaged slack-events skill is a manual for agents consuming these events and using the CLI.
