MeetStream CLI

August 26, 2026 · View on GitHub

The MeetStream meeting-bot API from your terminal. Create bots that join Zoom, Google Meet, and Microsoft Teams meetings; record, transcribe, and interact - without writing a line of code.

npm install -g @meetstream/cli     # or: npx @meetstream/cli ...
meetstream auth set-key ms_XXXX    # key from https://app.meetstream.ai/api-keys
meetstream bot create "https://meet.google.com/abc-defg-hij" -t deepgram

Authentication

Every command authenticates to https://api.meetstream.ai/api/v1 with Authorization: Token <your-key>. There's no OAuth flow or separate CLI login - the API key is the credential.

SourcePrecedenceSet with
MEETSTREAM_API_KEY env varwins if setexport MEETSTREAM_API_KEY=ms_XXXX
~/.meetstream/config.jsonfallbackmeetstream auth set-key <key> (written with 0600 permissions)

Verify it's working:

meetstream auth status
# ✓ API key is valid
#   key              ms_if0…tH0L
#   base_url         https://api.meetstream.ai/api/v1
#   bots_on_account  12

Get a key at app.meetstream.ai/api-keys.


60-second tour

# 1. Point a local webhook receiver at the world (great for dev)
meetstream listen --port 3333            # then: ngrok http 3333

# 2. Send a bot to a meeting with post-call transcription
meetstream bot create "https://zoom.us/j/123456789" \
  --name "Notetaker" -t deepgram -c https://<ngrok>.ngrok.io/webhook

# 3. Watch it join
meetstream bot status <bot_id> --watch

# 4. Grab the transcript the moment it's ready
meetstream transcript <bot_id> --wait

Full capability list

auth - credentials

CommandWhat it does
auth set-key <key>Stores the key in ~/.meetstream/config.json
auth statusValidates the configured key against the live API and shows account info

bot - lifecycle, media, interaction

CommandWhat it does
bot create <meeting-link>Sends (or schedules with --join-at) a bot to the meeting. See bot create options below - transcription provider, callbacks, per-participant streams, MIA agent, live streaming, idempotency, and safe leave-timeout defaults.
bot listLists every bot on the account with id, status, and platform
bot status <id> [--watch]Current status; --watch polls every 5s until a terminal state (Stopped/Done/Error/etc.)
bot detail <id>Full session metadata - platform, timings, status timeline, transcript_id, caption_file
bot summary <id>MeetStream's built-in AI meeting summary
bot audio <id> / bot video <id>Presigned recording URL (audio valid 1h, video valid 10min)
bot streams <id> / bot audio-streams <id>Per-participant video/audio streams (needs --separate-video/--separate-audio at creation)
bot participants <id>Everyone detected in the meeting
bot chats <id>In-meeting chat messages
bot screenshots <id>Screenshots captured during the meeting
bot timeline <id>Speaker timeline - who spoke when
bot send-message <id> <text...>Posts a chat message into the live meeting
bot send-image <id> <img-url> [-d seconds]Shows an image/GIF as the bot's video frame (public URL required)
bot remove <id>Makes the bot leave the meeting now (data is kept)
bot delete <id> --yesPermanently deletes audio/video/transcripts - the --yes flag is mandatory, no accidental deletes

bot create options:

-n, --name <name>                bot display name (default "MeetStream Bot")
--video                           record video (default: audio only)
-t, --transcript <provider>      deepgram | assemblyai | sarvam | meetstream |
                                   jigsawstack | meeting_captions |
                                   deepgram_streaming | assemblyai_streaming
-l, --language <lang>            transcription language (provider-specific format)
-c, --callback <url>             HTTPS webhook for lifecycle events
--join-at <iso8601>              schedule a future join, e.g. 2026-07-02T15:00:00Z
--bot-message <msg>              chat message posted when the bot joins
--image-url <url>                PUBLIC image URL for the bot avatar
--retention-hours <n>            data retention window (API default 24h)
--separate-audio                 capture per-participant audio streams
--separate-video                 capture per-participant video streams
--zoom-obf                       use Zoom On-Behalf-Of
--agent-config-id <id>           attach a MIA conversational agent
--live-transcript-webhook <url>  webhook URL for live transcript chunks
--live-audio-ws <wss>            WebSocket URL for live audio out
--live-video-ws <wss>            WebSocket URL for live video out
--socket-ws <wss>                two-way bot-control WebSocket (socket_connection_url)
--attr <key=value...>            custom_attributes entries (echoed back in webhooks)
--idempotency-key <uuid>         safe-retry key - a retry returns the original
                                   bot (HTTP 507), never a duplicate
--everyone-left-timeout <sec>    leave after everyone else leaves (default 60)
--waiting-room-timeout <sec>     max seconds in waiting room (default 300)
--max-recording-seconds <sec>    max in-call recording seconds (default 14400)

transcript / transcriptions / transcribe - transcription

CommandWhat it does
transcript <bot-id> [--wait] [--raw] [--json]Fetches the transcript, resolving transcript_id automatically (it's never in webhooks). --wait polls until ready. Default output is readable Speaker: text lines.
transcriptions <bot-id>Lists every transcription run for a bot - provider, status, presigned download URLs
transcribe <bot-id> -p <provider>(Re-)transcribes a bot's recorded audio, optionally with a different provider or language

calendar - Google Calendar auto-join

CommandWhat it does
calendar connect --client-id --client-secret --refresh-tokenConnects a Google Calendar via OAuth refresh-token flow
calendar listConnected calendars
calendar eventsFetch/sync upcoming events
calendar schedule <event-id> / calendar unschedule <event-id>Send/remove a bot for one specific event
calendar auto-join on|off [-n name] [--video]Enable/disable auto-join for every meeting on the calendar
calendar reschedule <bot-id> <iso8601>Change a scheduled bot's join time
calendar cancel <bot-id>Delete a scheduled (not-yet-joined) bot

mia - conversational AI agents

CommandWhat it does
mia listLists agent configs
mia create -f <config.json>Creates an agent config (agent_name, mode, model, voice, transcriber, …) - attach it to a bot with --agent-config-id
mia delete <agent-config-id>Deletes an agent config

listen - local webhook receiver

CommandWhat it does
listen [-p port] [--path path] [--forward url] [--json]Runs a local HTTP server that pretty-prints every MeetStream webhook event as it arrives, color-coded by outcome. Pair with ngrok http <port> to give bot create --callback a public URL during development. --forward also relays the raw payload to another URL.

Every command supports --json for scripting.


The webhook model - live-verified

Events arrive under the event key with bot_id, bot_status, message, status_code (200/500), custom_attributes - this is exactly what meetstream listen decodes and pretty-prints for you:

bot.joining → bot.in_waiting_room → bot.inmeeting → bot.recording → bot.leaving → bot.stopped
→ manifest.completed → audio.processed → transcription.processed → video.processed → bot.done
  • bot.stopped fires once - bot_status says why (Stopped normal · NotAllowed lobby-timeout · Denied host-denied · Error crash).
  • Streaming-only transcription providers (deepgram_streaming, assemblyai_streaming, meeting_captions) end at audio.processed - they never fire transcription.processed, transcription.failed, or bot.done.
  • transcript_id is not in webhooks - meetstream transcript <bot_id> resolves it via /detail automatically.
  • The public docs page for this describes a different (bot_event) envelope key - that's inaccurate; this CLI, and the MeetStream MCP server, both implement the live-verified model above.

Configuration

SourceNotes
MEETSTREAM_API_KEYwins over the config file
~/.meetstream/config.jsonwritten by auth set-key (0600)
MEETSTREAM_API_URLoverride the base URL (default https://api.meetstream.ai/api/v1)

Troubleshooting

SymptomFix
"No API key found"Run meetstream auth set-key <key> or export MEETSTREAM_API_KEY=...
auth status fails with 401Key is invalid/revoked - generate a new one at app.meetstream.ai/api-keys
transcript returns "not ready yet"The meeting isn't fully processed, or the provider is streaming-only (no post-call transcript) - check bot status first
listen events never arriveConfirm the bot's --callback URL is a public HTTPS URL (use ngrok http <port>) - MeetStream will not retry non-2xx or unreachable webhooks

Development

npm install
npm test          # node --test, fully mocked (no network)

Docs: docs.meetstream.ai · OpenAPI: openapi.json · MCP server for AI agents: @meetstream/mcp · Migrating from Recall.ai: @meetstream/migrate

MIT © MeetStream.ai

Telemetry

The CLI sends anonymous usage events (which commands you run) to help us improve MeetStream. It never sends your API key, meeting URLs, transcripts, or any content. Disable it any time:

export MEETSTREAM_TELEMETRY=0   # or the standard DO_NOT_TRACK=1