Conventions claude
Use when scoring or writing Claude Code artifacts — covers .claude/ paths, plugin.json schema, command + agent + skill frontmatter, CLAUDE.md, hook events, hooks.json format, settings.json, LSP, monitors, memory file conventions, and the Claude Code built-in tool catalog. Refreshed 2026-08-02 against current docs (Claude Code ≥ v2.1.218).From its SKILL.md
npx -y skills add xiaolai/nlpm --skill conventions-claudeAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
SKILL.md
25.6 KB, as published. Nobody here has run it
Claude Code Conventions
Tool-specific overlay for Claude Code plugin artifacts. Loaded by the scorer and checker when an artifact is classified as Tier 2-Claude (per agents/scorer.md step 3). The universal floor lives in nlpm:conventions; this overlay adds Claude-Code-specific schemas on top.
Primary authoritative sources:
- https://code.claude.com/docs/en/claude_code_docs_map.md
- https://code.claude.com/docs/en/skills.md
- https://code.claude.com/docs/en/hooks.md
- https://code.claude.com/docs/en/plugins.md
- https://code.claude.com/docs/en/plugins-reference.md
- https://code.claude.com/docs/en/sub-agents.md
- https://code.claude.com/docs/en/settings.md
- https://code.claude.com/docs/en/memory.md
- https://code.claude.com/docs/en/commands.md — built-in commands + bundled skills (successor to the retired
slash-commands.md) - https://code.claude.com/docs/en/tools-reference.md — authoritative built-in tool catalog (see §16)
- https://code.claude.com/docs/en/plugin-marketplaces.md
- https://code.claude.com/docs/en/workflows.md
1. .claude-plugin/plugin.json
The plugin manifest.
Required fields:
name— string, kebab-case, unique identifier
The manifest is fully optional — artifacts auto-discover from conventional paths, and only name is required when present. Unrecognized top-level fields are ignored with a warning (error only under claude plugin validate --strict).
Optional fields:
version— semver string (e.g."0.1.0"). If omitted, commit SHA is used (every commit = new version). For stable releases, set explicit semver.description— one-line summarydisplayName— human-readable name shown in installer UI (v2.1.143+)author— object:{ "name": "...", "email": "...", "url": "..." }homepage— URL stringrepository— URL string (the docs' Metadata table types this strictly asstring; no object form is documented)license— SPDX identifierkeywords— string array for discovery$schema— URL to the manifest JSON Schema (editor validation)defaultEnabled— boolean; whether the plugin is enabled on install (v2.1.154+)userConfig— object; per-key prompts shown to the user at enable time; values exposed as${user_config.<key>}substitutionschannels— array; message-injection channel bindingsdependencies— array of other plugins this one requires (supports semver constraints)
NOT plugin.json fields (common mistake):
agent— this is a settings.json default key (a plugin's bundledsettings.jsonsupports onlyagentandsubagentStatusLine), not a manifest field.category— belongs to a marketplace.json plugin entry, not the manifest.
Artifact path fields (all optional, string or string[]):
commands— path(s) to command markdown filesagents— path(s) to agent markdown filesskills— path(s) to skill directorieshooks— path to hooks.jsonmcpServers— path(s) to MCP server configlspServers— path(s) to LSP server config (stable in 2026; schema in §12)outputStyles— path(s) to output style definitionsworkflows— path(s) to workflow script files/directories (replaces defaultworkflows/; ties to the Workflow tool)experimental.themes— path(s) to theme definitions (was top-levelthemes; now nested underexperimental)experimental.monitors— path(s) to monitor config (was top-levelmonitors; schema in §13). Top-level still works butclaude plugin validatewarns; a future release will require theexperimental.*form.
Plugin structure note: a bin/ directory in a plugin root puts its executables on the Bash tool's PATH — files there are invokable as bare commands in any Bash call while the plugin is enabled.
Example:
{
"name": "my-plugin",
"version": "0.2.1",
"description": "Does useful things",
"author": { "name": "dev" },
"license": "MIT",
"keywords": ["tools", "productivity"],
"commands": "commands/",
"agents": "agents/",
"skills": "skills/"
}
2. Commands and Skills — merged surfaces (v2.1.x change)
Critical: as of Claude Code v2.1.x, commands and skills are the same architecture. Both surfaces support the same frontmatter and execution semantics. The recommended canonical path is:
.claude/skills/<name>/SKILL.md # preferred for new development
.claude/commands/<name>.md # still works; equivalent behavior
Existing .claude/commands/ files continue to function. New code should prefer the skill layout because it allows companion files (scripts/, references/, examples/) in the same directory.
Authoritative reference: https://code.claude.com/docs/en/skills.md (command/skill frontmatter now lives here; the old slash-commands.md page was retired)
2.1 Frontmatter (shared between commands and skills)
Recommended (per official docs, the only recommended frontmatter field — all keys are technically optional):
description— string; explains what it does and when to invoke. Combined withwhen_to_use:if present. The schema treats it as optional, but a model-invoked skill with no (or a weak) description cannot trigger reliably — so nlpm scores a missing/weak description as a quality finding (R04), not a hard schema violation.
Optional (universal):
name— string; per official docs, explicitly optional. When omitted, filename or enclosing directory is used. Pre-v0.7.15 nlpm incorrectly flagged missingname:as a bug; corrected after Jeffallan/claude-skills#184 maintainer feedback.argument-hint— string; placeholder shown in UI (e.g.,"[path]")arguments— space-separated or YAML list of named arguments for$namesubstitution (e.g.,"issue branch")allowed-tools— string array OR space-separated string; pre-approved tools (no per-use prompt). Format:"Read Grep Bash(git *)"or["Read", "Grep"].disallowed-tools— string array OR space-separated string; tools removed from the pool while the skill is active.model—haiku/sonnet/opus/fable/ a full model ID /inherit(keep the active model); overrides session model for one turn.effort—low/medium/high/xhigh/max; overrides session effort.user-invocable— boolean;falsehides from menu (only Claude invokes).disable-model-invocation— boolean;truemeans only the user invokes (manual/skill-nameonly).
Optional (v2.1.x additions — NEW since pre-2026 conventions):
when_to_use— string; additional trigger hints (appends to description)context—"fork"runs in a forked subagent (isolates from main history)agent— which subagent type (built-in:Explore,Plan,general-purpose)hooks—{...}skill-scoped hooks (same shape as settings.json hooks)paths— glob patterns; auto-load only for matching files (e.g.,"src/**/*.ts,lib/**/*.ts")shell—bash(default) orpowershellfor!cmd`` blocksbackground— boolean; only meaningful withcontext: fork.falsewaits for the forked subagent's result in the invoking turn instead of backgrounding it (defaulttrue; v2.1.218+).
Boolean frontmatter fields accept yes/no/on/off/1/0 (any case) in addition to true/false (v2.1.218+). The combined description + when_to_use shown in the skill listing is truncated at 1,536 characters — keep triggers within that budget.
2.2 Body conventions
- Write imperative instructions directed at Claude (not the user)
- Use numbered steps for multi-phase workflows
- Reference shared partials by relative path:
commands/shared/name.md - Define expected output format explicitly in the body
2.3 Dynamic context injection
!`git diff HEAD`— runs command before Claude sees the skill; replaces line with output.```!fenced blocks — multi-line commands.- Disabled if
"disableSkillShellExecution": truein settings.
2.4 String substitutions (valid in command/skill bodies)
$ARGUMENTS, $ARGUMENTS[N], $N (positional), $name (named argument), ${CLAUDE_SESSION_ID}, ${CLAUDE_EFFORT}, ${CLAUDE_SKILL_DIR}, ${CLAUDE_PLUGIN_ROOT}. Do NOT flag these as undefined variables.
3. Shared Partials
Reusable shared partials located in commands/shared/.
Rules:
- MUST include
user-invocable: falsein frontmatter — prevents appearing as top-level commands - MUST have a
descriptionstating their purpose as a partial - Referenced by full relative path from the consuming command file
- Can contain any mix of instructions, templates, or decision logic
4. Agent Frontmatter
Agents live in .claude/agents/<name>.md.
The system prompt is the markdown body of the file (in --agents JSON form it is the prompt key). There is no system-prompt frontmatter key — flagging or recommending one is a bug (corrected 2026-06-07 against sub-agents.md).
Documented fields:
name— string; identifier for invocation. Cannot contain:(reserved for plugin-scoped identifiers, v2.1.218+).description— string; critical for reliable triggering — should contain 3+ specific phrases describing when to use this agenttools— tools the agent body uses; two valid formats:- JSON array:
tools: ["Read", "Glob"] - Comma-separated string:
tools: Read, Glob, Grep
- JSON array:
disallowedTools— tools removed from the inherited pool (this is the correct key — there is notool-restrictions: {allow, deny}key; the old nlpm name was wrong)model—haiku/sonnet/opus/fable/ a full ID (e.g.claude-opus-5) /inherit; defaults toinheritskills— preload skill content into this agent's context at startup. Two valid formats:- JSON array:
skills: ["nlpm:conventions"] - YAML list:
skills:\n - nlpm:conventions
- JSON array:
Convention / additional fields:
effort—low/medium/high/xhigh/maxcolor— one ofred,blue,green,yellow,purple,orange,pink,cyan; visual label.magentais NOT valid (old nlpm list had it; the current valid set addspurple,orange,pink).permissionMode—default(aliasmanual, v2.1.200+) /acceptEdits/auto/dontAsk/bypassPermissions/planisolation— only valid value"worktree"(runs the agent in a git worktree)memory—user/project/localmaxTurns— integer turn capbackground— boolean; run asynchronouslyinitialPrompt— string; seeds the agent's first turnmcpServers,hooks— agent-scoped overrides
Plugin-shipped agents are restricted: hooks, mcpServers, and permissionMode are ignored for agents distributed inside a plugin (security). Score plugin agents accordingly.
Best practice: include <example> blocks in description. Two or more <example> blocks with diverse scenarios is the minimum for reliable triggering.
5. Skills — Claude Code path conventions
Universal SKILL.md spec lives in nlpm:conventions (open spec at agentskills.io). Claude Code uses these path conventions:
- Single plugin skill:
skills/<name>/SKILL.md - Multi-skill plugin:
skills/<plugin>/<name>/SKILL.md - Project-scoped:
.claude/skills/<name>/SKILL.md - User-scoped:
~/.claude/skills/<name>/SKILL.md
Skill discovery paths now support parent-directory and monorepo nested scanning (v2.1.x). Skills from ./parent/.claude/skills/ and ./packages/frontend/.claude/skills/ auto-load. Skills from --add-dir paths also load from .claude/skills/ within added directories.
Supporting files: Same directory as SKILL.md — scripts/, references/, examples/, etc. Reference them from SKILL.md so Claude knows when to load them.
Skill preloading in agents (v2.1.x): Declare skills: [name1, name2] in agent frontmatter to inject full skill content at startup (vs. Claude auto-loading on demand).
6. Rules
Rules live in .claude/rules/<name>.md.
Frontmatter:
description— string (required)paths— string array (optional); glob patterns scoping which files this rule applies to
Body format:
- Lead with a bold imperative:
**Always do X.**or**Use Y instead of Z.** - Follow immediately with rationale
- Be specific and testable
- State what to DO, not only what to avoid (Pink Elephant effect)
Budget: Under 500 lines total per rules file.
Naming convention for ordered sets: NN-kebab-name.md (e.g. 01-formatting.md).
7. Hook Events (Claude Code)
Hook events are case-sensitive. Using wrong case silently ignores the hook.
Confirmed against 2026-06-07 docs refresh (hooks.md):
| Event | Trigger | Context fields |
|---|---|---|
SessionStart | Session begin | source (startup/resume/clear/compact), model |
SessionEnd | Session end | (trigger only) |
UserPromptSubmit | User submits a prompt | prompt text |
PreToolUse | Before any tool call | tool_name, tool_input |
PostToolUse | After tool call | tool_name, tool_input, tool_output |
PermissionRequest | When Claude requests permission | tool_name, tool_input, permission_mode |
Stop | Once per turn | reason (can set decision: block to prevent stopping) |
StopFailure | Once per turn — Claude failed to complete | reason |
FileChanged | Per file change | filename, watcher_path |
Beyond the table above, many more events are valid (SubagentStop, PreCompact, Notification, PostToolUseFailure, Setup, SubagentStart, PermissionDenied, PostCompact, TaskCompleted, MessageDisplay, …). Full allow-list → reference.md. Any documented event name is valid even if it post-dates this doc; do NOT flag as unknown — verify against hooks.md rather than penalizing.
Hook types (canonical, all lowercase in JSON):
command— shell script (stdin/stdout)http— HTTP POST endpointmcp_tool— MCP server tool invocationprompt— LLM evaluationagent— subagent verification
A command hook may add "shell": "powershell" to run that hook in PowerShell instead of the default shell.
Matcher patterns: string (exact), pipe-separated list (Bash|Edit), or regex (non-alphanumeric chars).
MCP tool naming: mcp__<server>__<tool> (e.g., mcp__memory__write.*). Hook matchers use this format.
Exit codes (command hooks):
0— success (stdout to debug log; forUserPromptSubmit,UserPromptExpansion, andSessionStart, stdout is injected as context)2— blocking error (action denied, stderr fed to Claude) — only on blockable events. Non-blockable events ignore exit 2:PostToolUse,PostToolUseFailure,Notification,SessionStart,SessionEnd,InstructionsLoaded,StopFailure,MessageDisplay,SubagentStart,Setup,CwdChanged,FileChanged,PostCompact,WorktreeRemove,PermissionDenied(onPermissionDenied, use JSONretry: truerather than exit 2).1, 3+— non-blocking error (logged in debug only)
8. hooks.json Format
Located at .claude/hooks.json or <plugin>/hooks/hooks.json.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/pre-write-check.sh"
}
]
}
],
"SessionStart": [
{
"matcher": "",
"hooks": [
{
"type": "prompt",
"prompt": "You are now in strict TDD mode."
}
]
}
]
}
}
Structure rules:
- Top-level key:
"hooks" - Second-level keys: event names (case-sensitive)
- Each event maps to an array of matcher objects:
{ "matcher": "<regex>", "hooks": [...] } - Each hook object:
{ "type": "command"|"http"|"mcp_tool"|"prompt"|"agent", "<type-field>": "..." } - Field name matches the type:
"command"for typecommand,"prompt"for typeprompt, etc.
Optional hook-object fields (current — do NOT flag as malformed): if (Bash-pattern, permission-scoped condition), timeout (seconds), statusMessage, once (v2.1+; skills/agents only), exec-form args (array, as an alternative to shell-form command), and async / asyncRewake for background command hooks.
9. .mcp.json
Claude Code reads MCP server registrations from a standalone JSON file at the repo root (NOT embedded in settings.json like Gemini, NOT inside config.toml like Codex).
{
"mcpServers": {
"my-server": {
"type": "stdio",
"command": "node",
"args": ["./server.js"]
}
}
}
Plugin scope: <plugin>/.mcp.json at the plugin root, or inline in plugin.json under mcpServers. (Only the plugin-root form is documented; the older .claude-plugin/.mcp.json variant is not.)
10. CLAUDE.md (memory file)
Four memory scopes load in order (managed policy → user → project → local):
| Scope | Path | Notes |
|---|---|---|
| Managed policy | OS-specific managed path (e.g. /Library/Application Support/ClaudeCode/CLAUDE.md) | org-wide, set by administrators |
| User | ~/.claude/CLAUDE.md | personal, applies to all projects |
| Project | ./CLAUDE.md or ./.claude/CLAUDE.md | shared, committed |
| Local | ./CLAUDE.local.md | gitignored personal overrides for this repo |
Auto-memory is a separate system at ~/.claude/projects/<slug>/memory/ (see §15) — there is no .claude/memory/*.md convention.
Recommended pattern for multi-tool projects (per analysis/multi-tool-design-2026-05.md decision #5): use a one-line CLAUDE.md that imports AGENTS.md:
@AGENTS.md
This makes AGENTS.md the canonical universal memory file. AGENTS.md is what Codex reads natively; Gemini/Antigravity can be configured to read it via context.fileName array. This is how nlpm itself works.
Body conventions when content lives in CLAUDE.md directly:
- Build/run instructions
- Test commands
- Architecture overview (what lives where)
- Prerequisites section
- Valid
@-imports must reference existing files
11. .claude/settings.json and .claude/settings.local.json
| Field | Purpose |
|---|---|
permissions | Permission policy (allow/deny rules, modes); incl. permissions.additionalDirectories |
hooks | Hook event registrations (alternative to hooks/hooks.json for project-scoped hooks) |
model | Default model selection |
disableSkillShellExecution | If true, disables !...`` and ```! dynamic blocks in skills |
env | Environment variables injected into the session |
statusLine | Custom status line command/config |
agent | Default agent (also the only default-settings key, besides subagentStatusLine, a plugin may set) |
effortLevel | Default effort |
language, outputStyle | Locale / output style defaults |
enabledPlugins | Plugins enabled for the project |
claudeMd, claudeMdExcludes | Extra memory file globs / exclusions. claudeMd is honored only in managed/policy settings — it has no effect in user/project/local settings. |
skillOverrides | Per-skill visibility from settings (keys = skill name; values on / name-only / user-invocable-only / off); overrides the skill's own frontmatter |
pluginConfigs | Stores non-sensitive plugin userConfig values under pluginConfigs[<plugin-id>].options |
autoMemoryEnabled, autoMemoryDirectory | Auto-memory toggle + location (see §15) |
sandbox.enabled | Sandbox execution toggle |
extraKnownMarketplaces, strictKnownMarketplaces | Marketplace trust config |
themeis not a documentedsettings.jsonfield — do not flag its absence or treat it as valid here (removed from this list 2026-06-07). The above is representative, not exhaustive; treat unrecognized-but-plausible keys as advisory, not errors.
Rule: .local.json is gitignored (per-user); the non-local file is shared. NEVER set bypassPermissions: true in the shared file.
12. LSP Servers (.lsp.json)
Stable in 2026 (was experimental in 2025). .lsp.json file, or a lspServers object in plugin.json. Required fields command + extensionToLanguage. Full per-server schema → reference.md.
13. Monitors (monitors/monitors.json)
Experimental — lives under experimental.monitors (§1); its manifest schema may change between releases while it stabilizes. Plugin background watchers; requires v2.1.105+. Per-entry required name + command + description. Full schema → reference.md.
14. Reference Syntax
Commands referencing shared partials:
<!-- Include: commands/shared/discover.md -->
Or by instruction: "Follow the steps in commands/shared/discover.md"
Agents referencing skills in frontmatter:
skills: ["nlpm:conventions", "nlpm:conventions-claude"]
Hooks referencing scripts:
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/check.sh"
Always use ${CLAUDE_PLUGIN_ROOT} for intra-plugin file references. Hardcoded absolute paths break portability.
Cross-plugin skill references use the same plugin:skill format. The plugin must be installed for the reference to resolve.
15. Memory File Conventions (~/.claude/projects/<slug>/memory/)
Claude Code writes per-project persistent memory at ~/.claude/projects/<project-slug>/memory/ ("Auto memory", v2.1.59+). Toggled by autoMemoryEnabled; location overridable via autoMemoryDirectory (§11). At session start the first ~200 lines / 25 KB of MEMORY.md plus topic files are loaded into context.
Index file: MEMORY.md (no frontmatter; one-line-per-entry index).
Individual memory files MUST include YAML frontmatter:
---
name: "short identifier"
description: "one-line summary"
type: user | feedback | project | reference
---
type values:
| Value | Meaning |
|---|---|
user | Preferences, habits, or facts about the user |
feedback | Corrections or lessons from past sessions |
project | Project-specific facts, decisions, or context |
reference | External reference material copied into memory |
Rules:
- Every memory file must appear in
MEMORY.md(orphans are flagged). MEMORY.mditself is the index; not scored as a memory file.- Memory files should not reference removed files or functions.
16. Claude Code Tool Catalog
Tool names valid in tools:, allowed-tools:, disallowed-tools:. Never flag a well-formed tool name as "unknown" or "undocumented" — the catalog grows and any string matching Pascal-name or mcp__<server>__<tool> patterns is valid. Key renames: Task → Agent (alias kept); MultiEdit, BashOutput, KillBash removed; TodoWrite default-off (→ Task* family); SlashCommand folded into Skill.
Full catalog — built-in tools, renames/removals, MCP naming → reference.md. Authoritative source: code.claude.com/docs/en/tools-reference.md.
17. Plugin distribution
Marketplace manifest: .claude-plugin/marketplace.json at the marketplace repo root. Required top-level: name, owner (maintainer-info object), plugins. Optional: $schema, description, version, metadata.pluginRoot, renames. Per-plugin entries may add category, tags, strict, relevance, defaultEnabled. Full schema, source types, and renames/strict semantics → reference.md.
Plugin from URL (v2.1.x): --plugin-url and --plugin-dir flags accept .zip archives.
Namespacing: plugin skills, commands, and agents are all namespaced under the plugin — /my-plugin:hello for skills/commands, my-plugin:code-reviewer in the @-mention typeahead for agents. Prevents conflicts.
18. Scope and uncertainty
This skill covers Claude Code conventions. It does NOT cover:
- Universal SKILL.md spec →
nlpm:conventions - Penalty tables →
nlpm:scoring
Resolved in the 2026-08-02 refresh (no longer uncertain):
- Hook event lists verified 30/30 against current
hooks.md(§7); exit-code non-blocking list completed. descriptionis Recommended, not Required (§2.1);fablemodel alias +claude-opus-5example added (§2.1, §4).- Memory scopes corrected to managed/user/project/local; the bogus
.claude/memory/*.mdclaim removed (§10, was self-contradictory with §15). - Monitors reclassified experimental (§13); LSP confirmed genuinely stable (§12).
marketplace.jsonrequiredowner+strict/renamesfolded into §17; namespacing corrected (agents/commands are namespaced too).slash-commands.mdcitation retired forskills.md/commands.md.- Version gates v2.1.142 (
TodoWritedefault-off) and v2.1.154 (defaultEnabled) confirmed literal in current docs.
Still approximate (verify before citing a specific tag):
- Exact version pins beyond v2.1.218 (highest gate observed); no single current top-level Claude Code version is stated in the docs.
- Whether a
languagesettings.json key still exists — not found in repeated fetches, but the source page returned inconsistent partial coverage, so it is NOT dropped on that evidence alone. - Whether
.claude/rules/frontmatter recognizes adescriptionfield (§6) — not shown in any current docs example; unverified this pass.