Warpdrive CLI guide
The Warpdrive CLI drives the engine underneath Warpdrive: it gives each project its own Instance — an isolated container — and runs your coding agents inside it. This page is the terminal way in — install it, start it, get an Instance running, and pair it to a Gateway so the desktop and phone apps can drive it. Same engine either way.
Version 0.10.0. Everything below works on a machine with nothing else
installed and no account. Once the engine is running, warpdrive
--help is the authoritative command list for the build you actually
have.
What the engine is#
One warpdrive process on your machine manages Instances. An
Instance is a container — Docker, Podman, or another supported runtime provides
the isolation — with your project folder bind-mounted at /ws, a tmux
server for the agents to live in, whichever coding CLIs you enabled, and its own
MCP servers. The engine itself never sends your code anywhere; what an agent
sends to its AI provider is covered in Trust & Privacy.
Nothing about that requires a GUI, an account, or an internet connection. The TUI, the desktop app, and the phone app are three front ends over that same engine, and the terminal is the one that needs the least installed.
Console or app?#
They are two front ends over one engine, so this is not a fork in the road you have to commit to. Most people run the app for daily work and reach for the console when they want to automate something or when the machine doing the work has no screen.
Reach for it when
- The machine is headless. A server, an old laptop in a closet, a machine you only ever SSH into.
- You want it scripted.
warpdrive buildandwarpdrive attachare enough to drive an Instance from CI, cron, or a Makefile. - You live in the terminal.
warpdrive attachdrops you straight into the agent's tmux session with your own config and keybindings. - Nothing hosted is involved. No account, no Gateway, no network — the engine on its own is enough.
What you give up
- No Store. Store Apps, creator installs, and one-tap starting points live in the app.
- No chat surface. Basic mode's Assistant, Chats, and previews are app features.
- No phone. The console is where you are sitting; the app follows you to another room.
- You wire your own workflow. Fleet views, queues, and diffs are things the app gives you and the terminal does not.
- One machine at a time. Making several machines feel like one fleet is what pairing to a Gateway is for.
Reach for it when
- You want the whole deck. Instances, Workspaces, Orchestrators, snapshots, and diffs in one view.
- You want the Store. Install an App without cloning or configuring anything first, and build Orchestrators in Studio instead of writing a manifest.
- You move around. Pair by QR and pick the same run up on your phone.
- You want identity and notifications. Accounts, sign-in, and push come from the Gateway side.
- Someone else has to use it. Handing a teammate a URL beats handing them a terminal.
What you give up
- A Gateway has to exist. The Warpdrive desktop app runs your own Gateway — the connection point your other devices use. The mobile app is a client only and never hosts one.
- Automation is indirect. The app is for driving work by hand; scripted work belongs in the console.
- More moving parts. More to install, sign in to, and keep running than one tarball.
The Warpdrive desktop app already contains this engine — installing it is not an alternative to the CLI, it is the same engine plus a GUI and a Gateway.
The usual shape. Install the Warpdrive desktop app on the machine you
sit at. Install the CLI tarball on every other machine you want doing work, and
warpdrive remote pair each one to your
Gateway. The app becomes the console for all of them, and every machine still
runs its own Instances on its own disk.
Install#
| Requirement | Needed for |
|---|---|
| Node.js 20+ | Everything. The bundle is JavaScript plus launcher scripts, not a native binary. |
| A container runtime | Instances. Pairing, the relay, and remote status work without one. Docker (including Docker Desktop, OrbStack, Colima, and Rancher Desktop), Podman, nerdctl, and Apple Container (macOS 26 or later) are picked up automatically; point WARPDRIVE_CONTAINER_CLI at anything else that speaks the docker CLI. |
| tmux (host) | Only for warpdrive attach. Instances run their own tmux inside the container regardless. |
Runs on macOS, Windows, and Linux. Pick the archive for your machine —
macos-arm64, macos-x64, linux-x64,
linux-arm64, or the Windows zip. They differ only in the
bundled TUI binary, which is native code. Optional native accelerators fall back
to pure JS off their build architecture.
tar -xzf warpdrive-alpha-macos-arm64.tar.gz -C ~/
cd ~/warpdrive-alpha-*
./install.sh # or double-click "Install Warpdrive.command"
warpdrive -h
The installer puts warpdrive on your PATH and nothing else —
/usr/local/bin when it can write there, ~/.local/bin
otherwise. It checks for Node and a container runtime and tells you what is
missing rather than installing either behind your back, and it never touches an
engine it did not start.
Extract somewhere permanent and keep the folder intact — the launcher resolves
the engine and the TUI binary next to itself. Moving the whole folder later is
fine; copying warpdrive out of it is not, which is why the line
above symlinks. On Windows the entry point is warpdrive.cmd.
To upgrade, unpack the new archive beside the old one and repoint the symlink.
State lives in ~/.warpdrive/, not in the bundle, so Instances,
pairings, and config survive.
Quickstart#
Same four steps on macOS, Linux, and Windows. Your container runtime — Docker, Podman, or another supported one — has to be running before the first one.
-
Point it at your projects
warpdrive set-workspace-root ~/code # the folder your repos live inSaved to
~/.warpdrive/config.json. Skip this if you only ever work in one folder — every command below defaults to the directory you are standing in. -
Build an Instance for a project
cd ~/code/my-project warpdrive build # builds the container for this folder and starts itThe first build pulls and builds the image, so give it a few minutes. Your folder is mounted at
/wsinside the container — it is the real folder, so edits inside the Instance are edits on disk. -
Sit down inside it
warpdrive attach # Created tmux session "warpdrive-my-project". Press <prefix>+s to switch.Ordinary tmux from there — start Claude Code, Codex, or whatever you enabled, and <prefix>+d detaches and leaves every agent running.
-
Or drive it from the TUI
warpdrive # the full-screen console: create, start, stop, attachThe TUI does everything
buildandattachdo, plus Instance management, and it is the easier way in if you are just looking around.
Want the apps too? Pair this machine to a hosted Gateway with
warpdrive remote pair and the desktop and
phone apps can drive these same Instances. The Instances and the code stay
here.
Concepts#
| Term | What it means |
|---|---|
| Instance | One isolated container plus its state. Owns a Workspace, a tmux server, its agents, and its MCP servers. Basic mode in the app calls the same thing a Space. |
| Workspace | The host folder bind-mounted at /ws. Survives stop, start, and rebuild; captured by snapshots; deleted only when you delete the folder yourself. |
| Provider | A coding agent CLI available inside the Instance — claude-code, codex, copilot, opencode — or a raw API credential. You sign in to it inside the Instance; keys stay on your machine. |
| Orchestrator | A reusable definition of how coordinated work runs: which agents, in what order, where it stops for approval, and what it requires. In the app you build one in Studio. From the CLI you write it as a Git repo with a warpdrive.manifest.yml at its root that declares the sessions, background processes, and actions an Instance should have — and a Studio Orchestrator can call those actions. Either way it turns an Instance from a container into a workflow. See the manifest reference. |
| MCP server | A tool server wired into the agents. Per-Instance ones follow the Instance lifecycle; global ones are shared across Instances. MCP wiring is in the reference. |
| Snapshot | A point-in-time copy of the Workspace. Previewable before you restore it. |
| Relay | One outbound authenticated WebSocket from your machine to a hosted Gateway. The Gateway never dials in; nothing has to be port-forwarded. |
Command reference#
| Command | What it does |
|---|---|
warpdrive | Launch the TUI. Starts the engine first if it is not already running, and stops it again on exit — an engine you started yourself is left alone. |
warpdrive tui | The same thing, explicitly. |
warpdrive serve | Run the engine headless, logging to stdout. This is what you put behind systemd or a LaunchAgent. |
warpdrive attach | Attach to the tmux session of the Instance owning the current directory. |
warpdrive build | Build an Instance from the saved config without the TUI. |
warpdrive set-workspace-root <path> | Set the default project root in ~/.warpdrive/config.json. |
warpdrive remote … | Pair with a hosted Gateway, run the relay, and approve what it may touch. Details below. |
warpdrive local-ai … | Install a model that runs on this machine and point the agents in your Instances at it, so no API key is needed. Local AI guide. |
warpdrive --help | The full list, straight from the binary you have. |
warpdrive attach#
attach resolves the Instance from your current directory and opens
its first session in your own terminal. Run it again later and it reports the
existing session instead of creating a second one. The TUI's attach and this
command are the same mechanism, so they cannot drift apart.
| Exit code | Meaning |
|---|---|
0 | Attached, or reported an existing session. |
2 | No Instance matched the current directory. |
3 | An Instance matched but is not attachable — usually stopped. |
Pair with a Gateway#
This is the free path that keeps your work at home: your code and your Instances stay on your machine while a hosted Gateway provides identity, notifications, and the Store. Your machine opens one outbound authenticated WebSocket — the Gateway never dials into you, so there is nothing to port-forward and nothing to expose. Commands and terminal output you send through it do cross the relay; see Trust & Privacy.
# mint a pairing code in the desktop or mobile app first (they expire in 10 minutes)
# codes are 20 characters in five groups of four
warpdrive remote pair --gateway=https://your-gateway --code=XXXX-XXXX-XXXX-XXXX-XXXX
warpdrive remote relay
# keep it up across reboots (macOS)
warpdrive remote install-agent| Subcommand | What it does |
|---|---|
pair --gateway=<url> --code=<code> [--device-name=<name>] | Redeem a pairing code and save the device credential locally. |
relay [--once] | Hold the outbound device WebSocket open, reconnecting as needed. --once runs a single session. |
status [--json] | Show the saved pairing — device, realm, Gateway, config path — with the credential redacted. |
bind-workspace --workspace-id=<id> --path=<abs-path> [--display-name=<name>] | Approve one local folder for one backend Workspace ID. |
bind-provider --provider-id=<id> --provider=<codex|claude-code|opencode|copilot> | Approve a backend provider ID for a local provider. |
list-workspace-bindings [--json] | Show approved workspace bindings and where they are stored. |
list-provider-bindings [--json] | Show approved provider bindings. |
install-agent [--no-load] | Install and load the macOS LaunchAgent for the relay. |
uninstall-agent | Remove that LaunchAgent. |
Pairing alone grants nothing. The hosted side can only reach a Workspace or provider you have explicitly bound. Unbound IDs are refused. An approved path is the security boundary, so keep it as narrow as the work needs — bind the project folder, not your home directory.
--json is available on every read command and always redacts the
device credential, which makes these safe to pipe into jq in a
script or a log.
Configuration#
Precedence is project .warpdrive/config.json → global
~/.warpdrive/config.json → built-in defaults. Drop a project file in
a repo and it wins for that repo only; everything else falls back to the global
one.
Container runtime#
Leave it unset and the engine uses whichever known client it finds on PATH, in
this order: docker, podman, nerdctl, Apple
container. To pin one — or to use any other client that speaks the
docker CLI — name its binary or full path in the global config:
{ "containerCli": "podman" }
The WARPDRIVE_CONTAINER_CLI environment variable does the same for
one shell and wins over the config file. The choice is read at start-up, so
restart the engine after changing it.
Extra mounts#
{
"sandbox": {
"sshPort": 2222,
"mounts": [
{ "hostPath": "/Users/you/shared-data", "containerPath": "/data", "readOnly": false },
{ "hostPath": "/Users/you/secrets", "containerPath": "/secrets", "readOnly": true }
]
}
}
hostPath must be absolute. readOnly defaults to
false. The workspace folder is always mounted at /ws
and does not need an entry here.
Environment variables#
| Variable | Default | Effect |
|---|---|---|
WARPDRIVE_CONTAINER_CLI | first found | Container client to drive — a binary name or path. Overrides containerCli in the config. |
WARPDRIVE_WORKSPACE_ROOT | from config | Default project root when creating Instances. Same thing set-workspace-root writes, for when you would rather set it per shell. |
WARPDRIVE_API_PORT | 7777 | Port the engine listens on locally. Change it if something else already owns 7777. The HTTP API on that port is documented in the reference. |
WARPDRIVE_HOST_HOME | your home dir | Root for ~/.warpdrive/ state — Instances, pairings, config. |
WARPDRIVE_TMUX_SOCKET | Warpdrive's own | tmux socket name, so Warpdrive never collides with your personal tmux server. |
A scratch engine that cannot disturb your real Instances is a second port and a second state root together:
WARPDRIVE_API_PORT=7788 WARPDRIVE_HOST_HOME=/tmp/wd-scratch warpdriveAPI and manifest reference#
Everything the TUI and the apps do goes through the engine's local HTTP API on
port 7777. The API and manifest reference
covers that API, the warpdrive.manifest.yml Orchestrator format, MCP
server wiring, and publishing to the Store.
Security model#
The short version: the engine listens on your machine only, and pairing a Gateway to it grants that Gateway nothing until you name what it may touch.
- The engine is local. It binds loopback and stays there. It can run commands in every Instance you own, which is exactly why it is not something to expose to a network — pair to a Gateway instead. The relay is outbound-only and authenticated, so nothing on your machine has to listen for it.
- Remote reach is bounded by bindings, not by pairing. A Gateway can only touch the Workspaces and providers you approved by ID with
bind-workspaceandbind-provider. Anything unbound is refused. - Provider credentials stay here. You sign in to Claude Code, Codex, or Copilot inside the Instance. The engine does not ship those sign-ins to a hosted service.
- Instances are isolated from each other. Each one is its own container, its own tmux server, and its own Workspace mount.
- Watching is not driving. Read-only session access is a real boundary, not a UI hint — it is what lets a phone watch a run without being able to type into it.
Troubleshooting#
| Symptom | What is happening |
|---|---|
warpdrive-tui binary not found | The archive was extracted partially, or the launcher was copied out of its folder instead of symlinked. Re-extract, then symlink. |
| Port 7777 already in use | An engine is already running, which is fine — the TUI connects to it. Set WARPDRIVE_API_PORT to run a second one. |
no sandbox found for "<dir>" | No Instance was found for this folder — the message still uses the engine's older word for an Instance. attach matches on Workspace path, so cd to the Workspace root, or create an Instance for it. |
build fails at the container check | No reachable container runtime. Start Docker, Podman, or whichever you use and retry; if it is installed but not found, set containerCli. Pairing, relay, and status work without one, but Instances do not. |
| Instance fails to boot after 15s | Its tmux server never came up, which is a hard boot gate. warpdrive build --rebuild is the usual fix; an init script in the workspace racing the boot is the usual cause. |
| Relay will not reconnect | warpdrive remote status to confirm the pairing survived, then relay --once in the foreground to read the failure. |
Known limits#
- One engine drives one machine. A Gateway is what makes several machines feel like one fleet.
- Apple Container needs macOS 26 or later. Any other client has to accept the docker CLI's commands and flags, because the engine shells out to it the same way.
- No in-browser code editor. Attach, or open your own editor against the Instance.
- In the standalone tarball, the vault worker builds its container from a Dockerfile that ships with the full desktop install. Vault capture warns and retries; everything else runs normally.
- The bundle is unsigned. macOS Gatekeeper does not quarantine extracted tarballs the way it does DMGs, so no extra step is normally needed.