Writing a Fleet Adapter
An adapter is a thin wrapper that translates between Fleet’s mission brief format and a specific coding agent’s CLI or API. Writing one takes about 30 lines of TypeScript.
The adapter interface
Section titled “The adapter interface”export interface FleetAdapter { name: string;
// Start the agent with a mission brief start(mission: MissionBrief, context: FleetContext): Promise<AgentSession>;
// Check if the agent is still running isAlive(session: AgentSession): Promise<boolean>;
// Send a message to a running agent (for unblocking) send(session: AgentSession, message: string): Promise<void>;
// Stop the agent gracefully stop(session: AgentSession): Promise<void>;}
export interface MissionBrief { mission_id: string; branch: string; description: string; context_file?: string; // path to FLEET_CONTEXT.md if generated depends_on: string[];}
export interface AgentSession { pid?: number; started_at: string; worktree_path: string;}Example: minimal Claude Code adapter
Section titled “Example: minimal Claude Code adapter”import { spawn } from 'child_process';import { FleetAdapter, MissionBrief, AgentSession } from '@fleet/core';
export const claudeAdapter: FleetAdapter = { name: 'claude-code',
async start(mission: MissionBrief, context): Promise<AgentSession> { const worktreePath = context.worktreePath;
// Build the initial prompt from the mission brief const prompt = buildPrompt(mission, context.fleetContextPath);
// Launch Claude Code in the worktree directory const proc = spawn('claude', ['--dangerously-skip-permissions'], { cwd: worktreePath, stdio: ['pipe', 'pipe', 'pipe'], });
// Send the mission brief as the opening message proc.stdin.write(prompt + '\n');
return { pid: proc.pid, started_at: new Date().toISOString(), worktree_path: worktreePath, }; },
async isAlive(session): Promise<boolean> { if (!session.pid) return false; try { process.kill(session.pid, 0); return true; } catch { return false; } },
async send(session, message): Promise<void> { // Implementation: write to the agent's stdin },
async stop(session): Promise<void> { if (session.pid) process.kill(session.pid, 'SIGTERM'); },};
function buildPrompt(mission: MissionBrief, contextPath?: string): string { let prompt = `# Fleet Mission ${mission.mission_id}\n\n${mission.description}\n\n`;
if (contextPath) { prompt += `Read ${contextPath} first for codebase context.\n\n`; }
prompt += `When complete, update MISSION.md with status: completed.\n`; prompt += `Push MISSION.md every 60 seconds as a heartbeat even if no progress.\n`;
return prompt;}Submitting an adapter
Section titled “Submitting an adapter”- Fork
github.com/fleetspark/fleet - Create
packages/adapters/<your-agent>/ - Implement the
FleetAdapterinterface - Add a test: does
fleet ship --joinwork with your adapter on a real repo? - Open a PR — include the agent name, install instructions, and a short demo
Adapters for Gemini CLI, OpenCode, Cursor CLI, and Amp are all wanted.