Skip to content

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/
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 log

fleetd uninstall keeps all of it. See Updating & uninstall.

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

~/.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.

Sessions run claude with your own setup on that machine, ~/.claude. These all work as they do in your shell:

  • your login;
  • the env in ~/.claude/settings.json, such as a proxy’s ANTHROPIC_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.json

fleetd 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.

To give a worker’s sessions their own claude profile:

  1. Set "claudeConfigDir": "<dir>" in ~/.fleetd/node/node.json on the worker, or join with fleetd node join --claude-config-dir <dir>.
  2. Restart the node.

A session resumes only under the config dir it started in.

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>
# or
ANTHROPIC_BASE_URL=https://gateway.example.com
ANTHROPIC_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.

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.

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

--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.

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.

  1. Set up the test hub’s files. Run export FLEETD_HOME=$HOME/fleetd-test in each terminal you use for it.

    export FLEETD_HOME=$HOME/fleetd-test
    fleetd 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/null

    With no terminal (</dev/null), init only writes the hub’s setup and the CLI’s key, and starts nothing.

  2. Start the hub. Keep the terminal open; it logs there.

    fleetd hub start --listen 127.0.0.1:4797
  3. 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 --code
    fleetd node join --hub http://127.0.0.1:4797 --token <code> --machine test-1
  4. Use the test fleet as you would your own:

    fleetd doctor
    fleetd project add ~/src/sandbox --machine test-1 --yes
    fleetd 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.

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.

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>.

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.

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.