A Claude Code plugin that orchestrates multi-task workflows through a structured research-plan-implement-review lifecycle. Named after the obvious — a fellowship of agents, each on their own quest, coordinated by a wizard who never writes code.
Fellowship gives Claude Code a disciplined workflow engine. Instead of diving straight into code, a task goes through four phases with a hard gate leaving each of the first three: research the system, plan the changes, implement with TDD, then review — an adversarial pass, conventions, verification, and the PR.
For multiple independent tasks, it spins up parallel agent teammates — each in an isolated git worktree — coordinated by a lead agent (Gandalf) who routes approvals and reports progress.
From within Claude Code, run these as two separate commands:
/plugin marketplace add justinjdev/claude-plugins
/plugin install fellowship@justinjdev
Fellowship's /quest skill orchestrates skills from these plugins. Install them for the full workflow:
| Plugin | Skills used | Phase |
|---|---|---|
| superpowers | writing-plans, test-driven-development, verification-before-completion, finishing-a-development-branch |
Plan, Implement, Review |
| pr-review-toolkit | review-pr |
Review |
These are referenced by name in skill prompts. If a dependency isn't installed, Claude performs the step's goal manually and notes the substitution in its output — but you lose the structured discipline the dedicated skill provides.
/plugin marketplace add obra/superpowers-marketplace
/plugin install superpowers@superpowers-marketplace
/plugin install pr-review-toolkit@claude-plugins-official
- Go CLI binary — gate enforcement hooks use a Go binary that is installed once per session by the
SessionStarthook, downloaded from GitHub releases with its checksum verified against the release'schecksums.txtbefore it's installed. No manual installation required. Hooks never trigger the download themselves: if one runs before that install has completed (or after it failed), it blocks with a message telling you to restart the session or runensure-binary.shdirectly.
Add this hook to .claude/settings.local.json in repos where you use fellowship. It prints a one-line hint when a /lembas checkpoint from a previous session is lying around, so you know recovery is available:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "if [ -f .fellowship/checkpoint.md ]; then echo \"fellowship: a checkpoint from a previous session is present at .fellowship/checkpoint.md — run /rekindle to recover the fellowship, or /quest to resume a single quest.\"; fi"
}
]
}
]
}
}It is a convenience only: it prints the hint and nothing else. Resuming is always something you ask for — see Resuming after a crash.
Also add the fellowship data directory to your .gitignore — checkpoints and state are local ephemeral files. Keep .fellowship/config.json trackable, though: it holds committable team-shared settings (see /settings):
.fellowship/*
!.fellowship/config.jsonIf you have configured a custom dataDir in ~/.claude/fellowship.json, use that directory name instead.
Create ~/.claude/fellowship.json in your personal Claude directory to customize fellowship behavior across all projects. All settings are optional — missing keys use sensible defaults that match the out-of-box behavior.
{
"dataDir": ".fellowship",
"branch": {
"pattern": null,
"author": null,
"ticketPattern": "[A-Z]+-\\d+"
},
"worktree": {
"enabled": true,
"directory": null
},
"gates": {
"autoApprove": []
},
"pr": {
"draft": false,
"template": null
},
"palantir": {
"enabled": true,
"minQuests": 2
},
"issues": {
"autoClose": true
},
"failures": {
"expiryDays": 90
},
"models": {
"quest": null,
"scout": null,
"palantir": null,
"balrog": null,
"explore": null,
"validator": null
}
}Enforced by marks how a setting takes effect: "Binary" settings are read and applied by the fellowship Go CLI itself; "Prompt" settings only take effect because the agent reads the merged config and follows it — no CLI code enforces them structurally.
| Setting | Default | Enforced by | Description |
|---|---|---|---|
dataDir |
".fellowship" |
Binary | Directory name for fellowship working files (state, checkpoints, todos, history). Created inside each worktree and the main repo root. |
branch.pattern |
null |
Prompt | Branch name template with placeholders: {slug} (task description), {ticket} (extracted from description), {author} (from config). When null, defaults to "fellowship/{slug}". |
branch.author |
null |
Prompt | Static value for the {author} placeholder. If not set and pattern uses {author}, you'll be prompted. |
branch.ticketPattern |
"[A-Z]+-\\d+" |
Prompt | Regex to extract ticket IDs from quest descriptions. Default matches Jira-style IDs (e.g., PROJ-123). |
worktree.enabled |
true |
Prompt | Whether quests create isolated worktrees. Set to false to work on the current branch. |
worktree.directory |
null |
Prompt | Parent directory for worktrees. null uses Claude Code's default (.claude/worktrees/). |
gates.autoApprove |
[] |
Binary | Gate names to auto-approve: "Research", "Plan", "Implement" (the phase being left — "Research" auto-approves Research→Plan). "Review" is not a valid entry: it is the last phase and no gate leaves it. fellowship init reads the merged value when it creates a quest's state and fails with a clear error on an unknown phase name. Gates not listed still surface to you for approval. |
pr.draft |
false |
Prompt | Create PRs as drafts. |
pr.template |
null |
Prompt | PR body template string. Supports {task}, {summary}, and {changes} placeholders. |
palantir.enabled |
true |
Prompt | Whether to spawn a palantir monitoring agent during fellowships. |
palantir.minQuests |
2 |
Prompt | Minimum active quests before palantir is spawned. |
issues.autoClose |
true |
Prompt | When true, /missive includes Closes #N in PR keywords so issues close on merge. |
failures.expiryDays |
90 |
Binary | Days before a quest failure record expires and is eligible for cleanup. |
models.quest |
null |
Prompt | Model for quest teammates. Valid values: "haiku", "sonnet", "opus" (aliases only — spawn parameters accept neither "inherit" nor full model IDs; leave null to inherit). null = built-in default: inherit the session model. |
models.scout |
null |
Prompt | Model for scout teammates. Same valid values. null = built-in default: sonnet. |
models.palantir |
null |
Prompt | Model for the palantir monitor. Same valid values. null = built-in default: haiku. |
models.balrog |
null |
Prompt | Model for balrog adversarial review. Same valid values. null = built-in default: inherit the session model. |
models.explore |
null |
Prompt | Model for Explore scan subagents spawned by quest, scout, council, and guide. Same valid values. null = built-in default: haiku. |
models.validator |
null |
Prompt | Model for scout's validation subagent. Same valid values. null = built-in default: sonnet. |
The config is read at fellowship startup and at the start of a quest's Research phase. Changes to the file take effect on the next fellowship or quest invocation.
Skills are invoked automatically by Claude as part of a workflow (quest phases, context compression, etc.) — you can also invoke any of them directly with /name.
| Skill | Purpose |
|---|---|
/quest |
Full Research → Plan → Implement → Review lifecycle for non-trivial tasks. The hub that orchestrates everything else. |
/fellowship |
Multi-task orchestrator. Spawns parallel agent teammates running /quest (code) or /scout (research). |
/scout |
Research & analysis workflow. Investigates questions, optionally validates with a fresh adversarial subagent. No code, no PRs, no commits. |
/council |
Context-aware onboarding you invoke yourself. Loads task-relevant files, conventions, and architecture at session start. Quest inlines the same orientation, so it does not call this. |
/gather-lore |
Studies reference files to extract conventions before writing code, on request. Quest inlines the same extraction, so it does not call this. |
/lembas |
Context compression between phases. Writes a checkpoint and continues from it, keeping the context window in the reasoning sweet spot. |
/warden |
Pre-PR convention review. Compares changes against reference files and documented patterns. |
/missive |
Fetches GitHub issue context for quest spawning — title, body, labels, comments, branch suggestions, and PR close keywords. |
/retro |
Post-fellowship retrospective. Analyzes gate history, palantir alerts, and quest metrics, then recommends configuration improvements. |
/lorebook |
Loads phase-specific guidance from an assigned quest template at the start of each quest phase. Ships one built-in example template to copy. |
Commands are user-invoked only — Claude never calls them automatically, so they carry no base context cost.
| Command | Purpose |
|---|---|
/chronicle |
One-time codebase bootstrapping. Walks through your project to extract conventions into CLAUDE.md. |
/dashboard |
Starts the live web dashboard for the current fellowship — quest/scout progress, gate approvals, event history — in the background, and prints the URL. |
/guide |
Interactive, learn-by-doing walkthrough of fellowship using a real task on your codebase. |
/red-book |
Post-PR convention capture. Extracts conventions from reviewer comments and adds them to CLAUDE.md. |
/rekindle |
Recovers a fellowship after a session crash — scans worktrees and quest state, then re-spawns Gandalf with recovered context. |
/scribe |
Creates a reusable quest template that encodes project-specific rules and conventions into phase guidance. |
/settings |
View or edit fellowship settings (~/.claude/fellowship.json). Interactive setup for all configuration options. |
| Agent | Role |
|---|---|
| palantir | Background monitor during fellowship execution. A thin reporter over the CLI's health sweep (fellowship health — the same stalled/zombie/struggling classification events --problems and the dashboard read) plus scope-drift and file-conflict checks read from each quest's history. Reports to Gandalf. Defaults to the haiku model. |
| balrog | Adversarial validation agent spawned by quest as the first step of Review. Analyzes the diff for failure modes, writes and runs targeted test cases, and delivers a severity-ranked findings report. |
| scout | Research & analysis agent spawned as a fellowship teammate for read-only investigation — no code edits, no git operations. Defaults to the sonnet model. |
| validator | Read-only adversarial validator spawned by scout to verify research findings against the actual code (CONFIRMED/CONTESTED/UNVERIFIED). Tools restricted to Read/Glob/Grep. Defaults to the sonnet model. |
Single task — run /quest:
Four phases, three gates. A gate leaves Research, Plan, and Implement; nothing leaves Review — the quest ends inside it, when the PR is open and the task is marked complete.
Research → worktree + orientation, prior art, explore agents, convention study
──[GATE]─→
Plan → plan mode with file:line references + user approval
──[GATE]─→
Implement → TDD (red-green-refactor), todo tracking
──[GATE]─→
Review → balrog attacks the implementation (edge cases, error paths)
→ /warden conventions → code quality → verification
→ PR creation + worktree cleanup
/lembas compacts context between every phase.
Research — run /scout:
Investigate → (Validate) → Deliver
Autonomous research with confidence levels. For complex questions, spawns a fresh validator subagent to adversarially verify findings. Produces a structured report — no code changes, no PRs.
Multiple tasks — run /fellowship:
Gandalf (the coordinator) spawns quest and scout teammates. Quests run in isolated worktrees and produce PRs. Scouts research questions and deliver findings. Say "status" to see a progress table. By default, all quest gates surface to you for approval — auto-approve specific gates via ~/.claude/fellowship.json (see Configuration).
Health monitoring — fellowship health is the one classifier behind stalled/zombie/struggling detection; fellowship events --problems and the dashboard read the same sweep. With 2+ quests active (configurable via palantir.minQuests), Gandalf spawns palantir to report it continuously; below that threshold, or with palantir.enabled: false, Gandalf runs the sweep itself after gate transitions and spawns, so health monitoring never depends on an extra agent.
A /lembas checkpoint at .fellowship/checkpoint.md is what a dead session leaves behind. Exactly three things read it, and each has one job:
| Reads the checkpoint | When | |
|---|---|---|
| quest's Research step 0 | Yes | Inside a running quest. This is the only checkpoint check during a quest — a resumed teammate picks up at the phase its state records. |
/rekindle |
Yes | Outside a quest, after the whole fellowship died. Scans worktrees, classifies each quest, and respawns them with the resume spawn prompt. |
| The SessionStart hook above | No | At session start. Prints a hint that a checkpoint exists; it never resumes anything. |
/council does not check for checkpoints. It is orientation for a fresh task, nothing more.
Gate enforcement — gates are structurally enforced via plugin hooks. After a teammate submits a gate, their work tools (Edit, Write, Bash, etc.) are blocked until the lead approves (fellowship gate approve --dir <worktree>). Prerequisites — running /lembas and confirming the phase (fellowship phase confirm --dir <worktree> --phase <phase>) — are verified before gate submission is allowed. Self-approval is structurally impossible.
- Context is the bottleneck. Compact between every phase. Don't let research noise degrade implementation reasoning.
- Hard gates prevent drift. No planning without understanding. No implementing without a plan. No PR without review.
- Compose, don't rebuild. Skills call other skills. No new runtime code — just orchestration over Claude Code primitives.
- Human in the loop. By default, all gates require your approval. You can opt into auto-approval for specific gates via config. Gandalf never merges PRs.
- Isolation by default. Every quest gets its own worktree. No shared in-progress state.
- Local scope only. Teammates are restricted to code, tests, git, and the filesystem. MCP tools and external services (Notion, Slack, Jira, etc.) require explicit approval.
-
Gates are a question, not a keyword — Gandalf now surfaces each gate with
AskUserQuestion(Approve / Reject with feedback / Hold) after showing the teammate's gate message, one quest's gate per question. Typing "approve" still works. -
Teammates run the full lifecycle — a fellowship teammate could take
/quest's escape hatch for a small task, skipfellowship init, and finish with no gate ever submitted; with no state row the hooks had nothing to enforce. The escape hatch is now standalone-only, the spawn prompt says so, and untilfellowship inithas run in a registered worktreegate-guardallows only what bootstrap needs: Edit/Write into the data directory (a plan-driven quest copies its plan there), the fellowship CLI minus the lead'sstatecommands, read-only git, and read-only shell builtins with no redirection — a source write, a heredoc, agit commitall wait forinit. A[COMPLETE]with no gate history is a violation, not a finished quest. -
Hooks allow outside a git repository — a session started in a directory that is not inside any repo had every Bash, Edit and Write call blocked by
gate-guard"for safety": the store lookup surfaced git's "not a git repository" as an unreadable store. Outside a repo there is nothing to enforce, so it now reads as "no fellowship here" and hooks allow;fellowshipcommands report "no fellowship state" instead of a git error. -
Ported to the implicit-team API — Claude Code removed
TaskCreate,TaskUpdate,TaskGet,TaskList,TeamCreate,TeamDelete, and theshutdown_requestprotocol. The plugin now spawns teammates as named background agents (Agent(name: ...)), addresses them withSendMessage(to: <name>)(which resumes an idle teammate with its context intact), and stops them withTaskStop. Quest identity is the quest name, and the store (state add-quest/update-quest/show --json) is the only coordination state —--task-idflags are gone (thetask_id/team_namecolumns stay in the schema, unused, so no migration is needed). The metadata prerequisite is nowfellowship phase confirm --dir <worktree> --phase <phase>(same validation: a valid phase equal to the quest's current phase), and completion isfellowship complete --dir <worktree>(allowed only in Review with no gate pending, enforced by the command and by gate-guard's refusal of the Bash form) — each replacing a TaskUpdate hook (metadata-track,completion-guard) that no longer had anything to fire on. Teammates end their turn after a[GATE]message and are resumed by the lead's nextSendMessage; a[COMPLETE]envelope carries the PR URL; scouts report with[REPORT]; palantir droppedTaskGet/TaskList. Identity under the implicit team: a hook payload is the lead only when its session id matches the recorded lead's and it carries noagent_id(a background agent shares the lead's session id, so anagent_idin the payload is what marks it as a subagent, never the lead);fellowship initnow records a session id against a quest only when it differs from the recorded lead's, andinit --phase/--plan-skipon an existing quest additionally requires the process to be standing in the main working tree. Also: unknowngates.autoApprovenames are now ignored with a warning instead of failingfellowship init, and the out-of-date-store block message now says the upgrade command must be run alone. In-process teammates keep the lead's working directory for their whole life — a barecddoes not persist between their Bash calls — so hooks resolve a subagent's quest from the--diror file path its tool call names, backed by anagent_questsmapping (schema migration 6) that a new PostToolUseBashhook,agent-track, records after the teammate's firstfellowship init --dir <worktree>. Teammates now address everything by--dir <worktree>and absolute paths rather than relying on their cwd;fellowship complete --dir <X>is judged against the quest that--dirnames, andgate-submitreturns the wholetool_inputwith onlymessagerewritten. -
CLI correctness and cleanup —
--dirvalues that are relative (.,sub,../x) now resolve correctly instead of only working from an absolute path (gitutil.MainRepoRootwas joining a relativegit rev-parse --git-common-diranswer onto a possibly-relative input). Re-registering a worktree under a new quest name (e.g. after a respawn) no longer fails on the worktree's unique-index constraint — the previous holder's worktree is cleared and the reassignment is reported. The dashboard's gate approve/reject endpoints now share the same state machine asfellowship gate approve|rejectand group batch approval, so a dashboard decision records gate/phase history, not just events.fellowship health's report and the dashboard's health badges now carry each quest's worktree, matched in the UI by quest name as a fallback; the dashboard's "Implement+" count no longer silently assumes a fixed four-phase order.group show --jsongained aprogressfield.todo initno longer accepts a--taskit silently discarded, andtodo shownow emits"items": []instead ofnullfor a quest with no todos yet. Gate approvals now record a realduration_sfor the phase completed, instead of always0. -
Closed four ways past the gates — each of these let a quest advance or write where it should not, and each is now blocked with the honest path left open. (1)
fellowship init --phase X(or--plan-skip) on a quest that already exists rewrote its phase and then passed gate-guard, because the same command clears the pending flag the guard checks — a teammate could go from Research to Implement with no gate ever submitted. On an existing questinitnow only resets the gate and prerequisite flags; the phase moves only for the recorded lead, and gate-guard refuses the Bash form. (2) The lead marker lived at<data-dir>/lead, inside the one directory every write guard exempts, so a teammate could write its own session id into it and become "the lead" — and lock the real one out. The lead now lives in the store (leadtable, schema migration 4), which nothing writes through Edit/Write; the marker file is read for one release only when the store names no lead. Edit/Write aimed atfellowship.dbitself is refused in every phase. (3) Deleting or truncating the store turned every gate hook into an allow, and a zero-byte store was silently rebuilt into a fresh one by the first hook that opened it. A fellowship is now expected wherever the main worktree has a data directory holding more than the committableconfig.json(a fresh clone of a repo that ships one has never run a fellowship): gate hooks block when the store is missing or empty there, onlyinit/state initmay create or migrate a schema, and a quest whosequest_staterow disappears after it has already recorded history blocks instead of falling back into the bootstrap window. (4)worktree-guardonly looked at where the session stood, so a teammate that stayed in its own worktree and wrote an absolute path into the main tree was never examined; it now resolves the target file's own working tree, and scopes the.git/.claude/data-directory exemption to the session's own tree. -
Lead commands do not run inside a quest worktree —
fellowship state ...is the lead's own command set, andstate initrecords which session is the lead. A teammate could runcd <main-repo> && fellowship state init --claim-leadin a single Bash call and become the recorded lead — after which it moved its own phase and wrote in the main tree, while the real lead was refused.gate-guardnow refuses anyfellowship statecommand (and anyinit --phase/--plan-skip) from a registered quest worktree, scanning the whole command line: through&&/;/|, through command substitution and subshells ($(...), backticks,(...)) even inside double quotes, throughsh -c "..."andeval, and by any path to the binary. Behind it,state initno longer re-records a lead that is already recorded — that is--claim-lead's job, and--claim-leadrefuses a session thatfellowship initrecorded against a quest (quest_state.session_id, added by schema migration 5). -
A finished fellowship stops blocking its repo — the unregistered-worktree rule asked whether a fellowship row existed, and that row is never deleted, so one
fellowship state initmade every other linked worktree of the repo unusable forever. It now asks the same questionworktree-guarddoes: is any quest actually live? -
dataDiris read from the main repo — hooks resolved the configured data directory name from the session's own worktree, where the project config never is, so a fellowship that setdataDirhad its hooks exempting.fellowshipwhile every coordination write went elsewhere. Hooks resolve it from the main repo root now, exactly as the store path does, andfellowship state initwrites the fellowship, the lead andsettings.local.jsonat the main root rather than in whatever worktree it was run from. -
fellowship state init --claim-lead— re-records the running session as the fellowship's lead without re-initializing anything else (pass it alongside--namewhen a re-init should take the lead too). It runs only from the main working tree — a door back into the lead row that a teammate in its own worktree cannot use. It is the way out of the case where the lead's session id changes mid-fellowship (a new session in the main tree rather than a resumed one) and the guard starts refusing the lead's own writes; anyfellowshipcommand run in the main tree from a non-lead session now says so in one line, andstate initwarns when noCLAUDE_CODE_SESSION_IDis available to record. -
Smaller enforcement fixes — a held teammate can once again run the read-only escape commands (
status,gate status,history,events,health,failures,notes,todo), so it can see why it stopped;metadata-trackrequires the task metadata to name a valid phase that is the quest's current one, instead of accepting any non-empty string as the gate's metadata prerequisite; hooks never run schema migrations and the two that only decide hold a read-only connection; and hook git calls run under the hook's own 2s deadline. -
CLI subcommand nouns renamed to plain words — the CLI's Tolkien-flavored subcommand nouns are now plain English, matching their Go packages:
herald→events,tome→history,errand→todo,eagles→health,bulletin→notes,autopsy→failures,company→group(andstate add-company→state add-group). Skill and agent names are unaffected — this only touches the seven reporting/side-channel subcommand nouns above. Each old name still works for one release: running it prints one deprecation line to stderr, then runs the renamed command. Thefailures.expiryDaysconfig key replacesautopsy.expiryDays(no alias — update~/.claude/fellowship.jsonand any project.fellowship/config.json). SQLite table and column names are unchanged (no schema migration):herald,bulletin/bulletin_files,autopsies/autopsy_files/autopsy_modules/autopsy_tags,errands/errand_deps, andcompanies/company_memberskeep their existing names under the renamed packages. -
One health classifier, reachable everywhere —
fellowship healthandfellowship events --problemswere two separate Go implementations of the same stalled/zombie classification, and palantir carried a third copy in prose driven by unboundedgit diff/git statusover each worktree.events.DetectProblemsnow delegates to health's sweep (which gained astrugglingclassification — repeated gate rejections in a quest's current phase, independent of itshealth), andhealth.WriteReportand the.fellowship/health-report.jsonfile it wrote (nothing read it) are gone. palantir is now a thin reporter over that one sweep: it runsfellowship health --jsonandfellowship state show --jsoninstead of reconstructing stuck/stalled from task metadata, and reads scope-drift/file-conflict signals from each quest's history (history show --json'sfiles_touched) instead of diffing worktrees itself. Belowpalantir.minQuestsor withpalantir.enabled: false, Gandalf runs the same sweep itself after every gate transition and spawn, so health monitoring never depends on an extra agent./rekindleand/retroread quest state and phase/health the same way instead of shellinggate status --dir <worktree>per quest.state show(always JSON, but had no flag to name that) andgroup show <name>(table-only before) both accept--jsonnow. -
Four phases, three gates — The quest lifecycle is now Research → Plan → Implement → Review. Onboard's work (worktree provisioning, context loading, the checkpoint resume check) is the first step of Research; the adversarial balrog pass is the first step of Review and PR creation the last. A gate leaves Research, Plan, and Implement; nothing leaves Review, so the quest ends inside it when the PR is open and the task is marked complete — which
completion-guardnow allows only in Review with no gate pending. Validgates.autoApproveentries are the three gate-bearing phases. A schema migration rewrites stored phase names (live state, phase and gate history, and each quest'sautoApprovelist) in existing stores, and the pre-2.0 JSON importer runs through the same table, so an in-flight quest keeps advancing across the upgrade. -
/questand/fellowshipare half the size —quest/SKILL.mdwent from ~25 KB to ~15 KB andfellowship/SKILL.mdfrom ~21 KB to ~15.5 KB. Quest inlines the orientation/councildid and the pattern extraction/gather-loredid rather than invoking them, so a quest no longer hands its phase vocabulary to two satellite skills that then have to track it; both remain as skills you invoke yourself. Fellowship's isolation pre-flight and provisioning protocol moved toresources/isolation.md, and Gandalf's voice toresources/lead-behavior.md. -
/lembasstops asking for/compact— It ended by telling the user to run a command Claude cannot run, so the step was either ignored or handed over as a chore. It now writes the checkpoint and continues from that summary, which is what the checkpoint was always for. -
One checkpoint reader per context — Four things looked for a
/lembascheckpoint and disagreed about who resumes. Now quest's Research step 0 is the only checkpoint check inside a quest,/rekindleis the recovery path outside one, and the README'sSessionStarthook only prints a hint./councilno longer looks for one at all. See "Resuming after a crash". -
/rekindleshares the spawn template — It carried a hand-copied quest spawn prompt with an undefined{gate_config_override}placeholder.spawn-prompts.mdgained a RESUME variant and rekindle references it, so gate, hold, isolation, and boundary language has one home. -
Quest templates ship with one — Templates were a feature with nothing in it.
/lorebooknow resolves a built-in directory after project and user, and fellowship shipsexample— a worked template at the specificity the docs ask for, with no keywords so it never auto-suggests./lorebookand/scribeboth cover all four phases, and Review's section is the last guidance a quest loads. -
/dashboardcommand — Starts the fellowship web dashboard in the background and prints its URL. The dashboard's own company gate approval now sharescompany.BatchApprovewith the CLI'sfellowship company approveinstead of a second, drifted copy that skipped tome recording. The core fellowship state model (FellowshipState,QuestEntry,CompanyEntry, and their SQLite CRUD) moved out of thedashboardpackage into a newcli/internal/fellowshippackage, removing the import cycle that forcedcompanyto duplicate that batch-approve logic. The dashboard's/api/statusresponse now includes aphasesfield so the UI's phase list tracks the server instead of a hardcoded array (which was previously missing the Adversarial phase). -
Installer hardening — the mkdir-based install lock in
ensure-binary.shnow records its holder's PID and acquisition time, so a session killed mid-install (kill -9, OOM) no longer wedges every future install: a contending session reclaims the lock once the recorded PID is no longer alive, or once 120s have passed regardless. Leftover.install.*scratch dirs from a killed install are swept once they're 10 minutes old.fellowship.shno longer installs the binary itself on behalf of a gate hook (gate-guard,gate-submit,gate-prereq,completion-guard,metadata-track,file-track) — only theSessionStarthook does that — so a hook can no longer trigger a network download on the critical path of the tool call it's guarding; if the binary isn't installed yet, the hook blocks immediately with a message pointing atensure-binary.shinstead.ensure-binary.shalso tries apython3ornodefast path for readingplugin.json's version before falling back to its awk-based parser. -
The lead is no longer locked out of the main tree —
worktree-guardblocked everyEdit/Writein the main working tree while a fellowship was active, including the lead's own.fellowship state initnow records the lead's Claude Code session in aleadmarker inside the data directory, and the guard allows that session, blocks a quest worktree that resolves to the main root, blocks a session that is known not to be the lead, and allows anything it cannot identify. -
dataDirmoves the store too — the fellowship database was always created in.fellowship/even whendataDirnamed a different directory, so the store and everything that reads it lived in different places. The store now follows the configured data directory. -
hold/unholdreport an unregistered--dir— instead of guessing the quest from the directory's name, which could hold a different quest that happened to share it. -
One gate state machine — approve, reject, submit and reset are single functions in the state package, used by
gate approve|reject, group batch approval, the auto-approve path and the resets. Auto-approved gates now clear the gate id and record the approval and phase transition in the history and events log, exactly as a lead approval does; a held quest can no longer submit a gate; andfellowship initandstate clean-worktreesreset the lembas/metadata flags along with the gate flags. -
Fail-closed hook dispatch — Gate hooks (
gate-guard,gate-submit,gate-prereq,completion-guard,metadata-track,file-track) now run throughplugin/hooks/scripts/fellowship.shinstead of exec'ing the binary directly; if the binary is missing and can't be installed, they block (exit 2) instead of silently allowing the tool call through a shell "command not found".worktree-guardkeeps its fail-open backstop posture. Thefile-trackhook is now wired intohooks.json(it existed in the CLI but wasn't invoked), andSessionStartnow installs the binary onclearandcompactin addition tostartup/resume. -
Verified downloads —
ensure-binary.shverifies the downloaded tarball against the release'schecksums.txt(sha256sum/shasum) before installing, assembles the binary in a scratch directory and moves it into place atomically, and holds a simple lock so concurrent sessions don't race the same install. -
CI — added
gofmt -l .,go vet ./...,go test -race ./...,shellcheckon the hook scripts, a check that every path in.claude-plugin/plugin.jsonexists, and asite/build job. -
Tightened skill triggers —
quest,council,gather-lore, andwardendescriptions now name their actual invocation scope instead of "any non-trivial task", reducing over-triggering. -
Removed orphaned
quest-runneragent — never spawned (quest teammates usegeneral-purpose); removed from the plugin manifest, README, and the site's Agents and How It Works pages. -
Documentation drift fixes — corrected
gates.autoApprovevalid values on the site config page, replaced the removedusing-git-worktreesdependency withwriting-plans(Plan phase), added the missing v1.6.1 changelog entry, fixed the quest phase/gate count, documentedfailures.expiryDaysand added the missingdataDirrow to/settings' schema table, corrected the.fellowship/gitignore wording in lembas, corrected palantir's Bash tool description, and fixed several command titles and skill/command wording. -
Archived the
gate-state-machineOpenSpec change — superseded by the Go CLI + SQLite gate enforcement design (v1.5.1–v2.2.0); moved toopenspec/changes/archive/with a SUPERSEDED note. -
Documented CLI invocations now work —
--dir <path>is accepted bygate status|approve|reject,state add-quest|add-scout|add-group|update-quest|show,todo init|list|add|update|show,failures create|scan|infer, andhistory show, resolving the quest exactly as if the process were running in that directory.gatepreviously had no flag parsing at all, so every documented--dircall failed. -
fellowship initname resolution — Without--quest, init now uses the quest name the lead registered withstate add-questfor that worktree, falling back to the directory name only when the worktree is unregistered. -
fellowship initreadsgates.autoApprove— Auto-approved gates come from the merged config (project.fellowship/config.json, then~/.claude/fellowship.json) instead of always being empty. Unknown phase names are rejected. -
fellowship statushonors the base branch — Merged-branch detection compares against the fellowship's storedbase_branchinstead of a hardcodedmain. -
fellowship events post— Records a tiding from the CLI, so the palantir logs alerts withoutjqor a hand-written JSONL file.eventsgained--questand--limit;failures scan --allreturns every unexpired failure record. -
Prompt layer matches the binary — Skills, agents, and commands now call the CLI by its full path, use only flags that exist, and read state through the CLI instead of the pre-2.0 JSON files (
quest-state.json,fellowship-state.json,quest-tome.json,quest-herald.jsonl,quest-errands.json,palantir-alerts.jsonl,autopsies/).
- Model routing — Every subagent spawn point now routes to a cost-appropriate model: palantir defaults to
haiku, scout and the validator tosonnet, Explore scans tohaiku, while quest teammates and balrog keep the session model. Override any role via the newmodels.*config block. - Validator agent — Scout's adversarial validation runs in a dedicated read-only agent (Read/Glob/Grep only, enforced by tool restrictions) instead of an unrestricted general-purpose subagent.
- Mode-aware gate accounting — The lead verifies quest completion against the gates the quest's mode actually requires: 6 for standard/promoted quests (Adversarial included), 3 for plan-driven. Progress tracking and phase enumerations now include Adversarial everywhere.
- Spawn prompt consolidation — The three quest spawn prompt variants collapsed into one base template with per-variant deltas, eliminating ~250 lines of drift-prone duplication and unifying hold/shutdown language.
- Project config layer — Fellowship startup and quest onboard now merge
.fellowship/config.json(project) with~/.claude/fellowship.json(user) as defaults → project → user, matching/settings. - CLI phase fix —
fellowship init --phase Adversarialwas rejected and company progress ranked Adversarial-phase quests as zero; phase lists now derive from a single canonical order in the state package. - Messaging protocol fixes — SendMessage recipients are teammate names (task-ID addressing never delivered); balrog and scout embed the full report envelope inline; balrog gained Write/Edit scoped strictly to test files ("report, don't repair").
- Docs refresh — README and site document all 10 skills, 6 commands, and 5 agents; the skills page separates auto-invoked skills from user-invoked commands;
/validate-docsgained a config-schema cross-check.
- Worktree isolation guard — A fail-closed hook blocks quest teammates from writing source into the main working tree when isolation is skipped.
fellowship state initregisters it in the git-ignored.claude/settings.local.json(no commits to your repo), and it arms only while a quest worktree is live, so it never blocks ordinary solo work. - Lead cd-guard hardening — Gandalf is now blocked from
cd-ing into quest worktrees created outside.claude/worktrees/(e.g. lead-provisioned worktrees), preventing the lead from inheriting a quest's gate or hold state.
- SQLite storage — All state (quests, gates, tome, errands, herald, bulletin, autopsy) migrated from JSON files to SQLite with WAL mode. Eliminates file locking issues and race conditions in parallel quests. Run
fellowship migrateto upgrade existing data. - Interactive
/guide— Rewrote the guide from a passive concept explainer to a learn-by-doing walkthrough. Walks beginners through a real quest on their own codebase, then introduces/questand/fellowship. - Concepts page — New docs site page explaining agentic workflows, orchestration, isolation, context engineering, and human-in-the-loop.
- Quest autopsy — Failure memory that persists across sessions. When a quest fails, records what went wrong so future quests can learn from past failures.
- Bulletin board — Cross-quest knowledge sharing. Quests post discoveries to a shared bulletin during Research and Implement.
- Gate enrichment — Gate submissions now include structured context (diff stats, test results, phase summary) for informed approval decisions.
- WorktreeGuard — Blocks the lead session from accidentally
cd-ing into quest worktrees.
- Stale gate state fix — Gate guard hook no longer blocks Gandalf when a previous quest's gate state file is present in a fresh worktree. Prevents stale state from causing spurious tool blocks at session start. (#56)
- Fellowship startup fix —
ensure-binary.shnow runs before any fellowship operations, removing the PATH dependency. All CLI calls use the full binary path (~/.claude/fellowship/bin/fellowship). state initoverwrite warning — Instead of erroring whenfellowship-state.jsonalready exists,fellowship state initnow warns and proceeds (shows existing name and quest count).validate-docsmarketplace check — Validates that skill and agent counts in the marketplace description match the actual plugin.- Deprecated commands removed —
fellowship installandfellowship uninstallCLI subcommands removed.
/missiveskill — Fetches GitHub issue context for quest spawning. Pulls title, body, labels, and comments viaghCLI. Returns issue context, suggested branch name (with issue number), and PR closing keywords. Gandalf invokes it automatically on#Nreferences; also usable standalone as/missive 42.- Balrog agent — Adversarial validation agent. Reviews code for structural quality: factoring, coupling, cohesion, abstraction levels, information hiding. Challenges every design decision, not just obvious violations.
- Per-project config — Committable
.fellowship/config.jsonfor team-shared settings. Three-way merge: defaults → project → user (user always wins)./settingsshows merged config with provenance annotations. issues.autoCloseconfig — When true (default),/missiveaddsCloses #Nto PR keywords so issues close on merge.- Base branch fixes — Worktrees receive the correct base branch; handles detached HEAD and dirty working tree edge cases.
- Scout-to-quest promotion — Say
promote scout-X to a questduring a fellowship. Gandalf reads the scout's findings file, spawns a quest pre-loaded with the research, and the quest enters validation mode instead of researching from scratch. /retroskill — Post-fellowship retrospective. Analyzes gate history, palantir alerts, and quest metrics. Recommends configuration changes like auto-approving gates with zero rejection rates. Integrated into the fellowship disband flow.- Plan-driven quests — Provide a pre-existing plan file and quests skip Research and Plan phases, jumping straight to Implement. Gandalf can fan out large plans into multiple parallel quests.
- Structured conflict resolution — Hold mechanism for quests with file conflicts. Gandalf detects overlapping file sets and holds conflicting quests until dependencies complete.
- Herald logging — Dashboard gate handlers and company batch approve now emit herald events for observability.
- Palantir alert persistence — Alerts persisted to JSONL log for post-fellowship analysis by
/retro. /releasecommand — Repo-level release automation. Suggests version based on conventional commits, audits docs/site/changelog, bumps plugin.json, tags, pushes, and updates marketplace.
- Fix — Hook binary distribution fixes (v1.7.1–v1.7.5). Use binary directly in hooks, bootstrap via SessionStart, remove duplicate hook installation.
- Eagles — quest health monitoring daemon. Detects stuck quests, scope drift, and file conflicts via periodic patrol scans.
- Tome — persistent agent identity with quest CV chains. Tracks phases completed, gate history, and files touched across quest lifetimes.
- Company — work bundling for quest grouping. Groups related quests into a company for coordinated tracking and status reporting.
- Herald — activity feed with event logging, problem detection, and dashboard integration. Surfaces quest events and auto-detected problems.
- State CLI —
fellowship statecommands for inspecting and managing quest state, plusfellowship state add-companyfor company management. - File locking — mutex-based file locking for concurrent state mutations across parallel quests.
.fellowship/data directory — working files (state, checkpoints, errands, tome) now use.fellowship/instead oftmp/. Configurable viadataDirsetting.- CI — PR workflow to run Go tests on pull requests.
- LOTR theming — renamed internals: patrol→eagles, convoy→company, cv→tome, events/feed→herald.
- Shared helpers — extracted common git/file utilities into
internal/gitutilpackage. - Fix — phase tracking for auto-approved gates and pending submissions.
- Fix — hook errors silenced in non-quest contexts.
- Fix plugin discovery — moved
.claude-plugin/plugin.jsonto repo root with explicit path fields for skills, agents, commands, and hooks. Fixes skills not showing up after install.
- GitHub Pages site — SvelteKit static site with LOTR theme, all documentation pages, and CI deployment.
/rekindleskill — Crash recovery. Scans worktrees and state files, presents a recovery dashboard, and re-spawns Gandalf with recovered quest context./lorebookskill — Loads phase-specific guidance from quest templates created by/scribe.- Skills to commands migration — 5 user-only skills moved to
commands/for lower base context cost. - LOTR theming — Internal renames: convoy → company, cv → tome, patrol → eagles, work/hook → errand, events/feed → herald.
/scoutskill — research & analysis workflow for lightweight research teammates alongside code quests. Autonomous (no gates/hooks), optional adversarial validation via fresh subagent. (#12)- Fellowship scouts — Gandalf learns to spawn scouts via
"scout: <question>"alongside code quests, with status tracking and optional routing to other teammates.
- Go CLI —
fellowshipbinary replaces bash hook scripts. Handles hook logic, gate approval/rejection, install/uninstall, and status. Distributed via GitHub releases, auto-downloaded on first use. - Plugin subfolder — plugin files moved to
plugin/for clean installs via marketplacegit-subdir. Go source, CI, and build config stay at repo root. - Quest runner agent —
agents/quest-runner.mdfor CLI-driven quest execution. - BREAKING — bash hook scripts replaced by Go CLI binary.
jqno longer required.
- Gate state machine — structural enforcement of quest phase gates via plugin hooks. Teammate tools are blocked after gate submission until the lead approves. Prerequisites (lembas + metadata) are verified before submission. Self-approval is structurally impossible. Observed compliance: ~33% with prompt-only → ~95%+ with hooks. (#5)
- Hook scripts — 4 plugin hooks (
gate-guard,gate-submit,gate-prereq,metadata-track) with test suite jqdependency — required for gate enforcement. Hooks fail-closed ifjqis missing.- BREAKING — plugin now ships executable bash scripts (
hooks/scripts/). Previously pure markdown only.
- gather-lore rewrite — simplified to study-only (pattern extraction). Code generation and diff checking removed as redundant with quest Implement + warden Review phases.
/red-bookskill — new skill for capturing conventions from PR reviewer feedback into CLAUDE.md. Closes the convention learning loop.- Quest recovery — Phase 3 now has explicit recovery procedure: when implementation hits a wall, stop, commit partial work, document the blocker, return to Plan phase.
- Quest resume — failed/dead quests can be respawned into their existing worktree. Council finds the lembas checkpoint and offers to resume.
- Palantir fix — spawned as
fellowship:palantir(custom agent with restricted tools) instead ofgeneral-purpose. - Palantir cadence — event-driven monitoring triggered by Gandalf after gate transitions and quest spawns, instead of unbounded.
- Worktree ownership — quest Phase 0 owns worktree creation. Fellowship no longer passes
isolation: "worktree", eliminating double-worktree conflicts and unused branch naming logic. - Config schema dedup — canonical schema lives in
/settings. Fellowship references it instead of duplicating. branchPrefixremoved — deprecated key fully removed from all skills and config.- Escape hatch criteria — concrete heuristics (single file, < 50 lines, no new patterns, familiar area) replace "use judgment".
- Monorepo conditional — council package scope step now skips for single-package repos.
- Nested subagent worktrees removed — if plan subtasks have file conflicts, fix the plan.
- Branch name patterns —
branch.patternconfig with a flexible template system. Supports{slug},{ticket}, and{author}placeholders for team-specific branch naming conventions (e.g.,"{author}.{ticket}.{slug}"producesjustin.JIRA-123.fix-auth-bug). Missing placeholders are prompted interactively. Breaking: removedbranchPrefix(deprecated in v1.3.0). Usebranch.patterninstead — e.g.,"myprefix/{slug}"replaces"branchPrefix": "myprefix/".
/configcommand — interactive skill to view, edit, and reset fellowship settings- Config moved to personal directory —
~/.claude/fellowship.jsonis now loaded from the user's personal Claude directory instead of the project root, making settings cross-project - Custom worktree directory —
worktree.directoryconfig option for organizations that don't use Claude Code's default worktree location - Removed superpowers:using-git-worktrees dependency — quest now uses
EnterWorktreedirectly for worktree isolation
- Config file support —
~/.claude/fellowship.jsonfor customizing branch prefixes, gate auto-approval, PR defaults, worktree strategy, and palantir settings (#3) - Palantir rewrite — rewrote from dead code into a functional monitoring agent that watches quest progress, detects stuck quests and scope drift, and alerts Gandalf via SendMessage (#2)
- Progress tracking — teammates report current phase via task metadata; say "status" during a fellowship for a structured progress table (#1)
- Gate blocking fix — replaced ineffective "WAIT" instruction with explicit turn-ending so agents actually stop at gates (#1)
- Lembas compaction at all transitions — added missing
/lembasinvocations at Implement→Review and Review→Complete (#1) - Steward removed — deleted dead agent; decomposition logic was already inlined in quest Phase 3 (#1)
- Gate discipline — Gandalf must never combine or skip gate approvals
- Conventional commits — spawn prompt and quest guidelines now enforce conventional commit format
- Initial release: quest lifecycle, fellowship orchestration, council, gather-lore, lembas, warden, chronicle
MIT