
Ntm
- 23 installs
- 416 repo stars
- Updated August 5, 2026
- boshu2/agentops
ntm is a Claude skill that provides operating doctrine for orchestrating NTM tmux agent swarms through its robot API, work graph, locks, mail, and pipelines.
About
A skill that provides operating doctrine for orchestrating NTM (Named Tmux Manager) agent swarms through its robot API. A developer uses it to spawn and send panes, read robot state, manage locks and mail, run pipelines, and triage work in a tmux-based control plane. It enforces a mandatory loop that discovers the live NTM contract, snapshots state, and verifies transitions in the robot snapshot rather than trusting exit codes. The same binary is also aliased as atm.
- Operating doctrine for orchestrating NTM tmux agent swarms via its robot API
- Mandates a discover-snapshot-select-prove-execute-verify-cleanup loop
- Treats the robot snapshot, not command exit codes, as the source of truth
Ntm by the numbers
- 23 all-time installs (skills.sh)
- Ranked #1,263 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
ntm capabilities & compatibility
- Capabilities
- agent orchestration · swarm coordination · workflow automation
- Use cases
- orchestration
- Pricing
- Free
What ntm says it does
NTM is a control plane: robot API, attention feed, work graph, locks/mail, pipelines, safety, approvals, serve API, and durability all have explicit contracts.
The most common NTM mistake is treating it like a tmux macro runner.
If the snapshot or attention feed disagrees with what the command said happened, **trust the snapshot**
npx skills add https://github.com/boshu2/agentops --skill ntmAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 23 |
|---|---|
| repo stars | ★ 416 |
| Last updated | August 5, 2026 |
| Repository | boshu2/agentops ↗ |
What it does
Orchestrate NTM tmux agent swarms via the robot API using a discover-snapshot-verify operating loop.
Who is it for?
Coordinating multi-pane tmux agent swarms with the NTM robot API and verifying state via snapshots.
Skip if: Treating NTM as a plain tmux macro runner or trusting a command exit code over the robot snapshot.
When should I use this skill?
Spawning or sending panes, reading robot state, triaging work, handling locks and mail, or running NTM pipelines.
What you get
State-changing NTM actions verified in the robot snapshot and attention feed, with locks and pipelines released or handed off.
- Verified NTM state transitions
- Released or handed-off locks and pipelines
By the numbers
- 8-step mandatory loop
- atm is byte-identical to ntm
Files
<!-- TOC: One Rule | Outcome | Cold Start | Mandatory Loop | NTM Action Card | Surface Selection | Pattern Tiers | Anti-Patterns | Pre-Flight Checklist | Output | Operating Notes | Reference Index | Related Skills -->
Scope: this skill is AgentOps operating doctrine for NTM. The binary is self-describing — for command syntax, flags, schemas, and examples usentm --robot-docs=quickstart|commands|examples|exit-codes,ntm --robot-capabilities,ntm --robot-schema=all, orntm --help. Never trust this file (or any notes) over the live contract. For tending loops, marching orders, unstick ladders, and swarm cadence, use the companionvibing-with-ntmskill.
`atm` is the same binary.atm(Bo's fork/alias,~/.local/bin/atm) is byte-identical tontm— same--help, same--robot-*surface, same flags, same exit codes. Everyntm …form documented here and in the references applies verbatim toatm …, and vice-versa. Use them interchangeably; the companion out-of-session substrate skill is literally namedusing-atm. When--robot-capabilitiesmatters, query whichever binary you invoked — they resolve to the same contract.
NTM — Named Tmux Manager
The One Rule: Discover the live NTM contract first, then use the least interactive surface that can prove and execute the action. No--robot-capabilities/--robot-snapshotevidence -> no automation assumption.
The most common NTM mistake is treating it like a tmux macro runner. NTM is a control plane: robot API, attention feed, work graph, locks/mail, pipelines, safety, approvals, serve API, and durability all have explicit contracts. Use the contract.
Outcome — When an NTM Action Has Delivered
A state-changing NTM action is complete only when all of the following hold:
- The intended state transition is visible in `ntm --robot-snapshot` — not just acknowledged by the command's exit code. (NTM commands can succeed at the API layer while panes/work/locks remain unchanged; trust the snapshot, not the return value.)
- The attention feed (
--robot-attention/--robot-tail) shows the expected event(s) — pane output, work-graph movement, lock acquire/release, mail delivery. Absence is evidence of failure. - Adjacent state (git, br/beads, mail, pipelines) reflects the action's downstream effects within one observation window — otherwise the action fired in isolation and likely didn't accomplish its real purpose.
- Locks and pipelines you opened are either released / completed by you, or explicitly handed off via mail with a thread the next operator can claim. Orphaned locks block the swarm.
- For dispatched marching orders: the targeted pane has acknowledged (printed the order, started the work, or replied via mail). A sent-but-not-acknowledged order is not "done."
If the snapshot or attention feed disagrees with what the command said happened, trust the snapshot and re-discover the contract — the local model of NTM is stale.
Cold Start: Which NTM Skill?
| Situation | Start here |
|---|---|
You need NTM doctrine, then exact syntax via --robot-docs / references | This skill |
| You are tending an already-running swarm and deciding whether to nudge, restart, stand down, or dispatch marching orders | /vibing-with-ntm |
| You are running a Brenner-style hypothesis investigation or incident RCA through NTM panes | brennerbot-with-ntm |
| You only need Beads or BV mechanics | /beads-br or /beads-bv |
For any state-changing action, verify the live contract with ntm --robot-capabilities before executing.
Folded triggers (ag-s43tg wave 1): ntm-browser-test-coordination + ntm-review-worker-orchestration route here
- Browser/UI test coordination. Use when coordinating browser or UI tests through NTM panes
with screenshots and handoffs: dispatch the test run as marching orders to a dedicated pane, reserve the surfaces under test via agent-mail, keep screenshot/artifact paths in the pane output, and confirm completion in --robot-snapshot + the attention feed before handing off.
- Review/analysis workers. Use when operating an NTM review or
analysis worker with bounded inputs and evidence-backed output: scope the worker to an explicit input set (files, diff, bead), require artifact-backed findings (paths + line refs, not impressions), and treat a worker that emits conclusions without evidence as not-done — re-dispatch with the bounded-input contract restated.
The Loop (Mandatory)
1. DISCOVER -> ntm --robot-capabilities; ntm --robot-tools; repo AGENTS.md/README.md
2. SNAPSHOT -> ntm --robot-snapshot; inspect sources/degraded_sources, cursor, sessions, panes
3. SELECT -> choose the smallest surface: work/assign/send/wait/pipeline/locks/mail
4. PROVE -> fill the NTM action card: target, contract, safety, ownership, rollback
5. EXECUTE -> prefer --robot-* for automation; avoid human-only TUIs
6. VERIFY -> attention/events/causality/tail plus git/br/mail evidence changed as expected
7. CLEANUP -> release/renew locks, checkpoint/handoff, prune old pipeline state when appropriate
8. REPEAT -> re-snapshot on cursor expiry or after any state-changing actionNTM Action Card
For every state-changing NTM action, be able to answer this before running it:
## NTM action: <command>
- Target session/project: <name/path>; resolved by: `ntm config get projects_base` / `ntm quick` / snapshot
- Live contract checked: `ntm --robot-capabilities` contains <flag>; schema/docs checked if unfamiliar
- Evidence before: cursor=<N>; sources=<fresh/degraded>; panes=<count>; locks=<summary>
- Ownership/safety: Agent Mail reservation or worktree policy is clear; user pane inclusion is intentional
- Blast radius: panes/files/sessions affected; destructive/safety/policy approvals required? <yes/no>
- Verification after: <robot event / tail movement / bead state / git change / pipeline status>
- Recovery: <smart restart / interrupt / checkpoint restore / cancel pipeline / handoff>If you cannot fill the card, do a read-only discovery pass first.
Surface Selection
Score candidate surfaces when several could work:
Score = (ContractFit x Observability x Reversibility) / BlastRadius
ContractFit 1-5: exact robot/schema match beats human help text
Observability 1-5: action emits cursor/event/status/causality evidence
Reversibility 1-5: easy cancel/retry/restore/checkpoint
BlastRadius 1-5: one pane/file is low; whole session/process tree is highPick the highest score. In ties, prefer the surface that produces structured output. Enumerate candidates from ntm --robot-docs=commands, not from memory. Standing preferences:
--robot-*for anything machine-driven;ntm dashboard/ntm palette/ntm vieware human-only TUIs.--robot-format=toon(orNTM_ROBOT_FORMAT=toon) and--robot-verbosity=tersewhen context is tight.- Recovery order: diagnose -> probe / is-working -> smart-restart -> explicit restart. Never kill before a liveness proof.
- Event-driven tending (
--robot-wait/--robot-attention) over fixed sleep/poll loops.
Pattern Tiers
Escalate only with the action card filled; each tier raises the proof bar:
1. Tier 1 — safe read-only (capabilities/schema, snapshot, events/digest/attention, work triage/queue-dry, locks list/check). Always permitted; proof = fresh sources / degraded_sources reviewed, cursor advancing, no conflicting reservation. 2. Tier 2 — reversible control (directed send, interrupt, smart-restart, assign, pipeline cancel/resume). Guard = explicit pane/type scoping, tail/liveness evidence that intervention is warranted, run id and state confirmed. 3. Tier 3 — durable orchestration (pipelines, Agent Mail locks, checkpoint/handoff, serve API, safety/policy/approvals). Guard = dry-run first, lease/thread/run ids captured, auth and exposure understood, exit/recovery path named.
Anti-Patterns (Never Do)
| Bad move | Why it fails | Use instead |
|---|---|---|
Call ntm view from automation | Retiles the human layout and returns nothing useful | --robot-tail, --robot-snapshot, or --robot-dashboard |
Trust old notes over --robot-capabilities | NTM surface changes quickly | Discover first |
Send to --all without naming the user-pane intent | Can hit the operator pane | use type/panes or -s/--skip-first |
| Treat cursor values as portable | Cursors are per-server monotonic | checkpoint/handoff for portability |
| Kill/restart before a liveness proof | Destroys partial work | diagnose -> smart restart -> explicit restart |
| Conflate pipeline status and run | --robot-pipeline=<id> is status | --robot-pipeline-run=<file> |
| Retry degraded mail/CASS forever | Burns the session | record degraded source, use fallback, continue |
| Infer abandoned beads from silence | NTM deliberately does not implement bead_orphaned | explicit status/mail/reservation evidence |
Trust a fresh spawn --cod pane blind (bare shell) | Some builds leave a bare zsh; prompts execute as shell text | verify with --robot-tail; relaunch the CLI, or fall back to codex exec -C <worktree> per lane |
Fire a separate send right after a bare spawn (boot race) | spawn returns before the agent boots to its input box; the first send is silently dropped → pane is never-engaged (CLI alive, 0.0% CPU) | wait for input-ready first: --assign / --init-prompt / --robot-wait=ready; if already dropped, re-dispatch, don't restart (vibing OC-047) |
Pre-Flight Checklist
- [ ] Repo
AGENTS.md/ README read when operating inside a codebase (repo-local rules override this skill). - [ ]
ntm --robot-capabilitieschecked for any unfamiliar flag. - [ ]
ntm --robot-snapshotcaptured andsources/degraded_sourcesreviewed. - [ ] Session/project resolution verified; labels and
projects_basemake sense. - [ ] User pane inclusion/exclusion is explicit.
- [ ] File ownership is clear: Agent Mail reservation, bead assignee, or approved worktree policy.
- [ ] For pipelines: dry-run passed; run id/state file plan known.
- [ ] For recovery: liveness truth stack supports intervention.
- [ ] For destructive/risky actions: safety/policy/approval surfaces checked.
- [ ] Post-action verifier named before execution.
Output
NTM actions produce no skill-owned files. The deliverable is verified state plus evidence:
- Structured robot output (JSON or TOON) on stdout from
--robot-*commands, cited in your report. - The post-action proof named in the action card: snapshot/attention movement, bead/git/mail change, pipeline status.
- When the surrounding arc requires durable evidence, write it to the repo's evidence path (e.g. an
Evidence:file under.agents/or the path the bead names) — not into this skill.
Operating Notes (doctrine-critical facts)
- Project resolution is the #1 cross-tool breakage: session name MUST equal the directory basename under
projects_base(NTM_PROJECTS_BASE), or agent-mail/beads/reservations register under a different key than NTM sees. If tools "see different projects," fix this first. - Coordination default: Agent Mail reservations are the primary primitive;
--worktreesisolation is allowed when repo policy permits. If mail/reservations are degraded, record it and use bead assignee/status as the soft lock — no retry loops. - Cross-machine continuity is checkpoint export/import or handoff bundles — never shipped cursors.
- Safety surfaces are first-class: use
ntm safety/ntm policy/ntm approve(approve takes a token, not a bead id) instead of ad hoc shell habits; obey repo rules that route builds throughrchor similar. - The full distilled trip-wire list (CASS dedup blocking sends,
--label separator, send-vs-spawn flag parsers, attention flag namespacing, PATH precedence for safety wrappers, and more) lives in TROUBLESHOOTING.md.
Reference Index
Keep depth out of this file. The binary's own docs (ntm --robot-docs=...) are the first stop for syntax; load these for operator-handbook detail:
| Topic | Reference |
|---|---|
ntm send deep reference (selectors, templates, CASS dedup, error modes) | SEND.md |
ntm spawn deep reference (counts/variants, labels, worktrees, recipes, stagger) | SPAWN.md |
Work intelligence & assignment (ntm work *, ntm assign, bv integration) | WORK-AND-ASSIGN.md |
Ensemble mode (reasoning modes, presets, --robot-ensemble-*) | ENSEMBLE.md |
| Pipelines (YAML schema, run IDs, resume/cancel, robot flags) | PIPELINES.md |
| Serve API (auth modes, REST route map, OpenAPI, SSE) | SERVE.md |
Safety, policy, approvals (policy.yaml, tokens, what safety install drops) | SAFETY.md |
| Durability stack (checkpoint vs timeline vs handoff vs resume) | DURABILITY.md |
| Integration surfaces (DCG, SLB, CAAM, RCH, mail, cass, quota) | INTEGRATIONS.md |
Environment variables (NTM_*, TOON_*) | ENV-VARS.md |
| Troubleshooting (symptom / root cause / fix, full gotcha entries) | TROUBLESHOOTING.md |
| Self-test / trigger phrases | SELF-TEST.md |
| High-leverage command patterns, output capture, reusable assets | COMMANDS.md |
Attention feed, robot formats, wait conditions, full --robot-* index | ROBOT-MODE.md |
| Human dashboard, palette, keybindings, TUI notes | DASHBOARD.md |
Project resolution, projects_base, config paths, project-local assets | CONFIG.md |
Assets
Drop-in examples live under assets/:
- `pipeline-example.yaml` — a review pipeline with parallel step + retry
- `policy-example.yaml` — opinionated
~/.ntm/policy.yamlstarter - `envrc.example` — recommended
direnv/shell env vars
Related Skills
- `vibing-with-ntm` — the companion operator / orchestration skill: tending loops, marching-orders prompts, autonomous unstick recipes, steady-state cadence. Use it whenever the question is "how do I run the swarm well?" rather than "what does NTM do?"
agent-mailfor inboxes, contact handshakes, and file reservationsbrfor bead state changes and syncingbvfor graph-aware task prioritizationcassfor prior-session retrievalcaamfor account rotation across providers (paired with--robot-switch-account)dcg,slbfor destructive-command and two-person approval policy
# NTM environment — drop into `.envrc` (direnv) or source from shell profile.
# Project resolution — session name must equal directory basename under this dir
export NTM_PROJECTS_BASE="$HOME/Developer"
# Robot mode — TOON is ~60% cheaper than JSON for LLM consumers
export NTM_ROBOT_FORMAT=toon
export NTM_ROBOT_VERBOSITY=default
# CAAM rotation on rate-limit (pairs well with --robot-smart-restart)
export NTM_ACCOUNTS_AUTO_ROTATE=true
export NTM_ROTATION_ENABLED=true
# Auto-inject recovery context on spawn, cap at 4k tokens
export NTM_RECOVERY_AUTO_INJECT=true
export NTM_RECOVERY_MAX_TOKENS=4000
export NTM_RECOVERY_INCLUDE_AGENT_MAIL=true
export NTM_RECOVERY_INCLUDE_BEADS=true
# CASS context injection on spawn — but skip if pane already has big context
export NTM_CASS_CONTEXT_ENABLED=true
export NTM_CASS_MIN_RELEVANCE=0.6
export NTM_CASS_SKIP_IF_CONTEXT_ABOVE=50000
export NTM_CASS_PREFER_SAME_PROJECT=true
# Approval audit trail
export NTM_USER="${USER}"
# Put wrappers ahead of system binaries so `ntm safety` wrappers intercept
case ":$PATH:" in
*":$HOME/.ntm/bin:"*) ;;
*) export PATH="$HOME/.ntm/bin:$PATH" ;;
esac
schema_version: "2.0"
name: cross-agent-pr-review
description: Parallel PR review with Claude + Codex, then Gemini synthesizes
version: "1.0.0"
vars:
target_pr:
description: PR number to review
required: true
type: number
reviewers:
default: ["cc", "cod"]
type: array
settings:
timeout: 30m
on_error: fail
notify_on_error: true
notify_channels: [desktop]
steps:
- id: fetch
name: Fetch PR metadata
agent: claude
pane: 1
prompt: "Fetch and summarize PR ${vars.target_pr} — list changed files, diff size, test status."
wait: completion
timeout: 5m
output_var: fetch_summary
output_parse:
type: json
- id: review-parallel
depends_on: [fetch]
parallel:
- id: review-cc
agent: claude
prompt: "Review PR ${vars.target_pr} focusing on correctness and edge cases. Context: ${steps.fetch.output}"
- id: review-cod
agent: codex
prompt: "Review PR ${vars.target_pr} focusing on architecture and API surface. Context: ${steps.fetch.output}"
on_error: continue
- id: synthesize
depends_on: [review-parallel]
agent: gemini
route: least-loaded
prompt: |
Synthesize a unified review from two perspectives:
Claude: ${steps.review-cc.output}
Codex: ${steps.review-cod.output}
Output: must-fix, should-fix, nits — each with file:line references.
on_error: retry
retry_count: 2
retry_delay: 30s
retry_backoff: exponential
version: 1
automation:
auto_commit: false
auto_push: false
force_release: approval
allowed:
- pattern: '^git status(\s|$)'
reason: read-only git status
- pattern: '^git diff(\s|$)'
reason: read-only git diff
- pattern: '^git log(\s|$)'
reason: read-only git log
- pattern: '^git branch(\s|$)'
reason: read-only branch listing
blocked:
- pattern: '^git reset\s+--hard'
reason: destroys local changes
- pattern: '^git clean\s+-f'
reason: deletes untracked files
- pattern: '^git push.*--force'
reason: rewrites remote history
- pattern: '^rm\s+-rf\s+(/|~|\*|\.|\.\.)'
reason: mass deletion of protected paths
- pattern: '^git branch\s+-D'
reason: force-delete branch
- pattern: '^git stash\s+(drop|clear)'
reason: destroys stashed work
approval_required:
- pattern: '^git rebase\s+(-i|--interactive)'
reason: interactive rebase rewrites history
slb: false
- pattern: '^git commit\s+--amend'
reason: rewrites last commit
- pattern: '^rm\s+-rf\s+'
reason: recursive delete
slb: true
- pattern: '^git push(?!.*--dry-run)'
reason: publishes to remote
NTM Command Patterns
Use this file when the main ntm skill body is not enough and you need the denser operator command patterns that make NTM powerful in practice.
Contents
- Session Lifecycle — quick, spawn, scale, rebalance, adopt
- Agent Count Heuristics
- High-Leverage Send Patterns — targeting, file-backed, smart routing, distribute
- Monitoring and Output — capture, activity, health, diff
- Human-Only Surfaces — dashboard, palette, bind
- Work Intelligence — triage, alerts, impact, assign
- Coordination, Recovery, and Durable State — mail, locks, checkpoint, timeline, resume, handoff
- Controller Agents
- Reusable Assets — recipes, workflows, templates
---
Session Lifecycle
ntm quick myproject --template=go # template = go | python | node | rust
ntm quick myproject --label frontend
ntm spawn myproject --cc=3 --cod=2 --gmi=1
ntm spawn myproject --label frontend --cc=3
ntm spawn myproject --label backend --cc=2 --worktrees
ntm spawn myproject --no-user --cc=5 --cod=5
ntm spawn myproject --stagger-mode=smart # smart | fixed | none
ntm add myproject --cc=2
ntm add myproject --label frontend --cc=1
ntm list
ntm status myproject
ntm attach myproject
ntm zoom myproject 1
ntm kill myproject
ntm kill --project myproject
# Adjust a running swarm without re-spawning
ntm scale myproject --cc=4
ntm rebalance myproject
ntm respawn myproject # revive dead panes in place
ntm swarm plan # dry-run spawn
ntm swarm status
ntm swarm stop <pattern>
# Adopt an existing external tmux session into ntm
ntm adopt <session>ntm viewis a human-operator command that retiles the tmux layout. Do not call it from agent code — use--robot-tail,--robot-snapshot, or--robot-inspect-paneinstead.
Agent Count Heuristics
--cc=3 --cod=2 --gmi=1: good default mixed swarm--cc=5: architecture-heavy, lower coordination load--cc=2 --cod=3: straightforward implementation volume--cc=5 --cod=5: larger swarm only when the operator loop is already healthy
High-Leverage Send Patterns
# Basic targeting
ntm send myproject --cc "Review the API design"
ntm send myproject --cod --gmi "Run tests and summarize failures"
ntm send myproject --all "Checkpoint and summarize current state"
ntm send myproject --pane=2 "You own the auth migration."
ntm send myproject --panes=2,3 "Pair on the broken build."
# Broadcast across labeled sessions for one base project
ntm send --project myproject "Sync to main and report blockers."
# File-backed prompts, stdin, and reusable wrappers
ntm send myproject --file prompts/review.md
git diff | ntm send myproject --all --prefix "Review these changes:"
ntm send myproject --base-prompt-file ./common-instructions.txt --file ./task.txt
# File context and templates
ntm send myproject -c internal/auth/service.go "Refactor this safely"
ntm send myproject -c a.go -c b.go "Compare these implementations"
ntm send myproject -t fix --var issue="nil pointer" --file internal/auth/service.go
# Smart routing and automated distribution
ntm send myproject --smart "Take the next auth follow-up"
ntm send myproject --smart --route=affinity "Continue the migration work"
ntm send myproject --distribute --dist-strategy=dependency
ntm send myproject --distribute --dist-auto --dist-strategy=balanced
# Batch / randomized sends
ntm send myproject --batch prompts.txt --delay=5s
ntm send myproject --batch prompts.txt --broadcast
ntm send myproject --all --randomizeMonitoring and Output
# Output capture
ntm copy myproject:1
ntm copy myproject --all
ntm copy myproject --cc
ntm copy myproject --code
ntm save myproject
# Activity and stream monitoring
ntm activity myproject --watch
ntm health myproject
ntm watch myproject --cc
ntm logs myproject --panes=1,2
# Compare / inspect
ntm extract myproject --lines=200
ntm diff myproject cc_1 cod_1
ntm grep "timeout" myproject -C 3Human-Only Surfaces
These are excellent for operators, but not for agents driving automation:
ntm dashboard myproject
ntm palette myproject
ntm bind
ntm tutorialWork Intelligence
ntm work triage
ntm work triage --by-label
ntm work triage --by-track
ntm work triage --format=markdown --compact
ntm work alerts
ntm work search "JWT authentication"
ntm work impact internal/api/auth.go
ntm work next
ntm work history
ntm work forecast br-123
ntm work graph
ntm work label-health
ntm work label-flowUse ntm assign when you want NTM to help push work onto panes instead of just observing the graph:
ntm assign myproject --auto --strategy=dependency
ntm assign myproject --beads=br-123,br-124 --agent=codexCoordination, Recovery, and Durable State
ntm mail send myproject --all "Report blockers and current file focus."
ntm mail inbox myproject # or: ntm mail inbox myproject --json
ntm locks list myproject --all-agents
ntm locks renew myproject --extend 30 # minutes
ntm locks force-release myproject 42 --note "agent inactive"
ntm coordinator status myproject # alias: ntm coord status
ntm coordinator digest myproject
ntm coordinator conflicts myproject
ntm coordinator enable auto-assign # background automation
ntm coordinator enable digest --interval=30m
ntm checkpoint save myproject -m "before risky refactor"
ntm checkpoint list myproject
ntm checkpoint restore myproject # optional <id> positional
ntm checkpoint export myproject <id> # portable archive
ntm checkpoint import <archive>
ntm checkpoint verify myproject
ntm checkpoint show myproject <id>
ntm timeline list
ntm timeline show <session-id>
ntm timeline stats
ntm history search "authentication error"
ntm audit show myproject
ntm audit search "<pattern>"
# changes vs conflicts are TWO separate top-level commands (not a nested form):
ntm changes myproject # recent attributable file changes
ntm conflicts myproject --since 6h --limit 10 # files touched by multiple agents
ntm resume myproject
# Cross-session handoff bundles
ntm handoff create myproject
ntm handoff list
ntm handoff show <path>
ntm handoff ledgerController Agents
ntm controller myproject # coord agent in pane 1 (default cc)
ntm controller myproject --agent-type=cod # cc|cod|gmi|cursor|windsurf|ws|aider|ollama
ntm controller myproject --prompt=ctrl.txt # template vars: {{.Session}} {{.AgentList}} {{.ProjectDir}}
ntm controller myproject --no-prompt # launch agent but send no initial promptWorktree-specific commands when repo policy allows them:
ntm worktrees list
ntm worktrees merge claude_1
ntm worktrees clean --session myprojectReusable Assets
ntm recipes list
ntm recipes show full-stack
ntm workflows list
ntm workflows show red-green
ntm template list
ntm template show fix-bug
ntm session-templates list
ntm session-templates show refactorUse these when you want repeatable swarm composition rather than bespoke commands every time.
NTM Configuration and Project Resolution
Use this file when spawn, quick, templates, or project-local overrides behave in surprising ways.
Project Resolution
ntm spawn <name> expects NTM to resolve <name> to a project directory.
ntm config get projects_base
ntm quick myproject --template=goIf the repo is elsewhere, make it resolvable from projects_base or use the repo's preferred layout.
Labels extend the session name as:
project--frontend
project--backendThat means:
ntm quick myproject --label frontend
ntm spawn myproject --label frontend --cc=2
ntm add myproject --label frontend --cc=1Useful Config Commands
ntm config init
ntm config show
ntm config path # print resolved config file path
ntm config diff # show deltas from defaults
ntm config get projects_base
ntm config set projects-base <path> # convenience shortcut (note: dashes, not underscores)
ntm config validate
ntm config edit
ntm config reset --confirm # destructive; requires confirmation
ntm config project init [--force] # seed a .ntm/ tree in the current projectUser-Level Assets
Common user-level locations:
~/.config/ntm/config.toml~/.config/ntm/recipes.toml~/.config/ntm/workflows/~/.config/ntm/personas.toml~/.config/ntm/templates/~/.ntm/policy.yaml
Project-Level Assets
Project-local assets usually live under .ntm/ and override user defaults where appropriate.
Common examples:
.ntm/workflows/.ntm/pipelines/.ntm/templates/.ntm/personas.toml.ntm/recipes.toml.ntm/checkpoints/
These matter because session templates, prompt templates, workflows, pipelines, and persona definitions are often project-specific rather than globally shared.
Human Dashboard and TUI Surfaces
These surfaces are for humans, not agents trying to automate NTM.
Primary Commands
ntm dashboard myproject
ntm palette myproject
ntm bind
ntm view myprojectdashboard: live operator overviewpalette: fuzzy searchable command launcherbind: install convenience bindings such as the palette keybindingview: quick way to tile and attach
Command Palette
ntm palette myprojectUseful keys:
| Key | Action |
|---|---|
↑/↓ or j/k | Navigate |
1-9 | Quick select |
Enter | Execute |
? | Help |
Dashboard Notes
The dashboard is useful when:
- you are tending a swarm manually
- you want pane-level visual status
- you need a fast operator overview of sessions, activity, history, and focus
It is the wrong tool when:
- another agent or script needs deterministic state
- you need replayable automation
- you are trying to integrate with external systems
In those cases, use --robot-* or ntm serve.
Useful Internal Notes for NTM Contributors
If you are working on NTM itself, these dashboard architecture notes are still useful:
| File | Purpose |
|---|---|
model.go | Model structs, types, constants |
lifecycle.go | Init, cleanup, subscriptions |
keymap.go | Keymap and help bindings |
messages.go | Messages and refresh intervals |
popup.go | Popup / overlay rendering |
run.go | Entry points |
dashboard.go | Core update/view path |
focus.go | Focus management |
The TUI stack also leans heavily on Bubble Tea and the Charmbracelet ecosystem. That is useful context when changing dashboard behavior or trying to trace a rendering issue.
Durability Stack — Checkpoint / Timeline / Handoff / Resume / Rollback
Contents
- Primitive comparison — which to use
- `ntm checkpoint` — snapshot pane/git/bv state
- What `save` captures
- ID grammar —
last,~1,~N, prefix, full - Restore flags
- Export / import archive
- Cross-machine handoff example
- `ntm rollback` — apply snapshot's git + layout
- `ntm timeline` — session event log
- `ntm handoff` — human-readable YAML narrative
- Handoff file content
- Create modes
- Ledger — rolling continuity log
- `ntm resume` — re-attach with handoff injection
- Decision matrix — goal → primitive
- Gotchas
---
NTM has five related but distinct primitives for session durability. Pick the right one.
| Primitive | Captures | When to use |
|---|---|---|
checkpoint | Pane scrollback + layout + git state + bv summary | Before a risky change, or for rollback |
rollback | Applies a checkpoint's git state + pane layout | Restore code + panes from a checkpoint |
timeline | Session event log (state transitions) | Post-session audit / productivity analysis |
handoff | Human-readable YAML: goal / now / blockers / next | Context transfer to another operator or fresh agent |
resume | Re-attaches session with handoff context injection | Pick up where an operator/agent left off |
Sources: checkpoint.go, rollback.go, timeline.go, handoff.go, resume.go under /dp/ntm/internal/cli/.
ntm checkpoint
Subcommands (checkpoint.go:94-101):
| Subcommand | Purpose |
|---|---|
save <session> [-m "msg"] | Take a snapshot |
list [session] | List snapshots |
show <session> <id> | Full snapshot contents |
restore <session> [id] | Restore panes + git state |
delete <session> <id> | Delete |
verify <session> | Integrity check |
export <session> <id> | Portable archive |
import <archive> | Import a portable archive |
What save captures
- Pane configs: titles, agent types, commands (
checkpoint.go:116-120). - Pane scrollback — default 1000 lines, configurable via
--scrollback=N(checkpoint.go:200). - Git state: branch, commit hash,
IsDirty,StagedCount,UnstagedCount, optional patch. Disable with--no-git(checkpoint.go:201). cp.Assignments(current bv/ntm assignments) andcp.BVSummary.
Save flags
| Flag | Default |
|---|---|
-m/--message <str> | "" |
--scrollback N | 1000 lines per pane |
--no-git | false |
ID grammar
save emits YYYYMMDD-HHMMSS. restore accepts (checkpoint.go:34-38):
- Full ID:
20261230-123456 - Prefix:
20261230 - Aliases:
last,~1,~N(N-th most recent)
Restore flags (checkpoint.go:806-812)
--inject-contextre-injects scrollback into restored panes.--scrollback Nlimits inject size (0 = all).-f/--forceskip confirmation.-a/--attachattach after restoring.--skip-git-checkskipIsDirtyvalidation.--dry-runpreview.--directory <path>override target directory.
Export / import archive
exportwrites.tar.gz(default) or.zip(--format=tar.gz|zip).--output <path>destination.--redact-secretsstrips sensitive material (checkpoint.go:1099).- Manifest includes
exported_at. import <archive>accepts--session=<new>,--target-dir=<path>,--skip-verify.
Cross-machine handoff example
# Source machine
ntm checkpoint save myproject -m "pre-migration snapshot"
ntm checkpoint export myproject last \
--output /tmp/myproject-snap.tar.gz --redact-secrets
scp /tmp/myproject-snap.tar.gz target:/tmp/
# Target machine
ntm checkpoint import /tmp/myproject-snap.tar.gz \
--session=myproject-work --target-dir=/home/alice/work/myproject
ntm checkpoint restore myproject-work last --inject-contextntm rollback
ntm rollback <session> [checkpoint-id] (rollback.go:19). Applies a prior snapshot — stashes changes, applies the stored patch, walks HEAD back to the captured commit when present.
Flags (rollback.go:118-122):
--dry-run— preview.--no-stash— don't stash before apply (risky).--no-git— pane-only rollback; leave git alone.--last— alias forlastcheckpoint ref.--force— skip confirmation.
ID grammar matches checkpoint: last, ~1, ~N, prefix, full.
ntm timeline
Subcommands (timeline.go:57-688):
list— all saved timelines.show <session-id>— full state transition log.delete <session-id>.cleanup— retention-based prune.export <session-id>— exportable event log.stats— storage stats.
Timelines are session-scoped audit streams: when each agent went idle/working/error, when messages fired, when beads were claimed. Useful for post-session productivity analysis or incident reconstruction. Distinct from checkpoints (state snapshots) and handoffs (human narrative).
ntm handoff
Human-readable YAML context transfer. Stored under .ntm/handoffs/<session>/<date>_<desc>.yaml.
Subcommands (handoff.go:40-43): create, list, show, ledger.
Handoff file content (handoff.go:26-32)
goal: "Ship the auth refactor"
now: "PR #42 open; failing integration test on Windows"
status: in_progress
outcome: ""
decisions:
- "Chose JWT over session cookies"
- "Rejected refresh-token rotation for v1"
blockers:
- "Flaky test on CI, unrelated"
next:
- "Fix Windows test"
- "Get final review"
files_changed:
- internal/auth/*
git:
branch: feat/auth
commit: abc123
dirty: falseCreate modes (handoff.go:85-94)
--goal "..."+--now "..."→ explicit inline.--auto→ auto-generate from recent agent output.--from-file <yaml>→ load pre-written.- Interactive wizard if no flags.
--include-gitdefault true.--format yaml|json|markdown.-o/--output <path>(or-for stdout).
Ledger
.ntm/ledgers/CONTINUITY_{session}.md (handoff.go:156-181) — rolling continuity log combining the latest N handoffs.
ntm resume
Re-attach a session with handoff context. Flags (resume.go:97-104):
| Flag | Purpose |
|---|---|
--from <path> | Specific handoff file |
--spawn | Spawn fresh agents with handoff context (not just attach) |
--inject | Inject context into existing panes |
--dry-run | Preview |
--cc N / --cod N / --gmi N | Agent counts (only with --spawn) |
If --from is omitted:
- With session name →
handoff.NewReader().FindLatest(session)(resume.go:165). - Without session →
FindLatestAny()(resume.go:157).
Decision matrix
| Goal | Use |
|---|---|
| Snapshot before risky refactor | checkpoint save |
| Revert code + panes to an earlier state | checkpoint restore or rollback |
| Post-mortem: when did agents stop progressing? | timeline show |
| Transfer state to another operator | handoff create + resume --from |
| Move a session to a new machine | checkpoint export + checkpoint import |
Resume after ntm kill | resume --spawn with prior handoff |
| Audit log of what happened during a session | timeline export |
Gotchas
timelineis session-scoped, not cross-project. Multiple sessions = multiple timelines.checkpoint restoredefault confirms; script flows need-f/--force.rollback --no-stashwill lose uncommitted changes — pair it with manual stash.handoff --autoinference depends on recent pane output quality. Review before shipping.resume --spawn --cc=Nignores the prior pane count; pass it explicitly if you want to match.
Ensemble Mode Reference
Multi-agent reasoning swarm: each pane runs a distinct reasoning mode against the same question, outputs are synthesized. Catalog is large (80 modes, 9 presets, 10 synthesis strategies) — this is the lookup.
Availability gate: live NTM exposes ensemble catalog/status/suggest robot surfaces in normal builds, but ensemble spawning is experimental. If --robot-ensemble-spawn returns NOT_IMPLEMENTED, rebuild NTM with -tags ensemble_experimental or choose a normal ntm spawn / pipeline flow instead. Do not treat an experimental-spawn refusal as a broken swarm.
Contents
- What is Ensemble Mode
- Subcommand list
- Reasoning modes catalog — 80 modes across 12 categories
- A: Formal & Mathematical
- B: Ampliative
- C: Uncertainty
- D: Vagueness
- E: Change & Defaults
- F: Causal & Dynamic
- G: Practical
- H: Strategic & Social
- I: Dialectical & Interpretive
- J: Modal / Temporal / Spatial / Normative
- K: Domain-Specific
- L: Meta & Reflective
- Presets catalog — 9 presets
- Synthesis strategies — 10 strategies
- Robot-mode equivalents
- Example invocations
- Gotchas
---
What is Ensemble Mode
Ensemble mode spawns multiple agents in parallel in one tmux session, each reasoning about the same question using a different reasoning mode. The outputs are then synthesized into a unified analysis. Benefits:
- Mitigates single-agent blind spots
- Surfaces hidden assumptions
- Provides confidence scoring via mode agreement/disagreement
- Produces more robust and creative solutions
Workflow:
1. Load or define a preset (bundle of modes + synthesis strategy + budgets). 2. Spawn agents in a tmux session, one pane per mode. 3. Inject prompts guiding each agent toward its assigned mode. 4. Collect outputs as agents complete. 5. Synthesize using the specified strategy (e.g., adversarial, consensus, creative). 6. Merge findings and emit a final report.
Source: /dp/ntm/internal/cli/ensemble.go:96-164 (newEnsembleCmd).
Subcommand list
ntm ensemble [preset-name] "<question>"
Shorthand — spawn an ensemble with a preset and question.
ntm ensemble project-diagnosis "What are the main security issues in this codebase?"Source: /dp/ntm/internal/cli/ensemble.go:102-141.
ntm ensemble spawn <session>
Explicit create. Flags:
| Flag | Purpose |
|---|---|
--preset=<name> | Use preset (mutually exclusive with --modes) |
--modes=<id1>,<id2>,... | Explicit mode IDs |
--question="..." | Required |
--allow-advanced | Allow advanced/experimental tier modes |
--agent-mix=cc=3,cod=2,gmi=1 | Agent distribution |
| `--assignment=round-robin | affinity |
--synthesis=<strategy> | Synthesis strategy override |
--budget-total=<n> / --budget-per-agent=<n> | Token budget caps |
--no-cache | Skip context pack cache |
--no-inject | Create session without injecting prompts |
--project=<dir> | Project directory (default: cwd) |
--dry-run [--show-preambles] | Preview spawn plan |
Source: /dp/ntm/internal/cli/ensemble_spawn.go:61-84.
ntm ensemble presets (alias list)
List presets. Flags: --format=table|json|yaml, --verbose, --imported, --tag=<tag>. Source: /dp/ntm/internal/cli/ensemble_presets.go:105-150.
ntm ensemble suggest "<question>"
Recommend the best preset for a question.
ntm ensemble suggest "What features should we add next?" --id-only
# → idea-forgeSource: /dp/ntm/internal/cli/ensemble_suggest.go:33-66.
ntm ensemble status [session]
Show current state, assignments, synthesis readiness. Flags: --format=table|json|yaml, --show-contributions. Source: /dp/ntm/internal/cli/ensemble.go:171-208.
ntm ensemble stop [session]
Stop all agents, save partial state. Flags: --force, --no-collect, --quiet, --yes. Source: /dp/ntm/internal/cli/ensemble.go:230-282.
ntm ensemble synthesize [session]
Trigger synthesis of completed outputs. Flags:
| Flag | Purpose |
|---|---|
--strategy=<name> | Override synthesis strategy |
| `--format=markdown | json |
--output=<file> | Write to file |
--stream [--resume --run-id=<id>] | Incremental streaming + resume |
--force | Synthesize even if agents incomplete |
--explain / --verbose | Include reasoning detail |
--use-cache / --no-cache | Cache control |
Source: /dp/ntm/internal/cli/ensemble.go:885-950.
Additional subcommands
export <preset>— Export preset to TOML.import <file-or-url>— Import preset from TOML.estimate [session]— Token budget estimate.compare <session>— Compare outputs across modes.cache— Manage context pack cache.export-findings [session]— Export findings file.provenance [session]— Evidence chain for findings.resume [session]— Resume paused ensemble.rerun-mode [session] <mode>— Rerun a single mode.clean-checkpoints [session]— Prune checkpoint files.
Reasoning modes catalog
80 modes across 12 categories. Each mode has: id, category code (A1–L6), tier (Core / Advanced / Experimental), outputs, best-for, failure-modes, differentiator. Source: /dp/ntm/internal/ensemble/modes.go:12-1100 (EmbeddedModes).
Category A: Formal & Mathematical Reasoning (A1-A8)
| Code | ID | Name | Tier |
|---|---|---|---|
| A1 | deductive | Deductive Inference | Core |
| A2 | mathematical-proof | Mathematical Proof | Core |
| A3 | formal-verification | Formal Verification | Core |
| A4 | equational | Equational Reasoning | Advanced |
| A5 | model-theoretic | Model-Theoretic Reasoning | Advanced |
| A6 | constraint-sat | Constraint Satisfaction | Advanced |
| A7 | type-theoretic | Type-Theoretic Reasoning | Core |
| A8 | edge-case | Edge Case Reasoning | Core |
Category B: Ampliative Reasoning (B1-B11)
| Code | ID | Name | Tier |
|---|---|---|---|
| B1 | inductive | Inductive Generalization | Core |
| B2 | statistical | Statistical Reasoning | Advanced |
| B3 | bayesian | Bayesian Reasoning | Advanced |
| B4 | likelihood | Likelihood Reasoning | Advanced |
| B5 | option-generation | Option Generation (abductive) | Core |
| B6 | analogical | Analogical Transfer | Core |
| B7 | case-based | Case-Based Reasoning | Advanced |
| B8 | conceptual-blending | Conceptual Blending | Core |
| B9 | simplicity | Simplicity / Occam | Advanced |
| B10 | reference-class | Reference-Class Reasoning | Advanced |
| B11 | fermi | Fermi Estimation | Advanced |
Category C: Reasoning Under Uncertainty (C1-C5)
| Code | ID | Name | Tier |
|---|---|---|---|
| C1 | probabilistic-logic | Probabilistic Logic | Advanced |
| C2 | imprecise-probability | Imprecise Probability | Advanced |
| C3 | evidential | Evidential (Dempster-Shafer) | Advanced |
| C4 | maximum-entropy | Maximum-Entropy | Advanced |
| C5 | qualitative-probability | Qualitative Probability | Advanced |
Category D: Reasoning Under Vagueness (D1-D5)
| Code | ID | Name | Tier |
|---|---|---|---|
| D1 | fuzzy | Fuzzy Reasoning | Advanced |
| D2 | ambiguity-detection | Ambiguity Detection | Core |
| D3 | rough-set | Rough Set Reasoning | Advanced |
| D4 | prototype-reasoning | Prototype Reasoning | Core |
| D5 | qualitative | Qualitative Reasoning | Advanced |
Category E: Reasoning with Change & Defaults (E1-E7)
| Code | ID | Name | Tier |
|---|---|---|---|
| E1 | non-monotonic | Non-Monotonic | Advanced |
| E2 | default-typicality | Default Reasoning | Advanced |
| E3 | defeasible | Defeasible Reasoning | Advanced |
| E4 | belief-revision | Belief Revision (AGM) | Advanced |
| E5 | paraconsistent | Paraconsistent Reasoning | Advanced |
| E6 | argument-mapping | Argument Mapping | Core |
| E7 | assurance-case | Assurance Case | Advanced |
Category F: Causal & Dynamic Reasoning (F1-F7)
| Code | ID | Name | Tier |
|---|---|---|---|
| F1 | causal-inference | Causal Inference | Advanced |
| F2 | dependency-mapping | Dependency Mapping | Core |
| F3 | counterfactual | Counterfactual | Advanced |
| F4 | failure-mode | Failure Mode Analysis | Core |
| F5 | root-cause | Root Cause Analysis | Core |
| F6 | second-order-effects | Second-Order Effects | Core |
| F7 | systems-thinking | Systems Thinking | Core |
Category G: Practical Reasoning (G1-G11)
| Code | ID | Name | Tier |
|---|---|---|---|
| G1 | means-end | Means-End | Advanced |
| G2 | decision-under-uncertainty | Decision Under Uncertainty | Core |
| G3 | prioritization | Prioritization | Core |
| G4 | strategic-planning | Strategic Planning | Core |
| G5 | resource-allocation | Resource Allocation | Core |
| G6 | worst-case | Worst-Case Analysis | Core |
| G7 | minimax-regret | Minimax Regret | Advanced |
| G8 | satisficing | Satisficing | Advanced |
| G9 | value-of-information | Value-of-Information | Advanced |
| G10 | heuristic | Heuristic Reasoning | Advanced |
| G11 | search-based | Search-Based Reasoning | Advanced |
Category H: Strategic & Social Reasoning (H1-H4)
| Code | ID | Name | Tier |
|---|---|---|---|
| H1 | game-theoretic | Game-Theoretic | Advanced |
| H2 | perspective-taking | Perspective Taking | Core |
| H3 | negotiation | Negotiation | Advanced |
| H4 | mechanism-design | Mechanism Design | Advanced |
Category I: Dialectical & Interpretive Reasoning (I1-I5)
| Code | ID | Name | Tier |
|---|---|---|---|
| I1 | dialectical | Dialectical | Advanced |
| I2 | rhetorical | Rhetorical | Advanced |
| I3 | hermeneutic | Hermeneutic | Advanced |
| I4 | narrative | Narrative | Advanced |
| I5 | sensemaking | Sensemaking | Advanced |
Category J: Modal, Temporal, Spatial, Normative (J1-J4)
| Code | ID | Name | Tier |
|---|---|---|---|
| J1 | modal | Modal Reasoning | Advanced |
| J2 | deontic | Deontic Reasoning | Advanced |
| J3 | temporal | Temporal Reasoning | Advanced |
| J4 | spatial | Spatial Reasoning | Advanced |
Category K: Domain-Specific Reasoning (K1-K7)
| Code | ID | Name | Tier |
|---|---|---|---|
| K1 | scientific | Scientific Reasoning | Advanced |
| K2 | test-plan | Test Plan Mode | Core |
| K3 | engineering-design | Engineering Design | Core |
| K4 | compliance | Compliance Lens | Core |
| K5 | moral-ethical | Moral-Ethical | Advanced |
| K6 | historical-investigative | Historical-Investigative | Advanced |
| K7 | clinical-operational | Clinical-Operational | Advanced |
Category L: Meta-Level & Reflective (L1-L6)
| Code | ID | Name | Tier |
|---|---|---|---|
| L1 | meta-cognitive | Meta-Cognitive Monitoring | Core |
| L2 | calibration | Calibration Reasoning | Advanced |
| L3 | reflective-equilibrium | Reflective Equilibrium | Advanced |
| L4 | transcendental | Transcendental Reasoning | Advanced |
| L5 | adversarial-review | Adversarial Review | Core |
| L6 | debiasing | Debiasing Reasoning | Advanced |
Presets catalog
9 embedded presets. Source: /dp/ntm/internal/ensemble/ensembles.go:7-228 (EmbeddedEnsembles).
| Name | Modes | Synthesis | Budget | Advanced? | Best for |
|---|---|---|---|---|---|
| project-diagnosis | systems-thinking, worst-case, dependency-mapping, failure-mode, perspective-taking | adversarial | 30k | No | Holistic health check |
| idea-forge | conceptual-blending, analogical, option-generation, second-order-effects, prototype-reasoning | creative | 30k | No | Feature brainstorming, innovation |
| spec-critique | deductive, ambiguity-detection, edge-case, test-plan, perspective-taking | consensus | 25k | No | Requirements review, API contracts |
| safety-risk | worst-case, adversarial-review, compliance, failure-mode, root-cause | adversarial | 30k | No | Security audit, threat modeling |
| architecture-review | argument-mapping, root-cause, systems-thinking, perspective-taking, strategic-planning | deliberative | 30k | No | Design review |
| tech-debt-triage | dependency-mapping, failure-mode, resource-allocation, prioritization | prioritized | 20k | No | Debt prioritization |
| bug-hunt | clinical-operational, inductive, adversarial-review, deductive, causal-inference, type-theoretic | analytical | 28k | Yes | Multi-angle debugging |
| root-cause-analysis | clinical-operational, causal-inference, counterfactual, inductive, debiasing | deliberative | 28k | Yes | Postmortems, incident investigation |
| strategic-planning | strategic-planning, systems-thinking, decision-under-uncertainty, second-order-effects, resource-allocation, prioritization, perspective-taking | deliberative | 32k | No | Roadmap / policy design |
Synthesis strategies
10 strategies. Source: /dp/ntm/internal/ensemble/strategy.go:30-128 (strategyRegistry).
| Strategy | Requires Agent | Synthesizer Mode | Output Focus | Best for |
|---|---|---|---|---|
| manual | No | — | concatenated findings | Simple aggregation, debugging |
| adversarial | Yes | adversarial-review | vulnerabilities, counterarguments | Security, risk, stress-test |
| consensus | Yes | meta-evaluation | agreement areas, confidence-weighted | Multi-perspective validation |
| creative | Yes | conceptual-blending | novel combinations, emergent patterns | Innovation, cross-domain |
| analytical | Yes | systems-thinking | structured comparison, gap analysis | Architecture, comprehensive analysis |
| deliberative | Yes | decision-analysis | tradeoff analysis, weighted recommendations | Decision making, policy |
| prioritized | Yes | meta-evaluation | ranked findings, quality scores | Triage, best-of selection |
| dialectical | Yes | dialectical | thesis/antithesis pairs, resolved tensions | Controversial topics |
| meta-reasoning | Yes | meta-evaluation | reasoning quality, epistemic status | High-stakes decisions |
| voting | No | — | vote tallies, score distributions | Democratic aggregation |
| argumentation | Yes | argumentation | support/attack edges, grounded claims | Debate, legal reasoning |
Deprecated → current mapping (auto-migrated with warning, strategy.go:164-178):
debate→dialecticalweighted→prioritizedsequential→manualbest-of→prioritized
Robot-mode equivalents
All registered in /dp/ntm/internal/cli/root.go:3195-3213.
| Flag | Purpose | Args |
|---|---|---|
--robot-ensemble-modes | List reasoning modes | `--tier=core |
--robot-ensemble-presets | List presets | — |
--robot-ensemble=SESSION | Show ensemble status | SESSION |
--robot-ensemble-spawn=SESSION | Spawn ensemble | --preset, --modes, --question, --allow-advanced, --agents |
--robot-ensemble-suggest=QUESTION | Suggest preset | --suggest-id-only |
--robot-ensemble-stop=SESSION | Stop | --stop-force, --stop-no-collect |
Implementation: /dp/ntm/internal/robot/ensemble_presets.go:44-125, /dp/ntm/internal/robot/ensemble_modes.go:65-185.
Example invocations
1. Security audit
ntm ensemble safety-risk "Identify vulnerabilities in our authentication system"
ntm ensemble status
# wait for status.Done > 0, status.Pending == 0
ntm ensemble synthesize --strategy adversarial --format=json2. Architecture decision with deliberation
ntm ensemble spawn arch-review-2024 \
--preset=architecture-review \
--question="Microservices or monolith?" \
--agent-mix="cc=4,cod=2" \
--budget-total=50000
ntm ensemble status arch-review-2024
ntm ensemble synthesize arch-review-2024 \
--strategy deliberative --explain \
--format=markdown --output=architecture-decision.md3. Dry-run before expensive spawn
ntm ensemble spawn trial-session \
--preset=bug-hunt \
--question="Why is payment processing failing intermittently?" \
--allow-advanced \
--dry-run --show-preambles \
--format=json > dry-run-report.json
jq '.assignments, .budget, .validation' dry-run-report.json
# Looks good — spawn for real
ntm ensemble spawn bug-hunt-session \
--preset=bug-hunt \
--question="Why is payment processing failing intermittently?" \
--allow-advanced4. Robot mode for agent integration
ntm --robot-ensemble-presets | jq '.presets[].name'
ntm --robot-ensemble-suggest="What features should we add?" --suggest-id-only
# → idea-forge
ntm --robot-ensemble-spawn=myproject \
--preset=project-diagnosis \
--question="Main technical issues?" \
--robot-format=json
ntm --robot-ensemble=myproject | jq '.status_counts'
ntm --robot-ensemble-stop=myprojectGotchas
Session state & pane names
- Ensemble creates a new tmux session with unique panes per mode.
- Session must not already exist; use
ntm ensemble spawn <unique-name>. - Pane names follow
<session>:<pane-index>. - If the tmux session dies, partial outputs may be lost unless the context-pack cache
retains them (--no-cache=false is the default).
Source: /dp/ntm/internal/cli/ensemble_spawn.go:215-224.
Advanced modes & --allow-advanced
- 28 core modes always available; 52 advanced/experimental require
--allow-advanced. - Presets
bug-huntandroot-cause-analysisrequire--allow-advancedexplicitly
even if you only touch them through the preset.
- Without the flag, advanced modes are silently filtered out.
Source: /dp/ntm/internal/ensemble/ensembles.go:174-200.
Budget & token limits
--budget-per-agentoverridesMaxTokensPerModefor every mode.--budget-totalcaps absolute across all modes.- Estimates are rough; agents can be force-killed if they exceed budget mid-response.
Source: /dp/ntm/internal/ensemble/budget.go, ensemble_spawn.go:306-311.
Synthesis timing
- Synthesis waits for all agents to complete (or
--forcesynthesizes partial). - Synthesizer agent itself consumes budget tokens.
--stream --resume --run-id=<id>supports resume but checkpoints are **not durable
across CLI invocations**.
Source: /dp/ntm/internal/cli/ensemble.go:910-990.
Assignment strategies
round-robin— assign modes to panes in order.affinity— cluster similar-category modes together.category— one mode per category.explicit— requires--modeswithmode:agent-typespecs.
Source: /dp/ntm/internal/cli/ensemble_spawn.go:239-248.
Contribution scoring
ntm ensemble status --show-contributions reports per-mode contribution scores (overlap, unique insights, citations, rank) after synthesis completes.
Source: /dp/ntm/internal/cli/ensemble.go:657-689.
NTM Environment Variables
Comprehensive list from /dp/ntm/internal/config/config.go plus inherited vars in adjacent files.
Contents
- Config path resolution —
NTM_CONFIG, XDG - Project resolution —
NTM_PROJECTS_BASE - CASS integration — dedup, context injection toggles
- Recovery / session-context injection
- Account / provider rotation — CAAM
- Ollama
- Output format (robot mode) —
NTM_ROBOT_FORMATprecedence - TUI appearance — theme, colors, icons, motion
- Debug / testing —
NTM_DEBUG,NTM_TEST_MODE - Safety hook bridge (from Claude Code)
- User identity —
NTM_USER - TOON binary paths
- Recommended `.envrc` for automation
- Gotchas
---
Config path resolution
| Var | Purpose | Source |
|---|---|---|
NTM_CONFIG | Override config path | config.go:1792 |
XDG_CONFIG_HOME | $XDG_CONFIG_HOME/ntm/config.toml (if set) | config.go:1790-1804 |
HOME | $HOME/.config/ntm/config.toml fallback | |
TMPDIR | $TMPDIR/.config/ntm/config.toml when HOME unavailable |
Final precedence: NTM_CONFIG > XDG_CONFIG_HOME/ntm/ > $HOME/.config/ntm/ > $TMPDIR/.config/ntm/.
Project resolution
| Var | Purpose | Source |
|---|---|---|
NTM_PROJECTS_BASE | Override default projects directory — session name resolves under this | config.go:1810, 2331, 2580 |
Almost always the first env var you should set. See TROUBLESHOOTING.md → Project resolution.
CASS integration
| Var | Purpose | Source |
|---|---|---|
NTM_CASS_ENABLED | Toggle CASS-wide features | config.go:2599 |
NTM_CASS_TIMEOUT | CASS query timeout | config.go:2602 |
NTM_CASS_BINARY | Path to cass binary if non-default | config.go:2608 |
NTM_CASS_CONTEXT_ENABLED | Toggle context injection on spawn | config.go:2612 |
NTM_CASS_MIN_RELEVANCE | Minimum relevance score to inject | config.go:2615 |
NTM_CASS_SKIP_IF_CONTEXT_ABOVE | Skip inject past this context-size | config.go:2620 |
NTM_CASS_PREFER_SAME_PROJECT | Prefer same-project context | config.go:2625 |
Recovery / session-context injection
| Var | Purpose | Source |
|---|---|---|
NTM_RECOVERY_ENABLED | Session-recovery prompt injection | config.go:2643 |
NTM_RECOVERY_INCLUDE_AGENT_MAIL | Include recent agent-mail | config.go:2646 |
NTM_RECOVERY_INCLUDE_CM | Include CASS memory | config.go:2649 |
NTM_RECOVERY_INCLUDE_BEADS | Include recent beads | config.go:2652 |
NTM_RECOVERY_MAX_TOKENS | Cap recovery payload | config.go:2655 |
NTM_RECOVERY_AUTO_INJECT | Auto-inject on spawn | config.go:2660 |
NTM_RECOVERY_STALE_HOURS | Staleness threshold | config.go:2663 |
Account / provider rotation
| Var | Purpose | Source |
|---|---|---|
NTM_ACCOUNTS_AUTO_ROTATE | CAAM auto-rotate on rate-limit | config.go:2630 |
NTM_ROTATION_ENABLED | Master toggle for rotation | config.go:2633 |
NTM_GEMINI_AUTO_PRO | Auto-select Gemini Pro when available | config.go:2638 |
Ollama
| Var | Purpose | Source |
|---|---|---|
OLLAMA_HOST / NTM_OLLAMA_HOST | Ollama endpoint | spawn.go:2681-2684, adapter.go:141 |
Output format (robot mode)
| Var | Purpose | Source |
|---|---|---|
NTM_ROBOT_FORMAT | Primary override: json / toon / auto | root.go:4853-4859 |
NTM_OUTPUT_FORMAT | Secondary fallback | root.go:4853-4859 |
TOON_DEFAULT_FORMAT | Tertiary fallback (shared with TOON tool) | root.go:4853-4859 |
NTM_ROBOT_VERBOSITY | terse / default / debug | root.go:4914 |
Precedence: --robot-format flag > NTM_ROBOT_FORMAT > NTM_OUTPUT_FORMAT > TOON_DEFAULT_FORMAT > built-in default.
TUI appearance
| Var | Purpose | Source |
|---|---|---|
NTM_THEME | TUI theme name | theme.go:349, root.go:133 |
NTM_NO_COLOR | Disable colors | theme.go:309 |
NTM_USE_ICONS / NERD_FONTS / NTM_ICONS | Icon mode | icons.go:326-413 |
NTM_REDUCE_MOTION | Reduce dashboard animations | dashboard/env.go:18 |
NTM_DASHBOARD_REFRESH | Dashboard refresh interval | dashboard/env.go:37 |
NTM_POPUP | Force popup mode | dashboard.go:113 |
Debug / testing
| Var | Purpose | Source |
|---|---|---|
NTM_DEBUG / NTM_TUI_DEBUG | Debug logging | dashboard.go:109, focus.go:328 |
NTM_TEST_MODE / NTM_E2E | Test-mode behavior (skip side effects) | audit/logger.go:182, spawn.go:104 |
NTM_DISABLE_INTERNAL_MONITOR | Disable inline monitor loop | spawn.go:579 |
NTM_SKIP_BV | Skip BV priority scoring | priority.go:21 |
Safety hook bridge (from Claude Code)
Current NTM safety hooks read the Claude Code PreToolUse payload as JSON on stdin (tool_name, tool_input.command). These env vars are retained as legacy fallback and for blocked-command audit context:
| Var | Purpose | Source |
|---|---|---|
CLAUDE_TOOL_NAME | Legacy fallback for tool name when stdin JSON is absent | safety.go:837 |
CLAUDE_TOOL_INPUT_command | Legacy fallback for command when stdin JSON is absent | safety.go:840 |
CLAUDE_AGENT_TYPE | Agent type recorded in blocked-command logs | safety.go:858 |
NTM_SESSION | Session recorded in blocked-command logs | safety.go:857 |
User identity
| Var | Purpose | Source |
|---|---|---|
NTM_USER | Current approver id (recorded in approved_by) | approve.go:324 |
USER | Fallback for approver id | approve.go:324 |
TOON binary paths
| Var | Purpose | Source |
|---|---|---|
TOON_BIN | Path to toon binary | toon_test_helpers_test.go:18-19 |
TOON_TRU_BIN | Path to toon-tru binary | toon_test_helpers_test.go:18-19 |
Recommended .envrc for automation
# Project resolution
export NTM_PROJECTS_BASE="$HOME/Developer"
# Robot mode — TOON is significantly cheaper than JSON for LLMs
export NTM_ROBOT_FORMAT=toon
export NTM_ROBOT_VERBOSITY=default
# CAAM rotation on (pairs well with --robot-smart-restart)
export NTM_ACCOUNTS_AUTO_ROTATE=true
export NTM_ROTATION_ENABLED=true
# Recovery injection settings — conservative token cap
export NTM_RECOVERY_AUTO_INJECT=true
export NTM_RECOVERY_MAX_TOKENS=4000
# User identity for approval audit trail
export NTM_USER="$USER"Gotchas
NTM_PROJECTS_BASEis evaluated at NTM startup. Changing it mid-session does not
re-register existing panes — kill + respawn.
- Three env vars fallback for
--robot-format— precedence matters. If output
unexpectedly comes out as text, the shell may have TOON_DEFAULT_FORMAT unset and no upstream override. Set NTM_ROBOT_FORMAT explicitly.
NTM_CASS_ENABLED=falsedisables BOTH dedup-check-on-send and context-injection.
If you want only to disable dedup, prefer --no-cass-check per-call.
NTM Integration Surfaces — External Tools via --robot-*
NTM exposes one-shot adapters to sibling agent-fleet tools so an agent-mode operator can query or mutate adjacent systems without spawning sub-shells. All flags are registered in /dp/ntm/internal/cli/root.go.
Contents
- DCG — Destructive Command Guard
- SLB — Simultaneous Launch Button
- CAAM — AI coding CLI account manager
- Quota (caut)
- RCH — Remote compilation/build host
- RANO — Agent network observer
- RU — Multi-repo sync
- GIIL — Image link downloader
- Agent Mail
- CASS — Cross Agent Session Search
- Context injection
- Environment / setup probes
- JFP, MS, XF (content surfaces)
- Composition notes
- One-line quick index
---
DCG — Destructive Command Guard
| Flag | Purpose | Source |
|---|---|---|
--robot-dcg-status | DCG status + config | root.go:3568 |
--robot-dcg-check --command=<cmd> | Preflight a command via DCG | root.go:3569-3571 |
--robot-guard | DEPRECATED alias for --robot-dcg-check | root.go:3570 |
Adapter contract, verified against current code:
- Status uses
dcg doctor --format json. - Checks use
dcg --robot test --format json <command>. dcg check, inline--json,--context, and--cwdare not part of the
current DCG check contract; NTM propagates cwd through cmd.Dir.
- If the command is wrapped in
rch exec -- ..., NTM extracts the inner build
command before asking DCG so build offload does not hide destructive intent.
SLB — Simultaneous Launch Button (two-person approval)
| Flag | Purpose | Source |
|---|---|---|
--robot-slb-pending | List pending two-person approval requests | root.go:3577 |
--robot-slb-approve=<id> | Approve by request ID | root.go:3578 |
--robot-slb-deny=<id> --reason=<r> | Deny with required reason | root.go:3579 |
CAAM — AI coding CLI account manager
| Flag | Purpose | Source |
|---|---|---|
--robot-account-status [--account-status-provider=<p>] | Current account + limits for provider | root.go:3556 |
--robot-accounts-list [--accounts-list-provider=<p>] | List known accounts | root.go:3561 |
--robot-switch-account=<provider[:acct]> | Swap active account | root.go:3562 |
Quota (caut)
| Flag | Purpose | Source |
|---|---|---|
--robot-quota-status | Overall quota snapshot | root.go:3589 |
--robot-quota-check --provider=<p> | Check specific provider quota | root.go:3590-3591 |
RCH — Remote compilation/build host
| Flag | Purpose | Source |
|---|---|---|
--robot-rch-status | RCH orchestrator status | root.go:3598 |
--robot-proxy-status | rust_proxy status | root.go:3599 |
--robot-rch-workers [--worker=<n>] | Worker pool state | root.go:3600-3601 |
Use rch exec -- <command> (for example rch exec -- go test -short ./...) when repo rules require remote compilation. The NTM robot flags are health/visibility adapters; they do not submit a build on their own.
RANO — Agent network observer
| Flag | Purpose | Source |
|---|---|---|
--robot-rano-stats [--rano-window=5m] | Per-agent network stats | root.go:3594-3595 |
RU — Multi-repo sync
| Flag | Purpose | Source |
|---|---|---|
--robot-ru-sync [--dry-run] | Run ru sync returning JSON | root.go:3583 |
GIIL — Image link downloader
| Flag | Purpose | Source |
|---|---|---|
--robot-giil-fetch=<url> | Download image via giil | root.go:3586 |
Agent Mail
| Flag | Purpose | Source |
|---|---|---|
--robot-mail | Machine-readable digest | root.go:3298 |
--robot-mail-check --mail-project=<p> | Check with filters | root.go:3612-3621 |
Mail-check filters: --mail-agent, --thread, --mail-status, --include-bodies, --urgent-only, --mail-verbose, --mail-offset, --mail-until.
Prefer `ntm mail inbox <session>` from the CLI when you want the session-derived form. --mail-project=<project> is required by --robot-mail-check and should not be attached to unrelated CLI subcommands.
CASS — Cross Agent Session Search
| Flag | Purpose | Source |
|---|---|---|
--robot-cass-status | Index state | root.go:3383 |
--robot-cass-search=<query> | Search past sessions | root.go:3384 |
--robot-cass-insights | Aggregate insights | root.go:3385 |
--robot-cass-context=<task> | Context suggestions for a task | root.go:3386 |
Context injection
| Flag | Purpose | Source |
|---|---|---|
--robot-context-inject=<session> | Inject AGENTS.md / README.md into panes | root.go:3604-3609 |
Knobs: --inject-files=<csv>, --inject-max-bytes=<N>, --inject-all, --inject-pane=<i>, --inject-dry-run.
Environment / setup probes
| Flag | Purpose | Source |
|---|---|---|
| `--robot-env=<session\ | global>` | Session or global env snapshot |
--robot-setup / --robot-acfs-status | Bootstrap readiness (deps, dirs, tokens) | root.go:3304-3305 |
--robot-tools | Tool availability (tmux, git, etc.) | root.go:3301 |
JFP, MS, XF (content surfaces)
| Flag | Purpose | Source |
|---|---|---|
| `--robot-jfp-status\ | list\ | search\ |
--robot-ms-search=<q> / --robot-ms-show=<id> | MS registry lookup | root.go:3415-3416 |
--robot-xf-search=<q> / --robot-xf-status | X/Twitter archive search | root.go:3419-3420 |
Composition notes
These adapters return structured JSON, not TUI state. They are safe to call from a loop and safe to pipe through jq. Because they proxy to external binaries:
- A missing external tool yields a structured error rather than a crash.
- Each integration respects its own authentication (CAAM for accounts, slb for SLB, etc.).
- Most adapters respect
--robot-formatand--robot-verbosity.
One-line quick index
ntm --robot-dcg-status # what DCG is blocking now
ntm --robot-dcg-check --command="git status" # preflight without running
ntm --robot-slb-pending # pending two-person approvals
ntm --robot-accounts-list # list CAAM accounts
ntm --robot-switch-account=claude:alice2 # rotate CAAM account
ntm --robot-quota-check --provider=claude # quota check
ntm --robot-rch-status # remote compile host status
ntm --robot-rano-stats # agent network stats
ntm --robot-ru-sync --dry-run # preview multi-repo sync
ntm --robot-mail # mail digest for current workspace
ntm --robot-mail-check --mail-project=myproject # filtered project inbox
ntm --robot-cass-search="authentication error" # session search
ntm --robot-context-inject=myproject --inject-all # inject AGENTS.md into panesNTM Pipelines — Durable Agent Workflows
Contents
- Subcommands —
run,status,list,cancel,resume,cleanup,exec - Run ID format
- State persistence and cleanup
- YAML schema (v2.0) — vars, settings, steps, loops
- Step primitives —
agent,wait,on_error,retry_backoff,output_parse - Loop forms —
items,while,times - Execution states
- Robot mode —
--robot-pipeline-runvs--robot-pipeline - Legacy `exec` form
---
Pipelines are NTM's declarative, resumable workflow engine. A workflow is YAML; each execution is a tracked run identified by a timestamped run ID. State persists at .ntm/pipelines/<run-id>.json after every step so runs are resumable across crashes and restarts.
Source: /dp/ntm/internal/cli/pipeline.go, schema at /dp/ntm/internal/pipeline/schema.go.
Subcommands
| Command | Purpose | Source |
|---|---|---|
ntm pipeline run <workflow.yaml> | Execute a workflow | pipeline.go:78 |
ntm pipeline status [run-id] | Single run status, or all if no id | pipeline.go:294 |
ntm pipeline list | List tracked runs | pipeline.go:337 |
ntm pipeline cancel <run-id> | Cancel a running pipeline | pipeline.go:355 |
ntm pipeline resume <run-id> | Resume from last checkpoint | pipeline.go:383 |
ntm pipeline cleanup --older=<dur> | Prune state files older than duration | pipeline.go:605 |
ntm pipeline exec <session> | Legacy sequential stages via --stage | pipeline.go:728 |
run flags: -s/--session <session> (required), --var key=value (repeatable), --var-file <json>, --dry-run, -b/--background.
resume flags: -s/--session (optional; uses saved session if omitted).
cleanup flags: --older <dur> (required), --dry-run.
Run ID format
run-YYYYMMDD-HHMMSS-<8 hex chars>
# Example: run-20261230-123456-abcd1234Generated by pipeline.GenerateRunID() at /dp/ntm/internal/pipeline/executor.go:1772.
State persistence and cleanup
State lives at .ntm/pipelines/<run-id>.json and is written after each step so resume picks up at the last incomplete step. There is no automatic retention — files accumulate forever. Run ntm pipeline cleanup --older=7d periodically.
YAML schema (v2.0)
schema_version: "2.0" is pinned at schema.go:11. Top-level Workflow fields at schema.go:14-29:
schema_version: "2.0"
name: my-review-workflow
description: Cross-agent PR review pipeline
version: "1.0.0"
# Variables — required or optional inputs
vars:
target_pr:
description: PR number to review
required: true
type: number
reviewers:
default: ["cc", "cod"]
type: array
# Global settings
settings:
timeout: 30m # default 30m (DefaultWorkflowSettings, schema.go:289)
on_error: fail # fail | fail_fast | continue | retry
notify_on_complete: false
notify_on_error: true
notify_channels: [desktop, webhook, mail]
webhook_url: "https://..."
mail_recipient: "alice@example.com"
# Step list (executed top-down unless depends_on declared)
steps:
- id: fetch
name: Fetch PR
# Agent selection (one of)
agent: claude # claude|codex|gemini|cursor|windsurf|aider|ollama
pane: 2 # explicit pane index
route: least-loaded # least-loaded | first-available | round-robin
# Prompt (one of)
prompt: "Fetch and summarize PR ${vars.target_pr}."
prompt_file: ./prompts/fetch.md
# Wait behavior
wait: completion # completion | idle | time | none
timeout: 5m # DefaultStepTimeout = schema.go:299
# Dependency DAG
depends_on: []
# Error handling
on_error: retry # fail | fail_fast | continue | retry
retry_count: 2
retry_delay: 30s
retry_backoff: exponential # linear | exponential | none
# Skip condition
when: "${vars.target_pr > 0}"
# Capture output for downstream steps
output_var: fetch_summary
output_parse:
type: json # none | json | yaml | lines | first_line | regex
pattern: "" # only for type: regex
- id: review-parallel
depends_on: [fetch]
parallel:
- id: review-cc
agent: claude
prompt: "Review based on: ${steps.fetch.output}"
- id: review-cod
agent: codex
prompt: "Review based on: ${steps.fetch.output}"
- id: merge-reviews
depends_on: [review-parallel]
agent: gemini
prompt: "Synthesize: ${steps.review-cc.output} AND ${steps.review-cod.output}"
- id: file-loop
depends_on: [merge-reviews]
loop:
items: "${vars.files}" # for-each
as: file
max_iterations: 100 # DefaultMaxIterations = schema.go:206
delay: 2s
collect: per_file_results
steps:
- id: analyze
prompt: "Analyze ${file}"
# Alternatives: while: "${expr}" | times: NStep primitives
- `agent` (enum, schema.go:94):
claude,codex,gemini,cursor,windsurf,aider,ollama. - `wait` (schema.go:144-149):
completion(wait for agent to finish),idle(wait until agent shows idle state),time(wait fortimeoutduration),none(fire-and-forget). - `on_error` (schema.go:80-85):
fail(stop pipeline),fail_fast(stop immediately, skip cleanup),continue(ignore and advance),retry(useretry_count/retry_delay/retry_backoff). - `retry_backoff` (schema.go:113):
linear,exponential,none. - `output_parse.type` (schema.go:120):
none,json,yaml,lines,first_line,regex. - `when`: Skip expression evaluated against current var + output context.
Loop forms
Three forms, mutually exclusive:
items: <array>+as: <name>→ for-each.while: <expression>→ run until false.times: <N>→ run N iterations.
All support max_iterations safety cap (default 100), delay between iterations, and collect: <var-name> to accumulate per-iteration output into a named variable. Inside a loop, loop_control: break|continue in a child step alters flow.
Execution states
Per-step state (schema.go:212-219): pending, running, paused, completed, failed, cancelled, skipped.
Progress events (schema.go:273): workflow_start, workflow_complete, workflow_error, step_start, step_complete, step_error, step_skip, step_retry, parallel_start.
Robot mode
Single-shot JSON interface for external callers:
| Flag | Purpose | Notes |
|---|---|---|
--robot-pipeline-run=<file> | Run workflow (needs --pipeline-session) | root.go:3473 |
--robot-pipeline=<run-id> | Status, not run — get run status | root.go:3474 |
--robot-pipeline-list | List all pipelines | root.go:3475 |
--robot-pipeline-cancel=<run-id> | Cancel | root.go:3476 |
--pipeline-session=<s> | Required with --robot-pipeline-run | |
--pipeline-vars='{"k":"v"}' | JSON variable overrides | |
--pipeline-dry-run | Validate only | |
--pipeline-background | Return immediately with run id |
--robot-pipeline=<id>is status, not run. To run use--robot-pipeline-run.
# Run headless with vars
ntm --robot-pipeline-run=.ntm/pipelines/review.yaml \
--pipeline-session=myproject \
--pipeline-vars='{"target_pr": 42, "reviewers": ["cc","cod"]}' \
--pipeline-background
# Check status
ntm --robot-pipeline=run-20261230-123456-abcd1234
# Cancel
ntm --robot-pipeline-cancel=run-20261230-123456-abcd1234Legacy exec form
ntm pipeline exec <session> --stage "type:model: prompt" is legacy (pipeline.go:733). Accepts --stage "type: prompt" or --stage "type:model: prompt" repeatedly and runs sequentially, passing each step's output to the next.
Prefer the YAML schema for anything non-trivial.
NTM Robot Mode
Use this file when you need the deeper, structured automation side of NTM.
Contents
- Output Formats —
--robot-format, env fallbacks, verbosity - Start Here — discovery, capabilities, schema
- Canonical Operator Loop
- Attention Feed — snapshot, events, digest, wait, overlay
- Attention Profiles
- Wait Conditions
- Core Robot Actions — send, ack, tail, inspect
- Safe Restart Pattern
- Assignment and Routing
- Context and Health
- Files, Replay, Support
- Beads, Mail, and CASS
- Human-Friendly Robot Views
- Full `--robot-*` Flag Index — grouped with
root.goline refs - Discovery / docs
- State / snapshots / formats
- Events / attention
- Pane inspect / tail / watch
- Activity / health / diagnose
- Control / mutate
- Sessions / spawn / controller
- Assign / route / distribute
- Work / beads / bv
- Pipeline
- Mail / coordination
- CASS
- Ensemble / modes
- Monitor / tools / bundle
- Palette / recipes / setup / profile
- Integrations
---
Output Formats
| Flag | Meaning |
|---|---|
--robot-format=json | Full JSON output |
--robot-format=toon | More token-efficient structured output (prefer when context is tight) |
--robot-format=auto | Auto-select current default |
Env fallbacks honored (in order): NTM_ROBOT_FORMAT, NTM_OUTPUT_FORMAT, TOON_DEFAULT_FORMAT.
Note: --robot-output-format is a deprecated alias — always use --robot-format.
Verbosity: --robot-verbosity=terse|default|debug (env NTM_ROBOT_VERBOSITY).
Start Here
ntm --robot-help
ntm --robot-capabilities # machine-discoverable API schema (prefer this over --help)
ntm --robot-docs=quickstart # topics: quickstart | commands | examples | exit-codes
ntm --robot-schema=all # JSON Schema for every robot response type
ntm --robot-status
ntm --robot-snapshot
ntm --robot-plan
ntm --robot-dashboard
ntm --robot-markdown --md-compact
ntm --robot-terse--robot-capabilities is the canonical schema/discovery surface. Prefer it over parsing human help text. --robot-schema=all lets you validate parsed responses.
Response and Freshness Contract
Robot output is meant to be parsed mechanically:
- Treat
success=falsepluserror_codeas the control signal; do not scrape prose. - Required list fields should be present as empty arrays when checked-and-empty.
- Optional fields are omitted when irrelevant; do not expect
null. timestamp,schema_version, andoutput_formatare part of the envelope on
the newer surfaces.
- For derived views, read
sources/degraded_sourceswarnings before acting.
Decision rule:
| Source status | Operator posture |
|---|---|
| fresh / healthy | Safe to act on the derived recommendation |
| stale but available | Act only if low-risk; annotate the stale source |
| degraded / unavailable | Prefer non-mutating previews; fall back to native tools (br, bv, mail MCP) |
| contradictory sources | Re-bootstrap with --robot-snapshot, then inspect the native source |
Do not turn a degraded source into a hard stop by default. NTM is designed to remain useful when CASS, Agent Mail, or BV are partially unavailable, but mutating commands should be held to a higher proof threshold.
Canonical Operator Loop
1. Bootstrap with ntm --robot-snapshot
2. Read latest cursor / attention summary
3. Tend with ntm --robot-attention or ntm --robot-wait
4. Act with ntm --robot-send, ntm send, ntm assign, ntm mail, or ntm locks
5. Repeat
If the cursor expires, re-run --robot-snapshot.Attention Feed
| Command | Purpose |
|---|---|
--robot-snapshot | Bootstrap unified state plus attention summary and cursor handoff |
--robot-events | Raw replay since a cursor |
--robot-digest | Non-blocking attention-feed summary |
--robot-attention | Wait-then-digest tending command |
--robot-overlay | Human handoff / overlay actuator |
--robot-wait | Wait for pane or attention conditions |
Example flow:
ntm --robot-snapshot
ntm --robot-events --since-cursor=42 --events-limit=50 --events-category=agent
ntm --robot-digest --profile=minimal
ntm --robot-attention --attention-cursor=42
ntm --robot-overlay=myproject --overlay-no-waitAttention Profiles
| Profile | Flag | Behavior |
|---|---|---|
operator | --profile=operator | Default operator-focused blend |
debug | --profile=debug | Full verbosity |
minimal | --profile=minimal | Only the most urgent items |
alerts | --profile=alerts | Alert-centric view |
Explicit filters override profile defaults.
Wait Conditions
Flag: --wait-until (alias --condition). Canonical set from --robot-capabilities:
Pane-oriented:
idlecompletegeneratinghealthystalledrate_limited
Attention-oriented:
attentionaction_requiredmail_pendingmail_ack_requiredcontext_hotreservation_conflictfile_conflictsession_changedpane_changed
Deliberately unsupported: bead_orphaned. NTM refuses to emit this because abandonment cannot be proven from observable pane/session state alone — emitting it would invent conclusions from insufficient data. Do not try to wait on it; the command will reject.
Example:
ntm --robot-wait=myproject --wait-until=idle --timeout=5m
ntm --robot-wait=myproject --wait-until=action_required --attention-cursor=42
ntm --robot-wait=myproject --wait-until=mail_pending --attention-cursor=42
ntm --robot-wait=myproject --wait-until=reservation_conflict --attention-cursor=42Core Robot Actions
# Send and watch for response
ntm --robot-send=myproject --panes=2 --msg="Fix auth" --type=claude
ntm --robot-ack=myproject --timeout=30s # --ack-timeout/--ack-poll are deprecated aliases
# Inspect without retiling
ntm --robot-tail=myproject --panes=2 --lines=50
ntm --robot-inspect-pane=myproject --inspect-index=2
ntm --robot-inspect-session=myproject
ntm --robot-inspect-agent=myproject:2
ntm --robot-inspect-work=br-123
ntm --robot-inspect-coordination=<agent>
ntm --robot-inspect-quota=<provider>/<account>
ntm --robot-inspect-incident=<incident-id>Safe Restart Pattern
Raw --robot-interrupt is honest but blunt. Prefer the polite-probe-then-act pair:
# 1. Probe first
ntm --robot-is-working=myproject --panes=2,3 # returns structured working/idle state
ntm --robot-probe=myproject --panes=2 # responsiveness probe
ntm --robot-diagnose=myproject # comprehensive health + recommendations
# 2. Act with smart defaults that refuse to interrupt working agents
ntm --robot-smart-restart=myproject --panes=2 # safe — checks --robot-is-working first
ntm --robot-restart-pane=myproject --type=claude --dry-run
# 3. Only use raw interrupt when you've decided to override
ntm --robot-interrupt=myproject --panes=2 --msg="Stop and reconsider."Assignment and Routing
ntm --robot-assign=myproject --strategy=dependency
ntm --robot-bulk-assign=myproject --from-bv # one-shot: assign bv top picks to idle agents
ntm --robot-route=myproject --strategy=affinityContext and Health
ntm --robot-context=myproject # context-window usage per agent (anticipate rotation)
ntm --robot-agent-health=myproject
ntm --robot-health=myproject
ntm --robot-health-oauth=myproject
ntm --robot-health-restart-stuck=myproject
ntm --robot-monitor=myproject --interval=30s
ntm --robot-metrics=myproject --metrics-period=1hFiles, Replay, Support
ntm --robot-files=myproject --files-window=6h
ntm --robot-replay=myproject --replay-id=<id>
ntm --robot-support-bundle=myproject
ntm --robot-save=myproject
ntm --robot-restore=/path/to/snapshot.jsonBeads, Mail, and CASS
ntm --robot-beads-list --beads-status=open
ntm --robot-bead-show=br-123
ntm --robot-bead-claim=br-123 --bead-assignee=agent1
ntm --robot-bead-create --bead-title="..." --bead-type=task --bead-priority=2
ntm --robot-bead-close=br-123 --bead-close-reason="Completed"
ntm --robot-watch-bead=myproject # stream bead activity for a session
ntm --robot-mail # machine-readable mail digest
ntm --robot-mail-check --mail-project=myproject --urgent-only
ntm --robot-context-inject=myproject # inject mail + work context into panes
ntm --robot-cass-status
ntm --robot-cass-search="authentication error"
ntm --robot-cass-insights
ntm --robot-cass-context=<task-description>Graph-aware triage (wraps bv):
ntm --robot-triage --triage-limit=10
ntm --robot-plan
ntm --robot-graph
ntm --robot-forecast=all
ntm --robot-impact=<path>
ntm --robot-search=<query>
ntm --robot-label-health
ntm --robot-label-flow
ntm --robot-label-attention
ntm --robot-file-beads=<path> ntm --robot-file-hotspots ntm --robot-file-relations=<path>These are useful when a script or agent needs structured access to work state, coordination state, or past-session search.
Human-Friendly Robot Views
When JSON is too heavy but you still need automation-friendly output:
ntm --robot-markdown
ntm --robot-markdown --md-compact
ntm --robot-terseUse --robot-terse for operator summaries. Use --robot-markdown when a human or another model benefits from lower-token tables instead of raw JSON.
Full --robot-* Flag Index
Grouped by purpose. All flag definitions live in /dp/ntm/internal/cli/root.go in the range 3127-3612. Token after each line = source-file line number.
Discovery / docs
--robot-help3127--robot-status3128--robot-version3129--robot-capabilities3130--robot-docs=<topic>3131—quickstart|commands|examples|exit-codes--robot-schema=<type>3294—alldumps every schema--robot-default-prompts3426
State / snapshots / formats
--robot-snapshot3133--robot-terse3357--robot-markdown/--md-compact3366--robot-dashboard3193--robot-format=json|toon|auto3360--robot-output-format3363(DEPRECATED)--robot-verbosity=terse|default|debug3224--robot-limit N/--robot-offset N3222-3223
Events / attention
--robot-events --since-cursor=N --events-limit=M3135--robot-attention3146--robot-digest3147--robot-alerts3520--robot-dismiss-alert=<id>3510--robot-overlay3216
Pane inspect / tail / watch
--robot-tail=<session> --panes=N,M --lines=L3153--robot-watch-bead=<session>3154--robot-errors=<session>3156--robot-inspect-pane=<session> --inspect-index=N --inspect-lines=L --inspect-code3487--robot-inspect-session=<session>3491--robot-inspect-agent=<session:pane>3492--robot-inspect-work=<bead-id>3493--robot-inspect-coordination=<agent>3494--robot-inspect-quota=<provider/acct>3495--robot-inspect-incident=<id>3496
Activity / health / diagnose
--robot-activity=<session>3449--robot-is-working=<session> --panes=N,M3160--robot-agent-health=<session>3162--robot-health[=<session>]3272--robot-health-oauth=<session>3273--robot-health-restart-stuck=<session> --stuck-threshold=<dur>3276--robot-diagnose=<session> [--diagnose-fix]3285--robot-context=<session>3194--robot-logs=<session>3280
Control / mutate
--robot-send=<session> --panes=N --msg="..."3248--robot-ack=<session> --timeout=30s3308--robot-interrupt=<session> --panes=N --msg="..."3340--robot-smart-restart=<session> --panes=N [--force] [--hard-kill]3165--robot-restart-pane=<session> --type=claude --panes=N --dry-run3348--robot-probe=<session> --panes=N3351--robot-save=<session>3374--robot-restore=<path>3378--robot-switch-account=<provider[:acct]>3556
Sessions / spawn / controller
--robot-spawn=<session> --spawn-cc=N ...3314--robot-controller-spawn=<session>3334--robot-agent-names=<session>3331
Assign / route / distribute
--robot-assign=<session> --strategy=<s>3259--robot-bulk-assign=<session> --from-bv3264--robot-route=<session> --strategy=<s>3467
Work / beads / bv
--robot-plan3132--robot-graph3190--robot-triage --triage-limit=N3191--robot-suggest3228--robot-forecast=<id|all>3227--robot-impact=<path>3229--robot-search=<query>3230--robot-label-attention3233--robot-label-flow3235--robot-label-health3236--robot-file-beads=<path>3239--robot-file-hotspots3241--robot-file-relations=<path>3243--robot-beads-list3526--robot-bead-claim=<id> --bead-assignee=<a>3534--robot-bead-create --bead-title=<t> --bead-type=<t> --bead-priority=<n>3535--robot-bead-show=<id>3536--robot-bead-close=<id> --bead-close-reason=<r>3537
Pipeline
--robot-pipeline-run=<file> --pipeline-session=<s>3473(run)--robot-pipeline=<run-id>3474(status)--robot-pipeline-list3475--robot-pipeline-cancel=<run-id>3476
Mail / coordination
--robot-mail3298--robot-mail-check --mail-project=<project> [filters]3612--robot-context-inject=<session>3604
CASS
--robot-cass-status3383--robot-cass-search=<q>3384--robot-cass-insights3385--robot-cass-context=<task>3386
Ensemble / modes
--robot-ensemble-modes3195--robot-ensemble-presets3196--robot-ensemble=<session>3197--robot-ensemble-spawn=<session> --preset --question3198--robot-ensemble-suggest=<question>3209--robot-ensemble-stop=<session>3211
Monitor / tools / bundle
--robot-monitor=<session> --interval=30s3172--robot-support-bundle[=<session>]3182--robot-files[=<session>] --files-window=<dur>3483--robot-metrics[=<session>] --metrics-period=<dur>3498--robot-replay=<session> --replay-id=<id>3501--robot-diff=<session> --since=<dur>3516--robot-summary=<session> --since=<dur>3548--robot-history=<session>3441--robot-tokens3433--robot-wait=<session> --wait-until=<cond>3453
Palette / recipes / setup / profile
--robot-palette3505--robot-recipes3291--robot-setup/--robot-acfs-status3304-3305--robot-profile-list/--robot-profile-show=<name>3429-3430
Integrations
See INTEGRATIONS.md for DCG, SLB, CAAM, RCH, RANO, quota, ru, giil, JFP, MS, XF.
Safety, Policy, Approvals
Three related subsystems govern destructive operations:
1. `ntm safety` — the enforcement layer: wrappers, hooks, and a blocked-log. 2. `ntm policy` — the rule set stored in ~/.ntm/policy.yaml. 3. `ntm approve` — the token-based approval gate for human sign-off.
Sources: /dp/ntm/internal/cli/safety.go, policy_cmd.go, approve.go, plus the policy engine at /dp/ntm/internal/policy/.
Contents
- `ntm safety` — status, blocked-log, check, install/uninstall
- What `install` does on disk — wrappers + Claude hook
- `check` response shape
- `ntm policy` — show, validate, reset, edit, automation
- `policy.yaml` schema — allowed / blocked / approval_required
- `ntm policy automation` flags
- `ntm approve` — token-based approval gate
- Token semantics
- SLB (Simultaneous Launch Button)
- Workflow — blocked command to completion
- Scenario examples
---
ntm safety
| Subcommand | Purpose |
|---|---|
status | JSON snapshot: installed state, policy path, counts, wrapper + hook status |
blocked --hours N | Recent blocked commands from ~/.ntm/logs/blocked.jsonl (default 24) |
check "<command>" | Evaluate a command — returns allow, block, or approve |
install | Install wrappers + Claude hook (see below) |
uninstall | Remove wrappers + hook |
What install does on disk
From safety.go:434-516:
1. Shell wrappers at ~/.ntm/bin/git and ~/.ntm/bin/rm. Each script calls ntm safety check --json first; aborts if action != allow. Blocked events append to ~/.ntm/logs/blocked.jsonl. 2. Claude Code hook at ~/.claude/hooks/PreToolUse/ntm-safety.sh. Reads the current Claude hook JSON payload from stdin (tool_name, tool_input.command), falls back to legacy CLAUDE_TOOL_* env vars only when stdin is absent, and forwards Bash calls through the policy check (safety.go:820-870).
Wrappers require `$PATH` precedence. install does NOT modify $PATH. Confirm ~/.ntm/bin is earlier than /usr/bin in the shell profile, or the wrappers will not intercept.
check response shape
{
"action": "allow|block|approve",
"pattern": "regex that matched",
"reason": "human-readable explanation",
"policy": { "slb": false },
"dcg_verdict": { "verdict": "safe|dangerous|...", ... }
}Exit code 0 for allow, 1 for block/approve from ntm safety check itself. The installed Claude hook exits 0 for allowed/non-Bash calls and exits 2 when it blocks or requires approval, which is the Claude Code hook convention for a blocking PreToolUse decision. In scripts, parse JSON for the action field — don't rely on the exit code alone.
ntm policy
| Subcommand | Purpose |
|---|---|
show [--all] | JSON dump of current policy (full rule list with --all) |
validate [file] | Validate a policy.yaml without installing |
reset -f | Restore built-in defaults |
edit | Open ~/.ntm/policy.yaml in $EDITOR |
automation | Toggle auto-commit / auto-push / force-release mode |
policy.yaml schema
Default path: ~/.ntm/policy.yaml (policy_cmd.go:100). Written by writeDefaultPolicy (safety.go:551-595). Full schema:
version: 1
automation:
auto_commit: false
auto_push: false
force_release: approval # never | approval | auto (default: approval)
# Rule precedence: allowed > blocked > approval_required
allowed:
- pattern: '^git status(\s|$)'
reason: read-only git status
- pattern: '^git diff(\s|$)'
reason: read-only git diff
blocked:
- pattern: '^git reset\s+--hard'
reason: destroys local changes
- pattern: '^git clean\s+-f'
reason: deletes untracked files
- pattern: '^git push.*--force'
reason: rewrites remote history
- pattern: '^rm\s+-rf\s+(/|~|\*|\.|\.\.)'
reason: mass deletion of protected paths
- pattern: '^git branch\s+-D'
reason: force-delete branch
- pattern: '^git stash\s+(drop|clear)'
reason: destroys stashed work
approval_required:
- pattern: '^git rebase\s+(-i|--interactive)'
reason: interactive rebase rewrites history
slb: false # require two-person approval
- pattern: '^git commit\s+--amend'
reason: rewrites last commit
- pattern: '^rm\s+-rf\s+'
reason: recursive delete
slb: true # two-person for broad deletentm policy automation flags
Toggle automation behavior (policy_cmd.go:568-572):
--auto-commit/--no-auto-commit--auto-push/--no-auto-push--force-release never|approval|auto— defaultapproval. Validated at
policy_cmd.go:665-669.
ntm approve
Human-approval gate for any policy rule marked approval_required. Tokens are issued by the approval engine at /dp/ntm/internal/approval/ and stored in the main NTM state DB (opened at approve.go:110).
| Subcommand | Purpose |
|---|---|
list | Show pending approvals |
show <token> | Full details: resource, action, requires_slb, created_at, expires_at, decided_by |
<token> | Approve |
deny <token> --reason "..." | Deny with required reason |
history | Show recent decisions |
Token semantics
- Tokens, not bead IDs. Approvals are keyed by a generated token returned with the
approval request. Passing br-123 will be rejected.
- TTL —
ExpiresAtis populated fromDefaultConfig()per action class. Typical
values: 15m for high-risk, 24h for routine.
- Identity —
approved_byis$NTM_USERor$USER(approve.go:322-331). - Correlation —
correlation_idties the approval to the originating session/pane
so the blocked caller can resume.
SLB (Simultaneous Launch Button) — two-person approval
When a rule has slb: true, two different approvers must approve before the action is released. Robot-mode surface for integration with the slb tool:
--robot-slb-pending
--robot-slb-approve=<request-id>
--robot-slb-deny=<request-id> --reason=<r>Registered at root.go:3577-3579.
Workflow — from blocked command to completion
1. Agent runs a command in a shell with ~/.ntm/bin on PATH, or Claude Code sends a PreToolUse event as JSON on stdin to the installed hook. 2. Wrapper/hook calls ntm safety check --json "<cmd>". 3. If action=approve, engine creates a pending approval and returns an error identifying a token. 4. Human (or second approver for SLB) runs ntm approve <token> or ntm approve deny <token> --reason "...". 5. Approval state changes to approved / denied; agent can retry. 6. ~/.ntm/logs/blocked.jsonl retains the audit trail either way.
Scenario examples
# Check what a command would do
ntm safety check --json "git push --force origin main"
# List what was blocked in the last day
ntm safety blocked --hours 24
# See all rules
ntm policy show --all
# Toggle auto-commit on for a CI flow
ntm policy automation --auto-commit
# Approve a pending token
ntm approve list
ntm approve show t_abc123
ntm approve t_abc123 # authorize
# Deny
ntm approve deny t_abc123 --reason "Wrong target branch"NTM Skill Self-Test
Trigger phrases and scenarios the NTM skill should activate on, paired with the first thing the agent should do. Use this to sanity-check that skill description, triggers, and reference files still cover the real request surface.
Contents
- Swarm lifecycle
- Dispatch / send
- Coordination and recovery
- Safety and approvals
- Work intelligence
- Robot-mode automation
- Durability
- Pipelines and serve
- Error strings operators actually paste
- Non-triggers — what should NOT fire this skill
---
Swarm lifecycle
| Trigger phrase | First action |
|---|---|
"Spawn a swarm on myproject with 3 Claude and 2 Codex" | ntm spawn myproject --cc=3 --cod=2 — see SPAWN.md |
| "Launch a mixed agent swarm" | ntm spawn <session> --cc=N --cod=N --gmi=N |
| "Add another Claude pane to the running swarm" | ntm add <session> --cc=1 or ntm scale |
| "Adopt this existing tmux session into ntm" | ntm adopt <session> |
| "Kill the swarm" | ntm kill <session> |
| "Revive the dead panes in place" | ntm respawn <session> |
Dispatch / send
| Trigger phrase | First action |
|---|---|
| "Send marching orders to all Claude panes" | ntm send <session> --cc "..." — SEND.md |
| "Broadcast to every pane" | ntm send <session> --all "..." (warn: hits user pane) |
| "Pair panes 2 and 3 on the broken build" | ntm send <session> --panes=2,3 "..." |
| "Send this file's contents as the prompt" | ntm send <session> --file prompts/X.md |
| "Distribute ready beads across idle agents" | ntm send <session> --distribute --dist-strategy=dependency |
Coordination and recovery
| Trigger phrase | First action |
|---|---|
| "Check the agent mail inbox" | ntm mail inbox <session> --json |
| "See who holds which file locks" | ntm locks list <session> --all-agents |
| "Force-release a stale reservation" | ntm locks force-release <session> <id> --note "..." |
| "Get coordinator digest" | ntm coordinator digest <session> |
Safety and approvals
| Trigger phrase | First action |
|---|---|
| "Is that command going to be blocked?" | ntm safety check --json "<cmd>" — SAFETY.md |
| "Show me what got blocked last 24h" | ntm safety blocked --hours 24 |
| "Install the safety wrappers and Claude hook" | ntm safety install (then verify $PATH) |
| "Show me the policy rules" | ntm policy show --all |
| "Approve this pending token" | ntm approve <token> (NOT bead id) |
| "Deny approval with reason" | ntm approve deny <token> --reason "..." |
Work intelligence
| Trigger phrase | First action |
|---|---|
| "What should I work on next" | ntm work triage or ntm work next — WORK-AND-ASSIGN.md |
| "Triage by label" | ntm work triage --by-label |
| "Find beads touching this file" | ntm work impact <path> |
| "Assign ready work automatically" | ntm assign <session> --auto --strategy=dependency |
| "Pin these beads to codex" | ntm assign <session> --beads=br-1,br-2 --agent=codex |
| "The queue is dry / no ready work exists" | ntm work queue-dry --format=json, then preview --ideate only if dry |
| "Before assigning ten panes, check pressure" | ntm --robot-agent-health=<session> + ntm --robot-rch-status + ntm --robot-quota-status |
Robot-mode automation
| Trigger phrase | First action |
|---|---|
| "Bootstrap automation state" | ntm --robot-snapshot — ROBOT-MODE.md |
| "Wait until something needs attention" | ntm --robot-wait=<session> --wait-until=attention |
| "Is pane 2 actively working" | ntm --robot-is-working=<session> --panes=2 |
| "Smart-restart pane 2 (not brute kill)" | ntm --robot-smart-restart=<session> --panes=2 |
| "Show me context-window usage per pane" | ntm --robot-context=<session> |
| "Tail 50 lines from pane 3 without retiling" | ntm --robot-tail=<session> --panes=3 --lines=50 |
| "Rotate the Claude account (rate-limited)" | ntm --robot-switch-account=claude:<acct> |
| "Does this robot flag still exist" | `ntm --robot-capabilities |
Durability
| Trigger phrase | First action |
|---|---|
| "Snapshot the whole session before this refactor" | ntm checkpoint save <session> -m "..." — DURABILITY.md |
| "Roll everything back" | ntm checkpoint restore <session> last or ntm rollback |
| "Write a handoff for another operator" | ntm handoff create <session> |
| "Move this session to another machine" | ntm checkpoint export + checkpoint import |
| "Resume after a crash" | ntm resume <session> |
| "What happened during this session" | ntm timeline show <session-id> |
Pipelines and serve
| Trigger phrase | First action |
|---|---|
| "Run the review pipeline" | ntm pipeline run .ntm/pipelines/<file>.yaml --session <s> — PIPELINES.md |
| "Status of that pipeline run" | ntm pipeline status <run-id> |
| "Start the local NTM API server" | ntm serve --port 7337 — SERVE.md |
| "Headless pipeline from a script" | ntm --robot-pipeline-run=<file> --pipeline-session=<s> |
Error strings operators actually paste
These should all route to TROUBLESHOOTING.md via the index table:
project not foundCASS detected identical messageContinue anyway? [y/N]zsh: command not found(aftersend --all)reservation_conflictCURSOR_EXPIREDunknown flag: --mail-project=ntm: unknown command: timeline(old binaries)rate_limited/ "resets 3pm"project name %q contains '--'
Non-triggers
These look NTM-ish but belong to companion skills:
- "How do I tend a stuck swarm / unstick ladder / orchestrator loop" →
vibing-with-ntm - "Bead creation / dep graph / dependency resolution" →
br+beads-workflow - "Agent-mail reservation handshake" →
agent-mail - "Rotate which Claude account is active globally" →
caam(ntm's--robot-switch-accountwraps it for sessions) - "Block this destructive command system-wide" →
dcg - "Two-person launch button" →
slb
ntm send — Exhaustive Flag Reference
Contents
- Default targeting behavior
- Agent-type selectors (with `:variant` filter)
- Pane selectors —
--pane,--panes,--all,-s/--skip-first,--project,--tag - Input sources —
--file, stdin, positional, priority order - Base prompt (prepended to every target)
- `-c/--context` file-range injection
- Templates and variables —
-t/--template,--var - Smart routing (`--smart` + `--route`)
- Distribute mode (auto-distribute from bv triage)
- Batch / broadcast
- CASS duplicate-detection —
--cass-check,--no-cass-check, workarounds - Prefix, suffix, hooks, dry-run
- Output shapes
- Error matrix
- Scenario catalog — 10 copy-ready recipes
---
Covers every flag registered in /dp/ntm/internal/cli/send.go. Source citations use send.go:line shorthand; all paths are under /dp/ntm/internal/cli/.
Default targeting behavior
With no target flags, send targets all agent panes in the session and excludes the user pane. This is almost always what you want from automation.
--allexpands the target set to include the user pane.-s/--skip-firstexplicitly excludes pane 0 (the user pane). Mostly useful together
with --all to get "every pane except the operator shell" broadcast semantics.
Agent-type selectors (with :variant filter)
Custom flags implemented by sendTargetValue (send.go:297-341). All four accept NoOptDefVal=true, so bare --cc means "any Claude pane," while --cc=opus filters by tmux.Pane.Variant exact equality.
| Flag | AgentType | Example | Notes |
|---|---|---|---|
--cc[=variant] | cc (Claude) | --cc=opus | Variant is an open string, not pre-enumerated |
--cod[=variant] | cod (Codex) | --cod=gpt-5 | |
--gmi[=variant] | gmi (Gemini) | --gmi=pro | |
--agy[=variant] | agy (AGY / Antigravity) | --agy | Same selector semantics as tri-vendor spawn |
--cc=false is treated as a no-op (send.go:320-322). Selectors can be combined: --cc --cod sends to all Claude + Codex panes. Combining with --pane=N ANDs: a specific pane that doesn't match the type yields zero targets + error.
AGY (Antigravity) — --agy send selector
AGY panes spawned with ntm spawn --agy=… are targeted by `--agy` on ntm send (same family as --cc / --cod / --gmi / --agy):
ntm send <session> --agy "run the tests"
ntm send <session> --agy --file packet-agy.mdFor a specific pane index (or when mixing file + type filters), use `--pane=N` (or --panes=) with -f/--file:
ntm send <session> --pane=3 --file packet-agy.mdDo not use agy -p / gemini -p for swarm workers (LAW 0).
`--gmi` vs AGY: --gmi selects Gemini CLI (gmi agent type) panes. AGY / Antigravity is a separate agent family (agy); tri-vendor smoke uses --agy at spawn and send time. See `/dual-pane-atm` § Tri-vendor.
Pane selectors
| Flag | Type | Purpose | Source |
|---|---|---|---|
-p/--pane | int | Single pane by index (default -1 = unset) | send.go:727 |
--panes | string | CSV of indices or ranges; parsed by robot.ParsePanesArg | send.go:728,652 |
--all | bool | Include the user pane | send.go:725 |
-s/--skip-first | bool | Explicitly skip pane 0 | send.go:726 |
--project | string | Broadcast to all sessions sharing a SessionBase | send.go:775 |
--tag (repeatable) | []string | Match panes by tag (OR logic) | send.go:735 |
Conflicts
--pane+--panes→cannot use --pane and --panes together(send.go:658).--project+ specific session name →cannot use --project with a specific session name(send.go:580).
Addressing disambiguation (don't mis-target)
Three different selector families coexist and use different index spaces — easy to mis-address and silently hit the wrong pane (or the operator pane). When combined, they AND together (intersection); an empty intersection errors rather than broadcasting.
| Selector | Index space | Selects | Typical use |
|---|---|---|---|
--pane=N / --panes=N,M | tmux pane index (verify live; base-index may be 1 — OC-028/OC-045) | exactly that pane / that explicit set | targeted dispatch to a known pane |
--cc / --cod / --gmi / --agy (+ :variant) | agent type, not index | all panes of that type | broadcast to a model class |
--agent <idx> (batch/broadcast only, default -1) | round-robin selector over agent panes, NOT a tmux index | one agent per batch item, rotating; -1 = auto round-robin | distributing a batch across agents |
Rules: --agent is a batch-distribution knob (send.go:772), not a synonym for --pane. Don't reach for --agent 2 to mean "pane 2" — use --pane=2. With no target flags at all, send hits every agent pane and excludes the user pane (the usual automation default); --all re-includes the user pane. Verify the live pane index immediately before any raw tmux send-keys (OC-045).
--all vs --project
These are orthogonal axes.
--allscope: panes within one session, includes the user pane.--projectscope: all sessions whose `SessionBase(name)` matches, iterates each session and applies the intra-session pane filter independently.
You can combine them: ntm send --project myproject --all "x" → every pane of every session variant, including each session's user pane.
Input sources
Resolved by getPromptContent (send.go:851-891) in priority order. First match wins.
| Priority | Source | Flag | Source-label in JSON |
|---|---|---|---|
| 1 | File | -f/--file | file:<path> |
| 2 | Stdin | (pipe; only when no args) | stdin |
| 3 | Positional args | (joined with spaces) | args |
- Empty file errors at
send.go:862. - Empty stdin with no prefix errors at
send.go:878. --prefix/--suffix(send.go:730-731) wrap file or stdin content; ignored for positional args (send.go:889).
Base prompt (prepended to every target)
--base-prompt <string>(send.go:763).--base-prompt-file <path>(send.go:764).- Config fallbacks:
cfg.Send.BasePrompt,cfg.Send.BasePromptFile(send.go:594-595).
Resolution precedence: flag string > flag file > config string > config file (send.go:597).
-c/--context file-range injection
Repeatable StringArray (send.go:732). Parsed by prompt.ParseFileSpec (send.go:698).
Syntax (documented at send.go:539):
| Form | Meaning |
|---|---|
path | Whole file |
path:10-50 | Lines 10–50 inclusive |
path:10- | Line 10 through end |
path:-50 | Start through line 50 |
Multiple -c accumulate in order. prompt.InjectFiles (send.go:705) prepends them to the final prompt with file headers + code fences.
ntm send myproject --cc \
-c internal/auth/service.go:1-80 \
-c internal/auth/middleware.go \
"Review these handlers side by side and propose a unification."Templates and variables
-t/--template <name>(send.go:733): loads named template via the template loader.--var key=valuerepeatable (send.go:734).
Templates are resolved from project .ntm/templates/ then user ~/.config/ntm/templates/ (enumerate with ntm template list).
Template engine supports:
{{variable}}substitution{{#var}}...{{/var}}conditional blocks (non-empty → include){{file}}auto-bound to--filecontent
When -t is given the input path flows through runSendWithTemplate (send.go:686).
ntm send myproject --cc \
-t fix \
--var issue="nil pointer deref in JWT validator" \
--var severity="P0" \
--file internal/auth/service.goSmart routing (--smart + --route)
| Flag | Default | Source |
|---|---|---|
--smart | false | send.go:738 |
--route <strategy> | "" | send.go:739 |
Strategies (per help at send.go:739): least-loaded, round-robin, affinity, sticky, random.
Decision returned in SendResult.RoutedTo *SendRoutingResult (send.go:91-97) with {PaneIndex, AgentType, Strategy, Reason, Score}.
Distribute mode (auto-distribute from bv triage)
| Flag | Default | Source |
|---|---|---|
--distribute | false | send.go:742 |
--dist-strategy | balanced | send.go:743 |
--dist-limit N | 0 (one per idle agent) | send.go:744 |
--dist-auto | false (skip confirmation) | send.go:745 |
Valid --dist-strategy: balanced, speed, quality, dependency.
--dist-auto + --dry-run is rejected (send.go:605). Use one or the other.
Batch / broadcast
| Flag | Default | Source |
|---|---|---|
--batch <file> | "" | send.go:767 |
--delay <dur> | "" (parsed by time.ParseDuration) | send.go:768 |
--confirm-each | false | send.go:769 |
--stop-on-error | false | send.go:770 |
--broadcast | false | send.go:771 |
--agent <idx> | -1 (round-robin) | send.go:772 |
--randomize | false | send.go:756 |
--seed <int64> | 0 (time-based) | send.go:757 |
--priority-order | false | send.go:760 |
Batch file format: one prompt per line, or --- separated blocks (send.go:767).
Randomization uses xorshift64 Fisher-Yates (send.go:424-441). Seed 0 uses time.Now().UnixNano() and the chosen value is returned as SeedUsed in the JSON result so you can reproduce.
--confirm-each in batch mode blocks on stdin per prompt. In automation or cron,omit it or the command hangs.
CASS duplicate-detection
Default ON. CASS (Cross Agent Session Search) queries past sessions for prompts similar to what you're about to send and aborts with a confirmation if one is found.
| Flag | Default | Source |
|---|---|---|
--cass-check | true | send.go:748 |
--no-cass-check | false | send.go:749 |
--cass-similarity <float> | 0.7 | send.go:750 |
--cass-check-days N | 7 | send.go:751 |
In practice this blocks repeat-sends in tending loops. Two ways to bypass:
1. Per-call (recommended in scripts): ntm send ... --no-cass-check. 2. Structural (recommended for automation): ntm --robot-send=<session> is non-interactive and never prompts. 3. Rotating suffix trick (widely used in operator loops): append a marker that changes each pass — "... Tend pass 17 at 16:40" — which keeps the message distinctive enough to pass the similarity gate.
Prefix, suffix, hooks, dry-run
| Flag | Purpose | Source |
|---|---|---|
--prefix <str> | Prepend to prompt (file/stdin sources only) | send.go:730 |
--suffix <str> | Append to prompt (file/stdin sources only) | send.go:731 |
--no-hooks | Disable PreSend/PostSend hook chain | send.go:752 |
--dry-run | Emit SendDryRunResult without sending | send.go:753 |
Output shapes
Normal send (SendResult, send.go:49-64)
{
"success": true,
"session": "myproject",
"targets": [{"pane": 2, "agent": "cc"}],
"delivered": 1,
"failed": 0,
"routed_to": { "pane_index": 2, "agent_type": "cc", "strategy": "least-loaded", "reason": "idle for 34s", "score": 0.92 },
"randomized": false,
"seed_used": 0,
"error_code": ""
}Dry-run (SendDryRunResult, send.go:75-88)
{
"would_send": [
{ "pane": 2, "agent": "cc", "prompt": "...", "prompt_preview": "...", "source": "file:task.md", "priority": 0 }
]
}Error matrix
| Condition | Message |
|---|---|
--pane + --panes | cannot use --pane and --panes together |
--project + session arg | cannot use --project with a specific session name |
No session + no --project | session name required (or use --project) |
--project with zero matches | no sessions found for project %q |
| Empty file or stdin with no prefix | prompt content is empty |
--dist-auto + --dry-run | Rejected as incompatible |
Scenario catalog
1. One-shot message to all Claude agents
ntm send myproject --cc "Summarize current blockers in three bullets."2. Target two specific panes with a file prompt
ntm send myproject --panes=2,3 --file prompts/refactor.md3. File-range context injection for code review
ntm send myproject --cc=opus \
-c internal/auth/jwt.go:40-120 \
-c internal/auth/middleware.go:1-60 \
--prefix "Context: we're hardening JWT validation." \
"Review and propose concrete fixes."4. Smart-routing a new task to the least-loaded agent
ntm send myproject --smart --route=least-loaded \
"Take the next ready authentication bead and implement."5. Distribute bv triage across idle agents
ntm send myproject --distribute --dist-strategy=dependency --dist-auto6. Scripted batch with deterministic ordering
ntm send myproject --batch prompts.txt --delay=30s --seed=42 --stop-on-error7. Cross-session broadcast to every label variant
ntm send --project myproject \
"Sync to main and report any conflicts you encounter."8. Non-interactive send from an automation loop
ntm --robot-send=myproject --panes=2 \
--msg="Tend pass ${PASS} at $(date +%H:%M)" \
--type=cc9. Template + variables + file
ntm send myproject --cc \
-t fix --var issue="nil deref" --file internal/auth/jwt.go10. Bypass CASS dedup for a retry
ntm send myproject --pane=2 --no-cass-check "Please retry; previous send was rejected."ntm serve — HTTP API Server
ntm serve exposes NTM functionality as a REST API with optional SSE streams and WebSocket. Canonical routes live under /api/v1/*; the legacy /api/* tree is kept for back-compat.
Source: /dp/ntm/internal/cli/serve.go, routes in /dp/ntm/internal/serve/server.go.
Contents
- Launch flags — host, port, auth, TLS
- Auth mode summary —
local,api_key,oidc,mtls - Canonical REST map (`/api/v1/*`)
- Introspection — health, version, capabilities, openapi
- Config
- Sessions + panes
- Agent lifecycle
- Jobs (idempotent async work)
- Robot adapters
- Attention streams — SSE, WebSocket
- Additional families — pipelines, mail, beads, CASS, etc
- OpenAPI
- SSE and WebSocket
- Scenario examples
---
Launch flags
All in serve.go:55-66.
| Flag | Default | Purpose |
|---|---|---|
--host | 127.0.0.1 | Bind host |
--port | serve.DefaultPort (check ntm config show) | Port |
--auth-mode | local | local / api_key / oidc / mtls |
--api-key | "" | Required with auth-mode=api_key |
--oidc-issuer | "" | e.g. https://accounts.google.com |
--oidc-audience | "" | JWT aud claim |
--oidc-jwks-url | "" | JWKS discovery URL |
--mtls-cert / --mtls-key | "" | Server TLS cert + key |
--mtls-ca | "" | Client CA bundle (requires client certs) |
--cors-allow-origin (repeatable) | localhost-only | CORS allowed origins |
--public-base-url | "" | External-facing URL (for generated links) |
auth-mode=mtls automatically selects HTTPS (serve.go:210-212).
Auth mode summary
- `local`: no auth — only binds
127.0.0.1by default. Suitable for localhost IPC. - `api_key`: clients present a static key via
Authorization: Bearer <key>orX-API-Key. - `oidc`: validates JWTs against
--oidc-jwks-url, checksaud/iss. Supports rotating keys. - `mtls`: requires both server TLS cert + client cert; the client cert is the credential.
Canonical REST map (/api/v1/*)
Registered in server.go:972+. Every mutating route is protected by RequirePermission middleware with per-endpoint permissions enumerated in serve/rbac.go.
Introspection
GET /api/v1/health GET /api/v1/version GET /api/v1/capabilities
GET /api/v1/security GET /api/v1/doctor GET /api/v1/openapi.json
GET /docs (Swagger UI, no auth)Config
GET /api/v1/config
PATCH /api/v1/configSessions + panes
GET /api/v1/sessions
POST /api/v1/sessions # kernel-mediated create
GET /api/v1/sessions/{id} # details
GET /api/v1/sessions/{id}/status
POST /api/v1/sessions/{id}/attach
POST /api/v1/sessions/{id}/zoom
POST /api/v1/sessions/{id}/view
GET /api/v1/sessions/{id}/events
GET /api/v1/sessions/{id}/agents
# Per-pane
GET /api/v1/sessions/{sessionId}/panes
GET /api/v1/sessions/{sessionId}/panes/{idx}
GET /api/v1/sessions/{sessionId}/panes/{idx}/output
GET /api/v1/sessions/{sessionId}/panes/{idx}/title
POST /api/v1/sessions/{sessionId}/panes/{idx}/input
POST /api/v1/sessions/{sessionId}/panes/{idx}/interrupt
POST /api/v1/sessions/{sessionId}/panes/{idx}/stream
DELETE /api/v1/sessions/{sessionId}/panes/{idx}/stream
PATCH /api/v1/sessions/{sessionId}/panes/{idx}/titleAgent lifecycle
GET /api/v1/sessions/{sessionId}/agents
POST /api/v1/sessions/{sessionId}/agents/spawn
POST /api/v1/sessions/{sessionId}/agents/send
POST /api/v1/sessions/{sessionId}/agents/interrupt
POST /api/v1/sessions/{sessionId}/agents/waitJobs (idempotent async work)
GET /api/v1/jobs POST /api/v1/jobs
GET /api/v1/jobs/{id} DELETE /api/v1/jobs/{id}Robot adapters (convenient single-shot endpoints)
Registered at server.go:1000-1011:
GET /api/v1/robot/status /health /snapshot /digest
/attention /dashboard /terse /triage
/plan /graph /activity /alertsAttention streams
GET /api/v1/attention/stream # SSE of live events
GET /api/v1/attention/events # paginated replay
GET /api/v1/attention/digest # aggregated summary
POST /api/v1/attention/items/{cursor}/state # mark handled
GET /api/v1/ws # WebSocketAdditional families
Registered via helpers in server.go:1049-1070:
registerPipelineRoutes→/api/v1/pipelines/...registerMailRoutes→/api/v1/mail/...registerBeadsRoutes→/api/v1/beads/...registerScannerRoutes→/api/v1/scanner/...registerCASSRoutes→/api/v1/cass/...registerCheckpointRoutes→/api/v1/checkpoints/...registerSafetyRoutes→/api/v1/safety/...registerAccountsRoutes→/api/v1/accounts/...
OpenAPI
- Live endpoint:
GET /api/v1/openapi.json(server.go:1088). - Swagger UI mounted at
/docsand/docs/without auth (server.go:1092-1093). - Static spec generator:
ntm openapi generate(openapi.go:126).
SSE and WebSocket
/api/v1/attention/streamlong-polls events; honor cursor replay via?since-cursor=N.- Legacy
/events(server.go:952) provided as back-compat. /api/v1/wsWebSocket for bidirectional control.
Cursor values are monotonic int64 per server; not portable across machines. On CURSOR_EXPIRED, the response includes a resync_command ready to paste.
Scenario examples
# Local-only, default port
ntm serve
# API-key protected on all interfaces
ntm serve --host=0.0.0.0 --port=7337 \
--auth-mode=api_key --api-key="$(openssl rand -hex 32)"
# mTLS for mutual auth (external consumers)
ntm serve --host=0.0.0.0 --port=7443 \
--auth-mode=mtls \
--mtls-cert=/etc/ntm/server.pem \
--mtls-key=/etc/ntm/server.key \
--mtls-ca=/etc/ntm/client-ca.pem
# OIDC federation
ntm serve --auth-mode=oidc \
--oidc-issuer=https://accounts.google.com \
--oidc-audience=ntm-prod \
--oidc-jwks-url=https://www.googleapis.com/oauth2/v3/certsRelated skills
FAQ
Is atm the same as ntm?
Yes. The docs state atm is byte-identical to ntm, with the same help, robot surface, flags, and exit codes, and they can be used interchangeably.
How do I know an NTM action is done?
The state transition must be visible in ntm --robot-snapshot and the attention feed; if the snapshot disagrees with the command, trust the snapshot.