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.
| 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 create folder <name> | Create a folder | Receipt |
jam create reaction <commentId> <emoji> | React to a comment | Receipt |
jam update jam <id> [--title <title>] [--description <text>] [--folder <id>] | Rename a Jam, rewrite its description, or move it to a folder | Receipt |
jam update folder <folder> --name <name> | Rename a folder | Receipt |
jam update comment <commentId> <body> | Rewrite a comment you authored | Receipt |
jam delete jam <id> [-y] | Archive a Jam | Receipt |
jam delete comment <commentUid> [-y] | Delete a comment you wrote | Receipt |
jam delete folder <id> [-y] | Delete a folder and archive the Jams in it | Receipt |
jam delete reaction <commentId> <emoji> | Take back your reaction on a comment | 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:
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 thejam.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 }.vttis 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.
| 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:
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.