From dc85543d89171615fcddfff2b812e4f12d91d2e1 Mon Sep 17 00:00:00 2001 From: Rian Stockbower Date: Sat, 30 May 2026 11:28:31 -0400 Subject: [PATCH 1/3] docs: index agent guidance sources Closes #181 --- AGENTS.md | 21 +++++ CLAUDE.md | 203 +++----------------------------------------- docs/development.md | 117 +++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 191 deletions(-) create mode 100644 AGENTS.md create mode 100644 docs/development.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..79d6d99 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,21 @@ +# AGENTS.md + +Codex entrypoint for the slack-chat-api repository. + +## Start Here + +Source of truth: https://github.com/open-cli-collective/slack-chat-api/blob/main/docs/development.md +Local convenience copy, if present: `docs/development.md` + +## Shared Standards + +Source of truth: https://github.com/open-cli-collective/cli-common/tree/main/docs +Local convenience copy, if present: `../cli-common/docs` + +## Shared Automation + +Source of truth: https://github.com/open-cli-collective/.github +Local convenience copy, if present: `../.github` + +This file is an index. Keep Slack-specific guidance in `docs/development.md` +and shared conventions in the canonical repositories above. diff --git a/CLAUDE.md b/CLAUDE.md index 464cde9..e72b531 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,200 +1,21 @@ # CLAUDE.md -This file provides context for AI assistants working with this codebase. +Claude entrypoint for the slack-chat-api repository. -## Project Overview +## Start Here -A command-line interface for Slack, supporting channel management, user lookup, messaging, and workspace info. +Source of truth: https://github.com/open-cli-collective/slack-chat-api/blob/main/docs/development.md +Local convenience copy, if present: `docs/development.md` -## Quick Commands +## Shared Standards -```bash -make build # Build binary to ./bin/slck -make test # Run tests with race detection and coverage -make lint # Run golangci-lint -make clean # Remove build artifacts -make install # Install to $GOPATH/bin -``` +Source of truth: https://github.com/open-cli-collective/cli-common/tree/main/docs +Local convenience copy, if present: `../cli-common/docs` -## Project Structure +## Shared Automation -``` -slack-chat-api/ -├── main.go # Entry point -├── internal/ -│ ├── cmd/ # Command implementations -│ │ ├── root/ # Root command and global flags -│ │ ├── channels/ # Channel commands (list, get, create, etc.) -│ │ ├── users/ # User commands (list, get) -│ │ ├── messages/ # Message commands (send, history, react, etc.) -│ │ ├── workspace/ # Workspace info command -│ │ └── config/ # Token management commands -│ ├── client/ # Slack API client wrapper -│ ├── keychain/ # Secure credential storage -│ ├── output/ # Output formatting (text/json/table) -│ └── version/ # Build-time version injection -├── .github/workflows/ci.yml # CI pipeline -├── .golangci.yml # Linter configuration (v2 format) -└── Makefile # Build targets -``` +Source of truth: https://github.com/open-cli-collective/.github +Local convenience copy, if present: `../.github` -## Key Patterns - -### Options Struct Pattern - -All commands use an options struct with an injectable client for testability: - -```go -type listOptions struct { - types string - excludeArchived bool - limit int -} - -func runList(opts *listOptions, c *client.Client) error { - if c == nil { - var err error - c, err = client.New() - if err != nil { - return err - } - } - // Business logic... -} -``` - -### Output Formatting - -Resource and mutation-success commands emit text or table only. Per cli-common `docs/output-and-rendering.md` §2 (enforced by `output.ParseFormat`'s closed-set `{text, table}`), JSON is reserved for local control-plane carve-outs — today only `slck config show --json`. Do NOT add per-command `--json` flags or `output.IsJSON()` branches to new resource commands. - -The project-level JSON-vs-text contract lives in `ARCHITECTURE.md`: -JSON preserves upstream API semantics; text and table output may interpret -Slack data for terminal readability. - -```go -// Default + table path: -output.Table(headers, rows) // For list commands -output.KeyValue("ID", item.ID) // For detail views - -// Control-plane carve-out (config show pattern): -// local --json flag → call output.PrintJSON(envelope) directly. -``` - -### Global Flags - -- `--output, -o` - Output format: text (default) or table -- `--no-color` - Disable colored output - -## Testing - -Tests use mock clients injected via the options struct: - -```go -func TestRunList(t *testing.T) { - mockClient := &client.Client{...} // Mock setup - opts := &listOptions{limit: 10} - err := runList(opts, mockClient) - // Assertions... -} -``` - -Run tests: `make test` - -Coverage report: `go tool cover -html=coverage.out` - -## API Client - -The `internal/client` package wraps the Slack API: - -- `client.New()` - Creates client from token (env var or keychain) -- All API calls return typed responses -- Pagination handled internally with configurable limits - -## Adding a New Command - -1. Create file in appropriate `internal/cmd//` directory -2. Define options struct with flags -3. Implement `newXxxCmd()` returning `*cobra.Command` -4. Implement `runXxx(opts, client)` with business logic -5. Register in the resource's root command -6. Add tests using mock client injection - -## Common Issues - -- **Token not found**: Run `slck init` or `slck set-credential --key bot_token --stdin`. Environment variables are NOT read at runtime (only as setup ingress, e.g. `init --bot-token-from-env`). -- **Permission denied**: Check bot token scopes in Slack app settings -- **Lint failures**: Run `make lint` locally before pushing -- **golangci-lint version**: CI uses v2.12.2 with v2 config format (Go 1.26) - -## Credentials - -slck stores credentials in the OS keyring via `cli-common/credstore` (Open -CLI Collective Secret-Handling Standard §2.4). The `internal/keychain` -package is a credstore adapter (no `security` shell-out, no plaintext file). -Non-secret config (`credential_ref`, `workspace`, `keyring.backend`) lives in -`~/.config/slack-chat-api/config.yml`. Ingress is only `slck init` / -`slck set-credential` (stdin or `--from-env`); never a flag/positional value. - -**Backend selection** uses three user-configurable knobs that fall back to -auto-detect, in precedence order: - -1. `--backend ` persistent flag (wired in `internal/cmd/root/root.go` - `WireBackendSelection`, parsed eagerly at `PersistentPreRunE` so an invalid - value fails before opening the keyring) -2. `SLACK_CHAT_API_KEYRING_BACKEND=` env var (read by credstore directly) -3. `keyring.backend: ` in `config.yml` (validated at `openWith` time) -4. OS default - -Supported names: `keychain`, `wincred`, `secret-service`, `file`, `memory`. -When the configured backend opens cleanly, `slck config show` surfaces the -resolved backend, its source (explicit / env / config / auto), and the -`keyring.backend` value from config.yml verbatim. An invalid -`keyring.backend` in config.yml errors at the first credential access -(including `slck config show`, which opens the store internally) rather -than at config load. - -## Dependencies - -- `github.com/open-cli-collective/cli-common` - shared credstore (OS keyring) -- `github.com/spf13/cobra` - CLI framework -- `golang.org/x/term` - no-echo passphrase prompt (file-backend opt-in) - -(The HTTP Slack client is hand-rolled in `internal/client`; there is no -`slack-go`/`zalando` dependency.) - -## Commit Conventions - -Use conventional commits: - -``` -type(scope): description - -feat(channels): add archive command -fix(messages): handle rate limiting -docs(readme): add configuration examples -``` - -| Prefix | Purpose | Triggers Release? | -|--------|---------|-------------------| -| `feat:` | New features | Yes | -| `fix:` | Bug fixes | Yes | -| `docs:` | Documentation only | No | -| `test:` | Adding/updating tests | No | -| `refactor:` | Code changes that don't fix bugs or add features | No | -| `chore:` | Maintenance tasks | No | -| `ci:` | CI/CD changes | No | - -## CI & Release Workflow - -Releases are automated with a dual-gate system to avoid unnecessary releases: - -**Gate 1 - Path filter:** Only triggers when Go code changes (`**.go`, `go.mod`, `go.sum`) -**Gate 2 - Commit prefix:** Only `feat:` and `fix:` commits create releases - -This means: -- `feat: add command` + Go files changed → release -- `fix: handle edge case` + Go files changed → release -- `docs:`, `ci:`, `test:`, `refactor:` → no release -- Changes only to docs, packaging, workflows → no release - -**After merging a release-triggering PR:** The workflow creates a tag, which triggers GoReleaser to build binaries and publish to Homebrew. Chocolatey and Winget require manual workflow dispatch. +This file is an index. Keep Slack-specific guidance in `docs/development.md` +and shared conventions in the canonical repositories above. diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..c058a18 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,117 @@ +# slack-chat-api Development Guide + +This is the repo-local guide for Slack-specific facts. Shared Open CLI +Collective standards and automation remain canonical in their own repositories. + +## Project Overview + +slack-chat-api builds the `slck` command-line interface for Slack. It supports +channel management, user lookup, messaging, reactions, message history, and +workspace information. + +## Quick Commands + +```bash +make build # build binary to ./bin/slck +make test # run tests with race detection and coverage +make lint # run golangci-lint +make clean # remove build artifacts +make install # install to $GOPATH/bin +``` + +## Repo Structure + +```text +slack-chat-api/ +├── main.go +├── internal/ +│ ├── cmd/ # Cobra command implementations +│ ├── client/ # Slack API client wrapper +│ ├── keychain/ # cli-common credstore adapter +│ ├── output/ # text/table rendering helpers +│ └── version/ # build-time version injection +├── ARCHITECTURE.md # project-level JSON-vs-text contract +├── .golangci.yml +└── Makefile +``` + +## Command Patterns + +- Commands use small options structs with injectable clients for testability. +- New commands live under the appropriate `internal/cmd//` package. +- Register new commands from the resource root command. +- Add tests around the command runner with a mock or injectable client. + +## Output Contract + +Resource and mutation-success commands emit text or table output. JSON is +reserved for local control-plane carve-outs, currently `slck config show --json`. +The project-level JSON-vs-text contract lives in `ARCHITECTURE.md`. + +Source of truth: https://github.com/open-cli-collective/slack-chat-api/blob/main/ARCHITECTURE.md +Local convenience copy, if present: `ARCHITECTURE.md` + +Shared output policy: + +```md +Source of truth: https://github.com/open-cli-collective/cli-common/blob/main/docs/output-and-rendering.md +Local convenience copy, if present: `../cli-common/docs/output-and-rendering.md` +``` + +## Credentials And Config + +`slck` stores credentials in the OS keyring through `cli-common/credstore`. +Non-secret config such as `credential_ref`, `workspace`, and `keyring.backend` +lives in `~/.config/slack-chat-api/config.yml`. Secret ingress is through +`slck init` or `slck set-credential`, using stdin or `--from-env` style inputs. + +Shared credential and state policy: + +```md +Source of truth: https://github.com/open-cli-collective/cli-common/blob/main/docs/working-with-secrets.md +Local convenience copy, if present: `../cli-common/docs/working-with-secrets.md` + +Source of truth: https://github.com/open-cli-collective/cli-common/blob/main/docs/working-with-state.md +Local convenience copy, if present: `../cli-common/docs/working-with-state.md` +``` + +## Shared Repo Standards + +Use these sources for shared repository policy. Do not copy their mechanics into +this guide. + +```md +Source of truth: https://github.com/open-cli-collective/cli-common/blob/main/docs/command-surface.md +Local convenience copy, if present: `../cli-common/docs/command-surface.md` + +Source of truth: https://github.com/open-cli-collective/cli-common/blob/main/docs/repo-layout.md +Local convenience copy, if present: `../cli-common/docs/repo-layout.md` + +Source of truth: https://github.com/open-cli-collective/cli-common/blob/main/docs/ci.md +Local convenience copy, if present: `../cli-common/docs/ci.md` + +Source of truth: https://github.com/open-cli-collective/cli-common/blob/main/docs/release.md +Local convenience copy, if present: `../cli-common/docs/release.md` + +Source of truth: https://github.com/open-cli-collective/cli-common/blob/main/docs/distribution.md +Local convenience copy, if present: `../cli-common/docs/distribution.md` +``` + +## Shared Automation + +Use `open-cli-collective/.github` for shared action and reusable workflow +implementations. + +```md +Source of truth: https://github.com/open-cli-collective/.github +Local convenience copy, if present: `../.github` +``` + +## Dependencies + +- `github.com/open-cli-collective/cli-common` - shared credential storage. +- `github.com/spf13/cobra` - command framework. +- `golang.org/x/term` - no-echo prompt support. + +The Slack HTTP client is implemented in `internal/client`; this repo does not +use `slack-go` or `zalando`. From 5ef42b6d8615be4ead018496898e653c80257a0f Mon Sep 17 00:00:00 2001 From: Rian Stockbower Date: Sat, 30 May 2026 11:30:03 -0400 Subject: [PATCH 2/3] docs: fix slack guide facts Closes #181 --- docs/development.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/development.md b/docs/development.md index c058a18..9e8094a 100644 --- a/docs/development.md +++ b/docs/development.md @@ -13,7 +13,8 @@ workspace information. ```bash make build # build binary to ./bin/slck -make test # run tests with race detection and coverage +make test # run tests with race detection +make test-cover # run tests with coverage output make lint # run golangci-lint make clean # remove build artifacts make install # install to $GOPATH/bin @@ -23,7 +24,7 @@ make install # install to $GOPATH/bin ```text slack-chat-api/ -├── main.go +├── cmd/slck/main.go ├── internal/ │ ├── cmd/ # Cobra command implementations │ ├── client/ # Slack API client wrapper From 33ea7e4746052c6d8d89be922af3e5ca79e4b6e3 Mon Sep 17 00:00:00 2001 From: Rian Stockbower Date: Sat, 30 May 2026 11:30:47 -0400 Subject: [PATCH 3/3] docs: fix slack install target note Closes #181 --- docs/development.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development.md b/docs/development.md index 9e8094a..36a19af 100644 --- a/docs/development.md +++ b/docs/development.md @@ -17,7 +17,7 @@ make test # run tests with race detection make test-cover # run tests with coverage output make lint # run golangci-lint make clean # remove build artifacts -make install # install to $GOPATH/bin +make install # install to /usr/local/bin ``` ## Repo Structure