Documentation menu
Getting started
Three steps: install nid, cd into a Git repository, run nid.
You need a repository with at least one commit and at least one installed, logged-in
agent CLI (claude, codex, opencode, kimi). nid uses the agent's existing account
and provider configuration. Start with a small goal; grow the team once the first one works.
Install#
Requirements: git, and the agent CLIs you want to use (claude, codex, opencode, kimi),
already logged in. The release binaries are self-contained (no Node.js needed).
Linux and macOS:
curl -fsSL https://nid.dev/install.sh | sh
Windows (PowerShell):
irm https://nid.dev/install.ps1 | iex
No account, sign-up or token is needed. nid.dev serves the same scripts that are in the repository. If it is unreachable, take them from GitHub instead: every release carries them as assets, and the repository has them at the root.
curl -fsSL https://github.com/CatsWithKeyboards/nid/releases/latest/download/install.sh | sh
curl -fsSL https://raw.githubusercontent.com/CatsWithKeyboards/nid/main/install.sh | sh
irm https://github.com/CatsWithKeyboards/nid/releases/latest/download/install.ps1 | iex
irm https://raw.githubusercontent.com/CatsWithKeyboards/nid/main/install.ps1 | iex
(releases/ only points at stable releases; until the first stable release use the
raw line.) Upgrading from terminid or pawmux needs none of this:
terminid update (or pawmux update) does it, see
upgrading from terminid.
The installer downloads the newest release for your OS and CPU (nid-<os>-<arch>[.exe])
from GitHub Releases, verifies it against the release's SHA256SUMS (it refuses to install
anything that does not match, or a release without checksums), installs it to ~/.nid/bin
(%LOCALAPPDATA%\ on Windows) and adds that directory to your PATH: one line in
~/.profile plus any existing ~/.bashrc, ~/, ~/.zshrc or fish config, or the user
PATH on Windows. Open a new terminal, then run:
nid doctor # version, install method, updates, agent CLIs (also custom agents), daemon, Codex sandbox
Pick a release channel or an exact version (the channel is remembered for nid update):
curl -fsSL https://nid.dev/install.sh | sh -s -- --channel beta
curl -fsSL https://nid.dev/install.sh | sh -s -- --version 0.2.0
& ([scriptblock]::Create((irm https://nid.dev/install.ps1))) -Channel beta
& ([scriptblock]::Create((irm https://nid.dev/install.ps1))) -Version 0.2.0
| Channel | Gets |
|---|---|
stable | x.y.z releases only |
beta | betas and release candidates (-beta.N, -rc.N) and stable releases |
alpha | every release, alphas included |
Without a channel the installer takes the newest stable release, or the newest release of any kind
while there is no stable one yet, and nid update then follows the channel of the version you
run.
| Variable | Meaning |
|---|---|
NID_CHANNEL | same as --channel / -Channel |
NID_VERSION | same as --version / -Version |
NID | install directory |
NID | don't touch shell profiles or the user PATH |
NID / GITHUB_TOKEN / GH_TOKEN | optional. Releases are public; a token only raises GitHub's hourly limit for anonymous API requests (or opens a private fork). Without one, a logged-in gh is asked only if GitHub's API refuses the anonymous request (never for a custom NID host). The token is sent to the GitHub API host only, never to the download host it redirects to. |
The installer looks releases up through the GitHub API. If the API is unavailable or rate-limited,
it downloads the latest stable release (or the exact --version) straight from the release pages
(https:/), still verified against
SHA256SUMS; the beta and alpha channels need the API.
Or download a binary by hand from the releases page
together with SHA256SUMS, check it with sha256sum --check --ignore-missing SHA256SUMS
(PowerShell: compare Get-FileHash nid-windows-x64 with its line), and put it on your
PATH as nid.
From source#
Requires Node.js >= 22.13 (nid uses the built-in node:sqlite) and pnpm.
git clone https://github.com/CatsWithKeyboards/nid
cd nid
pnpm install
node packages/nid/bin/nid.mjs --help
To get a nid command on your PATH, link the package globally:
cd packages/nid && pnpm link --global
nid doctor
State and the daemon#
nid keeps its state in ~/.nid (database, logs, worktrees); set NID_HOME to use a
different directory. The daemon starts automatically on the first command; manage it with
nid daemon start|stop|status|logs (or nid daemon run in the foreground).
Commands warn once on stderr if the daemon's version or source fingerprint differs from the
CLI, suggesting nid daemon restart. This also detects source edits without a version bump.
nid daemon status shows the running daemon's version and fingerprint.
Each session keeps only its newest events in the database — 20000 by default, pruned in cheap
batches as events are appended. Set NID to a positive integer to change the
cap; non-positive or non-numeric values fall back to the default.
Your first team#
cd your-repo
nid
The first time, nid greets you, lists the agent CLIs it found with their login and
billing mode, and offers a team: a lead with workers, a writer with a cross-vendor
reviewer, or a solo agent (↑/↓, Enter; the best fit for your installed agents is
preselected). When the team has a Claude member you then pick each member's model
(↑/↓ member, ←/→ model: the agent's default, opus, sonnet or haiku; Enter). It writes
nid.yaml and asks What should your agents work on?
Type a goal, for example Add a regression test for the login redirect, and press Enter.
The team starts in the background daemon: the lead plans tasks, workers claim them, each
in its own Git worktree, and finished work is merged into the team's integration branch.
You watch it in the terminal app:
- Permission requests appear inline. Press 1 (Yes), 2 (Yes, don't ask again this session) or 3 (No, and tell the agent what to do instead).
- Type to talk to the team, or
@name ...to talk to one agent./lists commands such as/tasks,/diffand/stop; Esc interrupts the agent that is working. - When the lead reports the goal is done, a summary card shows what changed, the diff
stats and the cost. Press
lto land the work in your checkout,pfor a GitHub pull request,dto view the diff orkto keep going.
Ctrl-C twice leaves the app; the team keeps working. Run nid again to reattach with
recent history, or nid dashboard to follow the same team in your browser
(dashboard).
You can also skip the question: nid "your goal" opens the app with the goal sent, and
nid -p "your goal" runs without the app and prints a summary at the end (exit code 0
when done), which suits scripts and CI.
Commit nid.yaml if you want everyone working on the repository to get the same team;
nid land leaves it alone while it is uncommitted. Review it before larger runs, in
particular the copy list:
files such as .env listed there are copied into every worktree and readable by agents.
See local worktree files and
agent permissions.
Set up with commands#
Everything the app does is also available as plain commands. In your repository, run:
nid doctor
nid init
The initializer checks installed agents and available login evidence, then offers
three presets: a lead with two workers, a writer with a reviewer (another vendor
when available), or a solo agent. It suggests an installation command from lockfiles,
local files to copy into worktrees, a group name, goal and a $20 reported-spending
budget. It writes nid.yaml; it does not start the agents or install dependencies.
Choose the settings interactively or take defaults:
nid init --yes --preset solo --goal "Add a small regression test"
nid up
nid dashboard
Noninteractive stdin also takes defaults. --yes still refuses an existing config;
use --force only when you want to replace it. --preset lead|review|solo, --group,
--goal, --budget and --yolo override their corresponding choices. Interactively,
init offers to choose a model for each team member (Enter keeps the agent's default);
--model lead=opus --model sonnet does the same without asking (a bare model goes to
every member whose agent takes it). To default whole roles or agent types across
projects instead, use a models: block; see default models. Change a
running agent's model any time with /model in the terminal app or nid model lead sonnet. Without any
installed agent the file uses Claude as a placeholder: install/log in before up.
Login probes are limited to what each CLI reports; unknown does not mean logged out
(installed (login not checked)): Codex, for example, keeps its login in the OS keyring by
default. nid doctor asks each CLI directly.
The dashboard offers the same flow: type a goal in the overview's What should your agents
work on? box, pick a repository and a team preset, and press Start (it writes
nid.yaml when the repository has none). Advanced → Set up a repo gives every
init option. See the dashboard guide.
Review the generated copy list before starting a team: --yes accepts suggested
local config, including .env files, which makes their contents available to agents.
See local worktree files and
agent permissions.
Follow and finish with commands#
nid ls
nid board
nid inbox
nid approvals
nid approve 3 # allow request #3 (or: nid approve 3 --deny)
Use nid send <group/ to steer one session or pass a group to
message the whole team. The dashboard gives the same board, live
activity, questions and approvals in a browser.
When the work is ready, inspect and integrate it:
nid diff
nid land
# Or create a GitHub pull request:
nid land --pr
land merges the integration branch into your checkout. land --pr pushes it and
opens/reuses a PR. nid stop <group> stops processes while keeping the work;
nid resume <group> resumes conversations where the driver supports it.
nid rm <group> removes sessions, worktrees and agent branches, so review or land
the work first. It keeps the team's lessons: learnings and board decisions go to project
memory and its history is archived for nid learn; nid rm <group> --purge
deletes everything. See coordination and reviews.
Watch and steer from your phone#
In the terminal app, type /rc. The first time, your browser opens the nid.dev sign-in page (accounts.nid.dev). Sign in with a
passkey and approve the code your terminal shows. Your computer then asks for Windows Hello,
Touch ID or your password once, to confirm that this machine may be linked to that account.
From then on, open app.nid.dev on any phone or browser signed in to the same account and
you see the current team's sessions, approvals and questions. You can add it to your home
screen and turn on notifications.
nid rc # share the team of this repository
nid rc --view --for 8h # read-only, for eight hours
nid rc status # what is shared, with whom, and which devices are connected
nid rc off # stop sharing everything (the machine stays linked)
While something is shared, the status line shows rc: N devices. The first time a new phone
or browser connects you get a notice naming nid rc devices rm <id>, so you can block it on
this machine. Your nid.dev account is the lock: anyone who can sign in to it can steer the
shared teams. For per-device pairing with a fingerprint check instead, see
strict mode and
security.
Update#
nid update # install the newest release, then restart the daemon
nid update --check # only report whether a newer release exists
nid update --version 0.3.0 # install exactly this version (also to go back)
nid update --channel beta # follow another channel from now on (stable, beta, alpha)
update finds the newest release on your channel: the one you chose with --channel (or with
the installer), else the channel of the version you run (an alpha build follows alpha, a stable
build stable; a stable install is never moved to a prerelease unless you ask). It needs no
token; if the GitHub API is rate-limited it falls back to the release pages for the stable channel
and exact versions. It downloads the binary for your platform, verifies its SHA256 and replaces the running binary in
place (on Windows the old exe is moved aside and deleted on the next start). If a daemon is running
it then runs nid daemon restart with the new binary, so your sessions resume on the new build.
Installed binaries check for a newer release in the background at most once every 24 hours and
print one line on stderr when there is one (nid doctor always checks fresh). The check is
skipped off a terminal and turned off with NID. NID (default CatsWithKeyboards/) and the
token variables above apply to update as well.
From a source checkout, update only explains what to do instead:
git pull && pnpm install
nid daemon restart
Start the daemon at login#
nid daemon autostart on # start the daemon (and with it the dashboard) when you log in
nid daemon autostart status
nid daemon autostart off
| Platform | What on registers |
|---|---|
| Windows | A Task Scheduler task nid-daemon with a logon trigger for your user (no elevation needed). It runs a small ~/ that starts nid daemon start without a console window. If Task Scheduler refuses, the same script goes into your Startup folder. |
| macOS | A launchd agent ~/ (RunAtLoad, restarted only after a failure), loaded with launchctl bootstrap gui/. Output goes to ~/. |
| Linux | A systemd user unit ~/ (enabled; started now if no daemon is running). Run loginctl enable-linger to start it at boot rather than at login. Without a systemd user instance an XDG autostart entry ~/ is written instead. |
The login item records your current PATH (so the agent CLIs are found) and NID_HOME
when set. Re-run nid daemon autostart on after installing new agent CLIs in other
directories. nid doctor shows whether autostart is on.
Uninstall#
nid uninstall # lists what it will remove, then asks
nid uninstall --yes # no questions; keeps your data
nid uninstall --yes --purge # also deletes ~/.nid (NID_HOME)
uninstall stops the daemon gracefully, turns autostart off, removes the installed binary
(plus leftover update files) and removes exactly the PATH entry the installer added: the
# nid lines in ~/.profile, ~/.bashrc, ~/, ~/.zshrc and fish's
config.fish, or the install directory in your Windows user Path. On Windows the running
nid.exe cannot delete itself: it is renamed aside and removed a few seconds after the
command exits. Open a new terminal afterwards for the PATH change.
Your data directory (~/.nid or NID_HOME: database, logs, agent worktrees) is deleted
only after a second explicit yes, or with --yes --purge. Agent worktrees may hold unlanded
work, so land or copy it first. A directory that does not look like nid data is never
deleted. Without a terminal and without --yes nothing is removed. Agent branches
(nid/*) stay in your repositories until you nid rm their groups or delete them
with git; run git worktree prune in repositories nid worked in after a purge.
From a source checkout there is no binary to remove: uninstall says so and only offers to
stop the daemon, turn autostart off and delete the data directory.
Spawning agents#
Run spawn inside the git repository you want the agents to work on (it needs at least one
commit). Agents are given as agent[:name][@model]:
nid spawn claude:lead@opus codex opencode \
--goal "Add dark mode to the settings page" \
--setup "pnpm install" --budget 20
| Option | Meaning |
|---|---|
-g, --group <group> | group name (default: the repo folder name) |
--goal <text> | group goal; the lead gets it as its first task |
--policy <lead|peers> | lead (default): the first session is the lead and plans the work; peers: no lead |
--role <role> | role for these sessions (default: first is lead under the lead policy, others workers) |
-p, --prompt <text> | first message for each spawned session |
--yolo | let agents run tools without asking (each still works in its own worktree) |
--shared | work in the main checkout instead of isolated worktrees |
--setup <cmd> | command run in each new worktree, e.g. pnpm install |
--copy <path> | copy a local path/glob into new worktrees before setup; repeat for more paths |
--link <path> | share a local directory with new worktrees using a symlink (Windows junction); repeat for more directories |
--no-auto-restart | don't resume a session automatically when its agent crashes |
--budget <usd> | cumulative group budget; see Budgets |
-C, --dir <dir> | repository directory (default: current directory) |
Run spawn again with the same -g to add more agents to a running group. Inspect with
nid ls [group] (sessions, state, turns, cost, status line, pending approvals and questions)
and nid groups (sessions, tasks, spent vs budget). Change the goal later with
nid goal <group> <text...>.
nid ls also shows cumulative input/output tokens in TOKENS (IN/, including for
drivers that do not report USD cost. Counts are recorded at turn completion and survive
daemon restarts. Codex input includes its cached input (already part of input_tokens);
Claude input sums uncached, cache creation and cache read tokens. ACP uses per-turn
PromptResponse counts, falling back to explicit input/output counts in usage updates
when available; the final response replaces update counts, so they are counted once.
ACP context-window used/size values are not consumed-token counts.
Sessions without reported token usage, including sessions migrated from older databases,
start at zero; historical turns are not backfilled.
A session that is working but has emitted no events for NID (default 10;
fractional values such as 0.5 are allowed) is quiet: nid ls shows working quiet 12m
in the STATE column and nid status appends quiet:<session> Nm to the SESSIONS cell, and
the session gets one quiet for Nm (no events while working) notice per quiet period (visible in
nid watch and nid logs). A new event from the agent ends the quiet period, so a later
stretch of silence is noticed again. The daemon scans every 30 seconds (NID,
also in milliseconds, mainly for tests).