> ## Documentation Index
> Fetch the complete documentation index at: https://jam.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Reference

> Every Jam CLI command, flag, exit code, and environment variable. Install, authenticate, read and write Jams, record, and manage recording links.

Every command the Jam CLI ships, with its flags and output shape. For the agent workflow and quickstart, start at [CLI](/docs/cli).

<Info>
  The CLI runs on macOS, Linux, and Windows (x64 and arm64). Windows publishes an x64 binary, and Windows on ARM runs it under the built-in x64 emulation. You can also run the CLI under Windows Subsystem for Linux (WSL). On WSL, authenticate with a personal access token (see [Authenticate](#authenticate)).
</Info>

## Install

<Tabs>
  <Tab title="macOS / Linux">
    Run the installer:

    ```bash theme={"theme":"css-variables"}
    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:

    ```bash theme={"theme":"css-variables"}
    jam --version
    ```
  </Tab>

  <Tab title="Windows">
    Open PowerShell and run:

    ```powershell theme={"theme":"css-variables"}
    powershell -c "irm https://native.jam.dev/install.ps1 | iex"
    ```

    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:

    ```powershell theme={"theme":"css-variables"}
    jam --version
    ```

    <Note>
      Only an x64 binary is published. Windows on ARM runs it under the built-in x64 emulation, so the same one-liner works with no extra steps.
    </Note>

    **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`](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`.
  </Tab>
</Tabs>

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

<CodeGroup>
  ```bash macOS theme={"theme":"css-variables"}
  brew install ffmpeg
  ```

  ```bash Linux theme={"theme":"css-variables"}
  sudo apt install ffmpeg
  ```

  ```powershell Windows theme={"theme":"css-variables"}
  winget install ffmpeg
  ```
</CodeGroup>

Or skip ffmpeg entirely by passing `posterImagePath`, `durationMs`, `width`, `height`, and `micEnabled` explicitly on the create payload.

### Recording with jam record

`jam record` captures a window or the whole desktop and uploads it as a video Jam. Nothing has to be a browser. A desktop app, a terminal, a simulator, an editor: they all record the same way. Use it from a script, a CI job, or a coding agent that needs to show its work. The Chrome extension remains the capture path in the browser. `jam doctor` reports recording readiness and names any missing packages.

<Info>
  Screen capture commands under `jam record` run on macOS and Linux. On Windows these commands exit with a message that the platform is unsupported. Everything else the CLI does still works there.
</Info>

<CodeGroup>
  ```bash macOS theme={"theme":"css-variables"}
  # Captures through the embedded ScreenCaptureKit helper. Grant Screen Recording
  # permission to your terminal app in System Settings → Privacy & Security.
  jam doctor
  ```

  ```bash Linux theme={"theme":"css-variables"}
  # X11 only (Wayland is not supported). Window capture is a screen-region grab,
  # so an overlapping window appears in the recording.
  sudo apt-get install -y ffmpeg wmctrl x11-xserver-utils x11-utils util-linux
  jam doctor
  ```

  ```powershell Windows theme={"theme":"css-variables"}
  # `jam record` is not supported on Windows. Use macOS or Linux.
  jam doctor
  ```
</CodeGroup>

On macOS, a window is captured on its own (it can sit behind other windows). The CLI draws a red outline around the recorded window on your screen, and `--no-outline` hides it. That outline is not in the video. On Linux, keep the target window uncovered.

Add `--speedup` to compress spans where nothing on screen changes. It is off by default, works on macOS and Linux, and reads only the video's pixels, so a blinking caret or a spinner keeps its span at normal speed.

Add `--cdp` to fill the Jam's Console and Network panels from a Chromium-based browser while you record it. It takes a debug port (`9222`), a `ws://` DevTools URL, or `auto` for a Chrome 144 or later that allows local debugging under `chrome://inspect/#remote-debugging`. The receipt then carries a `cdpProxy` address, and a driver pointed at that address instead of at the browser has its clicks and typing recorded as user actions. See [Record an agent's browser](/docs/cli-record-browser) for the tools this works with.

## Authenticate

Every command that reads or writes workspace data needs an authenticated session. The CLI supports two modes.

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

<Tabs>
  <Tab title="Browser OAuth">
    Run:

    ```bash theme={"theme":"css-variables"}
    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`.
  </Tab>

  <Tab title="Personal access token">
    Use a personal access token for headless environments, CI jobs, or WSL:

    ```bash theme={"theme":"css-variables"}
    echo "jam_pat_abc123..." | jam auth login --token
    ```

    Create PATs in [**Settings → MCP**](https://jam.dev/s/settings/mcp). See [Personal Access Tokens](/docs/personal-access-tokens) for scopes, expiration, and rotation guidance.
  </Tab>
</Tabs>

### Check auth status

```bash theme={"theme":"css-variables"}
jam auth status
```

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

### Log out

```bash theme={"theme":"css-variables"}
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:

```bash theme={"theme":"css-variables"}
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, [set up your coding agent](/docs/cli#quickstart), or scan the [commands table](#commands) for the command you need.

## Set up your coding agent

`jam skills install` writes the bundled `jam-cli` and `jam-proof` skills where your agent reads them. The workflow, and what each skill teaches, is on the [CLI](/docs/cli) page.

```bash theme={"theme":"css-variables"}
jam skills list                    # see the catalog
jam skills install jam-cli         # install one skill
jam skills install --project       # install into this repo instead of your home directory
jam skills path                    # preview the destination without writing
```

The CLI detects the runtime from environment variables, falls back to project marker directories, and defaults to Claude Code. Name one with `--target`.

## Commands

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 <levels>]`                                                                                                                                                                                                          | Console log events                                                               | Paginated   |
| `jam get network <id> [--status <codes>] [--method <verbs>] [--host <hosts>] [--content-type <types>]`                                                                                                                                             | Network requests                                                                 | Paginated   |
| `jam get events <id>`                                                                                                                                                                                                                              | Full unfiltered event stream                                                     | Paginated   |
| `jam get transcript <id>`                                                                                                                                                                                                                          | WebVTT transcript for video Jams                                                 | Single      |
| `jam get chapters <id>`                                                                                                                                                                                                                            | AI-generated chapter markers 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> [--overview] [--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>' [--speedup] [--folder <folder>]`                                                                                                                                                                                          | 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 <folder>]`                                                                                                                                                                 | 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]`                                                                                                                                                                                                                         | Delete a Jam                                                                     | Receipt     |
| `jam delete comment <commentUid> [-y]`                                                                                                                                                                                                             | Delete a comment you wrote                                                       | Receipt     |
| `jam delete folder <id> [-y]`                                                                                                                                                                                                                      | Delete a folder and the Jams in it                                               | Receipt     |
| `jam delete reaction <commentId> <emoji>`                                                                                                                                                                                                          | Take back your reaction on a comment                                             | Receipt     |
| `jam record windows`                                                                                                                                                                                                                               | List the windows available to record                                             | List        |
| `jam record displays`                                                                                                                                                                                                                              | List the displays available to record                                            | List        |
| `jam record start [--window-id <id>] [--app <name>] [--bundle-id <bundleId>] [--pid <pid>] [--display <id>] [--url <url>] [--title <title>] [--description <text>] [--folder <folderId>] [--no-outline] [--speedup] [--cdp <endpoint>]`            | Start recording in the background and return at once                             | Receipt     |
| `jam record status`                                                                                                                                                                                                                                | Show a JSON snapshot of the current recording                                    | Single      |
| `jam record stop`                                                                                                                                                                                                                                  | Stop the background recording and upload it as a Jam                             | Receipt     |
| `jam record cancel`                                                                                                                                                                                                                                | Stop the background recording and discard it                                     | Receipt     |
| `jam record run [command...] [--window-id <id>] [--app <name>] [--bundle-id <bundleId>] [--pid <pid>] [--display <id>] [--url <url>] [--title <title>] [--description <text>] [--folder <folderId>] [--no-outline] [--speedup] [--cdp <endpoint>]` | Record a window or the desktop into a Jam                                        | 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 delete <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] [--dir <dir>]`                                                                                                                                                                           | Install bundled skill into an agent's directory, or into `<dir>/<name>/SKILL.md` | 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, auth status, and recording readiness            | Text        |
| `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 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.

Every filter accepts a comma-separated list, for example `--level error,warn` or `--status 401,5xx`.

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

Three media reads:

* `jam get transcript <id>` returns `{ status, vtt }`. `vtt` is null while generation is pending.
* `jam get chapters <id>` returns `{ status, chapters, language }`. `chapters` is null unless `status` is `ready`, and `status` is `not_requested` when generation was never queued. Chapters are text only, so to see what one looked like on screen run `jam get frames <id> --at <ms>` at a timestamp inside its span.
* `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 Jams it's the poster image, and for Instant Replay Jams it's the captured screenshot.

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

```bash theme={"theme":"css-variables"}
# overview grid: one labeled image spanning the whole video
jam get frames <id> --overview

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

* **Overview grid.** `--overview`. 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

```bash theme={"theme":"css-variables"}
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:

```bash theme={"theme":"css-variables"}
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`. If you omit `posterImagePath`, the CLI extracts the video's first frame locally with ffmpeg.

A video Jam can also carry the console logs and network requests from a Playwright test run. Point `playwrightTracePath` at the `trace.zip` Playwright wrote, and the CLI parses it and attaches the events to the Jam, synced to the video timeline:

```bash theme={"theme":"css-variables"}
jam create jam '{
  "kind": "video",
  "url": "https://example.com/checkout",
  "videoPath": "./test-results/checkout/video.webm",
  "playwrightTracePath": "./test-results/checkout/trace.zip",
  "screenDimensions": { "width": 1280, "height": 720 }
}'
```

The same trace can drive an automatic edit to the video. Add `--speedup` to compress idle spans where nothing on screen changes. It is off by default and requires `playwrightTracePath`. Start tracing with `screenshots: true`: the CLI lines the trace up with the video through its screencast frames. When the trace cannot be read, the CLI uploads the video unedited.

Headers and request bodies are redacted before upload, the same way the browser extension redacts them during a recording. If the trace cannot be read, the CLI reports it and still creates the Jam, without events. The create payload has no HAR field. Attach console and network events from a Playwright `trace.zip` with `playwrightTracePath`.

The trace also records every `fill`, `type`, `pressSequentially` and `insertText` the test ran. The Jam shows each of those as a typing action, with the text it typed. A password field, a one-time-code or credit-card field, and any field whose name, id, autocomplete or placeholder reads as sensitive show `***` instead. So does text the CLI cannot attribute to a field, which includes everything typed through `keyboard.insertText`.

`--folder` files the new Jam on creation. It takes a folder ID or a folder name, so `--folder "Bug reports"` works without a lookup. Leave it off and move the Jam later with `jam update jam <id> --folder <folder>`.

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:

```bash theme={"theme":"css-variables"}
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).

Comment on a Jam, then keep that comment current as you learn more instead of posting a second one:

```bash theme={"theme":"css-variables"}
jam create comment <jamId> "Looking into the 500 on /checkout." --at 42000
jam update comment <commentId> "The 500 on /checkout was an expired Stripe key. Fixed in #1423."
```

`<body>` is Markdown. `--at` pins the comment to a video timestamp in milliseconds, and only `create` accepts it. An edit replaces the body entirely, keeps the timestamp the comment was created with, and works only on comments you authored. `<commentId>` is the `id` the create call returned, and the share URL it printed works too.

React to a comment, or take the reaction back:

```bash theme={"theme":"css-variables"}
jam create reaction <commentId> "👀"
jam delete reaction <commentId> "👀"
```

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:

```bash theme={"theme":"css-variables"}
jam update jam <id> --title "Checkout fails on Safari"
jam update jam <id> --description "Repro steps are in the console log."
jam update jam <id> --folder <folder>
jam update jam <id> --folder ""
```

Pass at least one flag. Only the fields you pass change. `--folder` takes a folder name, its short ID, or its UUID. Pass an empty string 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

```bash theme={"theme":"css-variables"}
jam create folder "Checkout bugs"
jam update folder checkout-bugs --name "Checkout"
```

`create folder` returns `{ id, shortId, name }`, so you can file a Jam into the new folder straight away with `jam update jam <id> --folder <folder>`. 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

```bash theme={"theme":"css-variables"}
jam delete jam <id>
jam delete comment <commentUid>
jam delete folder <folder-id>
```

Deleting a Jam takes it out of your lists and search, and there is no way to restore it. The dashboard has no trash or archive view. Deleting a folder deletes every Jam inside it and reports how many in `archivedJamCount`. Deleting a comment is permanent and takes its attachments with it, and 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.

### Record a window or the desktop

`jam record` is the CLI capture path. It is not [Recording Links](/docs/recording-links), which are shareable URLs that collect Jams from a browser. `jam record` captures pixels from a window or display. Console logs and network requests come along only when you record a Chromium-based browser and pass `--cdp`, covered in [Record an agent's browser](/docs/cli-record-browser).

The common use is proof of work. Wrap a test run, a script, or the steps an agent drives, and the Jam link becomes the evidence: what was on screen, in order, at the time it happened. Attach it to the pull request instead of describing the result in words. See the [CLI](/docs/cli) page for the agent side of that workflow.

List targets first. Window IDs change when a window is reopened, so re-run `jam record windows` before each recording:

```bash theme={"theme":"css-variables"}
jam record windows
jam record displays
```

Then record. With no selector flag, `jam record run` records the whole primary display. Name a window with exactly one of `--window-id`, `--app`, `--bundle-id`, or `--pid`. Name a display with `--display`. Do not combine those flags.

`--app` and `--bundle-id` match case-insensitively but exactly. If more than one window matches, the command fails and lists candidate IDs. Prefer `--window-id` from a fresh `jam record windows` when an app has several windows open.

On macOS, a red outline marks the recorded window or display on screen while recording runs. The outline is not part of the video. Pass `--no-outline` to hide it. Linux draws no outline, and the flag is accepted there without effect.

`--pid` selects the window owned by a process you launched yourself. It waits up to five seconds for that process to open a window, so a script can start a browser and record it without listing windows first. On macOS a window records whole even when part of it hangs off the display.

`--url` sets the page URL the Jam shows, so the share page names the page under test. Without it the Jam shows no page URL.

```bash theme={"theme":"css-variables"}
jam record run -- sleep 30
jam record run --app "Google Chrome" --title "Checkout 500s" -- bun run e2e/checkout.ts
jam --json record run --window-id 4213 --title "Checkout 500s"
jam --json record run --pid $BROWSER_PID --url https://app.example.com/checkout --title "Checkout completes"
```

Put the wrapped command after `--` so its own flags reach it instead of `jam`. Command output goes to stderr. Stdout carries only the Jam receipt:

```json theme={"theme":"css-variables"}
{
  "id": "<jam-id>",
  "url": "https://jam.dev/c/<jam-id>",
  "durationMs": 5080,
  "width": 1440,
  "height": 900,
  "target": { "windowId": 4213, "app": "Google Chrome" }
}
```

`target` is `{ "displayId": <id> }` for a display recording. The size is the video's pixel size.

The wrapped form exits with the command's code when the command fails, and with the upload's code otherwise. A failing test still produces a Jam and still fails the pipeline. If upload fails, the mp4 is kept and its path is printed to stderr.

With no wrapped command, recording runs until you stop it. Press Ctrl-C at a terminal, or send SIGINT (`kill -INT <pid>`) from a script that started the process in the background. Both forms upload and print the same receipt. The no-command form exits 0. A wrapped command killed by SIGINT exits 130 after the upload.

`--url`, `--title`, `--description`, and `--folder` set those fields at creation. `--folder` takes a folder ID. Leave them off and set the title or description later with `jam update jam <id>`.

#### How to start and stop a screen recording from separate commands

To record a screen without wrapping a command, run `jam record start`, do the steps, then run `jam record stop`. `start` returns as soon as the first frame is captured. `stop` uploads the video and prints the Jam link. Use this when the steps run in the same process that calls the CLI, for example a coding agent that drives the app with its own browser tool, or a shell script whose steps are separate commands.

```bash theme={"theme":"css-variables"}
jam record start --app "Google Chrome" --title "Checkout completes"
jam record status
# drive the app: open the page, add to cart, pay
jam record stop
```

`start` prints the session ID, and with `--cdp` the browser it tapped and the proxy address to hand a driver:

```json theme={"theme":"css-variables"}
{
  "session": "<session-id>",
  "cdpEndpoint": "ws://127.0.0.1:9222/devtools/browser/<id>",
  "cdpProxy": "http://127.0.0.1:<port>"
}
```

Without `--cdp` the receipt is `{ "session": "<id>" }` alone. `stop` prints the same receipt as `run`. One recording runs at a time; a second `start` fails until `stop` or `cancel`. If `stop` cannot upload, the recording is kept and the next `stop` retries it.

To throw a recording away, run `jam record cancel`. It stops the recording and deletes it. Nothing is uploaded. Use it when the steps went wrong and a Jam of them would only mislead.

| Situation                                               | Command                                    |
| ------------------------------------------------------- | ------------------------------------------ |
| A test or script runs the steps                         | `jam record run -- <command>`              |
| The caller runs the steps itself, between two CLI calls | `jam record start`, then `jam record stop` |
| The current recording needs to be checked               | `jam record status`                        |
| The recording should not become a Jam                   | `jam record cancel`                        |

#### Recording status

`jam record status` prints a JSON snapshot without changing the recording. It requires no login and works when a CLI update is required. It does not start or stop a recording, upload a Jam, or remove local recording files.

With no current recording session, the output is:

```json theme={"theme":"css-variables"}
{ "status": "idle" }
```

| `status`   | Meaning                                                                                    |
| ---------- | ------------------------------------------------------------------------------------------ |
| `idle`     | No current recording session. A start command may still be resolving its target.           |
| `starting` | The recorder is starting and has not reported that recording is ready.                     |
| `active`   | The recorder is recording or finalizing the video. Status cannot distinguish those stages. |
| `ready`    | A local recording result is available. An upload may already be in progress.               |
| `stale`    | The recorder exited without a usable result.                                               |

Every successful response includes `status`. All states except `idle` include the session ID (`session`), recorder process ID (`pid`), and local directory (`workdir`).

The `active` and `ready` states also include `startedAt`, the recording start time in epoch milliseconds, and `target`. The target is `{ "kind": "window", "windowId": <id>, "app": "<name>" }` or `{ "kind": "display", "displayId": <id> }`.

A `ready` response includes `durationMs`. A `stale` response includes `startedAt` and `target` when valid recording metadata is available.

The command exits with code `0` for all five states. Scripts must read `status` to distinguish them. Unreadable, corrupt, or repeatedly changing recording state produces an error and a nonzero exit code.

### 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](/docs/recording-links) for the dashboard workflow.

```bash theme={"theme":"css-variables"}
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.

```bash theme={"theme":"css-variables"}
jam recording-links jams <id> --limit 50
jam recording-links update <id> --name "Q3 support intake"
jam recording-links delete <id>
```

`jams` lists the Jams recorded through a link. `update` edits its settings (name, folder, reference, Jam title, expiration, metadata). `delete` 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:

```bash theme={"theme":"css-variables"}
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. Exception: `jam doctor` always prints a human-readable report.

## Pagination

Paginated commands return:

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

Walk every page in a shell loop:

```bash theme={"theme":"css-variables"}
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.                                          |
| 7    | rate\_limited | The API refused the call (HTTP 429). Wait a minute, then retry. |

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.                          |
| `JAM_SKIP_UPDATE_CHECK` | Set to `1` to skip the check for a newer CLI version. Use it in CI, where the check costs a request and an outdated binary is the pinned one you asked for. |

## Update and uninstall

Install the latest CLI binary:

```bash theme={"theme":"css-variables"}
jam upgrade
```

Install a specific version:

```bash theme={"theme":"css-variables"}
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. 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:

```bash theme={"theme":"css-variables"}
jam uninstall
```

Skip the confirmation in non-interactive environments:

```bash theme={"theme":"css-variables"}
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. On Windows it removes the `%LOCALAPPDATA%\Programs\Jam` install folder and drops its entry from your user `PATH`.

<Warning>
  `jam uninstall` is irreversible. Re-install via the curl one-liner to recover.
</Warning>
