beacon-docs
v0.4.1
Published
Trail markers for AI-collaborative codebases — opinionated documentation convention and CLI.
Maintainers
Readme
Beacon
Trail markers for AI-collaborative codebases. Opinionated documentation convention + CLI that scaffolds the structure, generates per-vendor AI rule files (Claude, Cursor, Codex, Gemini), and lints the result.
The problem
You're building with AI agents — Claude Code, Cursor, Codex, Gemini CLI. After a few weeks of vibing, your repo has:
- 47 markdown files in random folders
PLAN_v2_FINAL.md,plan-v2.md,_2025_plan.md— three versions of the same plan- ADRs duplicated across
/docs,/notes, and/decisions - No
CLAUDE.mdor.cursorrulestelling agents where new docs should go - A graveyard of "is this still relevant?" content nobody dares delete
The result: neither humans nor AI agents can answer where X lives, whether it's current, or why it exists.
The solution
Beacon ships one opinionated convention and a CLI that enforces it:
- 🗂️ Structure: 6 core folders every project needs + 6 opt-in add-ons (
compliance/,business/,modules/, etc.) - 🏷️ Naming: filename suffix encodes type (
.plan.md,.adr.md,.pattern.md), folder encodes status (_archive/) - 🤖 AI rule files: generates
CLAUDE.md,AGENTS.md,GEMINI.md,.cursorrules, and.cursor/rules/beacon.mdcfrom a single source — every AI agent gets the rules in its preferred format - 🚨 Linter: 11 rules validate structure, naming, and AI-file sync (CI-friendly with
--strictand--json) - ⚡ Interactive wizard: project-type-aware defaults via
@clack/prompts
Result: AI agents stop creating docs in random places. Humans stop hunting for "the latest version." Reviews stop devolving into "should this be here?"
Demo
$ npx beacon-docs init
◆ Project type?
│ ● Library / SDK / Package
│ ○ Web Application
│ ○ Backend Service / API
│ ○ CLI Tool
│ ○ ...
◆ Which categories to enable?
│ ◼ reference ◼ architecture ◼ adr ◼ plans ◼ backlog ◼ evaluations
│ ◻ compliance ◻ business ◻ modules ◻ integrations ◻ operations ◻ roadmaps
◆ Which AI agents do you use?
│ ◼ Claude Code ◼ Cursor ◻ Codex / Copilot ◻ Gemini CLI
✔ Beacon docs scaffolded at /your/project/docs/You now have a complete docs tree, AI rule files at the project root, and a docs:lint script added to your package.json. Your next AI session will read CLAUDE.md and know exactly where to put new docs.
What you get
your-project/
├── CLAUDE.md ← generated, read by Claude Code
├── .cursorrules ← generated, legacy Cursor
├── .cursor/rules/beacon.mdc ← generated, modern Cursor
├── package.json ← gets a `docs:lint` script
└── docs/
├── README.md ← master index, "where do I find X?"
├── _meta/
│ ├── convention.md ← SINGLE SOURCE OF TRUTH (you edit this)
│ └── beacon.config.json ← project type + enabled categories
├── reference/ ← replicable patterns (.pattern.md)
│ └── README.md
├── architecture/ ← system structure (.architecture.md)
│ └── README.md
├── adr/ ← decisions (ADR-NNN-*.md, auto-numbered)
│ └── README.md
├── plans/ ← active work (.plan.md)
│ ├── README.md
│ └── _archive/ ← closed plans (status = folder, not filename)
├── backlog/ ← future items (.todo.md)
│ └── README.md
└── evaluations/ ← audits / snapshots (YYYY-MM-DD-*.eval.md)
└── README.mdAnd the generated CLAUDE.md (only the categories your project enabled show up):
<!-- generated by beacon — do not edit. Edit docs/_meta/convention.md and run `beacon sync`. -->
# Documentation Convention
> Project type: **library**. Full convention: [`docs/_meta/convention.md`](docs/_meta/convention.md).
## Universal rules
1. **One doc = one category.** Never duplicate across folders.
2. **Status via folder, never filename.** Closed plan → `_archive/`, never `*_DONE.md` or `*_v2.md`.
3. **kebab-case for all filenames.**
4. **README required in every category folder.**
5. **ADRs are append-only.** Supersede with a new ADR; never edit an accepted one.
6. **Evaluations are immutable snapshots.** To revise, create a new dated file.
...
## Where does X go?
| Question | Folder |
|---|---|
| "How is X done technically?" | `reference/` |
| "Why was X decided?" | `adr/` |
| "What is being built right now?" | `plans/` |
| "What was the state at date X?" | `evaluations/` |Install
npm install -D beacon-docsOr use without installing:
npx beacon-docs initRequires Node ≥ 20.
Quick start
Interactive (recommended for first run)
npx beacon-docs initThe wizard detects your project (reads package.json, suggests add-ons based on installed deps like stripe/@prisma/client), then walks you through choices.
Non-interactive (for CI / scripted setup)
npx beacon-docs init \
--yes \
--type=library \
--with=operations \
--without=backlog \
--agents=claude,cursor| Flag | Purpose |
|---|---|
| --yes | Skip the interactive wizard |
| --type=<type> | One of: web-app, backend-service, library, cli-tool, mobile-app, monorepo, custom |
| --with=a,b | Add categories beyond your project type's defaults |
| --without=a,b | Remove categories from defaults |
| --agents=a,b | AI agents to support: claude, cursor, codex, gemini |
| --language=en | Docs language (only en ships in v1) |
Project types & default categories
Project type suggests defaults. The wizard pre-checks them, but every choice is deselectable, and unmarked categories can be opted into. Granular customization is available on every type — custom just starts with nothing pre-selected.
| Folder | Library | Web App | Backend | CLI Tool | Mobile | Monorepo | Custom |
|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| reference/ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⬜ |
| architecture/ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⬜ |
| adr/ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⬜ |
| plans/ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⬜ |
| backlog/ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⬜ |
| evaluations/ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⬜ |
| compliance/ | ⬜ | ⬜* | ⬜* | ⬜ | ⬜* | ⬜ | ⬜ |
| business/ | ⬜ | ✅ | ⬜ | ⬜ | ✅ | ⬜ | ⬜ |
| modules/ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ✅ | ⬜ |
| integrations/ | ⬜ | ✅ | ✅ | ⬜ | ✅ | ✅ | ⬜ |
| operations/ | ⬜ | ✅ | ✅ | ✅ | ✅ | ✅ | ⬜ |
| roadmaps/ | ⬜ | ✅ | ✅ | ⬜ | ✅ | ✅ | ⬜ |
✅ pre-selected — ⬜ available but not pre-selected — * prompted explicitly ("Do you handle regulated data?")
Commands
| Command | Purpose |
|---|---|
| beacon init | Interactive scaffold (or --yes --type=... for CI) |
| beacon new <type> <slug> | Create a doc with correct location, naming, frontmatter |
| beacon archive <type> <slug> | Move a completed plan/roadmap to _archive/ |
| beacon sync | Regenerate AI rule files from docs/_meta/convention.md |
| beacon enable <addon> | Enable an add-on category (creates folder + README, re-syncs AI files) |
| beacon disable <addon> | Disable an add-on category (--force if folder has content) |
| beacon lint | Validate the docs tree (--strict to escalate warnings, --json for CI) |
| beacon doctor | Surface health signals: stale plans, proposed-ADRs, old evals, backlog balance |
| beacon completion <shell> | Print a shell completion script (bash, zsh, fish) for TAB-completion |
| beacon about | Print version, install path, project config, and AI-file status (diagnostics) |
beacon new examples
beacon new plan billing-integration # → docs/plans/billing-integration.plan.md
beacon new adr add-rate-limiting # → docs/adr/ADR-001-add-rate-limiting.md (auto-numbered)
beacon new pattern multi-tenancy # → docs/reference/multi-tenancy.pattern.md
beacon new eval frontend-audit # → docs/evaluations/2026-05-22-frontend-audit.eval.md
beacon new module invoicing # → docs/modules/invoicing.module.md (requires `modules` enabled)
beacon new todo realtime-hardening # → docs/backlog/realtime-hardening.todo.md
beacon new guide deploy --category=operations # → docs/operations/deploy.guide.mdEach command opens a doc with the right frontmatter skeleton — title, status, date, etc.
beacon lint vs beacon doctor
Two different jobs:
beacon lintanswers "is the structure correct?" — hard rules about file naming, folder placement, AI-file sync. Use in CI (fail PRs on violations).beacon doctoranswers "is the docs tree healthy?" — soft signals about activity, decisions, snapshots, balance. Run weekly or before releases.
beacon doctor # exit 0 even with findings (informational)
beacon doctor --strict # exit 1 if any findings exist (for CI gating)
beacon doctor --json # machine-readable for tooling
beacon doctor --explain # list all checks grouped by area
beacon doctor --explain <check> # verbose docs (why it exists, triggers, fix)The 5 checks are: stale-plans (>30 days), proposed-adrs (stuck >14 days), old-evaluations (>6 months, no refresh), orphan-readmes (add-on enabled >30 days ago but folder still empty), backlog-balance (too many plans, no backlog). The same --explain flag exists on beacon lint.
Tuning thresholds. Every threshold is configurable per-project. Add a doctor.thresholds section to docs/_meta/beacon.config.json:
{
"doctor": {
"thresholds": {
"stalePlanDays": 60,
"proposedAdrDays": 21,
"oldEvalMonths": 12,
"orphanReadmeDays": 45,
"backlogMinPlans": 10,
"backlogPlansPerItem": 8
}
}
}All fields are optional; unset ones use the defaults. beacon about shows which thresholds are overridden vs default. Design rationale: ADR-010.
Plugins
beacon doctor and beacon lint are extensible — third-party plugins can add custom checks and rules without forking. Configure plugins in docs/_meta/beacon.config.json:
{
"plugins": [
"beacon-plugin-compliance", // installed via npm
"./scripts/internal-checks.mjs" // relative path
]
}A plugin is a JavaScript module exporting a BeaconPlugin object:
// scripts/internal-checks.mjs
export default {
name: "internal-checks",
version: "0.1.0",
checks: [/* Check[] for `beacon doctor` */],
rules: [/* Rule[] for `beacon lint` */],
explain: { /* optional --explain entries */ },
};Plugin-contributed checks and rules fire alongside built-ins. beacon about lists loaded plugins with counts. beacon doctor --explain <check> and beacon lint --explain <rule> work for both built-in and plugin names.
Working reference: examples/plugin-example/ ships in the repo. Design rationale in ADR-011. Full authoring guide in docs/reference/writing-a-plugin.pattern.md.
Convention for publishing: name your package beacon-plugin-<scope> and add "beacon-plugin" to keywords.
Shell completion
Beacon ships TAB-completion for bash, zsh, and fish. Install once per shell:
# bash (Linux, Git Bash on Windows)
beacon completion bash > ~/.local/share/bash-completion/completions/beacon
# zsh (macOS default since 2019)
beacon completion zsh > "${fpath[1]}/_beacon"
# then: autoload -U compinit && compinit
# fish
beacon completion fish > ~/.config/fish/completions/beacon.fishRestart the shell (fish reloads automatically). Then:
$ beacon <TAB>
archive completion disable doctor enable init lint new sync
$ beacon doctor --explain <TAB>
backlog-balance old-evaluations proposed-adrs stale-plans
$ beacon archive plan <TAB> # reads docs/plans/ in the current project
billing-integration refactor-auth shipping-v2Completion is static — the script is generated once and embeds all command/flag/value lists. The only dynamic case is beacon archive plan|roadmap <slug>, which reads the filesystem inline. See ADR-009 for the design rationale.
CI integration
Drop this into .github/workflows/docs-lint.yml:
name: Beacon docs lint
on:
pull_request:
paths:
- "docs/**"
- "CLAUDE.md"
- "AGENTS.md"
- "GEMINI.md"
- ".cursorrules"
- ".cursor/**"
push:
branches: [main]
jobs:
beacon-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npx beacon-docs lint --strict--strict escalates warnings to errors, so a stale plan or oversized folder will fail the PR.
How it works
Single source of truth → generated artifacts.
docs/_meta/convention.md ← human-edited, project-specific
│
├─► CLAUDE.md (project root)
├─► AGENTS.md (project root, for Codex / Copilot)
├─► GEMINI.md (project root)
├─► .cursorrules (project root, legacy Cursor)
└─► .cursor/rules/beacon.mdc (modern Cursor rule format)Generated files carry a <!-- generated by beacon --> header. Run beacon sync after editing convention.md — or let beacon lint --strict catch out-of-sync files in CI.
Each generated file has two layers:
- Universal (identical in every project) — the 9 invariant rules: one doc = one category, status via folder, kebab-case, ADRs append-only, evaluations immutable, etc.
- Project-specific (conditional on enabled categories) — e.g., "business/ is for strategy/pricing, no technical content" only appears if you enabled
business/.
A library project's CLAUDE.md is ~30 lines. A full web-app with every add-on is ~70 lines. Density scales with complexity.
How Beacon compares
| Tool | What it does | Beacon's difference | |---|---|---| | Diátaxis | Philosophy of 4 doc types (tutorials, how-to, reference, explanation) | Beacon is CLI + enforced convention; Diátaxis is a mental model | | adr-tools | CLI for Architecture Decision Records only | Beacon covers ADRs and plans, patterns, evaluations, etc. | | .cursorrules / CLAUDE.md by hand | You write the rules yourself | Beacon generates all 4 vendor formats from one source, keeps them in sync | | Docusaurus / Vitepress / Starlight | Builds a docs site | Beacon manages the source tree convention; pair it with any docs site generator | | Conventional Commits | Standardizes commit messages | Same philosophy, different layer: standardizes documentation structure |
Beacon's wedge: AI-first. Built for projects where AI agents are routinely creating, editing, and reading documentation.
Configuration
Beacon stores per-project config at docs/_meta/beacon.config.json:
{
"version": "1.0",
"projectType": "library",
"categories": [
"reference", "architecture", "adr",
"plans", "backlog", "evaluations",
"operations"
],
"agents": ["claude", "cursor"],
"language": "en"
}Edited via beacon init, beacon enable, beacon disable. You don't hand-edit it normally — but you can in a pinch (followed by beacon sync).
Customizing the convention
Want to tweak the universal rules or the "where does X go?" table for your team? Edit docs/_meta/convention.md directly. Then:
beacon sync # regenerate all AI rule files
beacon lint # confirm sync (and structure)The linter's ai-files-sync rule will fail in CI if anyone forgets to run beacon sync after editing the convention.
Dogfooding
beacon-docs itself uses Beacon to organize its own documentation — see docs/ for live examples:
docs/architecture/system-overview.architecture.md— how Beacon is structured internallydocs/adr/— 6 ADRs explaining the major design decisionsdocs/reference/— contributor guides (add a category, add a lint rule, add an AI vendor)docs/operations/release-process.guide.md— release runbookdocs/backlog/— 7 deferred-to-post-1.0 features
If you want to see what your project's docs could look like, browse this repo.
Versioning policy
Beacon follows SemVer, with pre-1.0 conventions:
- Patch (
0.2.x) — bug fixes, UX polish, new lint rules, refinements to existing commands. Safe to upgrade within a^0.2range. - Minor (
0.x.0) — new top-level commands or new feature surfaces (e.g.,beacon doctorin0.2.0). May change behavior of existing commands when it's strictly an additive opt-in. - Major (
1.0.0) — first commitment to API stability. Until then, expect minor versions to occasionally tighten things in non-breaking-but-noticeable ways.
That's why the release history jumps from 0.1.8 straight to 0.2.0: beacon doctor is a brand-new command, not a polish of lint.
Project status
v0.1.0 — initial public release. Feature-complete for the V1 scope: scaffold + 4 vendor generators + 7 commands + 11 lint rules.
Deferred to post-1.0
See docs/backlog/ for the full list. Highlights:
- Plugin system for custom categories
- Auto-migration from existing doc structures (Diátaxis, ad-hoc)
- i18n of AI rule templates
- VSCode extension surfacing lint warnings inline
beacon serve— local docs preview server- Brew / scoop distribution
PRs welcome for any of these — see Contributing below.
Contributing
The repo dogfoods its own convention, so contributing means:
- Open an issue describing the problem or feature.
- For non-trivial changes, propose an ADR in
docs/adr/first. - Code changes go in
src/; add or update tests intests/. - Run
npm test(302 tests must keep passing),npm run typecheck,npm run build. - Add a changeset (
npx changeset add) describing your change. - PR to
main.
Common contribution types — see the contributor patterns in docs/reference/:
- Adding a category →
docs/reference/adding-a-category.pattern.md - Adding a lint rule →
docs/reference/adding-a-lint-rule.pattern.md - Adding an AI vendor →
docs/reference/adding-an-ai-vendor.pattern.md
FAQ
Q: Does Beacon write documentation for me? A: No. Beacon enforces where docs go and how they're named, and tells AI agents the rules. Your AI agent (or you) still writes the actual content.
Q: Can I use Beacon with a docs site like Docusaurus / Vitepress?
A: Yes. Beacon manages the source tree convention; layer any site generator on top of docs/.
Q: Does it work without AI agents?
A: Yes — humans benefit from the same convention. The AI rule files are just opt-in via --agents.
Q: Why force kebab-case filenames? A: AI agents are wildly inconsistent with casing (camelCase, snake_case, Title Case). Enforcing kebab-case at lint time means agents stop creating duplicates that differ only in casing.
Q: Can I disable a rule I don't like? A: Not in v1. The 11 lint rules are fixed by design (consistency beats configurability for an opinionated tool). Configurable rules are on the backlog.
Q: What if my project doesn't fit any of the 7 types?
A: Use --type=custom — starts with no categories enabled, you opt into exactly what you need.
License
MIT © 2026 julio
