Guide Origin: Official | ArcKit Version: [VERSION]
This guide explains how to add a new /arckit.<n> command. A command is a single Markdown file that ArcKit fans out to six AI-assistant formats automatically. Read this before opening a PR that adds a command.
For template customisation (changing the output of an existing command), see customize.md. For background on why ArcKit uses commands rather than skills, see the README section "Why Commands, Not Skills".
How Commands Work
You write one source file in plugins/arckit-claude/commands/<n>.md. The converter at scripts/converter.py reads it and produces six target-specific outputs:
| Target | Output path | Format |
|---|---|---|
| Claude Code (source — edit this) | plugins/arckit-claude/commands/<n>.md |
Markdown with YAML frontmatter |
| Codex CLI (command) | extensions/arckit-codex/prompts/arckit.<n>.md |
Markdown |
| Codex CLI (skill) | extensions/arckit-codex/skills/arckit-<n>/SKILL.md |
Skill format |
| OpenCode CLI | extensions/arckit-opencode/commands/arckit.<n>.md |
Markdown |
| Gemini CLI | extensions/arckit-gemini/commands/arckit/<n>.toml |
TOML |
| GitHub Copilot | extensions/arckit-copilot/prompts/arckit-<n>.prompt.md |
Prompt frontmatter |
| Paperclip | extensions/arckit-paperclip/src/data/commands.json (entry) |
JSON |
The first row is the file you edit by hand; the converter generates all others. You do not edit the generated files directly. The converter handles argument-placeholder rewriting, path rewriting for the Gemini sandbox, frontmatter stripping for Claude-only fields, and extension-file copying.
ArcKit does not use a root-level SKILL.md for plugin behaviour. Reusable
Claude Code skills live in plugins/arckit-claude/skills/<skill-name>/SKILL.md;
Codex skill outputs live under extensions/arckit-codex/skills/. Keep command
authoring guidance in this guide unless Claude Code's plugin layout explicitly
adds root-level skill support.
The Source File
Create plugins/arckit-claude/commands/<n>.md with YAML frontmatter and a prompt body.
---
description: One-line description in imperative mood
argument-hint: "<hint shown in autocomplete>"
effort: medium
handoffs:
- command: next-command
description: Why a user might run this next
---
You are helping an enterprise architect do X.
## User Input
```text
$ARGUMENTS
```
## Instructions
1. Read the template (with user override support): ...
2. Read related artifacts from the project context: ...
3. Generate the output: ...
4. Write to `projects/<project-id>/ARC-<id>-<CODE>-v<version>.md`
Frontmatter Reference
| Field | Required | Notes |
|---|---|---|
description |
Yes | Imperative, one line. Used as the slash-command description in every target. |
argument-hint |
Recommended | Shown in Claude Code autocomplete. Short hint showing the expected shape of input. |
effort |
No | low / medium / high. Claude Code only — stripped from other targets by the converter. |
handoffs |
No | List of {command, description} entries suggesting follow-on commands. Rendered into a handoffs section in generated outputs. |
paths |
No | Claude-only. Stripped from other targets. |
keep-coding-instructions |
No | Claude-only. Stripped from other targets. |
The $ARGUMENTS Contract
Always include a ## User Input section with a fenced text block containing $ARGUMENTS. The converter rewrites the placeholder per target:
| Target | Placeholder used |
|---|---|
| Claude Code | $ARGUMENTS (unchanged) |
| Codex, OpenCode | $ARGUMENTS (unchanged) |
| Gemini | {{args}} |
| Copilot | ${input:topic:Enter project name or topic} |
| Paperclip | {topic} |
Do not hand-write target-specific placeholders — use $ARGUMENTS and let the converter do the work.
Need a literal
$before a digit? Claude Code treats$1,$2, … as positional argument placeholders in command/skill bodies. To write a literal dollar-then-digit (e.g. a price like$5, or a regex like$1), escape it as\$(Claude Code v2.1.163+) —\$5,\$1. ArcKit commands rarely need this since they use$ARGUMENTS, but it matters if you write a worked example containing currency or shell positional vars.
The Copilot placeholder currently hard-codes the
topic:label regardless of what the command expects as input. If you need a command-specific label, it requires changes toscripts/converter.py— the converter is the right place to thread that customisation through.
Reading Templates with User Overrides
Commands should prefer a user-customised template over the bundled default. Use this pattern in the prompt body:
1. **Read the template** (with user override support):
- **First**, check if `.arckit/templates/<your-template>.md` exists in the project root
- **If found**: Read the user's customised template (user override takes precedence)
- **If not found**: Read `${CLAUDE_PLUGIN_ROOT}/templates/<your-template>.md` (default)
The converter rewrites ${CLAUDE_PLUGIN_ROOT} paths to the correct location for each target (for example, shell commands against ~/.gemini/extensions/arckit/ for Gemini because that directory sits outside Gemini's workspace sandbox).
Put the template file alongside the command: plugins/arckit-claude/templates/<your-template>-template.md. The filename convention is <command-name>-template.md.
How the template reaches each target:
- Paperclip embeds the template content directly into its generated
commands.jsonviaread_template_for_command()in the converter. - All other targets receive the whole
templates/tree copied verbatim into each extension directory bycopy_extension_files(), and the command reads the file at runtime via the target's path prefix (${CLAUDE_PLUGIN_ROOT},~/.gemini/extensions/arckit/, etc.).
Worked Example: /arckit:sla
Say you want a command that generates a Service Level Agreement skeleton from existing non-functional requirements.
1. Create plugins/arckit-claude/commands/sla.md:
---
description: Generate an SLA skeleton from non-functional requirements
doc-type: SLA
argument-hint: "<project ID, e.g. '001'>"
effort: medium
handoffs:
- command: servicenow
description: Feed SLAs into ServiceNow service design
- command: dld-review
description: Validate SLA coverage in detailed design review
---
You are helping an enterprise architect draft a Service Level Agreement (SLA) that inherits its targets from previously documented non-functional requirements.
## User Input
```text
$ARGUMENTS
```
## Instructions
1. **Read the template** (with user override support):
- **First**, check if `.arckit/templates/sla-template.md` exists in the project root
- **If found**: Read the user's customised template
- **If not found**: Read `${CLAUDE_PLUGIN_ROOT}/templates/sla-template.md` (default)
2. **Read the project requirements**:
- Locate `projects/<project-id>/ARC-<id>-REQ-v*.md`
- Extract all NFR-* entries (availability, latency, throughput, RTO/RPO)
- If no requirements file exists, ask the user to run `/arckit:requirements` first
3. **Generate the SLA** using the extracted NFRs:
- One row per NFR, mapped to an SLA target
- Include measurement method, reporting cadence, and breach consequences
- Maintain traceability: every SLA row cites its source NFR ID
4. **Detect version** with `${CLAUDE_PLUGIN_ROOT}/references/version-detection.md` and write to `projects/<project-id>/ARC-<id>-SLA-v<version>.md`.
2. Register the SLA code. Add 'SLA': { name: 'Service Level Agreement', category: 'Operations' }, to DOC_TYPES in plugins/arckit-claude/config/doc-types.mjs, and add SLA to the known artifact types in plugins/arckit-claude/commands/pages.md. validate-arc-filename.mjs blocks any ARC-* write whose code is not registered, and scripts/check-doc-type-registry.py fails CI on an unregistered code in a command, template or guide.
3. Create plugins/arckit-claude/templates/sla-template.md with the document skeleton (document-control header, SLA table, review cadence, and signature block).
4. Run the converter:
python scripts/converter.py
This writes out the six target files with correct placeholders and paths.
5. Add the user-facing guide at docs/guides/sla.md following the house style (see docs/guides/principles.md or docs/guides/adr.md for examples). This is the source location: python3 scripts/check-guide-parity.py --sync copies it to plugins/arckit-claude/docs/guides/, and the converter carries it into every extension's docs/guides/ tree.
6. Update CHANGELOG.md under ## [Unreleased].
Commands, Skills, Agents, and Hooks — When to Use Which
| You want to... | Use | Location |
|---|---|---|
| Generate a specific artifact on explicit invocation | Command | plugins/arckit-claude/commands/ |
| Share procedural knowledge across multiple commands | Skill | plugins/arckit-claude/skills/<skill-name>/ |
| Run heavy research in an isolated context window | Agent | plugins/arckit-claude/agents/arckit-<n>.md |
| React to lifecycle events (session start, file write, prompt submit) | Hook | plugins/arckit-claude/hooks/ |
| Override a command's behaviour on non-Claude targets only | Standalone command | plugins/arckit-claude/commands-standalone/ |
A command and an agent with matching names are linked automatically: the converter uses the agent's prompt as the command body for non-Claude targets (which lack Claude Code's agent architecture). See plugins/arckit-claude/agents/arckit-research.md paired with plugins/arckit-claude/commands/research.md for the canonical example.
Conventions
Taken from CONTRIBUTING.md. Repeated here because they matter most for commands:
- Naming: lowercase with hyphens (
data-model, notdataModel). Verbs for actions (analyse,review). Nouns for artifacts (requirements,runbook). Group related commands with shared prefixes (hld-review,dld-review). - UK English throughout (
organisation,analyse,colour). - MUST / SHOULD / MAY for normative language — aligns with the wider ArcKit tone and with GDS content design.
- Technology-agnostic — describe qualities and patterns, not specific vendors or products.
- Traceability — every generated artifact should cite its inputs (requirement IDs, risk IDs, principle IDs).
- Commit message:
feat(commands): add /arckit.<n> command.
Testing a New Command
Before opening the PR, verify the command works across at least Claude Code and one other target:
# 1. Regenerate all target files
python scripts/converter.py
# 2. Test in Claude Code (requires the plugin installed from marketplace)
/arckit.<n> Test scenario description
# 3. Test in Gemini CLI
gemini extensions install .
/arckit:<n> Test scenario description
# 4. Inspect the generated output
cat projects/001-<test-project>/ARC-001-<CODE>-v1.0.md
Check:
- [ ] The command reads the template (customised or default) correctly
- [ ] The output contains every section the template specifies
- [ ] Every reference to a source artifact uses a real ID that exists in the project
- [ ] Re-running the command with an existing output file correctly bumps the version
- [ ]
python scripts/converter.pyregenerates cleanly with no diff noise - [ ] Generated TOML and prompt files look sensible on a quick read
Submitting the PR
- Branch: pick a short descriptive name — recent history uses both
feat/anddocs/prefixes, either is fine. - Commit the source command, the template, the guide, the converter-regenerated files, and the CHANGELOG entry together.
- PR title follows conventional commits:
feat(commands): add /arckit.<n> command. - PR description should include: the use case, a link to any related issue, and at least one screenshot or pasted output showing the command running in Claude Code.
See CONTRIBUTING.md for the broader contribution process.