Interactive agent fleet designer - configure your multi-agent workspace. Triggers: "configure fleet", "setup agents", "multi-agent workspace", "fleet layout".
Interactive agent fleet designer - configure your multi-agent workspace.
Interactive agent fleet designer. Helps users configure their multi-agent workspace based on their workflow, not generic categories.
High-level themes that organize your work. Not everyone has all of these:
| Workgroup | Description | Examples |
|---|---|---|
| project | Active codebase work | Viewer, Layout, API, Extraction |
| company | Company-specific agents | MCP tools, internal systems |
| domain | Domain research & expertise | Insurance, Financials, Legal |
| meta | Engine & session work | Sessions analysis, reports, engine |
| personal | Personal productivity | Notes, learning, experiments |
Actual features/areas you work on β discovered through interview, not picked from a menu.
Slots for areas you don't know yet. Create "Future" agents to reserve space.
| Command | Action |
|---|---|
/fleet |
Full interview (new or update) |
/fleet update |
Quick changes |
/fleet rearrange |
Reorder agents/tabs |
/fleet launch |
Start the fleet |
/fleet launch {workgroup} |
Start specific workgroup |
/fleet status |
Show current state |
/fleet add {workgroup} |
Add agents to workgroup |
/fleet placeholder {workgroup} |
Add future slot |
Auto-detect identity (per ΒΆINV_INFER_USER_FROM_GDRIVE):
USERNAME=$(engine user-info username)
EMAIL=$(engine user-info email)
Announce: "Detected identity: {USERNAME} ({EMAIL})"
Check for existing config: Use engine fleet to detect existing configs:
engine fleet status
This outputs the fleet directory path and any running sessions.
Then check for yml files:
engine fleet list
Detect pane context (if running inside a fleet pane):
# Check if we're in a fleet tmux session
TMUX_SOCKET=$(echo "$TMUX" | cut -d, -f1 | xargs basename 2>/dev/null || echo "")
if [ "$TMUX_SOCKET" = "fleet" ]; then
CURRENT_PANE_ID="${TMUX_PANE_TITLE:-}"
CURRENT_LABEL=$(tmux -L fleet display-message -p '#{@pane_label}' 2>/dev/null || echo "")
CURRENT_WINDOW=$(tmux -L fleet display-message -p '#W' 2>/dev/null || echo "")
fi
If running in a fleet pane, offer: "You're in pane {CURRENT_LABEL} ({CURRENT_PANE_ID}). Update this pane, or configure the whole fleet?"
Phase 0 always proceeds to Phase 1 β no transition question needed.
The goal is to discover what the user actually works on, not force them into categories.
Execute AskUserQuestion (multiSelect: true):
"What levels of work do you do?"
- "Project work" β Building features in your codebase
- "Company work" β Company-specific tools, MCPs, internal systems
- "Domain research" β Industry expertise (insurance, finance, legal, etc.)
- "Meta work" β Sessions, reports, engine improvements, documentation
(Personal/experiments/learning β user types in "Other")
For each selected workgroup, execute an AskUserQuestion to discover subprojects. Use hardcoded examples as options β the user names their actual subprojects via "Other".
If Project selected:
Execute AskUserQuestion (multiSelect: true):
"What features or areas of your app do you actively work on?"
- "Viewer" β Frontend viewing/display components
- "Layout" β Page layout and structure analysis
- "API" β Backend API and services
- "Extraction" β Data extraction and parsing
Then execute AskUserQuestion (multiSelect: false):
"Any areas you might work on soon but haven't started?"
- "Yes, I'll list them" β Creates placeholder agents (type in "Other")
- "No placeholders needed" β Skip placeholder creation
If Company selected:
Execute AskUserQuestion (multiSelect: true):
"What company-specific tools or systems do you work with?"
- "MCP tools" β Model Context Protocol integrations
- "Internal dashboards" β Company-internal admin tools
- "Company docs" β Internal documentation and knowledge bases
If Domain selected:
Execute AskUserQuestion (multiSelect: true):
"What domains do you research or need expertise in?"
- "Insurance claims" β Claims processing, Xactimate, adjusting
- "Financials" β Financial analysis and reporting
- "Legal compliance" β Regulatory and legal requirements
If Meta selected:
Execute AskUserQuestion (multiSelect: true):
"What meta-level work do you do?"
- "Sessions analysis" β Reviewing and analyzing agent sessions
- "Reports" β Generating progress and status reports
- "Engine work" β Workflow engine improvements and maintenance
- "Documentation" β Docs, standards, and knowledge management
Key principle: Let the user name their subprojects via "Other". The hardcoded options are starting points, not an exhaustive list.
Execute AskUserQuestion (multiSelect: false):
"How many monitors?"
- "1" β Single monitor setup
- "2" β Dual monitor setup
- "3+" β Three or more monitors
Execute AskUserQuestion (multiSelect: false):
"Agents visible per screen?"
- "4 (2x2)" β Compact grid, 4 agents per monitor
- "6 (2x3)" β Medium grid, 6 agents per monitor
- "9 (3x3)" β Large grid, 9 agents per monitor
- "12 (3x4)" β Maximum density, 12 agents per monitor
Execute AskUserQuestion (multiSelect: false):
"How should workgroups be organized?"
- "Separate tabs per workgroup" β One tab per workgroup (Project tab, Domain tab, Meta tab)
- "Combined" β All in fewer tabs, grouped by relatedness
- "Separate tmux sessions" β Independent tmux sessions per workgroup (launch separately)
Execute AskUserQuestion (multiSelect: false):
"Add an Intakes tab for per-project inbox grooming (
/intake)?"
- "Yes β one pane per project" β An Intakes tab with one agent pane per Linear project (you name them); invoke
/intakein a pane to groom that project's feedback inbox- "Yes β projects + a spare" β Same, plus one
Futureplaceholder pane to activate for a new project later- "No" β No Intakes tab
Based on organization preference:
[!!!] QUOTE ALL STRING VALUES IN YML. YAML silently converts unquoted values into non-string types. This causes runtime bugs that are invisible until the config is parsed.
Dangerous unquoted values (YAML interprets these as non-strings):
| Written | Parsed As | Type | Fix |
|---|---|---|---|
no |
false |
boolean | "no" |
yes |
true |
boolean | "yes" |
on / off |
true / false |
boolean | "on" / "off" |
null |
null |
null | "null" |
1.0 |
1 (integer) |
number | "1.0" |
3:00 |
180 (seconds) |
sexagesimal | "3:00" |
value: with colon |
nested object | mapping | "value: with colon" |
- starts with dash |
array item | sequence | "- starts with dash" |
{curly} |
flow mapping | object | "{curly}" |
[bracket] |
flow sequence | array | "[bracket]" |
Rule: Always double-quote ALL string values in generated yml β descriptions, labels, env var values, command arguments. The only safe unquoted values are simple single-word identifiers with no special characters.
Examples:
# BAD β "Deep research: web and docs" is parsed as nested mapping
- export AGENT_DESCRIPTION=Deep research: web and docs
# BAD β "no" becomes boolean false
- export AGENT_FOCUS=no specific focus
# GOOD β always quote
- export AGENT_DESCRIPTION="Deep research: web and docs"
- export AGENT_FOCUS="no specific focus"
- tmux set-option -p -t $TMUX_PANE @pane_label "Research"
For each subproject discovered, gather three things during the interview:
~/.claude/agents/#needs-* tags this agent handlesGenerate a yml pane block with all three:
- {workgroup}-{subproject}:
- export TMUX_PANE_TITLE="{workgroup}-{subproject}"
- export AGENT_DESCRIPTION="{topic description}"
- tmux set-option -p -t $TMUX_PANE @pane_label "{Subproject}"
- clear && engine run --agent {agent_type} --description "$AGENT_DESCRIPTION"
Agent type is chosen based on the subproject's primary function:
Description is a concise topic summary that gets injected into Claude's system prompt via --description. It tells the agent what area of the codebase/domain it specializes in. Write it as if briefing a new team member.
Delegation tags map subprojects to #needs-* tags for dispatch routing. Each active agent should have 1-2 tags:
#needs-viewer, #needs-frontend#needs-layout, #needs-frontend#needs-parsing, #needs-extraction#needs-insurance, #needs-domain#needs-sessions, #needs-metaDelegation tags are used by the dispatch daemon to route work to the right agent. They are NOT passed to run.sh β they are stored in the worker registration files created at startup by persistent agents (future feature) or in pool worker --accepts flags.
For areas mentioned as "might work on soon" β no agent, no description, just engine fleet wait:
- {workgroup}-future-1:
- export TMUX_PANE_TITLE="{workgroup}-future-1"
- tmux set-option -p -t $TMUX_PANE @pane_label "Future"
- engine fleet wait
Intake panes are ordinary interactive agent panes β one per Linear project β where the user invokes /intake to run an inbox-grooming wave for that project. They use run.sh --agent operator (the operator runs the /intake protocol); no daemon, no --monitor-tags.
- intakes-{project-slug}:
- export TMUX_PANE_TITLE="intakes-{project-slug}"
- export AGENT_DESCRIPTION="Intake grooming for the '{Project}' Linear project. Drain the inbox, organize + consolidate feedback, triage each signal toward an outcome, graduate ripe items to tickets. Run /intake to start a wave."
- tmux set-option -p -t $TMUX_PANE @pane_label "{Short Label}"
- clear && ~/.claude/scripts/run.sh --agent operator --description "$AGENT_DESCRIPTION"
Generate one such pane per project the user names, and (if they chose "projects + a spare") a trailing intakes-future-1 placeholder that runs ~/.claude/scripts/fleet.sh wait. See /intake for what a grooming wave does.
Legacy β Delegation Pool: earlier fleets had a
pooltab ofworker.sh --acceptsdaemon workers that auto-picked up#delegated-*work. That feature is deprecated; new fleets use the Intakes tab instead. If a user explicitly wants background daemon workers, the oldworker.sh --pane-id β¦ --accepts "#needs-delegation,#needs-implementation" --agent operatorform still works.
This flow handles both:
When /fleet activate is invoked (or user presses 'a' in a placeholder):
CURRENT_PANE_ID="${TMUX_PANE_TITLE:-unknown}"
CURRENT_LABEL=$(tmux -L fleet display-message -p '#{@pane_label}' 2>/dev/null || echo "Future")
CURRENT_WINDOW=$(tmux -L fleet display-message -p '#W' 2>/dev/null || echo "unknown")
Use AskUserQuestion to gather:
Name/Label: "What should this agent be called?"
Agent Type: "What type of agent?"
researcher, builder, operator, analyzer, reviewer, writer, tester, prompterDescription: "Describe what this agent does (1-2 sentences)"
Focus Areas: "What topics does this agent specialize in? (comma-separated)"
# Update pane label (visible immediately)
tmux -L fleet set-option -p @pane_label "{NEW_LABEL}"
ALWAYS ask after setting the label:
Execute AskUserQuestion (multiSelect: false):
"Make this permanent in fleet.yml?"
- "Yes β persist across fleet restarts" β Update yml config so this survives
engine fleet start- "No β temporary until restart" β Keep as runtime-only change (reverts on next fleet launch)
Get yml path (use engine fleet config-path for dynamic resolution):
# Default fleet config:
YML_PATH=$(engine fleet config-path)
# Workgroup-specific config:
YML_PATH=$(engine fleet config-path project)
Read the yml and find the pane entry by TMUX_PANE_TITLE:
export TMUX_PANE_TITLE="{CURRENT_PANE_ID}"Update the pane block:
domain-future-2 β domain-research)@pane_label valueengine fleet wait with engine run --agent {TYPE} --description "{DESC}" --focus "{FOCUS}"Before (placeholder):
- domain-future-2:
- export TMUX_PANE_TITLE="domain-future-2"
- tmux set-option -p -t $TMUX_PANE @pane_label "Future"
- engine fleet wait
After (activated):
- domain-research:
- export TMUX_PANE_TITLE="domain-research"
- export AGENT_DESCRIPTION="Deep research agent for web, docs, and codebase exploration"
- export AGENT_FOCUS="Insurance claims, Xactimate codes, PDF extraction"
- tmux set-option -p -t $TMUX_PANE @pane_label "Research"
- clear && engine run --agent researcher --description "$AGENT_DESCRIPTION" --focus "$AGENT_FOCUS"
Write the updated yml using the Edit tool.
Confirm: "Updated {YML_PATH}. Changes will persist on fleet restart."
Show the proposed layout with workgroup organization:
## Your Fleet Layout
**Person**: yarik (yarik@finchclaims.com)
**Setup**: 2 monitors, 6 agents per view
### Workgroup: Project
**Tab: Project** (2x3 grid)
βββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ
β Viewer β Layout β Extraction β
βββββββββββββββΌββββββββββββββΌββββββββββββββ€
β API β Schema β Future β
βββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ
### Workgroup: Domain
**Tab: Domain** (2x2 grid)
βββββββββββββββ¬ββββββββββββββ
β Insurance β Financials β
βββββββββββββββΌββββββββββββββ€
β Future β Future β
βββββββββββββββ΄ββββββββββββββ
### Workgroup: Meta
**Tab: Meta** (2x2 grid)
βββββββββββββββ¬ββββββββββββββ
β Sessions β Reports β
βββββββββββββββΌββββββββββββββ€
β Engine β Future β
βββββββββββββββ΄ββββββββββββββ
### Intakes
**Tab: Intakes** (2x3 grid) β one pane per Linear project, invoke `/intake` per pane
βββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ
β Intake Sys β Differ β Email Class β
βββββββββββββββΌββββββββββββββΌββββββββββββββ€
β Doc Extract β Claims & Polβ Future β
βββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ
Adjust anything? (Add/remove/rename/reorder)
Create directories:
mkdir -p ~/.claude/fleet/workers
Generate tmuxinator config:
engine fleet config-path [workgroup]tmux_command: tmux -L fleet -f ~/.claude/engine/skills/fleet/assets/tmux.conftmux_command: tmux -L fleet-{workgroup} -f ~/.claude/engine/skills/fleet/assets/tmux.confAGENT_DESCRIPTION and calls run.sh --agent {type} --description "$AGENT_DESCRIPTION"engine fleet wait (no agent, no description)run.sh --agent operator β one per Linear project, invoke /intake to groom that project's inboxReport:
Fleet configured!
To start default: engine fleet start
To start workgroup: engine fleet start {workgroup}
To update: /fleet update
To rearrange: /fleet rearrange
Quick operations without full interview.
Execute AskUserQuestion (multiSelect: false):
"What do you want to change?"
- "Add agents to a workgroup" β Create new agent panes in an existing workgroup
- "Remove agents" β Delete agent panes from the fleet config
- "Rename agents/tabs" β Change labels or tab names
- "Rearrange layout" β Reorder tabs, move agents between tabs
(Add/remove workgroups, convert placeholder β type in "Other")
For easy reordering:
Show current layout as numbered list:
1. [Project] Viewer
2. [Project] Layout
3. [Project] Extraction
4. [Domain] Insurance
5. [Meta] Sessions
Ask: "Enter new order (e.g., '3,1,2,5,4') or move commands ('move 5 to Project')"
Apply changes, regenerate config
The Intakes tab holds one interactive agent pane per Linear project. Each pane runs an operator agent; the user invokes /intake in it to run an inbox-grooming wave for that project (drain new feedback β organize + consolidate β triage each signal β graduate ripe items to tickets β debrief). Panes are ordinary run.sh --agent operator panes β no daemon, no tag monitoring. Add a trailing intakes-future-1 placeholder (fleet.sh wait) as a cheap slot for a new project.
Legacy β Daemon Mode: earlier fleets ran a
pooltab of daemon workers (worker.sh --accepts/run.sh --monitor-tags) that scannedsessions/for#delegated-*tags and auto-spawned the resolving skill perΒ§TAG_DISPATCH. Deprecated in favor of the Intakes tab. Still available on request for background delegation workloads.
/intake pane per Linear project (plus an optional spare) β not daemon workers.