CtrlK
BlogDocsLog inGet started
Tessl Logo

claude-command-authoring

This skill should be used when the user asks to 'create a slash command', 'author a Claude Code command', 'decide command vs skill', 'choose project vs user scope', 'version custom commands for my team', or 'design command frontmatter'. Covers commands/*.md authoring and the command-vs-skill decision; unifies the custom-commands kata with the extension decision tree.

SKILL.md
Quality
Evals
Security

Claude Command Authoring

Author Claude Code slash commands and decide correctly between a command (explicit /x trigger) and a skill (model-activated on-demand workflow).

Official facts. [DOC]

  • Commands are merged into skills: .claude/commands/deploy.md and .claude/skills/deploy/SKILL.md both produce /deploy and behave the same. The real decision is the invocation controls (disable-model-invocation, context: fork), not "command vs skill" as separate systems.
  • allowed-tools does NOT restrict tools — it pre-approves (auto-approves) the listed tools while active; every other tool stays callable under your permissions. To limit tools use disallowed-tools or permissions.deny.

Mental Model

  • Slash command = .claude/commands/x.md, fired explicitly by typing /x.
  • Skill = .claude/skills/x/SKILL.md, activated on-demand when the model matches the description to the task.
  • Scope: project (.claude/) travels with git → reaches the whole team; user (~/.claude/) is personal and never shared. [DOC]
  • Permanent conventions belong in CLAUDE.md, not in a command or skill. [DOC]

Decision: command vs skill

ChooseWhen
CommandUser invokes an exact, explicit action by name; deterministic trigger.
SkillCapability the model should select contextually from its description.
BothA command body can delegate to a skill; keep the command thin.
CLAUDE.mdAlways-on convention — neither command nor skill.

Name collisions & nested namespacing. A skill and a command sharing a name collide; the skill takes precedence, so rename one to avoid silently shadowing the other. Commands in subdirectories namespace by path: .claude/commands/apps/web/deploy.md becomes /apps/web:deploy, keeping team variants distinct. [DOC]

Authoring a command

  1. Scope: .claude/commands/ (team, versioned) vs ~/.claude/commands/ (personal). A user-scope command does NOT replicate to the team via git. [DOC]
  2. Frontmatter: description, optional argument-hint, optional allowed-tools whitelist. Use $ARGUMENTS (full string) or positional $N in the body. $N is 0-based shorthand for $ARGUMENTS[N]: $0 is the FIRST arg, $1 the second. [DOC]
  3. Least privilege: allowed-tools only pre-approves (skips prompts). To actually prevent Write/Bash, add disallowed-tools: Write, Edit, Bash or permissions.deny. [DOC]
  4. Context economy: if the command produces verbose exploratory output, prefer a skill with context: fork so ~thousands of tokens don't pollute the main session. [DOC]
  5. Validate plugin commands with ${CLAUDE_PLUGIN_ROOT}/scripts/validate_plugin_contracts.py. The vendored validate_frontmatter.py targets SKILL.md and therefore applies the toolkit's local name requirement; it now recognizes all current official skill invocation controls, but should not be applied directly to a command file that has no name. [DOC][CONFIG]

Example: thin command delegating to a skill

# .claude/commands/changelog.md  (project scope, versionado)
---
description: "Genera el changelog entre dos tags."
argument-hint: "<tag-desde> <tag-hasta>"
allowed-tools: Read, Grep, Bash    # pre-aprueba; NO cierra Write/Edit
---
Genera el changelog de $0 a $1. Usa la skill `release-notes` para el formato;
mantén este command delgado y delega el grueso del trabajo. $ARGUMENTS

$N es 0-based: $0 es el primer argumento posicional y $1 el segundo (equivalen a $ARGUMENTS[0] / $ARGUMENTS[1]); $ARGUMENTS recibe la cadena completa. El cuerpo delega en una skill (fila Both): el command queda como trigger explícito y thin, la skill carga el detalle. [DOC]

Anti-Patterns

  • Saving a team command in user scope → teammates never receive it.
  • Believing allowed-tools closes tools — it only pre-approves; use disallowed-tools/deny.
  • Encoding a permanent rule as a command instead of in CLAUDE.md.
  • Re-explaining skill authoring here (see claude-skill-authoring).

Related

  • claude-skill-authoring — SKILL.md authoring contract.
  • custom-tooling-extension — extension decision tree + tool whitelisting.
  • katas-custom-commands-skills — the command-vs-skill kata.
  • katas-context-dilution-mitigation, katas-prefix-caching — context economy.

Sources

  • references/source-map.md — official command-authoring provenance and refresh boundary. [CONFIG]

Contract

  • Aceptación: command escrito PARA Claude, least-priv allowed-tools, argument-hint, paths portables. [EXPLICIT]
  • Límites: autoría de command; los commands se tratan como skills flat. [EXPLICIT]
  • Casos borde: elegir command vs skill — context:fork y scope cambian el comportamiento. [EXPLICIT]
  • Supuestos: auto-namespacing /<plugin>:<name> [DOC]. [SUPUESTO]
  • Trade-off: command explícito vs skill auto-activada — invocación directa vs descubrimiento. [EXPLICIT]

Packet

Capas del packet, cargables bajo demanda (disciplina ICM: una capa por vez, nunca todas juntas): references/ guías de profundidad (cargar UNA por etapa).

Repository
JaviMontano/claude-plugins
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.