Stealth previewdocs are early and rough. Please don't share publicly.
New Theory
DocsAPIModels
Reference

CLI Reference

Every command, flag, and environment variable in the newt CLI.

View as Markdown

The newt CLI is the primary tool for authenticating, inspecting your API key, listing models, and installing the onboarding skill. It is a global command — installed once, used in any directory.

newt [command] [flags]

Global flags

FlagDescription
-h, --helpPrint usage and exit. Zero network calls, zero writes.
-V, --versionPrint newt <version> and exit. Also available as newt version. Zero network calls, zero writes.

Help guard: newt --help and newt -h are safe to call anywhere — they make no network calls and write nothing to disk.


Commands

newt login

Authenticate with the New Theory console and save your API key.

newt login [--print]

What it does: Opens an interactive browser pairing flow. Prints a URL and an 8-character code formatted XXXX-XXXX, then polls the console until you complete the authorization. On success, writes your API key to ~/.nt/credentials.

First-line output: Starting authentication…

The pairing URL and code appear on subsequent lines (~line 6). The load-bearing fact (the code itself) is not on line 1 — this is a known constraint of the interactive auth flow.

Flags:

FlagDescription
--printRoute auth output to stderr; print only the bare API key to stdout. Does not write ~/.nt/credentials. Use to pipe the key into another tool or capture it in a script.

Exit codes:

CodeCondition
0Authentication succeeded
1Network failure, pairing expired, or other error

Network: POST to NT_CONSOLE_URL/api/cli/auth/start; polls NT_CONSOLE_URL/api/cli/auth/poll every 2 s for up to 10 minutes.

Writes: ~/.nt/credentials (mode 0600) on success — unless --print is set.

Help guard: newt login --help and newt login -h are safe — they print usage and exit 0 with zero network calls and zero writes. The guard shipped 2026-06-11 (commit 50004519, 44 tests).


newt logout

Remove your API key from disk.

newt logout [--json]

What it does: Deletes ~/.nt/credentials and removes ~/.nt/ if it is now empty. Safe to call when already logged out.

First-line output (human): Logged out. or Already logged out — no credentials file found.

Flags:

FlagDescription
--jsonEmit a JSON object instead of human-readable output. See output shape below.

--json output shape:

{
  "action": "removed" | "already_logged_out",
  "credentials_path": "/Users/<user>/.nt/credentials",
  "env_var_warning": true | false
}

env_var_warning is true when NT_API_KEY is set in the environment — your key remains active even after logout.

Exit codes:

CodeCondition
0Always (idempotent)

Network: None.

Writes: Deletes ~/.nt/credentials; removes ~/.nt/ if empty.

Help guard: newt logout --help and newt logout -h are safe — they print usage and exit 0 with zero network calls and zero writes. The guard shipped 2026-06-11 (commit 50004519, 44 tests).


newt models

List models available to your API key.

newt models [--json] [--ids]

What it does: Calls the New Theory registry and prints the model families your key has access to. Human output leads with a Key line naming which credential produced the listing (masked — never the full key) and its source (environment or credentials file), then the catalog grouped by base with its fine-tunes indented underneath. Raw uids are left out by default — the tag is the identity you scan by; --ids brings them back alongside each name.

First-line output (human): Key nt_••••••••<last8> (<source>) — the masked key identity and where it came from (environment or credentials file). The model catalog follows below it. If your key has no models, a message appears on stdout.

Example (default):

Key nt_••••••••5bde16a3 (environment)

ft-64cad948c4e9f09c-red-cube-bowl  [base: ft_base_so101_ft]
ft-64cad948c4e9f09c-svla-so101-pickplace-20260714213146  [base: ft_base_so101_ft]
ft-64cad948c4e9f09c-my-first-pickplace  [base: ft_base_so101_ft]

molmoact2
    so101

Example (--ids):

Key nt_••••••••5bde16a3 (environment)

ft-64cad948c4e9f09c-red-cube-bowl  ft_64cad948c4e9f09c_31ac23c75952  [base: ft_base_so101_ft]
ft-64cad948c4e9f09c-svla-so101-pickplace-20260714213146  ft_64cad948c4e9f09c_e4519e2a61d5  [base: ft_base_so101_ft]
ft-64cad948c4e9f09c-my-first-pickplace  ft_64cad948c4e9f09c_4527340bb316  [base: ft_base_so101_ft]

molmoact2  ft_base_molmoact2
    so101  ft_6341c5_d13da9

Flags:

FlagDescription
--jsonEmit the raw model array from the registry as JSON.
--idsShow each model's uid alongside its name.

--json output shape: An array of model objects. Shape is determined by the registry API.

Exit codes:

CodeCondition
0Models listed successfully
1No API key, authentication failure, or registry unreachable

Network: Registry call via newt.list_models(api_key).

Writes: None.

Help guard: newt models --help and newt models -h are safe — they print usage and exit 0 with zero network calls and zero writes. The guard shipped 2026-06-11 (commit 50004519, 44 tests).


newt status

Show your current authentication state and registry connectivity.

newt status [--json]

What it does: Reports your key source (environment variable or credentials file), any active URL overrides, and whether the registry is reachable. Prints an amber warning block if NT_BOOTSTRAP_URL or NT_INFERENCE_URL is set.

First-line output (human): Key source: env_var / Key source: credentials_file / Key source: none. Registry reachability appears on a subsequent line (~line 4).

Flags:

FlagDescription
--jsonEmit a JSON status object.

--json output shape:

{
  "key_source": "env_var" | "credentials_file" | "none",
  "overrides": {
    "NT_BOOTSTRAP_URL": null | "<url>",
    "NT_INFERENCE_URL": null | "<url>"
  },
  "registry_reachable": true | false,
  "latency_ms": <int> | null
}

Exit codes:

CodeCondition
0Status check completed without error
1No key, bad key, registry unreachable, or other error

Network: Registry call via newt.list_models(api_key). Skipped when no key is present.

Writes: None.

Help guard: newt status --help and newt status -h are safe — they print usage and exit 0 with zero network calls and zero writes. The guard shipped 2026-06-11 (commit 50004519, 44 tests).


newt run

Run one real inference against your model and print what came back.

newt run <tag> [--snapshot <name>] [--prompt <text>] [--json]

What it does: Loads a bundled recorded observation and calls your model once against prod via Robot(model=<tag>).infer(obs) — no hardware involved. Prints the resolved model, the round-trip latency, and the action-chunk shape. No robot is connected and nothing moves — this is a live inference against your model, not a robot demo, and the output says so plainly.

First-line output (human): The resolved model name.

Flags:

FlagDescription
--snapshot <name>Bundled observation to send. Options are red_cube (6-axis SO-101), cup_stacking (8-axis rig), and pour_coffee_beans (8-axis rig). Defaults to the snapshot matching your model's contract.
--prompt <text>Override the snapshot's recorded prompt.
--jsonEmit machine-readable JSON instead of human output.

--json output shape:

{
  "tag": "<tag>",
  "model": "<resolved model>",
  "snapshot": "<name>",
  "prompt": "<prompt sent>",
  "latency_ms": <float>,
  "total_ms": <float>,
  "retries": <int>,
  "action_chunk": {
    "shape": [<int>, ...],
    "axes": ["<axis>", ...]
  }
}

Exit codes:

CodeCondition
0Inference completed and result printed
1No model tag given, unknown --snapshot, no API key, or the call failed (authentication, model not found, model not deployable, registry unreachable, contract mismatch, server error, verifier unavailable, or protocol error)

Network: One inference call against prod via Robot(model=<tag>).infer(obs).

Writes: None.

Help guard: newt run --help and newt run -h are safe — they print usage and exit 0 with zero network calls and zero writes.


newt skill

Manage Claude Code skills provided by New Theory.

newt skill <subcommand> [-h | --help]

Subcommands:

SubcommandDescription
installInstall the newt-onboarding skill into .claude/skills/ in the current directory.

Help guard: newt skill --help and newt skill -h are safe — they print usage and exit 0 with zero network calls and zero writes.

Exit codes:

CodeCondition
0--help flag; or subcommand succeeded
1Unknown subcommand

Network: None.

Writes: None (for the skill dispatcher itself; install writes — see below).


newt skill install

Install the newt-onboarding skill into the current directory.

newt skill install [--json]

What it does: Writes .claude/skills/newt-onboarding/SKILL.md into the current working directory, creating the directory if needed. If the file already exists, it is updated in-place.

First-line output (human): Skill installed — <path> or Skill updated — <path>

Flags:

FlagDescription
--jsonEmit a JSON result object.

--json output shape:

{"ok": true, "path": "/path/to/.claude/skills/newt-onboarding/SKILL.md", "overwrite": false}

On error:

{"ok": false, "error": "<message>"}

Exit codes:

CodeCondition
0Skill written or updated successfully
1Read or write error

Network: None. The skill file is read from package resources, not fetched over the network.

Writes: .claude/skills/newt-onboarding/SKILL.md relative to the current working directory.

Help guard: newt skill install --help and newt skill install -h are safe — they print usage and exit 0 with zero network calls and zero writes. The guard shipped 2026-06-11 (commit 50004519, 44 tests).


newt record

Record NT episodes from a robot (or a simulated joint stream) — the keyboard capture frontend on newt.recording.Session.

newt record --task <text> [--dest <dir>] [--simulate | --source <module:factory>] [--target <n>] [--hz <n>] [--json]

What it does: Reads keystrokes and drives a recording session. SPACE starts and stops an episode; at the stop, ENTER keeps it, D discards, R redoes. A live frame counter and joint readout print during capture, and Ctrl+H is the kill — it torques off and leaves no partial episode directory. Every decision about episode format, atomicity, and the kill lives in newt.recording.Session; this command is only the skin.

Requires the recording extra: pip install "newt[recording]". Without it, the command stands down with the exact install line.

Flags:

FlagDescription
--task <text>Language task prompt recorded in every episode. Required.
--dest <dir>Episode output directory (default: ./episodes).
--simulateRecord from a fake joint stream — no hardware.
--source <module:factory>Load a developer RecordingSource, MODULE:FACTORY (e.g. mypkg.rig:make_source). Mutually exclusive with --simulate.
--target <n>Stop after N kept episodes.
--hz <n>State sample rate (default: 30).
--author <text> / --license <text>Provenance written to each episode.json.
--jsonAgent mode: line-delimited JSON events on stdout, line-delimited commands on stdin.

Exit codes:

CodeCondition
0Session ran and closed cleanly
130Ctrl+H kill (no partial episode left behind)
1Missing --task, no writable destination, or the recording extra is not installed

Network: None. Writes: episode_<id> directories under --dest.

Non-TTY without --json: stands down loudly — there is no keyboard to read.


newt finetune

Launch a training run on New Theory's GPUs with your API key, then watch it to completion.

newt finetune (--dataset <name> | --handle <job> | --list) [--status] [--steps <int>] [--name <slug>] [--fresh] [--json]

What it does: Sends your dataset to the New Theory console, which launches the training job server-side on New Theory's GPUs and returns a job handle. No infrastructure credential ever reaches your machine. The CLI then polls the run until it reaches a terminal state, printing the resulting model tag and report-card pointer on success, or the pipeline gate that failed. --handle re-attaches to a run you already launched (poll only, no new launch); --status prints that run's current state once and exits; --list prints your recent runs.

First-line output (human): Launched fine-tune on dataset '<name>'. followed by the job handle. When re-attaching, the first line is Watching <job> ….

Flags:

FlagDescription
--dataset <name>The staged dataset to fine-tune on. Launches a new run.
--handle <job>Re-attach to a run already launched, and poll it.
--statusWith --handle, print the run's current state once and exit instead of watching.
--listList your recent runs — handle, dataset, last recorded state, and when.
--steps <int>Advanced. Total training steps for this run, used with --dataset. A whole number between 2000 and 100000. Optional; omit it for the default.
--name <slug>Advanced. Name for the model this run produces, used with --dataset. A slug — lowercase letters, digits, and hyphens, 3–40 characters. Optional; omit it to name the model after the dataset.
--freshAdvanced. Ignore any existing checkpoint and retrain from scratch, used with --dataset. Optional; omit it to resume a completed run's finishing steps.
--jsonEmit machine-readable JSON instead of human output.

--steps bounds: A value outside 2000100000 is rejected with an error naming the bounds, never clamped into range. The value is recorded on the run. Leave --steps off for the default step count.

--name validation and collision: A name is validated as a slug — lowercase letters, digits, and hyphens, 3–40 characters — before any network call; anything else is rejected with an error, never reshaped to fit. If a model of that name already exists under your account, the launch is refused with a 409 naming the tag, before any training starts and before any GPU time is spent. Omit --name to name the model after its dataset (the default).

--fresh behavior: By default a re-run resumes a completed run's finishing steps instead of retraining. --fresh forces the full retrain from scratch, ignoring any checkpoint. Either way, the launch output names which path ran — resume or forced retrain — so the choice is never silent.

--json output shape (launch, --handle, --status):

{
  "job_handle": "<id>",
  "status": "succeeded" | "failed",
  "gate": null | "<failing gate>",
  "tag": null | "<model tag>",
  "report_card": null | "<pointer>",
  "steps": null | <int>,
  "name": null | "<slug>"
}

steps is the value set with --steps, or null when none was set (the server default is in force). name is the value set with --name, or null when none was set (the model is named after its dataset).

--list --json output shape:

[
  {
    "job_handle": "<id>",
    "dataset": "<name>",
    "status": "<last recorded state>",
    "created_at": "<ISO 8601>",
    "model_status": null | "pending" | "probed" | "live" | "dead"
  }
]

model_status is each run's model lifecycle state: null before the model registers, pending/probed while New Theory verifies the weights load, live once they do, and dead if they don't. A dead model is recoverable and stays listed.

Each run also carries a stable model identity (uid), assigned at launch and returned by the finetune status and jobs APIs. Bring it to the support table if you need help with a specific run.

Exit codes:

CodeCondition
0Run reached succeeded (or --status/--list completed)
1No API key, launch rejected, run failed, or the poll gave up
130You stopped watching with Ctrl-C (the run keeps going)

Network: POST /api/finetune to launch, GET /api/finetune/status to poll a handle, and GET /api/finetune/jobs for --list. The console holds the training credentials; the CLI only ever sees a job handle.

Writes: None.


newt promote

Keep a fine-tune's checkpoint band and serve it — the CLI twin of the console's promote button.

newt promote <job-handle> --band <token> [--json]

What it does: Registers one of a run's evaluated checkpoint bands as a served model, over the same route the console's promote button calls. The model is born pending; New Theory's admission chain runs a safety check and takes it live, usually within a few minutes. The output names the new model and points at newt models to watch it. Handle-only: list your runs with newt finetune --list.

First-line output (human): Promoted — your checkpoint is registered as a model. followed by the model tag and its pending status.

Flags:

FlagDescription
<job-handle>The run whose checkpoint to serve (required, first argument).
--band <token>Which checkpoint band to serve — the evaluated step, passed verbatim (e.g. 010000). Required.
--jsonEmit the route's JSON response body on stdout (the registered model, or the server's refusal detail).

Refusals: Every server refusal prints its plain reason verbatim — a band whose eval hasn't completed, a checkpoint whose location the training pipeline hasn't reported yet, or a run that already has a registered model (with that model's identity). A refusal is never collapsed into a generic failure.

Exit codes:

CodeCondition
0The band was registered (model born pending)
1No API key, a bad argument, or the server refused the promote

Network: POST /api/finetune/runs/<job-handle>/promote. Writes: None.


newt episodes

Inspect recorded episodes, and pull a staged dataset back down.

newt episodes validate <dir> [--json]
newt episodes pull <dataset> [--dest DIR] [--json]

validate calls newt.recording.validate on an episode_<id> directory and renders the verdict — a PASS/FAIL line plus one line per invariant check. Frontend only: the checks themselves are the library's. Requires the recording extra: pip install "newt[recording]".

pull downloads a staged dataset from your NT namespace. It fetches the owner-scoped download manifest (authed with your nt_ key), then downloads each object straight from storage over signed links — the bytes go GCS → your machine, never through the console. Files land under --dest (default ./<dataset>), recreating the dataset's relative layout. Progress is reported by files completed, never a percentage. Reruns are resumable: a file already present at the manifest's size is skipped, so an interrupted pull resumes cleanly.

Subcommands:

SubcommandDescription
validate <dir>Validate an episode_<id> directory.
pull <dataset>Download a staged dataset into --dest (default ./<dataset>).

Flags:

FlagDescription
--dest <dir>(pull) Where to write the dataset. Default: ./<dataset>.
--jsonEmit machine-readable JSON (validate: the verdict; pull: total_files, downloaded, skipped, bytes).

Exit codes:

CodeCondition
0Episode is valid / the pull completed
1A check failed, no argument given, an unknown subcommand, the recording extra is missing (validate), or the download failed / no key / dataset not found (pull)

Network: validate none; pull reads the console manifest + downloads from storage. Writes: validate none; pull writes files under --dest.

Help guard: newt episodes --help and newt episodes -h print usage and exit 0.


newt upgrade

newt upgrade [--print]

Upgrade the CLI to the latest version. When newt was installed as a uv tool (the documented install), this runs uv tool upgrade newt for you and streams its output. When the install method can't be confirmed, it prints the command instead of running it — it never guess-runs a package manager against the wrong environment.

Flags:

FlagDescription
--printPrint the upgrade command and exit — never runs it.

Passive update notice: After any command succeeds, the CLI may print one quiet line to stderr when a newer version is available — newt <latest> available — run 'newt upgrade'. It runs at most once a day, never blocks or slows a command, is silent on any network failure, and is skipped entirely under --json. Disable it with NEWT_NO_UPDATE_CHECK=1.

Exit codes:

CodeCondition
0The upgrade ran and succeeded, or the command was printed (unconfirmed install)
1The upgrade command failed, or uv was not found

Network: GET /api/cli/version (public, to source the command). Writes: ~/.nt/update-check.json (the once-a-day timestamp cache).


newt version

newt version

Prints newt <version> and exits. Identical to newt --version and newt -V.

Exit codeMeaning
0Always

Network: None. Writes: None.


Environment and credentials

API key resolution

The CLI and SDK resolve your API key in this order, stopping at the first hit:

  1. NT_API_KEY environment variable
  2. ~/.nt/credentials file

NT_API_KEY always wins over the credentials file.

~/.nt/credentials

Written by newt login. Deleted by newt logout.

PropertyValue
Path~/.nt/credentials
Mode0600
Formatapi_key = nt_<hex>

Environment variables

VariableScopeBehaviorDefault
NT_API_KEYCLI + SDKAPI key; takes precedence over ~/.nt/credentials
NT_CONSOLE_URLloginConsole URL for the pairing flowhttps://newtheory-console.vercel.app
NT_BOOTSTRAP_URLstatus, SDKOverride the registry discovery base URLhttps://nt-registry-production.up.railway.app
NT_INFERENCE_URLstatus, SDKOverride the inference endpoint; bypasses per-model routing via /v1/models
NT_CONSOLE_URLupgradeConsole URL the version check + newt upgrade readhttps://newtheory-console.vercel.app
NEWT_NO_UPDATE_CHECKCLISet to 1 to disable the passive once-a-day "update available" notice

Override warnings:

  • CLI (newt status): An amber Overrides active: block is printed when NT_BOOTSTRAP_URL or NT_INFERENCE_URL is set, showing the active values.
  • SDK (import newt): EnvOverrideWarning is emitted via warnings.warn() when NT_INFERENCE_URL is set. Warning text: NT_INFERENCE_URL is set to <url> — this overrides dynamic /v1/models discovery for ALL models. Unset it to use per-model cross-app routing.

Override variables are intended for development and testing against local or staging infrastructure. Unset them before running production workloads.


On this page