| name | spacecraft-agentic-cli |
|---|---|
| description | The agent-facing UX layer for Spacecraft Software CLIs — loads alongside spacecraft-cli-standard. cli-standard defines structure; this skill defines how the CLI must feel to an AI agent. ALWAYS use when scaffolding or auditing a Spacecraft Software CLI, writing AGENTS.md or CLAUDE.md, designing tips-thinking error hints, implementing agent env-var detection (AI_AGENT, AGENT, CI, CLAUDECODE, CURSOR_AGENT, GEMINI_CLI), shaping schema output for LLM function-calling (Anthropic, OpenAI, Gemini, MCP), defending against prompt injection / path traversal / hallucinated args, designing an MCP surface with lazy schema loading, or optimizing output for agent token budgets. Triggers: "scaffold a CLI", "audit this CLI", "agent-friendly", "agent-native", AGENTS.md, CLAUDE.md, MCP server, Claude Code, Codex CLI, Cursor, function calling, tips-thinking. Applies to every Spacecraft Software project with a CLI (Ferrocast, Caliper, Craton, Ironway, Zamak, Bravais, Mawaqit, Flux, future). |
| license | GPL-3.0-or-later |
| maintainer | Mohamed Hammad <Mohamed.Hammad@SpacecraftSoftware.org> |
| website | https://Construct.SpacecraftSoftware.org/ |
Version: 1.0.0 | Spec Date: 2026-04-10 | Author: Mohamed Hammad Maintainer: Mohamed Hammad | Contact: Mohamed.Hammad@SpacecraftSoftware.org Copyright: (C) 2026 Mohamed Hammad & Spacecraft Software | License: GPL-3.0-or-later Website: https://Construct.SpacecraftSoftware.org/ | Source Spec: Spacecraft Software Dual-Mode Self-Documenting CLI Standard (v1.0.0)
This skill is the agent-facing UX specialist for Spacecraft Software CLIs. The
companion skill spacecraft-cli-standard already encodes the structural
CLI Standard rules (output cascade, exit codes, JSON envelope, schema sub-command,
TUI graceful degradation, shell compat). This skill goes deeper on the
disciplines that determine whether an AI agent can actually use the CLI
well in practice:
- AGENTS.md / CLAUDE.md / SKILL.md as first-class repository artifacts
- Tips-thinking error hints that prevent agent hallucination loops
- Agent environment-variable detection cascades (concrete, behavioral)
<tool> schemaoutput that drops directly into LLM function-calling APIs- MCP lazy-loading discipline so tool definitions don't eat the context window
- Token-economy hygiene (
--fields,jsonl, payload minimization) - The agent-invoked threat model (prompt injection, hallucinated args)
If the CLI Standard structural rules conflict with anything in this skill, the CLI Standard
wins and spacecraft-cli-standard is authoritative. This skill never
weakens the structural Standard; it only adds depth to the agent-facing
surfaces.
Every Spacecraft Software CLI has two co-equal readers, and every design decision must satisfy both:
| Reader | Optimizes for | Reads via |
|---|---|---|
| Human in a terminal | Discoverability, forgiveness, visual scanning | TTY with color, tables, TUI |
| AI agent paying for tokens | Predictability, schema stability, token frugality | Pipes, JSON, schema introspection, MCP |
The two readers are orthogonal, not opposite. The same command must serve both — but the human-mode and agent-mode renderings are independently tuned. When they trade off, the agent-mode rendering optimizes for the agent's constraints (tokens, parseability, stability), and the human-mode rendering optimizes for the human's constraints (visual clarity, discoverability). Never sacrifice one for the other; render twice.
The Mei Park framing applies: human DX optimizes for discoverability and
forgiveness; agent DX optimizes for predictability and defense-in-depth.
Hold both lenses simultaneously. When in doubt, ask: "Would an agent
hallucinate here? Would gh ship this?"
Context files are not documentation — they are runtime configuration for agents. Every Spacecraft Software CLI repository ships these four files at the repository root, on day one, before business logic:
| File | Primary consumer | Contents |
|---|---|---|
AGENTS.md |
Generic agents (Codex CLI, Cursor, Aider, OpenCode) | Coding conventions, test/build commands, forbidden patterns, repository invariants |
CLAUDE.md |
Claude Code agent | Same as AGENTS.md, plus Claude Code–specific context (skills referenced, MCP servers expected, tool preferences) |
SKILL.md |
Spacecraft Software Skills + CLI-Anything + gws |
YAML frontmatter (name, description, license) + capability surface for the CLI itself |
CONTRIBUTING.md |
Human contributors | Onboarding, dev environment setup, PR conventions |
Read references/agents-md-authoring.md before writing any of these
files. It contains canonical templates, the difference between AGENTS.md
and CLAUDE.md content, and anti-patterns (e.g., dumping the CLI Standard verbatim
into AGENTS.md is wrong — agents already have the cli-standard skill;
AGENTS.md is for project-specific invariants).
Drop-in templates live in assets/agents-md.template.md and
assets/claude-md.template.md. Never copy them blindly — each file must be
specialized for the project.
No-clobber: read before you write. Scaffolding these files is the one
durable change this skill triggers on the user's own machine, and a repo often
already has an AGENTS.md or CLAUDE.md with real project context. Read any
existing context file first. If it exists, propose a merge or a diff — never
overwrite it wholesale. Treat a scaffold as a proposal, not a force-write; the
consent-before-durable principle from spacecraft-missing-pkg applies here too.
See references/local-host-authoring.md.
When a CLI emits a narrative error message ("invalid argument"), an AI agent has nowhere to go but hallucinatory exploration: it guesses flag names, retries with permuted arguments, and burns tokens until it either succeeds by accident or exhausts its retry budget. Tips-thinking inverts this: every error carries the exact next command the agent should run.
The structured error in machine mode (defined by spacecraft-cli-standard)
already mandates a hint field. This skill specifies how to author it:
{
"error": {
"code": "NOT_FOUND",
"exit_code": 3,
"message": "Repository 'foo/bar' does not exist",
"hint": "Run 'mytool repo list --json' to see available repositories",
...
}
}A good hint is a runnable command, not a sentence about the command.
"Use the list flag" is bad. mytool repo list --json | jq '.data[].name'
is good. The agent can directly execute the hint without further
inference.
Read references/tips-thinking.md for the full pattern catalog,
including:
- Hint formulas for each canonical
error.codevalue - Anti-patterns (vague hints, hints that lie, hints requiring inference)
- Cascading hints (when the hint itself might fail → what to point at next)
Canonical hint strings for every standard error code live in
assets/error-hint-catalog.json — use them as starting points.
spacecraft-cli-standard §5 specifies which env vars to detect. This
skill specifies what each one should change in behavior. The cascade
checks specific variables in priority order and adjusts multiple aspects
simultaneously:
| Variable | Output format | Color | TUI | Interactivity | Verbosity |
|---|---|---|---|---|---|
AI_AGENT set |
json | off | suppressed | non-interactive (--yes implicit) | minimal — failures only |
AGENT set |
json | off | suppressed | non-interactive | minimal |
CI truthy |
json | off | suppressed | non-interactive | normal |
CLAUDECODE set |
(informational) | (per other rules) | (per other rules) | (per other rules) | (per other rules) |
CURSOR_AGENT set |
(informational) | (per other rules) | (per other rules) | (per other rules) | (per other rules) |
GEMINI_CLI set |
(informational) | (per other rules) | (per other rules) | (per other rules) | (per other rules) |
TERM=dumb |
(per other rules) | off | suppressed | (per other rules) | (per other rules) |
Detection is presence-based. "Set" means set to any non-empty value —
not =1. Real harnesses export descriptive strings (a live Claude Code
session sets AI_AGENT=claude-code_2-1-218_agent), so a detector that matches
AI_AGENT == "1" fails to recognise the agent it runs under. CI is the lone
value-carrying exception (truthy = set and not false/0). Full predicates
and the grounding probe: references/agent-env-detection.md and
references/local-host-authoring.md.
CLAUDECODE, CURSOR_AGENT, and GEMINI_CLI are informational only.
They MUST NOT override the output format on their own — AI_AGENT /
AGENT / CI handle that. They MAY appear in metadata.invoking_agent
in the JSON envelope for telemetry, never as behavioral switches.
TERM=dumb deserves special care: a dumb terminal is not necessarily an
agent, but it is incompatible with TUI and ANSI escapes. Suppress those
without inferring agent intent.
Read references/agent-env-detection.md for concrete Rust detection
code, the canonical priority order, and a Bun-style verbosity adaptation
(suppress passing test logs under AI_AGENT; emit only failure traces).
The <tool> schema sub-command (mandated by spacecraft-cli-standard §2
Rule 4) is not just human-readable JSON Schema. It must be directly
droppable into the function-calling APIs of the major LLM providers:
| Provider | Format expected | Adapter required |
|---|---|---|
| Anthropic | tools[].input_schema (JSON Schema Draft 2020-12) |
None — direct paste |
| OpenAI | tools[].function.parameters (JSON Schema subset) |
Wrap with {type:"function", function:{name, description, parameters}} |
| Google Gemini | tools[].function_declarations[].parameters |
Wrap with {name, description, parameters} |
| MCP | tools[].inputSchema |
None — direct paste |
<tool> schema --format anthropic|openai|gemini|mcp SHOULD emit the
provider-specific wrapping. The default (--format json) emits the raw
JSON Schema, which equals the Anthropic/MCP format.
Read references/llm-tool-calling.md for the exact wrapper templates,
required-field rules per provider (e.g., OpenAI requires description
on every parameter), and the gotchas (Gemini doesn't support oneOf;
OpenAI strict mode disallows additionalProperties).
The examples array in the schema output is also agent-facing: each
example MUST be a complete, runnable invocation. An agent reads these
to bootstrap its first attempt, so accuracy matters more than density.
spacecraft-cli-standard §2 Rule 8 mandates an MCP surface for tools with
10 sub-commands. This skill specifies the token-economy discipline required to make that surface actually useful.
The naive MCP server pattern advertises every tool's full schema on connection, consuming 50–150 KB of agent context window before the agent has done anything. The Spacecraft Software pattern advertises only:
- Tool names
- One-line descriptions
- Capability tags (e.g.,
read,write,destructive)
Full input/output schemas are loaded only when the agent calls
tools/get for a specific tool. This mirrors:
- Claude Code's deferred MCP schema injection
- Cursor's tool-search approach (reported 46.9% token reduction)
- Anthropic's
antlazy tool registry
Read references/token-economy.md for the lazy-loading server
implementation pattern, the tools/list minimal envelope, and the
trade-off matrix between eager and lazy loading.
The discipline extends to CLI output too: the --fields flag is the
agent's primary mechanism for trimming token cost when full records are
unnecessary. Every list command MUST honor --fields. Streaming use
cases use --format jsonl — one JSON object per line — so the agent can
process records as they arrive without buffering the full payload.
When a Spacecraft Software CLI is invoked by a human, the human has agency and intent. When invoked by an agent, the agent may be:
- Hallucinating arguments — guessing flag names and values
- Operating on untrusted input — processing email, web pages, files from external sources that may contain prompt-injection payloads
- Retrying after failure — possibly mutating state idempotently
- Operating with elevated privileges — running as the human's user
The CLI is the last line of defense before the host system. The threat model in the CLI Standard §7 is non-negotiable, and this skill operationalizes it:
- Path arguments: canonicalize, validate against allow-list, reject
traversal sequences (
.., encoded variants, symlink escapes) - String arguments: reject control characters (0x00–0x08, 0x0B–0x0C, 0x0E–0x1F) at parse time
- Numeric arguments: bounds-check against schema-declared min/max
- Confirmation flow: destructive operations require
--yes/--forcein non-TTY mode; default-deny when interactive prompt is unavailable - Sub-process arguments: never interpolate user-provided strings into shell commands; use argv arrays exclusively
Read references/agent-threat-model.md for the full attack catalog,
the indirect-prompt-injection scenarios specific to CLI tools, and
example Rust validation code.
When designing or auditing a Spacecraft Software CLI for agent friendliness, walk this checklist. Each item maps to a token-cost lever:
--fieldshonored on every list/get command — agents trim payload to what they need. Without this, an agent paying for tokens is forced to receive the full record.jsonlmode available — for any list command that may return >50 records, support streaming so the agent can process incrementally.- Error hints are runnable commands, not prose — see §3.
- MCP advertises names + descriptions only — full schemas are
tools/get-loaded. See §6. schemasub-command emits Anthropic-format JSON Schema by default — drops directly into function-calling without translation.- Default JSON output is compact (no pretty-printing) when stdout is not a TTY. Pretty-printing wastes tokens.
- Timestamps as ISO 8601 strings, not objects —
"2026-04-10T14:30:00Z"is 22 chars; an object with{year, month, day, hour, minute, second, tz}is 80+. Use the string form. - No null-padding fields — omit fields whose value is null in JSON
output (use
serde(skip_serializing_if = "Option::is_none")). Each"field": nullline is wasted tokens.
When reviewing an existing Spacecraft Software CLI for agent-friendliness
(complementary to the structural audit in spacecraft-cli-standard §9),
walk this list.
Audit by running, not by reading. On the user's own machine you can invoke
the CLI under the host's actual agent environment and observe the real output
mode — which catches presence-vs-value detection bugs (item 6) that a source
read sails past. Probe the live env first (references/local-host-authoring.md),
then drive the CLI with those real values.
| # | Check | Severity if missing |
|---|---|---|
| 1 | AGENTS.md exists at repo root |
MAJOR |
| 2 | CLAUDE.md exists at repo root |
MAJOR |
| 3 | SKILL.md exists at repo root |
MAJOR |
| 4 | Every error response has a non-empty hint field |
CRITICAL |
| 5 | Hints are runnable commands, not prose | CRITICAL |
| 6 | Setting the host's actual AI_AGENT value (a string, not necessarily 1) makes <tool> describe report profile=agent + json + no-color + non-interactive — verified by running, not reading |
CRITICAL |
| 7 | <tool> schema output is valid JSON Schema Draft 2020-12 |
BLOCKER |
| 8 | --fields honored on every list/get |
CRITICAL |
| 9 | --format jsonl works for streaming-eligible commands |
MAJOR |
| 10 | MCP server (if present) uses lazy loading | CRITICAL |
| 11 | Path arguments are canonicalized + allow-list validated | BLOCKER |
| 12 | Control-character rejection on string arguments | CRITICAL |
| 13 | Non-TTY destructive ops require --yes / --force |
BLOCKER |
| 14 | JSON output omits null fields | MAJOR |
| 15 | JSON output is compact (not pretty) when stdout is non-TTY | MAJOR |
Findings categorized as BLOCKER / CRITICAL / MAJOR per
spacecraft-cli-standard §9.
| File | Read when implementing... |
|---|---|
references/agents-md-authoring.md |
Writing AGENTS.md / CLAUDE.md / SKILL.md / CONTRIBUTING.md; choosing what goes where; avoiding template anti-patterns |
references/tips-thinking.md |
Authoring the hint field of any error; designing cascading hints; avoiding vague hint anti-patterns |
references/agent-env-detection.md |
Implementing the env-var detection cascade; writing detection in Rust / Nushell / PowerShell; behavioral adaptation per variable |
references/llm-tool-calling.md |
Shaping <tool> schema output for Anthropic / OpenAI / Gemini / MCP; provider-specific wrappers; required-field rules |
references/token-economy.md |
MCP lazy loading; --fields; jsonl streaming; payload minimization; null-field omission |
references/agent-threat-model.md |
Input validation; path canonicalization; control-character rejection; indirect prompt injection defenses |
references/local-host-authoring.md |
Scaffolding or auditing a CLI on the user's own machine; probing the real agent env; presence-based detection; run-to-verify auditing; no-clobber scaffolding; agent-runnable hints |
Assets:
assets/agents-md.template.md— drop-in AGENTS.md templateassets/claude-md.template.md— drop-in CLAUDE.md templateassets/error-hint-catalog.json— canonical hint strings keyed byerror.code
This skill is the agent-UX layer in the Spacecraft Software CLI skill stack:
spacecraft-standard-constitution— master Standard. Master wins on conflict.spacecraft-cli-standard— structural CLI Standard rules (what the CLI must be). Authoritative on structure. This skill is subordinate; never weakens its rules. Both load together when a Spacecraft Software CLI is in scope.spacecraft-cli-preference— picks which external CLI tools the CLI (and you, while building it) should invoke (e.g.,rgovergrep). Now local-host aware: substitutes only when the tool is present.spacecraft-cli-shell— shell syntax for any command you emit while scaffolding, testing, or documenting the CLI. Now local-host aware: routes by who executes the command (agent-run vs handed to the user vs written to a file).spacecraft-missing-pkg— provisioning. When building the CLI needs a toolchain, linter, or interpreter that isn't installed, this owns getting it — ephemeral-first, consent before any durable install.microsoft-rust-guidelines— Microsoft Pragmatic Rust Guidelines. Consult when writing Rust.spacecraft-brand-guidelines— six-token color palette source of truth.
The three CLI/shell/provisioning siblings were all retargeted at the local host; route to them rather than restating their rules.
Scaffolding and auditing a Spacecraft Software CLI happen on the user's real
machine, not in a throwaway sandbox. Five rules follow; detail lives in
references/local-host-authoring.md.
- Detect agents by presence, not by
=1.AI_AGENT,AGENT,CLAUDECODE, and the rest are set to whatever the harness likes — a live Claude Code session exportsAI_AGENT=claude-code_2-1-218_agent. Test set-and-non-empty; onlyCIcarries a truthy/falsy value. (§4.) - Probe the real environment before testing. Read the agent env vars
actually present on the host and use their concrete values as fixtures —
don't assume
=1. - Audit by running, not by reading. Drive the CLI under those real values and observe the output mode; a source read misses exactly the detection bug in rule 1. (§9.)
- Scaffolding is no-clobber. Read existing context files first; propose a merge, never overwrite. (§2.)
- Emit agent-runnable hints. A hint an agent cannot run without a TTY or
root — anything starting
sudo— violates tips-thinking's own rule. Point at a non-privileged path, or mark human-escalation explicitly. (§3,references/tips-thinking.md.)
End of SKILL.md. Full normative spec: Spacecraft Software Dual-Mode Self-Documenting CLI Standard (v1.0.0) "Dual-Mode
Self-Documenting CLI Framework", §3 (Eight Rules), §6 (Schema
Introspection), §7 (Input Hardening), §9 (Agent Environment Detection),
§10 (MCP Surface). Companion skill: spacecraft-cli-standard.