Repository navigation
feat(channels): add join and leave - #211
Conversation
Joining a public channel as yourself is what lets you invite others to a channel you are not in, and slck had no way to do it. Both commands are idempotent: Slack reports an existing membership as an already_in_channel warning and a missing one as not_in_channel on a successful response.
monit-reviewer
left a comment
There was a problem hiding this comment.
Automated PR Review
Reviewed commit: c9e34be6068b
Profile: claude-monit-reviewer - Posting as: monit-reviewer
Summary
| Reviewer | Findings |
|---|---|
| go:implementation-tests | 0 |
| harness-engineering:repo-health | 0 |
| policies:conventions | 0 |
| architecture:solid-reviewer-agnostic | 1 |
| security:code-auditor | 0 |
| documentation:docs | 0 |
architecture:solid-reviewer-agnostic (1 finding)
Minor - internal/client/client.go:973
U-T1: the behavior this PR adds is the membership signal parsed in JoinChannel (
already_in_channelinresponse_metadata.warnings) and LeaveChannel (not_in_channel), but no test checks it. TestRunJoin and TestRunLeave in channels_test.go only assertrequire.NoErrorfor both the member and non-member replies. IfJoinChannelalways returnedfalse, or the warning were read from the top-levelwarningstring, every test would still pass and the CLI would print "Joined" for an existing membership. Suggested fix: addTestClient_JoinChannel_*andTestClient_LeaveChannel_*cases to internal/client/client_test.go, matching the existingTestClient_ArchiveChannel_Successpattern, and assert the returned bool for each reply shape. Alternatively (or as well), have the cmd tests capture output the waycaptureOutputdoes in internal/cmd/emoji/emoji_test.go and assert "Already in channel" / "Not in channel".
Reviewer Coverage
go:implementation-tests— complete (broad); inspected 5 assigned files (7 inspected across reviewers):internal/client/client.go,internal/cmd/channels/channels.go,internal/cmd/channels/channels_test.go,internal/cmd/channels/join.go,internal/cmd/channels/leave.go; skipped: none; constraints: noneharness-engineering:repo-health— complete (constrained); inspected 5 assigned files (7 inspected across reviewers):internal/client/client.go,internal/cmd/channels/channels.go,internal/cmd/channels/channels_test.go,internal/cmd/channels/join.go,internal/cmd/channels/leave.go; skipped: none; constraints: nonepolicies:conventions— complete (broad); inspected 5 assigned files (7 inspected across reviewers):README.md,internal/cmd/channels/channels.go,internal/cmd/channels/channels_test.go,internal/cmd/channels/join.go,internal/cmd/channels/leave.go; skipped: none; constraints: Shared cli-common docs and .github automation were not available as sibling checkouts in this workbench; convention check relied on in-repo precedent (internal/cmd/channels/invite.go) rather than canonical external docs.architecture:solid-reviewer-agnostic— complete (broad); inspected 4 assigned files (7 inspected across reviewers):internal/client/client.go,internal/cmd/channels/channels.go,internal/cmd/channels/join.go,internal/cmd/channels/leave.go; skipped: none; constraints: Ran go build ./... and go test for internal/cmd/channels and internal/client at the PR head; both pass.security:code-auditor— complete (broad); inspected 3 assigned files (7 inspected across reviewers):internal/client/client.go,internal/cmd/channels/join.go,internal/cmd/channels/leave.go; skipped: none; constraints: nonedocumentation:docs— complete (broad); inspected 2 assigned files (7 inspected across reviewers):README.md,integration-tests.md; skipped: none; constraints: none
Inspected files (7)
README.mdintegration-tests.mdinternal/client/client.gointernal/cmd/channels/channels.gointernal/cmd/channels/channels_test.gointernal/cmd/channels/join.gointernal/cmd/channels/leave.go
0 PR discussion threads considered. 0 summarized; 0 resolved.
Completed in 2m 57s | ~$2.43 (est.) | claude-sonnet-5, claude-opus-5-5 | cr 0.10.319
| Field | Value |
|---|---|
| Model | claude-sonnet-5, claude-opus-5-5 |
| Reviewers | go:implementation-tests, harness-engineering:repo-health, policies:conventions, architecture:solid-reviewer-agnostic, security:code-auditor, documentation:docs |
| Engine | claude_cli · claude-sonnet-5, claude-opus-5-5 |
| Reviewed by | cr · monit-reviewer |
| Duration | 2m 57s wall · 6m 26s compute |
| Cost | ~$2.43 (est.) |
| Pricing basis | anthropic-public-2026-09-23 |
| Tokens | 100 in / 18.4k out |
Per-workstream usage
orchestrator-selection— claude-sonnet-5- In: 6
- Out: 3.6k
- Cache read: 93.9k
- Cache create: 41.1k
- Cost: ~$0.22 (est.)
- Duration: 47s
go:implementation-tests— claude-sonnet-5- In: 16
- Out: 2.5k
- Cache read: 390.8k
- Cache create: 64.1k
- Cost: ~$0.36 (est.)
- Duration: 1m 05s
harness-engineering:repo-health— claude-sonnet-5- In: 22
- Out: 3.6k
- Cache read: 603.5k
- Cache create: 46.8k
- Cost: ~$0.34 (est.)
- Duration: 1m 33s
policies:conventions— claude-sonnet-5- In: 14
- Out: 2.2k
- Cache read: 340.9k
- Cache create: 41.1k
- Cost: ~$0.25 (est.)
- Duration: 38s
architecture:solid-reviewer-agnostic— claude-opus-5-5- In: 14
- Out: 2.4k
- Cache read: 278.6k
- Cache create: 58.5k
- Cost: ~$0.57 (est.)
- Duration: 55s
security:code-auditor— claude-sonnet-5- In: 8
- Out: 1.4k
- Cache read: 175.4k
- Cache create: 53.0k
- Cost: ~$0.26 (est.)
- Duration: 27s
documentation:docs— claude-sonnet-5- In: 16
- Out: 2.3k
- Cache read: 395.9k
- Cache create: 41.1k
- Cost: ~$0.27 (est.)
- Duration: 38s
orchestrator-rollup— claude-sonnet-5- In: 4
- Out: 461
- Cache read: 87.1k
- Cache create: 33.5k
- Cost: ~$0.16 (est.)
- Duration: 19s
Summary
Adds
slck channels join <channel>andslck channels leave <channel>. Joining as yourself (--as-user) is what lets you invite a bot or person to a public channel you are not in; slck could invite but not join.conversations.join. Slack answers an existing membership with ok plus analready_in_channelwarning (alongside others such asmissing_charset, inresponse_metadata.warnings), reported as "Already in channel".conversations.leave. Slack answers a missing membership with ok andnot_in_channel: true, reported as "Not in channel".Verification
make lintclean.integration-tests.mdgains the same four steps.