CLI - Jam Documenation

Install

Run the installer:

curl -fsSL https://native.jam.dev/install | bash

The script detects your OS and architecture, downloads the matching binary into ~/.local/bin/jam, and adds that directory to your shell PATH. Open a new shell or source your rc file, then confirm the install:

jam --version

Authenticate

Every read and write command needs an authenticated session. The CLI supports two modes.

On WSL, use a personal access token. The browser login flow expects your browser and the CLI to share the same local address, which WSL splits between Windows and Linux, so token auth is the reliable path for now.

Run:

jam auth login

The CLI opens an OAuth flow in your default browser, exchanges the authorization code for access and refresh tokens, and stores them in ~/.config/jam/credentials.json.

Use a personal access token for headless environments, CI jobs, or WSL:

echo "jam_pat_abc123..." | jam auth login --token

Create PATs in Settings → MCP. See Personal Access Tokens for scopes, expiration, and rotation guidance.

Check auth status

jam auth status

Prints the authenticated user, workspace, and auth method. Pass --json to consume the same data from a script.

Log out

jam auth logout

Revokes tokens server-side where supported and clears the local credential store.

Where credentials live

The CLI stores credentials at ~/.config/jam/credentials.json with 0600 permissions, the same model used by gh, aws, gcloud, and other major developer CLIs. Bypass the credential file entirely by setting JAM_TOKEN in your shell. The CLI uses the env-var token for the lifetime of the process and never writes it to disk.

First steps

After install and auth, run this short loop to confirm the CLI talks to your workspace:

jam auth status
jam list jams --limit 5
jam get jam <id>

auth status confirms the CLI can read the stored token. list jams returns a page of Jams from your workspace. get jam walks a single Jam by ID. From there, scan the command reference for the command you need.

Command reference

Every command supports --help. The machine-readable surface (argument types, flags, output shapes) lives at jam agent-context.

Command Summary Output
jam auth login [--token] Authenticate via browser OAuth or stdin PAT Side effect
jam auth logout Revoke tokens and clear credentials Side effect
jam auth status Show current user, workspace, and auth method Single
jam get jam <id> Fetch a Jam by ID Single
jam get metadata <id> Structured jam.metadata() events Paginated
jam get console <id> [--level <lvl>] Console log events Paginated
jam get network <id> [--status <code>] [--method <verb>] [--host <h>] [--content-type <ct>] Network requests Paginated
jam get events <id> Full unfiltered event stream Paginated
jam get transcript <id> WebVTT transcript for video Jams Single
jam get intents <id> Cached intents summary Single
jam get screenshots <id> --out <dir> Download image media into a directory Receipt
jam get frames <id> [--at <ms>] [--from <ms> --to <ms> --count <n>] [--size <s>] [--out <dir>] Save still video frames as jpgs Receipt
jam list jams [...] List Jams in the workspace Paginated
jam list folders [...] List folders Paginated
jam list members [...] List workspace members Paginated
jam create jam '<json>' Create a screenshot or video Jam Receipt
jam create comment <jamId> <body> [--at <ms>] Add a comment to a Jam Receipt
jam update jam <id> --folder <id> Move a Jam to a folder Receipt
jam recording-links urls List connected recording domains Paginated
jam recording-links list [--limit <n>] [--after <cursor>] List the team’s recording links Paginated
jam recording-links get <id> Fetch a recording link by public ID Single
jam recording-links jams <id> [--limit <n>] [--after <cursor>] List Jams recorded through a link Paginated
jam recording-links create --name <name> [--recording-url-id <id>] [--folder <f>] [--jam-title <t>] [--reference <r>] [--expires-at <iso>] [--metadata <json>] Create a reusable recording link Receipt
jam recording-links update <id> [--name <n>] [--folder <f>] [--reference <r>] [--jam-title <t>] [--expires-at <iso>] [--metadata <json>] Edit a recording link’s settings Receipt
jam recording-links revoke <id> Revoke a recording link Receipt
jam recording-links verify <url> [--wait] Verify a connected recording domain Receipt
jam skills list List bundled agent skills List
jam skills install [name] [--target <agent>] [--project] Install bundled skill into an agent’s directory Receipt
jam skills path [--target <agent>] [--project] Show where skills would be installed Single
jam skills source Print the absolute path to the bundled SKILL.md Path
jam agent-context Print the machine-readable command surface as JSON Single
jam doctor Show CLI channel, URLs, version, and auth status Single
jam upgrade [--target <version>] Install the latest or pinned CLI binary Side effect
jam uninstall [-y] Remove the CLI and local data Side effect

Read Jam data

Three commands return different views of the same Jam:

Three commands return slices of the captured event stream:

All three accept --limit (default 50, max 500) and --after <cursor> for pagination. Two media reads:

Video frames

jam get frames <id> saves still frames from a video Jam as jpgs, so you or an agent can see what was on screen instead of only reading the transcript. Frames land in --out (default ./jam-frames/<id>/) and the command prints the saved paths as JSON.

# overview grid: no flags, one labeled image spanning the whole video
jam get frames <id>

# a single moment, or several explicit timestamps
jam get frames <id> --at 7000
jam get frames <id> --at 4000,7000,9000

# evenly-spaced frames across a window
jam get frames <id> --from 2000 --to 10000 --count 5

The mode depends on the flags:

--size accepts small, medium, or large (default medium) and sets the frame height. When frames aren’t available (a screenshot Jam, or a video not hosted on Cloudflare Stream), the command prints the reason to stderr and exits non-zero.

List workspace collections

jam list jams --query "checkout" --type video --limit 20
jam list folders --order-by createdAt
jam list members --query "@example.com"

--type accepts screenshot, video, replay, or unknown. --order-by accepts createdAt or updatedAt. --limit defaults to 20 (max 500). All three list commands accept --after <cursor> for pagination. See jam list jams --help for all filters.

Create and update Jams

Create a screenshot Jam from a JSON payload:

jam create jam '{
  "url": "https://example.com/checkout",
  "title": "Checkout button is broken",
  "screenshotPath": "./checkout.png",
  "screenDimensions": { "width": 1440, "height": 900 }
}'

The payload requires url, screenDimensions, and exactly one screenshot source (screenshotPath, screenshotDataUrl, or screenshotMediaId). To create a video Jam, set kind to "video" and provide videoPath. The poster image is generated downstream if you omit posterImagePath. To avoid escaping a large JSON blob on the command line, read the payload from a file with an @ prefix, or pipe it in on stdin:

jam create jam @jam.json        # read from a file
cat jam.json | jam create jam   # pipe via stdin

Run jam create jam --help for both payload shapes, or jam agent-context for the full machine-readable JSON Schema (under create.jam, on the source arg). Add a comment to a Jam:

jam create comment <jamId> "Logs at 00:42 show a 500 on /checkout." --at 42000

<body> is Markdown. --at pins the comment to a video timestamp in milliseconds. Move a Jam to a folder:

jam update jam <id> --folder <folder-id>
jam update jam <id> --folder ""

Pass an empty string to remove the Jam from its current folder.

Recording links

A recording link is a shareable URL that collects Jams: anyone who opens it can record and submit a Jam back to your workspace. A link captures console and network logs only when it records from a connected recording domain (a “recording URL”), so list your connected domains first and pass one when you create the link. See Recording Links for the dashboard workflow.

jam recording-links urls
jam recording-links create --name "Support intake" --recording-url-id <url-id> --folder "Bug reports"

create returns the link’s public ID and shareable URL. Every other command addresses the link by that public ID.

jam recording-links jams <id> --limit 50
jam recording-links update <id> --name "Q3 support intake"
jam recording-links revoke <id>

jams lists the Jams recorded through a link. update edits its settings (name, folder, reference, Jam title, expiration, metadata). revoke soft-deletes the link so it stops accepting new recordings; the Jams it already collected stay. To connect a new domain, run jam recording-links verify <url> and open the returned link in a browser where Jam is live on that domain.

Output mode

The CLI pretty-prints when stdout is a TTY and emits compact JSON when output is piped. Force JSON output in any context with the top-level --json flag:

jam --json auth status
jam --json get jam <id> | jq '.title'

Machine consumers (agents, scripts) should pass --json so output stays parseable regardless of where the command runs.

Pagination

Paginated commands return:

{
  "items": [...],
  "next_cursor": "<opaque>" | null,
  "truncated": true | false,
  "hint": "Use --after=<cursor> to fetch the next page."
}

Walk every page in a shell loop:

cursor=""
while :; do
  page=$(jam --json get console "$ID" --limit 500 ${cursor:+--after "$cursor"})
  echo "$page" | jq -c '.items[]'
  cursor=$(echo "$page" | jq -r '.next_cursor // empty')
  [ -z "$cursor" ] && break
done

--limit caps each page at 500. Defaults: 50 for get commands, 20 for list commands.

Exit codes

The exit code is authoritative. Branch on it, not on stderr parsing.

Code Name When
0 success Command completed.
1 generic Unclassified error.
2 usage Invalid flag or argument.
3 auth Not authenticated or token rejected (HTTP 401 or 403).
4 not_found Resource missing (HTTP 404).
5 validation Enum or integer validation failed.
6 server Upstream returned 5xx.

In JSON mode, errors print to stderr as { "error":{"code":"...","message":"..."}}. valid_values is included on validation errors when applicable.

Environment variables

Variable Purpose
JAM_TOKEN Bearer token used in place of stored credentials. The CLI uses it for the lifetime of the process and never writes it to disk.
JAM_NO_TELEMETRY Set to 1 to disable all CLI telemetry: lifecycle events (install, update, uninstall) plus per-command usage and error reporting.

Update and uninstall

Install the latest CLI binary:

jam upgrade

Install a specific version:

jam upgrade --target 0.2.0

The CLI verifies the new binary’s checksum, runs a --version smoke test, and replaces the running binary atomically. Remove the CLI and local data:

jam uninstall

Skip the confirmation in non-interactive environments:

jam uninstall --yes

Uninstall removes ~/.local/bin/jam, the ~/.local/state/jam/ state directory, your stored credentials in ~/.config/jam/, and the PATH marker the installer added to your shell rc files.

jam uninstall is irreversible. Re-install via the curl one-liner to recover.

Use the CLI with AI coding agents

The CLI ships two surfaces for AI coding agents: a bundled skill and a JSON command catalog.

Bundled skills

jam skills install writes the bundled SKILL.md into the location your agent runtime expects (Claude Code, Cursor, Codex, OpenCode). The CLI auto-detects the runtime via environment variables, then falls back to project-level marker directories before defaulting to Claude.

jam skills install                  # auto-detect target, user-global install
jam skills install --project        # install into the current repo
jam skills install --target cursor  # explicit target
jam skills path                     # preview destination without writing
jam skills list                     # list bundled skills

The skill teaches your agent which command to reach for at each step (read Jam, filter errors, leave a comment) and how to interpret the structured output.

Machine-readable command surface

jam agent-context prints the command surface as JSON: argument types, flag enums, default limits, and output shapes. Pair it with --json on every read or write call to keep tool wrappers thin.

jam agent-context | jq '.commands["get.jam"]'

The shape is locked by a snapshot test, so the JSON stays stable across releases inside the same schema_version.