NookOS fleet control plane
Apache-2.0 Self-hosted No telemetry Rust + React

nook start <repo> --node azul --runtime claude

That starts Claude Code on a different computer. nook exec types at it and waits for the answer. No ssh, no tmux, no hostname, no port to forward. Close your laptop and it keeps working.

you@laptop — demo shell simulated · nothing leaves your browser
# azul is a box across the room. or across the world. same command.
$ nook start acme/checkout-api --node azul --runtime claude --name api
 api — claude on azul

$ nook exec api 'what machine are you on, and what is this repo?'
❯ what machine are you on, and what is this repo?
 I'm on azul (linux), in /srv/work/acme/checkout-api — the payment
  capture and settlement service. Want me to run the tests?
✻ thought for 3s

Try ↑ for history · tab to complete

Not a mockup

This is already how the work gets done.

An agent running on one machine started a Claude Code session on a second machine, sent it prompts, read its answers, and drove the work to completion — using nothing but nook start, nook send, nook read and nook exec. No ssh session was opened. No port was forwarded. No hostname was typed.

NookOS ships that capability as an agent skill, so any agent you run can do the same thing: ./skills/install.sh --host <box>. The protocol is small enough to explain in one line — send types, read looks, exec does both and waits — which is exactly why an agent can pick it up without a wrapper library.

How it works

Four commands is the whole protocol.

You name a workspace and a runtime. The control plane finds a machine that has that repo checked out and starts the session there. You never address the machine directly.

  1. Look at the fleet

    Machines, repos and running sessions, kubectl-style. Every node reports its own capabilities, including which runtimes it actually has installed.

    $ nook get nodes
    NAME     PLATFORM  STATUS  RUNTIMES
    azul     linux     online  claude,codex,bash
    crimson  linux     online  hermes,bash
    
    $ nook get workspaces
    $ nook get sessions
  2. Start a session anywhere

    Pick the runtime you want — claude, codex, hermes, bash, zsh. Drop --node and the scheduler picks an online machine that has the repo.

    $ nook start acme/checkout-api --runtime claude
    $ nook start acme/checkout-api --node azul --runtime claude --name refactor-auth
  3. Talk to it

    exec polls until the screen stops changing for two consecutive reads — the only honest way to know an agent has finished, because thinking time is unpredictable and a fixed sleep either truncates the answer or wastes minutes.

    $ nook exec refactor-auth 'move the token refresh into middleware' --timeout 600
    $ nook send refactor-auth 'yes'      # answer a permission prompt
    $ nook read refactor-auth --lines 400
  4. Fan out

    Sessions are independent and persistent. Start work on three repos across three machines, go and do something else, and collect the results when you get back.

    $ nook start acme/checkout-api    --node azul    --runtime claude --name api
    $ nook start widgets/web-dashboard --node crimson --runtime claude --name web
    $ nook send api 'upgrade sqlx and fix the fallout'
    $ nook send web 'migrate settings to the new form component'

What it is

A control plane for machines, workspaces and sessions.

NookOS does not replace your editor, your Git, or your AI. It coordinates everything around them, and it keeps the coordination in one place you own. Claude writes the code. Nook decides where it runs, remembers that it ran, and is still holding the session when you come back — an operating system for the work rather than for the machine.

Nodes

Machines join with a token and connect outbound over WebSocket — no inbound SSH, no public ports. Each reports CPU, memory, load, session capacity and installed runtimes, live.

Workspaces

A workspace is a repo, not a machine. The same workspace can exist on many nodes; a repository's identity is its git remote, so two checkouts of the same thing are the same thing.

Sessions

tmux-backed and persistent, streamed to xterm.js in the browser. They survive page refreshes, network drops, your process exiting and the node restarting.

Runtimes

A session runs whatever you choose — bash, zsh, claude, hermes, codex. Ask a node for a runtime it doesn't have and it fails immediately, not mysteriously.

Board

Kanban that actually dispatches work. Triage → Todo → In Progress → Done, where start work creates a worktree and a session, and prune tears the worktree back down.

Activity

Everything produces an event, streamed live over WebSocket. Plus rolling per-workspace notes, so the context of a piece of work lives next to the work.

MCP surface

An MCP server at /mcp exposes the whole system to any MCP client: list workspaces, nodes and sessions, start a session, send to it, read activity, create a task.

Identity

Generic OIDC against any standards-compliant IdP, authorization code + PKCE, multi-tenant from the schema up. Access tokens are issued and revoked in the UI.

Desktop

A Tauri shell wraps the same application, so the fleet is a native window when you want one and a browser tab when you don't.

The application

Mission control, in amber.

One screen for every machine, every repo and every running session you own.

The NookOS dashboard: a dark amber-on-charcoal panel layout showing online nodes, recent workspaces, running sessions and a live activity feed.
DashboardNodes, workspaces, running sessions and the live activity feed on one screen.
A NookOS session view with Claude Code running live in the embedded terminal, mid-conversation inside a repository.
A session, liveClaude Code running in a persistent tmux-backed session, streamed into the browser.
The NookOS workspaces list, showing repositories with their branch, dirty state and which machines hold a checkout.
WorkspacesEvery repo NookOS knows about, and which machines hold a checkout of it.
The NookOS kanban board with Triage, Todo, In Progress and Done columns holding task cards.
BoardKanban that dispatches: a card becomes a worktree, a machine and a session.
The NookOS nodes page listing machines with live capacity bars for CPU, memory and active sessions.
NodesLive CPU, memory, load and session capacity, so you can see what can take the work.
The New Work modal in NookOS, offering to clone a repository, add a worktree, start a new project or open an existing workspace, with machine and runtime pickers.
New WorkClone, add a worktree, or open what's already there — then pick the machine and the runtime.
The NookOS settings page on the Access tokens tab, listing issued tokens with their scope and creation date.
Access tokensIssue a user token to drive the whole fleet from the CLI; revoke it in one click.

Install

Docker first. Up in one command.

  1. Bring up the control plane

    Point OIDC_* at your identity provider, or leave dev sign-in on while you look around. Open http://localhost:5173.

    $ git clone https://github.com/nook-os/nook-os
    $ cd nook-os
    $ cp .env.example .env
    $ ./run.sh
  2. Add a machine

    In the UI: Nodes → add node, then run this on the machine you want to add. It connects outbound; nothing needs to be reachable from the internet.

    $ nook join --server https://nook.example.com --token nook_join_...
    $ nook run
  3. Get a user token

    A node token is confined to its own machine on purpose — it sits in a file on a box that runs other people's code, so one compromised machine must not become every machine. A user token is what drives the fleet.

    $ nook login --token nook_user_...
    $ nook whoami
  4. Teach your agents

    NookOS ships as an agent skill. Install it and your agent can start and drive sessions across the fleet on its own.

    $ ./skills/install.sh                 # this machine
    $ ./skills/install.sh --host crimson  # and that one

Posture

Self-hosted means self-hosted.

PropertyHow it behaves
NetworkNodes dial out over WebSocket. No inbound SSH, no public ports, no reverse tunnel to a vendor.
TelemetryNone. There is no phone-home, no analytics endpoint, and no account required to run it.
CredentialsA node token can only act on its own machine. Only a user token drives other machines, and it lives 0600 in your home directory.
DataYour Postgres, your disks, your repos. Git stays the source of truth; NookOS coordinates, it does not own.
LicenceApache-2.0. Fork it, run it, embed it, sell services on it.
ExtensibilityRust owns the types: OpenAPI is generated from the code and TypeScript from OpenAPI, so third-party clients cannot drift.

Questions

The ones people actually ask.

Why not just ssh and tmux?

You can. You will also be managing hostnames, keys, jump hosts, VPN state, port forwards and a mental map of which box has which repo — and none of that is addressable by an agent without giving it shell credentials to everything.

NookOS gives you one verb per intent instead: name the repo, name the runtime, go. The machine is an implementation detail the control plane resolves.

Do sessions really survive?

Yes — they're tmux sessions on the node, not proxied processes. Your laptop closing, your terminal dying, the network dropping and the control plane restarting are all survivable. Come back hours later and nook read still prints the screen and its scrollback.

What happens when a node goes offline?

The session is marked as having an offline node and starts working again when the machine reconnects. The tmux session was never destroyed; only the transport went away.

Does it work with agents other than Claude?

--runtime is any executable the node reports. Claude Code, Codex and Hermes are the ones in daily use; a plain shell is a first-class runtime, and adding another is a matter of it being installed on the machine.

Can an AI drive NookOS itself?

That's the point. There's an MCP server at /mcp covering the whole surface, and an agent skill that teaches the CLI. The built-in dispatcher recommends where work should run — it recommends, it never acts. Humans approve.

What's not done yet?

Multiple worktrees of the same app on one machine can collide on ports, and there's no automatic fix yet. Kanban federation to Jira, GitHub, Linear and Trello sits behind a provider trait but ships local-only today. The roadmap is in the repo, not in a press release.

Is there a hosted version?

A managed service is coming. The self-hosted build is not a crippled tier — it is the whole product, and it always will be. Join the waitlist if you'd rather someone else ran the control plane.

Your machines, one control plane.

Free, open source, Apache-2.0, self-hosted, no telemetry. Clone it and have a fleet in about five minutes.