Documentation
¶
Overview ¶
Package cli implements a composer.Composer backed by the operator's resident coding-agent CLI (Claude Code or Codex) running under its own logged-in SUBSCRIPTION — no API key is minted or passed. It shells out to the CLI with a schema-forcing structured-output mode, extracts the schema-valid JSON object the CLI emits, and hands it to composer.ProposeWithRetry for the canonical parse/validate/bounded-retry/fail-closed loop.
Trust model: the child runs on the CONTROL-PLANE host against UNTRUSTED input (task text + attachments), so it must be able to take NO action against the host. Wardyn enforces this per tool with explicit least-privilege flags, NOT the CLI's ambient default: codex gets `--sandbox read-only --ask-for-approval never` (which also blocks the network); claude gets `--permission-mode plan` PLUS an explicit `--disallowedTools` denylist (composerDisallowedTools) — plan mode ALONE still permits read-only tools including WebFetch/WebSearch (network), host file reads, and any resident MCP tool, so the denylist PLUS `--strict-mcp-config` (which drops every operator MCP server) is what actually closes host file-exfiltration / SSRF from a prompt-injected attachment (H12). The CLI is used purely as a structured-output text generator; its output is Grade+Clamped downstream. ANTHROPIC_API_KEY is scrubbed from the child env for the claude tool so it uses the subscription session (never an API key) and never bills/leaks one.
Index ¶
Constants ¶
const ( ToolClaude = "claude" ToolCodex = "codex" )
Tool identifies which resident CLI to shell out to.
const ( ComposerDisallowedTools = composerDisallowedTools ComposerMaxTurns = composerMaxTurns )
ComposerDisallowedTools / ComposerMaxTurns re-export the claude least-privilege arg values so the SANDBOX composer backend — which runs this SAME claude wire INSIDE a governed run instead of on the host — reuses the EXACT denylist + turn cap. One source of truth: a new built-in tool added to composerDisallowedTools tightens both wires at once.
Variables ¶
This section is empty.
Functions ¶
func ExtractProposalJSON ¶ added in v0.4.0
ExtractProposalJSON pulls the schema-valid proposal object out of the claude `-p --output-format json` wrapper (its ".structured_output" field) — the bytes composer.ParseProposal/ProposeWithRetry parse. It is exported so the SANDBOX composer backend, which runs this SAME claude wire inside a governed run and receives claude's raw stdout back over the brokered upload, parses the wrapper IDENTICALLY (no reinvented JSON handling). Semantics match runClaude's old inline parse: a non-wrapper response returns the raw bytes (ParseProposal then fails closed / the loop retries); a wrapper is_error is a real backend error returned immediately; a wrapper with no object returns the empty bytes.
func NewComposer ¶
NewComposer validates cfg and returns a Composer that shells out to the operator's resident subscription CLI. It does NOT verify the binary exists at construction time (the operator may install it later / it may live only in the daemon's PATH); a missing binary surfaces as a clear error on Propose.
Types ¶
type Config ¶
type Config struct {
// Tool selects the resident CLI: "claude" (Claude Code) or "codex".
Tool string
// Model is the model id passed to the CLI (e.g. "claude-sonnet-4-5",
// "gpt-5"). Empty lets the CLI use its own configured default.
Model string
// BinPath is the path to the CLI binary. Empty defaults to the tool name
// ("claude" / "codex"), resolved against PATH.
BinPath string
// Timeout bounds a single CLI invocation. Zero uses defaultTimeout.
Timeout time.Duration
// MaxAttempts bounds the parse/validate/retry loop. <1 uses
// composer.DefaultMaxAttempts.
MaxAttempts int
}
Config configures the CLI composer backend.