Skip to main content
This page documents every command in the tuple CLI. For an introduction and installation instructions, see the Tuple CLI overview.

Global flags

These flags work on every command:

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

contacts get <person>

Show full details for a single contact.

contacts favorite <person> / contacts unfavorite <person>

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

contacts remove <person>

Remove someone from your contacts.

contacts invite <email>

Send a Tuple invite to an email address.

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

call join <person-or-url>

Join a contact’s active call, or a room by slug or URL.
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.

call hang-up

Leave the active call.

call mute / call unmute

Mute or unmute yourself.

tuple rooms

List, join, favorite, and create Tuple 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.

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.

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

Pin or unpin a room.

rooms create <name>

Create a team room.

tuple screen

Inspect the screen being shared in a call.

screen capture -o <file>

Save a JPEG screenshot of the shared screen.
Defaults: --call current, --user current (whoever is currently sharing).

tuple transcription

Control call transcription, 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.

transcription start / transcription stop

Start or stop transcription for the active call.

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 or transcription search) 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 reports — pass --recording <uuid>. See 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), 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:A selection that would emit nothing (for example --without-speech alone) is rejected with an error.

Following flags

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.

Switching watch-words mid-stream

--watch-words accepts three kinds of values, mixed freely in the same comma-separated list:
  • A literal word or phrase (e.g. claude, hey claude) — case-insensitive.
  • @<path> — read watch words from a file, one per line. Blank lines are ignored.
  • * — match every finalized speech record. Use this to surface all speech to an agent.
When any @<path> reference is used with --follow or --wait, show watches those files and reloads them in-place whenever they change. The reload happens mid-stream: the current batch is flushed immediately, and the new watch words take effect on the very next record. There is no restart, no PID lookup, and no signal — whoever wants to switch modes just rewrites the file (atomically, e.g. temp-file-then-rename).This is the mechanism a long-running follower uses to toggle listening modes on a live call — for example, from wake-word-only to react-to-everything and back:
If a reload fails to read or parse the file, show logs the error to stderr and keeps the previous watch words rather than dying mid-call.

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.

transcription search <query>

Full-text search across every indexed transcript. The query uses SQLite FTS5 syntax: bare terms are ANDed, "quoted phrases" match exactly, and OR/NOT are supported.
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.

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.

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 and call-transcription-complete triggers. You cannot discover it elsewhere — transcription list and the MCP tools 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:

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

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.

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.
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.
  • contactstotal / 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).
  • roomspersonal, team, and occupied counts.
  • invites — number of pending invitations.
  • connectionwebsocket_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:
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.
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:

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 for the full walkthrough.

tuple mcp

Run an MCP server over stdin/stdout, or register Tuple with an AI coding agent. See the MCP server page for details.