agentleFS
kirkchenkirkchen/beat/CLAUDE.md

beat

CLAUDE.md9 starsChanged 7 months agoMITView on GitHub

Beat is a Claude Code plugin that provides an agent-driven BDD (Behavior-Driven Development) workflow. It uses Gherkin .feature files as the single source of truth for behavior specifications. Beat is not an application — it is a set of skills (SKILL.md files) that Claude Code loads as a plugin.

The file

We split this CLAUDE.md into the rules it gives an agent

10 rules. About 0 are common, 1 is distinctive, and 9 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 9

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    When installed in a user's project, Beat creates this structure:

    line 78
  2. Very specific:

    Spec self-review: After writing each artifact, /beat:design runs a four-check pass (placeholder / consistency / scope / ambiguity) and …

    line 158
  3. Very specific:

    Test files include // @feature: <file>.feature and // @scenario: <name> comments

    line 168
  4. Distinctive:

    Verify checks these annotations for bidirectional traceability

    line 169
  5. Very specific:

    After changing any skill description → run skill-triggering/run-all.sh

    line 251
  6. Very specific:

    After changing enforcement rules (Hard Gate, Rationalization Table) → run pressure/run-all.sh

    line 252
  7. Very specific:

    After changing skill content → run skill-content/run-all.sh

    line 253
  8. Very specific:

    Run the skill command (e.g., /beat:design, /beat:plan)

    line 263
  9. Very specific:

    Verify the skill produces correct artifacts and status.yaml updates

    line 264
  10. Very specific:

    If we ever want to publish Beat to the canonical openai/plugins curated marketplace, that's a separate manual step (open a PR upstream that …

    line 284

≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What Is Beat

Beat is a Claude Code plugin that provides an agent-driven BDD (Behavior-Driven Development) workflow. It uses Gherkin .feature files as the single source of truth for behavior specifications. Beat is not an application — it is a set of skills (SKILL.md files) that Claude Code loads as a plugin.

Installation

claude --plugin-dir /path/to/beat

Architecture

Plugin Structure

beat/
├── .claude-plugin/plugin.json   # Claude Code plugin manifest
├── .codex-plugin/plugin.json    # Codex plugin manifest (with interface block)
├── .agents/plugins/marketplace.json  # Codex marketplace manifest — makes this repo a single-plugin marketplace
├── plugins/beat/                # Codex plugin overlay (symlinks to root files: skills, assets, .codex-plugin, references)
├── assets/                      # Brand icons (composerIcon, logo) for Codex
├── skills/                      # Each subdirectory = one invocable skill (SKILL.md + synced references/)
│   ├── design/                  # /beat:design — create change + generate spec artifacts
│   ├── plan/                    # /beat:plan — task breakdown with multi-role review
│   ├── apply/                   # /beat:apply — TDD implementation
│   ├── verify/                  # /beat:verify — 5-dimension verification
│   ├── archive/                 # /beat:archive — sync features + archive completed change
│   ├── explore/                 # /beat:explore — thinking partner mode; ends by declaring an exit (small / standard / too-big / blocked / drop)
│   ├── to-issue/                # /beat:to-issue — turn a settled exploration into a tracker issue (or epic + sub-issues)
│   ├── setup/                   # /beat:setup — create beat/config.yaml + the agent docs (issue-tracker.md, CODING_STANDARDS.md, Agent docs block)
│   └── distill/                 # /beat:distill — reverse-engineer specs from code
├── references/                  # Source of truth for shared schemas — edit here, then run scripts/sync-references.mjs
│   ├── status-schema.md         # status.yaml format
│   ├── config-schema.md         # config.yaml format
│   ├── testing-conventions.md   # Annotation format and e2e test style reference
│   ├── project-layout.md        # Map of every project-level path Beat writes (authority for paths)
│   ├── context-format.md        # GLOSSARY.md glossary format (Layer 1 living docs)
│   ├── adr-format.md            # docs/adr/ ADR format + three-condition gate (Layer 2 living docs)
│   ├── architecture-format.md   # beat/ARCHITECTURE.md hub + module README format (Layer 3 living docs)
│   ├── route-schema.md          # beat/routes/<name>/ map + nodes (research / prototype / decision / change); status is derived
│   ├── verify-findings.md       # verify.md front matter — findings that /beat:apply fix-from-verify consumes
│   ├── handoff-report.md        # The "## Beat Handoff" block every skill ends with, plus the rhythm-stage-result suffix
│   ├── unattended-mode.md       # How skills behave under an orchestrator: defaults, decision briefs, sensitivity, per-skill mapping
│   ├── decision-brief.md        # Ten-line brief a skill writes when it must stop for a human in unattended mode
│   ├── issue-tracker-github.md  # docs/agents/issue-tracker.md template — GitHub (gh)
│   ├── issue-tracker-gitlab.md  # docs/agents/issue-tracker.md template — GitLab (glab)
│   ├── issue-tracker-other.md   # docs/agents/issue-tracker.md template — any other tracker
│   ├── coding-standards-template.md  # CODING_STANDARDS.md template
│   ├── lint-tools.md            # How and when skills run validate-beat.mjs / lint-features.mjs
│   ├── tool-mapping.md          # Cross-platform tool name mapping (root only)
│   └── codex-agents-snippet.md  # Per-project AGENTS.md snippet for Codex (root only)
├── scripts/sync-references.mjs  # Syncs /references and /scripts into each skill's references/ and scripts/ (see header)
├── scripts/validate-beat.mjs    # Deterministic checks: status.yaml, routes, verify.md, config, .orig residue, --pre-archive, --stale-paths, --handoff, --layout
├── scripts/lint-features.mjs    # Feature-file linter (annotations, layer tags, user story, tags, placeholders, README index)
├── docs/migrations/             # Upgrade prompts an agent runs inside a target project (0.6-project-layout.md)
├── NOTICE.md                    # Third-party attribution (mattpocock-skills, superpowers — both MIT)
├── hooks/                       # Claude Code hooks (Codex ignores; replaced by AGENTS.md snippet)
│   ├── hooks.json               # SessionStart hook config
│   └── session-start            # Detects Beat project, injects workflow context
├── tests/                       # Automated skill tests (claude -p headless)
│   ├── test-helpers.sh          # Shared assertion framework
│   ├── run-all.sh               # Run all fast tests (--integration for pipeline)
│   ├── analyze-token-usage.py   # Token analysis for test sessions
│   ├── skill-triggering/        # Layer 1: Description CSO validation
│   ├── skill-content/           # Layer 2: Enforcement awareness smoke tests
│   ├── pressure/                # Layer 3: Anti-rationalization under pressure
│   ├── validator/               # Deterministic fixtures for scripts/validate-beat.mjs (no LLM)
│   └── pipeline/                # Layer 4: End-to-end pipeline (--integration)
└── README.md

How It Works in Target Projects

When installed in a user's project, Beat creates this structure:

<project>/
├── GLOSSARY.md                  # Layer 1 — domain glossary (lazy, created on first term)
├── CODING_STANDARDS.md          # Reviewer-facing judgement rules (written by /beat:setup)
├── CLAUDE.md | AGENTS.md        # Contains the "## Agent docs" pointer block (written by /beat:setup)
├── beat/
│   ├── config.yaml              # Optional project config (language, context, rules)
│   ├── ARCHITECTURE.md          # Layer 3 — architecture hub (lazy, multi-module projects)
│   ├── changes/                 # Active and archived changes
│   │   ├── <change-name>/       # One directory per active change
│   │   │   ├── status.yaml      # Change lifecycle state
│   │   │   ├── proposal.md      # Optional: why this change exists
│   │   │   ├── features/        # Gherkin feature files (mandatory by default)
│   │   │   │   └── *.feature
│   │   │   ├── design.md        # Optional: technical decisions
│   │   │   ├── tasks.md         # Optional: implementation checklist
│   │   │   └── verify.md        # Written by /beat:verify: findings front matter + report
│   │   └── archive/             # Completed changes (YYYY-MM-DD-<name>/)
│   ├── routes/                  # Work too big for one change (lazy)
│   │   └── <route-name>/
│   │       ├── route.md         # Destination / decisions so far / not yet specified / out of scope
│   │       └── status.yaml      # Nodes + blocked_by edges; node status derived from changes
│   └── features/                # Persistent living documentation
│       └── <capability>/        # Organized by capability after sync
│           ├── *.feature
│           └── README.md
├── docs/
│   ├── adr/                     # Layer 2 — ADRs (lazy, three-condition gate)
│   │   └── NNNN-slug.md
│   └── agents/
│       └── issue-tracker.md     # Tracker, labels, dispatch conventions (required for /beat:to-issue)
└── packages|src/<module>/
    └── README.md                # Layer 3 — module README (lazy, on public-interface change)

Pipeline Flow

explore ──exit──► [to-issue ──label──►] design → plan → apply ⇄ verify → archive
   │                                       │        │        (fix-from-verify / incremental)
   │                                       │        └── tasks (review depth follows preset)
   │                                       └── [proposal] → gherkin → [design]   (preset: full / standard / minimal / technical)
   ├─ too-big → beat/routes/<name>/ (map + nodes); each change node re-enters at explore/design (to-issue: epic + sub-issues)
   ├─ blocked → research (AFK) / prototype (HITL) / decision (HITL) node, then explore again
   └─ drop → nothing is built; the issue (if any) is closed with the reason

For purely technical changes (tooling, deps, refactor): gherkin can be skipped, proposal becomes the driver.

Explore ends by declaring one exit (small, standard, too-big, blocked, drop) with the facts behind it. /beat:to-issue is optional: it writes the conclusion into a tracker issue (an epic with sub-issues for a route) so an orchestrator or a person can run design later without the conversation; the dispatch label is added only when the user asks. The preset chosen in design sets the strength of later phases: minimal/technical get a test-coverage-only plan review and a single verify subagent, and /beat:apply upgrades them to standard when the diff crosses config.yaml preset_upgrade thresholds. Verify writes verify.md; apply fix-from-verify fixes the open CRITICALs (explicit ids for anything else); re-runs are incremental from verification.sha and bounded by convergence rules (severity floor, prose ceiling, iteration ramp, round cap — see skills/verify/SKILL.md "Convergence"). A full re-run is the user's choice; archive never requires it. Apply never pushes — pushing comes after archive. Every skill ends with the ## Beat Handoff block.

  • design: Creates worktree + change container + generates spec artifacts (proposal, gherkin, design.md) + commits
  • plan: Creates execution plan (tasks.md) with multi-role review against spec artifacts + commits
  • apply: TDD implementation — gherkin-driven (every scenario must have a test) or proposal-driven (when gherkin skipped). Verifies worktree isolation (should exist from design/plan).
  • verify: Dispatches independent subagent(s) to verify against artifacts (two in parallel at standard strength, one at minimal); writes verify.md findings; incremental on re-run
  • archive: Syncs features to beat/features/ as living documentation (merging the change's design.md into an existing capability design.md rather than overwriting it) + moves change to beat/changes/archive/ + rewrites every tracked reference to the old beat/changes/<name> path + commits the archive as the last commit on the feature branch, then hands off to superpowers:finishing-a-development-branch for merge/PR. Archive runs before the PR, never after it is merged.

Key Concepts

  • Project-level paths (GLOSSARY.md, CODING_STANDARDS.md, docs/agents/issue-tracker.md, the ## Agent docs block, docs/adr/, beat/…) are defined in references/project-layout.md; it is the authority, and skills point at it instead of hardcoding paths. Projects created before 0.6 migrate with docs/migrations/0.6-project-layout.md.
  • status.yaml is the state machine — schema defined in references/status-schema.md. Phase advances forward only. Pipeline entries use inline YAML flow style: { status: done }. preset records the artifact preset and drives later-phase strength; route links a change to its route node. /beat:verify records its outcome in the top-level verification field (status, counts, sha, mode; it never advances phase); /beat:archive warns when archiving a change without a passing, full verification record. No field outside the schema — node scripts/validate-beat.mjs <project> rejects unknown keys.
  • routes (beat/routes/<name>/, schema references/route-schema.md) hold work too big for one change: a map plus nodes with blocked_by edges. Node status is always derived (a change node is done when its change is archived), never written, so there is no second state machine to drift. Rhythm or any dispatcher only sees one change per task; parallelism is a human reading the frontier.
  • config.yaml is optional project config — schema in references/config-schema.md. Controls artifact language, injects project context, and adds per-artifact rules (proposal, gherkin, design, tasks, adr). rules.adr applies at every ADR trigger point, so every skill that can write an ADR (including /beat:explore) reads the config; a project docs/adr/TEMPLATE.md takes precedence over Beat's built-in ADR template.
  • Unattended mode (references/unattended-mode.md) is on only when the run carries a stage-result nonce (Rhythm). Questions take defaults recorded in beat/changes/<name>/decisions/assumed.md; a decision that meets the ADR gate or matches config.yaml sensitive becomes a brief (references/decision-brief.md) and the run stops with blocked-on: decision; the handoff suffix carries blocked-on / decision / sensitive / diverging. Archive pushes and opens a ready PR with a "決定與影響" section instead of invoking finishing-a-development-branch. Explore is never unattended.
  • Gherkin is mandatory by default but can be skipped for purely technical changes (tooling, deps, refactoring without behavior change). When skipped, proposal drives plan, apply, and verify.
  • verify uses independent subagents (Agent tool: Explore for spec verification, general-purpose for code review) to avoid context bias. When verifying distilled specs (source: distill), it switches to accuracy mode.
  • distill works in reverse (code → spec), marks features with @distilled tag, and relies on /beat:verify for independent accuracy verification. A distill change sets tasks: skipped (nothing to implement) and flows distill → verify → archive; future changes to the distilled area use the normal flow in their own change containers.

Living Documentation (three layers)

Beat maintains three layers of project-level living documentation alongside the per-change artifacts. All three are lazy — created on first need, never preemptively. They complement the per-change archives, not replace them.

  • Layer 1 — GLOSSARY.md at the project root (glossary, the same file mattpocock's domain-modeling writes). Domain vocabulary, one canonical term per concept, opinionated about synonyms. Maintained inline by /beat:design (four-challenge check before writing gherkin), /beat:distill (glossary check on terms recovered from code), and /beat:archive (scan synced features for undefined terms). Format: references/context-format.md. Optional grilling via mattpocock-skills:grill-with-docs when ambiguity is complex.
  • Layer 2 — docs/adr/NNNN-slug.md (decisions). 1-3 sentence ADRs gated by three conditions: hard-to-reverse + surprising without context + result of a real trade-off. Offered at six trigger points: /beat:explore (decision capture during exploration), /beat:design (per Key Decision), /beat:plan (review rejections), /beat:apply (implementation-forced choices), /beat:distill (Key Decisions recovered from code — rationale from evidence or the user, never invented), /beat:archive (last-mile sweep when zero ADRs written). Format: references/adr-format.md. ADRs live at docs/adr/ rather than beat/adr/ because the ADR format is an industry standard (Nygard 2011) with its own tool ecosystem; Beat only triggers and offers, while the files belong to the project and outlive Beat if the plugin is removed.
  • Layer 3 — beat/ARCHITECTURE.md hub + module README.md spokes (structure & intent). Hub stays under ~150 lines: one Mermaid diagram, modules table, constraints referencing ADRs. Each module README under ~100 lines: purpose, public interface, dependencies, tests. Vocabulary is intentionally unspecified — use the codebase's native terms (package/service/module/layer). Maintained by /beat:apply (hard prompt on public-interface change, README scaffold offer on new module), /beat:design (hub update suggestion on module-level architecture change), /beat:distill (README scaffold offer for distilled modules), and /beat:verify (Dimension 5, WARNING tier, advisory only). Format: references/architecture-format.md. Structural snapshots (file tree, symbol map) are derive-tool territory — Beat doesn't generate them.
  • Spec self-review: After writing each artifact, /beat:design runs a four-check pass (placeholder / consistency / scope / ambiguity) and fixes issues inline. Adapted from superpowers:brainstorming.

Testing Architecture

Beat supports a three-layer testing architecture that connects feature files to tests at the appropriate level:

Layer 1: E2E Tests — @e2e tagged scenarios → e2e tests or BDD step definitions (using project's e2e framework)

Layer 2: Behavior Tests — @behavior tagged scenarios → tests with annotation linking (using project's test framework):

  • Feature files include # @covered-by: <path/to/test.ts> between the tag and scenario line
  • Test files include // @feature: <file>.feature and // @scenario: <name> comments
  • Verify checks these annotations for bidirectional traceability

Layer 3: Unit Tests — No feature binding, driven by proposal risk points or developer judgment

Annotation conventions:

In .feature files (annotation placed between tag and scenario line):

@behavior @happy-path
# @covered-by: src/services/__tests__/date-calculation.test.ts
Scenario: Monthly billing adjusts for short months

In test files (use the project language's comment syntax):

@feature: monthly-billing.feature
@scenario: Monthly billing adjusts for short months

Granularity guidance — Scenarios should describe behavior (what the system does), not function specs (how a function works). See design/SKILL.md for Gherkin creation guidelines.

Proposal-driven testing — When gherkin is skipped (technical changes), testing is driven by proposal.md risk points and success criteria. Tests use the project's test framework without feature file annotations.

Dependencies

Requires the superpowers plugin for the rigor inside a phase: brainstorming (explore, design), using-git-worktrees (design, plan, apply, distill), writing-plans (plan), test-driven-development / systematic-debugging / subagent-driven-development (apply), finishing-a-development-branch (archive). Each has an inline fallback when not installed. Beat suppresses the hand-offs those skills would otherwise make (brainstorming → writing-plans, SDD → finishing) because Beat's phases decide the next step.

Optionally integrates with mattpocock-skills at the edges of the pipeline: grilling + domain-modeling (explore / design, when a glossary term is genuinely ambiguous; both model-invoked — grill-with-docs is user-invoked and unreachable from a skill), pr (archive in unattended mode), research and prototype (explore, for a blocked exit of that kind), retro (mentioned after archive). All optional with graceful fallback. The route map format is adapted from its wayfinder skill (see NOTICE.md). The "when which" guidance lives in README "Companion Skills" and docs/DESIGN_PRINCIPLES.md "Companions, Not Owners".

NOTICE.md records third-party attribution for content adapted from these projects (both MIT-licensed).

Superpowers Integration

Beat cooperates with Superpowers via a SessionStart hook (hooks/session-start). When beat/config.yaml or beat/changes/ exists, the hook injects context telling Claude to transition to Beat workflow after brainstorming instead of writing-plans directly. Skills reference Superpowers via MUST invoke prerequisites with anti-rationalization enforcement (Hard Gate, Rationalization Table, Red Flags).

Design Philosophy

See docs/DESIGN_PRINCIPLES.md for the full design philosophy — core beliefs, testing philosophy, pipeline design rationale, and what Beat is and isn't. Consult it when evaluating changes that affect multiple skills or the overall direction.

Development Guidelines

Editing Skills

Each skill is a single SKILL.md file with YAML frontmatter (name, description) followed by markdown instructions. Skills are self-contained — they reference schemas in references/ but don't import code.

Schema Changes

references/status-schema.md, references/config-schema.md, references/route-schema.md and references/verify-findings.md are the single sources of truth. Every skill that reads/writes these files must follow the schemas exactly. If you change a schema, audit all skills that reference it, update scripts/validate-beat.mjs, and run tests/validator/run.sh.

References sync

/references and /scripts are the source of truth; skills/<name>/references/ and skills/<name>/scripts/ are synced copies. After editing anything under either, run node scripts/sync-references.mjs (or --check for CI). Do not hand-edit synced copies. Rationale in the script header.

Lint tools

Two scripts carry the checks that are deterministic (references/lint-tools.md): validate-beat.mjs (status.yaml / routes / verify.md / config schema, .orig residue, --pre-archive, --stale-paths, --handoff) and lint-features.mjs (feature-file conventions). Skills call them as node <skill-dir>/scripts/<name>.mjs so they work the same under the Claude Code plugin, the Codex plugin (plugins/beat/scripts symlink plus the per-skill copies) and npx skills add (which copies one skill folder, scripts included). They need Node 18+ and no packages. When a rule can be written as a script, put it there and reduce the prose to "run it, fix what it lists".

Testing Changes

Beat has a four-layer automated test suite using claude -p headless mode. Tests are in tests/.

Run fast tests (~20 min):

cd tests && ./run-all.sh

Run all tests including pipeline integration (~50 min):

cd tests && ./run-all.sh --integration

Four test layers:

LayerWhat it testsScripts
Skill TriggeringNaive prompts trigger correct Beat skillskill-triggering/
Skill ContentSkills know their enforcement rules (smoke test)skill-content/
PressureAnti-rationalization holds under implicit pressurepressure/
Pipeline IntegrationEnd-to-end design → plan → apply → verify → archivepipeline/ (--integration only)
ValidatorSchema fixtures for scripts/validate-beat.mjs, deterministic, secondsvalidator/run.sh

When to run tests:

  • After changing any skill description → run skill-triggering/run-all.sh
  • After changing enforcement rules (Hard Gate, Rationalization Table) → run pressure/run-all.sh
  • After changing skill content → run skill-content/run-all.sh

Notes:

  • Tests use claude -p --output-format stream-json --verbose and grep for tool invocations
  • Some tests are non-deterministic (LLM behavior varies) — a single flaky fail doesn't indicate a real problem
  • Pressure tests assert the rule the prompt pressures, nothing more: for a Superpowers gate, that the skill was invoked (ASSERT_SKILL), never how Superpowers executed it; for one of Beat's own gates (feature sync, .orig cleanup, subagent dispatch, updating an existing test), the observable result (ASSERT_FILE, ASSERT_NO_FILE, ASSERT_FILE_CHANGED, ASSERT_TOOL). A scenario whose assertion cannot fail on the behaviour it pressures is not a test. Pressure scenarios tempt the agent without ordering a skip; explicit-override scenarios (*-explicit-*) have the user order one and assert the informed-skip promise via ASSERT_OUTPUT
  • macOS compatible (Perl-based timeout fallback, no GNU coreutils needed)

Manual testing is still useful for verifying the full user experience:

  1. Install the plugin in a test project
  2. Run the skill command (e.g., /beat:design, /beat:plan)
  3. Verify the skill produces correct artifacts and status.yaml updates

Codex Distribution

Beat is installable on Codex directly from this GitHub repo — no separate marketplace fork or sync step. The repo is structured as a single-plugin Codex marketplace:

  • .agents/plugins/marketplace.json declares one plugin beat with source.path: "./plugins/beat".
  • plugins/beat/ is a thin overlay containing symlinks back to repo-root files (.codex-plugin/, skills/, assets/, references/, README.md, LICENSE). Single source of truth at root, no duplication.

source.path: "./" (root as plugin) was tried first but Codex's plugin scanner does not pick up content when marketplace and plugin overlap at the same path — the subdirectory layout matches the convention in openai/plugins and other working marketplaces.

End-user install (two steps because the Codex CLI has no plugin-install subcommand — only marketplace add/upgrade/remove):

  1. codex plugin marketplace add https://github.com/kirkchen/beat
  2. Inside Codex UI plugins panel, install Beat.

See docs/INSTALL-CODEX.md for the full user-facing flow.

Codex doesn't support hooks, so the SessionStart context injection performed by hooks/session-start does not run on Codex. The replacement is a per-project AGENTS.md snippet — see references/codex-agents-snippet.md for the text.

If we ever want to publish Beat to the canonical openai/plugins curated marketplace, that's a separate manual step (open a PR upstream that copies the plugin into their plugins/beat/ subdirectory — same shape we already use locally). The current setup intentionally does not automate that.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.