AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
Type a task on any device. A machine you own runs Claude Code, Codex or opencode in its own worktree and streams every step back live.
Developer toolsRust · SvelteGitHub @foodakaOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Run coding agents on your own machines, from anywhere.
Taken from the repository README
Loading the full README.
Read the full README ↗Run coding agents on your own machines, from anywhere.
Website · Install · Quick start · API
[!NOTE] Sidefleet is under active development: expect rough edges, and things may change between versions.
Type a task on a web page, pick an agent, a model and a repo, and a machine you own picks it up: your desk Mac, a Mac mini, a VPS. It runs Claude Code, Codex or opencode in its own git worktree and streams the agent's narration back live; reply to keep the conversation going. No API keys for Claude or Codex: it uses the login already on that machine. opencode brings any other model (Kimi, GLM, DeepSeek, Qwen through OpenRouter, or local ones). No open ports: machines only make outbound calls to your control plane. One Rust binary, macOS and Linux.
browser ──HTTP/SSE──▶ sidefleet serve (control plane: web page + API + Postgres)
▲
│ outbound HTTP only (register, heartbeat, claim, events)
│
sidefleet run ──spawns──▶ claude -p / codex exec --json / opencode run --format json
(worker on your Mac, VPS, Linux box: cwd = the repo)
sidefleet/<id>), so
several tasks on one repo run side by side without touching your checkout. Choose "In place"
when a task needs installed dependencies or local config.origin at most once a minute while the agent edits.
If the machine stops responding (a laptop going to sleep), the task moves to another machine with
the repo and continues from the last pushed commit, with a digest of the thread so far. Off by
default, because it pushes; only the task's own sidefleet/... branch is ever pushed.localhost (on iPhone, add the page to the Home Screen first). serve creates the VAPID key for
it in ~/.sidefleet/server.env; elsewhere set SIDEFLEET_VAPID_PRIVATE_KEY.connect checks which agents are installed and signed in, finds your
git checkouts (repos match by their git remote, whatever the folder is called), and installs a
launchd or systemd service that survives reboots. Or click "Copy prompt" and let Claude Code or
Codex on the other machine connect itself.
curl -fsSL https://raw.githubusercontent.com/foodaka/side-fleet/main/install.sh | sh
Downloads a prebuilt sidefleet into ~/.local/bin (no sudo), or builds from source when there
is no release for your platform.
While the repository is private, the raw URL returns 404. Use the GitHub CLI (gh auth login),
which the script then uses for the download:
gh api repos/foodaka/side-fleet/contents/install.sh -H "Accept: application/vnd.github.raw" | sh
Or clone over SSH and build from the checkout, never contacting GitHub:
git clone [email protected]:foodaka/side-fleet.git && sh side-fleet/install.sh
1. Start the control plane on the machine that will host the page. It needs Postgres:
docker run -d --name sidefleet-db --restart unless-stopped \
-e POSTGRES_USER=sidefleet -e POSTGRES_PASSWORD=sidefleet -e POSTGRES_DB=sidefleet \
-p 5432:5432 -v sidefleet-pgdata:/var/lib/postgresql/data postgres:16-alpine
sidefleet serve
Sidefleet control plane is running.
Open the page: http://<this-machine>:7373/
Developer key: 3f9c…
Connect a machine: sidefleet connect --control http://<this-machine>:7373 --token 7b2e…
Keys are saved to ~/.sidefleet/server.env. If the machine has a coding agent installed, serve
runs a worker on it too, so a single box is one command.
2. Open the page and paste the developer key.
3. Connect more machines. On any machine with an agent set up (see Agents), run the install line, then the connect line the page shows you. The page switches to the compose box as soon as the first heartbeat lands.
Across networks, put the control plane on Tailscale and use its tailnet IP: no port forwarding, no public exposure. Running it on a VPS or a spare machine is covered in HOSTING.md.
No token at hand? sidefleet connect --control <url> without --token asks the control plane
to let the machine in: it prints a link and a short code, and the machine joins once someone
approves it under Pending machines on the Machines page (the request expires after ten minutes).
Hosted, multi-tenant mode. Setting SIDEFLEET_GITHUB_CLIENT_ID,
SIDEFLEET_GITHUB_CLIENT_SECRET and SIDEFLEET_PUBLIC_URL turns on GitHub sign-in, orgs, per-org
worker tokens and plan limits. What it stores and how to deploy or try it locally:
HOSTED.md.
On a hosted control plane, an org is a team workspace:
sidefleet/room-<id>, never force-pushed), and new tasks then start from it. Every task's agent
gets a brief with the goal, the notes and what the other tasks are doing, so it doesn't redo or
undo a teammate's work. A merge conflict shows its files on the task card, with Ask my agent to
fix. When the work is finished, Compare on GitHub opens the room branch for one PR.
How it's designed, and what comes next, is in docs/multiplayer/.
| Agent | Set it up on the machine | Models |
|---|---|---|
| Claude Code | claude, sign in once | Opus, Sonnet, Haiku |
| Codex | codex login (ChatGPT sign-in or API key) | what codex debug models lists for the account, or its default |
| opencode | opencode auth login, e.g. OpenRouter; or add OPENROUTER_API_KEY=… to ~/.sidefleet/worker.env | any provider/model it lists, e.g. openrouter/moonshotai/kimi-k2 |
sidefleet connect reports which agents it found and whether they are signed in, and the Machines
page shows the same. Local models (Ollama, LM Studio) run through opencode once you add them as an
opencode provider.
The page's permission modes map onto each agent:
| Mode | Claude Code | Codex | opencode |
|---|---|---|---|
| Read & edit files | acceptEdits | sandbox workspace-write (commands run sandboxed, no network) | shell denied |
| Full access | bypassPermissions | no sandbox | all permissions granted |
| Read only | plan | sandbox read-only | plan agent, edits, shell and fetches denied |
| Ask me | acceptEdits, other tools asked on the page | not offered yet | not offered yet |
With "Ask me", a tool call that acceptEdits would refuse shows on the page as a card with
Approve and Deny, and the thread is marked "Waiting on you" in the sidebar. The agent waits until
you decide, or denies the call after 15 minutes (sidefleet run --approval-timeout <secs>). Claude
Code's acceptEdits already lets simple file commands in the workspace (mkdir, rm, ls)
through without asking; everything else, such as running a script, a network call or an MCP tool,
is asked.
Whatever you have already allowed Claude Code on that machine still applies: rules in
~/.claude/settings.json, and the checkout's own .claude/settings.local.json (where "don't ask
again" answers go), which the worker copies into each task's worktree while git ignores it.
sidefleet serve # control plane on :7373, plus a local worker
sidefleet serve --no-worker # control plane only
sidefleet serve --install-service # run serve as a background service
sidefleet connect --control <url> --token <t> # register this machine, install the service
sidefleet connect --control <url> # no token: wait for approval on the Machines page
sidefleet connect … --name "Mac mini" --parallel 3 --permission-mode bypassPermissions
sidefleet status # saved settings, service and process state, log path
sidefleet disconnect # remove the service (settings kept)
sidefleet run # worker in the foreground with the saved settings
sidefleet detect # what this machine can run, as JSON
sidefleet update # pull the latest, reinstall, restart services
Every flag can also come from the environment (SIDEFLEET_BIND, DATABASE_URL,
SIDEFLEET_DEV_KEY, SIDEFLEET_WORKER_TOKENS, …), a .env in the current directory, or
~/.sidefleet/server.env / worker.env. sidefleet <command> --help lists them all. Worker logs
are in ~/.sidefleet/logs/.
The HTTP API and the lifecycle of a run are documented in docs/API.md.
docker compose up -d --wait # Postgres for local runs and tests
cargo test --workspace # integration tests create and drop sidefleet_test_* databases
cargo run -p sidefleet -- serve
The web UI's build output in crates/server/web-dist/ is committed so Rust-only installs keep
working, but only by CI: after a change to web/ lands on main, the web-dist workflow rebuilds
it and commits the result. Pull requests change web/ only and leave web-dist/ alone (CI fails
otherwise); run pnpm build in web/ to try a change locally, then git checkout crates/server/web-dist before committing. Tagging
vX.Y.Z builds release binaries for macOS (arm64, x86_64) and Linux (x86_64, arm64).
crates/core: shared models, the agents and the mapping of each one's output to events, redaction.crates/server: Axum control plane, Postgres via sqlx migrations; embeds the web app.crates/worker: machine detection, control-plane client, process-group executor, worker loop.crates/cli: the sidefleet binary.web/: the web UI, SvelteKit + shadcn-svelte. See web/README.md.site/: the website at www.sidefleet.xyz, one static page. See
site/README.md.refs/sidefleet/snapshots/ (remove with
git for-each-ref --format='delete %(refname)' refs/sidefleet/ | git update-ref --stdin).git commit by Codex can fail under "Read & edit files". Commit from the branch
afterwards, or use Full access.HEAD without untracked or ignored files (node_modules,
.env), and are kept until you remove them (git worktree remove, or delete the folder under
~/.sidefleet/worktrees and run git worktree prune).License: MIT.