# Primitive Catalog

> Decision cards for selecting Claude Code primitives while designing a plugin - skill vs hook vs subagent vs agent team vs MCP server vs bundled script vs LSP vs workflow vs loop. Load during any plugin architecture or composition discussion, when writing a Primitive Decision Record (design/CONTRACT.md), filling six-step consequence chains (trigger, context economics, enforcement, failure modes, testability, distribution), choosing who holds the plan, picking a loop primitive (/goal vs Stop hook vs /loop vs schedule), or deciding MCP-versus-bundled-script. Cards carry exact syntax, version floors, context costs, failure modes, and the grader type that can observe each primitive.

- Skill: `aznatkoiny/primitive-catalog` (Agent Skill, multi-file: 13 files)
- Install (CLI): `npx skillmds@latest add aznatkoiny/primitive-catalog`
- Raw SKILL.md: https://api.skillmd.com/api/skills/aznatkoiny/primitive-catalog/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: aznatkoiny (https://skillmd.com/u/aznatkoiny)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/aznatkoiny/primitive-catalog

---


# Primitive catalog — the decision layer for plugin composition

Use this catalog while drafting a Primitive Decision Record (PDR) in `design/CONTRACT.md`. Each card in
`references/cards/` is a decision-oriented distillation: exact syntax, version floors, context costs, and
failure modes. For exhaustive syntax the cards point to the official Claude Code docs
(https://code.claude.com/docs — fetch llms.txt for the page index) — never duplicate that
encyclopedia here.

Rules of use:
- Answer every loaded card's **Consequence prompts** in the PDR chain columns C1–C6 before committing to that primitive.
- When a card's **Reject when** criteria match, record the rejection as that capability's rejected alternative, naming the chain step that killed it.
- When a card's **Eval hooks** section cannot name a grader that observes the primitive in the target design, the choice is unverifiable → unbuildable (the C5 hard gate).

## Master rubric 1 — who holds the plan

Escalate only as far as the capability demands; every step up costs tokens, latency, or interactivity.

| Level | Who holds the plan | Intermediates live in | Repeatable unit | Scale | Pick when |
|---|---|---|---|---|---|
| Main conversation | Claude, turn by turn | Main context | Nothing | 1 thread | Frequent back-and-forth; phases share context |
| Skill (inline) | The SKILL.md prompt | Main context | The instructions | 1 thread | Repeatable process knowledge; standing rules |
| Subagent | Delegation prompt + agent body | Subagent context; summary returns | The agent definition | A few parallel | Verbose-output isolation; tool restriction; clean expert lens |
| Forked skill (`context: fork` / `/subtask`) | SKILL.md as the fork's prompt | Fork context (inherits conversation; shares prompt cache) | The skill | A few parallel | Side task needs the accumulated conversation state |
| Agent team | Lead + shared task list | Task list + mailboxes (`~/.claude/tasks/`) | Subagent definitions as roles | 3–5 peers, 5–6 tasks each | Workers must discuss/challenge each other; file-partitioned parallel builds |
| Workflow | The JS script | Script variables | The orchestration script itself | Dozens–hundreds (16 concurrent, 1000/run) | Homogeneous fan-out; intermediates would overflow context |

## Master rubric 2 — loop primitives

| Primitive | Next turn fires | Stops when | Persists | Can a plugin ship it? |
|---|---|---|---|---|
| `/goal <condition>` | When the previous turn finishes | Tool-less small-model evaluator judges the condition true from the transcript alone | Session only (survives `--resume`, counters reset) | **No** — session command (v2.1.139+; needs trust + hooks enabled) |
| `/loop` | On a time interval | User or model decides | Session only | **No** |
| Stop hook (prompt/agent type) | When the previous turn finishes | Per the hook's script/prompt verdict | Its settings scope — survives sessions | **Yes** — via `hooks/hooks.json`; the productized `/goal` |
| Schedule (cloud routine / scheduled task) | On cron, independent of open sessions | Per schedule | Account/repo level | Plugin ships the skill it invokes, not the schedule |

A plugin cannot ship `/goal` itself. The distributable equivalent is a prompt- or agent-type Stop hook in
`hooks/hooks.json` (honoring `stop_hook_active` and the 8-block cap, `CLAUDE_CODE_STOP_HOOK_BLOCK_CAP`),
plus documented "goal recipes" — pre-written ≤4,000-char conditions users paste into `/goal`. Note:
scheduled tasks cannot invoke `disable-model-invocation: true` skills (v2.1.196+). Full loop mechanics:
`references/cards/loops-card.md`.

## Master rubric 3 — MCP server vs bundled script

```
Does the capability need persistent connection state, OAuth to a remote API,
server push (channels), elicitation dialogs, MCP resources/prompts, or a large
tool surface (tool search scales)?
├─ YES → bundle an MCP server (.mcp.json at plugin root)      → mcp-card.md
└─ NO
   ├─ One-shot computation or CLI call, no connection state
   │    → bundled stdlib script + skill with
   │      allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/x.sh *)
   │      (zero prompts, no server lifecycle, no approval dialog,
   │       no timeout design, headless-safe)                   → skills-card.md
   ├─ Long-running local watch (tail a log, poll a queue)      → monitors-bin-card.md
   └─ CLI users should call directly by name                   → bin/ on PATH, monitors-bin-card.md
```

Default to the script. MCP must earn its lifecycle cost: approval prompts, trust dialogs, timeout/idle
design, headless auth preflight, and stdio's never-reconnects failure mode.

## Card index

Load only the cards relevant to the candidate compositions under discussion.

- **`references/cards/skills-card.md`** — load when any capability could be a skill or command: invocation-control matrix (`disable-model-invocation` vs `user-invocable`), 1,536-char description cap and 1% listing budget, arguments, the `!`-backtick dynamic injection and its policy fallback, `context: fork` narrowing, 5k/25k compaction budgets, `paths` scoping, model/effort routing, stacking stop rule.
- **`references/cards/hooks-card.md`** — load when behavior must be *enforced* rather than suggested, or automated at a lifecycle point: 30-event catalog with per-event matcher vocabulary, five executor types and their selection rule, exit-code discipline, per-event output schemas, Stop-loop mechanics, headless gaps.
- **`references/cards/agents-teams-card.md`** — load when delegating to subagents or coordinating an agent team: plugin frontmatter stripping and its two workarounds, background 19-tool filter, `memory: project`, `isolation: worktree` base-branch gotcha, dual-mode bodies, resume-via-SendMessage, team task DAGs, plan approval, TaskCompleted gates.
- **`references/cards/mcp-card.md`** — load when integrating external systems: transport selection, plugin-scoped tool naming, tool search and 2KB instruction discovery, timeouts and backgrounding, tools vs resources vs prompts vs elicitation vs channels, headless auth preflight, and the honest MCP-apps status note.
- **`references/cards/lsp-card.md`** — load when the target plugin serves a programming language and post-edit diagnostics or code navigation would help: configure-never-bundle rule, official-plugin dependency route, first-server-wins, diagnostics toggle.
- **`references/cards/workflows-card.md`** — load when a capability fans out over many homogeneous items: `agent()`/`pipeline()` with schema and label, 16/1000 caps, resume replay order, the ultracode-never-fires-headless trap, always-pair-with-a-script rule.
- **`references/cards/loops-card.md`** — load when a capability is "keep working until done": `/goal` condition authoring, evaluator mechanics, shipped Stop-hook productization, `/loop`, ralph/karpathy outer-loop patterns.
- **`references/cards/headless-card.md`** — load when anything must run under `claude -p` (CI, evals, routines): `--bare` hermeticity, output formats, `--json-schema`, `system/init` gating, permission rule syntax, session chaining.
- **`references/cards/worktrees-card.md`** — load when work needs filesystem isolation: `--worktree` lifecycle, `-p` never cleans up, `worktree.baseRef`, `.worktreeinclude`, sharing semantics.
- **`references/cards/monitors-bin-card.md`** — load for long-running background watchers (`monitors/monitors.json`, `when: on-skill-invoke`) and `bin/` executables added to the Bash PATH.
- **`references/cards/output-styles-settings-card.md`** — load when the plugin needs a persona shift or fleet display: output styles vs CLAUDE.md vs agents, `force-for-plugin`, plugin `settings.json` (`agent`, `subagentStatusLine` only).
- **`references/cards/distribution-card.md`** — load when deciding install level and lifecycle: marketplaces, version strategy (SHA vs pinned semver), `dependencies`, renames, seed dirs for CI, cloud-session declaration.

