Config & files
Where fleetd keeps everything, and the settings you can change. The hub keeps its state under
~/.fleetd/hub; each worker’s node under ~/.fleetd/node.
~/.fleetd
Section titled “~/.fleetd”~/.fleetd/ bin/fleetd the CLI (linked from ~/.local/bin/fleetd) hub/ the hub's home (hub machine only) hub.sqlite everything the hub knows, timelines included browser/<session>/ browser screen recordings (see Screens) setup.json what fleetd init and machine add set up: address, commit identity, machines hub.log the hub service's log cli.key the admin key the CLI on this machine uses (an agent key) keys/<name>.key agent keys made with fleetd hub key create --agent prompts/<id>.md your version of a prompt, hub-wide prompts/projects/<key>/<id>.md the same for one project memory/people/<id>.md what the agents remember about how one person works, theirs alone memory/user.md the shared memory of a hub from before people; its owner got a copy memory/<machine>/<project>/MEMORY.md one project's memory, with its topic files beside it node/ the node's home (every worker) node.json the node's settings (below) node-key.pem proves the node to the hub node-box-key.pem opens secrets sealed to this machine node.sock the socket agents' fleetd tools use to reach the hub bin/ the running node's own binary, linked here so its agents' fleetd tools survive an update sessions.sqlite the node's sessions, and timings not yet sent to the hub worktrees/ one git worktree per task session, readers' and reviewers' too project-env/<project>.json a project's environment variables, secrets included (mode 0600; Settings → Projects) mcp-secrets/ the secrets of the MCP servers agents get, global and per project (mode 0600; Settings › Hub › Every project › Tools & skills, and a project's Agents) browser/ browser screens: the pinned Chrome, ffmpeg and agent-browser, and recordings not yet on the hub previews/<project>/ up to 3 worktrees for previews of the project's PRs, each kept as the next preview's build cache device/ Android screens: the pinned SDK, emulator, snapshot and agent-device, and recordings not yet on the hub ios/ iOS screens: the node's simulator set, its golden, agent-device's runner, and recordings not yet on the hub desktop/ Linux desktop screens: each display's folder, and recordings not yet on the hub claude.env optional extra environment for every claude fleetd starts logs/node.log the node service's logfleetd uninstall keeps all of it. See Updating & uninstall.
Memory files
Section titled “Memory files”What the leads remember is plain markdown under ~/.fleetd/hub/memory: each
person’s own in people/<person id>.md (one shared user.md on a hub from before people), and per project a
MEMORY.md (its always-on entries, then one - [topic](topic.md) line per topic) with its topic files beside it. Each remembered line is one - entry.
Settings › a project › Instructions & memory (and Settings › Your memory for yours) lists each file as cards, one per entry, with a search across them and the file’s length against its cap. An entry the lead wrote says when, and links to the “Remembered: …” line in that project’s chat (or the nightly refresh’s line); an entry you wrote or changed since shows no source. Edit an entry in its card, or delete it and use Undo in the toast to put it back. Edit as text opens the whole file; a save past a cap is refused there, as it is for the lead. The files stay the truth: every change in the app rewrites the file, and you can edit them by hand on the hub too.
| Run as | Hub log | Node log |
|---|---|---|
A service (fleetd init, fleetd machine add) |
~/.fleetd/hub/hub.log |
~/.fleetd/logs/node.log |
By hand (fleetd hub start, fleetd node join or node run) |
The terminal | The terminal |
node.json
Section titled “node.json”~/.fleetd/node/node.json on each worker. fleetd node join and fleetd machine add write it. Restart the node
after you change it.
| Key | Means |
|---|---|
hub |
The hub’s address. |
machineId, name, tags |
How the hub knows this machine. |
enrolled |
true once the hub accepted the node’s key. |
cmdRoots |
Folders the node may run commands in, and below. Absent: your home directory. |
claudeConfigDir |
A dedicated claude profile for this machine’s sessions. See below. |
minFreeGb |
New agents wait while the disk holding the worktrees has less than this many GB free. Absent: 10% of the disk or 20 GB, whichever is larger. 0 turns it off. Read with every heartbeat, no restart needed. See Disk and load. |
memPerAgentGb |
GB of memory to allow per agent when the hub works out how many agents this machine runs at once by default. It sizes the default only: no agent waits for the memory it might take. Absent or 0: 2 GB. Read with every heartbeat. |
diskPerAgentGb |
GB of disk to allow per new agent’s worktree when the hub works out how many more fit above minFreeGb. Absent or 0: 5 GB, about a Rust worktree with a build cache; a JS project needs 1 to 2. Read with every heartbeat. |
browser |
How this machine runs browser screens: enabled, chrome, ffmpeg, pool, sandbox, idleMinutes. |
preview |
Previews of PRs someone asked to try: enabled (false: this machine runs none) and slots, the previews of one project at once, each in a worktree of its own (default 3). |
device |
How this machine runs Android screens: enabled, pool, idleMinutes. |
ios |
How this Mac runs iOS screens: enabled, pool, idleMinutes, deviceType, remoteInstall. |
desktop |
How this machine runs Linux desktop screens: enabled, backend, runtime, image, xvfb, ffmpeg, pool, idleMinutes. |
The Claude login
Section titled “The Claude login”Sessions run claude with your own setup on that machine, ~/.claude. These all work as they do in your shell:
- your login;
- the
envin~/.claude/settings.json, such as a proxy’sANTHROPIC_BASE_URL; - an
apiKeyHelper; - your MCP servers.
fleetd doctor shows what each worker uses:
claude 2.1.302, logged in (Max), via proxy http://127.0.0.1:8317 from ~/.claude/settings.jsonfleetd adds its own settings on top of yours, per session:
| fleetd adds | Why |
|---|---|
--mcp-config |
fleetd’s agent tools. |
A --settings overlay |
Pins claude’s version, turns claude’s auto memory and its own subagents off (why), and denies tools agents never get: plan mode, worktrees, cron. |
agent-browser on PATH, its AGENT_BROWSER_* variables and its skill |
A lead’s and a task’s browser screen. |
agent-device on PATH (it alone: the node’s SDK and adb stay inside it), its AGENT_DEVICE_* variables and its skill, on a machine with Android screens |
A lead’s and a task’s Android screen. |
agent-device on PATH (it alone: the node’s simulator set and runner stay inside it), its AGENT_DEVICE_* variables and its skill, on a Mac with iOS screens |
A lead’s and a task’s iOS screen. |
A folder first on PATH that holds a forwarding agent-device only while the session’s iOS screen runs on another machine |
A lead’s and a task’s iOS screen elsewhere. |
A dedicated claude profile
Section titled “A dedicated claude profile”To give a worker’s sessions their own claude profile:
- Set
"claudeConfigDir": "<dir>"in~/.fleetd/node/node.jsonon the worker, or join withfleetd node join --claude-config-dir <dir>. - Restart the node.
A session resumes only under the config dir it started in.
claude.env
Section titled “claude.env”Optional. KEY=VALUE lines for every claude fleetd runs, for a variable your login needs that the services don’t
see. Blank lines, # comments and export are allowed. Keep it mode 0600.
CLAUDE_CODE_OAUTH_TOKEN=<token from claude setup-token># orANTHROPIC_BASE_URL=https://gateway.example.comANTHROPIC_AUTH_TOKEN=<token>Nodes put every line in each session’s environment, re-read at each session start.
The env in your ~/.claude/settings.json outranks it, as it does for your own claude.
.fleetd/policy.yaml
Section titled “.fleetd/policy.yaml”Optional: a project with no .fleetd/ runs at full speed with the defaults below. fleetd reads the file from the
project’s checkout on its machine (the working tree of the folder you added, committed or not), so an edit there
applies within a minute. Commit it if your other checkouts and machines should get it too.
tools: allow: ["Bash(npm test:*)"] deny: ["Bash(git push:*)"]branchPrefix: team-a/| Key | Default | Does |
|---|---|---|
tools.allow, tools.deny |
none | Claude permission rules for every session. Deny wins. |
branchPrefix |
fleetd/ |
What writer and train branches start with. Must end in /. |
A broken file is refused with the exact problem, never ignored, so a typo can’t drop a deny rule.
Services
Section titled “Services”fleetd init and fleetd machine add run the hub and node as user services:
| launchd file | |
|---|---|
| Hub | ~/Library/LaunchAgents/sh.fleetd.hub.plist |
| Node | ~/Library/LaunchAgents/sh.fleetd.node.plist |
| systemd unit | |
|---|---|
| Hub | ~/.config/systemd/user/fleetd-hub.service |
| Node | ~/.config/systemd/user/fleetd-node.service |
--unit-suffix <s> adds a suffix to these names, to run a second fleet’s services on one machine. A second fleet
never writes, stops or removes the first one’s services.
Run a second fleet on one machine
Section titled “Run a second fleet on one machine”To try fleetd next to a fleet you already run, give the test fleet its own folder with FLEETD_HOME and its own port.
Every command then keeps all its state there and never reads or writes ~/.fleetd.
-
Set up the test hub’s files. Run
export FLEETD_HOME=$HOME/fleetd-testin each terminal you use for it.export FLEETD_HOME=$HOME/fleetd-testfleetd init --no-service --listen 127.0.0.1:4797 --url http://127.0.0.1:4797 \--git-identity "Your Name <id+you@users.noreply.github.com>" </dev/nullWith no terminal (
</dev/null),initonly writes the hub’s setup and the CLI’s key, and starts nothing. -
Start the hub. Keep the terminal open; it logs there.
fleetd hub start --listen 127.0.0.1:4797 -
In another terminal, add this machine as a worker of the test hub:
fleetd pair --worker test-1 # prints a join command; take its one-time --codefleetd node join --hub http://127.0.0.1:4797 --token <code> --machine test-1 -
Use the test fleet as you would your own:
fleetd doctorfleetd project add ~/src/sandbox --machine test-1 --yesfleetd status
Stop the hub and node with Ctrl+C. Delete $FLEETD_HOME to remove the test fleet. To run it as services instead, add
--unit-suffix <s> to fleetd init and fleetd machine add.
What FLEETD_HOME covers
Section titled “What FLEETD_HOME covers”| Where | |
|---|---|
The hub’s home: init, doctor, uninstall, machine, pair, project, hub, prompts, instructions, and status, time, steer, steers without --hub |
$FLEETD_HOME/hub |
The node’s home: node join, node run |
$FLEETD_HOME/node |
The app’s hand-off from init and pair |
$FLEETD_HOME/app-pair.json. Start the desktop app with the same FLEETD_HOME to pair with it. |
Lead-side commands (close, change, …) |
FLEETD_NODE_SOCK, else $FLEETD_HOME/node/node.sock. Sessions get it set. |
--home <dir> names one hub’s or node’s folder. Without FLEETD_HOME, that command keeps everything else in the
folder above it, so --home $T/hub works like FLEETD_HOME=$T. FLEETD_HOME wins when both are given.
Ports and addresses
Section titled “Ports and addresses”| Port | 4790 by default. One port for the app, nodes and MCP clients. |
| Address | Your tailnet address when fleetd init finds Tailscale, otherwise 127.0.0.1 only. |
| MCP endpoint | <hub url>/mcp |
| Workers | Open no port: their nodes connect out. |
| Previews | A machine running a preview opens one port for it from 8400–8499, on its tailnet address only, and only for devices of the tailnet user who owns the hub. It closes when the preview ends. |
Change it with fleetd init --listen <host:port> --url <url>.
Timelines
Section titled “Timelines”The hub keeps the spans behind Where time went in hub.sqlite. A span is one stretch of
one agent’s work or wait, such as a tool call or a CI check.
| Data | Kept |
|---|---|
| Spans | 30 days (1 to 365 with fleetd time --retention <days>) |
| Daily totals and each piece of work’s critical path | 400 days |
Each node holds timings it hasn’t sent yet in sessions.sqlite. While the hub is away, it keeps up to 7 days or
500,000 of them, then drops the oldest; the timeline shows the gap.
The desktop app
Section titled “The desktop app”| Where | |
|---|---|
Pairing hand-off from fleetd init or fleetd pair |
~/.config/fleetd/app-pair.json (macOS: ~/Library/Application Support/fleetd/app-pair.json), or $FLEETD_HOME/app-pair.json for a second fleet |
| Its hub address and key | desktop-hub.bin in the same folder, encrypted with the OS keychain or keyring. Without one (no keyring on Linux, or an unsigned or ad-hoc signed Mac build): desktop-hub.json, mode 0600. |
| Its own browser state | desktop/ in the same folder. |
| Its log | ~/Library/Logs/fleetd/app.log on macOS, ~/.local/state/fleetd/app.log on Linux ($XDG_STATE_HOME/fleetd), or $FLEETD_HOME/logs. Errors only, without keys or message text; crash dumps go in crashes/ beside it. Help → Reveal Logs opens it. |