Command writing
Use when creating or editing a slash command in src/agent-src/commands/ — frontmatter, numbered steps, safety gates — even when the user just says 'add a /command for X'.From its SKILL.md
npx -y skills add event4u-app/agent-config --skill command-writingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
12.9 KB, ~3.1k tokens by cl100k_base, as published. Nobody here has run it
command-writing
When to use
- Creating a new slash command in
src/agent-src/commands/{name}.md - Rewriting an existing command (not a typo fix)
- Deciding whether a request should be a command at all
- Splitting an oversized command into smaller ones
Do NOT use this skill when:
- The content is a constraint the agent must always honor → use
rule-writing - The content is reference knowledge agents cite → use
guideline-writing - The content is a triggered workflow invoked by the model → use
skill-writing
Command vs skill — critical test
| Intent | Artifact |
|---|---|
"User types /foo to explicitly run this" | Command |
| "Agent picks this up from description match" | Skill |
A command is user-invoked and carries disable-model-invocation: true.
A skill is model-invoked via description routing. If both audiences apply,
author as a skill and add a thin command that delegates to it.
A command must EARN a top-level slot. Only three justifications qualify:
flow-entry, state-query, or product-surface — everything else is a
skill. Check before authoring: command-clusters § Command justification
(ADR-048).
Categorize at creation (checklist). When you author a NEW top-level command,
declare its justification as a category: in the frontmatter — the schema enum
is flow-entry | state-query | product-surface:
- flow-entry — a daily work starting point the user TYPES to begin
(
work,git-commit,review-changes). - state-query — a read-only check (
agent-status,project-health,profile). - product-surface — a feature started deliberately (
council,research,roadmap). - fits none → it is a skill. Don't add the command; author a skill.
- genuinely ambiguous? Omit
category:and note why —category:is OPTIONAL (validate-when-present); deferring is intentional, not forgotten.
Sub-commands (council:debate) inherit the parent cluster's category — leave
category: off them. Why optional + not yet a blocking lint, and what triggers
the upgrade: command-category-governance.
Commands ARE Claude skills (projection reality)
Every command in src/agent-src/commands/{name}.md is projected
into .claude/skills/{slug}/SKILL.md by scripts/condense.ts
(generate_claude_commands). Nested commands flatten with -
(council/default.md → council-default). Skills and commands share the
same .claude/skills/ namespace — Claude does not distinguish them.
Consequences for authoring:
- The frontmatter
descriptionis the routing surface Claude reads. Polite or generic phrasing causes undertriggering even withdisable-model-invocation: trueset, because the in-host command suggester, fuzzy search, and any tooling that scans.claude/skills/rank by description match. disable-model-invocation: trueblocks automatic invocation. It does NOT remove the command from discovery surfaces. A weak description means the command is invisible to the suggester even when the user's intent matches.- Trigger phrasing must follow the same Iron Law as skill descriptions:
name 2+ trigger classes (domains, symptoms, user phrasing), end with
the
... even when the user just says ...tail, ≤ 200 chars. Seeskill-writing§ 1b for the canonical before/after. - The
suggestion.trigger_descriptionandsuggestion.trigger_contextblocks are separate from the frontmatterdescription— they drive the in-host suggester (command-suggestion-policy), not Claude's skill router. Both matter, both must be precise.
Bottom line: write the command's description as if a skill router will
read it — because one will.
Procedure
0. Run the Drafting Protocol
Creating or materially rewriting a command must go through Understand →
Research → Draft from the
artifact-drafting-protocol rule.
- Understand — what user-facing problem does
/{name}solve in one session? What are the inputs, outputs, side effects? - Research — inspect
src/agent-src/templates/command.md, grepcommands/for overlap, and analyze 1–2 peer commands (e.g.create-pr,commit). - Draft — propose frontmatter (
name,description) first, then the step skeleton. Only fill bodies after both are confirmed.
1. Use the template
Canonical source: src/agent-src/templates/command.md.
Minimum frontmatter:
---
name: {command-name} # must match filename without .md
description: "Short human-readable summary of what /{name} does"
disable-model-invocation: true
skills: [optional-skill-1] # optional — skills this command delegates to
suggestion: # required (road-to-context-aware-command-suggestion Phase 2)
eligible: true # default; set false to opt out of auto-surfacing
trigger_description: "natural-language pattern, comma-separated examples"
trigger_context: "concrete signal — branch name, file pattern, recent tool output"
---
Or, when opting out:
suggestion:
eligible: false
rationale: "one-line reason this command must be invoked deliberately"
Suggestion-block rules (linter-enforced):
eligibleis required and must betrueorfalse.eligible: true→ bothtrigger_descriptionandtrigger_contextmust be non-empty (≥ 10 chars each); the linter rejects empty or overly generic patterns. The suggestion layer never auto-executes; the user always picks.eligible: false→rationalemust be non-empty. Use the opt-out for intentional-only invocations (settings mutations, destructive actions, package-internal tools, niche maintenance).- Optional
confidence_floor(0.0–1.0) andcooldown(e.g.10m) override the global settings per command.
Eligibility decisions are tracked in
agents/settings/contexts/command-suggestion-eligibility.md.
Add or revise entries there before changing a command's suggestion block.
When iterating on the description, delegate to the
description-assist skill — approval-gated,
no silent edits, max two rounds.
2. Structure the body
Required sections in this order:
# /{name}heading + one-line summary- Source of truth note — works on
src/, never on generated directories ## Steps— numbered sub-headings### 1.,### 2., ...- Final step presents findings and asks the user before destructive
changes (numbered options per
user-interactionrule) - Optional
## Rules— short, command-specific constraints
3. Enforce safety gates
- No auto-apply of destructive actions without user confirmation.
- Every step with side effects (git push, file delete, PR merge) asks first.
- If the command calls external APIs, list required keys / permissions.
- If the command edits agent files, target
src/only.
3b. Path conventions in command body
Body links to guidelines / contracts use the verbatim relative form
(../../docs/guidelines/..., ../../docs/contracts/...); the
condense-time rewriter handles depth. Do not pre-rewrite in source. Do
not write src/ in any markdown link target — the
file ships into .augment/commands/ and the prefix breaks consumer
resolution. The only legitimate src/ strings in a
command file are prose mentions and step instructions about where to
edit (per § 2 above). Canonical reference: rule-writing § 3b.
4. Enforce the size budget
Normative source: size-enforcement +
docs/guidelines/agent-infra/size-and-scope.md.
| Category | Target |
|---|---|
| Ideal | ≤ 120 lines |
| Acceptable | ≤ 200 lines |
| Split signal | > 250 lines |
Commands orchestrate, they do not implement detail. If a step needs a multi-paragraph explanation, extract it into a skill and call it.
5. Validate
- Run
./scripts-run src/scripts/skill_linter src/agent-src/commands/{name}.md→ 0 FAIL. - Run
bash scripts/condense.sh --sync→ regeneratesdist/agent-src/commands/{name}.md. - Run
./scripts-run src/scripts/condense --generate-tools→ creates the Claude symlink at.claude/skills/{name}/SKILL.md. - Run the full CI pipeline locally (see
Taskfile.ymlin this repo for the script list) — must exit 0 except for tolerated warnings.
6. Governance baseline (when introducing a new linter check)
Advisory, reviewer-checked — no CI gate. When the same PR adds a
new check to scripts/skill_linter.ts (or strengthens an existing
one) such that previously-clean commands now warn, the PR body MUST
record the pre-existing violations on main in a Markdown table:
### Pre-existing baseline (informational)
| Code | Count on main | Bucket |
|---|---:|---|
| {new_code} | N | (a) genuine fix · (b) accept · (c) check too aggressive |
Forward-only: the new check applies to the file under review and
to future edits. The baseline table is informational so reviewers
can spot intent (fix-now vs. backlog) without diffing the full lint
output. See agents/evidence/analysis/lint-warning-triage.md for the
3-bucket reference.
Output format
- Complete command file at
src/agent-src/commands/{name}.md - Frontmatter populated,
disable-model-invocation: truepresent - Linter output showing 0 FAIL
- Generated Claude symlink verified
Gotchas
- Forgetting
disable-model-invocation: true— the model will auto-invoke the command as if it were a skill. - Numbered options without a "skip" / "no change" path.
- Steps that silently apply destructive changes — always show summary + ask.
- Referring to
.augment/paths for editing — source of truth issrc/. - Duplicating another command's workflow instead of delegating via
skills:.
Frugality Standards
Apply the Frugality Charter to every command you author.
Examples in this artifact:
- Per the charter's default-terse rule, command output blocks state the action result, not "Now we will execute…".
- Per the post-action summary suppression, the success path emits the artifact (PR URL, commit hash) without a wrapping summary.
- Per the cheap-question check, never offer "preview vs. execute" as a numbered option when the command's role is to execute.
Pre-save self-check:
- Does any command step prescribe a "Let me…" or "Found it" output line?
- Does the command default to multi-line summaries when a one-line outcome suffices?
- Is a confirmation gate used outside the Iron-Law / Routine / Contextual taxonomy?
- Are template placeholders (
{{var}}) accompanied by setup prose instead of action prose?
Do NOT
- Do NOT set
disable-model-invocation: false - Do NOT auto-apply destructive actions
- Do NOT inline skill-level detail — delegate
- Do NOT edit
dist/agent-src/,.augment/, or.claude/projections - Do NOT exceed the hard size limit without a waiver
Cloud Behavior
On cloud surfaces (Claude.ai Web, Skills API) the package's
scripts/skill_linter.ts, scripts/condense.ts, and the task
runner are not available. This skill still applies — but with
prose-only validation:
- Emit the full command file as a copyable Markdown block. Do not attempt to write it to disk.
- Self-check the frontmatter against the rules below —
name,description,disable-model-invocation: trueMUST all be present. - Self-check the body shape: numbered steps, explicit safety gates, no inline skill-level detail.
- Tell the user to save the file under
src/agent-src/commands/{name}.mdand runtask sync && task lint-skillslocally before committing. - Skip every reference to running the linter, condenseor, or generators yourself — they only run on the user's machine.
Examples
Good description (trigger-shaped, outcome-focused):
"Create a GitHub PR with structured description from Jira ticket and code changes"
Bad description (vague, no outcome):
"PR command"
Encode usage policy in the description
Workflow sequencing, preconditions, ID/output provenance ("copy ids verbatim,
never from memory"), a mandatory "why" intent field, and turn-end contracts
belong INSIDE this artifact's description/frontmatter — where they fire at the
decision point — not in always-on prose. See
tool-description-as-policy.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.