@north-light/cli
v0.3.509
Published
crtr — agent runtime with memory, plugins, and marketplaces
Keywords
Readme
crouter — an agent runtime: durable agents on a canvas, driven from a CLI or an SDK
crouter is an agent runtime for Node.js. Each agent is a node: a record with a goal, a context directory, and a detached process (its broker) that hosts the model session. A daemon, crtrd, owns every node's state and lifecycle. You drive it with the crtr command line, a terminal viewer, or a typed TypeScript SDK — all three are clients of the same local API. Each model session runs on pi, the open-source coding-agent harness; crouter adds the daemon, the node graph, the context system and the CLI around it.
Closing a terminal does not stop an agent, and an agent that is waiting on something has no process at all. Nodes can spawn children, report to whoever subscribes to them, and share markdown documents that other agents are shown when they become relevant. crouter is not a model and does not bundle one: you sign in to a model provider during setup. It is also not a hosted service; it runs on your machine, or in a container you start.
Docs · Getting started · Concepts · SDK · Plugins · Marketplace · Discord
Install
npm install -g @north-light/cli
crtrThe first crtr on a machine opens the setup installer. It signs you in to a model provider, then offers companion packages (including the official plugin marketplace) and system dependencies such as tmux. After setup, crtr opens a conversation with an agent, which offers a short tour of how crouter works. crtr sys setup reopens the installer later.
Requirements:
- Node.js 22.19 or later. This is the floor set by the pi packages crouter depends on; CI and the Docker image run Node 24.
- tmux, for the in-terminal viewer. The first-run installer offers to install it, and
crtrstarted outside tmux opens acroutertmux session for you and runs there. - macOS is what CI exercises. On Linux, the supported route is the Docker image (see Run it in a container).
Quick start
From the directory you want the agent to work in (outside tmux, crtr starts it for you):
crtr # a conversation here
crtr . "Inspect this repository and report the failing tests." # with a first message
crtr -c # return to the latest conversation here
crtr -r <node-id> # reopen one conversation by id (`crtr -r` alone picks)Enter sends a message; Alt+Enter (Option+Enter on a Mac) or Shift+Enter starts a new line.
To start an agent without taking over the terminal, from a script or another agent, create a root node:
crtr node new --root "Inspect this repository and report the failing tests."--root creates an independent node and starts its broker. Inside tmux the command opens a viewer pane for it; outside tmux it prints the node id, and you open the viewer yourself:
crtr surface attach to <node-id>The viewer is not the agent. Close it and the node keeps working; open it again later for the saved conversation. To see every node on the canvas:
crtr canvas dashboard # the subscription tree as ASCII: status, kind, context size
crtr canvas browse # interactive navigator with tabs and search
crtr canvas attention list # nodes waiting on youThe first-session guide walks through this in order.
What it does
Each item names the command that does it. crtr <command> -h prints the exact contract for any of them.
Nodes and delegation. crtr node new creates a child and subscribes its parent to it; the child reports with crtr push update and finishes with crtr push final, and that report wakes the parent. --worktree <branch> gives a child its own git worktree on a crtr/<node-id> branch, --fork-from starts it from another node's conversation, and --output-schema makes its final result a JSON document validated against a schema. A node that decides its work divides into independent parts runs crtr node promote and becomes an orchestrator.
Waiting costs nothing. A node with nothing to do ends its turn and becomes dormant: no broker, no model call. A child's report, a message (crtr node message send), a human answer, or a cron wakes it with its conversation intact. If a broker crashes, the daemon keeps the node's row, session, waits and inbox; crtr canvas revive --all reconnects every disconnected node after a reboot.
The canvas. Every node, document, background job and owner is an object with a name. crtr canvas read, list, search and edges work on all of them. Reading or writing an object makes you a watcher, so later edits and reports arrive in your inbox. crtr canvas history searches what past runs in a directory were told and said.
Documents. Knowledge (consulted) and preferences (followed) are markdown documents owned by a node, repo, profile, user or plugin. Delivery rules decide whether an agent is shown a document's name, its one-line "read when" preview, or its full body — at startup, when it reads a file, or before a command. crtr doc write and crtr doc edit write them; crtr sys context explains why one did or did not load; crtr sys sync imports CLAUDE.md, AGENTS.md, .claude/rules and skill bundles.
Human inbox. crtr human send puts a typed page (a picker, a table, free text) in your inbox; your answer is delivered back to the node that asked. crtr human review opens a document for review with anchored comments, and crtr human show keeps a file live in a tmux pane.
Scheduling. crtr cron add stores a bash command the daemon runs at a time or cadence (--at, --every) and can route its output to a node's inbox or to a fresh node (--sink node:<id> / spawn:<kind>). A command that exits 75 is treated as not yet eligible, and the next cadence re-checks it.
Scopes. A node or a remote token carries an allow-list (crtr:llm, crtr:act, crtr:schedule, crtr:memory:read:user, …) that the daemon checks at the route that performs the action. crtr sys connect --app <id> --scopes … mints a token whose list caps everything an application can create.
Plugins and marketplaces. A marketplace is a git repository of plugins; crtr pkg market add <git-url> registers one and crtr pkg plugin install <marketplace>/<plugin> installs from it. A plugin can add commands (local executable or HTTP), documents, agent kinds, and binaries. crtr custom-object register makes an outside service a watchable object on the canvas.
How it fits together
flowchart LR
CLI[crtr CLI] --> API["/v1 API"]
SDK[SDK application] --> API
Viewer[Terminal viewer] --> API
API --> Daemon[crtrd]
Daemon --> Canvas[Canvas state]
Daemon --> Broker[Detached broker per node]
Viewer -. live session .-> Brokercrtrd is the only writer of canvas state and the only launcher of brokers. The CLI, the viewer and SDK applications call its /v1 API; none of them opens the canvas database or starts an engine of its own. On one machine they use an owner-only Unix socket. A browser or a remote process uses a TCP listener and a bearer token (crtr sys connect).
What this costs: a daemon has to be running (the CLI and SDK start it on first use), and a network failure on a remote client fails a request loudly rather than replaying it. What it buys is one owner for state, so a node outlives the terminal, the viewer, or the application that created it. Why a daemon covers the reasoning.
Use crouter from an application
npm install @north-light/sdk zodimport Crouter from '@north-light/sdk';
import { z } from 'zod';
const client = new Crouter(); // local daemon; started on first request if it is not running
const run = await client.nodes.parse({
prompt: 'Read package.json and return its name and version.',
cwd: '/absolute/path/to/project',
output_schema: z.object({ name: z.string(), version: z.string() }),
});
if (run.kind === 'result') console.log(run.output_parsed.name, run.output_parsed.version);
else console.error(run.reason, run.detail);nodes.parse returns a typed result or an explicit failure; it never hands back text you have to parse. nodes.stream pipes a run's text and tool calls to a UI. See the SDK docs and the recipes.
Run it in a container
docker run --cap-add SYS_ADMIN --cap-add NET_ADMIN --security-opt seccomp=unconfined --security-opt apparmor=unconfined \
-e CRTRD_TOKEN=<a-secret-you-choose> -p 7777:7777 ghcr.io/northlight-systems/crtrd
curl -H "Authorization: Bearer <a-secret-you-choose>" http://localhost:7777/healthzThe image runs crtrd headless behind TCP; every request needs the bearer token. Its sandbox launcher needs the two capabilities and unconfined seccomp/AppArmor profiles shown. It contains no model credential, so give the agent one before you create a run. Mount a named volume at /volume to keep the canvas and installed credentials across restarts. From Node, @north-light/env-docker starts and stops this container for you. Details are in docker/README.md.
Extend crouter
An application exposes typed operations as native crtr commands with @north-light/plugin: define a command tree once and it produces the HTTP handler and the archive that crtr pkg plugin install --endpoint <url> --name <name> reads. The plugin docs cover commands, parameters, output, errors and deployment.
Ready-made plugins live in the official marketplace: exa-search, capture, tsym, bird, github-asset, dev, vercel, fly, railway, cloudflare, and others. The first-run installer offers to register it.
Packages
| Package | What it is | Source |
|---|---|---|
| @north-light/cli | The crtr CLI, the crtrd daemon, and the terminal viewer | src/ |
| @north-light/sdk | Typed Node and browser client: runs, streaming, results, files, bash, memory | packages/crouter-sdk |
| @north-light/plugin | Author HTTP plugins from one typed command tree | packages/crouter-plugin |
| @north-light/api | The /v1 API contract: CrtrClient, DTOs, routes, errors | packages/crouter-api |
| @north-light/env-docker | Start or attach to a crtrd container | packages/crouter-env-docker |
| @north-light/identity | Verify access tokens and evaluate scopes | packages/crouter-identity |
Most applications need only @north-light/sdk. The other repository contents: docs/ is the documentation source, apps/docs is the TanStack Start site that publishes it at crouter.docs.northlight.ai, docker/ builds the crtrd image, and examples/ holds the SDK recipes and a localhost demo.
Develop
The source repository is private to Northlight Systems; this section is for its developers.
git clone [email protected]:Northlight-Systems/crouter.git
cd crouter
npm ci
npm run buildTests come in three lanes — unit (npm test), integration, and seam against the compiled dist/. Run them with npm run test:isolated, which copies the checkout into a temporary HOME first: the suite refuses to run against your real account home, because the runtime installer and project-scope lookups could otherwise write to it. test:isolated uses /usr/bin/lockf and /Users/Shared, so it runs on macOS.
npm run test:isolated # unit lane
npm run test:isolated -- integration seam
npm run test:isolated -- path/to/file.test.tsThe docs site runs from apps/docs with npm run dev. CONTRIBUTING.md has the pull-request conventions for Northlight Systems developers.
Security
To report a vulnerability, follow SECURITY.md rather than opening a public issue.
License
crouter is proprietary software. Copyright (c) 2026 Northlight Systems. All rights reserved. The source repository is private; the packages are published to npm as compiled, minified builds. See LICENSE.
