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

# Command reference

<View title="macOS" icon="apple">
  This page documents every command in the `tuple` CLI. For an introduction and installation instructions, see the [Tuple CLI overview](/cli/overview).

  ## Global flags

  These flags work on every command:

  | Flag                            | Description                                                                       |
  | ------------------------------- | --------------------------------------------------------------------------------- |
  | `--format default\|json\|table` | Output format. Default is human-friendly; `json` is machine-readable.             |
  | `-H`, `--host PATH`             | Path to the Tuple app socket (Unix socket on macOS/Linux, named pipe on Windows). |

  ## Person arguments

  Many commands take a `<person>` argument — that's a free-text query, not an ID. The CLI runs a substring match against your contacts' names and emails:

  * Exactly one match: the command runs.
  * Zero matches: the command errors.
  * Multiple matches: the command errors and lists the candidates.

  ## `tuple contacts`

  Manage your Tuple contacts.

  ### `contacts list [query] [flags]`

  List contacts, sorted by favorites, then status (online > busy > offline), then name.

  ```text theme={null}
  tuple contacts list [query]
    [-q, --query <q>]
    [--status online|busy|offline]
    [--kind teammate|external]
    [--favorited]
    [--recent]
    [-f, --follow]
  ```

  | Flag              | Description                                                                                                                    |
  | ----------------- | ------------------------------------------------------------------------------------------------------------------------------ |
  | `-q, --query <q>` | Search by name or email. Equivalent to the positional `[query]` argument — supply one or the other, not both.                  |
  | `--status`        | Keep only contacts in the given presence state. Accepts `online`, `busy`, or `offline`. `available` is a synonym for `online`. |
  | `--kind`          | Keep only `teammate` (people in your org) or `external` contacts.                                                              |
  | `--favorited`     | Keep only favorited contacts. Use `--favorited=false` to keep only unfavorited contacts.                                       |
  | `--recent`        | Keep only people you've contacted recently.                                                                                    |
  | `-f, --follow`    | Stream updates as availability changes. Cannot be combined with any filter flag or a query.                                    |

  All filter flags compose with AND. An empty result is a success (exit `0`, empty table or `[]`). Invalid `--status` or `--kind` values error with a non-zero exit.

  ```bash theme={null}
  tuple contacts list                              # everyone
  tuple contacts list ben                          # filter by name/email substring (positional)
  tuple contacts list --query ben                  # same, via the flag
  tuple contacts list --status online              # everyone currently online
  tuple contacts list --status available --kind teammate
  tuple contacts list --favorited --recent         # favorites you've talked to lately
  tuple contacts list --favorited=false            # everyone who isn't favorited
  tuple contacts list --follow                     # stream updates (no filters allowed)
  ```

  ### `contacts get <person>`

  Show full details for a single contact.

  ```bash theme={null}
  tuple contacts get ben@example.com
  ```

  ### `contacts favorite <person>` / `contacts unfavorite <person>`

  Pin or unpin a contact at the top of your list.

  ```bash theme={null}
  tuple contacts favorite alice
  ```

  ### `contacts remove <person>`

  Remove someone from your contacts.

  ### `contacts invite <email>`

  Send a Tuple invite to an email address.

  ```bash theme={null}
  tuple contacts invite teammate@example.com
  ```

  ## `tuple call`

  Start, join, and control calls. All call subcommands accept `--call <id>` to target a specific call; the default is `current` (the active call).

  ### `call current`

  Print the call you're currently in. Use this when a script or agent needs the active call id without parsing the full `tuple state` payload.

  The default output is just the bare call id, so no JSON parser is required. When you're not in a call, the command writes nothing to stdout, prints `not in a call` to stderr, and exits non-zero — branch on the exit code regardless of `--format`.

  ```bash theme={null}
  # Capture the current call id in a script — no JSON parser needed
  id="$(tuple call current)"

  # Branch on whether you're in a call
  if tuple call current >/dev/null 2>&1; then echo "in a call"; fi
  ```

  Output formats:

  * **default** — the bare call id followed by a newline.
  * **`--format json`** — the full current-call object, byte-for-byte identical to `tuple state`'s `current_call` field (including `local`, `tracks`, `capacity`, `sfu_backed`, `room`, and `recorder`).
  * **`--format table`** — a short human summary with id, participant count, and participant emails.

  ### `call start <person>`

  Start a 1:1 call with the matched contact.

  ```bash theme={null}
  tuple call start ben
  ```

  ### `call join <person-or-url>`

  Join a contact's active call, or a room by slug or URL.

  ```bash theme={null}
  tuple call join alice
  tuple call join my-team-room
  tuple call join https://tuple.app/room/my-team-room
  ```

  The argument is resolved as a contact first. If no contact matches, the last path segment of the URL is treated as a room slug.

  ### `call add <person>` / `call remove <person>`

  Add or remove a participant from the active call.

  ```bash theme={null}
  tuple call add carol
  tuple call remove carol
  ```

  ### `call hang-up`

  Leave the active call.

  ### `call mute` / `call unmute`

  Mute or unmute yourself.

  ```bash theme={null}
  tuple call mute && some-long-command && tuple call unmute
  ```

  ## `tuple rooms`

  List, join, favorite, and create [Tuple rooms](/pairing-with-tuple/using-rooms). Commands that target an existing room accept a slug such as `acme/general` or a full room URL.

  ### `rooms list [flags]`

  List your personal rooms and the rooms for every team you belong to. Results are sorted by occupied rooms, favorites, then name.

  ```bash theme={null}
  tuple rooms list
  tuple rooms list --kind personal --occupied
  tuple rooms list --favorited --members
  tuple rooms list --limit -1
  ```

  | Flag                 | Description                                                                                  |
  | -------------------- | -------------------------------------------------------------------------------------------- |
  | `--kind <kind>`      | Show only `personal` or `team` rooms.                                                        |
  | `--occupied`         | Show only rooms with someone currently present.                                              |
  | `--favorited[=BOOL]` | Show only favorited rooms, or pass `--favorited=false` to show only unfavorited rooms.       |
  | `--limit <n>`        | Maximum rooms to return. The default cap is `100`; pass `-1` for all rooms.                  |
  | `--members`          | Include member names. By default, the command shows only the number of members in each room. |

  ### `rooms join <slug-or-url>`

  Join a room without first trying to resolve the argument as a contact. This is useful for personal rooms, where joining alone is valid.

  ```bash theme={null}
  tuple rooms join acme/general
  ```

  ### `rooms favorite <slug-or-url>` / `rooms unfavorite <slug-or-url>`

  Pin or unpin a room.

  ### `rooms create <name>`

  Create a team room.

  ```bash theme={null}
  tuple rooms create "Engineering touchbase"
  ```

  ## `tuple screen`

  Inspect the screen being shared in a call.

  ### `screen capture -o <file>`

  Save a JPEG screenshot of the shared screen.

  ```bash theme={null}
  tuple screen capture -o screenshot.jpg
  tuple screen capture -o -            # write JPEG bytes to stdout
  ```

  Defaults: `--call current`, `--user current` (whoever is currently sharing).

  ## `tuple transcription`

  Control [call transcription](/pairing-with-tuple/transcribing-calls), stream its output, and search, show, or export the transcripts of past calls. The stored-transcript subcommands (`list`, `search`, `export`) work without an active call — the Tuple daemon indexes every transcribed call into a local database as it records. For a walkthrough, see [Searching past calls](/pairing-with-tuple/searching-past-calls).

  ### `transcription start` / `transcription stop`

  Start or stop transcription for the active call.

  ```bash theme={null}
  tuple transcription start
  ```

  ### `transcription show [call-id] [--follow|--wait] [--interval=DURATION] [--watch-words=…] [--timeout=DURATION] [--cursor=TAG] [--recording UUID] [--with-events] [--without-speech] [--with-speech-markers]`

  Read a call's transcription records. With no argument, `show` targets the active call; pass any unique prefix of a call ID (as printed by [`transcription list`](#transcription-list) or [`transcription search`](#transcription-search-query)) to read a stored transcript instead. This single command replaces the older `current`, `events`, `text`, and `stream` surfaces.

  To read exactly one recording session — for example, the specific session a [`call-transcription-complete` trigger](/triggers/api-reference#call-transcription-complete) reports — pass `--recording <uuid>`. See [Targeting a recording session](#targeting-a-recording-session).

  `show` has three consumption modes:

  * **Snapshot** (default): print all records so far, sorted by timestamp, then exit. Good for one-shot reads of a finished call or a quick look at the live one.
  * **`--follow`**: stream continuously until the call ends, in arrival order. Use this under a per-line wake mechanism (such as Claude Code's Monitor); a plain backgrounded `--follow` won't wake an idle agent.
  * **`--wait`**: block until the next batch of records, print it, then exit. Loop this in the foreground to follow a call from any agent. Each run resumes where the last left off using a per-call cursor, so there are no gaps or repeats. This is the universal fallback when no per-line wake mechanism is available.

  If you pass a stored call ID with `--follow` or `--wait` and that call isn't active, `show` prints a one-shot snapshot instead so scripts targeting a specific call degrade cleanly.

  Human output is one line per record (timestamped, speaker-prefixed for speech). With `--format json` (see [Output formats](#global-flags)), each record is emitted as an NDJSON line — pipe it into log aggregators, agent runners, or `jq`.

  #### Content toggles

  By default `show` prints finalized speech. Combine these flags to widen or narrow the feed:

  | Flag                    | Description                                                                                                                                                                                                                       |
  | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `--with-events`         | Include lifecycle event records (transcription started, user joined, screen sharing started, and so on).                                                                                                                          |
  | `--without-speech`      | Suppress finalized speech records. Combine with `--with-events` to read just lifecycle events.                                                                                                                                    |
  | `--with-speech-markers` | Include `transcription_started` / `transcription_dropped` markers. Defaults to on with `--follow` and `--wait` so live readers can see gaps; off for snapshots. Pass `--with-speech-markers=false` to suppress in a live session. |

  A selection that would emit nothing (for example `--without-speech` alone) is rejected with an error.

  #### Following flags

  | Flag                  | Description                                                                                                                                                                                             |
  | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `-f`, `--follow`      | Stream in real time until the call ends. Mutually exclusive with `--wait`.                                                                                                                              |
  | `--wait`              | Block until the next batch, print it, then exit. Loop to follow without a per-line wake mechanism. Mutually exclusive with `--follow`.                                                                  |
  | `--interval DURATION` | Buffer output and flush at most once per interval (e.g. `60s`). Combine with `--wait` to gather one batch per interval; combine with `--follow` to flush a buffered window per interval.                |
  | `--watch-words a,b,c` | Case-insensitive words or phrases that flush a batch early when spoken. Requires `--interval` with `--wait` or `--follow`. Use this so an agent responds immediately when addressed.                    |
  | `--timeout DURATION`  | With `--wait`, return an empty result after this much silence so a loop can re-check. Default `30s`. `0` blocks until the next speech.                                                                  |
  | `--cursor TAG`        | With `--wait`, the named read position saved between runs. Default `default`. Give each concurrent follower its own tag — one reader per tag.                                                           |
  | `--recording UUID`    | Read one recording session instead of a whole call (see [Targeting a recording session](#targeting-a-recording-session)). Composes with `--follow` and `--wait`; the stream ends when the session does. |

  The first `--wait` run for a call (no saved cursor) returns the whole backlog at once as a catch-up. Later runs return only what's new since the previous cursor save. When the call ends, `--wait` and `--follow` emit a terminal `{"kind":"status","status":"call_ended"}` line so the loop knows to stop.

  ```bash theme={null}
  # Quick snapshot of the active call's transcript:
  tuple transcription show

  # Read a stored call by ID prefix:
  tuple transcription show a1b2c3d4

  # Watch a live call and see lifecycle events as well as speech:
  tuple transcription show --follow --with-events

  # Follow loop suitable for any agent harness:
  while tuple transcription show --wait --interval 60s --watch-words "claude,hey claude"; do
    : # process the batch this run just printed
  done
  ```

  ### `transcription list`

  List calls that have a stored transcript, most recent first. Each row shows the start time, the call's title (if set), a short call ID, the transcript segment count, and the participants Tuple resolved from the recording.

  ```bash theme={null}
  tuple transcription list
  tuple transcription list --participant mikey --after 2026-05-11
  ```

  | Flag                   | Description                                                         |
  | ---------------------- | ------------------------------------------------------------------- |
  | `--participant <text>` | Only calls with a participant whose name or email contains `<text>` |
  | `--after <date>`       | Only calls starting on or after `<date>` (e.g. `2026-05-19`)        |
  | `--before <date>`      | Only calls starting on or before `<date>`                           |
  | `--limit <n>`          | Maximum calls (default `100`; pass `-1` for all)                    |

  ### `transcription search <query>`

  Full-text search across every indexed transcript. The query uses [SQLite FTS5 syntax](https://www.sqlite.org/fts5.html#full_text_query_syntax): bare terms are ANDed, `"quoted phrases"` match exactly, and `OR`/`NOT` are supported.

  ```bash theme={null}
  tuple transcription search "feature flag"
  tuple transcription search rollback --speaker alex -C 2
  ```

  | Flag                   | Description                                                                                                     |
  | ---------------------- | --------------------------------------------------------------------------------------------------------------- |
  | `--call <id>`          | Only this call. Repeatable; accepts `current` or short call ID prefixes.                                        |
  | `--recording <uuid>`   | Only segments from one recording session (see [Targeting a recording session](#targeting-a-recording-session)). |
  | `--speaker <text>`     | Only segments spoken by someone whose name or email contains `<text>`                                           |
  | `--participant <text>` | Only calls with a participant whose name or email contains `<text>`                                             |
  | `--after <date>`       | Only segments on or after `<date>`                                                                              |
  | `--before <date>`      | Only segments on or before `<date>`                                                                             |
  | `-C`, `--context <n>`  | Show `n` segments of conversation around each match                                                             |
  | `--limit <n>`          | Maximum matches (default `50`; pass `-1` for all)                                                               |

  To print one call's full transcript, pass its short ID to `transcription show` (documented above) — `show` reads a stored call when given any unique call-ID prefix.

  ### `transcription export <dir>`

  Write one flat file per call into `<dir>`, named `<date>@<call-id>.<ext>`. Calls without transcript segments are skipped, and existing files are overwritten — re-running refreshes the export.

  ```bash theme={null}
  tuple transcription export ~/Documents/tuple-transcripts
  tuple transcription export ~/Documents/tuple-transcripts --after 2026-05-01 --format md
  ```

  | Flag                   | Description                                                                                                  |
  | ---------------------- | ------------------------------------------------------------------------------------------------------------ |
  | `--format <fmt>`       | `md` (default), `text`, or `ndjson`.                                                                         |
  | `--call <id>`          | Only this call. Repeatable; accepts `current` or short call ID prefixes.                                     |
  | `--recording <uuid>`   | Only one recording session's segments (see [Targeting a recording session](#targeting-a-recording-session)). |
  | `--participant <text>` | Only calls with a participant whose name or email contains `<text>`                                          |
  | `--after <date>`       | Only calls starting on or after `<date>`                                                                     |
  | `--before <date>`      | Only calls starting on or before `<date>`                                                                    |

  ### `transcription delete <call-id>`

  Permanently delete one stored call's recordings, transcript segments, and events from the local database. The command accepts the short call IDs printed by `transcription list` and `transcription search`. This cannot be undone.

  ```bash theme={null}
  tuple transcription delete a1b2c3d4
  ```

  ### Targeting a recording session

  Every time transcription starts on a call, Tuple mints a UUID for that *recording session*. `show`, `search`, and `export` accept `--recording <uuid>` to scope to one session instead of a whole call. This matters when transcription is stopped and restarted mid-call — each start/stop is a distinct session with its own started/complete pair.

  The UUID is only ever exposed to you through the `TUPLE_TRIGGER_RECORDING_ID` environment variable in [`call-transcription-started`](/triggers/api-reference#call-transcription-started) and [`call-transcription-complete`](/triggers/api-reference#call-transcription-complete) triggers. You cannot discover it elsewhere — `transcription list` and the [MCP tools](/cli/mcp) deliberately do not expose session-level IDs.

  A recording UUID identifies its session on its own, so `--call` is redundant alongside `--recording` and is ignored. With `show`, `--recording` composes with `--follow` and `--wait`: the stream ends when that session ends, even if the call continues.

  The canonical use is a `call-transcription-complete` trigger that hands the UUID straight to the CLI to grab exactly that session's transcript:

  ```sh theme={null}
  #!/bin/sh
  # ~/.tuple/triggers/summarize/call-transcription-complete
  tuple transcription export ~/Documents/tuple-transcripts \
    --recording "$TUPLE_TRIGGER_RECORDING_ID"
  ```

  ## `tuple notifications`

  Post notification cards into an active call. Agents and scripts use these to nudge the user, or to ask a yes/no question, without leaving Tuple. Use `notify` for a fire-and-forget notice or `ask` for a decision card with Accept/Reject buttons that blocks until the user answers.

  ### `notifications notify`

  Post a fire-and-forget notice — a status update or nudge the user doesn't need to act on. `--title`, `--body`, and `--sender` are required.

  ```bash theme={null}
  tuple notifications notify \
    --title "Tests passed" \
    --body "go test ./... is green" \
    --sender "Claude"
  ```

  | Flag                    | Required | Notes                                                                                 |
  | ----------------------- | -------- | ------------------------------------------------------------------------------------- |
  | `--title`               | yes      | Shown bold at the top.                                                                |
  | `--body`                | yes      | The notice body.                                                                      |
  | `--sender`              | yes      | Shown as the "from" name.                                                             |
  | `--ephemeral`           | no       | Auto-dismiss after the default 10s of going unnoticed. Interacting resets the timer.  |
  | `--interaction-timeout` | no       | Auto-dismiss after this long without interaction (`2s`–`60s`; implies `--ephemeral`). |

  By default the notice persists until the user dismisses it or you cancel it.

  ### `notifications ask`

  Post a decision card and block until the user responds. Prints the outcome (`accepted`, `rejected`, or `canceled`) and exits `0` **only** when the user accepted — any other outcome exits non-zero, so a script can gate a consequential action on an explicit yes. The card stays up until the user answers or it's withdrawn; there is no timeout.

  ```bash theme={null}
  if tuple notifications ask \
    --title "Run tests?" \
    --body "tuple wants to run go test ./..." \
    --sender "Claude" \
    --accept-label "Run" \
    --reject-label "Skip"
  then
    go test ./...
  fi
  ```

  | Flag             | Required | Notes                                             |
  | ---------------- | -------- | ------------------------------------------------- |
  | `--title`        | yes      | Shown bold at the top.                            |
  | `--body`         | yes      | The question body.                                |
  | `--sender`       | yes      | Shown as the "from" name.                         |
  | `--accept-label` | no       | Custom accept-button label. Defaults to `Accept`. |
  | `--reject-label` | no       | Custom reject-button label. Defaults to `Reject`. |

  ### `notifications list [--follow] [--interval=DURATION]`

  List notification events (posted, accepted, rejected, canceled). Run with `--follow` (`-f`) after posting to watch for the user's response; `--interval` buffers streamed output and applies only with `--follow`.

  ```bash theme={null}
  tuple notifications list --follow
  ```

  ### `notifications cancel <notification-id>`

  Withdraw a card you posted before the user has answered. Only external notifications (the ones you posted) can be canceled — accepting or rejecting is user-driven.

  ## `tuple whoami`

  Print the identity of the authenticated Tuple user. Use this when a script or agent needs the signed-in user's email or ID without parsing the full `tuple state` payload.

  The default output is the bare email address followed by a newline, so no JSON parser is required.

  ```bash theme={null}
  # Capture the current user email in a script — no JSON parser needed
  email="$(tuple whoami)"

  # Get the user id for filtering yourself out of a roster
  id=$(tuple whoami --format json | jq .id)
  ```

  Output formats:

  * **default** — the bare email address followed by a newline. Exits non-zero with `current user has no email — is Tuple logged in?` on stderr when the daemon has no identity.
  * **`--format json`** — the full identity object: `id`, `email`, `full_name`, `short_name`.
  * **`--format table`** — a labeled four-row block with ID, Email, Name, and Short name.

  ## `tuple state [--follow]`

  Print a **bounded orientation summary** of the Tuple app — a constant-size snapshot designed for agents and scripts that need to know what's going on without paging the full team into their context. The default output collapses every collection to counts:

  * `in_call` — boolean shortcut for "am I on a call right now".
  * `call` — the normalized call object, byte-for-byte identical to `tuple call current --format json`, or `null` when you're not in a call.
  * `user` — your `id`, `email`, and `short_name`.
  * `contacts` — `total` / `online` / `busy` counts, plus a `favorites` block with `total`, `online`, and `online_names` (a capped sample of up to 10 online favorites — enough to actually name who you could pair with).
  * `rooms` — `personal`, `team`, and `occupied` counts.
  * `invites` — number of pending invitations.
  * `connection` — `websocket_state` and `is_internet_connected`. When the websocket isn't `connected`, the presence-derived counts are last-known.
  * `platform`, `app_version`, `available_update_version` — install and update status.
  * `see` — a drill-down map naming the entity command that returns each collapsed section in full, so a script never has to guess where the detail lives:

    ```json theme={null}
    {
      "contacts": "tuple contacts list",
      "favorites_online": "tuple contacts list --favorited --status online",
      "rooms": "tuple rooms list",
      "call": "tuple call current",
      "user": "tuple whoami"
    }
    ```

  <Warning>
    **Breaking change.** `tuple state` previously dumped the daemon's full state payload — the entire contacts list and every room's member roster. It now always returns the bounded summary above; there is no `--full` opt-in.

    If you were reading `contacts`, `rooms`, or `current_call` arrays from `tuple state`, move to the entity commands (`tuple contacts list`, `tuple call current`, `tuple rooms list`, `tuple whoami`) — or to a streaming surface that still carries the full payload: `tuple state --follow` or the [`tuple://state` MCP resource](/cli/mcp#resources).
  </Warning>

  Use `--follow` to stream incremental state events from the daemon as they happen — useful for dashboards or AI agents that need to react to call lifecycle changes. The stream carries the **full** payload (the same shape `GET /state` returns), not the summary:

  ```bash theme={null}
  tuple state --follow --format json | jq -c 'select(.type == "current_call")'
  ```

  ## `tuple connect [purpose]`

  Launch an AI coding agent into your active Tuple call with a generated context prompt. See the [Connect an AI agent page](/cli/connect) for the full walkthrough.

  ```bash theme={null}
  tuple connect                          # interactive picker
  tuple connect "help debug this bug"   # picker, with starting purpose
  tuple connect --harness claude         # skip the picker
  tuple connect --print                  # write the prompt to stdout
  tuple connect --config                 # edit per-agent settings
  ```

  | Flag                  | Description                                                                                                       |
  | --------------------- | ----------------------------------------------------------------------------------------------------------------- |
  | `--harness <name>`    | Builtin key (`claude`, `codex`, `cursor`, `copilot`, `opencode`, `pi`, `droid`), custom name, or executable path. |
  | `--print`             | Write the context prompt to stdout instead of launching an agent.                                                 |
  | `--model <name>`      | Model to pass to the harness's model flag. Overrides saved per-harness settings.                                  |
  | `--reasoning <level>` | Reasoning effort to pass to the harness's effort flag. Overrides saved per-harness settings.                      |
  | `--config`            | Open the TUI to edit per-harness settings saved to `~/.tuple/cli.toml`.                                           |

  ## `tuple mcp`

  Run an MCP server over stdin/stdout, or register Tuple with an AI coding agent. See the [MCP server page](/cli/mcp) for details.

  ```bash theme={null}
  tuple mcp                              # run the server (used by agents)
  tuple mcp install claude               # register with Claude Code
  tuple mcp install                      # interactive picker
  ```
</View>
