Observed since 20 Oct, 21:35 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
9agent
Universal 9Router agent launcher — discover models, pick agent, launch.
One launcher for Claude Code, Pi, and Hermes — pick a model from your gateway, launch the agent, optionally in Docker.

npm i -g 9agent
9agent # prompts: agent → model → mode
9agent -a claude -m ag/gemini-3.7-flash-high --yolo # skip the prompts
9agent -a claude -m ag/gemini-3.7-flash-high --yes safe --sandbox # ...and in Docker
| Need | Why |
|---|---|
| Node >= 20 | fetch, import.meta |
A gateway serving GET /v1/models | Where the model list comes from. Built for 9Router; anything OpenAI-compatible works |
One of claude, pi, hermes | 9agent launches these, it doesn't bundle them |
| Docker | Only for --sandbox |
No gateway? You get Is 9Router running? and exit 1 — never a hang.
| Flag | Description | Default |
|---|---|---|
-a, --agent <name> | claude|pi|hermes, or alias c/cc/p/h | picker |
-m, --model <id> | Model id | searchable picker |
--sandbox | Run the agent in Docker | host |
--yolo | Skip permission prompts | safe |
--yes <mode> | Non-interactive: safe|dangerous | — |
--gateway <url> | Gateway base URL | http://localhost:20128/v1 |
--key | Prompt for this gateway's key and save it to its profile | see below |
--print-only | Print the resolved env + argv, spawn nothing | — |
-V, --version | Print version | — |
The gateway URL comes from --gateway, else NINEROUTER_URL. The key comes
from the profile saved for that gateway, else NINEROUTER_KEY, else
LOCAL_9ROUTER_KEY, else the sk_9router placeholder (a local placeholder,
not a credential).
Save a key once, at a masked prompt, rather than typing it inline where it lands in shell history:
9agent --gateway https://router.example.com/v1 --key
Profiles live in ~/.config/9agent/config.json (mode 0600), one key per
gateway URL. LOCAL_9ROUTER_KEY exists because a sandboxed agent
reaches the gateway as a remote client, where the placeholder is rejected and a
real key is required.
Sandbox runs invoke docker from PATH; set NINEAGENT_DOCKER_BIN to route them
through something else, e.g. NINEAGENT_DOCKER_BIN="sudo -n docker" (requires
passwordless sudo). Prefer adding yourself to the docker group — group
membership and sudo grant the same power with less ceremony.
Anything after -- goes to the agent verbatim:
9agent -a claude -m ag/gemini-3.7-flash-high --yes safe -- --verbose
| Agent | --yolo becomes | Gateway routing |
|---|---|---|
| Claude Code | --dangerously-skip-permissions | env vars |
| Pi | nothing — Pi has no permission system | ~/.pi/agent/models.json |
| Hermes | --yolo | 9router provider in ~/.hermes/config.yaml |
Pi and Hermes have no env var for the base URL, so the gateway must already be in their config. 9agent reads those files; it never writes them.
For Hermes, --safe-mode is not the opposite of --yolo — it disables
customizations. Safe mode is simply omitting --yolo.
9agent -a claude -m ag/gemini-3.7-flash-high --yes safe --sandbox
Runs the agent in Docker — a blast-radius limiter, not a security boundary against a hostile agent. Only cwd and the agent home are mounted, and anything your host executes (hooks, plugins, settings) is mounted read-only. The container keeps full network egress — reaching the gateway requires it — so it bounds filesystem blast radius, not exfiltration.
docs/sandbox.md has the full threat model, the per-agent details, and the known limits.
9agent resolves a model, execs the agent, and mirrors its exit code. It is not a session manager and not a config broker. Two rules follow:
CONTEXT.md is the vocabulary. ADR-0001 records what this trades away.
npm install
npm run dev # tsx
npm run check # typecheck, build, unit tests
npm run test:docker # integration harness (needs Docker)
npm run release # gate, build, verify the tarball, tag — CI publishes to npm
Issues and pull requests welcome — see CONTRIBUTING.md. Release history is in the changelog.
MIT — see LICENSE.
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
commanderEnvironment{
"local_name": "commander",
"alias": false,
"peer_metadata": null
} | ^13.0.0 | runtime |
@inquirer/promptsEnvironment{
"local_name": "@inquirer/prompts",
"alias": false,
"peer_metadata": null
} | ^7.0.0 | runtime |
tsxEnvironment{
"local_name": "tsx",
"alias": false,
"peer_metadata": null
} | ^4.0.0 | development |
eslintEnvironment{
"local_name": "eslint",
"alias": false,
"peer_metadata": null
} | ^9.39.5 | development |
@eslint/jsEnvironment{
"local_name": "@eslint/js",
"alias": false,
"peer_metadata": null
} | ^9.39.5 | development |
typescriptEnvironment{
"local_name": "typescript",
"alias": false,
"peer_metadata": null
} | ^5.7.0 | development |
@types/nodeEnvironment{
"local_name": "@types/node",
"alias": false,
"peer_metadata": null
} | ^22.0.0 | development |
typescript-eslintEnvironment{
"local_name": "typescript-eslint",
"alias": false,
"peer_metadata": null
} | ^8.67.0 | development |
Source distribution
{
"shasum": "da9e4f5cc2887548286299bd315c34da4145d193",
"tarball": "https://registry.npmjs.org/9agent/-/9agent-0.3.0.tgz",
"fileCount": 27,
"integrity": "sha512-td34l2XG7zxDCFh6lfwRNXkWQjz+jJkajUhhvVmPyQbnLhQRPClSCwOF3Exc5xfqbJ+lgy0qxa3ohUM1ex4xqQ==",
"signatures": [
{
"sig": "MEUCIFyuDYJFrylU9VVnMYzz1+pBxrZUrk2CtbcihxHp3l5VAiEAyRx5j9ek1RejF5TCdm1QWotRmQUWsA4y29jkG864M5g=",
"keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"
}
],
"unpackedSize": 72444
}Observed since 20 Oct, 21:35 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:60c15fb33290c5011cbce2871efd088d1d4e4741a2a85f8940921c7a2487cf0d