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/latest only points at stable releases; until the first stable release use the raw.githubusercontent.com 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%\nid\bin on Windows) and adds that directory to your PATH: one line in ~/.profile plus any existing ~/.bashrc, ~/.bash_profile, ~/.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
ChannelGets
stablex.y.z releases only
betabetas and release candidates (-beta.N, -rc.N) and stable releases
alphaevery 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.

VariableMeaning
NID_CHANNELsame as --channel / -Channel
NID_VERSIONsame as --version / -Version
NID_INSTALL_DIRinstall directory
NID_NO_MODIFY_PATH=1don't touch shell profiles or the user PATH
NID_GITHUB_TOKEN / GITHUB_TOKEN / GH_TOKENoptional. 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_RELEASE_API 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://github.com/CatsWithKeyboards/nid/releases/...), 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.exe 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_EVENT_RETENTION 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, /diff and /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 l to land the work in your checkout, p for a GitHub pull request, d to view the diff or k to 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/name> "message" 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_NO_UPDATE_CHECK=1. NID_RELEASE_REPO (default CatsWithKeyboards/nid) 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
PlatformWhat on registers
WindowsA Task Scheduler task nid-daemon with a logon trigger for your user (no elevation needed). It runs a small ~/.nid/autostart/nid-daemon.vbs that starts nid daemon start without a console window. If Task Scheduler refuses, the same script goes into your Startup folder.
macOSA launchd agent ~/Library/LaunchAgents/dev.nid.daemon.plist (RunAtLoad, restarted only after a failure), loaded with launchctl bootstrap gui/$UID. Output goes to ~/.nid/logs/daemon.log.
LinuxA systemd user unit ~/.config/systemd/user/nid.service (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 ~/.config/autostart/nid.desktop 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, ~/.bash_profile, ~/.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
OptionMeaning
-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
--yololet agents run tools without asking (each still works in its own worktree)
--sharedwork 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-restartdon'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/OUT), 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.usage 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_QUIET_MINUTES (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_QUIET_CHECK_MS, also in milliseconds, mainly for tests).