Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ jobs:
with:
go-version: "1.26.x"
- name: Lint with Gavel
uses: flanksource/gavel@25b5e48fb166ba33a47544606aaa3e16644fa4bb # v0.0.53
uses: flanksource/gavel@43a9189b99e71ed928f418e01cd34aa797c2c0e0 # v0.0.54
with:
args: lint golangci-lint
version: v0.0.53
artifact-name: gavel-lint-results
comment-header: captain-gavel-lint
comment: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository }}
Expand All @@ -53,10 +52,9 @@ jobs:
# dbtest shares one embedded PostgreSQL server while isolating each test
# with a leased ephemeral database.
- name: Test with Gavel
uses: flanksource/gavel@25b5e48fb166ba33a47544606aaa3e16644fa4bb # v0.0.53
uses: flanksource/gavel@43a9189b99e71ed928f418e01cd34aa797c2c0e0 # v0.0.54
with:
args: test --ignore tests/e2e
version: v0.0.53
artifact-name: gavel-test-results
comment-header: captain-gavel-test
comment: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository }}
Expand Down
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ Supported backends are inferred from code and dependencies, including:

### 8. Utility commands

- `cmux info <copy-id-lines|pid>` — resolves all processes in a cmux surface, pane, or workspace and reports runtime, CPU, memory, listening TCP ports, and optional Go stacks
- `cmux screenshot` — captures a screenshot of the active browser surface in cmux and copies the path to the clipboard
- `port kill <port>` — finds and kills the process listening on a TCP port

Expand Down Expand Up @@ -184,7 +185,7 @@ captain/
├── 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/cmux/ # Terminal multiplexer integration (processes and screenshots)
├── pkg/collections/ # Generic collection utilities
├── pkg/container/ # Sandbox discovery, generation, build/run logic
├── pkg/dod/ # Definition of Done persistence and execution
Expand Down Expand Up @@ -536,6 +537,17 @@ Exposes captain commands as MCP tools. Auto-exposes all commands except `sandbox
### Utility commands

```bash
# Inspect every process attributed to a copied cmux surface
captain cmux info \
surface_ref=surface:21 \
surface_id=65BB4725-B785-48DE-B3FD-31167ECB8300

# Pipe the Copy IDs block directly from the clipboard
pbpaste | captain cmux info

# Inspect a PID and request a Go goroutine stack through gops
captain cmux info 33745 --stack

# Screenshot active browser surface in cmux
captain cmux screenshot

Expand Down
6 changes: 5 additions & 1 deletion cmd/captain/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func main() {

whoamiCmd := clicky.AddNamedCommand("whoami", rootCmd, cli.WhoamiOptions{}, cli.RunWhoami)
whoamiCmd.Short = "List agent adapters, auth methods, and available models"
whoamiCmd.Long = "Show every AI agent adapter (API providers and CLI agents), how each is authenticated (Captain vault, API-key env var, or CLI login), whether its CLI binary is installed, and the models each provider exposes via a live API call. Pass --models=false to skip the network probes, or --backend to inspect a single adapter."
whoamiCmd.Long = "Show every AI agent adapter (API providers and CLI agents), how each is authenticated (Captain vault, API-key env var, or CLI login), whether its CLI binary is installed, and the models each provider exposes via a live API call. Disabled models are hidden by default; pass --disabled=true to include them. Pass --models=false to skip the network probes, or --backend to inspect a single adapter."

configureCmd := clicky.AddNamedCommandWithContext("configure", rootCmd, cli.ConfigureOptions{}, cli.RunConfigure)
configureCmd.Use = "configure [provider]"
Expand Down Expand Up @@ -248,6 +248,10 @@ func main() {

cmuxCmd := &cobra.Command{Use: "cmux", Short: "Cmux terminal multiplexer commands"}
rootCmd.AddCommand(cmuxCmd)
cmuxInfoCmd := clicky.AddNamedCommandWithContext("info", cmuxCmd, cli.CmuxInfoOptions{}, cli.RunCmuxInfo)
cmuxInfoCmd.Use = "info [copy-id-lines|pid]..."
cmuxInfoCmd.Short = "Inspect processes running in a cmux target"
cmuxInfoCmd.Long = "Resolve copied cmux workspace, pane, or surface IDs (or a PID) and report each process, runtime, CPU, memory, and listening TCP ports. Use --stack to request Go goroutine stacks through gops."
screenshotCmd := clicky.AddNamedCommand("screenshot", cmuxCmd, cli.CmuxScreenshotOptions{}, cli.RunCmuxScreenshot)
screenshotCmd.Short = "Take a screenshot of the active browser surface"
screenshotCmd.Long = "Capture a screenshot of the currently focused browser panel in cmux and copy the file path to the clipboard."
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ require (
github.com/samber/lo v1.53.0
github.com/segmentio/encoding v0.5.4
github.com/sergi/go-diff v1.4.0
github.com/shirou/gopsutil/v3 v3.24.5
github.com/spf13/cobra v1.10.2
github.com/stretchr/testify v1.11.1
github.com/t14raptor/go-fast v0.1.0
Expand Down Expand Up @@ -60,7 +61,7 @@ require (
github.com/nukilabs/ftoa v1.0.0 // indirect
github.com/nukilabs/unicodeid v0.1.0 // indirect
github.com/pgplex/pgparser v0.2.0 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/zclconf/go-cty v1.14.4 // indirect
github.com/zclconf/go-cty-yaml v1.1.0 // indirect
Expand Down Expand Up @@ -136,7 +137,7 @@ require (
github.com/charmbracelet/bubbletea v1.3.10 // indirect
github.com/charmbracelet/colorprofile v0.4.3 // indirect
github.com/charmbracelet/lipgloss v1.1.0 // indirect
github.com/charmbracelet/x/ansi v0.11.6 // indirect
github.com/charmbracelet/x/ansi v0.11.6
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect
github.com/charmbracelet/x/term v0.2.2 // indirect
Expand Down Expand Up @@ -292,7 +293,6 @@ require (
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/samber/oops v1.21.0 // indirect
github.com/segmentio/asm v1.2.1 // indirect
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
github.com/shoenig/go-m1cpu v0.1.7 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
Expand Down
32 changes: 32 additions & 0 deletions migrations/20_prompt_runs_and_plans.pg.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ table "captain_prompt_runs" {
null = false
type = uuid
}
column "turn_id" {
null = true
type = uuid
}
column "root_session_id" {
null = false
type = uuid
Expand Down Expand Up @@ -87,6 +91,22 @@ table "captain_prompt_runs" {
null = true
type = jsonb
}
column "approval_state" {
null = true
type = jsonb
}
column "provider_checkpoint_codec" {
null = true
type = text
}
column "provider_checkpoint_version" {
null = true
type = integer
}
column "provider_checkpoint" {
null = true
type = bytea
}
column "error" {
null = true
type = text
Expand Down Expand Up @@ -130,6 +150,12 @@ table "captain_prompt_runs" {
on_update = NO_ACTION
on_delete = CASCADE
}
foreign_key "captain_prompt_runs_turn_id_fkey" {
columns = [column.turn_id]
ref_columns = [table.captain_turns.column.id]
on_update = NO_ACTION
on_delete = CASCADE
}
foreign_key "captain_prompt_runs_root_session_id_fkey" {
columns = [column.root_session_id]
ref_columns = [table.captain_sessions.column.id]
Expand Down Expand Up @@ -192,6 +218,9 @@ table "captain_prompt_runs" {
index "captain_prompt_runs_state_idx" {
columns = [column.state, column.phase, column.updated_at]
}
index "captain_prompt_runs_turn_id_idx" {
columns = [column.turn_id]
}

check "captain_prompt_runs_iteration_nonnegative" {
expr = "current_iteration >= 0"
Expand All @@ -208,6 +237,9 @@ table "captain_prompt_runs" {
check "captain_prompt_runs_time_order" {
expr = "(started_at IS NULL OR started_at >= queued_at) AND (finished_at IS NULL OR (started_at IS NOT NULL AND finished_at >= started_at))"
}
check "captain_prompt_runs_provider_checkpoint" {
expr = "(provider_checkpoint IS NULL AND provider_checkpoint_codec IS NULL AND provider_checkpoint_version IS NULL) OR (provider_checkpoint IS NOT NULL AND length(btrim(provider_checkpoint_codec)) > 0 AND provider_checkpoint_version > 0)"
}
}

table "captain_prompt_run_iterations" {
Expand Down
Loading
Loading