feat(slack): reproducible "all channels" wiring (list + invite helpers) - #19
Merged
Merged
Conversation
The Slack Socket Mode adapter (bidirectional) and launchd LaunchAgent already exist. The missing piece was reproducible "all channels" wiring: a Slack bot only sees/posts in channels it has joined, and there's no bulk-add API. Add two CLI helpers: - `hermes slack channels` — list channels and report which ones the bot is / isn't a member of (audits coverage, reports gaps). - `hermes slack invite [--all|--channel] [--user-token] [--dry-run]` — self-join public channels via conversations.join; invite the bot to private channels via conversations.invite when a user token is given. Also: - add `channels:join` bot scope to the generated manifest so self-join works - add `hermes slack manifest --yaml` (Slack accepts JSON or YAML) - document SLACK_USER_TOKEN, the connections:write app-token requirement, and the invite-per-channel vs read-all (user token) trade-off - tests for channel listing, invite paths, and manifest rendering
🔎 Lint report:
|
| Rule | Count |
|---|---|
unresolved-import |
2 |
First entries
tests/hermes_cli/test_slack_cli.py:5: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`
hermes_cli/slack_cli.py:241: [unresolved-import] unresolved-import: Cannot resolve imported module `slack_sdk`
✅ Fixed issues: none
Unchanged: 4795 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
The fetchNpmDeps hash in nix/web.nix drifted from web/package-lock.json (pre-existing on main after an earlier npm dependabot bump), failing the `nix` build check. Update to the hash computed by the nix build itself.
dizhaky
marked this pull request as ready for review
June 16, 2026 19:27
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Task: wire the Hermes agent to all Slack channels, bidirectionally.
After auditing the repo, most of this already exists — so this PR fills the one genuine gap rather than reinventing wiring.
What already exists (verified, no changes needed)
gateway/platforms/slack.pyalready usesslack-boltAsyncSocketModeHandlerwithSLACK_BOT_TOKEN(xoxb-) +SLACK_APP_TOKEN(xapp-), listens forapp_mention/message.*, replies in-thread, handles slash commands, reactions, file uploads, and multi-workspace.chat:write+SlackAdapter.send().hermes gateway service installgenerates anai.hermes.gatewaylaunchd LaunchAgent withKeepAlive, so the Socket Mode client reconnects on wake/reboot.hermes slack manifest.The gap this PR closes — "all channels"
A Slack bot only sees/posts in channels it has joined, and there's no bulk-add API. That made "all channels" a manual checklist. New helpers make it reproducible:
hermes slack channels— list every channel the bot token can see and report which it is / isn't a member of (audits coverage, reports gaps).hermes slack invite [--all | --channel NAME/ID] [--user-token] [--dry-run]— self-join public channels viaconversations.join; invite the bot to private channels viaconversations.invitewhen a user token is supplied.Also:
channels:joinbot scope to the generated manifest so self-join works.hermes slack manifest --yaml(Slack accepts JSON or YAML).SLACK_USER_TOKEN, theconnections:writeapp-token requirement, and the invite-per-channel (safe default) vs read-all user token trade-off.Tests
tests/hermes_cli/test_slack_cli.py— channel listing/pagination, public-join vs private-skip vs user-token-invite paths,already_in_channelhandling, and JSON/YAML manifest rendering. All 13 pass; full Slack suite (199) green; ruff clean.Operator action items (only you can do these)
hermes slack manifest --yaml), enable Socket Mode, generate thexapp-app token withconnections:write, install to workspace.SLACK_BOT_TOKEN+SLACK_APP_TOKENin~/.hermes/.env.hermes slack invite --all, then verify:@mentionthe bot (in-thread reply), post outbound, and confirm the launchd job logs "Socket Mode connected".https://claude.ai/code/session_01XMJSckDomPtewEipAjfSGD
Generated by Claude Code