Skip to content
Back to skills

Command Writing

ASecurity

Use when creating or editing a slash command in .agent-src.uncondensed/commands/ — frontmatter, numbered steps, safety gates — even when the user just says 'add a /command for X'.

  • 10 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added June 5, 2026
ai-agentspythongobashgitapi

Works with

  • api

Security analysis

A100/100

Scanned June 5, 2026

npx -y skills add event4u-app/agent-config --skill command-writing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Command Writing?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Command Writing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/event4u-app-command-writing/badge)](https://www.skillsdirectory.com/skills/event4u-app-command-writing)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
model_tier: inherit
name: command-writing
description: "Use when creating or editing a slash command in .agent-src.uncondensed/commands/ — frontmatter, numbered steps, safety gates — even when the user just says 'add a /command for X'."
domain: process
workspaces:
  - agent-config-maintainer
packs:
  - meta
---

<!-- cloud_safe: degrade -->

# command-writing

## When to use

* Creating a new slash command in `.agent-src.uncondensed/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.

## Commands ARE Claude skills (projection reality)

Every command in `.agent-src.uncondensed/commands/{name}.md` is projected
into `.claude/skills/{slug}/SKILL.md` by `scripts/condense.py`
(`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 `description` is the **routing surface** Claude reads.
  Polite or generic phrasing causes undertriggering even with
  `disable-model-invocation: true` set, because the in-host command
  suggester, fuzzy search, and any tooling that scans `.claude/skills/`
  rank by description match.
* `disable-model-invocation: true` blocks **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. See
  `skill-writing` § 1b for the canonical before/after.
* The `suggestion.trigger_description` and `suggestion.trigger_context`
  blocks are **separate** from the frontmatter `description` — 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`](../../rules/artifact-drafting-protocol.md) rule.

* **Understand** — what user-facing problem does `/{name}` solve in one
  session? What are the inputs, outputs, side effects?
* **Research** — **inspect** `.agent-src.uncondensed/templates/command.md`,
  grep `commands/` 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: `.agent-src.uncondensed/templates/command.md`.

Minimum frontmatter:

```yaml
---
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:

```yaml
suggestion:
  eligible: false
  rationale: "one-line reason this command must be invoked deliberately"
```

Suggestion-block rules (linter-enforced):

* `eligible` is **required** and must be `true` or `false`.
* `eligible: true` → both `trigger_description` and `trigger_context` must 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` → `rationale` must 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) and `cooldown` (e.g. `10m`)
  override the global settings per command.

Eligibility decisions are tracked in
[`agents/settings/contexts/command-suggestion-eligibility.md`](../../../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`](../description-assist/SKILL.md) skill — approval-gated,
no silent edits, max two rounds.

### 2. Structure the body

Required sections in this order:

1. `# /{name}` heading + one-line summary
2. **Source of truth note** — works on `.agent-src.uncondensed/`, never on
   generated directories
3. `## Steps` — numbered sub-headings `### 1.`, `### 2.`, ...
4. Final step **presents findings** and asks the user before destructive
   changes (numbered options per `user-interaction` rule)
5. 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 `.agent-src.uncondensed/` 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 `.agent-src.uncondensed/` in any markdown link target — the
file ships into `.augment/commands/` and the prefix breaks consumer
resolution. The only legitimate `.agent-src.uncondensed/` 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`](../../rules/size-enforcement.md) +
`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 `python3 scripts/skill_linter.py .agent-src.uncondensed/commands/{name}.md`
  → 0 FAIL.
* Run `bash scripts/condense.sh --sync` → regenerates `.agent-src/commands/{name}.md`.
* Run `python3 scripts/condense.py --generate-tools` → creates the Claude symlink at
  `.claude/skills/{name}/SKILL.md`.
* Run the full CI pipeline locally (see `Taskfile.yml` in 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.py` (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:

```markdown
### 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

1. Complete command file at `.agent-src.uncondensed/commands/{name}.md`
2. Frontmatter populated, `disable-model-invocation: true` present
3. Linter output showing 0 FAIL
4. 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 is
  `.agent-src.uncondensed/`.
* Duplicating another command's workflow instead of delegating via `skills:`.

## Frugality Standards

Apply the [Frugality Charter](../../contexts/contracts/frugality-charter.md)
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:**
1. Does any command step prescribe a "Let me…" or "Found it" output
   line?
2. Does the command default to multi-line summaries when a one-line
   outcome suffices?
3. Is a confirmation gate used outside the Iron-Law / Routine /
   Contextual taxonomy?
4. 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 `.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.py`, `scripts/condense.py`, 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: true` MUST 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
  `.agent-src.uncondensed/commands/{name}.md` and run
  `task sync && task lint-skills` locally 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"

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.