CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Overview
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Repository Overview
This is a starter template repository providing a complete development environment for Claude Code with pre-configured MCP servers and tools. It is a configuration-only repository with no application code.
Architecture
Three integrated components:
- Claude Code (
.claude/): Project settings (settings.json), statusline scripts, and sync infrastructure - kk plugin (
klaude-plugin/): Skills, commands, hooks, and utility scripts — distributed via the Claude Code plugin system - Serena (
.serena/): Semantic code analysis via LSP — language detection, gitignore integration, tool exclusions (project.yml)
For API keys and MCP server setup, see the "MCP Server Configuration" section in README.md.
Testing
Tests for the template-sync feature are in test/. Run with:
for test in test/test-*.sh; do $test; done
Tests use shared utilities from test/helpers.sh. See that file for available assertions and helpers.
Troubleshooting
See README.md for detailed troubleshooting of MCP connection issues, Serena language detection, and template sync problems.
Skill & Command Naming Conventions
Applies when creating or renaming kk-plugin skills and commands.
Skills
- Imperative verbs over noun phrases.
designnotanalysis-process,implementnotimplementation-process. Drop filler suffixes like-process. Skills are invoked as/skill-name— shorter names are faster to type. - Self-documenting over acronyms.
chain-of-verificationbeatscove. If the name requires expansion to understand it, it's the wrong name. - Family prefixes for grouped skills. When multiple skills do the same action on different targets, share a prefix:
review-design,review-spec,review-code. Tab-completion, discoverability, and mental grouping all benefit. - Reference bare in prose. Inside skill/command files, reference other skills without the
kk:prefix (e.g.,`review-code`not`kk:review-code`). Thekk:prefix is for command invocations, not prose references.
Commands
Commands live under klaude-plugin/commands/<name>/. For skills with standard + isolated modes:
default.md— standard variant, invoked as/kk:<name>:defaultisolated.md— isolated sub-agent variant, invoked as/kk:<name>:isolated
Symmetric naming avoids stuttering (/kk:cove:cove → /kk:chain-of-verification:default).
Agents
Agent names describe the role, not the skill that invokes them. code-reviewer, design-reviewer, spec-reviewer persist across skill renames. Don't rename agent files when renaming the skills that delegate to them.
Shared instructions
Instructions referenced by more than one skill live in klaude-plugin/skills/_shared/<name>.md with a bare basename (e.g., review-scope-protocol.md, pal-codereview-invocation.md).
Each consuming skill gets a per-skill symlink at klaude-plugin/skills/<skill>/shared-<name>.md pointing to ../_shared/<name>.md. Reasons:
- Markdown links inside a skill stay local —
[shared-foo.md](shared-foo.md)resolves without../path traversal, which keeps links working when the skill is bundled/copied. - The
shared-prefix in the skill directory makes it obvious at a glance which files are shared vs skill-specific. - Only symlink into skills that actually reference the file — don't blanket-symlink.
When adding a new shared instruction:
- Create
klaude-plugin/skills/_shared/<name>.md(bare basename, noshared-prefix on the source file). - In each consuming skill directory, run
ln -s ../_shared/<name>.md shared-<name>.md. - Reference it in skill docs as
[shared-<name>.md](shared-<name>.md). - Agents (in
klaude-plugin/agents/) can't use the per-skill symlink pattern — reference shared files by their repo-relative path:klaude-plugin/skills/_shared/<name>.md.
When renaming
- Update
test/test-plugin-structure.shEXPECTED_SKILLSandEXPECTED_COMMANDS. - Don't touch
run_plugin_migration'sdirs_to_removein.github/scripts/template-sync.sh— those are historical paths for cleaning up pre-v0.5.0 downstream projects. They must stay as the names that existed at migration time. - Leave
docs/done/**untouched — it's frozen history. - Watch for substring collisions (e.g., a
design-review→review-designrename will also hit thedesign-revieweragent name via simple sed; hand-fix those).
Skill description budget
Claude Code loads skill descriptions into context so the model can pick the right skill. Two caps apply (see Claude Code docs — Skill descriptions are cut short):
- Per-entry cap: 1,536 characters. Each skill's
description+when_to_usecombined text is truncated at 1,536 characters regardless of the global budget. - Global context budget. Scales dynamically at 1% of the context window, with a fallback of 8,000 characters. Override via the
SLASH_COMMAND_TOOL_CHAR_BUDGETenvironment variable. When many skills are loaded, each description's share of the budget shrinks — trailing content gets stripped first.
OpenCode's documented limit for the same field is 1024 characters. For portability across both harnesses, treat 1,024 as a soft budget for skills that must work on both; stay under 1,536 at a minimum.
Authoring rules:
- Lead with trigger keywords. Truncation happens at the tail, so the decisive "when to invoke this" words must come first.
- Front-load the key use case. The Claude Code docs' own guidance — one concrete TRIGGER phrase beats a paragraph of hedging.
- Keep descriptions tight. Detailed rules, cascades, and examples belong in the SKILL.md body, not the description.
When touching a skill description in the future, re-check the docs page linked above in case the caps have shifted.
Skill workflow ordering — instructions before action
Applies to every plugin skill. The canonical failure example surfaced in review-code, but the rule is universal. See ADR 0004 for the full rationale and the failure transcripts.
Core rule: a skill MUST fully load its instructions before taking any action on its subject matter.
- Instructions =
SKILL.md+ every process/rubric/protocol file it links + every per-skill symlinked shared instruction + (for profile-driven skills) every profile file the detection procedure resolves. - Action on subject matter = reading diff/file content, editing code, engaging with idea prose beyond detection keywords, running tests, emitting documentation, producing findings.
- Minimal early scope is permitted — enough to drive profile detection. Examples:
git diff --statfor filenames, a feature-directory listing, a keyword scan of idea prose. Content-level reading is blocked until instructions are fully loaded. - Content-level read instructions appear exactly once in the workflow, after the instruction-load steps. Restating them earlier — even as a "Preflight" step — re-creates the failure mode.
Profile-driven skills have an additional specialization: profile content (resolved checklists, gotchas, rubrics, validator lists) is part of "instructions". Every (profile, <phase>/<content>) pair the detection procedure resolves is read via the Read tool before content-level subject-matter reading — index entries alone are not enough.
Authoring requirements for every skill:
- Mandatory-order directive at the top of SKILL.md's Workflow section, explicitly stating that the flow is strictly sequential and subject-matter action is blocked until instructions are loaded. Name the rule by intent, not by step numbers — step numbers drift; intent does not.
- Workflow phase summary in SKILL.md matches the detailed process file. A reader who skims SKILL.md must not see a different ordering than the process file prescribes.
- Dedup pass. After drafting, grep the skill directory for repeated content-read instructions — if the same
git diff/Readstep appears twice, collapse to one instance at the post-instruction position.
Sub-agents delegated by skills (in klaude-plugin/agents/) inherit the same rule. Payload delivery order (the spawning skill passing instructions and subject matter in the same prompt) is not sufficient — the sub-agent's own workflow must read instructions before acting, or the LLM will re-create the shortcut on its side.
Skill evaluations
Skills with non-trivial decision logic (routing, detection, conditional loading) should ship evaluation scenarios under klaude-plugin/skills/<skill>/evals/. Evals are spec files — no built-in harness exists (Anthropic docs — Evaluation and iteration) — but they give a reviewer or future harness an objective rubric to grade against.
Directory layout:
klaude-plugin/skills/<skill>/evals/
<eval-name>/
eval.json # scenario definition
test-files/ # real fixtures (YAML, code, configs, …)
…
One directory per eval, not a single evals.json. Skills that detect on paths or directory adjacency (e.g., review-code → values* adjacent to Chart.yaml, templates/ ancestor chains, kustomization.yaml filename signal) can only be exercised against real filesystem structure. Inline-in-prompt fixtures force the evaluator to describe directory layout in prose, which tests pattern-matching on prose rather than the detection logic. Real fixtures are also syntax-highlightable, validatable (kubeconform, helm lint, go build), and trivial to edit — YAML embedded in JSON strings as \ -escaped text is not.
eval.json schema:
{
"id": 1,
"name": "eval-name-kebab-case",
"description": "One-sentence summary of what this eval tests.",
"skills": ["skill-name"],
"prompt": "The natural user prompt that triggers the skill.",
"trap": "The failure hypothesis — what a model is likely to get wrong.",
"files": ["test-files/foo.yaml", "test-files/bar.yaml"],
"assertions": [
{ "id": "1.1", "text": "Specific, graded behavior bullet." },
{ "id": "1.2", "text": "…" }
]
}
skills,prompt,filesfollow the Anthropic best-practices format so a future harness aligned with that spec can ingest these evals.trapand numbered{id, text}assertions are borrowed from samber/cc-skills-golang — the trap sharpens intent (which failure mode is this eval testing?); numbered assertions make manual grading and failure reports traceable.assertions[].idfollows<eval-id>.<n>— eval 1's assertions are1.1, 1.2, …; eval 2's are2.1, 2.2, ….
When to author evals. Proactively, for skills with detection/routing logic where false positives and false negatives both matter; for skills with conditional content loading; and include at least one regression eval proving the skill does NOT activate (or falls back to default behavior) when it shouldn't. Skip for trivial skills whose behavior is captured by the skill's markdown alone.
Running. No built-in harness. A reviewer (or a future harness) stages the eval's test-files/ where the skill expects input, sends prompt with the target skill available, and grades the response against each assertion. Keep per-eval directories self-contained so the harness has zero external dependencies.
Profile Conventions
Applies when authoring profiles under klaude-plugin/profiles/. Profiles make per-domain concerns (programming languages, IaC DSLs, config schemas) available to every phase of the design → implement → review-code → test → document flow.
Directory layout
Every profile lives at klaude-plugin/profiles/<name>/ and follows the same shape:
klaude-plugin/profiles/<name>/
DETECTION.md # authoritative trigger rule (required)
overview.md # human-readable summary + dependency-lookup targets (required)
review-code/ # per-phase subdirectory (populated as needed)
index.md # router; see §`index.md` contract
<content files>
design/
implement/
test/
document/
review-spec/
Not every profile populates every phase — a programming-language profile may only need review-code/; an IaC profile like k8s populates all six. A phase subdirectory contains only its index.md and the files the index references; human-facing authoring notes belong in overview.md or a sibling file at the profile root.
DETECTION.md — schema
DETECTION.md is the single authoritative source for "when does this profile activate". It has three mandatory sections (every heading must be present even when its body is empty) and one optional section:
## Path signals— path globs that promote a file to a candidate. Fast pre-filter only; not authoritative on their own.## Filename signals— literal filenames or filename globs. Authoritative: any match activates the profile.## Content signals— content-inspection rules (anchors, regexes, key presence). Authoritative for files not already caught by filename signals. Bounded inspection (~16 KB per file; multi-document YAML inspected per----separated block).## Design signals(optional) — enables design-phase detection for profiles that participate before code exists. Containsdisplay_name(human-readable label for confirmation prompts) andtokens(keyword list matched against idea prose). Not required; not asserted by the structure test. Only relevant to profiles that need design-phase activation.
Two dimensions, different orders. Signals are evaluated in cost order (path → filename → content) but authority runs filename ≈ content > path — filename and content are equally authoritative; filename resolves first only because it is cheaper to evaluate (a filename match short-circuits content inspection for that file). A file caught only by a path signal does not activate the profile.
Consumers invoke klaude-plugin/skills/_shared/profile-detection.md (via the per-skill symlinks shared-profile-detection.md) — they do not replicate per-profile logic.
index.md contract — bidirectional invariant
Each phase subdirectory's index.md is the contract between the profile and the consuming skill. It has two sections:
- Always load. Files loaded whenever the profile is active. Each entry: markdown link + one-line description.
- Conditional. Files loaded only when a stated trigger matches. Each entry: link + description + an explicit Load if: clause naming con