coach

module
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2026 License: BSD-2-Clause

README

coach

coach is an experimental AI coach for people (and agents) who write software. The thing you can use today is a local CLI: it reads a Git checkout, analyzes Go / TypeScript / TSX source, and prints advisory structural signals — code smells, design issues, and architecture-policy findings you opted into.

It does not execute your code, contact GitHub, or call a model unless you stand up the separate local platform preview. Coach stays on the 0.x line on purpose.

Quick start

Install mise if you do not already have it, then install the coach CLI from GitHub Releases with mise's GitHub backend:

curl https://mise.run | sh
~/.local/bin/mise use -g github:lousy-agents/coach

Hook mise into your current shell so coach is on PATH (pick the one you use):

echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc && eval "$(~/.local/bin/mise activate bash)"
# echo 'eval "$(~/.local/bin/mise activate zsh)"' >> ~/.zshrc && eval "$(~/.local/bin/mise activate zsh)"
# ~/.local/bin/mise activate fish | source

Pin a release if you want a fixed binary (latest published tag is v0.5.0):

mise use -g github:lousy-agents/coach@v0.5.0

From any Git worktree:

coach codesignal --base main          # diff HEAD against main
coach codesignal --baseline           # every tracked Go/TS/TSX file at HEAD
coach codesignal --base main --format json

--base can be any ref Git can resolve (branch, tag, or SHA). Text output is the default. A completed analysis exits 0 even when it found signals — this is advisory, not a gate.

You need git on PATH. No Docker, no API key, no network.

One-shot without writing a mise config or activating your shell:

mise exec github:lousy-agents/coach -- coach codesignal --base main

Release archives exist for darwin_arm64, darwin_x86_64, linux_x86_64, and windows_x86_64. There is no linux_arm64 build yet.

From source instead of the release binary

This path uses the repo's mise.toml to pin the dev toolchain (Go 1.27.1, Node 24). That is not the same as installing the published coach binary.

git clone https://github.com/lousy-agents/coach.git
cd coach
mise install
mise exec -- go install ./cmd/coach
Signed archive without mise

Download the archive for your platform from Releases, verify checksums.txt with cosign, then put coach on your PATH. The exact commands live in the CLI contract.

What you should see

A short text report per signal (path, line, lifecycle, changed, evidence, why it matters, recommendation), or a quiet report if the analyzed files produced no active signals. lifecycle is introduced / existing / resolved / unknown relative to the merge-base.

  • Advisory only. Coach does not judge correctness or block merges.
  • Go, TypeScript, and TSX only. Other languages are skipped with an unsupported_language diagnostic.
  • Static and local. It reads source bytes via git show. File-local unless you pass --project-config.
  • Absence is not a clean bill of health. An empty signal set means no matched rule for the inputs that were analyzed.

Full flag, schema, and exit-status contract: CLI contract.

Preview — experimental, try it now

These commands work on the current CLI or local stack. They are under active development, may change without a 1.0 promise, and are here so you can kick the tires. Absence of findings is not compliance.

1. Project-level architecture policy

Opt into cross-file layer checks with a committed JSON config. Coach does not guess your architecture — you declare layers and forbidden import edges.

# Go: discover module/workspace roots (candidate only — review, add layers, commit)
coach codesignal --baseline --suggest-project-config

# after the file is committed at the analyzed revision
coach codesignal --base main --project-config project.json
coach codesignal --baseline --project-config project.json --project-language typescript

--project-config is read from the analyzed revision, not your dirty worktree. An uncommitted candidate is invisible to the scan. A valid config switches the report to schema_version: "2" and can emit architecture.layer_violation. For Go only, required_layer can also emit architecture.layer_bypass on a narrow handler→SQL registry.

TypeScript --project-config uses Coach's embedded analyzer and a host-resolved compiler whose own package.json version is in the supported set (7.0.2 today). Version ranges (^, ~, latest) never count. If you previously vendored Coach's analyzer under the analyzed repository, you can delete that copy. --suggest-project-config never invents layers or forbidden_imports, and it never auto-applies a config.

2. TypeScript project readiness

A guided on-ramp for first-class TypeScript project analysis (epic #280, in flight).

coach codesignal --baseline --check-project --project-language typescript
coach codesignal --baseline --suggest-project-config --project-language typescript

Run --check-project first. It is the diagnostic for compiler, Node, and policy fit, and it is read-only: it reports readiness gaps and exits 0 so you inspect the result instead of treating the process status as a gate. A scan that cannot resolve a supported compiler or host Node exits 2 with empty stdout and one stderr line naming that same invocation. The interactive authoring session writes nothing until you say so.

Coach's supported Node majors are exactly 24 and 26 — every release within either major passes the --check-project Node/runtime check with no code and no warning. Any other major is the node_unsupported readiness gap. @lousy-agents/coach-semantics declares this as engines.node: "^24 || ^26", and CI runs the real TypeScript analyzer under both Node 24 and Node 26.

Still being built — do not expect these to work yet: consented package-manager / mise compiler setup for the scanned project, Bun as a project runtime, and a packaged foreign-repository TypeScript journey.

3. Local platform, including agent judgments

The CLI above never calls a model. The local API + worker stack can, if you want a preview of deterministic findings plus agent judgments on a baseline scan.

git clone https://github.com/lousy-agents/coach.git && cd coach
mise install
mise run platform-up
mise run platform-smoke    # expect: platform-smoke: ok

Full paths (stub model, local Qwen, GitHub.com scan without cloning): Local Coach quickstart. This is a pilot, not the default install. Findings are tagged source=deterministic or source=agent; agent output cannot suppress a deterministic finding.

Working in a Claude Code cloud session? See Claude Code cloud development.

Libraries

If you want the analyzer as a library rather than the CLI:

  • pkg/semantics — deterministic structural analysis of Go, TypeScript, and TSX source bytes. Quickstart.
  • pkg/githubingest — optional GitHub App-authenticated single-file reader.
  • @lousy-agents/coach-semantics — Node ESM bindings. Not published to npm yet; clone and build locally. JS/TS Quickstart.
go get github.com/lousy-agents/coach/pkg/semantics
go get github.com/lousy-agents/coach/pkg/githubingest

coach codesignal CLI Preview

The full flag, schema, exit-status, and --project-config contract now lives in docs/cli-codesignal.md.

Directories

Path Synopsis
cmd
acceptance-guard-preflight command
Command acceptance-guard-preflight is the activation entry point for internal/acceptanceharness's ambient-credential guard: run it before any acceptance suite starts (see mise.toml's test-acceptance-fast task).
Command acceptance-guard-preflight is the activation entry point for internal/acceptanceharness's ambient-credential guard: run it before any acceptance suite starts (see mise.toml's test-acceptance-fast task).
acceptance-style-guard command
Command acceptance-style-guard fails if any acceptance_test.go or *_acceptance_test.go under the module root does not import github.com/onsi/ginkgo/v2 and reference a Ginkgo suite/spec API, except an explicit allowlist (see internal/acceptancestyle).
Command acceptance-style-guard fails if any acceptance_test.go or *_acceptance_test.go under the module root does not import github.com/onsi/ginkgo/v2 and reference a Ginkgo suite/spec API, except an explicit allowlist (see internal/acceptancestyle).
coach command
Command coach is the composition-root CLI for the coach project.
Command coach is the composition-root CLI for the coach project.
coach-api command
Command coach-api is the composition-root HTTP service for the coach platform (Task 2 / GitHub issue #103, epic #97): it wires internal/authn (Coach JWT auth, optional GitHub OAuth login, config-gated test mint) and internal/coachapi (POST /v1/jobs, GET /v1/jobs/{id}, GET /v1/jobs/{id}/report) behind a live authz.RepoAuthorizer and a Redis Streams queue.TaskQueue into one runnable server.
Command coach-api is the composition-root HTTP service for the coach platform (Task 2 / GitHub issue #103, epic #97): it wires internal/authn (Coach JWT auth, optional GitHub OAuth login, config-gated test mint) and internal/coachapi (POST /v1/jobs, GET /v1/jobs/{id}, GET /v1/jobs/{id}/report) behind a live authz.RepoAuthorizer and a Redis Streams queue.TaskQueue into one runnable server.
coach-worker command
Command coach-worker claims work through queue.TaskQueue, persists claim/heartbeat/fenced writes via coachapi.WorkerJobStore, and runs the repo_baseline_scan handler.
Command coach-worker claims work through queue.TaskQueue, persists claim/heartbeat/fenced writes via coachapi.WorkerJobStore, and runs the repo_baseline_scan handler.
codesignal-report command
Command codesignal-report reads a batch of NDJSON lines from stdin, accumulates a single codesignal.Input, and writes exactly one JSON codesignal.Report to stdout.
Command codesignal-report reads a batch of NDJSON lines from stdin, accumulates a single codesignal.Input, and writes exactly one JSON codesignal.Report to stdout.
fakegithub-server command
Command fakegithub-server runs internal/fakegithub as a standalone HTTP process, packaging the issue #79 Task 0.3 thin-offline-proof fixture (internal/acceptanceharness/thinproof) as an internal-network Compose service rather than an in-process httptest.Server.
Command fakegithub-server runs internal/fakegithub as a standalone HTTP process, packaging the issue #79 Task 0.3 thin-offline-proof fixture (internal/acceptanceharness/thinproof) as an internal-network Compose service rather than an in-process httptest.Server.
model-stub command
Command model-stub serves the compose OpenAI-compatible HTTP stub from internal/modelgateway so core smoke can exercise worker → Envoy AI Gateway → backend without model weights.
Command model-stub serves the compose OpenAI-compatible HTTP stub from internal/modelgateway so core smoke can exercise worker → Envoy AI Gateway → backend without model weights.
platform-smoke command
Command platform-smoke is the end-to-end credential-free smoke for the local platform compose stack (Baseline Scan Story 4 / Task 10): mint → submit repo_baseline_scan → poll → assert provenance-tagged report.
Command platform-smoke is the end-to-end credential-free smoke for the local platform compose stack (Baseline Scan Story 4 / Task 10): mint → submit repo_baseline_scan → poll → assert provenance-tagged report.
semantics-json command
Command semantics-json exposes internal/jsbridge as a long-running newline-delimited-JSON server on stdin/stdout, so non-Go hosts (the js/semantics package) can call pkg/semantics without linking CGO themselves.
Command semantics-json exposes internal/jsbridge as a long-running newline-delimited-JSON server on stdin/stdout, so non-Go hosts (the js/semantics package) can call pkg/semantics without linking CGO themselves.
semantics-wasm-smoke command
Stub entry point so `go build ./...` / `go vet ./...` on native platforms don't fail with "build constraints exclude all Go files".
Stub entry point so `go build ./...` / `go vet ./...` on native platforms don't fail with "build constraints exclude all Go files".
thinproof-preflight command
Command thinproof-preflight is the no-pull/offline Compose preflight for issue #79's Task 0.3 thin offline proof (see docs/architecture/acceptance-harness.md section 2's binding contract): it checks, via `docker image inspect`, that the two local images deploy/compose/thinproof's docker-compose.yml expects already exist, before any `docker compose up` runs.
Command thinproof-preflight is the no-pull/offline Compose preflight for issue #79's Task 0.3 thin offline proof (see docs/architecture/acceptance-harness.md section 2's binding contract): it checks, via `docker image inspect`, that the two local images deploy/compose/thinproof's docker-compose.yml expects already exist, before any `docker compose up` runs.
thinproof-runner command
Command thinproof-runner is the external test-runner container for issue #79's Task 0.3 thin offline proof: it exercises the fake-GitHub -> pkg/githubingest -> pkg/semantics -> pkg/codesignal path against a fake GitHub service reachable only at FAKE_GITHUB_BASE_URL (e.g.
Command thinproof-runner is the external test-runner container for issue #79's Task 0.3 thin offline proof: it exercises the fake-GitHub -> pkg/githubingest -> pkg/semantics -> pkg/codesignal path against a fake GitHub service reachable only at FAKE_GITHUB_BASE_URL (e.g.
deploy
internal
acceptanceharness
Package acceptanceharness provides the offline acceptance-test guard rails for Feature Zero (GitHub issue #76, epic #73): an ambient-credential scanner that flags leaked-in, CI-style GitHub/AWS credentials before an acceptance suite runs, and a no-egress http.RoundTripper that makes an accidental public network call (e.g.
Package acceptanceharness provides the offline acceptance-test guard rails for Feature Zero (GitHub issue #76, epic #73): an ambient-credential scanner that flags leaked-in, CI-style GitHub/AWS credentials before an acceptance suite runs, and a no-egress http.RoundTripper that makes an accidental public network call (e.g.
acceptanceharness/agentloopharness
Package agentloopharness defines test/harness seams that a later epic's internal/agentloop package will import from its own tests: a scripted model-gateway stand-in (ScriptedGateway) and a recording tool-call broker (RecordingToolRegistry).
Package agentloopharness defines test/harness seams that a later epic's internal/agentloop package will import from its own tests: a scripted model-gateway stand-in (ScriptedGateway) and a recording tool-call broker (RecordingToolRegistry).
acceptanceharness/queueconformance
Package queueconformance defines a black-box behavioral contract for the eventual TaskQueue port described by ADR-006, and a reusable conformance suite (Run) that exercises any Queue implementation against it.
Package queueconformance defines a black-box behavioral contract for the eventual TaskQueue port described by ADR-006, and a reusable conformance suite (Run) that exercises any Queue implementation against it.
acceptanceharness/thinproof
Package thinproof is the shared, data-as-code fixture for GitHub issue #79's Task 0.3 thin offline proof: a single small file, at a fixed owner/repo/ref/path, served by internal/fakegithub and read back through pkg/githubingest's public GitHubFileReader API.
Package thinproof is the shared, data-as-code fixture for GitHub issue #79's Task 0.3 thin offline proof: a single small file, at a fixed owner/repo/ref/path, served by internal/fakegithub and read back through pkg/githubingest's public GitHubFileReader API.
acceptancestyle
Package acceptancestyle mechanically checks that every acceptance_test.go and *_acceptance_test.go imports github.com/onsi/ginkgo/v2 and references a Ginkgo suite/spec API (RunSpecs, Describe, It, …), except an explicit allowlist.
Package acceptancestyle mechanically checks that every acceptance_test.go and *_acceptance_test.go imports github.com/onsi/ginkgo/v2 and references a Ginkgo suite/spec API (RunSpecs, Describe, It, …), except an explicit allowlist.
agentloop
Package agentloop is a bounded tool-call broker over a typed registry (ADR-005).
Package agentloop is a bounded tool-call broker over a typed registry (ADR-005).
authn
Package authn implements Coach-signed JWT issue, validation, jti denylist revocation, HTTP auth middleware, optional GitHub OAuth App login (no scope), and a config-gated test-mint path for protected /v1 routes (ADR-001).
Package authn implements Coach-signed JWT issue, validation, jti denylist revocation, HTTP auth middleware, optional GitHub OAuth App login (no scope), and a config-gated test-mint path for protected /v1 routes (ADR-001).
authz
Package authz implements ADR-003's synchronous, submit-time repository authorization check: a principal may submit a scan of owner/repo only if the Coach GitHub App installation can read the repository and the principal has a GitHub-recognized role in it.
Package authz implements ADR-003's synchronous, submit-time repository authorization check: a principal may submit a scan of owner/repo only if the Coach GitHub App installation can read the repository and the principal has a GitHub-recognized role in it.
coachapi/queue
Package queue defines the application-owned TaskQueue and EventBus ports required by ADR-006 (docs/architecture/ADR-006-watermill-queue-abstraction.md): coach-api and coach-worker depend only on these interfaces, never on Watermill or a specific broker's types, so the backend (Redis Streams, SQS, ...) can be swapped without touching domain code.
Package queue defines the application-owned TaskQueue and EventBus ports required by ADR-006 (docs/architecture/ADR-006-watermill-queue-abstraction.md): coach-api and coach-worker depend only on these interfaces, never on Watermill or a specific broker's types, so the backend (Redis Streams, SQS, ...) can be swapped without touching domain code.
coachapi/queue/redisstream
Package redisstream implements the internal/coachapi/queue.TaskQueue port (ADR-006, docs/architecture/ADR-006-watermill-queue-abstraction.md) on top of Watermill's Redis Streams pub/sub (github.com/ThreeDotsLabs/watermill-redisstream), for coach's non-AWS / self-hosted deployment target.
Package redisstream implements the internal/coachapi/queue.TaskQueue port (ADR-006, docs/architecture/ADR-006-watermill-queue-abstraction.md) on top of Watermill's Redis Streams pub/sub (github.com/ThreeDotsLabs/watermill-redisstream), for coach's non-AWS / self-hosted deployment target.
coachapi/queue/sqs
Package sqs implements the internal/coachapi/queue.TaskQueue port (ADR-006, "Provider configuration" -> aws-sqs) on top of Amazon SQS.
Package sqs implements the internal/coachapi/queue.TaskQueue port (ADR-006, "Provider configuration" -> aws-sqs) on top of Amazon SQS.
codesignalcli
Package codesignalcli implements the Git-facing plumbing behind the `coach codesignal` subcommand: resolving revisions and selecting the files a CodeSignal report should analyze.
Package codesignalcli implements the Git-facing plumbing behind the `coach codesignal` subcommand: resolving revisions and selecting the files a CodeSignal report should analyze.
fakegithub
Package fakegithub is a Coach-owned, fixture-driven fake GitHub HTTP service for offline acceptance testing.
Package fakegithub is a Coach-owned, fixture-driven fake GitHub HTTP service for offline acceptance testing.
jsbridge
Package jsbridge defines the JSON protocol that exposes pkg/semantics to JavaScript/TypeScript consumers, plus the single handler both transport backends (WASM and stdio CLI) call.
Package jsbridge defines the JSON protocol that exposes pkg/semantics to JavaScript/TypeScript consumers, plus the single handler both transport backends (WASM and stdio CLI) call.
modelgateway
Package modelgateway is the sole inference seam for structured judgment: request in → schema-validated response out.
Package modelgateway is the sole inference seam for structured judgment: request in → schema-validated response out.
projectbridge
Package projectbridge defines the JSON protocol between pkg/projectmodel's TypeScript sidecar client and a pinned local Node/TypeScript sidecar subprocess that produces raw TypeScript/TSX import facts from an immutable snapshot (issue #214).
Package projectbridge defines the JSON protocol between pkg/projectmodel's TypeScript sidecar client and a pinned local Node/TypeScript sidecar subprocess that produces raw TypeScript/TSX import facts from an immutable snapshot (issue #214).
rubrics
Package rubrics holds versioned LLM-as-judge definitions, prompt assembly, and agent-loop tool adapters for seed rubrics (ADR-005).
Package rubrics holds versioned LLM-as-judge definitions, prompt assembly, and agent-loop tool adapters for seed rubrics (ADR-005).
tstestutil
Package tstestutil holds helpers shared by Ginkgo acceptance tests that copy this repository's installed TypeScript compiler into a fixture worktree.
Package tstestutil holds helpers shared by Ginkgo acceptance tests that copy this repository's installed TypeScript compiler into a fixture worktree.
pkg
codesignal
Package codesignal turns pkg/semantics analysis results into prioritized, change-aware coaching signals.
Package codesignal turns pkg/semantics analysis results into prioritized, change-aware coaching signals.
githubingest
Package githubingest reads individual file contents from a GitHub repository via the GitHub Contents API, authenticated as a GitHub App installation.
Package githubingest reads individual file contents from a GitHub repository via the GitHub Contents API, authenticated as a GitHub App installation.
projectmodel
Package projectmodel defines deterministic, offline, whole-repository structural facts about a codebase.
Package projectmodel defines deterministic, offline, whole-repository structural facts about a codebase.
semantics
Package semantics extracts deterministic structural facts from raw source bytes (syntax validity, imports, branching metrics, constructor-like patterns, mutates_input) using Tree-sitter grammars.
Package semantics extracts deterministic structural facts from raw source bytes (syntax validity, imports, branching metrics, constructor-like patterns, mutates_input) using Tree-sitter grammars.
semantics/internal/engine
Package engine defines the narrow tree-sitter surface pkg/semantics relies on.
Package engine defines the narrow tree-sitter surface pkg/semantics relies on.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL