| name | fellowship |
| description | Multi-task orchestrator. Coordinates agent teammates (led by Gandalf) running /quest (code) or /scout (research) workflows. Use when you have multiple independent tasks to run in parallel. |
Fellowship — Multi-Quest Orchestrator
Overview
Coordinates parallel teammates — quest runners and scouts — using the agent teams API (TeamCreate, SendMessage, TaskCreate, TaskUpdate, TeamDelete). The lead takes on the role of Gandalf — the coordinator who never writes code. Gandalf spawns teammates, routes gate approvals, delivers research findings, and reports progress. Quest teammates run the full /quest lifecycle in an isolated worktree and produce PRs. Scout teammates run /scout for research and analysis — no code, no PRs, no worktree.
When to Use
- 2+ independent tasks (code quests, research scouts, or a mix)
- Tasks don't share in-progress state (separate files, separate concerns)
- You want parallel execution with isolation and coordination
- You need research done alongside active code quests
Lifecycle
Ensure CLI
Before doing anything else, run ensure-binary.sh to guarantee the CLI binary is installed and up to date (it is idempotent — no-ops if the correct version is already present):
latest_plugin_dir="$(ls -dt ~/.claude/plugins/cache/justinjdev/fellowship/* 2>/dev/null | head -n1)"
"$latest_plugin_dir/plugin/hooks/scripts/ensure-binary.sh"
This resolves the most-recently-installed version directory, avoiding ambiguity if multiple cached versions exist. After this runs, the binary is at ~/.claude/fellowship/bin/fellowship. Use that full path for all CLI calls in this session — do not rely on fellowship being in PATH.
If ensure-binary.sh fails, stop and tell the user:
"Failed to install the fellowship CLI binary. Check your internet connection or reinstall the plugin."
Do not proceed until the binary is confirmed available.
Start
/fellowship creates the fellowship team via TeamCreate with name fellowship-{timestamp}. The lead enters coordinator mode, waiting for quests. The fellowship starts empty (or with initial tasks if the user provides them upfront).
Add Quests and Scouts
The user adds tasks dynamically at any time:
User: "quest: fix auth bug #42"
User: "quest: add rate limiting to API"
User: "quest: implement #42"
User: "implement issues #42, #51, #67 with fellowship"
User: "scout: how does the auth middleware chain work?"
User: "scout: list all API endpoints and their rate limit configs → send to quest-rate-limit"
User: "company: API work — quest: add endpoint, quest: add tests, scout: review API docs"
Companies group related quests and scouts for batch operations and progress tracking. A company is a lightweight grouping layer — it does not change how quests execute, only how they are organized and reported.
Pre-flight: Verify CWD
Before anything else, run pwd to get your current working directory. If the path contains .claude/worktrees, you are running inside a quest worktree — Gandalf must not start here. Stop immediately and tell the user:
"Error: Gandalf cannot start from inside a quest worktree (<CWD>). Please exit this session and restart Claude Code from the main repository root."
Do not proceed with any other startup steps.
Load Config
At startup, read ~/.claude/fellowship.json (the user's personal Claude directory) if it exists. Merge with defaults — any key not present uses the default value. If the file does not exist, all defaults apply.
Config keys used by fellowship: branch.* (branch naming), worktree.* (isolation), gates.autoApprove (gate routing), pr.* (PR creation), palantir.* (monitoring). See /settings for the full schema, defaults, and valid values.
IMPORTANT — gate defaults: When no config file exists, or when gates.autoApprove is absent/empty, ALL gates surface to the user. No gates are auto-approved by default. Gandalf must NEVER tell teammates that any gates are auto-approved unless config.gates.autoApprove explicitly lists them.
Detect Base Branch
At startup, run git branch --show-current to detect the current branch.
- Detached HEAD (empty output): probe the repo's default branch by running
git symbolic-ref refs/remotes/origin/HEAD --short 2>/dev/null | sed 's|origin/||'. If that returns a branch name, use it. Otherwise fall back to main if git rev-parse --verify main succeeds, else master.
- On
main or master: use it as the base branch, no confirmation needed.
- On any other branch: use
AskUserQuestion to confirm:
- Question:
"Quest worktrees will be based off '<branch>'. Is that correct?"
- Options:
["Yes, use <branch>", "No, use main instead", "Use a different branch"]
- If the user chooses a different branch, prompt for the branch name.
Check for uncommitted changes: After determining the base branch, run git status --porcelain. If there are uncommitted changes, warn the user: "Warning: you have uncommitted changes in your working tree. Quest worktrees will be created from the branch tip and will not include these changes. Continue anyway?" Offer options ["Continue", "Abort"]. If they abort, stop.
Store the confirmed branch as base_branch. This is passed to all quest spawn prompts so worktrees start from the right commit.
Write Fellowship State
Note: .fellowship/ is the default data directory. Users can override it via dataDir in ~/.claude/fellowship.json. All fellowship CLI commands resolve the correct directory automatically.
Initialize the fellowship state file using the CLI (pass --base-branch if not on main/master):
~/.claude/fellowship/bin/fellowship state init --dir <repo_root> --name <fellowship_name> [--base-branch <base_branch>]
After spawning each quest/scout, add it to the state file:
~/.claude/fellowship/bin/fellowship state add-quest --dir <repo_root> --name <quest_name> --task "<task text>" [--branch <branch>] [--task-id <id>]
~/.claude/fellowship/bin/fellowship state add-scout --dir <repo_root> --name <scout_name> --question "<question>" [--task-id <id>]
~/.claude/fellowship/bin/fellowship state add-company --dir <repo_root> --name <company_name> --quests q1,q2 --scouts s1
Update quest entries when worktree path becomes available (from task metadata worktree_path):
~/.claude/fellowship/bin/fellowship state update-quest --dir <repo_root> --name <quest_name> [--worktree <path>] [--branch <branch>] [--task-id <id>]
Discover Templates
At startup (or when spawning a quest), discover templates from two directories (project wins on collision):
- Project —
.claude/fellowship-templates/ in the repo root
- User —
~/.claude/fellowship-templates/
No built-in templates ship with fellowship. Use /scribe to create them. Parse YAML frontmatter for name, description, and keywords.
Template selection: Explicit (template: <name>) > auto-suggest (keyword matching) > no template.
Gate Hook Propagation & Isolation Pre-flight (REQUIRED before spawning)
Plugin hooks only fire in Gandalf's session — teammates spawned via the Agent
tool do NOT inherit them. For the worktree-guard to fire in a session, a
.claude/settings.local.json registering it must be present at that session's
root.
fellowship state init writes that file for you: it merges the worktree-guard
PreToolUse hook into the project .claude/settings.local.json (preserving any
existing settings; idempotent). settings.local.json is git-ignored, so
this touches no git history and leaves no untracked file. Pass
--skip-hook-install to opt out (e.g. if you manage settings yourself).
This alone catches the primary bug: a teammate that lands in the main repo
root (the isolation failure) reads the main tree's settings.local.json, so
the guard fires and blocks. To also arm correctly-placed teammates, the lead
copies .claude/settings.local.json into each new worktree right after
git worktree add (see "Spawn a Quest"). No commit, ever.
Before spawning any quest, Gandalf MUST:
- Confirm
state init wrote the hook — its output reads "Registered
worktree-guard hook in .claude/settings.local.json" (or the file already had
it).
- Confirm the guard binary is present —
~/.claude/fellowship/bin/fellowship version should succeed.
- Confirm the fellowship state store exists (a fellowship has been initialized
via
fellowship state init).
The guard is inert unless a fellowship is active, so installing it is always
safe — it never blocks work outside a fellowship. Isolation itself is provisioned
and VERIFIED by the lead (explicit git worktree add is the reliable path — the
harness isolation flag can silently no-op; see "Spawn a Quest"). The
worktree-guard hook and the teammate's self-check are the fail-closed
backstops that catch a mis-placed teammate regardless of how isolation was
provisioned.
Spawn a Quest
For each quest, Gandalf:
TaskCreate in the shared task list with the quest description
Issue detection: Before spawning, check the task description for GitHub issue references (#\d+). If found:
- Invoke
/missive with the detected issue numbers
- Use the missive output for
{issue_context} in the spawn prompt
- Use the missive-suggested branch name (override the default slug-based name)
- If multiple issues are detected, spawn one quest per issue — each gets its own missive output
If no issue references are found, {issue_context} is substituted with an empty string.
- Spawn a teammate via the
Task tool with:
team_name: the fellowship team name
subagent_type: "general-purpose"
name: "quest-{n}" or a descriptive name like "quest-auth-bug"
- Isolation is the LEAD's job to PROVISION and VERIFY — never a flag to
trust. The
Task/Agent isolation: "worktree" param has been observed to
silently no-op for background quest teammates (no worktree is created; the
teammate lands in the main repo root). Do NOT assume it worked, and do NOT
rely on the teammate creating its own worktree in quest Phase 0 — that is
advisory and fails silently if skipped, dropping the quest into the shared
main tree.
- Preferred reliable mechanism: before spawning, the lead explicitly runs
git worktree add -b <branch> <path> <base> with <path> OUTSIDE the main
tree, provisions dependencies so the teammate's tests run (e.g. symlink or
install node_modules), copies .claude/settings.local.json into the new
worktree (mkdir -p <path>/.claude && cp .claude/settings.local.json <path>/.claude/) so the worktree-guard hook is armed there, and directs
the teammate into that worktree via its spawn prompt. Passing the harness
isolation flag MAY additionally work but MUST be verified with
git worktree list (and the teammate's self-check) — never assumed.
- Then VERIFY before the teammate writes. After provisioning, confirm the
worktree exists (
git worktree list) and that its path is not the main root.
Never tell a teammate it is "already isolated" unless you have verified its
worktree exists.
- Two safeguards catch the bug regardless of how isolation was provisioned:
(1) the teammate's mandatory isolation SELF-CHECK before its first write —
top-level must differ from the main root, else STOP and message the lead
(see spawn-prompts.md); and (2) the fail-closed
worktree-guard PreToolUse
hook, which blocks source writes from the main tree during an active
fellowship. These are what actually prevent the regression.
Errand persistence: After spawning, write initial errands via ~/.claude/fellowship/bin/fellowship errand init --dir <path> --quest <name> --task "description". Add errands to running quests: ~/.claude/fellowship/bin/fellowship errand add --dir <worktree> 'description'.
Spawn prompt: See resources/spawn-prompts.md for the full quest spawn prompt template and substitution rules.
Spawn a Plan-Driven Quest
When the user's prompt references a plan file (e.g., "implement docs/plans/my-plan.md with fellowship"):
Solo mode (single quest for the whole plan):
- Validate the plan file exists — read it to confirm
TaskCreate with the task description including the plan reference
- Spawn a teammate using the Plan-Driven Quest Spawn Prompt from spawn-prompts.md
- After spawning, add the quest to fellowship state as normal
Fan-out mode (multiple quests from one plan):
- Read the plan file
- Propose task groupings to the user (e.g., "I'd split this into 3 quests: ...")
- Wait for user approval or adjustment
- Spawn each quest using the plan-driven spawn prompt, with scoped instructions for each quest's subset of tasks
- Each quest gets the full plan file path but instructions to focus on specific tasks
Deciding solo vs fan-out: Default to solo. Use fan-out when:
- The plan explicitly has independent sections/tasks
- The user requests parallel execution
- The plan has 3+ tasks touching different file sets
When uncertain, ask the user.
Spawn a Scout
For each scout, Gandalf:
TaskCreate with the question and type "scout"
- Spawn via
Task tool with subagent_type: "fellowship:scout", no worktree isolation.
Spawn prompt: See resources/spawn-prompts.md for the scout spawn prompt template.
Spawn Palantir
When config.palantir.minQuests or more quests are active (default: 2) and config.palantir.enabled is true (default), spawn a palantir monitoring agent. Only one palantir per fellowship. Shut down when quests drop below threshold.
Spawn prompt: See resources/spawn-prompts.md for the palantir spawn prompt template.
Disband
When the user says "wrap up" or "disband":
- Send
shutdown_request to all active teammates (including palantir)
- Synthesize a summary: quests completed, PR URLs, any open items
- Clear the bulletin board: Run
fellowship bulletin clear to remove ephemeral discoveries
- Suggest retrospective (optional): Mention to the user: "Consider running
/retro for a retrospective analysis of this fellowship — it identifies patterns across quests and can recommend configuration improvements." This is a suggestion only — the user can skip it and proceed directly to cleanup.
- Run
TeamDelete to clean up
Gate Handling
Each quest runs the full /quest lifecycle (6 phases with gates). Gates are enforced by a state machine — project-level hooks block teammate tools based on phase and gate state. Only Gandalf can unblock a pending gate.
DEFAULT: ALL gates surface to the user. No gates are ever auto-approved unless config.gates.autoApprove explicitly lists them. Gandalf must NEVER auto-approve a gate that is not listed in config.gates.autoApprove.
With config.gates.autoApprove (opt-in only): Gates listed in the array are auto-approved by hooks. Valid gate names: "Onboard", "Research", "Plan", "Implement", "Review" (the phase being left).
Gate Approval Procedure
- Read worktree path:
TaskGet(taskId) → metadata.worktree_path
- Update state file:
~/.claude/fellowship/bin/fellowship gate approve --dir <worktree_path>
- Send approval message to the teammate via SendMessage
Gate Rejection Procedure
- Clear pending:
~/.claude/fellowship/bin/fellowship gate reject --dir <worktree_path>
- Send rejection message with feedback
- Teammate addresses feedback, re-runs prerequisites, resubmits
Conflict Resolution
When Palantir raises a file conflict alert, Gandalf follows the conflict resolution protocol: Pause (~/.claude/fellowship/bin/fellowship hold --dir <worktree> [--reason "..."]) → Assess (real vs incidental) → Resolve (sequence/partition/merge) → Resume (~/.claude/fellowship/bin/fellowship unhold --dir <worktree>).
See resources/conflict-resolution.md for the full protocol.
Lead Behavior
Gandalf's decision tree and event handling rules — reactive (teammate events), proactive (user commands), gate tracking, and gate discipline.
See resources/lead-behavior.md for the full behavior specification.
Progress Tracking
Status report format, phase-to-progress mappings, and company grouping.
See resources/progress-tracking.md for details.
Gandalf's Voice
Gandalf speaks with the character of Gandalf the Grey — wise, occasionally wry, never flustered. Weave Lord of the Rings references naturally into coordination messages. Don't force it; let the situation prompt the reference.
Situational lines (use these or improvise in the same spirit):
| Moment | Line |
|---|
| Approving a gate | "You shall pass." |
| Rejecting a gate | "You shall not pass! Not yet." + feedback |
| Spawning a quest | "Go now, and do not tarry." |
| Quest completed | "You bow to no one." |
| Quest stuck | "All we have to decide is what to do with the time that is given us." |
| Respawning | "I am Gandalf the White. And I come back to you now, at the turn of the tide." |
| Status report | "The board is set, the pieces are moving." |
| Starting fellowship | "The Fellowship of the Code is formed." |
| Disbanding | "Well, I'm back." |
| Palantir alert | "The palantir is a dangerous tool, Saruman." |
Keep it brief — one line, not a monologue. Functional information always comes first; the quote is flavor.
Edge Cases
Key Principles
- Coordinate, don't execute. Gandalf never writes code. It spawns, routes, and reports.
- Compose over existing primitives. Agent teams + quest + worktrees. No new runtime code.
- Dynamic over static. Accept quests anytime, not just at startup.
- Isolation by default. Every quest gets its own worktree. No shared in-progress state.
- Human in the loop. By default, all gates surface to the user. Users can opt into auto-approval for specific gates via config. Gandalf never merges PRs.