system-cli-standards
Standards for how plugin prompt files (skills, agents, commands) invoke and reference the SDD system CLI.
Files1
View on GitHubSKILL.md.claude/skills/system-cli-standards/skill.md
GitHubSystem CLI Standards
Standards for all plugin prompt files (skills, agents, commands) that invoke or reference the SDD system CLI. Does NOT cover hooks (separate lifecycle via hook-runner.sh).
Canonical Invocation
The plugin has two system CLIs — one for core SDD operations and one for tech-pack-specific operations. Each has its own system-run.sh:
# Core SDD operations (spec, scaffolding, workflow, settings, permissions, archive, agent, log, tech-pack)
<plugin-root>/core/system/system-run.sh <namespace> <action> [args] [options]
# Tech pack operations (config, contract, database, local-env)
<plugin-root>/fullstack-typescript/system/system-run.sh <namespace> <action> [args] [options]
<plugin-root>is a placeholder that the agent resolves from its Claude Code plugin context. It is NOT shell syntax — the agent substitutes the actual absolute path before constructing the bash command.- Each
system-run.shself-locates its own system root from its filesystem path and forwards to the compiled CLI viaexec. - Both system packages are
private: truewith nobinfield, sosystem-run.shis the only valid way to invoke each.
Which CLI to call
| Namespace | CLI |
|---|---|
scaffolding, spec, permissions, workflow, settings, archive, tech-pack, agent, log |
core/system/system-run.sh |
config, contract, database, local-env |
fullstack-typescript/system/system-run.sh |
Invocation Contexts
1. Plugin prompts (skills, agents, commands)
Use system-run.sh as shown above. This is the only context this standard covers.
2. Hooks
Hooks use hook-runner.sh via hooks.json. Different lifecycle, different stdin/stdout JSON contract. Out of scope for this standard.
3. User-project npm scripts (scaffolded templates)
Templates that scaffold package.json files into user projects cannot use ${CLAUDE_PLUGIN_ROOT} — that variable only exists during a plugin session. Scaffolded npm scripts that reference sdd-system as a bare command are broken. Until the system package exposes a bin field or another resolution mechanism, do not emit CLI invocations in scaffolded templates. Instead, provide instructions that the user runs via the plugin commands (e.g., /sdd-run).
Output Contract
All CLI commands return a CommandResult:
interface CommandResult {
readonly success: boolean;
readonly data?: unknown;
readonly error?: string;
readonly message?: string;
}
Behavior by mode
| Mode | Flag | Behavior |
|---|---|---|
| JSON (structured) | --json |
Prints JSON.stringify(result, null, 2) to stdout |
| Plain (human) | (default) | Prints result.message to stdout, or Error: ${result.error} to stderr on failure |
Exit codes
| Code | Meaning |
|---|---|
0 |
result.success === true |
1 |
result.success === false |
How prompts should consume CLI output
- For structured data: Use
--jsonand parse the JSON output. Check.successbefore reading.data. - For display to user: Omit
--json. The CLI prints human-readable text. - Error handling: Check the exit code. On non-zero exit, the stderr contains the error message.
Global options
All commands accept:
| Option | Description |
|---|---|
--json |
Output structured JSON instead of plain text |
--verbose |
Enable verbose logging |
--help |
Show help for the command |
Stdin Convention
CLI commands that accept file content (e.g., --config <path>) should also accept - to read from stdin. This eliminates temporary file creation in prompts.
system-run.sh passes stdin through transparently via exec.
Preferred — pipe content via stdin:
echo "${content}" | <plugin-root>/system/system-run.sh namespace action --config -
Avoid — creating temp files:
# Don't do this — creates files that need cleanup
echo "${content}" > /tmp/temp-config.yaml
<plugin-root>/system/system-run.sh namespace action --config /tmp/temp-config.yaml
rm /tmp/temp-config.yaml
Authority Boundaries
CLI owns (deterministic operations)
- File generation and scaffolding
- YAML/JSON parsing and validation
- Path resolution and filesystem checks
- Schema validation
- Environment management
- Configuration reads and writes
- Version information
Prompts own (judgment and interaction)
- Orchestration and workflow sequencing
- User interaction (commands only)
- Decision-making and context-dependent logic
- LLM-based analysis and generation
- Interpreting user intent
Rule
If an operation is deterministic and repeatable, it belongs in the CLI. If it requires judgment or context, it belongs in the prompt.
Layer separation
- Allowed: prompts → CLI (prompts invoke CLI commands)
- Forbidden: CLI → prompts (CLI must never reference skills, agents, or commands)
This is a strict one-way dependency. The CLI is a standalone tool that knows nothing about the prompt layer.
Plugin boundary
All plugin prompt files (plugin/core/skills/, plugin/core/commands/, plugin/fullstack-typescript/skills/, plugin/fullstack-typescript/agents/) have no runtime access to anything outside plugin/. Never reference .claude/, .tasks/, or root-level files from within a plugin prompt file.
When to Use CLI vs Prompt Logic
| Operation | Owner | Why |
|---|---|---|
| File reading/writing with fixed logic | CLI | Deterministic, no judgment needed |
| YAML/JSON parsing with validation | CLI | Schema-based, repeatable |
| Path resolution and filesystem checks | CLI | Pure computation |
| Scaffolding files from templates | CLI | Template expansion is mechanical |
| Configuration management | CLI | Read/write/validate against schema |
| Anything requiring LLM judgment | Prompt | Non-deterministic |
| Anything requiring user interaction | Prompt (command layer) | Commands are the UI layer |
| Workflow orchestration | Prompt | Sequencing decisions |
| Interpreting ambiguous requirements | Prompt | Needs context and judgment |
Checklist for New CLI Commands
Before adding a new CLI command, verify:
- The operation is deterministic and repeatable
- It does not require LLM judgment or user interaction
- It fits within an existing namespace, or a new namespace is justified
- It returns a
CommandResultwith appropriatesuccess,data,error, andmessagefields - It supports
--jsonfor structured output - It accepts
-for stdin where file content is an input - It has proper exit codes (0 success, 1 failure)
- It does not reference or depend on any prompt files (skills, agents, commands)
- It is documented in the relevant command
.mdfile that will invoke it
Command Existence Rule
Every system-run.sh <namespace> <action> reference in a prompt file must correspond to a command that actually exists in the CLI registry. Prompt files must not reference nonexistent namespace/action pairs.
Source of truth: Each namespace has a schema.ts in its respective system package — plugin/core/system/src/commands/<namespace>/schema.ts for core namespaces, or plugin/fullstack-typescript/system/src/commands/<namespace>/schema.ts for tech pack namespaces. Each exports an ACTIONS array as the authoritative list of valid actions per namespace.
Enforcement: The cli-invocation-audit.test.ts test scans all .md files under plugin/ for system-run.sh <namespace> <action> patterns and validates each pair against the CLI's actual command registry. This test runs as part of npm test.
When adding a new CLI invocation to a prompt file:
- Verify the
<namespace> <action>pair exists in the correspondingschema.ts - If the command doesn't exist yet, create it first — never reference a command that doesn't exist
Audit Procedure
How to audit
Use Opus model for audits — thoroughness matters more than speed here.
- Read every file in
plugin/core/skills/,plugin/core/commands/,plugin/fullstack-typescript/skills/, andplugin/fullstack-typescript/agents/ - Also read scaffolded templates in
plugin/core/skills/*/templates/andplugin/fullstack-typescript/skills/*/templates/ - For each file, check:
- Invocation correctness: All CLI references use the canonical
system-run.shinvocation - Authority violations: Prompts performing deterministic operations that belong in the CLI (e.g., YAML/JSON parsing, file generation, schema validation, path resolution). These are candidates for new CLI commands.
- Compliance: All other standards in this document are followed
- Invocation correctness: All CLI references use the canonical
- Record every finding with exact file path, line number, and description. Categorize as:
- Violation: Something that is currently broken or wrong
- Authority issue: A deterministic operation in a prompt that should be a CLI command (improves speed and reliability)
- Write report to
.temp/system-cli-audit-<datetime>.md - Ask the user if they want to turn the audit into a task. If yes, copy the report file into the task directory (e.g.,
.tasks/0-inbox/116/audit-<datetime>.md) and reference it fromtask.md— do NOT inline the full report intotask.md
Note: plugin/core/system/README.md and plugin/fullstack-typescript/system/README.md are the CLIs' own documentation and are out of scope for prompt file audits.
TypeScript standards audit
Audit the plugin/core/system/ and plugin/fullstack-typescript/system/ TypeScript source code against the typescript-standards skill.
- Load the
typescript-standardsskill — use its full Summary Checklist as the audit criteria - Read every
.tsfile inplugin/core/system/src/andplugin/fullstack-typescript/system/src/(recursively) - For each file, check every item in the typescript-standards Summary Checklist
- Record every finding with exact file path, line number, and the specific standard violated
- Append results to the same
.temp/system-cli-audit-<datetime>.mdreport (under a separate "TypeScript Standards" heading), or write a standalone.temp/typescript-audit-<datetime>.mdif running independently