Light-touch, pragmatic, artifact-driven framework for AI-assisted software delivery
Project description
BEACON
Light-touch, pragmatic, artifact-driven framework for AI-assisted software delivery.
"Would I proudly sign my name to this?"
BEACON owns the Product side of delivery — strategy, epics, ADRs, lifecycle discipline. It composes with SpecKit for the Engineering side — per-feature specs, plans, tasks. Each is independently installable; neither writes into the other's files. Active work is discovered from git, not stored — so parallel agents in worktrees never merge-conflict on a central state file.
quarter scope Roadmap/README.md ← strategy (BEACON)
weeks scope Roadmap/epics/<slug>.md ← initiative (BEACON)
days scope specs/<NNN-slug>/ ← feature (SpecKit)
hours scope specs/<NNN-slug>/tasks.md ← tasks (SpecKit)
seconds scope git branch + tasks.md state ← active work (discovered)
Install
For humans
Install globally with uv tool (once per machine):
uv tool install beacon-framework
Then from any project:
beacon init --here
Idempotent — re-running is safe. User-seeded files are preserved. beacon init offers to install SpecKit interactively (highly recommended for the /beacon.{specify,plan,tasks,implement} wrappers; everything else works without it). Pass --speckit or --no-speckit to bypass the prompt in non-interactive contexts.
To upgrade later: uv tool upgrade beacon-framework, then beacon upgrade --here in each project. See Upgrading an existing installation for the full two-step flow.
For the full installation walkthrough (including brownfield install), see AGENTS.md. It works equally well as a human read.
Alternative install paths:
# Ephemeral, no global install
uvx --from beacon-framework beacon init --here
# Track main from git (unreleased changes ahead of the latest PyPI release)
uvx --from git+https://github.com/darth-veitcher/beacon beacon init --here
For LLM agents
Fetch the agent guide and follow it:
curl -s https://raw.githubusercontent.com/darth-veitcher/beacon/main/AGENTS.md
AGENTS.md is self-contained: vocabulary, install order (SpecKit then BEACON), workflow end-to-end, command reference, and what to do next on a fresh project.
Concepts
Five terms cover everything:
- Epic — a weeks-scope initiative at
project-management/Roadmap/epics/<slug>.md. Groups one or more specs. Creating or editing an epic is a BEACON DESIGN-phase activity — produces cross-spec ADRs that no single featurespec.mdcan capture. - Spec — a SpecKit feature folder at
specs/<NNN-slug>/. SpecKit owns it. BEACON writes one file inside:.beacon.toml, the epic backlink. - Bullet — the active piece of work in the current git worktree. Discovered live by resolving the current branch.
- ADR — a Markdown decision record at
project-management/ADRs/ADR-NNN-<slug>.md(MADR format). - Phase — SEED → DESIGN → BUILD → SHIP. Lifecycle gates surfaced as Claude Code skills.
Commands
Project lifecycle
beacon init [--here] [--language python|node] [--ai claude] # install (idempotent)
beacon upgrade [--here] # refresh framework files
beacon check [--here] # files-present validation
beacon doctor [--here] [--strict] # semantic health check (15 checks)
beacon --version / beacon -V # show installed version
SEED phase (project bootstrap)
beacon seed # status of the four SEED deliverables
beacon seed --strict # CI mode — WARN becomes FAIL
beacon seed scaffold # conversational fill-in from the terminal
Inside Claude Code, /beacon.seed runs an inferential scaffold — one or two broad questions, then Claude infers values for every template slot, presents them back plan-mode style, and writes the files on confirmation.
Epics (Product)
beacon epic new <slug> --title "<title>" # create from template
beacon epic list [--detailed] # active epics + owned-spec rollup
beacon epic refresh <slug> # recompute spec rollup (read-only)
beacon epic finish <slug> # archive; refuses while specs in flight
Shipped state is inferred from git-merge history — a spec whose branch merged to the trunk reads as complete even if its tasks.md still carries a leftover [ ]. No "ship-it marker" checkbox required.
Specs (merge-time bookkeeping)
beacon spec finish <NNN-slug> # mark a merged spec shipped (optional tidy-up)
beacon spec finish flips any leftover [ ] to [x] # shipped, records status = "shipped" in the spec sidecar, and refreshes the parent epic. It's optional — the framework already infers shipped state from git — but it's the clean lifecycle command for clearing a leftover checkbox after a PR merges.
Bullets (Engineering, per worktree)
beacon bullet start [<title>] [--epic <slug>] # start current worktree's bullet
beacon bullet finish # mark done
beacon bullet status # show current bullet
beacon bullet list # all bullets across local branches, grouped by epic
beacon bullet sweep # prune bullets whose branch is gone
Spec ↔ epic link
beacon link-spec <NNN-slug> --epic <slug> # backlink an existing spec to an epic
PRD bridge (Claude Code)
/beacon.prd <epic-slug> # export — generate a PRD from the epic, problem statement, ADRs, and spec rollup
/beacon.prd import <path> # import — ingest an existing PRD and scaffold the epic, problem statement, and ADR stubs
The export writes project-management/Roadmap/epics/<slug>-prd.md. If .beacon/prd-template.md exists, its structure is used instead of the built-in default.
The import creates the problem statement, epic file, and ADR stubs from a PRD you already have — then lists the features it found as suggested /beacon.specify calls.
Roadmap export
beacon roadmap export # → ROADMAP.md (Markdown + Mermaid Gantt, commit this)
beacon roadmap export --stdout # pipe to stdout
beacon roadmap render # → ROADMAP.html (interactive, gitignore this)
beacon roadmap export generates a version-controlled ROADMAP.md with a Mermaid Gantt timeline, epic status table with fidelity badges (S+ A+ T:67%), active bullets, and ADR index.
beacon roadmap render produces a self-contained ROADMAP.html — no build step, one file — styled with the Structural Breath design system. Open in a browser, screenshot into slides, or host as a static page.
Epics view — status, spec progress, fidelity indicators per initiative:
Decisions view — ADR index across all epics with Accepted/Proposed status:
Wire into CI to keep ROADMAP.md current on every push to main:
- run: beacon roadmap export
- run: git diff --exit-code ROADMAP.md || (git add ROADMAP.md && git commit -m "chore: refresh roadmap")
Integrations
beacon integration list
beacon integration add <name> # claude (default), release
beacon integration remove <name>
Languages
Quality-gate placeholders render per-language at install time:
beacon init --language node # → bun run lint; bunx tsc --noEmit; …
beacon init --language python # → uv run ruff; uv run ty check; … (default)
Add a language by dropping a TOML at src/beacon/resources/languages/<name>.toml.
Integrations
beacon integration list shows what's available.
claude (installed by default)
Slash commands (/init, /git:*, /design:*) and the marker-delimited block in .claude/CLAUDE.md that briefs the agent on the lifecycle. If SpecKit is detected at install time, four additional wrappers ship at .claude/commands/beacon/:
| Wrapper | Inlines (via @) |
Adds before | Adds after |
|---|---|---|---|
/beacon.specify <epic-slug> <feature> |
SpecKit's specify | Epic Success criteria, Non-goals, ADRs | beacon link-spec <NNN-slug> --epic <slug> |
/beacon.plan |
SpecKit's plan | (none) | Placeholder + ADR-reference sweep |
/beacon.tasks |
SpecKit's tasks | (none) | (hook in place; no-op today) |
/beacon.implement |
SpecKit's implement | (none) | beacon epic refresh <slug>; prompt to epic finish if all specs done |
Wrappers compose with SpecKit's commands via Claude Code's @<path> inclusion — no prompt duplication, no maintenance burden when SpecKit updates. If SpecKit isn't installed, the wrappers are skipped (with a notice); installing SpecKit later and running beacon upgrade retro-wires them.
Two BEACON-native commands ship unconditionally (no SpecKit needed): /beacon.status reads the repo and reports which phase you're in, its health, and the single recommended next step; /beacon.continue runs that step for you — proposing-then-confirming by default, or dispatching the reversible build-loop steps unattended under --auto (pair it with /loop to keep work advancing while you're away).
release (opt-in)
beacon integration add release
Drops three things into the project:
| File | What it is |
|---|---|
.github/workflows/release.yml |
Branch-based release: push to main → PyPI, push to develop → TestPyPI (pre-release). Framework-owned. |
PUBLISHING.md |
One-time PyPI/TestPyPI Trusted Publisher registration steps. User-seeded — never overwritten. |
[tool.semantic_release] block in pyproject.toml |
python-semantic-release config wrapped in # ──── BEACON release integration ──── sentinels. Refuses to clobber an existing hand-authored block. |
beacon integration remove release cleanly reverses — deletes the workflow + the fenced PSR block; leaves PUBLISHING.md alone.
Health checks
beacon check # files-present validation against the manifest
beacon doctor # semantic — 15 checks across content health, active-work integrity, Product↔Engineering drift
beacon doctor --strict # CI mode — every WARN becomes FAIL
Doctor's 15 checks group into three concerns:
- Content health — placeholder text in
00-problem-statement.md, staleWork/sessions/, ADR coverage, framework files modified on disk. - Active-work integrity — current worktree has a discoverable bullet (resolved from the committed
.beacon/bullets.toml, so it works on a fresh CI clone), spec branches have an active task intasks.md. - Product ↔ Engineering drift — every spec has an epic backlink, every backlink is reciprocated in the epic's
## Specs, active branches are tied to active epics, no ghost epics, no lifecycle mismatches, Roadmap reviewed in the last quarter.
Sample output on a project with one epic, one spec, and the problem statement still unfilled:
✗ problem-statement: Placeholder text still in problem statement: [Replace with
your problem statement] …. Fill in 00-problem-statement.md before opening a
feature branch.
✓ active-bullet: 001-oauth-login → T001 scaffold OAuth callback (owner: agent-A,
source: spec)
✓ spec-task-alignment: Active task in 001-oauth-login: T001 — scaffold OAuth
callback
✓ spec-backlink-integrity: All 1 spec folder(s) backlink an epic.
✓ epic-spec-listed: All spec→epic backlinks are reciprocated in epic files.
✓ epic-coverage: 001-oauth-login → epic user-auth
✓ ghost-epic: All 1 Active epic(s) have current work.
✓ epic-spec-lifecycle: Epic statuses match their owned-spec state.
✓ epic-rollup: user-auth (Active): 1/2 shipped, 1 in flight
! epic-adr-coverage: Active epic(s) with no ADRs listed: user-auth. …
! roadmap-staleness: Roadmap/README.md has no `Last reviewed: YYYY-MM-DD` header.
✓ sessions: No stale session files.
✓ adr-coverage: 0 ADR(s) on file across 5 commits.
✓ drift: Framework files match shipped resources.
ok=11 warn=2 fail=1
A FAIL exits non-zero (--strict does the same for WARN), so it wires cleanly into a pre-commit hook or CI gate.
What gets installed
project-management/
├── .beacon/init-options.json # manifest — pins version, lists framework vs seeded files
├── .beacon/bullets.toml # committed — active non-spec bullets, keyed by branch
├── Background/
│ ├── 00-problem-statement.md # seeded
│ └── 01-final-architecture-document.md # seeded
├── ADRs/
│ ├── README.md # framework
│ └── ADR-000-template.md # framework (MADR)
├── Roadmap/
│ ├── README.md # seeded — STRATEGY only (quarter scope)
│ └── epics/
│ ├── EPIC-TEMPLATE.md # framework
│ └── archive/.gitkeep
└── Work/
├── README.md # framework
└── sessions/ # transient — delete after merge
beacon.md # generated dashboard
.claude/
├── CLAUDE.md # BEACON-managed block between <!-- BEACON START/END -->
├── commands/
│ ├── init.md # /init (SEED phase)
│ ├── git/{feature,pr,release}.md
│ ├── design/{wardley,evaluate,diagram}.md
│ └── beacon/ # only if SpecKit detected
│ ├── specify.md plan.md tasks.md implement.md
└── skills/
├── beacon-seed/SKILL.md
├── beacon-design/SKILL.md
├── beacon-build/SKILL.md
└── beacon-ship/SKILL.md
Framework files are overwritten on beacon upgrade. Seeded files are written only when absent. The manifest is the contract.
Adding BEACON to an existing project (brownfield)
BEACON is designed to drop into an existing repo without clobbering anything. From the project root:
beacon init --here
What you can rely on:
| You already have | BEACON's behaviour |
|---|---|
.claude/CLAUDE.md |
Your content stays. A <!-- BEACON START --> … <!-- BEACON END --> block is appended at the bottom; only that block is refreshed on re-runs. |
project-management/ directory with your own notes/ADRs |
Sibling files preserved. BEACON adds its own subtree alongside. Files at BEACON paths are left alone if user-seeded; framework files overwrite. |
src/, tests/, pyproject.toml, README.md |
Untouched. BEACON writes only inside .claude/, project-management/, and beacon.md. |
| Existing git history + branches | Untouched. BEACON reads git state; it never commits or branches on your behalf. |
Pre-existing SpecKit (.claude/skills/speckit-*/ or .claude/commands/speckit.*.md) |
Detected; the four /beacon.{specify,plan,tasks,implement} wrappers install on top via @-includes. |
Verify before you commit:
git status # see exactly what BEACON added/modified
git diff .claude/CLAUDE.md # confirm only the marker block changed
Try it ephemerally without the global install:
uvx --from beacon-framework beacon init --here
git status # decide whether to keep
Upgrading an existing installation
BEACON follows semantic versioning from 1.0.0: patch releases (1.0.x) are bug fixes, minor releases (1.x.0) add features, major releases (x.0.0) contain breaking changes. Releases are cut automatically from commits on main — you don't need to do anything special to get them.
Upgrading a project that already has an earlier BEACON in place is two steps — and missing the second is the usual gotcha:
- Upgrade the CLI tool — the
beaconprogram on your machine. - Refresh the project's files —
beacon upgrade --hererewrites the framework files inside this repo to match the new CLI. Upgrading the tool alone does not touch files already written into your project; the manifest stays pinned to the old version until you run this.
# 1. Upgrade the installed CLI (global tool install)
uv tool upgrade beacon-framework
# 2. Confirm the new version
beacon --version
# 3. Refresh this project's framework files (run from the project root)
beacon upgrade --here
# 4. Verify the result
beacon doctor --here
You should see:
✓ BEACON upgraded to <version>
files refreshed: <N>
integrations: claude
No global install? Re-run through uvx, forcing a fresh fetch of the latest release (--refresh bypasses the cache), or pin to a version / git ref:
uvx --refresh --from beacon-framework beacon upgrade --here # latest published
uvx --from beacon-framework==1.0.1 beacon upgrade --here # a specific release
uvx --from git+https://github.com/darth-veitcher/beacon beacon upgrade --here # main (unreleased)
What beacon upgrade changes — and what it leaves alone
| Touched | Behaviour |
|---|---|
Framework files — templates, skills (.claude/skills/beacon-*/), slash commands (.claude/commands/), the <!-- BEACON START/END --> block in .claude/CLAUDE.md |
Overwritten with the new version. Don't hand-edit these; your changes are replaced on upgrade. |
User-seeded files — Background/00-problem-statement.md, Roadmap/README.md, your epics, ADRs you authored, anything outside BEACON's paths |
Untouched. Written only when absent at init; upgrade never overwrites them. |
Manifest (project-management/.beacon/init-options.json) |
beacon_version and installed_at are bumped; files reclassified between framework/seeded across versions are moved to the right list. |
SpecKit wrappers (/beacon.{specify,plan,tasks,implement}) |
SpecKit detection is re-run. If SpecKit was added since your last install, the wrappers are retro-wired. Pass --speckit / --no-speckit to decide non-interactively. |
Optional flags persist your preferences into the manifest for future upgrades:
beacon upgrade --here --hooks # (re-)install Claude Code hooks
beacon upgrade --here --no-hooks # skip hooks on this and later upgrades
beacon upgrade --here --git-flow trunk # switch branching model (trunk | gitflow); re-renders /git:* commands
Review and commit
beacon upgrade only writes files — it never commits. Review the diff, then commit so the version bump is recorded:
git status # framework files refreshed; seeded files unchanged
git diff # eyeball what moved — should be framework files + the manifest
git add -A && git commit -m "chore: upgrade BEACON to $(beacon --version)"
If beacon doctor --here flags missing framework files after an upgrade (rare — usually a deleted file), beacon upgrade is also the fix: re-running restores anything in the manifest's framework list.
Atomicity
- BEACON imports nothing from SpecKit. No build-time dependency.
beacon initsucceeds on projects with no SpecKit installed; the four/beacon.*wrappers are skipped with a notice.beacon upgraderetro-wires them once SpecKit appears.beacon bullet *,beacon epic *,beacon link-spec,beacon doctorall work without SpecKit anywhere on the system. Doctor's spec-aware checks no-op when no spec folders exist.- BEACON writes nothing into
.specify/. SpecKit writes nothing intoproject-management/. The only file insidespecs/<slug>/BEACON owns is.beacon.toml— SpecKit ignores it. - Install, upgrade, and remove either framework independently.
Documentation
AGENTS.md— install + use, self-contained, agent-readableBEACON.md— full framework specificationpragmatic-principles.md— agent operating principles applied universally by BEACON
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file beacon_framework-1.11.0.tar.gz.
File metadata
- Download URL: beacon_framework-1.11.0.tar.gz
- Upload date:
- Size: 204.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
007a911aaddcb727bda9917c6c07f8ecab8d547a81c598df71f25d899ce18e9f
|
|
| MD5 |
940f62ffc21e88895a23ab62c170d2fa
|
|
| BLAKE2b-256 |
fbff10d21ff076a3fe9a2afe38b917f6fa36121b4ad00b83fcccb18643c00130
|
Provenance
The following attestation bundles were made for beacon_framework-1.11.0.tar.gz:
Publisher:
release.yml on darth-veitcher/beacon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
beacon_framework-1.11.0.tar.gz -
Subject digest:
007a911aaddcb727bda9917c6c07f8ecab8d547a81c598df71f25d899ce18e9f - Sigstore transparency entry: 2019253403
- Sigstore integration time:
-
Permalink:
darth-veitcher/beacon@61cc2b55a6e8751e92820e7bfebea45ab96cf099 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/darth-veitcher
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@61cc2b55a6e8751e92820e7bfebea45ab96cf099 -
Trigger Event:
push
-
Statement type:
File details
Details for the file beacon_framework-1.11.0-py3-none-any.whl.
File metadata
- Download URL: beacon_framework-1.11.0-py3-none-any.whl
- Upload date:
- Size: 236.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
26e49e43079e7035aa5133858af0c477f1351739ed4422ac3b2060569a680f5c
|
|
| MD5 |
16d4a9c73caf51c7eaaa5531b6d22d83
|
|
| BLAKE2b-256 |
d77f97b479824b4d8c0ab74994e4dbb41c62c72c24e107d40447436c5c8263bc
|
Provenance
The following attestation bundles were made for beacon_framework-1.11.0-py3-none-any.whl:
Publisher:
release.yml on darth-veitcher/beacon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
beacon_framework-1.11.0-py3-none-any.whl -
Subject digest:
26e49e43079e7035aa5133858af0c477f1351739ed4422ac3b2060569a680f5c - Sigstore transparency entry: 2019253487
- Sigstore integration time:
-
Permalink:
darth-veitcher/beacon@61cc2b55a6e8751e92820e7bfebea45ab96cf099 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/darth-veitcher
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@61cc2b55a6e8751e92820e7bfebea45ab96cf099 -
Trigger Event:
push
-
Statement type: