Plugin layout

Where everything lives in the repository, and how the pieces reference each other.

plugins/devflow/
├── .claude-plugin/plugin.json    manifest — name, version, statusLine
├── skills/<name>/SKILL.md        user-invocable slash commands
├── agents/<agent>.md             subagent prompts
├── hooks/
│   ├── hooks.json                event registrations, auto-loaded
│   ├── sync-runtime.js           SessionStart: mirrors devflow/ → ~/.claude/devflow/
│   └── *.js                      the rest of the hooks
└── devflow/                      runtime, mirrored to ~/.claude/devflow/
    ├── bin/df-tools.cjs          the central CLI
    ├── bin/lib/*.cjs             df-tools internals
    ├── workflows/<name>.md       workflow bodies, referenced via @~/.claude/devflow/...
    ├── references/<name>.md      static docs agents read at runtime
    └── templates/<name>.md       files copied into user projects' .planning/

Skills

A skill is a directory containing exactly one SKILL.md:

---
name: build
description: |
  Build a feature from start to finish...
  Triggers on: "build this", "implement this", ...
argument-hint: "<objective-number-or-description> [--pause] ..."
allowed-tools: Read, Write, Edit, Glob, Grep, Bash, Task, ...
---

<objective>...</objective>
<execution_context>
  @~/.claude/devflow/workflows/build.md
</execution_context>
<process>...</process>

Skills are deliberately thin. They load state through df-tools, then dispatch agents with the Task tool. Keeping the orchestrating session small is what lets it stay coherent across a long build.

The description field does double duty: it is what a human reads, and its Triggers on: line is what routes natural language to the skill.

The @path convention

Skills and agents reference shared files with @~/.claude/devflow/.... Those references are resolved by Claude Code and do not interpolate ${CLAUDE_PLUGIN_ROOT} — which is why the runtime mirror exists.

The rule that follows

In @path references, always use @~/.claude/devflow/.... Never ${CLAUDE_PLUGIN_ROOT} — it does not interpolate there and the reference silently resolves to nothing.

In hooks.json commands, always use ${CLAUDE_PLUGIN_ROOT} — hooks run from the plugin directory, not the mirror.

Workflows, references, templates

Workflows (devflow/workflows/) are the executable bodies skills pull in. Every one carries a status on frontmatter:

StatusMeaning
activein use by a skill or agent
legacysuperseded, kept for cross-reference
stubplaceholder, not yet implemented

References (devflow/references/) are static documents agents read during execution — TDD posture, git conventions, checkpoint handling, verification patterns, anti-patterns, the defaults table.

Templates (devflow/templates/) are copied into user projects’ .planning/ directories by df-tools.

The marketplace

/.claude-plugin/marketplace.json at the repository root declares the marketplace and every plugin it ships. Users add it by repo slug:

/plugin marketplace add AO-Cyber-Systems/devflow-claude

Conventions

AreaConvention
Module formatCommonJS (.cjs) — df-tools is a CLI, not a library
File I/OSynchronous throughout df-tools
NamingSkills <name>/SKILL.md, agents <agent-name>.md, hooks <purpose>.js
Prompt structureYAML frontmatter plus XML-like semantic tags
Commits{type}({scope}): {description} — feat, fix, test, refactor, perf, chore, docs
TestsNode native test runner, .test.cjs adjacent to source

Version sync

Three files must carry matching versions on every release:

package.json
plugins/devflow/.claude-plugin/plugin.json
.claude-plugin/marketplace.json

The changelog-on-tag hook enforces this — it blocks git tag -a vX.Y.Z when the three disagree, or when CHANGELOG.md has no entry for that version.