> For the complete documentation index, see [llms.txt](https://docs.birdie.so/birdie-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.birdie.so/birdie-docs/cli.md).

# CLI

Read Birdie recording signals from your terminal - console logs, network requests, user events, transcripts, metadata, and frames. Built for shell scripts, CI jobs, and AI coding agents.

The CLI reads the same data through the same permissions as the [MCP server](/birdie-docs/mcp-server.md): it is MCP over a different transport. If your agent connects over MCP you may not need the CLI at all; reach for it when you want to pipe recording data through standard tools (`grep`, `jq`), script it in CI, or hand an agent a plain binary instead of an MCP connection.

### Install

{% tabs %}
{% tab title="macOS and Linux (Intel and ARM)" icon="apple" %}

```bash
curl -fsSL https://cli.birdie.so/install.sh | sh
```

The installer detects your OS and architecture, verifies the download against its SHA-256 checksum, and installs to `/usr/local/bin` (or `~/.local/bin` when that isn't writable). No runtime dependencies — it's a single static binary.

Options, via environment variables:

| Variable         | Effect                                                      |
| ---------------- | ----------------------------------------------------------- |
| `BIRDIE_VERSION` | Install a specific version, e.g. `v0.2.3` (default: latest) |
| `INSTALL_DIR`    | Install somewhere else, e.g. `INSTALL_DIR=~/bin`            |
| {% endtab %}     |                                                             |

{% tab title="Windows" icon="windows" %}
**D**ownload the `windows_amd64.zip` archive for the latest version from `https://cli.birdie.so/releases/<version>/` (the current version is at [cli.birdie.so/releases/latest](https://cli.birdie.so/releases/latest)), unzip it, and put `birdie.exe` on your `PATH`.
{% endtab %}
{% endtabs %}

**Updating**: re-run the install command — it always fetches the latest version. \
**Uninstalling**: delete the binary and, if you logged in, the config file at `~/.config/birdie/` (`%APPDATA%\birdie\` on Windows).

### Authenticate

The CLI uses your personal access token — the same one the MCP server accepts. Create one in [Settings → AI agents & CLI](https://app.birdie.so/settings/ai-agents), then:

```bash
birdie auth login
```

Paste the token at the prompt (or pass it with `--token`). The token is verified against the API before it's saved — a wrong paste is rejected on the spot, never stored. It's then kept with owner-only permissions in `~/.config/birdie/config.json` (`%APPDATA%\birdie\config.json` on Windows).

`birdie auth status` shows whether a token is configured and where it came from (`--check` also verifies it against the API); `birdie auth logout` removes the stored token.

`birdie auth status` shows whether a token is configured and where it came from; `birdie auth logout` removes the stored token.

{% hint style="info" %}
**In CI**, set the `BIRDIE_TOKEN` environment variable instead of running `login`. It takes precedence over the config file and nothing is written to disk.
{% endhint %}

### First steps

```bash
birdie list                  # your team's latest recordings
birdie console <recording>   # console logs from one of them
```

Every command accepts a recording in any form you have at hand: the numeric id, the uuid, the short public code (e.g. `w3uqNNG`), or a pasted share URL.

### Commands

| Command                   | What it reads                                                                                                    |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `birdie list`             | Find recordings by title, ticket, email, folder, or date                                                         |
| `birdie console <rec>`    | Console logs — filter with `--level error`                                                                       |
| `birdie network <rec>`    | Network requests — filter by `--status`, `--method`, `--host`, `--content-type`; inspect one in full with `--at` |
| `birdie repro <rec>`      | Reproduction steps: clicks, inputs, navigation. `--full` adds the starting context and any errors                |
| `birdie transcript <rec>` | Spoken content, as text or WebVTT (`--vtt`)                                                                      |
| `birdie metadata <rec>`   | Browser, OS, page URL, duration, custom metadata                                                                 |
| `birdie scenes <rec>`     | Where the screen changed — a cheap visual index, no images                                                       |
| `birdie frames <rec>`     | Still frames written to disk as images                                                                           |
| `birdie auth`             | `login`, `status`, `logout`                                                                                      |
| `birdie version`          | Print the installed version                                                                                      |

{% hint style="info" %}
`birdie events` was the previous name for `birdie repro` and still works, so existing scripts keep running. New ones should use `repro` from version 0.2.3.
{% endhint %}

Every command also works written as `birdie get <command>` — both forms are identical. Run `birdie <command> --help` for the full flags of any command.

Global flags on every command:

| Flag      | Effect                                    |
| --------- | ----------------------------------------- |
| `--json`  | Emit raw JSON instead of formatted output |
| `--quiet` | Suppress progress messages on stderr      |

### Inspecting a recording

Start wide, then narrow:

```bash
# Only the errors
birdie console w3uqNNG --level error

# Which requests failed?
birdie network w3uqNNG --status 5xx

# Full detail on one request: headers, payload, response body.
# Paste the timecode straight from the list output.
birdie network w3uqNNG --at 00:15.326

# What did the user actually do?
birdie repro w3uqNNG

# What was on screen around the failure?
birdie scenes w3uqNNG
birdie frames w3uqNNG --at 15326 --out ./frames
```

`frames` extracts an evenly spaced overview by default (`--count`, up to 12), a single moment with `--at`, or a window with `--from`/`--to` — times in milliseconds. Images land in the current directory unless `--out` says otherwise.

### Finding recordings

`birdie list` filters your team's recordings, newest first:

```bash
birdie list --ticket 4821
birdie list --email jane@acme.com --date 2026-08-22
birdie list --query "checkout"
```

| Flag                 | Matches                                                 |
| -------------------- | ------------------------------------------------------- |
| `--query`            | Title, tags, uuid, or custom metadata                   |
| `--ticket`           | Recordings attached to a helpdesk ticket                |
| `--email`            | Recorded by, requested by, or customer email            |
| `--folder`           | Recordings in a folder                                  |
| `--date`             | Recording date: `2026-08-23`, `"2026-08-23 14"`, or ISO |
| `--limit` / `--page` | Paging (default 10 per page, max 20)                    |

{% hint style="info" %}
**Filters match recording metadata - never log content.** This is intentional. Birdie is designed so that recording logs are securely stored without being indexed in a searchable database. That architecture limits unnecessary exposure of potentially sensitive log data, but it also means log contents can’t be queried across recordings - for example, “which recordings had a 500 error last week?”

To answer content questions, list by metadata, then inspect each candidate - the logs flow from the bucket to you, never through a Birdie-side scan:

```bash
birdie list --ticket 4821 --json | jq -r '.results[].recording_identifier' \
  | xargs -I{} sh -c 'birdie network {} --status 5xx --json | jq -e "length>0" >/dev/null && echo {}'
```

{% endhint %}

### Scripting

**Output.** In a terminal you get formatted, human-readable output; progress and notes go to stderr so stdout stays clean when piped. Pass `--json` for the raw API response — the shape every script and agent should consume:

```bash
birdie network w3uqNNG --status 5xx --json | jq '.[].url'
```

**Pagination.** The signal commands (`console`, `network`, `events`) page with a cursor. In JSON mode the response carries `next_cursor` when there is more; pass it back with `--cursor` (alias `--after`), or use `--all` to follow pagination to the end in one call.

**Exit codes.** Branch on the code, not on stderr text:

| Code | Meaning                                             |
| ---- | --------------------------------------------------- |
| 0    | Success                                             |
| 1    | Unexpected error                                    |
| 2    | Bad invocation: unknown flag, missing argument      |
| 3    | Not authenticated, or not permitted                 |
| 4    | No such recording in this workspace                 |
| 5    | The request was rejected as invalid                 |
| 6    | Birdie could not serve it; retrying may help        |
| 7    | Success, but the recording has no data of this kind |

Code 7 makes "no console logs" distinguishable from failure without parsing anything.

**Environment variables.**

| Variable                 | Effect                                                       |
| ------------------------ | ------------------------------------------------------------ |
| `BIRDIE_TOKEN`           | Authenticate without a config file; takes precedence over it |
| `BIRDIE_NO_UPDATE_CHECK` | Set to `1` to disable the daily update hint                  |

### Notes

* The CLI sees exactly what your token's owner sees in the Birdie app - folder access rules and workspace permissions apply identically. It never exposes recordings the token owner couldn't open.
* The CLI is read-only: it inspects recordings, it never creates, modifies, or deletes anything.
* Recording data is redacted at source in the customer’s browser or our Chrome extension, before it ever leaves the browser. As a result, Birdie’s servers, CLI, MCP server, and app only ever see the redacted data.
