command-authoring — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited command-authoring (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Reference for authoring and auditing slash commands across CC, Codex, and Gemini. Commands are L4 (Instructions) artifacts in the COC 5-layer architecture per rules/cc-artifacts.md — distinct from agents (L1 Intent), skills (L2 Context), and rules (L3 Guardrails). They inject as user-message prompts at invocation; every line competes with actual user intent for context.
Authoring a new slash command. Auditing an existing command for line cap, neutral phrasing, native-primitive carve-out drift, or cross-CLI parity. Deciding whether work belongs in a command (procedure invoked by name) versus an agent (specialist judgment + tools) or a skill (reference looked up on demand).
| CLI | On-disk path | Format | Slash invocation | Frontmatter shape |
|---|---|---|---|---|
| CC | .claude/commands/<name>.md | Markdown | /<name> | YAML: name: + description: + optional argument-hint: / allowed-tools: |
| Codex | .codex/prompts/<name>.md | Markdown | bin/coc <name> "<prompt>" (deprecated upstream: /prompts:<name> is no longer loaded by Codex CLI 0.128+ — bin/coc dispatcher is canonical) | Same YAML, preserved from source |
| Gemini | .gemini/commands/<name>.toml | TOML | /<name> | name, description, prompt = '''…''', optional tools = [...] |
| Constraint | Value |
|---|---|
name: | Lowercase, hyphen-separated. Matches filename stem. |
description: | One short line. Failure-mode language. Per rules/cc-artifacts.md Rule 1 cap ≤120 chars for any frontmatter that flows into a listing surface. |
| Body length | ≤150 lines per rules/cc-artifacts.md Rule 3. Push reference content to skills, judgment to agents. |
| Neutral phrasing | No CC-native delegation syntax (Agent(subagent_type=…), Task(…)) in prescriptive prose — Codex and Gemini consume the same body. |
argument-hint: | Single line; used by CC to render the hint after /name. |
The authoritative copy lives at .claude/commands/<name>.md. The emitter .claude/bin/emit-cli-artifacts.mjs (driven by coc-sync Step 6.6) produces:
.codex/prompts/<name>.md — Markdown passthrough with Codex-native adaptations from variants/codex/commands/<name>.md overlays (if any)..gemini/commands/<name>.toml — TOML wrap of the same body inside a triple-single-quote prompt block; YAML frontmatter is converted to TOML keys.Both consumers read the source body. Anything CC-native that appears in the body — Agent(subagent_type=…), Task(…), TodoWrite(…) — leaks into Codex/Gemini emissions and is unparseable there.
# DO — minimal, action-oriented
---
name: redteam
description: "Load phase 04 (validate) for the current workspace. Red team testing."
---The description: is what appears in the CC /help listing and in Codex's /prompts enumeration. Failure-mode language ("Red team testing"; "Production hardening for frontend") wins over generic noun phrases ("Validation command"; "Hardening utility").
---
name: implement
description: "Load phase 03 (implement) for the current workspace."
argument-hint: "[shard-id]"
---argument-hint: renders inline after the command name during typeahead. Use bracketed placeholders for optional args, angle brackets for required.
allowed-tools: restricts which tools the agent may invoke during the command body. Default is unrestricted. Use only when the command genuinely shouldn't reach for, e.g., Bash or Write. Most commands omit it.
Per rules/cc-artifacts.md Rule 3: commands inject as user messages and compete with the actual user prompt. Long commands crowd out user intent.
workspaces/<project>/02-plans/analyze.md).If a command exceeds 150 lines, the fix is almost always extraction — move the reference block into a numbered skill the command references.
The ≤150-line cap is an output-quality discipline, not only a budget one: per the curation/over-density principle (rules/rule-authoring.md MUST NOT § "Rules longer than 200 lines" + cc-architect dimension 7, grounded in journal/0193's directional ablation), a body whose load-bearing steps are drowned in non-load-bearing prose degrades the OUTPUT of the agent that loads it. Surfacing over-density at audit time is an advisory FINDING (recommend extraction), never a structural FAIL.
Commands ship to all three CLIs. Body content MUST NOT bake in CC-native syntax that breaks on Codex / Gemini. Per rules/cross-cli-artifact-hygiene.md:
# DO — neutral phrasing
Delegate to security-reviewer for parallel scan; dispatch reviewer and
gold-standards-validator in the same wave.
# DO NOT — CC-native delegation syntax in command body
Agent(subagent_type="security-reviewer", run_in_background=true, prompt=…)
Task(subagent_type="reviewer", …)Codex reads natural-language specialist references and spawns subagents accordingly; Gemini uses @<agent-name> syntax. Both fail on literal Agent(...) / Task(...) calls embedded in prose. The same applies to hook event names — write "the SessionStart hook" rather than hooks.SessionStart.
CLI-specific or language-specific bodies live at .claude/variants/<axis>/commands/<name>.md and overlay only the diverging slot. Axes:
variants/codex/ — Codex-only deltas (e.g. invoke codex review natively instead of redirecting)variants/gemini/ — Gemini-only deltasvariants/py/, variants/rs/, variants/rb/, variants/prism/ — language deltasvariants/py-codex/, variants/rs-codex/, variants/py-gemini/, variants/rs-gemini/ — ternary overlays (language × CLI)Slot-marker syntax matches the skill-authoring convention:
<!-- slot:neutral-body -->
This content emits to all CLIs.
<!-- /slot:neutral-body -->
<!-- slot:examples -->
CLI-neutral examples — overridable per CLI.
<!-- /slot:examples -->Variant files supply replacement bodies only for the slots that diverge. Unoverridden slots inherit the global file.
Some CC commands map to a CLI's own native primitive — emitting a .codex/prompts/<name>.md or .gemini/commands/<name>.toml for them would shadow the native path. Per .claude/agents/codex-architect.md § Codex-Native Primitives:
codex review --uncommitted --base main (Codex native). Do NOT emit a .codex/prompts/review.md.The exclusion mechanism lives in .claude/sync-manifest.yaml::cli_emit_exclusions.{codex,gemini} as a glob list. New commands that have a native counterpart MUST add a commands/<name>.md exclusion entry for the relevant CLI.
Bash wrappers (bin/coc-<name>, e.g. bin/coc-analyze invoking codex exec --json --output-schema=…) were authored at Phase J1 but wrapper emission was deferred at Shard C 2026-05-10 per journal/0006-DECISION-wrapper-emission-disposition-strip.md. Reasons: the wrappers' runtime dependency .codex/developer-instructions/ was never authored; the native prompt surface covers all 28 commands; manifest emit_to declarations were stubs.
Treat .claude/wrappers/*.sh.template as historical. New commands MUST NOT add wrapper templates. If a future workstream requires structured-output enforcement or external CLI invocation, revival is documented in the journal entry — propose at /codify, do not assume it's live.
Every new command MUST be added to .claude/sync-manifest.yaml under the appropriate tier block. The tiers determine which USE templates receive the command:
# .claude/sync-manifest.yaml
tiers:
co:
- commands/<name>.md # ships everywhere CO baseline ships
coc:
- commands/<name>.md # ships to all COC consumers
cc:
- commands/<name>.md # CC-only (e.g. /review)repos.<target>.tier_subscriptions controls which tiers a USE template receives. Per the emitter's --target flag, the per-repo subscription list IS the filter — a command in co but not in repos.kailash-coc-py.tier_subscriptions does not ship there.
cli_emit_exclusions:
codex:
- commands/review.md # codex review is native
gemini:
- commands/review.md # gemini has its own review path (if any)Glob form is supported (commands/i-*.md). The emitter honors exclusions at source-tree scan time.
| Symptom | Belongs in |
|---|---|
User types /foo to start a procedure | Command |
| Reference content looked up on demand | Skill |
| Specialist judgment with tools + delegation | Agent |
| Always-on boundary enforcement | Rule |
| Deterministic hook firing on tool event / session lifecycle | Hook |
If a "command" file grows judgment rubrics, scoring criteria, or conditional branching with recovery paths, it's an agent in disguise. Move the body into .claude/agents/<name>.md and shrink the command to a 20-line dispatch (Delegate to <name>-specialist with the user's input as the prompt.).
Most frequent. Reference tables, exhaustive option lists, multi-page review rubrics inflate the body until command injection floods the user's prompt context. Fix: extract the reference content into a skill or agent.
Agent(subagent_type="…") / Task(…) / TodoWrite(…) in prescriptive prose breaks Codex + Gemini emissions. Fix: rewrite as neutral instruction ("delegate to security-reviewer", "dispatch reviewer + gold-standards-validator in parallel").
New command in .claude/commands/ but not in sync-manifest.yaml ships to nobody — emitter scans tier-listed files only. Fix: add commands/<name>.md to the correct tier; verify with a dry-run emission against one USE target.
Authoring a review command file (shadowing Codex's native codex review) without an exclusion entry causes the emitter to overwrite the native invocation with a redirected prompt. Fix: add that command to cli_emit_exclusions.codex BEFORE it lands.
Multi-sentence descriptions waste listing-budget bytes and dilute the failure-mode signal. Fix: one short clause naming the situation the command addresses ("Production hardening for frontend"), not a paragraph.
argument-hint: Without Body HandlingFrontmatter hints at args, body never references $ARGUMENTS or the user's argv. Result: typeahead promises a feature the command doesn't deliver. Fix: either remove the hint or wire $ARGUMENTS resolution into the body.
When auditing an existing command:
name: matches filename stemdescription: one short line, failure-mode languagesync-manifest.yaml under correct tiercli_emit_exclusions.<cli>.claude/wrappers/<name>.sh.template (wrappers deferred per journal/0006)variants/<axis>/commands/<name>.md use slot markersargument-hint: set, body resolves $ARGUMENTSrules/cc-artifacts.md Rule 3 — ≤150-line cap on commandsrules/cc-artifacts.md Rule 1 — description char caps + listing-budget pressurerules/cross-cli-artifact-hygiene.md — neutral phrasing requirementrules/cross-cli-parity.md — variant overlay semanticsagents/codex-architect.md § Codex-Native Primitives — carve-out tableagents/gemini-architect.md § Gemini-Native Primitives — Gemini equivalentsbin/emit-cli-artifacts.mjs — emitter source of truthskill-authoring (F1) — sibling meta-skill, same shape conventionshook-authoring (F3, planned) — hook lifecycle + validator-13 bijection~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.