Captain is a Go CLI for working with Claude Code sessions, hooks, and sandboxes.
It provides tools to:
- inspect Claude Code project/session history
- summarize tool usage, paths, binaries, and API cost
- list files changed by a session
- install Claude Code hooks
- enforce a session-specific Definition of Done gate
- test and use AI providers from the command line
- run iterative AI agents with verifiers, worktrees, and commits
- generate/build/run containerized Claude Code sandboxes
- inspect and clean stored Claude project session data
- expose captain commands as an MCP server
- run a web UI for launching and chatting with AI agents
- configure default backend, model, and AI safety toggles
From the codebase, Captain is organized around a few core capabilities:
Captain reads Claude session history and exposes commands for:
history— inspect tool usage from Claude sessionsinfo— show project/session metadata for the current directorycost— estimate and group token/API usage across sessionsprojects list— list tracked Claude projects and sessionsprojects clean— remove old session history
It analyzes:
- tools used
- files/directories read and written
- domains accessed
- binaries executed
- approval / denial state
- categories of bash activity
- token and cost summaries
Captain can install hook commands into Claude settings for:
- PreToolUse bash scanning via
hook bash-check - Stop hook gating via
hook dod install
The bash-check hook scans bash commands and can deny unsafe or disallowed commands.
Captain supports a per-session Definition of Done workflow:
dod set— attach one or more validation commands to a Claude sessiondod check— intended for Claude Stop hooksdod run— manually execute DoD checksdod status— show current DoD config/resultsdod clear— remove the DoD gate
This lets Claude continue iterating until required checks pass.
captain changes lists the files written or edited during a Claude Code or Codex session:
- defaults to the most recent session in the current directory
--session-idtargets a specific session by exact or prefix match--allsearches across all projects--claude/--codexfilter by session source--agents(default: true) includes files edited by nested sub-agents--plans/--ignoredcontrol whether plan files and git-ignored files are shown
Captain includes provider-agnostic AI utilities under captain ai:
ai prompt— send a prompt to a selected backend/modelai agent— run an iterative agent loop with optional verifiers, a throwaway git worktree, commit, and LLM judgeai models— list model informationai test— verify provider connectivityai fixture— run a YAML benchmark fixture across multiple Claude configurations and capture a markdown evidence report
Supported backends are inferred from code and dependencies, including:
- Anthropic
- Gemini / Google
- OpenAI-compatible paths via the internal provider layer
- CLI/provider abstractions for local tool-backed backends (claude, codex, gemini)
whoami— lists every AI adapter (API providers and CLI agents), how each is authenticated, whether its binary is installed, and the models it exposesconfigure— interactive wizard to set default backend, model, reasoning effort, budget, timeout, and feature toggles (caching, MCP, hooks, skills, user/project settings, memory) saved to~/.captain.yaml
serve— starts an HTTP API and embedded web UI for launching AI agents and opening follow-up chat sessions; supports--devto proxy to the Vite dev servermcp— exposes captain commands (history, info, cost, changes, dod, etc.) as MCP tools so Claude Code can invoke them directly
cmux screenshot— captures a screenshot of the active browser surface in cmux and copies the path to the clipboardport kill <port>— finds and kills the process listening on a TCP port
Captain can discover Claude-related local configuration and package it into a container sandbox.
Supported workflows include:
container— interactive TUIcontainer list— list discovered componentscontainer generate— generate Dockerfile/build context and sandbox configcontainer build— build the sandbox imagecontainer run— run the generated sandboxsandbox presets— list available sandbox-runtime presets
The container workflow is designed to package things like:
- Claude config
- agents
- commands
- hooks
- MCP server config
- project settings
- token/env passthrough
- sandbox-runtime presets for languages/tools
captain/
├── cmd/captain/ # CLI entrypoint
├── docs/ # Astro documentation site
├── pkg/ai/ # AI abstraction, provider config, models
├── pkg/ai/agent/ # Iterative agent loop, plugins (verify, worktree, judge)
├── pkg/ai/fixture/ # YAML fixture runner for Claude configuration benchmarks
├── pkg/api/ # HTTP API types and handlers (used by serve)
├── pkg/bash/ # Bash scanning, classification, rules
├── pkg/captainconfig/ # ~/.captain.yaml config load/save
├── pkg/claude/ # Claude history, sessions, parsing, formatting
├── pkg/cli/ # Cobra/clicky command implementations
├── pkg/cli/webapp/ # Embedded React web UI (served by captain serve)
├── pkg/cmux/ # Terminal multiplexer integration (screenshot)
├── pkg/collections/ # Generic collection utilities
├── pkg/container/ # Sandbox discovery, generation, build/run logic
├── pkg/dod/ # Definition of Done persistence and execution
├── pkg/git/ # Git worktree helpers
├── pkg/sandbox/ # Token/preset/sandbox helpers
├── Dockerfile # Container image for captain/Claude tooling
├── entrypoint.sh # gosu-based user switching entrypoint
├── Makefile # Thin wrapper around Taskfile
└── Taskfile.yaml # Main developer tasks
Top-level commands exposed by cmd/captain/main.go:
captain history
captain info
captain cost
captain changes
captain sandbox
captain ai
captain whoami
captain configure
captain serve
captain dod
captain hook
captain projects
captain container
captain mcp
captain cmux
captain portcaptain history
captain history --summary
captain history --all
captain history --tool Bash --since now-7d
captain history --category git --compact
captain history --session-id 019e0365-dc2a-7ad0-a5a8-78936481a928
captain history 019e0365-dc2a-7ad0-a5a8-78936481a928Useful flags include:
--file--tool--dir--category--approved--session-id--limit--since--all--short--compact--summary
captain info
captain info --path /path/to/projectShows project root detection, Claude project directory, session counts, history range, and tool call totals.
captain cost
captain cost --group-by project
captain cost --group-by model
captain cost --group-by tool
captain cost --group-by category
captain cost --session-id 019e0365-dc2a-7ad0-a5a8-78936481a928
captain cost --all --since now-30dSupported groupings from the code:
sessionprojectmodeldaydirfiletoolcategory
captain changes
captain changes --session-id <session-id>
captain changes --all --since now-7d
captain changes --claude
captain changes --agents=falseLists the files written or edited during a Claude Code or Codex session. Defaults to the most recent session in the current directory.
Install the bash safety hook:
captain hook bash-check install
captain hook bash-check install --userInstall the DoD stop hook and related skill files:
captain hook dod install
captain hook dod install --usercaptain dod set --session-id <session-id> "go test ./..." "golangci-lint run"
captain dod status --session-id <session-id>
captain dod run --session-id <session-id>
captain dod clear --session-id <session-id>captain ai prompt --model claude-sonnet-4 --prompt "Summarize this diff"
captain ai agent --prompt "Fix the failing tests" --verify "go test ./..."
captain ai agent --prompt "Refactor this module" --worktree --commit --judge "all tests pass"
captain ai test --model gemini-2.0-flash
captain ai models
captain ai fixture --file examples/ai-fixtures/mission-control-investigate.yamlRelevant provider flags include:
--model--backend--api-key--no-cache--budget--debug
captain ai agent runs an iterative AI agent loop with optional quality gates:
--prompt/-p— task prompt (required; can be piped from stdin)--system/-s— system prompt override--verify— shell command run after each turn; non-zero exit triggers a re-run (repeatable)--max-iterations— max verify-and-rerun iterations (default: 1)--scope— verifier scope:changed(only changed files) orall(default)--worktree— run in a throwaway git branch/worktree--branch— worktree branch name (default:captain/agent-<timestamp>)--commit— commit changes on the worktree branch (requires--worktree)--judge— LLM rubric; fails a turn when the judge rejects the result
captain ai fixture runs the same prompt against multiple Claude
configurations (different models, tool allowlists, MCP servers, prompt
caching on/off) and prints a side-by-side table of duration, cost,
tokens, and tool-call counts. It's intended to produce evidence that
one approach — e.g. a structured MCP — is faster and cheaper than a
Bash/CLI equivalent.
captain ai fixture -f examples/ai-fixtures/mission-control-investigate.yaml
captain ai fixture -f examples/ai-fixtures/mission-control-describe.yaml --report /tmp/mc-describe.md
captain ai fixture -f examples/ai-fixtures/mission-control-multistep.yaml --repeat 5Flags:
--file/-f— path to the YAML fixture (required)--report/-r— write an evidence report (headline, metrics table, per-run config, tool-usage breakdown) to this path--format— report format:markdown(default),html, oransi--artifacts— directory for per-runstream-jsoncaptures (default:<fixture-dir>/.captain/fixtures/<name>/)--repeat— override every run's repeat count (useful for smoke tests:--repeat 1)
YAML schema (abridged):
name: my-benchmark
description: What you're measuring and why
prompt: |
The prompt sent to every run (can be overridden per-run).
baseline: direct # which run to compare against for Speedup/Cheaper ratios
repeat: 3 # default N per run; overridable per-run and via --repeat
defaults:
timeout: 3m
permissionMode: bypassPermissions
promptCaching: true
model: claude-sonnet-4
runs:
- name: direct
tools: [Bash]
allowedTools: ["Bash(kubectl *)", "Bash(aws *)"]
- name: mission-control
tools: [default]
mcpConfig: [.mcp.json]
allowedTools: ["mcp__mission-control__*"]
repeat: 5 # overrides fixture-level repeat for this runTwo rules the runner enforces for you so direct-vs-MCP comparisons stay honest — both are automatic, no extra flags needed:
- MCP is opt-in per run. A run gets MCP servers only when
mcpConfigis set. With nomcpConfig, the runner passes--strict-mcp-configwith an empty inline config, so ambient.mcp.jsonin the fixture directory and user-level MCP servers are never picked up. allowedToolsis treated as a real allowlist. Claude CLI's--allowedToolsis natively an auto-approve list, not a restriction — underbypassPermissionsthe model can still reach for anything. When a run specifiesallowedTools, the runner demotes the effective--permission-modefrombypassPermissionstodefaultso unlisted tools are denied in non-interactive mode. If you setpermissionModeto anything other thanbypassPermissionsexplicitly, your choice is preserved. Runs withoutallowedToolskeep whatever permission mode they asked for.
Practical consequence for a direct-vs-MCP fixture: the direct run with
allowedTools: [Bash(kubectl *), ...] can only shell out to those
patterns; the mission-control run with
allowedTools: [mcp__mission-control__*] can only use MCP — Bash is off
even though it's a built-in. Neither run can accidentally borrow from
the other's toolset.
Supported per-run fields: name, prompt, system, model, timeout,
cwd, permissionMode, appendSystemPrompt, settings,
maxBudgetUSD, repeat, tools, allowedTools, disallowedTools,
mcpConfig, addDir, betas, extraArgs, env, promptCaching,
noSessionPersistence, bare. See
examples/ai-fixtures/ for working benchmarks.
Repeats (repeat: N) execute each run N times and report the mean
duration/cost plus a sample standard deviation — single-shot LLM numbers
are noisy and N≥3 makes comparisons defensible. The raw per-iteration
stream-json is saved under the artifacts directory so every claim in
the report is reproducible.
Set captureKubernetesProxy: true at the fixture level to route every
kubectl call made during the fixture through a captain-managed reverse
proxy, and record both layers of activity:
captureKubernetesProxy: true
kubeconfig: ~/.kube/config # optional; defaults to client-go discoveryWhen enabled, the runner:
- starts a localhost reverse proxy that loads the user's kubeconfig (auth plugins included) and forwards to the real cluster
- generates a temp kubeconfig pointing at the proxy and injects
KUBECONFIG=<that path>into every run's environment, so kubectl can't bypass it - writes a JSONL log per run/iteration to
<artifacts>/<run>-<iter>.kubectl.jsonlwith two record types:{"type":"command","command":"kubectl get pods -n prod"}— literal CLI invocation parsed from the model's Bash tool calls{"type":"request","method":"GET","path":"/api/v1/...","status":200}— every API call observed by the proxy
- surfaces a Kubectl activity section in the report with per-run CLI and API counts plus a few sample commands
captain container
captain container list
captain container generate
captain container generate -i
captain container build --preset golang
captain container run
captain sandbox presetsImportant generate/build flags:
--interactive--preset--base--mode copy|mount
captain whoami
captain whoami --backend anthropic
captain whoami --models=falseLists every AI adapter (API providers and CLI agents: anthropic, openai, gemini, claude-cli, claude-agent, codex-cli, gemini-cli), their authentication method, binary availability, and a live model listing.
captain configureInteractive wizard that writes ~/.captain.yaml with defaults for backend, model, reasoning effort, budget, timeout, and feature toggles (caching, MCP, hooks, skills, user/project settings, memory). These defaults apply to captain ai prompt, captain ai agent, captain ai test, and other AI commands.
captain serve
captain serve --port 8080
captain serve --dev
go run ./cmd/captain serve --dev --open
task www:dev
task www:buildStarts an HTTP API and embedded web UI. The UI launches captain ai agent operations and opens follow-up chat windows that resume the returned session. --dev starts the Vite dev server from pkg/cli/webapp and proxies /api back to the Go process. Use task www:dev for the local Go-backed Vite proxy with the browser opened, and task www:build to rebuild the embedded web UI assets.
captain mcpExposes captain commands as MCP tools. Auto-exposes all commands except sandbox, projects, container, hook, ai, dod set/clear/run.
# Screenshot active browser surface in cmux
captain cmux screenshot
# Kill the process on a TCP port
captain port kill 3000This repo uses task as the main task runner.
task build
# or
make buildBinary output:
.bin/captain
task docs:dev
task docs:buildThe Astro docs site lives in docs/. The prompts engine is the first complete section; other Captain areas are scaffolded for future expansion.
task test
# or
make testtask linttask installBy default this copies the built binary to:
/usr/local/bin/captain
The included Dockerfile builds on flanksource/base-image and installs:
- Node.js
- git, gh, jq, vim, nano, zsh, fzf, etc.
- Claude Code via
@anthropic-ai/claude-code
The image is set up to:
- create a user matching host UID/GID
- switch execution using
gosu - use
/workspaceas the working directory
Primary stack:
- Go 1.25.8
- Cobra for CLI wiring
- clicky for formatting/output/flag binding
- charmbracelet/huh for the interactive
configureTUI - sandbox-runtime for sandbox preset handling
- AI SDKs for Anthropic, OpenAI, and Gemini/Google
- shell parsing via
mvdan.cc/sh/v3
cd captain
make build
.bin/captain info
.bin/captain history --summary
.bin/captain changes
.bin/captain container listConfigure defaults:
.bin/captain configure
.bin/captain whoamiIf you want to use hooks:
.bin/captain hook bash-check install --user
.bin/captain hook dod install --userStart the web UI:
.bin/captain serve- Captain is tightly focused on Claude Code workflows.
- It is both an analysis tool and an execution/control tool.
- The container/sandbox functionality is a major part of the project, not a side feature.
- Many commands assume the presence of Claude local state under the user’s Claude config/projects directories.
- Configuration is persisted to
~/.captain.yamlviacaptain configure.