Conversation
Module github.com/basecamp/cli with Go 1.24. Makefile with check (default), fmt-check, vet, and test targets. MAKEFILE-CONVENTION.md documents the standard target contract for all 37signals CLI repos.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b2da56831a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Introduces a new shared Go module (github.com/basecamp/cli) intended to standardize behavior across 37signals CLIs (output contracts, auth helpers, PKCE/OAuth flow support, surface snapshots, profiles), plus a rubric/specification, reusable GitHub Actions, and a “seed” starter kit for bootstrapping new CLIs.
Changes:
- Added shared Go packages:
output,credstore,pkce,oauthcallback,surface,profile(with unit tests). - Added portfolio-level specs/docs:
RUBRIC.mdandMAKEFILE-CONVENTION.md. - Added reusable GitHub Actions and a seed kit (templates, scripts, Claude plugin scaffolding, prompts, skill templates).
Reviewed changes
Copilot reviewed 47 out of 48 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| surface/surface_test.go | Tests for Cobra surface snapshotting and diffing. |
| surface/snapshot.go | Implements command/flag/subcommand snapshot traversal. |
| surface/diff.go | Implements snapshot diffing (added/removed entries). |
| skills/rubric-audit/SKILL.md | Agent skill doc for auditing a CLI against the rubric. |
| seed/skills/embed.go.tmpl | Template for embedding skill files via go:embed. |
| seed/skills/app/SKILL.md.tmpl | Template SKILL.md for a seeded CLI. |
| seed/scripts/sync-skills.sh | CI script to sync skills into a distribution repo. |
| seed/internal/output/output.go | Seed wrapper re-exporting shared output types/helpers. |
| seed/internal/commands/skill.go.tmpl | Seed skill command to print embedded SKILL.md. |
| seed/internal/commands/setup.go.tmpl | Seed skeleton doc for interactive setup wizard. |
| seed/internal/commands/doctor.go.tmpl | Seed skeleton doc for a doctor health-check command. |
| seed/internal/auth/auth.go | Seed auth helpers wiring credstore + pkce. |
| seed/Makefile | Seed CLI Makefile implementing the documented target contract. |
| seed/CONTRIBUTING.md.tmpl | Seed contributing guide template. |
| seed/API-COVERAGE.md.tmpl | Seed template for tracking endpoint-to-command coverage. |
| seed/AGENTS.md.tmpl | Seed development context and conventions template. |
| seed/.goreleaser.yaml | Seed GoReleaser config (signing/SBOM/notarization). |
| seed/.golangci.yml | Seed golangci-lint configuration. |
| seed/.claude-plugin/plugin.json | Seed Claude plugin manifest template. |
| seed/.claude-plugin/hooks/session-start.sh | Seed SessionStart hook to emit CLI context. |
| seed/.claude-plugin/agents/navigator.md | Seed “navigator” agent template. |
| seed/.claude-plugin/agents/context-linker.md | Seed “context linker” agent template. |
| prompts/seed-cli.md | Prompt/spec for generating a new CLI from the seed. |
| prompts/close-gap.md | Prompt/spec for closing a specific rubric gap. |
| profile/resolve.go | Profile resolution logic (flag/env/config/auto/picker). |
| profile/profile_test.go | Tests for profile store + resolution. |
| profile/profile.go | Profile store implementation and validation helpers. |
| pkce/pkce_test.go | Tests for PKCE verifier/challenge/state generation. |
| pkce/pkce.go | PKCE helpers for verifier/challenge/state. |
| output/output_test.go | Extensive tests for output envelopes, codes, formats, helpers. |
| output/normalize.go | Normalizes data types (incl. UseNumber) for JSON output. |
| output/errors.go | Typed error model and constructors, plus AsError. |
| output/envelope.go | Writer implementation, formats, envelopes, and helpers. |
| output/codes.go | Exit-code and code-string constants + mapping. |
| oauthcallback/server_test.go | Tests for local OAuth callback server behavior. |
| oauthcallback/server.go | Local HTTP callback server implementation. |
| credstore/store_test.go | Tests for file-based credential storage fallback. |
| credstore/store.go | Credential store abstraction (keyring + file fallback). |
| credstore/migrate.go | Migration helper from file store to keyring. |
| credstore/file.go | File-backed credential storage implementation. |
| actions/sync-skills/action.yml | Composite action to sync skills to distribution repo. |
| actions/surface-compat/action.yml | Composite action to detect breaking CLI surface removals. |
| actions/rubric-check/action.yml | Composite action to score a CLI against key rubric checks. |
| RUBRIC.md | Full rubric spec (tiers/criteria/scoring template). |
| Makefile | Root module Makefile (library-style: fmt/vet/test/lint/etc). |
| MAKEFILE-CONVENTION.md | Standard target contract for CLI/library Makefiles. |
| go.mod | Defines module path and dependencies. |
| go.sum | Dependency checksums. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 48 out of 49 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The agent contract in type form. A CLI that imports output and uses Writer.OK() / Writer.Err() automatically complies with Tier 1A and 1B of the rubric. - Response / ErrorResponse envelope types - Format enum with TTY auto-detection (FormatAuto) - 8 typed exit codes (0=OK through 8=Ambiguous) - CLIError with Code, Message, Hint, Retryable, HTTPStatus - Typed constructors: ErrUsage, ErrNotFound, ErrAuth, etc. - NormalizeData with json.Number preservation for large IDs - TruncationNotice helpers for paginated responses - Breadcrumb type for agent chaining
Parameterized by ServiceName, DisableEnvVar, and FallbackDir so each CLI configures its own namespace. Probes system keyring at init, falls back to atomic file writes with 0600 permissions. Includes MigrateToKeyring() for upgrading file-based credentials.
Three stdlib-only functions implementing RFC 7636 for OAuth flows. GenerateVerifier (32 bytes), GenerateChallenge (S256), GenerateState (16 bytes).
WaitForCallback starts a local HTTP server, validates the OAuth state parameter, and returns the authorization code. 5-minute timeout, sync.Once shutdown, HTML response to the browser.
Walks a Cobra command tree to produce deterministic CMD/FLAG/SUB entries. Diff() compares two snapshots and reports additions and removals. HasBreakingChanges() flags flag/subcommand removals for CI enforcement.
Profile bundles a base URL with optional app-specific Extra fields. Store manages profiles in a JSON config file with atomic writes. Resolve implements strict precedence: --profile flag > APP_PROFILE env > default_profile config > auto-select single > interactive picker. CredentialKey returns "profile:<name>" for named profiles.
80 criteria across 4 tiers evaluating agent operability, reliability, integration, and distribution. Two profiles: API CLI (full rubric) and TUI tool (subset). 7 design principles. Scoring template for evaluating any CLI against the standard. Tier 1: Agent Contract (26) — structured output, exit codes, programmatic discovery, authentication Tier 2: Reliability (16) — surface stability, resilience, configuration Tier 3: Agent Integration (11) — skill/plugin, pagination, observability Tier 4: Distribution & Ecosystem (27) — distribution, testing, completion, developer experience
actions/rubric-check — score a CLI against the rubric actions/surface-compat — fail on flag/subcommand removal actions/sync-skills — publish embedded skills to basecamp/skills
Complete starter kit for a new 37signals CLI: - internal/output/ and internal/auth/ wrapping shared packages - internal/commands/ with doctor, setup, and skill command skeletons - .claude-plugin/ with SessionStart hook, navigator and context-linker agent templates - skills/ with embed.go and SKILL.md templates - scripts/sync-skills.sh for publishing skills on release - .goreleaser.yaml with cosign signing, SBOM, and notarization - .golangci.yml, Makefile, AGENTS.md, CONTRIBUTING.md templates - API-COVERAGE.md tracking matrix template
skills/rubric-audit/SKILL.md — agent skill for scoring any CLI prompts/close-gap.md — agent prompt for closing a specific rubric gap prompts/seed-cli.md — agent prompt for bootstrapping a new CLI
|
/cc @robzolkos @monorkin @kevinmcconnell Extracting and harmonizing common app CLI bits! |
Summary
Shared Go module and specification for all 37signals CLIs. Extracted from basecamp-cli and generalized for fizzy-cli, hey-cli, etc.
Packages
output/— Envelope types, exit codes, typed errors, format dispatch, TTY auto-detection. A CLI that imports this and usesWriter.OK()/Writer.Err()automatically complies with Tier 1A and 1B of the rubric.credstore/— Keyring + file fallback credential storage, parameterized per CLI.pkce/— PKCE verifier, challenge, and state generation (RFC 7636).oauthcallback/— Local HTTP server for OAuth redirect flows.surface/— CLI surface snapshots and compatibility diffs for Cobra command trees.profile/— Named environment profiles with resolution precedence (flag > env > config > auto-select > interactive picker).Specification
RUBRIC.md— 80 criteria across 4 tiers (Agent Contract, Reliability, Agent Integration, Distribution & Ecosystem). Two profiles: API CLI (full) and TUI tool (subset). Scoring template included.MAKEFILE-CONVENTION.md— Standard target contract for all 37signals CLI repos.Infrastructure
actions/— Reusable GitHub Actions: rubric-check, surface-compat, sync-skills.seed/— Complete starter kit for bootstrapping a new CLI: output/auth wrappers, .claude-plugin with hooks and agents, skill embedding, doctor/setup/skill command skeletons, .goreleaser.yaml (cosign, SBOM, notarization), API-COVERAGE.md template.skills/— rubric-audit agent skill.prompts/— Agent prompts for closing rubric gaps and seeding new CLIs.Test plan
makepasses (vet + test across all packages)replacedirective