Jam Documenation

The Jam CLI runs every Jam read and write from your terminal. Authenticate once, then pipe Jam data into shell scripts, CI jobs, or AI coding agents.

Install

  • macOS / Linux

  • Windows

Run the installer:

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:

Open PowerShell and run:

The script downloads the binary into %LOCALAPPDATA%\Programs\Jam, points a jam command at it, and adds it to your user PATH. Open a new terminal, then confirm the install:

Locked-down PowerShell. If your environment blocks irm | iex (a restricted execution policy is common on managed machines), install by hand: download the binary from https://native.jam.dev/download/windows/x64, save it as jam.exe in a folder such as %LOCALAPPDATA%\Programs\Jam\bin, then add that folder to your PATH under Settings → Edit environment variables for your account. Open a new terminal and run jam --version.

Creating video Jams needs ffmpeg

jam create jam extracts the poster image and probes the audio track with ffmpeg/ffprobe when you create a video Jam. Every other command works without it. Install ffmpeg if you plan to create video Jams from the CLI:

Or skip ffmpeg entirely by passing posterImagePath and screenDimensions explicitly on the create payload.

Authenticate

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

  • Browser OAuth

  • Personal access token

Run:

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.

Check auth status

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

Log out

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:

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.

CommandSummaryOutput
jam auth login [--token]Authenticate via browser OAuth or stdin PATSide effect
jam auth logoutRevoke tokens and clear credentialsSide effect
jam auth statusShow current user, workspace, and auth methodSingle
jam get jam <id>Fetch a Jam by IDSingle
jam get metadata <id>Structured jam.metadata() eventsPaginated
jam get console <id> [--level <lvl>]Console log eventsPaginated
jam get network <id> [--status <code>] [--method <verb>] [--host <h>] [--content-type <ct>]Network requestsPaginated
jam get events <id>Full unfiltered event streamPaginated
jam get transcript <id>WebVTT transcript for video JamsSingle
jam get intents <id>Cached intents summarySingle
jam get screenshots <id> --out <dir>Download image media into a directoryReceipt
jam get frames <id> [--at <ms>] [--from <ms> --to <ms> --count <n>] [--size <s>] [--out <dir>]Save still video frames as jpgsReceipt
jam list jams [...]List Jams in the workspacePaginated
jam list folders [...]List foldersPaginated
jam list members [...]List workspace membersPaginated
jam create jam '<json>'Create a screenshot or video JamReceipt
jam create comment <jamId> <body> [--at <ms>]Add a comment to a JamReceipt
jam create folder <name>Create a folderReceipt
jam create reaction <commentId> <emoji>React to a commentReceipt
jam update jam <id> [--title <title>] [--description <text>] [--folder <id>]Rename a Jam, rewrite its description, or move it to a folderReceipt
jam update folder <folder> --name <name>Rename a folderReceipt
jam update comment <commentId> <body>Rewrite a comment you authoredReceipt
jam delete jam <id> [-y]Archive a JamReceipt
jam delete comment <commentUid> [-y]Delete a comment you wroteReceipt
jam delete folder <id> [-y]Delete a folder and archive the Jams in itReceipt
jam delete reaction <commentId> <emoji>Take back your reaction on a commentReceipt
jam recording-links urlsList connected recording domainsPaginated
jam recording-links list [--limit <n>] [--after <cursor>]List the team’s recording linksPaginated
jam recording-links get <id>Fetch a recording link by public IDSingle
jam recording-links jams <id> [--limit <n>] [--after <cursor>]List Jams recorded through a linkPaginated
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 linkReceipt
jam recording-links update <id> [--name <n>] [--folder <f>] [--reference <r>] [--jam-title <t>] [--expires-at <iso>] [--metadata <json>]Edit a recording link’s settingsReceipt
jam recording-links revoke <id>Revoke a recording linkReceipt
jam recording-links verify <url> [--wait]Verify a connected recording domainReceipt
jam skills listList bundled agent skillsList
jam skills install [name] [--target <agent>] [--project]Install bundled skill into an agent’s directoryReceipt
jam skills path [--target <agent>] [--project]Show where skills would be installedSingle
jam skills sourcePrint the absolute path to the bundled SKILL.mdPath
jam agent-contextPrint the machine-readable command surface as JSONSingle
jam doctorShow CLI channel, URLs, version, and auth statusSingle
jam upgrade [--target <version>]Install the latest or pinned CLI binarySide effect
jam uninstall [-y]Remove the CLI and local dataSide effect

Read Jam data

Three commands return different views of the same Jam:

  • jam get jam <id> returns the top-level record (title, author, URL, dates, folder, and kind-specific data).
  • jam get metadata <id> returns structured metadata events emitted by the page via the jam.metadata() SDK call.
  • jam get intents <id> returns the structured summary (what the user was trying to do, observed issues, impact). It returns { "status": "not_requested", "value": null } when no summary is available. Treat that as absence, not an error.

Three commands return slices of the captured event stream:

  • jam get console <id> [--level error|warn|info|debug|log]
  • jam get network <id> [--status 5xx|<code>] [--method GET|POST|...] [--host <substring>] [--content-type <ct>]
  • jam get events <id> returns the unfiltered event stream.

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

  • jam get transcript <id> returns { status, vtt }. vtt is null while generation is pending.
  • jam get screenshots <id> --out <dir> downloads the Jam’s images into <dir>. For screenshot Jams that’s the primary and secondary screenshots, for video and replay Jams it’s the poster image.

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.

The mode depends on the flags:

  • Overview grid. No flags. Saves one grid image with frames evenly spaced across the whole video, each cell labeled with its timestamp. The frame count scales with duration (6 for short clips up to 16 for long ones). Best for orienting before you know which moment you care about.
  • Timestamps. --at <ms>, single or comma-separated. Saves one jpg per timestamp.
  • Window. --from <ms> --to <ms> --count <n>. Saves N evenly-spaced frames across the range.

--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

--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:

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:

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:

<body> is Markdown. --at pins the comment to a video timestamp in milliseconds. Rewrite a comment you left earlier:

The new body replaces the old one entirely, and you can only edit comments you authored. <commentId> is the id the create call returned; the share URL it printed works too. React to a comment, or take the reaction back:

Reactions are one of 🐛 💜 ✅ 👀 ❓ 👏 🔥 👍 — the same set the share page offers. Both commands are idempotent, and removing only clears your own reaction. Rename a Jam, rewrite its description, or move it to a folder:

Pass at least one flag. Only the fields you pass change. Pass an empty string to --folder to remove the Jam from its current folder. --description takes Markdown, and an @mention of a teammate’s email notifies them. Editing the title or description needs an Admin or Creator role; moving folders does not.

Create and rename folders

create folder returns { id, shortId, name }, so you can file a Jam into the new folder straight away with jam update jam <id> --folder <shortId>. Folder names are not unique — run jam list folders first if you mean to reuse an existing folder rather than add another one with the same name. update folder accepts a folder name, its short ID, or its UUID. Renaming leaves the folder’s Jams and short ID untouched.

Delete Jams, comments, and folders

Archiving a Jam takes it out of your lists and search but keeps the recording, so you can restore it from the dashboard. Deleting a folder archives every Jam inside it and reports how many in archivedJamCount. Deleting a comment is permanent and takes its attachments with it — only the comment’s author can do it. Each command asks you to confirm first. Pass -y (or --yes) to skip the prompt. Scripts and agents have no terminal to answer on, so they must pass -y; without it the command refuses rather than assuming an answer.

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.

create returns the link’s public ID and shareable URL. Every other command addresses the link by that public 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, while 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:

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

Paginated commands return:

Walk every page in a shell loop:

--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.

CodeNameWhen
0successCommand completed.
1genericUnclassified error.
2usageInvalid flag or argument.
3authNot authenticated or token rejected (HTTP 401 or 403).
4not_foundResource missing (HTTP 404).
5validationEnum or integer validation failed.
6serverUpstream returned 5xx.

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

Environment variables

VariablePurpose
JAM_TOKENBearer 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_TELEMETRYSet 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:

Install a specific version:

The CLI verifies the new binary’s checksum, runs a --version smoke test, and replaces the running binary atomically. On Windows the running .exe is locked, so each version installs into its own folder and jam upgrade re-points a jam command at the new one — a jam process you already have open keeps running the old version until you restart it. Remove the CLI and local data:

Skip the confirmation in non-interactive environments:

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. On Windows it removes the %LOCALAPPDATA%\Programs\Jam install folder and drops its entry from your user PATH.

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.

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.

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

Read the original on jam.dev ↗