cli

package
v0.22.66 Latest Latest
Warning

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

Go to latest
Published: Apr 30, 2026 License: MIT Imports: 59 Imported by: 0

Documentation

Overview

Package cli — `clawtool a2a` subcommand. Phase 1 surface for ADR-024 (A2A networking): emits the agent's A2A Agent Card to stdout, lists registered peers from the daemon's local registry. mDNS announce, cross-host transport, and capability tier enforcement land in Phase 2+.

Package cli implements clawtool's user-facing subcommands.

Subcommand layout (ADR-004 §4):

clawtool init              interactive wizard: pick recipes, apply to repo
clawtool serve             run as MCP server (delegates to internal/server)
clawtool version           print version
clawtool help              print top-level usage
clawtool tools list        list known tools and resolved enabled state
clawtool tools enable <s>  set tools.<selector>.enabled = true
clawtool tools disable <s> set tools.<selector>.enabled = false
clawtool tools status <s>  print resolved state and the rule that won

Source / profile / group subcommands are scaffolded in main.go usage but not wired in v0.2 — they land alongside the source-instance feature.

Package cli — short markdown completion message for init runs.

ChatRender produces a 3-line markdown block aimed at a chat session: a parent LLM context driving clawtool over MCP wants to surface a digest of what just happened without re-rendering the full TTY output. The format is deliberately rigid so downstream consumers can pattern-match it:

✓ N recipes applied: a, b, c
○ M already present (idempotent skip)
→ Suggested next: <first NextStep>; <second NextStep>

Lines are emitted unconditionally (zeros render as "0"). When NextSteps is empty the third line is omitted. Lives in its own file so the chat-onboard branch can import this single helper without pulling the whole init wizard's dependency closure.

`clawtool daemon` — manage the persistent shared MCP server every host (Codex / OpenCode / Gemini / Claude Code) fans into. The adapter (internal/agents/mcp_host.go) calls daemon.Ensure under the hood when the operator runs `clawtool agents claim <host>`, but the CLI exposes the lifecycle directly so the operator can start / stop / inspect the daemon without going through claim.

Package cli — `clawtool doctor` is the one-command diagnostic. It surveys binary / agents / sources / recipes and prints a colour-coded checklist with suggested fix commands. Pure composition of existing internal helpers — no new deps.

`clawtool egress` — runs the egress allowlist proxy (ADR-029 phase 4, task #209). Sandbox workers route their HTTP_PROXY / HTTPS_PROXY through this binary so model-generated network calls pass through an explicit allowlist before reaching the host network.

Operator path:

clawtool egress --listen :3128 \
    --allow api.openai.com,api.anthropic.com,.github.com

In the worker container:

docker run -e HTTP_PROXY=http://egress:3128 \
           -e HTTPS_PROXY=http://egress:3128 \
           clawtool-worker:0.21 ...

Package cli — wizard-side install-prompt UX. Implements setup.Prompter (the abstraction the runner uses for missing prereqs) on top of huh + os/exec, plus the CommandRunner that actually shells out the per-platform install commands.

Kept in a separate file from init_wizard.go so the prompter + runner pair can be swapped or wrapped (e.g. by a dry-run wrapper) without touching the rest of the wizard. Test files inject a recordingRunner and a scriptedPrompter against the same interfaces — the wizard surface stays huh-bound, but every install decision is exercised in unit tests.

Package cli — structured summary of an `init` run.

InitSummary is the machine-parseable counterpart to the human- readable lines `clawtool init` prints. The chat-driven onboard flow (a parallel branch) consumes either the `--summary-json` stdout payload or the in-process struct directly to decide what to surface to the operator and what to do next.

The shape is intentionally narrow and append-only: chat-onboard can take a hard dependency on these field names. Adding new fields is fine; renaming or removing them is a breaking change.

Package cli — `clawtool init` wizard. Two-scope welcome screen: repo (recipes) and user-global (agents + sources + secrets), with "both" and a read-only "show me what's available" preview path.

Honors --yes for non-interactive runs and falls back to the same path when stdin/stdout aren't TTYs (CI / containers).

Package cli — `clawtool mcp` subcommand surface (ADR-019).

v0.17 fills in `new`, `list`, `run`, `build`, `install`. The `new` verb runs the huh.Form wizard implemented in mcp_wizard.go; `install` lives in mcp_install.go; this file keeps the dispatcher + the read-only `list` walker.

Package cli — `clawtool mcp install` (ADR-019).

Reads `.clawtool/mcp.toml` from the project at <path>, derives the launch command from the project's language + transport, writes a [sources.<name>] block into ~/.config/clawtool/config.toml. Same surface as `clawtool source add` for catalog entries — just auto-discovers the command instead of asking.

Package cli — `clawtool mcp new` interactive wizard (ADR-019).

huh.Form sequence collects the operator's spec, hands it to internal/mcpgen which renders + writes the project. Tests substitute mcpgenDeps to drive the wizard without hitting disk.

Package cli — `clawtool` (no args) launches a friendly TUI landing menu that points at the most-used flows. Designed for users who'd rather not memorise subcommands; pure huh.Select.

internal/cli/onboard_resume.go — wizard progress persistence so `clawtool onboard` can survive mid-flow interruption (Ctrl-C, terminal close, accidental crash) and pick up where it left off instead of starting from step 1 each time.

Wire:

  • State file: $XDG_CONFIG_HOME/clawtool/.onboard-progress.json (mode 0600 — same conventions as the rest of the config tree).
  • Saved after every wizard step completion (step index + the onboardState snapshot at that point).
  • Cleared after a successful finish so the next `clawtool onboard` either starts fresh (if .onboarded marker absent) or hits the "already onboarded → redo?" guard.

Re-entry behaviour:

  • .onboarded marker present, no progress file → "Already onboarded. Re-run the wizard?"
  • Progress file present → "Resume from step X?" (No = wipe progress + start fresh).
  • Neither → fresh wizard, no extra prompt.

internal/cli/onboard_tui.go — Bubble Tea wizard for `clawtool onboard`. Replaces the prior linear huh.NewForm(groups...) flow with a step-by-step wizard: each question gets its own focused viewport with a "Step X of Y" indicator, the rounded-box header stays pinned at the top, and the side-effect run phase renders as live progress inside the same alt-screen program.

Why:

  • Operator wanted bounded TUI ("vim/htop feel") instead of the scroll-pollution we'd get from emitting a clear sequence and dumping output below the prompt. tea.WithAltScreen() owns a dedicated screen buffer; on exit the operator's terminal state is restored exactly as it was.
  • Stepwise progression makes the wizard feel structured. The prior huh.NewForm rendered all groups in one continuous form; the operator couldn't tell where they were in the sequence.

Non-TTY / `--yes` invocations still run through the linear onboard() path so CI scripts, Dockerfiles, and the test harness keep their stable plain-text contract.

internal/cli/onboard_ux.go — visual rendering for `clawtool onboard`. Onboard is the first ten seconds the operator spends with clawtool; the wizard either hooks them or churns them. This file polishes that surface:

  • Clear screen on entry so the operator sees a clean canvas, not the pile of `npm install` / `git status` noise that was in their terminal when they typed `clawtool onboard`.
  • Boxed header with the live host-detection result rendered as a single tight row of ✓ / ✗ pills.
  • Phase-style side-effect output (Section / PhaseStart / PhaseDone) instead of raw `stdoutLn` lines, so a multi- bridge install reads as a labelled progress block.
  • Tight final summary: a ✓-checklist of what was wired, not the full `clawtool overview` dump.

Mirrors upgrade_ux.go's design constraints: TTY-aware (plain ASCII when piped), no spinners (Ctrl-C-friendly), one-shot output.

internal/cli/onboard_widgets.go — minimal custom wizard widgets (Select / MultiSelect / Confirm) that replace charmbracelet/huh inside the onboard alt-screen TUI.

Why custom: huh.Form embedding inside our parent tea.Program had two intractable bugs we kept rediscovering:

  1. huh's Select widget renders only the cursor row when its internal viewport height is unset. WindowSizeMsg.Height does NOT propagate to per-field viewports — only Form.WithHeight() and Select.Height() do, and we don't want clamping anyway.
  2. Wrapping huh.View() in a height-clamped lipgloss style fights huh's own internal styles.Base.Height() — the inner clamp wins at minHeight=1, killing the option list.

These widgets render every option every frame, no viewport, no height drama. They expose:

  • Update(msg) — route a tea.Msg, returns updated widget + cmd
  • View() — render full natural-size output
  • Done() — true once the operator submitted
  • Keybinds() — short hint string for the wizard's footer (e.g. "↑/↓ select · enter confirm")

The wizard's outer model owns navigation between widgets; the widgets only handle their own keys.

Package cli — `clawtool orchestrator` (aliases: dashboard, tui, orch). One Bubble Tea program — the orchestrator — fronted by four interchangeable verbs because operators reach for whichever name they remember. All four routes call this single handler.

Two modes:

default                interactive Bubble Tea TUI in alt-screen
--plain / --once       stdout snapshot for chat-visible pairing
                       with the Monitor tool (no TUI)

Pre-v0.22.36 we shipped two distinct programs (dashboard.go + orchestrator.go) that both called tui.RunOrchestrator and got maintained independently. They drifted, the docstrings disagreed on which "is the real one", and operators had to memorise the alias-to-program mapping. The single-handler shape replaces all of that.

`clawtool overview` — one-screen status of the running system (UX gap from the #193 smoke pass). Operators wanted a single verb that reports daemon + sandbox-worker + agents + bridges without remembering five subcommand names.

This deliberately skips diagnostic depth (`clawtool doctor` remains the deep checklist). Overview is the at-a-glance "is everything wired?" answer.

Package cli — `clawtool peer` subcommand. Phase 1 surface for ADR-024 peer discovery: the runtime-side primitive every hook (claude-code, codex, gemini, opencode) calls to register the running session into the daemon's peer registry.

Three verbs:

clawtool peer register --backend X [--display-name Y] [--session ID]
clawtool peer heartbeat [--session ID] [--status busy|online]
clawtool peer deregister [--session ID]

State: each register writes the assigned peer_id to a session- keyed file under ~/.config/clawtool/peers.d/<session>.id, so the downstream heartbeat / deregister calls find the right peer without the hook having to thread the id explicitly. Session IDs come from the runtime's hook payload (claude-code's transcript_path already has one); when --session is omitted, falls back to "default" — single-session-per-host hosts work out of the box.

Package cli — `clawtool portal` subcommand surface (ADR-018).

Read-only + persistence operations land in v0.16.1. The interactive `ask` flow that drives Obscura over CDP arrives in v0.16.2; today it returns a clear "deferred" error so the surface is discoverable before the engine ships.

Package cli — `clawtool portal add` interactive wizard (ADR-018, v0.16.3).

Rebuilt on top of the chromedp-backed BrowserSession (ADR-007). Spawns the user's installed Chrome with --headless=false + a temp profile, waits for them to log in (optionally with a copy/paste prompt for the Claude in Chrome side-panel), pulls cookies via Network.getAllCookies, collects the three CSS selectors + a "response done" predicate template, and writes config.toml + secrets.toml.

Per ADR-017 we never wrap claude-in-chrome — the wizard generates a plain-text prompt the operator can paste. clawtool stays MCP-server-free for the wizard transport.

Package cli — `clawtool rules` subcommand. Lifecycle management for the operator's predicate-based invariants in .clawtool/rules.toml (project-local) or ~/.config/clawtool/rules.toml (user-global).

Operator-facing surface:

clawtool rules list                     show every loaded rule + its source
clawtool rules show <name>              detail view of one rule
clawtool rules new <name> [flags]       add a new rule (asks scope when ambiguous)
clawtool rules remove <name>            delete a rule
clawtool rules path [--user|--local]    print the rules file path
clawtool rules check <event> [flags]    one-shot evaluation against current state

Why this lives in CLI: the operator wants to add a rule from a fresh-context shell without firing up an editor; the parallel MCP-side tool (RulesAdd) is a thin wrapper that calls the same rules.AppendRule helper this CLI does.

Package cli — `clawtool sandbox` subcommand surface (ADR-020).

v0.18 ships read-only verbs (list / show / doctor) plus the surface stub for `run`. The dispatch-time integration (`clawtool send --sandbox <profile>`) lands v0.18.1+ alongside the per-OS engine implementations.

`clawtool sandbox-worker` — runs the sandbox worker (ADR-029 phase 1). Mirrors `clawtool serve --listen` semantics but for the worker leg of the orchestrator+worker pair: bearer-auth'd WebSocket endpoint that the daemon dials to route Bash / Read / Edit / Write tool calls into an isolated container.

Operator runs this inside a docker / runsc container; the daemon is the only trusted dialer. Auth is a shared bearer token; the worker reads it from a file or stdin so it never lands in argv.

Package cli — `clawtool setup` is the unified first-run entry. Phase 2 of ADR-027: one huh form with a per-feature opt-in matrix instead of the onboard → init verb chain. --legacy falls back to the Phase 1 sequential dispatch for operators who hit a bug or prefer the old prompts.

Package cli — Phase 2 setup state machine. Collapses onboard + init into one huh form with a single per-feature opt-in matrix. Per ADR-027: probe → matrix → required options → apply → verify.

Phase 2 v1 ships the matrix for: bridge installs, MCP host claims, daemon up, BIAM identity, secrets store init, telemetry, AND the subset of recipes that are Stable + don't require any caller-supplied options. Recipes with required options (license, codeowners, …) still flow through `clawtool init`'s per-recipe prompts since the matrix can't ask for option values inline.

`clawtool setup --legacy` falls back to the Phase 1 chain (onboard → init) for operators who prefer the old verb shape.

Package cli — helper wiring for setup_wizard.go. Lives alongside onboard.go so the production callbacks share one import set (daemon, agents, biam, secrets) without bloating setup_wizard.go.

Package cli — `clawtool skill` subcommand. Scaffolds and lists Agent Skills per the agentskills.io spec: a folder containing SKILL.md (required, with frontmatter name + description) plus optional scripts/, references/, assets/ subdirectories.

The standard was authored by Anthropic and is now open. clawtool's skill subcommand is the bootstrap layer — `clawtool skill new` is the analogue of `npm init` for Agent Skills.

Package cli — `clawtool task watch` (ADR-026, Gemini design pass b8ab4c9a). Streams BIAM task state transitions as one stdout line per event so the operator can pair it with Claude Code's native Monitor tool and see dispatch progress as inline chat events.

Two modes:

clawtool task watch <task_id>   single task, exits when terminal
clawtool task watch --all       every active task, runs forever
                                 (or until SIGINT / pipe close)

Output format defaults to human-readable; --json switches to NDJSON for downstream tooling.

Polling cadence is 250ms by default — sub-second feel with negligible disk pressure on SQLite WAL. Tunable via --poll-interval.

Per the ADR's security clause, watch lines NEVER carry the task's body / completion text — only metadata (status, agent, message_count, last_message preview capped at 80 chars). A gigabyte-sized completion blob landing in the operator's chat would be its own outage.

Package cli — `clawtool unattended` subcommand. Operator-facing trust management for ADR-023's --unattended dispatch mode.

Two surfaces:

clawtool unattended status [<repo>]    show whether <repo> (or cwd) is trusted
clawtool unattended grant  [<repo>]    explicitly trust <repo> for unattended dispatch
clawtool unattended revoke [<repo>]    remove the trust grant
clawtool unattended list               list every granted repo
clawtool unattended path                print the trust file location

`clawtool yolo` is a deliberately-jokey alias so operators searching docs / muscle-memory the Cline term find it.

Package cli — `clawtool uninstall` removes every artifact clawtool drops on the host. Designed for the tester / dogfooder who installs the binary fresh ten times a day and ends up with duplicate sources / portals / sticky defaults.

The cleanup is intentionally exhaustive — config + secrets + caches + data dirs + sticky pointers + worktrees + BIAM SQLite + telemetry id. The binary itself is opt-in (--purge-binary) because the user may have installed via Homebrew / curl / Go and the right removal command differs by source.

Per ADR-007 doesn't apply here: this is "rm -rf clawtool's own files", which is by definition not delegable to an upstream. We still rely on stdlib os.RemoveAll for the actual removal.

internal/cli/upgrade_ux.go — visual rendering for `clawtool upgrade`. The upgrade flow is one of the rare CLI moments where the user is actively waiting on us; that's where polish earns disproportionate trust. This file encapsulates the rendering so upgrade.go's orchestration stays linear and readable.

Design constraints:

  • TTY-aware: colours + box-drawing only when stdout is a real terminal. Pipe-redirect (e.g. `clawtool upgrade | tee`) gets plain ASCII so log files stay greppable.
  • No spinner / animation: the upgrade is short (1–5s on a local network), and an animated spinner stuck to the terminal control codes turns into garbage when redirected. Static phase markers ("→ doing X" → "✓ X (350ms)") read fine in both modes.
  • One-shot output: each phase prints its line as it completes, so a Ctrl-C mid-flow leaves a partial but legible transcript instead of a half-redrawn screen.

Index

Constants

This section is empty.

Variables

View Source
var ErrApmManifestMissing = errors.New("apm: manifest file not found")

ErrApmManifestMissing is returned when the apm.yml the operator pointed at doesn't exist on disk. Tests pin this typed error.

View Source
var ErrApmYAMLParse = errors.New("apm: yaml parse error")

ErrApmYAMLParse wraps a yaml.v3 decode failure so tests can assert errors.Is without depending on the upstream's error type.

View Source
var ErrSourceNotFound = errors.New("source not found")

ErrSourceNotFound is returned by `source inspect` when the operator names an instance that isn't in the local config. Stable error so scripts can branch on it via errors.Is.

Functions

func IsOnboarded added in v0.22.13

func IsOnboarded() bool

IsOnboarded reports whether the operator has completed the onboard wizard at least once. Exported so the SessionStart hook (claude_bootstrap.go) and the no-args first-run check can both consume the same signal.

Types

type App

type App struct {
	Stdout io.Writer
	Stderr io.Writer
	Stdin  io.Reader
	// ConfigPath overrides the default config location. Empty = config.DefaultPath().
	ConfigPath string
	// contains filtered or unexported fields
}

App holds CLI dependencies. Stdout/stderr are injected so tests can capture.

func New

func New() *App

New returns an App writing to the process's stdout/stderr and using the default config path.

func (*App) AgentUnset added in v0.20.0

func (a *App) AgentUnset() error

AgentUnset clears the sticky default file. Idempotent.

func (*App) AgentUse added in v0.20.0

func (a *App) AgentUse(instance string) error

AgentUse persists the sticky default. We validate the instance exists in the supervisor's registry up front so the user gets a clean error here rather than at the next `clawtool send`.

func (*App) AgentWhich added in v0.20.0

func (a *App) AgentWhich() error

AgentWhich resolves the empty selector and prints the result. Same precedence chain Send uses, exposed read-only for the user to inspect what would happen.

func (*App) BridgeAdd added in v0.20.0

func (a *App) BridgeAdd(family string) error

BridgeAdd resolves the family to its recipe and applies it. Idempotent; if the bridge is already installed Detect returns Applied and Apply short-circuits.

func (*App) BridgeList added in v0.20.0

func (a *App) BridgeList(format listfmt.Format) error

BridgeList prints all known bridge recipes with their Detect state. Output format follows the operator's --format flag: table (default, human-readable), tsv (pipe-friendly), json (programmatic).

func (*App) BridgeRemove added in v0.20.0

func (a *App) BridgeRemove(family string) error

BridgeRemove is a placeholder. Claude Code's `claude plugin remove` surface isn't standardized yet across plugin types; v0.10.x will add proper uninstall semantics. For now we print a manual hint.

func (*App) HooksInstall added in v0.22.36

func (a *App) HooksInstall(runtime string) error

HooksInstall prints the runtime-specific snippet that wires <runtime> into clawtool's peer registry. We deliberately *print* rather than mutate config files: each runtime's config layout changes between versions, and an operator can paste the snippet into whichever location their version expects. claude-code's bundled hooks/hooks.json already covers it via the plugin, so we short-circuit there.

func (*App) HooksList added in v0.20.0

func (a *App) HooksList(format listfmt.Format) error

HooksList prints every configured event with its entry count. Empty config → friendly hint.

func (*App) HooksShow added in v0.20.0

func (a *App) HooksShow(event string) error

HooksShow dumps the per-entry config for a single event.

func (*App) HooksTest added in v0.20.0

func (a *App) HooksTest(event string, payload map[string]any) error

HooksTest synthesises the event with the given payload and runs every configured entry. Prints per-entry success/failure so the operator can iterate on hook scripts without firing the real lifecycle event (which might be hard to reproduce).

func (*App) Init

func (a *App) Init() error

Init writes a default config to disk if the file does not already exist. Returns an "already exists" error if it does — callers can ignore that.

func (*App) McpList added in v0.20.0

func (a *App) McpList(argv []string) error

McpList walks `root` (default cwd) for `.clawtool/mcp.toml` markers and prints one line per project. Skips node_modules / vendor / .git so a recursive walk doesn't melt on a typical repo.

func (*App) Path

func (a *App) Path() string

Path returns the resolved config path (override > default).

func (*App) PortalAdd added in v0.20.0

func (a *App) PortalAdd(name string) error

PortalAdd opens $EDITOR with a TOML template for the named portal. On save we validate the parsed stanza and append it to config.toml. The validation refuses anything that wouldn't drive an Ask flow successfully, so a fat-finger landing in config never reaches the dispatch path.

func (*App) PortalAsk added in v0.20.0

func (a *App) PortalAsk(argv []string) error

PortalAsk is the deferred-feature placeholder. Validates the resolved portal so the operator gets the same diagnostics they will get in v0.16.2, then surfaces the deferred error.

func (*App) PortalList added in v0.20.0

func (a *App) PortalList(format listfmt.Format) error

PortalList prints the configured portals one per line — same shape as `clawtool send --list` so the operator sees both surfaces consistently. Compile-time drivers (bifrost and other gateway integrations registered via portal.RegisterDriver) are merged into the same table with a STATUS column so operators discover deferred / ready integrations alongside their hand-saved web-UI portals.

func (*App) PortalRemove added in v0.20.0

func (a *App) PortalRemove(name string, dryRun bool) error

PortalRemove rewrites config.toml without the [portals.<name>] stanza. Cookies in secrets.toml are left in place so a temporary remove-then-re-add doesn't lose the export. Operators clean secrets manually when they want a true uninstall.

When dryRun is true, the existence check still runs (so typos surface at preview time) but the file is not rewritten — the caller gets a `(dry-run) would remove …` banner instead of the success line. Symmetric with `source remove --dry-run` (b364ec6) and the rest of the dry-run uniformity series.

func (*App) PortalUnset added in v0.20.0

func (a *App) PortalUnset() error

PortalUnset removes the sticky-default file. Idempotent.

func (*App) PortalUse added in v0.20.0

func (a *App) PortalUse(name string) error

PortalUse persists the sticky default for `clawtool portal ask`.

func (*App) PortalWhich added in v0.20.0

func (a *App) PortalWhich() error

PortalWhich resolves the sticky-default portal. Same precedence chain as the agent sticky default (env > sticky file > single- configured fallback).

func (*App) RecipeApply added in v0.9.0

func (a *App) RecipeApply(name string, kvs []string) error

RecipeApply runs the recipe against the current working directory. Options are key=value strings; comma-separated values become []string. v0.9 keeps options simple — wizard / MCP path will pass richer types as the surface evolves.

func (*App) RecipeList added in v0.9.0

func (a *App) RecipeList(category string) error

RecipeList prints every registered recipe grouped by category with its Detect state in the cwd.

func (*App) RecipeStatus added in v0.9.0

func (a *App) RecipeStatus(name string) error

RecipeStatus prints the Detect output for one recipe or all recipes.

func (*App) Run

func (a *App) Run(argv []string) int

Run dispatches argv (excluding program name) to the right subcommand. Returns the exit code; 0 = success, 2 = usage error, 1 = runtime failure.

Every dispatch is timed and emitted as a `cli.command` telemetry event (when telemetry is opted in) — command, subcommand, exit_code, duration_ms, error_class. Long-running verbs (`serve`, `dashboard`, `daemon` foreground) emit on dispatcher exit so a 2-hour `serve` session lands as one event with the full uptime.

func (*App) SandboxDoctor added in v0.20.0

func (a *App) SandboxDoctor(asJSON bool) error

SandboxDoctor reports every registered engine's availability. JSON path emits a stable {engines, selected} shape — automation pipelines that gate on `selected == "noop"` to flag missing enforcement can branch on it without parsing the human table.

func (*App) SandboxList added in v0.20.0

func (a *App) SandboxList(format listfmt.Format) error

SandboxList prints every configured profile + the engine that would run it on this host.

func (*App) SandboxShow added in v0.20.0

func (a *App) SandboxShow(name string) error

SandboxShow parses one profile + prints the resolved view.

func (*App) SecretsPath

func (a *App) SecretsPath() string

SecretsPath returns the secrets-store path. Tests can shadow App.SecretsPath to point at a tmp file; production uses secrets.DefaultPath().

func (*App) Send added in v0.20.0

func (a *App) Send(args sendArgs) error

Send routes through Supervisor.Send and streams stdout.

func (*App) SendList added in v0.20.0

func (a *App) SendList() error

SendList prints the supervisor's agent registry — same shape as the MCP `AgentList` response and the HTTP `GET /v1/agents` body.

func (*App) SetSecretsPath

func (a *App) SetSecretsPath(p string)

SetSecretsPath lets tests redirect the secrets store to a tmp file.

func (*App) TaskCancel added in v0.21.5

func (a *App) TaskCancel(taskID string) error

TaskCancel flips a pending/active task to "cancelled". The CLI invocation is a separate process from the runner that owns the dispatch goroutine, so we do a store-only flip + Notifier publish here — the runner side handles in-process cancel via Runner.Cancel when the same caller already holds it. Cross-process pollers (`clawtool task watch`) wake on the Notifier broadcast.

Audit fix #204: pairs with Runner.Cancel — without this the CLI had no way to abort a runaway --async dispatch short of kill -9 on the binary.

func (*App) TaskGet added in v0.20.0

func (a *App) TaskGet(taskID string) error

TaskGet prints the task row + every message envelope for the task, JSON-formatted so a script can parse it.

func (*App) TaskList added in v0.20.0

func (a *App) TaskList(limit int, filter taskFilter, statusOverride string) error

TaskList prints the recent BIAM task summary, filtered by `filter`. When filter == taskFilterStatus, `statusOverride` names the single status to keep (done | failed | cancelled | expired). To honour the operator-supplied --limit while still filtering meaningfully, we pull a wider window from the store (10× limit, capped at 1000) and slice client-side.

func (*App) TaskWait added in v0.20.0

func (a *App) TaskWait(taskID string, timeout time.Duration) error

TaskWait blocks until the task is terminal, then dumps the same shape TaskGet does.

func (*App) ToolsDisable

func (a *App) ToolsDisable(selector string) error

ToolsDisable writes tools.<selector>.enabled = false.

func (*App) ToolsEnable

func (a *App) ToolsEnable(selector string) error

ToolsEnable writes tools.<selector>.enabled = true.

func (*App) ToolsExportTypeScript added in v0.22.31

func (a *App) ToolsExportTypeScript(outDir string) error

ToolsExportTypeScript emits the manifest as a TypeScript module tree under outDir. One .ts per tool plus an index.ts barrel. The underlying generator (registry.Manifest.ExportTypeScript) is the single source of truth — this method just wires the manifest + stdout chatter.

func (*App) ToolsList

func (a *App) ToolsList() error

ToolsList prints every shipped tool — both the file/exec/web primitives in config.KnownCoreTools and the dispatch/agent/task/ recipe/bridge surface registered via core.BuildManifest().

Pre-v0.22.20 this only listed config.KnownCoreTools (9 entries), which created a confusing UX gap: SendMessage / AgentList / TaskGet / etc. WERE registered with the MCP server at daemon boot (host CLIs see them as `mcp__clawtool__SendMessage`) but `clawtool tools list` never showed them — operators couldn't confirm what surface their hosts actually had access to. Now the union of both sources is rendered, deduped on Name, sorted alphabetically. Resolution still flows through cfg.IsEnabled so per-selector overrides work for every tool — even ones that don't have an explicit core_tools.X entry.

func (*App) ToolsStatus

func (a *App) ToolsStatus(selector string) error

ToolsStatus prints the resolved enabled state for a selector and the rule that won, per ADR-004 §4.

func (*App) Uninstall added in v0.20.0

func (a *App) Uninstall(args uninstallArgs) error

Uninstall performs the cleanup. Public so the MCP tool surface + integration tests can call it without going through argv.

func (*App) WorktreeGC added in v0.20.0

func (a *App) WorktreeGC(minAge time.Duration) error

WorktreeGC reaps orphans (dead PID + minAge cutoff).

func (*App) WorktreeList added in v0.20.0

func (a *App) WorktreeList() error

WorktreeList prints every worktree under ~/.cache/clawtool/worktrees with its marker info. Useful before running gc to see what's reapable.

func (*App) WorktreeShow added in v0.20.0

func (a *App) WorktreeShow(taskID string) error

WorktreeShow dumps the marker JSON for one worktree.

type InitSummary added in v0.22.60

type InitSummary struct {
	AppliedRecipes []RecipeApply     `json:"applied_recipes"`
	SkippedRecipes []RecipeSkip      `json:"skipped_recipes"`
	PendingActions []string          `json:"pending_actions"`
	Generated      map[string]string `json:"generated"`
	NextSteps      []string          `json:"next_steps"`
}

InitSummary is the structured tail of `clawtool init`. Designed for two audiences:

  • Operators on a TTY get the human-readable rendering (the pre-existing wizard output, unchanged by default).
  • LLM / chat-onboard sessions get this struct serialised as compact JSON via `--summary-json`, or in-process via ChatRender() when re-used from the parallel chat branch.

Field semantics:

  • AppliedRecipes: every recipe the apply loop touched, including idempotent skips (status=already-present) and failures (status=failed). One entry per recipe considered.
  • SkippedRecipes: recipes that never reached Apply because the pre-filter dropped them (deselected, needs options, not Core).
  • PendingActions: human-curated next-step suggestions built from the registry's known follow-ups (e.g. "install gh CLI").
  • Generated: files written this run, keyed by absolute path, value is the managed-by marker ("clawtool" / "external").
  • NextSteps: ordered, prompt-friendly bullets for an LLM to read aloud. Distinct from PendingActions: NextSteps is the curated short-list (≤5), PendingActions is the full registry.

func (InitSummary) AlreadyPresentCount added in v0.22.60

func (s InitSummary) AlreadyPresentCount() int

AlreadyPresentCount returns the count of idempotent skips.

func (InitSummary) AppliedCount added in v0.22.60

func (s InitSummary) AppliedCount() int

AppliedCount returns the number of rows whose terminal status is RecipeStatusApplied. Used by ChatRender and by the JSON consumer to decide whether anything actually changed.

func (InitSummary) AppliedNames added in v0.22.60

func (s InitSummary) AppliedNames() []string

AppliedNames returns recipe names in apply order, filtered to status=applied. Used by ChatRender for the "✓ N recipes applied: foo, bar" line.

func (InitSummary) ChatRender added in v0.22.60

func (s InitSummary) ChatRender() string

ChatRender returns the markdown completion paragraph. Stable output: pinned by TestInitSummary_ChatRender. The chat-onboard branch (parallel) imports this verbatim.

func (InitSummary) FailedCount added in v0.22.60

func (s InitSummary) FailedCount() int

FailedCount returns the count of recipes whose Apply errored.

func (InitSummary) WriteJSON added in v0.22.60

func (s InitSummary) WriteJSON(w io.Writer) error

WriteJSON emits the summary as compact JSON terminated by a newline. Used by the `--summary-json` flag in runInitAll. Errors are returned to the caller so the dispatcher can downgrade the exit code if the encoder fails (it shouldn't — InitSummary has no non-marshallable types).

type RecipeApply added in v0.22.60

type RecipeApply struct {
	Name     string            `json:"name"`
	Category string            `json:"category"`
	Status   RecipeApplyStatus `json:"status"`
	Error    string            `json:"error,omitempty"`
}

RecipeApply is one row of the apply loop. Status is mandatory; Error is set only when Status == RecipeStatusFailed.

type RecipeApplyStatus added in v0.22.60

type RecipeApplyStatus string

RecipeApplyStatus enumerates the terminal states of a single recipe in an init run. Stable string values — chat-onboard reads them verbatim.

const (
	// RecipeStatusApplied: recipe wrote artifacts this run.
	RecipeStatusApplied RecipeApplyStatus = "applied"
	// RecipeStatusAlreadyPresent: Detect reported non-Absent
	// before Apply ran. Idempotent skip — nothing was written.
	RecipeStatusAlreadyPresent RecipeApplyStatus = "already-present"
	// RecipeStatusSkipped: recipe was deselected, deferred (e.g.
	// needs required options), or the prompter voted skip.
	RecipeStatusSkipped RecipeApplyStatus = "skipped"
	// RecipeStatusFailed: Apply returned a non-skip error.
	RecipeStatusFailed RecipeApplyStatus = "failed"
)

type RecipeSkip added in v0.22.60

type RecipeSkip struct {
	Name   string `json:"name"`
	Reason string `json:"reason"`
}

RecipeSkip captures why a recipe never reached Apply. Reasons are short kebab-case tokens so chat-onboard can branch on them:

  • "operator-deselected" — user unchecked the row in the wizard
  • "missing-required-option" — recipe needs holder/owners/etc.
  • "not-core" — `--all` filter excluded the row
  • "stability-not-stable" — non-interactive defaults filter

type SummaryRow added in v0.22.38

type SummaryRow struct {
	Label   string
	Outcome string // "ok" | "skip" | "fail"
	Detail  string // optional dim suffix
}

SummaryRow is one line in the closing checklist.

Directories

Path Synopsis
Package listfmt — small renderer used by every `clawtool * list` subcommand (bridges, agents, sources, recipes, sandboxes, portals, hooks, …).
Package listfmt — small renderer used by every `clawtool * list` subcommand (bridges, agents, sources, recipes, sandboxes, portals, hooks, …).

Jump to

Keyboard shortcuts

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