Skill: wangnov/cli-design-framework (version 1.0.2)

--- name: cli-design-framework description: Use when designing a new CLI, reviewing an existing CLI, or resolving uncertainty about a CLI's role, user type, interaction form, statefulness, risk profile, or human-vs-machine surfaces. --- # CLI Design Framework ## Overview Design and review CLIs with a classification-first framework. Treat this as a decision system, not a generic style guide. Do not assume every CLI should become agent-first, machine-protocol-first, or raw-payload-first. ## When to Use Use this skill when: - designing a new CLI and the right command shape is not obvious - reviewing an existing CLI whose help, output, or command tree feels mismatched - deciding whether a CLI is primarily Capability, Runtime, Environment / Workspace, Workflow, Package / Build, or Meta - deciding whether human-readable and machine-readable surfaces are primary or secondary - deciding whether session semantics are justified or over-engineered Do not use this skill when: - the CLI classification is already settled and you only need implementation mechanics - the question is only about parser libraries, repository layout, or exact flag spelling - the task is purely cosmetic copy editing with no design consequence ## Quick Path - For quick asks, produce a compressed pass: purpose, classification, short reasoning, top design consequences, and only the unresolved questions that could change the answer. - Use the full blueprint or full review template only when the user asks for it explicitly, or when ambiguity or risk justifies the longer form. ## Core rule Classify first. Design second. Review third. Always work in this order: 1. State the CLI purpose in one sentence. 2. Classify the primary role/control surface. 3. Classify the primary user type. 4. Classify the primary interaction form. 5. Classify statefulness. 6. Classify risk profile. 7. Identify secondary surfaces explicitly. 8. Derive design consequences. Start with these files when using the framework: - `references/taxonomy.md` for the taxonomy. - `references/output-templates.md` for the required output shape. Pull these only when needed: - `references/classification-examples.md` for classification anchors when the category is ambiguous. - `examples/design-blueprint-example.md` and `examples/review-example.md` when you need a concrete example of final form. - `examples/anti-patterns.md` when the design smells wrong but the category mistake is not yet crisp. ## Operating modes Operate in one of two modes: 1. **Design mode** — create or refine a CLI design direction. 2. **Review mode** — evaluate an existing CLI against the framework. --- ## Design mode ### Goal Clarify the CLI's design target, then produce a blueprint that constrains implementation. ### Workflow 1. Infer what is already known. - Extract every strong signal from the user's request. - Infer likely role, user type, interaction form, statefulness, risk profile, and secondary surfaces whenever possible. - Do not ask for facts that are already strongly implied. 2. Ask only the highest-leverage unresolved questions. - Ask the smallest set of questions that could materially change the classification or the blueprint. - Prefer classification questions over implementation trivia. - Prioritize: purpose → control surface → primary user → interaction form → statefulness → side effects → secondary surfaces. - If the current information is already sufficient, do **not** ask questions. Produce the blueprint directly. 3. Classify the CLI explicitly. - State the inferred or confirmed: - primary role/control-surface type - primary user type - primary interaction form - statefulness - risk profile - secondary surfaces - State confidence when inference is uncertain. - Use explicit primary-vs-secondary wording. Do not blur them together. 4. State the design stance before proposing commands. - Write one short paragraph that says what the CLI is optimizing for. - State what the CLI is **not** trying to be. - Do not jump straight from classification to command trees. 5. Produce a design blueprint. - Use the structure in `references/output-templates.md`. - Use the full template when the user wants a blueprint or when the ambiguity/risk warrants it. - For quick requests, compress to: purpose, classification, classification reasoning, design stance, top design consequences, and only the unresolved questions that matter. - Connect classification directly to design consequences. - Keep the blueprint concrete, not generic. 6. Constrain downstream implementation. - End with a short direction section that states: - what to optimize for - what not to optimize for - acceptable patterns - category mistakes - v1 boundaries and non-goals ### Required design discipline For every blueprint, enforce these rules: - **Primary vs secondary surfaces** - Name the primary surface explicitly. - Name secondary surfaces explicitly. - State what each surface is for. - Do not describe JSON, event streams, templates, raw payloads, or TUI as “important” without saying whether they are primary or secondary. - **Human-primary / balanced discoverability** - If the CLI is human-primary or balanced, explicitly cover: - help quality - examples - discoverability - explain/describe surfaces when appropriate - Do not discuss only command structure and ignore learnability. - **Structured machine contract** - If the CLI has a machine-readable surface, explicitly state: - which commands expose it - output format (`--json`, `--jsonl`, etc.) - whether field names are stable - whether exit codes matter - whether schema / fields / describe support is needed - Do not call a surface “script-friendly” unless the contract is described. - **Risk ladder** - If the CLI mutates state, define at least: - low-risk operations - medium-risk operations - high-risk operations - State the expected guardrails for each level. - Do not stop at “be careful” or “add confirmations.” - **State model** - If the CLI is sessionful, long-running, or attach/detach capable, describe session identity and lifecycle explicitly. - If it is mostly stateless, say so explicitly and avoid inventing session semantics. - **v1 boundaries** - State what v1 should include. - State what v1 should defer. - State what would be premature abstraction. ### Question policy Ask only questions that affect classification or the blueprint. Do **not** begin with implementation-detail questions such as: - language choice - parsing library - repository layout - naming bikesheds - exact flag spelling Ask those only if they materially affect the CLI's classification or design consequences. --- ## Review mode ### Goal Inspect the CLI and its source, reverse-infer its design intent, then review it in two layers: 1. **Classification fit** — Is it designed like the right kind of CLI? 2. **Execution quality** — Given that type, how well is it executed? ### Workflow 1. Inspect before asking. - Inspect help output, subcommand help, docs, examples, parser code, output code, error handling, state/session code, config surfaces, and tests. - Prefer direct evidence over speculation. 2. Reverse-infer the design intent. - Infer: - apparent purpose - likely primary role/control-surface type - likely primary user type - likely interaction form - likely statefulness - likely risk profile - existing secondary surfaces 3. Confirm only what cannot be inferred reliably. - Ask focused confirmation questions only when the answer could materially change the classification or review. - Do not ask the user to restate facts already evident from the CLI or code. 4. Review in two layers. - Keep **classification fit** and **execution quality** separate. - Do not criticize a human-primary CLI for not being agent-primary unless the user explicitly wants that shift. 5. Produce a structured review. - Use the review structure in `references/output-templates.md`. - Use the full template when the user wants a formal review or when the category tension is material. - For quick requests, compress to: inferred intent, classification, evidence-backed category mistakes, in-category weaknesses, and highest-priority improvements. - Separate category mistakes from in-category execution weaknesses. ### Required review checks When reviewing, explicitly check these areas when relevant: - **Primary vs secondary surface clarity** - Is the CLI clear about what the main surface is? - Are secondary surfaces real contracts or just informal add-ons? - **Discoverability** - Does help output support the claimed user type? - Are examples, option descriptions, and command structure aligned with the CLI's center of gravity? - **Structured output contract** - Are JSON / JSONL / field-selection / exit-code surfaces explicit and stable? - Are unknown fields rejected or silently tolerated? - Is the machine surface strong enough for the claims made in docs? - **Risk model** - Are low-, medium-, and high-risk actions meaningfully separated? - Are confirm / dry-run / preview / audit guardrails aligned with the risk profile? - **State model** - Is statefulness handled correctly? - Are attach/detach/resume/session/history concepts used only when justified? - **v1 discipline** - Does the CLI keep a coherent v1 boundary? - Does it introduce premature abstraction or missing contracts? ### Review rules - Do not grade every CLI on an agent-first curve. - Do not require raw payloads, full schema introspection, or machine-first output unless the classification justifies them. - Treat modern CLIs as multi-surface systems: one primary role, one primary interaction form, optional secondary surfaces. - Prefer strong inference, then targeted confirmation. - When criticizing machine support, specify whether the problem is: - missing primary/secondary surface clarity, - weak machine contract, - or a true category mismatch. --- ## Handling hybrid CLIs Some CLIs genuinely straddle multiple roles at the subcommand level. Rules for hybrid CLIs: 1. Classify at the **product level** first — what is the CLI's center of gravity? 2. If subcommands clearly split into different roles, note the split explicitly. 3. Name the **primary role** (the one that defines the CLI's identity and design constraints). 4. Name **secondary roles** as secondary surfaces with their own local constraints. 5. Do not force a single role on a CLI whose subcommands genuinely serve different roles. Example: Docker - Product-level primary role: **Runtime** (its center of gravity is container execution). - `docker run`, `docker exec`, `docker attach` → Runtime interaction. - `docker image ls`, `docker volume inspect` → Capability-like resource surfaces (secondary). - `docker compose up` → Workflow/Orchestration (secondary). Guidance for evolving CLIs: - If a CLI is migrating from one type to another, state the current center of gravity and the intended direction. - Do not classify based on the future target alone; classify based on current evidence and note the trajectory. --- ## Common failure modes Watch for these mistakes: - Treating every CLI as a capability CLI. - Treating every CLI as a runtime CLI. - Treating TUI or REPL as a role instead of an interaction form. - Ignoring statefulness. - Ignoring risk profile. - Ignoring help/discoverability for human-primary CLIs. - Treating automation fitness as a top-level identity instead of a design consequence. - Forcing human-primary tools into agent-only patterns. - Calling a JSON surface “strong” without defining the contract. - Ignoring secondary surfaces in mixed-mode CLIs. - Jumping from classification directly to command trees without stating design stance. - Failing to mark v1 boundaries and non-goals. - Forcing a single role on a hybrid CLI whose subcommands genuinely serve different control surfaces. - Over-engineering statefulness for a CLI that only has durable config/lockfile side-effects but no true sessions. - Classifying a CLI by its future aspirations instead of its current evidence. ## Output bar Keep final outputs: - explicit about classification - explicit about classification reasoning when there is tension or ambiguity - explicit about evidence, confidence, and assumptions - explicit about design consequences - explicit about primary vs secondary surfaces - explicit about discoverability and machine contracts when relevant - explicit about risk ladders when mutations exist - scaled to the user's requested depth - concise but dense - diagnostic rather than generic Avoid vague advice such as "improve UX" or "make it more agent-friendly" unless tied to a specific classification and a concrete design consequence.

path: examples/anti-patterns.md
content: # Anti-Patterns

Three worked negative examples showing common classification and design mistakes when applying the CLI design framework. Each case shows a concrete scenario, what went wrong, why the framework flags it as an error, and what the correct approach looks like. Two additional shorter cases cover interaction-form and statefulness errors.

---

## 1. Agent-washing a human-primary CLI

### Scenario

A team maintains `store`, a human-primary capability CLI for managing cloud storage buckets. Typical usage looks like:

```
store bucket list
store object get abc-123
store object delete abc-123    # prompts "Are you sure?"
```

The team reads about "agent-first CLI design" and ships a redesign:

- Human-readable table output is removed; JSON becomes the only output format.
- `store object get <id>` is replaced with `store object get --json '{"id":"...","fields":"..."}'` as the sole input path.
- Most `--help` examples are stripped because "agents don't read help."
- Confirmation prompts on destructive operations are removed because "agents need non-interactive mode."

### What went wrong

Category mistake — applying agent-primary design patterns to a human-primary CLI.

The CLI's actual user base is humans typing commands in a terminal. The redesign optimized for a user type that barely exists here while actively degrading the experience for the real users. Removing human-readable defaults, help text, and safety prompts doesn't make the CLI "modern" — it makes it hostile to its primary audience.

### Why it's wrong

The framework classifies this CLI as **Human-Primary** by user type. Human-primary CLIs require:

- Human-readable output as the default surface (tables, colored text).
- Strong `--help` with examples and discoverability.
- Confirmation prompts for destructive operations as a safety layer.

None of these conflict with also supporting machines. The mistake is treating human and machine surfaces as mutually exclusive rather than layered.

### Correct approach

Keep human-readable table output as the default. **Add** `--json` as a secondary machine-readable surface. Keep `--help` rich with examples. Keep confirmation prompts for interactive use; add `--yes` / `--force` flags for automation paths. The principle: layer machine surfaces on top of human defaults, never replace them.

---

## 2. Treating a runtime CLI as a capability CLI

### Scenario

A team builds `neuron`, an AI agent runtime (similar in role to `claude` or `codex`). They design it as a clean resource-CRUD interface:

```
neuron session list
neuron session get <id>
neuron session delete <id>
neuron tool list
neuron tool install <name>
neuron model list
neuron model set <name>
```

The command surface looks tidy. But there is no way to actually run an agent session, no approval model for tool use, no sandbox governance, no attach/resume/fork for live sessions, no event streaming, and no execution lifecycle management.

### What went wrong

Role misclassification — the CLI's primary role is **Runtime** (execution governance), but it was designed as if it were a **Capability CLI** (resource CRUD).

The team focused on "what objects exist" (sessions, tools, models) and built CRUD around them. But the core of a runtime CLI is not object inventory — it is how execution proceeds, who approves what, what is sandboxed, and how sessions live, pause, resume, and die.

### Why it's wrong

The framework distinguishes Runtime CLIs from Capability CLIs precisely because their primary surface is different. A runtime CLI's primary commands are execution-oriented: start, approve, pause, resume, attach, fork. Resource listing is a secondary concern. By building only CRUD, the team shipped a CLI that can describe agent sessions but cannot govern them — which is the entire point of a runtime.

### Correct approach

Start with the execution model as the primary surface:

- `neuron run "task description"` — start a session.
- `neuron resume <session-id>` — continue a paused session.
- `neuron attach <session-id>` — connect to a live session's event stream.

Build approval and sandbox governance into the execution flow (approval prompts, `--sandbox` flags, permission policies). Then layer resource inspection (`neuron session list`, `neuron tool list`) as secondary capability surfaces on top. Execution first, inventory second.

---

## 3. "We have JSON output, so we're script-friendly"

### Scenario

A CLI adds `--json` to its `list` and `get` commands. The README proudly states: *"Script-friendly: supports JSON output for automation."* But in practice:

- Field names change between minor versions without notice or deprecation.
- Some commands return `{"data": [...]}` while others return bare arrays.
- Exit code is always `0`, even when 3 of 5 items in a batch operation failed.
- There is no `--fields` or field selection mechanism.
- There is no `describe` or schema command.
- Error messages in JSON mode are still unstructured text on `stderr`.

### What went wrong

Surface existence does not equal contract maturity. Having a `--json` flag is necessary but not sufficient for a real machine-readable secondary surface.

Scripts and agents that consume JSON output depend on structural stability: predictable field names, consistent envelope shapes, meaningful exit codes, and parseable error output. Without these, `--json` is a formatting convenience, not a contract. Every downstream consumer becomes fragile.

### Why it's wrong

The framework requires that a machine-readable surface be evaluated on contract strength, not mere presence. A strong machine contract includes:

- **Field stability**: named fields don't disappear or rename without a major version bump.
- **Consistent envelope**: every command uses the same top-level shape (e.g., always `{"data": ...}`).
- **Meaningful exit codes**: `0` = full success, `1` = partial failure, `2` = complete failure.
- **Field selection**: `--fields id,name,status` for bandwidth- and context-window-conscious consumers.
- **Schema support**: a `describe` or `--schema` surface so agents can introspect the contract.

The CLI in this scenario satisfies none of these. Claiming "script-friendly" based on `--json` alone is an incomplete contract.

### Correct approach

Define and document field stability guarantees (ideally tied to semver). Standardize the JSON envelope across all commands. Make exit codes meaningful and documented. Add `--fields` for selective output. Consider a `describe` or `--schema` surface for agent consumers. Ensure errors in JSON mode are also structured JSON. The flag is the easy part — the contract is the work.

---

## 4. Promoting TUI to a role

### Scenario

A team classifies their monitoring dashboard CLI as a "TUI tool" — the role is TUI, the interaction form is TUI, and the design is driven by "TUI best practices." They build rich widgets, keyboard shortcuts, and live-updating panels, but never clarify whether the CLI is primarily monitoring resources (Capability), managing a running system (Runtime), or governing a workspace (Environment/Workspace).

### What went wrong

TUI is an interaction form, not a role. Calling a CLI a "TUI tool" is like calling a web app a "browser app" — it describes the delivery channel, not what the tool controls. Without identifying the role, the team cannot decide what the command structure should look like, what objects need introspection, or what risk model applies.

### Why it's wrong

The framework explicitly separates interaction form from role. A TUI can serve any role: `lazygit` is a TUI over a Capability CLI (git resources), `htop` is a TUI over an Environment/Workspace CLI (system processes), and `codex` is a TUI over a Runtime CLI (agent execution). Promoting TUI to role makes these three tools look identical in the taxonomy, when they actually need fundamentally different command structures, state models, and risk profiles.

### Correct approach

Classify the role by what the CLI controls, not by how it renders. Then classify the interaction form as TUI. The role determines command structure and state model; the interaction form determines surface ergonomics and feedback style. Both matter, but they are orthogonal.

---

## 5. Over-engineering statefulness for a Config-Stateful CLI

### Scenario

A team builds a package manager CLI. Users run `pkg install <name>`, `pkg list`, `pkg update`. The CLI writes a lockfile and modifies a local dependency directory — classic Config-Stateful behavior. But the team, inspired by database CLIs, adds:

- `pkg session start` / `pkg session end` to "track installation transactions"
- `pkg history` showing a "session log" of past installations
- `pkg rollback --session <id>` to undo a "session"
- A session ID attached to every `pkg install` invocation

### What went wrong

The CLI invented session semantics where none are needed. A lockfile and dependency directory are durable side-effects (Config-Stateful), not sessions. Users don't think of `pkg install lodash` as happening "inside a session" — they think of it as a single action that changes the project state.

### Why it's wrong

The framework's Statefulness dimension distinguishes Config-Stateful from Sessionful precisely to prevent this. Config-Stateful means "durable side-effects but no session identity." The correct design primitives are `init` / `reset` / `status` / `diff` — operations that inspect or manage durable state without imposing session structure. Adding sessions to a Config-Stateful CLI creates cognitive overhead (users must understand session lifecycle), implementation complexity (session tracking, rollback logic), and API surface area (session CRUD) — all for a mental model that doesn't match how users actually think about package installation.

### Correct approach

Keep the CLI Config-Stateful. Use `pkg install`, `pkg list`, `pkg update`, `pkg remove` as stateless-feeling commands with durable effects. Add `pkg status` to show current state, `pkg diff` to show pending changes (if applicable), and `pkg reset` for clean-state recovery. If undo is needed, implement it as `pkg remove <name>` (reversing a specific action), not as session rollback.


path: examples/design-blueprint-example.md
content: # Design Blueprint Example — `axon`

> A local AI agent runtime that manages agent sessions, tool sandboxes, approval flows, and execution governance.

## 1. Purpose

Provide a local CLI that lets a human operator start, observe, steer, and govern AI agent sessions — including tool-use sandboxing, human-in-the-loop approval, and execution lifecycle — while exposing a structured secondary surface for headless batch execution and programmatic event consumption.

## 2. Classification

- **Primary role:** Runtime
- **Primary user type:** Human-Primary
- **Primary interaction form:** Interactive CLI
- **Statefulness:** Sessionful
- **Risk profile:** High Side-Effect
- **Secondary surfaces:** `axon exec --json` (batch execution), NDJSON event stream, scriptable session control
- **Confidence level:** High

## 2b. Classification reasoning

**Why Runtime, not Capability.**
`axon` manages agent *execution* — it starts sessions, brokers tool calls through a sandbox, mediates approval flows, and governs what a running agent is allowed to do. The core abstraction is a *live execution context*, not a set of CRUD-able resources. A Capability CLI controls objects that exist at rest (issues, images, DNS records); `axon` controls processes that exist *in flight*. The fact that sessions can be listed, inspected, or resumed does not make them "resources" in the Capability sense — `tmux` sessions and `docker` containers are also listable, but tmux and Docker are classified by what they *run*, not by what they *store*. If you designed `axon` as a Capability CLI, you would end up with `axon session create / get / update / delete` — a CRUD shell around an execution engine, which is a category mistake. The command structure should reflect lifecycle verbs (`start`, `attach`, `stop`, `approve`, `deny`) rather than resource-mutation verbs.

**Why Interactive CLI, not TUI.**
`axon`'s primary surface is a connected, prompt-driven terminal session with streaming output and inline approval prompts. That makes it an **Interactive CLI** in this blueprint: the operator is conversing with a live runtime inside a single terminal flow, not navigating a full-screen layout with panels, panes, or persistent dashboard chrome. A future version could add a true TUI as an alternate surface, but that is not the primary interaction form assumed here. The *role* still remains Runtime because the CLI's center of gravity is execution governance. Classify the role by *what is controlled*; classify the interaction form by *how the user drives it*.

**How classification drives every subsequent section.**
- *Runtime role* → command structure uses lifecycle/governance verbs, not CRUD verbs (§4). Introspection surfaces describe execution state, not object schemas (§7).
- *Human-Primary user type* → human-readable output is the default; structured output is a secondary surface, not the primary contract (§6). Help and examples must be strong (§7).
- *Interactive CLI interaction form* → primary surface is a connected interactive session; batch exec is a deliberate secondary mode with its own contract (§11).
- *Sessionful statefulness* → session identity, resume, and attach/detach are core design requirements, not bolted-on features (§8).
- *High Side-Effect risk* → a concrete risk ladder with per-level guardrails is mandatory (§9). Approval flows are a first-class primitive, not a future nice-to-have.

## 3. Primary design stance

Optimize for a human operator who starts an agent session, watches it run, intervenes when the agent requests approval, and steers or terminates execution when needed. The interactive session is the primary surface; the human is the governor, not a spectator.

`axon` is **not** trying to be a headless agent orchestrator, a machine-to-machine execution protocol, or a resource CRUD tool. Batch and programmatic surfaces exist to support CI, testing, and script-driven workflows — but they are secondary to the interactive governance experience.

## 4. Command structure

**Shape:** Lifecycle-and-governance verbs at the top level, not noun-first CRUD.

```
axon start [--model ...] [--tools ...] [--policy ...]   # start a new session
axon attach <session-id>                                  # reconnect to a running session
axon stop <session-id>                                    # terminate a session
axon approve <request-id>                                 # approve a pending tool call
axon deny <request-id> [--reason ...]                     # deny a pending tool call
axon status [<session-id>]                                # inspect session state
axon list                                                 # list sessions
axon logs <session-id>                                    # view execution transcript
axon exec [--json] <prompt>                               # headless batch execution (secondary)
axon policy <subcommand>                                  # manage governance policies
```

**Why this shape.** Runtime role drives lifecycle verbs. The operator's primary actions are *start, attach, steer, approve, stop* — these are execution verbs, not resource verbs. `approve` / `deny` are first-class top-level commands because Human-Primary + High Side-Effect means the approval flow is a core interaction, not an edge case buried in subcommand flags. `axon exec` is deliberately separate from `axon start` to make the boundary between interactive governance and headless batch execution explicit.

## 5. Input model

**Primary:** Interactive-first. During an active session, input is conversational — the operator sends messages, approves/denies requests, and issues steering commands through the session interface. Session startup uses flags (`--model`, `--tools`, `--policy`, `--sandbox`) for configuration.

**Secondary:** `axon exec` accepts flags + prompt for batch execution. `axon policy` subcommands use flags-first input for policy CRUD. No raw-payload-first path is needed in v1 — the input domain (model selection, tool lists, policy names, natural-language prompts) maps cleanly to flags and positional arguments.

**Where machine input belongs:** `axon exec --json` accepts a structured request on stdin for programmatic invocation. This is the *only* raw-payload entry point, and it is explicitly a secondary surface.

## 6. Output model

**Default (TTY):** Human-readable. Session output streams agent reasoning, tool calls, approval prompts, and results in a formatted interactive view. `axon list` and `axon status` produce human-readable tables/summaries.

**Structured secondary:** `axon exec --json` emits a JSON result object. `axon logs --json <session-id>` emits NDJSON transcript. `axon status --json` emits machine-readable session state. `axon list --json` emits a JSON array of session summaries.

**Contract level:** The `--json` surfaces are strong contracts — field names are stable across minor versions, and breaking changes require a major version bump. The interactive session view is a human-optimized presentation layer with no stability guarantee on layout or formatting.

## 7. Help / discoverability / introspection

**Help and examples (high priority — Human-Primary drives this):**
- Every command must have `--help` with at least one realistic example.
- `axon start --help` must show a complete start-to-finish example including model, tools, and policy flags.
- `axon approve --help` must explain what happens when an approval times out.

**Discoverability (high priority):**
- `axon` with no arguments shows a short command summary grouped by lifecycle phase (start → interact → govern → inspect).
- Unknown commands suggest the closest match.

**Introspection (execution-state-oriented, not object-schema-oriented):**
- `axon status <session-id>` shows: model, active tools, sandbox state, pending approvals, elapsed time, token usage.
- `axon policy show <policy-name>` shows the effective governance rules.
- No generic `describe` / `schema` / `fields` surface is needed — Runtime CLIs expose *execution state*, not *object schemas*. This is a direct consequence of the Runtime classification. A Capability CLI would need field-level introspection; `axon` needs state-level introspection.

## 8. State / session model

**Derived from classification:** Sessionful statefulness means session identity is a core primitive, not an add-on. This section exists *because* the classification says Sessionful — for a Stateless or Config-Stateful CLI, this section would say "not applicable" and move on.

**Session identity:** Every `axon start` creates a session with a unique ID (short hash, human-typeable). Sessions are the unit of execution, governance, and auditability.

**Resume / attach / detach:**
- `axon attach <session-id>` reconnects to a running session from any terminal.
- Closing the terminal detaches but does not stop the session (agent continues in background).
- `axon stop <session-id>` explicitly terminates.
- Detached sessions with pending approvals remain blocked until the operator re-attaches or the approval times out (configurable).

**History / transcript:**
- `axon logs <session-id>` replays the full execution transcript (agent messages, tool calls, approvals, results).
- Transcripts are stored locally and are the primary audit artifact.

**State inspection:**
- `axon status` (no args) lists all active/paused sessions.
- `axon status <session-id>` shows detailed session state.

## 9. Risk / safety model

**Derived from classification:** High Side-Effect means every mutation path needs explicit guardrails. The risk ladder below is not generic advice — it is driven by what `axon` actually controls (agent execution, tool calls, system access).

**Low-risk operations (no confirmation):**
- `axon list`, `axon status`, `axon logs` — read-only inspection.
- `axon attach` — connecting to an existing session does not change state.

**Medium-risk operations (confirmation or explicit flag):**
- `axon start` with tools that have filesystem/network access — display the tool manifest and sandbox policy at startup, require `--confirm` or interactive acknowledgment.
- `axon approve` for tool calls within the session's declared sandbox — approve proceeds, but the tool call's scope is logged.

**High-risk operations (strict guardrails):**
- `axon approve` for tool calls that exceed the session's sandbox policy (e.g., agent requests a tool not in the allowed set) — explicit warning, require `--force` or interactive confirmation with the specific risk explained.
- `axon stop --force` (kill without graceful shutdown) — requires `--force` flag; without it, `axon stop` attempts graceful termination.
- `axon exec` in batch mode with broad tool access — requires an explicit policy file; refuses to run with no governance constraints.

**Dry-run:** `axon exec --dry-run` shows the resolved execution plan (model, tools, sandbox, policy) without starting the agent.

**Audit:** Every session produces a transcript log. Every approval/denial is timestamped and attributed. `axon logs --json <session-id>` is the machine-readable audit surface.

**Sanitization:** Prompts passed via `axon exec` are logged verbatim but never interpreted as shell commands. Tool call arguments are sandboxed and validated against the declared tool schema before execution.

## 10. Hardening model

**Input validation:**
- Session IDs and request IDs are validated syntactically before any operation.
- Unknown flags are rejected, not silently ignored.
- `axon exec` with `--json` on stdin validates the request object against a known schema and rejects unknown fields.

**Field stability:** `--json` output field names are stable. New fields may be added; existing fields are not removed or renamed without a major version bump.

**Exit codes:**
- `0` = success.
- `1` = general error.
- `2` = invalid input / usage error.
- `3` = session not found.
- `4` = approval denied / policy violation.
- `5` = timeout (approval timeout, execution timeout).
- Distinct exit codes matter because `axon exec` in CI pipelines needs to distinguish "agent failed" from "policy blocked the run."

**Timeout / idempotency:**
- `axon stop` is idempotent — stopping an already-stopped session succeeds with a notice.
- `axon approve` / `axon deny` on an already-resolved request fails with a clear error and exit code, not a silent no-op.
- Approval requests have a configurable timeout; expired approvals auto-deny and log the timeout.

## 11. Secondary surface contract

**`axon exec --json` (batch execution surface):**
- *Who:* CI pipelines, test harnesses, scripts.
- *What:* Run a prompt headlessly with a declared policy, return a structured result.
- *Contract:* Strong. Input schema is documented; output schema has stable field names; exit codes are meaningful. This is the primary machine surface.
- *Boundary:* `exec` is fire-and-forget — it does not support mid-execution approval. If the policy requires human approval, `exec` either uses auto-approve rules from the policy file or fails. This constraint is deliberate: interactive governance belongs on the primary surface.

**NDJSON event stream (`axon attach --events <session-id>`) — planned for post-v1:**
- *Who:* Monitoring tools, dashboards, agent-orchestration scripts.
- *What:* Tap into a running session's event stream (tool calls, approvals, agent messages) as newline-delimited JSON.
- *Contract:* Strong for event types and field names; event ordering is best-effort. This is a secondary observation surface, not a control surface — you cannot send commands through it. Included here to define the contract target; actual implementation is deferred to post-v1 (see §12) because the event vocabulary needs to stabilize first.
- *Boundary:* Read-only. Steering and approval happen through the primary interactive surface or dedicated commands (`axon approve`), not through the event stream.

**Scriptable session control (`axon approve`, `axon deny`, `axon stop` from a second terminal):**
- *Who:* Operators managing multiple sessions, automation scripts that handle approval queues.
- *What:* Issue governance commands to a session without being attached to it.
- *Contract:* Convenience layer with stable command signatures but no versioned wire protocol. These are CLI commands, not an API.

## 12. v1 boundaries

**v1 includes:**
- `start`, `attach`, `stop`, `approve`, `deny`, `status`, `list`, `logs` — the core lifecycle and governance commands.
- One sandbox backend (local process isolation).
- One policy format (YAML file declaring allowed tools, approval rules, timeouts).
- `axon exec --json` for batch execution.
- `axon logs --json` for machine-readable transcript export.
- Local session storage (filesystem-based).

**v1 defers:**
- Remote session management (multi-machine, cloud-hosted agents).
- Plugin system for custom tool backends.
- Multi-agent orchestration (sessions containing multiple cooperating agents).
- Web dashboard or GUI.
- `axon attach --events` (NDJSON event stream) — useful but not needed before the core lifecycle is stable.
- Policy inheritance / composition (v1 uses flat policy files).

**What would be premature abstraction:**
- Building a generic "resource management" layer for sessions — sessions are execution contexts, not REST resources. CRUD semantics would fight the runtime model.
- Designing a plugin API before the core sandbox and approval interfaces are stable — plugin boundaries cannot be drawn until v1 usage reveals where extensibility is actually needed.
- Adding a policy DSL or policy engine — v1 should validate that the policy model is correct with simple YAML before investing in expressive power.
- Exposing the event stream before the event vocabulary stabilizes — shipping an unstable event contract creates backwards-compatibility debt.

## 13. Direction for implementation

**Optimize for:** Interactive session governance. The attach → observe → approve/deny → steer loop is the core experience. If this loop is fast, clear, and trustworthy, the CLI succeeds.

**Do not optimize for:** Headless orchestration, agent-to-agent communication, or API-first design. These may matter later, but optimizing for them now would pull design decisions away from the human governance experience.

**Acceptable patterns:**
- Session state stored as local files (JSON or SQLite) — simple, inspectable, no server dependency.
- Approval flow as a blocking prompt in the interactive session, with timeout-based auto-deny for detached sessions.
- `axon exec` as a thin wrapper that creates a session, runs to completion, and returns the result — no special "batch mode" engine.

**What would be a category mistake:**
- Designing `axon` as `axon session create / session get / session update / session delete` — this treats sessions as REST resources and buries the execution lifecycle under CRUD verbs. The Runtime classification specifically warns against this.
- Making `axon exec --json` the primary surface and treating the interactive mode as a convenience wrapper — this inverts the Human-Primary design target.
- Requiring a policy file for interactive use — the operator *is* the governance layer in interactive mode; forcing policy-file configuration for a human sitting at the terminal adds friction without safety benefit.
- Omitting the approval flow from v1 — High Side-Effect classification means governance is not a nice-to-have; it is the product.


path: examples/review-example.md
content: # Review Example — `depot`

> A DevOps deployment CLI with subcommands for deploying, rolling back, and promoting services across environments.

## 1. Inferred intent

`depot` appears designed to let DevOps engineers deploy, promote, and roll back services across multiple environments (staging, production) from the terminal. It organizes work around services and environments as durable objects, with deployment operations acting on those objects. Some commands suggest pipeline-style orchestration, but the actual command structure and data model are resource-oriented.

## 2. Classification

- **Primary role:** Capability
- **Primary user type:** Human-Primary
- **Primary interaction form:** Batch CLI
- **Statefulness:** Config-Stateful (deployment state persisted to disk, but no true session identity)
- **Risk profile:** Mixed — reads are safe, but `rollback` and `promote` carry high side-effect risk
- **Secondary surfaces:** Partial `--json` on some commands; `depot status` as a lightweight runtime-observation surface
- **Confidence level:** Medium
- **Hybrid notes:** `deploy`, `rollback`, and `promote` have workflow characteristics (multi-step, stage-dependent). `service list/get` and `env show` are pure Capability CRUD. `status` showing ongoing deployments has a thin runtime-observation quality. The center of gravity is Capability because the durable objects (services, environments, deployment records) are what the CLI primarily controls — workflow steps and runtime observation exist as operations on those objects, not as the core abstraction.
- **Evolution trajectory:** If `depot` adds pipeline definitions, step dependencies, or DAG execution, the center of gravity could shift toward Workflow/Orchestration. Current evidence does not support that classification yet.

### Why Capability, not Workflow

This is the central classification question for `depot`. The help text uses words like "pipeline" and "stages," and commands like `deploy` and `promote` look like workflow steps. However, the actual command structure tells a different story:

- **The nouns are durable resources.** `depot service list`, `depot service get <name>`, `depot env show <env>` — these are CRUD operations on objects that exist at rest. A Workflow CLI's core nouns would be tasks, stages, or pipelines, not services and environments.
- **The verbs operate on resources, not on execution flow.** `depot deploy --service web --env staging` means "act on this resource in this context." A workflow CLI would say `depot run pipeline deploy-web` or `depot trigger staging-pipeline` — the verb targets a *flow*, not an *object*.
- **There is no pipeline definition.** No `depot pipeline create`, no DAG specification, no step-dependency configuration. The "pipeline" language in help text is aspirational framing, not a design reality.
- **State is resource-shaped.** Deployment records are stored as durable artifacts (which service, which version, which environment, when). This is Config-Stateful resource tracking, not sessionful execution state.

A Workflow CLI's center of gravity is the *execution graph* — steps, dependencies, conditions, retries. `depot`'s center of gravity is the *resource graph* — services, environments, deployment records.

### Why not Runtime

`depot status` shows ongoing deployments, which gives it a thin runtime-observation quality. But `depot` does not manage a running process — it fires off deployments and tracks their state. There is no `attach`, no live streaming, no mid-execution steering. `status` is resource-state inspection (like `kubectl get pods`), not runtime-session observation (like `tmux attach`).

## 3. Evidence

**Help output observations:**

- `depot --help` groups commands as: Deploy (`deploy`, `rollback`, `promote`), Services (`service list`, `service get`), Environments (`env show`, `env list`), and Status (`status`). The grouping is resource-oriented: the deployment commands are organized *by what they do to resources*, not *by pipeline stage*.
- `depot deploy --help` says "Deploy a service to an environment" and takes `--service`, `--env`, `--version` flags. This is a resource-mutation signature, not a pipeline-invocation signature.
- `depot rollback --help` says "Roll back a service to the previous deployment." No `--dry-run`, no `--confirm`, no impact preview.
- `depot promote --help` says "Promote a deployment from staging to production." Resource flags, no safety guardrails beyond `--yes`.
**Command structure observations:**

- `depot service list` returns a table of services with columns: NAME, CURRENT_VERSION, LAST_DEPLOY, STATUS. Resource-listing pattern.
- `depot service get <name>` returns detailed service info including deployment history. Resource-detail pattern.
- `depot env show <env>` returns environment configuration. Resource-inspection pattern.
- `depot status` returns currently in-progress deployments. This is the only command with runtime-like behavior.
**Output behavior evidence:**

- `depot service list --json` works. Returns a JSON array of service objects.
- `depot service get <name> --json` works. Returns a JSON service object.
- `depot deploy --json` does **not** work — the flag is silently ignored, and human-readable progress output is emitted regardless.
- `depot rollback` has no `--json` flag at all.
- `depot status --json` works, but the output schema differs from `service list --json` in field naming conventions (`deployedAt` vs `last_deploy`).

**Code path observations:**

- The formatter module has separate table formatters per command with no shared output-contract layer.
- Deploy/rollback/promote call an HTTP API and poll for status; polling output is hardcoded human-readable text.
- No shared confirmation module — `--yes` is implemented ad hoc in `promote` and absent from `rollback`.

## 4. What fits the category well

- **Resource-oriented command structure is clear and learnable.** `depot service list`, `depot service get`, `depot env show` follow a `<noun> <verb>` pattern that a Capability CLI should use.
- **Service and environment as top-level nouns is correct.** The CLI's object model matches what operators actually manage — services are the unit of deployment, environments are the unit of targeting.
- **Human-readable table output for list commands is strong.** Column alignment, status coloring, and sort order are all sensible defaults for a Human-Primary Capability CLI.
- **Help text is well-structured for the basic commands.** `--help` on `service` and `env` subcommands gives clear descriptions with examples.

## 5. Classification mismatches

These are places where `depot` is designed as if it were a *different kind* of CLI than it actually is. These are not execution weaknesses — they are category-level design confusion.

**5a. Pipeline language applied to a resource CLI.**
The help text and README describe `depot` as a "deployment pipeline tool" and use terms like "stages" and "pipeline runs." But nothing in the command structure, state model, or data model implements pipelines. There are no stages, no step dependencies, no conditional execution, no retry policies. This language mismatch creates false expectations: a user reading "pipeline" will look for `depot pipeline run` or `depot stage list` and find nothing. If `depot` is a Capability CLI (which it is), its framing should use resource language: "manage deployments across services and environments," not "orchestrate deployment pipelines."

**5b. `deploy`/`rollback`/`promote` designed as workflow verbs, not resource mutations.**
These three commands are top-level verbs (`depot deploy`, `depot rollback`) rather than actions on a resource (`depot deployment create`, `depot deployment rollback <id>`). This makes them feel like pipeline stages rather than operations on objects. For a Capability CLI, the natural structure organizes mutations under the resource they affect. The current design creates a split personality: half the CLI follows `<noun> <verb>` (correct for Capability) and the other half follows bare verbs (natural for Workflow). This is a classification mismatch, not a style preference.

**5c. `status` designed as a runtime observation command, not a resource query.**
`depot status` shows "ongoing deployments" as a live-feeling status board. But `depot` is not a runtime CLI — it does not manage running processes. The deployment status is a *property of deployment records*, not a *runtime session*. The correct Capability design would be `depot deployment list --status=in-progress`, which treats deployment state as a queryable resource attribute rather than a special runtime view. The current design imports a runtime metaphor into a resource CLI.

## 6. In-category design weaknesses

These are places where `depot` is correctly designed as a Capability CLI but executed poorly *within* that category.

**6a. Inconsistent machine-readable surface.**
`--json` works on `service list`, `service get`, `env show`, and `status`, but not on `deploy`, `rollback`, or `promote`. For a Capability CLI with a machine secondary surface, the contract rule is simple: every command that produces output should support `--json`, and the format should be consistent. The mutation commands are exactly the ones CI pipelines most need structured output from (to capture deployment IDs, track success/failure, feed into downstream automation). Omitting `--json` from mutations while providing it for reads is the worst possible inconsistency — it makes the machine surface useless for the highest-value automation path.

**6b. No field-naming consistency across `--json` outputs.**
`service list --json` uses `last_deploy` (snake_case). `status --json` uses `deployedAt` (camelCase). For a Capability CLI claiming a machine secondary surface, field-name stability and consistency are the baseline contract. Mixed conventions signal that the JSON output was added per-command without a shared schema, which means automation consumers cannot trust field names across commands.

**6c. Destructive operations lack proper risk separation.**
`rollback` has no confirmation, no `--dry-run`, no impact preview. `promote` has only a basic `--yes` bypass with a one-line "are you sure?" prompt that does not describe what will happen. For a Mixed risk profile Capability CLI where `rollback` and `promote` affect production traffic, the risk ladder should be:

- Low-risk (no confirmation): `service list`, `service get`, `env show`, `status`
- Medium-risk (confirm + preview): `deploy` to staging — show what will change, require confirmation
- High-risk (confirm + preview + explicit flag): `promote` to production and `rollback` — show the blast radius (which services, which traffic), require `--confirm` or interactive review, support `--dry-run`

The current design treats all mutations as medium-risk (a basic yes/no prompt) when some are clearly high-risk.

**6d. Silent `--json` flag failure on `deploy`.**
When `depot deploy --service web --env staging --json` is run, the `--json` flag is silently ignored and human-readable output is emitted. Silent flag failure violates a basic hardening rule: unknown or unsupported flags should be rejected with an error. A CI script passing `--json` and receiving human-readable text will break on parse or silently misinterpret the output.

**6e. No deployment ID in mutation output.**
`depot deploy` emits progress text but does not return a deployment identifier for subsequent `status`, `rollback`, or audit queries. For a Capability CLI, mutations should return the identity of the created/modified resource. Without this, correlating a deployment action with its result requires timestamp matching — fragile and error-prone.

## 7. Highest-priority improvements

**1. Unify the command structure under resource-action pattern.**
*Why:* The Capability classification means the command structure should be organized around resources, not bare workflow verbs. Restructure `deploy`/`rollback`/`promote` as actions on a `deployment` resource: `depot deployment create`, `depot deployment rollback <id>`, `depot deployment promote <id>`. This eliminates the split personality (§5b), enables consistent `--json` on all `deployment` subcommands, and makes deployment records first-class queryable objects — which they already are in the data model.

**2. Standardize `--json` across all commands with a shared output contract.**
*Why:* For a Capability CLI with a machine secondary surface, every output-producing command must support `--json` with consistent field naming and stable schema. Implement a shared output layer that enforces snake_case field names, includes a `kind` field for type discrimination, and always returns the affected resource identity on mutations. Reject `--json` with a clear error on commands where it is not yet implemented, rather than silently ignoring it.

**3. Implement a risk ladder for destructive operations.**
*Why:* Mixed risk profile with production-affecting mutations means `rollback` and `promote` need explicit guardrails proportional to their blast radius. Add `--dry-run` (shows what will change without executing) and `--confirm` (interactive impact preview) to all mutation commands. Make `promote --env production` require explicit confirmation with a blast-radius summary by default. This is not generic "add safety" advice — it is a direct consequence of the risk profile classification: production-affecting mutations in a Capability CLI must be separable from staging-safe operations.

**4. Replace pipeline/stage language with resource language in help and docs.**
*Why:* The Capability classification means the mental model should be "manage resources," not "orchestrate pipelines." Rewrite help text and README to describe `depot` as managing services, environments, and deployments — not running pipelines. This eliminates the expectation gap (§5a) and aligns documentation with the actual command structure.

**5. Return resource identity from all mutations.**
*Why:* Capability CLIs must return the identity of created/modified resources so downstream operations can reference them. `depot deploy` should return a deployment ID; `depot rollback` should return the ID of the rollback deployment record; `depot promote` should return the new production deployment ID. This enables `depot deployment get <id>` for audit, `depot deployment rollback <id>` for targeted undo, and reliable CI pipeline chaining.

## 8. Questions to confirm with the user

- **Is pipeline orchestration a future direction?** If `depot` genuinely intends to add pipeline definitions, step dependencies, and DAG execution, the classification should be noted as "Capability evolving toward Workflow/Orchestration," and the command structure recommendations would change. The current review assumes pipeline language is aspirational framing, not a design commitment. If it is a commitment, the review needs revision.
- **Is `promote` always staging→production, or are arbitrary environment promotions planned?** If promotion targets are fixed, the risk model can be simpler (promote always means production, always high-risk). If arbitrary promotion paths are planned (staging→canary→production), the risk model needs to account for variable blast radius per target.
- **Should the machine surface (`--json`) become a strong contract or remain a convenience layer?** If CI/CD pipeline integration is a primary use case, the JSON surface should be versioned, field-stable, and documented as a contract. If it is purely for ad-hoc scripting, a lighter approach is acceptable. The improvements above assume a strong contract is intended — if not, items 2 and 5 can be deprioritized.


path: manifest.yaml
content: slug: cli-design-framework
name: CLI Design Framework
tagline: Classify first. Design second.
version: 1.0.2
summary: Classification-first framework for designing and reviewing CLIs.
description: Use when designing a new CLI, reviewing an existing CLI, or resolving uncertainty about a CLI's role, user type, interaction form, statefulness, risk profile, or human-vs-machine surfaces.
license: MIT-0
tags:
  - latest
  - cli
  - design
  - review
  - framework
entrypoint: SKILL.md
readme: ../../README.md
repository:
  type: git
  path: ../..
compatibility:
  agents:
    - claude-code
    - codex
    - openclaw
  distribution:
    - skills-cli
    - clawhub
contents:
  references:
    - references/taxonomy.md
    - references/output-templates.md
    - references/classification-examples.md
  examples:
    - examples/design-blueprint-example.md
    - examples/review-example.md
    - examples/anti-patterns.md


path: references/classification-examples.md
content: # Classification Examples

Use these examples to stabilize classification decisions. Treat them as representative anchors, not rigid templates.

## 1. Capability — `gh`

- **Primary role:** Capability
- **Primary user type:** Human-Primary
- **Primary interaction form:** Batch CLI
- **Statefulness:** Config-Stateful (auth tokens, aliases, repo-level defaults)
- **Risk profile:** Mixed
- **Secondary surfaces:** `--json`, `--jq`, `--template`

Why it fits:
- Primarily controls GitHub resources and collaboration objects.
- Human-readable output is the default.
- Machine-readable output exists as a strong secondary surface (`--json`, `--jq`, `--template`), making it close to Balanced — but the default output, help text, and discoverability all optimize for human operators, keeping the center of gravity on Human-Primary.
- It is not a runtime CLI and not a workspace manager.

## 2. Runtime — `codex`

- **Primary role:** Runtime
- **Primary user type:** Human-Primary
- **Primary interaction form:** TUI
- **Statefulness:** Sessionful
- **Risk profile:** High Side-Effect (agent execution with code, filesystem, and network mutation capabilities)
- **Secondary surfaces:** `exec --json`, batch execution, machine event streams

Why it fits:
- Primarily controls agent execution, sessions, sandboxing, approvals, and runtime behavior.
- The main product surface is an interactive TUI; batch execution and machine event streams are secondary surfaces.
- Read-only inspection exists (session list, status) but the dominant activity is execution governance with high mutation potential.

## 3. Environment / Workspace — `tmux`

- **Primary role:** Environment / Workspace
- **Primary user type:** Human-Primary
- **Primary interaction form:** TUI
- **Statefulness:** Sessionful, Long-running, Attach/Detach-capable
- **Risk profile:** Mixed
- **Secondary surfaces:** Batch CLI command surface for scripting (`tmux new-session`, `tmux send-keys`, etc.)

Why it fits:
- Primarily manages terminal workspace state.
- The primary experience is the full-screen workspace inside a tmux session; the `tmux` CLI command surface is a secondary control interface used for setup, automation, and scripting.
- Session identity and attach/detach are core.
- It is not primarily about business resources or agent execution.

## 4. Workflow / Orchestration — `make`

- **Primary role:** Workflow / Orchestration
- **Primary user type:** Human-Primary
- **Primary interaction form:** Batch CLI
- **Statefulness:** Stateless
- **Risk profile:** Mixed (varies by target; build targets are low-risk, deployment targets can be high-risk)
- **Secondary surfaces:** CI and automation invocation

Why it fits:
- Primarily orchestrates multi-step tasks and dependencies.
- The core abstraction is targets and execution flow, not persistent resources.

## 5. Package / Build / Toolchain — `uv`

- **Primary role:** Package / Build / Toolchain
- **Primary user type:** Human-Primary
- **Primary interaction form:** Batch CLI
- **Statefulness:** Config-Stateful (lockfiles, virtualenv, toolchain installations)
- **Risk profile:** Mixed
- **Secondary surfaces:** CI automation and reproducible toolchain flows

Why it fits:
- Primarily manages dependency, environment, and toolchain lifecycle.
- It is neither a generic workflow CLI nor a runtime CLI.

## 6. Meta / Control-Plane — `git config`

- **Primary role:** Meta / Control-Plane
- **Primary user type:** Human-Primary
- **Primary interaction form:** Batch CLI
- **Statefulness:** Config-Stateful (durable configuration effects that change downstream system behavior)
- **Risk profile:** Mixed
- **Secondary surfaces:** Scripted configuration management

Why it fits:
- Primarily controls configuration that changes how another system behaves.
- The controlled object is not a resource or workflow target but an effective configuration layer.

## 7. Balanced — `kubectl`

- **Primary role:** Capability (+ Meta / Control-Plane secondary)
- **Primary user type:** Balanced
- **Primary interaction form:** Batch CLI
- **Statefulness:** Config-Stateful (kubeconfig context, namespace state)
- **Risk profile:** Mixed (reads like `get`/`describe`/`logs` are safe; mutations like `delete`/`apply`/`scale` affect live cluster state)
- **Secondary surfaces:** `-o json`, `-o jsonpath`, `--dry-run=server`, extensive label/field selectors

Why it fits:
- Used equally heavily by human operators (interactive debugging, ad-hoc inspection) and by CI/CD pipelines, GitOps controllers, and automation scripts.
- Human-readable table output is the default, but structured output is not an afterthought — it is a production-critical surface.
- Neither side dominates: removing the human experience would break operator workflows; removing the machine surface would break the entire ecosystem.

## 8. Agent-Primary — `gws` (Google Workspace CLI)

- **Primary role:** Capability
- **Primary user type:** Agent-Primary
- **Primary interaction form:** Batch CLI
- **Statefulness:** Stateless
- **Risk profile:** High Side-Effect (wraps mutation-capable Workspace APIs; agent-primary means most invocation paths are mutations)
- **Secondary surfaces:** Schema introspection (`gws schema`), MCP JSON-RPC surface, Gemini Extension surface, SKILL.md agent knowledge packaging

Why it fits:
- Designed from day one for AI agents as the primary consumer.
- Input model is raw-payload-first (`--json`, `--params`) rather than flags-first.
- Runtime schema introspection replaces static documentation as the primary discoverability surface.
- Context window discipline (field masks, NDJSON pagination) is a first-class design concern.
- Input hardening is designed against agent-specific failure modes (hallucination, path traversal, double-encoding), not just human typos.
- Human debugging use exists but is secondary.

Agent-Primary design patterns visible in `gws` (use as reference when designing Agent-Primary CLIs): raw-payload-first input model in §5; JSON-default output with human-readable as convenience layer in §6; schema introspection replacing help as primary discoverability in §7; `--fields` for context-window discipline in §6; agent-specific input hardening (unknown field rejection, double-encoding detection) in §10.

Input sketch:
- Primary machine path is raw-payload-first: `gws users create --json @payload.json` or `gws groups patch --params @patch.json`.
- Flags remain available for lightweight debugging and human inspection, but they are not the primary entry path.
- Unknown fields, wrong enum values, and double-encoded JSON are rejected loudly rather than coerced.

Output sketch:
- Default output is JSON with stable field names and a documented contract level.
- Human-readable output exists as a convenience layer for debugging, not as the canonical surface.
- `--fields` and field masks are first-class so agents can limit payload size and context-window pressure.

Discoverability sketch:
- Runtime schema introspection (`gws schema`, `gws users describe`) is the primary discovery path.
- Help text points to schema commands rather than trying to inline every field in prose.
- Examples emphasize minimal valid payloads, field selection, and contract-safe mutation patterns.

## 9. Agent-Only — MCP server binaries / internal execution engines

- **Primary role:** varies (Capability, Runtime, or Meta depending on the tool)
- **Primary user type:** Agent-Only
- **Primary interaction form:** Machine Protocol / Event Stream Surface
- **Statefulness:** varies
- **Risk profile:** varies
- **Secondary surfaces:** minimal or none; human surfaces limited to version/health checks

Why this category exists:
- Agent-Only CLIs are rarely standalone consumer products. They more commonly exist as execution engines behind higher-level tools (e.g., `runc` behind `docker`, MCP server binaries behind agent frameworks).
- The defining characteristic: there is no meaningful human-interactive workflow. Human invocation is limited to debugging, health checks, or version inspection.
- Design consequences: human discoverability is low-priority; machine contract stability, schema rigor, and input hardening are the dominant concerns.

Note: If you find yourself classifying a user-facing product as Agent-Only, re-examine whether it is truly Agent-Only or Agent-Primary with a thin human debugging surface.

## Notes

- A product may expose multiple roles through different surfaces or subcommands.
- Classify the **primary** role first.
- Add secondary surfaces afterward.
- Do not promote TUI or REPL to role type; treat them as interaction forms.

## Coverage notes

Not every taxonomy value requires a dedicated anchor example. The following values are intentionally left without a standalone example because they are either self-explanatory or rare enough that an example would not improve calibration:

- **Pure Human** (User Type): Rare in modern CLIs. Most tools have at least some script/automation use. Examples include pure display utilities (`cal`, `banner`). If the CLI has no plausible machine consumer, classify as Pure Human and design entirely for discoverability and ergonomics.
- **REPL** (Interaction Form): Well-understood pattern (Python REPL, `sqlite3`, `node`). Classify the role by what the REPL controls, not by the fact that it is a REPL.
- **Read-heavy** (Risk Profile): CLIs that primarily query/inspect without mutation (e.g., `jq`, monitoring CLIs, network diagnostics). Low guardrail intensity for individual operations, but read-only does not mean risk-free — resource-intensive reads (network sweeps, large-scale queries, CIDR scans) require conservative concurrency defaults and scope warnings to prevent accidental overload. Focus on output quality, machine-readable contracts, and exit codes as the primary machine signal.
- **Irreversible / External-Action Heavy** (Risk Profile): CLIs that trigger actions that cannot be undone (revoking certificates, rotating secrets, sending emails, issuing payments, publishing packages). Design patterns for this risk level:
  - Multi-step confirmation on the most destructive operations (type the resource name, not just `y/N`); no `--yes` bypass for truly irreversible actions.
  - Mandatory `--reason` flag on irreversible mutations for audit attribution.
  - Audit-write-before-execute: write the audit event first; if it fails, abort the operation.
  - Automatic impact preview before confirmation (blast radius, affected consumers, active usage stats).
  - Explicit scope flags on all mutations (e.g., `--env prod`); never infer destructive scope from a config default.
  - `--dry-run` that validates against the backend in read mode, producing a realistic preview.


path: references/output-templates.md
content: # Output Templates

Use these templates as the default output shape.

Use the full template when the user asks for a blueprint/review explicitly, or when ambiguity, risk, or hybrid classification makes the extra structure valuable.

For quick asks, compress to:
- purpose or inferred intent
- classification
- short classification reasoning
- top design consequences or highest-priority improvements
- only the unresolved questions that could materially change the answer

## Design Blueprint Template

### 1. Purpose
One-sentence statement of what the CLI is for.

### 2. Classification
- Primary role:
- Primary user type:
- Primary interaction form:
- Statefulness:
- Risk profile:
- Secondary surfaces:
- Confidence level:
- Hybrid notes: (if subcommands or surfaces span multiple roles, note the split here; omit if not applicable)
- Evolution trajectory: (if the CLI is evolving toward a different type, note the direction; omit if not applicable)

### 2b. Classification reasoning
State why this classification was chosen. Specifically address:
- Why this role and not a plausible alternative.
- If there is classification tension, state it and explain how it was resolved.
- If interaction form could be confused with role, clarify the distinction.

### 3. Primary design stance
State the central optimization target in one paragraph.
Also state what the CLI is **not** trying to be.

### 4. Command structure
State the recommended command shape and why.
Do not list commands without explaining how the classification drives the shape.

### 5. Input model
State whether the CLI should be:
- flags-first
- raw-payload-first
- dual-track
- interactive-first

Explain the reason.
If there is a machine path, state where it belongs and where it does not.

### 6. Output model
State the recommended output defaults.
State the primary output surface.
State the secondary output surfaces.
If structured output exists, state the expected contract level.
Per-surface contract details (who, what, strong-vs-convenience) belong in §11, not here.

### 7. Help / discoverability / introspection
State the expected level of:
- help/examples
- discoverability
- describe/explain
- schema / fields support

### 8. State / session model
State whether the CLI needs:
- session identity
- resume/fork
- attach/detach
- history/transcript
- state inspection

If the CLI is mostly stateless, say so explicitly and avoid inventing session semantics.

### 9. Risk / safety model
State the expected guardrails:
- low-risk operations:
- medium-risk operations:
- high-risk operations:
- confirm:
- dry-run:
- impact preview:
- audit:
- sanitization:

### 10. Hardening model
State the expected validation and defensive design level.
If machine-readable surfaces exist, mention:
- field stability
- selector ambiguity rules
- exit-code expectations
- timeout / retry / idempotency expectations where relevant

### 11. Secondary surface contract
§6 establishes what surfaces exist and their defaults. This section specifies the contract for each.
Describe secondary human or machine surfaces explicitly.
For each important secondary surface, state:
- who it is for
- what it is for
- whether it is a strong contract or a convenience layer

### 12. v1 boundaries
State explicitly:
- what v1 should include
- what v1 should defer
- what would be premature abstraction

### 13. Direction for implementation
State:
- what to optimize for
- what not to optimize for
- acceptable patterns
- what would be a category mistake

---

## Review Template

### 1. Inferred intent
State what the CLI appears designed to do.

### 2. Classification
- Primary role:
- Primary user type:
- Primary interaction form:
- Statefulness:
- Risk profile:
- Secondary surfaces:
- Confidence level:
- Hybrid notes: (if subcommands span multiple roles, note the split here; omit if not applicable)
- Evolution trajectory: (if the CLI is evolving toward a different type, note the direction; omit if not applicable)

### 2b. Classification reasoning
If the classification involved tension or ambiguity, explain the resolution:
- Why this primary role and not a plausible alternative.
- If the CLI straddles two roles, explain where the center of gravity lies and why.
- If interaction form could be confused with role, clarify the distinction.
This section may be omitted when the classification is straightforward and high-confidence.

### 3. Evidence
List the evidence used:
- help output
- command structure
- code paths
- output contract
- docs/tests
- runtime behavior

### 4. What fits the category well
List strengths relative to the inferred category.

### 5. Classification mismatches
List places where the CLI appears designed like the wrong kind of CLI.
Keep true category mistakes separate from ordinary implementation weakness.

### 6. In-category design weaknesses
List places where the CLI is the right type but executed weakly.
When relevant, explicitly cover:
- discoverability/help
- secondary surface clarity
- structured output contract
- risk separation
- state handling
- v1 boundary discipline

### 7. Highest-priority improvements
List the top improvements in ranked order.
Prefer contract-level improvements over generic polish.

### 8. Questions to confirm with the user
Ask only the unresolved questions that could materially change the review.


path: references/taxonomy.md
content: # Taxonomy

This taxonomy describes a CLI along five primary dimensions plus secondary surfaces.

## 1. User Type

Answer: who is the stable primary user?

- **Pure Human** — effectively human-only
- **Human-Primary** — mainly for humans, with secondary script/agent support
- **Balanced** — humans and agents are both first-class users
- **Agent-Primary** — mainly for agents/automation, with some human debugging/inspection use
- **Agent-Only** — fundamentally program/agent facing

Use **Balanced** only when removing either the human or machine surface would materially harm a core workflow. If automation exists but is still secondary to an operator-centric experience, classify as **Human-Primary**.

## 2. Role / Control-Surface Type

Answer: what does the CLI primarily control?

- **Capability** — resources, objects, actions, CRUD/query surfaces
- **Runtime** — agent/model/session/tool/sandbox/approval execution surfaces
- **Environment / Workspace** — workspaces, panes, sessions, layouts, shells, attach/detach
- **Workflow / Orchestration** — multi-step tasks, pipelines, goals, dependency chains
- **Package / Build / Toolchain** — dependencies, build, run, publish, environment/toolchain lifecycle
- **Meta / Control-Plane** — configuration, profiles, feature flags, policy, plugin/settings/control surfaces

When distinguishing **Meta / Control-Plane** from **Capability**: Meta CLIs primarily configure policy or settings that govern another system's behavior (rate limits, routing rules, feature flags, config layers). Capability CLIs primarily manage resources that exist at rest (issues, records, certificates, endpoints). If a CLI manages both resources and policy, classify by center of gravity — if the primary user action is "configure how the system behaves," lean Meta; if the primary user action is "manage discrete objects," lean Capability. Use hybrid notes to acknowledge the secondary role.

## 3. Interaction Form

Answer: how is it primarily used?

- **Batch CLI**
- **Interactive CLI** — prompt-driven conversational or wizard-style interaction within a single invocation; differs from REPL (no persistent eval loop) and TUI (no full-screen layout)
- **REPL**
- **TUI**
- **Machine Protocol / Event Stream Surface**

Interaction form describes the primary interaction pattern, not the data entry method. **Input model** (flags-first, raw-payload-first, dual-track, interactive-first) is a separate design property driven primarily by user type — it belongs in the blueprint's §5, not in this classification field. Do not combine interaction form and input model in the classification — e.g., write `Batch CLI`, not `Batch CLI with raw-payload-first input model`.

## 4. Statefulness

Answer: how much durable or ongoing state shapes use?

- **Stateless** — no durable state across invocations
- **Config-Stateful** — no sessions, but invocations produce durable side-effects (config files, lockfiles, environment changes, caches)
- **Sessionful** — explicit session identity across invocations
- **Long-running** — persistent process with ongoing state
- **Attach/Detach-capable** — sessions that survive disconnection and can be resumed

Remote resources having durable state does not, by itself, make the CLI Config-Stateful. Use **Config-Stateful** when durable local or user-scoped config, caches, lockfiles, or contexts materially shape invocation behavior. A pure remote CRUD CLI can still be **Stateless**.

## 5. Risk Profile

Answer: what is the dominant side-effect profile?

- **Read-heavy**
- **Mixed**
- **High Side-Effect**
- **Irreversible / External-Action Heavy**

## 6. Secondary Surfaces

Modern CLIs often have a primary identity plus secondary surfaces.

Examples:
- human-primary capability CLI + JSON secondary surface
- runtime CLI with TUI primary surface + machine event-stream secondary surface
- workspace CLI with interactive primary surface + scriptable control secondary surface

Always classify the primary role and primary interaction form first. Add secondary surfaces only afterward.

## Decision order

Use this sequence:
1. State the CLI purpose in one sentence.
2. Classify the primary role.
3. Classify the primary user type.
4. Classify the primary interaction form.
5. Classify statefulness.
6. Classify risk profile.
7. Note secondary surfaces.
8. Derive design consequences.

## Design consequence map

### Role type primarily drives
- command structure
- object model vs execution model vs workspace model
- expected introspection type
- what counts as a category mistake

Role-specific defaults:
- **Capability** → noun/verb or resource/action surfaces; resource-state introspection
- **Runtime** → lifecycle/governance verbs; execution-state introspection
- **Environment / Workspace** → workspace/session verbs; attach/detach and layout/state inspection
- **Workflow / Orchestration** → task/pipeline verbs; dependency-graph and run-state introspection
- **Package / Build / Toolchain** → lifecycle-phase verbs; dependency, environment, cache, and artifact introspection
- **Meta / Control-Plane** → config/policy/profile verbs; settings and effective-policy introspection

### User type primarily drives
- default output surface: Human-Primary/Balanced → human-readable default, `--json` secondary; Agent-Primary → JSON default, human-readable secondary (surface inversion)
- input model: Human-Primary → flags-first; Agent-Primary → raw-payload-first with schema introspection; Balanced → dual-track
- discoverability: Human-Primary/Balanced → help/examples/error suggestions; Agent-Primary → runtime schema introspection, `--fields` selection, context-window discipline
- hardening focus: Human-Primary → typo correction, readable errors; Agent-Primary → unknown field rejection, type validation, double-encoded JSON detection

### Interaction form primarily drives
- surface ergonomics
- progress/feedback style
- prompting/confirmation style
- event stream or view-layer needs

### Statefulness primarily drives
- need for session identity
- need for resume/fork/attach/detach
- need for history/transcript/state inspection
- for Config-Stateful CLIs: need for init/reset/status/diff of durable effects, without inventing session semantics

### Risk profile primarily drives
- dry-run needs
- confirmation and impact preview needs
- audit and sanitization needs
- hardening and guardrail intensity
- for Irreversible / External-Action Heavy: multi-step confirmation (not just `--yes`), mandatory attribution (`--reason`), audit-write-before-execute with abort-on-failure, automatic impact preview showing blast radius, explicit scope flags on all mutations (never infer destructive scope from defaults)
- for Read-heavy: conservative defaults for resource-intensive operations (concurrency limits, scope warnings) to prevent accidental overload of target systems

## Classification precision

Each dimension uses discrete representative labels, not continuous scales. When a CLI does not fall cleanly into one value:

1. **Pick the dominant value** — the one that best describes the CLI's center of gravity for that dimension.
2. **Add a parenthetical qualifier** if needed — e.g., `High Side-Effect (reads are safe but agent execution carries high mutation risk)`.
3. **Do not use slashes between two values** — `Mixed / High Side-Effect` is ambiguous. Pick one: `High Side-Effect` or `Mixed`, then qualify.
4. **Handle per-operation variation in the design/review body, not in the classification label.** The risk ladder (§9 in blueprints) is where per-operation risk variation is described in detail. The classification label captures the dominant profile.

The same principle applies to all dimensions. Statefulness values are roughly cumulative (a Long-running CLI is also Sessionful), so listing multiple values with commas is acceptable when the CLI genuinely exhibits all of them (e.g., `tmux`: Sessionful, Long-running, Attach/Detach-capable).


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)