ADR-0015: Markdown-Native Configuration — Eliminate .claude-plugin-design.json
Context and Problem Statement
The design plugin currently stores runtime configuration in .claude-plugin-design.json — tracker choice, branch conventions, PR conventions, worktree settings, and review settings. This creates a split source of truth with CLAUDE.md, which already carries architecture context and instructions that Claude Code interprets natively. How should the plugin consolidate configuration into a single, conflict-resistant, human-readable format that leverages Claude Code's existing capabilities?
Three production projects (spotter, joe-links, claude-ops) exposed two concrete failures of JSON config:
- Split truth: Developers had to keep
.claude-plugin-design.jsonandCLAUDE.mdsynchronized. When they diverged, agent behavior became unpredictable — one source said "use GitHub Issues" while the other referenced Gitea. - Merge conflict hotspot: In claude-ops,
.claude-plugin-design.jsonwas modified by every single parallel PR in a sprint. It was the #1 merge conflict source across all three repos because every agent that ran/design:workor/design:planupdated shared fields in the same JSON file.
Decision Drivers
- Single source of truth: Configuration and architectural context should live in one place, not two
- Leverage existing platform capabilities: Claude Code already recursively loads
CLAUDE.mdfrom subdirectories — multi-module/workspace support should come for free, not require a custom config resolver - Eliminate the #1 conflict source: Parallel agents modifying a shared JSON file caused guaranteed merge conflicts in every production project
- Human readability: Configuration should be readable and editable by humans without tooling — markdown is universally understood
- No false determinism: JSON schema validation suggests machine-parseable precision, but Claude is interpreting the values as natural language regardless — the JSON structure adds ceremony without adding determinism
- Migration simplicity: Existing users need a clear, low-friction path from JSON to markdown
Considered Options
- Option 1: Keep
.claude-plugin-design.jsonwith JSON Schema validation - Option 2: YAML configuration file (
.claude-plugin-design.yml) - Option 3: TOML configuration file (
.claude-plugin-design.toml) - Option 4: Structured markdown sections in
CLAUDE.md(chosen)
Decision Outcome
Chosen option: "Option 4 — Structured markdown sections in CLAUDE.md", because Claude Code already loads and interprets CLAUDE.md natively, including recursive loading from subdirectories. Moving configuration into CLAUDE.md eliminates the split truth problem entirely, removes the #1 merge conflict source, and gives workspace/multi-module support for free through Claude Code's existing recursive CLAUDE.md resolution. The markdown format matches how Claude actually consumes the data — as natural language instructions — rather than pretending JSON adds machine precision to values that are interpreted by an LLM.
Consequences
- Good, because single source of truth — all plugin configuration and architectural context live in
CLAUDE.md - Good, because recursive
CLAUDE.mdloading enables workspace and multi-module support without custom config resolution logic - Good, because eliminates the #1 merge conflict source —
CLAUDE.mdis less likely to be modified by every parallel agent since it carries stable, rarely-changing configuration - Good, because human-readable and editable without JSON tooling or schema knowledge
- Good, because Claude Code sessions automatically pick up configuration without requiring explicit config-loading logic in skills
- Good, because version-controlled and diffable — markdown diffs are cleaner than JSON diffs
- Bad, because less structured than JSON — there is no schema validation to catch typos in configuration keys (mitigated by Claude's natural language understanding, which tolerates minor variations like "branch prefix" vs "prefix")
- Bad, because migration is required for existing users who have
.claude-plugin-design.jsonin their repos (mitigated by a one-time migration in/design:initthat reads the JSON and writes equivalent CLAUDE.md sections) - Neutral, because the configuration format is now coupled to Claude Code's
CLAUDE.mdconvention — if Claude Code changes its file loading behavior, the plugin must adapt
Confirmation
Implementation will be confirmed by:
- All skills read configuration from
CLAUDE.mdsections instead of.claude-plugin-design.json /design:initwrites configuration as structured markdown sections inCLAUDE.mdinstead of generating a JSON file/design:initdetects existing.claude-plugin-design.jsonfiles and offers to migrate them toCLAUDE.mdsections- Workspace projects with per-module
CLAUDE.mdfiles correctly resolve module-specific configuration - No skill references
.claude-plugin-design.jsonfor reading or writing configuration - Running
/design:workwith parallel agents no longer produces merge conflicts on the configuration file
Pros and Cons of the Options
Option 1: Keep .claude-plugin-design.json with JSON Schema Validation
Retain the JSON config file but add a formal JSON Schema for validation and editor autocompletion.
- Good, because JSON is a well-understood structured format with tooling support (schema validation, editor autocompletion)
- Good, because no migration needed — existing users keep their current setup
- Good, because structured format makes programmatic reading/writing straightforward
- Bad, because split truth persists — two config sources (
CLAUDE.md+ JSON) that must stay synchronized - Bad, because JSON schema validation adds false determinism — Claude interprets values as natural language regardless of whether they pass schema validation
- Bad, because remains the #1 merge conflict source — every parallel agent still modifies the same JSON file
- Bad, because does not support workspaces — a single JSON file at the project root cannot express per-module configuration without inventing a custom module-resolution scheme
Option 2: YAML Configuration File
Replace .claude-plugin-design.json with .claude-plugin-design.yml for more human-readable structured config.
- Good, because YAML is more human-readable than JSON (supports comments, less syntactic noise)
- Good, because structured format with established tooling and schema validation options
- Neutral, because slightly better merge behavior than JSON (YAML diffs are cleaner) but still a separate file that parallel agents would modify
- Bad, because still creates split truth with
CLAUDE.md— two config sources instead of one - Bad, because still a merge conflict target when multiple agents modify it concurrently
- Bad, because YAML has well-known footguns (implicit type coercion, the Norway problem, significant whitespace)
- Bad, because does not leverage Claude Code's recursive
CLAUDE.mdloading for workspace support
Option 3: TOML Configuration File
Replace .claude-plugin-design.json with .claude-plugin-design.toml.
- Good, because TOML has clear, unambiguous syntax with explicit typing
- Good, because supports comments and is human-readable
- Good, because table-based structure maps cleanly to the existing config sections (tracker, branch, PR, review)
- Bad, because still creates split truth with
CLAUDE.md - Bad, because still a merge conflict target for parallel agents
- Bad, because TOML is less universally familiar than markdown or JSON — adds a learning curve
- Bad, because does not leverage Claude Code's recursive
CLAUDE.mdloading
Option 4: Structured Markdown Sections in CLAUDE.md
Eliminate the config file entirely. Move all configuration into ### Design Plugin Configuration sections within CLAUDE.md, using markdown lists and tables.
- Good, because single source of truth — configuration lives alongside architectural context in
CLAUDE.md - Good, because Claude Code's recursive
CLAUDE.mdloading from subdirectories provides workspace support for free - Good, because eliminates the merge conflict hotspot —
CLAUDE.mdcarries stable configuration that does not change per-PR - Good, because the format matches how Claude actually consumes the data — as natural language
- Good, because no additional tooling, schema files, or file format knowledge required
- Neutral, because configuration structure is conventional rather than enforced — relies on section headings and list formatting rather than schema validation
- Bad, because configuration mixed with other
CLAUDE.mdcontent could become cluttered in large projects (mitigated by using a dedicated### Design Plugin Configurationsection with clear subsection headings) - Bad, because no programmatic validation of configuration values without parsing markdown (mitigated by Claude's tolerance for natural language variations)
Architecture Diagram
More Information
- The
CLAUDE.mdconfig structure uses a### Design Plugin Configurationheading with subsections for Tracker, Branch Conventions, PR Conventions, and Review settings. Each subsection uses markdown lists with bold keys (e.g.,- **Type**: gitea). See the plan document for the full example structure. - Migration from
.claude-plugin-design.jsonwill be handled by/design:init, which will detect the JSON file, read its contents, write equivalentCLAUDE.mdsections, and offer to delete the JSON file. - This ADR enables 📝 ADR-0016 (Workspace Mode) — recursive
CLAUDE.mdloading for multi-module support depends on configuration living inCLAUDE.mdrather than a single JSON file at the project root. - Related: 📝 ADR-0016 (Workspace Mode), SPEC-0014 (Markdown-Native Configuration and Workspace Mode requirements).
- Evidence base:
.claude-plugin-design.jsonwas the worst file hotspot in claude-ops (all 7 parallel PRs modified it). In the parallel agent coordination analysis across three repos, it was the only file that was guaranteed to conflict in every sprint.