Cosmo Realtime SDK
Quickstart

Set up with the CLI

One command that signs you in, stores a key every SDK finds, and equips your coding agent.

The cosmo CLI is the shortest path from nothing to a machine that can build. It is the recommended first step for all three SDKs — after it, a client constructed with no arguments finds its own credential, and there is no key in your source, your environment, or your shell profile.

Prerequisites

  • macOS or Linux with a browser you can sign in from
  • A Cosmo account — sign up at platform.askcosmo.ai

Install the CLI

curl -fsSL https://platform.askcosmo.ai/docs/install.sh | sh

The script installs with whichever tool is already on your machine. To name one yourself, any of these installs the same program:

brew install socratic-ai/tap/cosmo    # Homebrew
uv tool install cosmo-cli             # uv
pipx install cosmo-cli                # pipx

Homebrew builds the CLI into an isolated virtualenv with its own Python, so it pulls in no Python tooling of yours — reach for it if you don't already have uv or pipx.

The CLI is a tool, not a library, so it installs into its own environment. Plain pip install cosmo-cli works too, but only inside an activated virtualenv — a current macOS or Linux Python refuses to install into itself.

Set up this machine

cosmo init

Three things happen, and then it exits — nothing runs in the background:

  1. You sign in. The terminal prints a short code and opens the sign-in page, which shows the same code — matching them confirms the page answers your terminal. Pick a workspace, and the CLI mints a workspace API key carrying the realtime verb scopes (start, dial, read, logs, delete) plus support, named after your machine's hostname so you can tell which one to revoke later. The sign-in link works from any device, and an interrupted command loses nothing: run cosmo init (or cosmo login) again and it resumes the same sign-in — instantly, if you already approved in the browser.
  2. The key is stored at ~/.cosmo/credentials, mode 0600. Every Cosmo SDK reads this file, along with the backend the key was issued for.
  3. The Cosmo skill is installed for every coding agent detected on this machine — Claude Code, Codex, Cursor, Gemini CLI, and the rest of the skills installer's ecosystem — teaching each one the current SDK API across all three languages. When the installer can't be reached, a bundled copy is installed for Claude Code at ~/.claude/skills/cosmo/.

What you should see:

Signed in as you@acme.co to Acme (acme).
  Granted: realtime:start, realtime:dial, realtime:read, realtime:logs, realtime:delete, support:write
  Saved to /Users/you/.cosmo/credentials

Cosmo skill installed to /Users/you/.claude/skills/cosmo (published).
  Your coding agent can now write Cosmo code against the current API.

Run it again any time. A credential that still works is reused rather than replaced, so re-running setup never retires the key your apps are already using. Skip the third step with cosmo init --no-skill.

The installed skill teaches a coding agent to write Cosmo code. It is unrelated to agent skills, which are playbooks you attach to an agent you build. Same file format, opposite direction.

Install an SDK

npm install cosmo-ai        # TypeScript / React
pip install cosmo-ai-sdk    # Python

For Swift, add https://github.com/socratic-ai/cosmo-swift-sdk as a package dependency — see the Swift quickstart.

Now a client built with no credential resolves one on its own:

const client = new RealtimeClient({});
client = RealtimeClient()
let client = try RealtimeClient()

Resolution order is COSMO_API_KEY first, then the credentials file. A browser is the one place it can't reach — a page has no home directory and no environment — so browser apps pass a credential explicitly while prototyping and minted end-user tokens in production.

Check what you're pointed at

cosmo whoami
Signed in to Acme (acme) — realtime ready.

cosmo whoami exits non-zero when the credential won't actually start a session, so cosmo whoami && python agent.py stops before your app does. Add --json for a machine-readable result.

List recent sessions

cosmo sessions list
2026-08-09 14:28   1m12s  completed  cosmo_voice_ultravox  3f2b8c1e-9a4d-4e7f-8b21-06d5c9a1f4e2
2026-08-09 14:26       -  active     cosmo_voice_ultravox  9b0d6f42-1c8e-4a53-b7d9-5e2f8c1a0d34

One line per session, newest first: start time, duration, status, provider, and the session id. A session that hasn't ended yet shows active with no duration. --limit raises the count (up to 100), and --json prints the records as the API returned them.

Read a session's transcript

cosmo sessions logs 3f2b8c1e-9a4d-4e7f-8b21-06d5c9a1f4e2
[00:00] You    Book me a table for Friday.
[00:04] Cosmo  For how many people?
[01:10] You    Four.

One line per turn, timed from the first one, so you can read a call back without opening the dashboard. --json prints the turns as the API returned them.

Add --bundle to download it instead, together with the call's recordings:

cosmo sessions logs 3f2b8c1e-9a4d-4e7f-8b21-06d5c9a1f4e2 --bundle
Downloading 3f2b8c1e-9a4d-4e7f-8b21-06d5c9a1f4e2-audio.wav ...
Wrote cosmo-session-3f2b8c1e-9a4d-4e7f-8b21-06d5c9a1f4e2.zip

The zip holds transcript.json, transcript.txt, and each recording the session produced. --bundle <path> writes somewhere else; a directory gets the same generated filename. A session still running, or one that recorded no audio, bundles its transcript alone.

Read a session's usage

cosmo sessions usage 3f2b8c1e-9a4d-4e7f-8b21-06d5c9a1f4e2
status:     completed
duration:   2m01s
turns:      7
talk time:  user 41s / agent 1m03s
model:      gemini-3.1-flash-live-preview
tokens:     1300 total (in 900 / out 400 / cached 30)

The summary a session's usage() returns in the SDKs, from the shell: duration, per-side talk time, and token counts in provider-reported units. The detailed numbers are recorded shortly after a session ends; until then the command says to check back, and if the session recorded none at all it says that instead of leaving you checking. A provider that bills by speech time rather than tokens reports talk time only. --json prints the summary as the API returned it.

Read a session's turn timeline

cosmo sessions timeline 3f2b8c1e-9a4d-4e7f-8b21-06d5c9a1f4e2
  turn  at          ttft    reply  playout  gen→play

     0  +10.0s     610ms   1800ms   1700ms     120ms
     1  +40.5s     720ms   1800ms   1700ms     120ms
     2  +88.2s    1310ms   1800ms   1700ms     120ms

median ttft 640ms  p95 980ms  first response 1450ms (agent greeted first)

Where usage reports what a session cost and logs what was said, this reports when each turn happened and how long its parts took. at is the offset from session start; ttft is the model's time to first token as the provider reported it, and reply how long it generated for.

Only the columns some turn actually measured are shown, so a session whose turns came from a speech pipeline shows its endpointing figures (eou, stt) instead of the model ones. A blank column would suggest a measurement failed rather than one that was never taken.

These are the server's numbers, and the server's clock stops at the frame it hands to the transport — none of them include the listener's playout hop. For that side, set COSMO_LOG_LEVEL=info in your own process and read the SDK's per-turn lines, described under debugging. --json prints the timeline as the API returned it, including the spans the table leaves out.

Keep workspaces apart

Every command takes --profile <name>, and each profile is its own table in the credentials file. The SDKs read the same selection from COSMO_PROFILE — which is the one that matters, since they run inside your own process where a command-line flag can't reach them.

cosmo init --profile work
COSMO_PROFILE=work python agent.py

COSMO_CREDENTIALS_FILE moves the file itself, for containers and CI.

Sign out

cosmo logout

This is a revocation, not a local delete: the key is retired server-side first, then removed from this machine. If the server can't be reached the credentials are left in place, so a live key is never forgotten locally while it still works.

Next steps

  • Follow a quickstart in your language.
  • Or ask your coding agent to build one: "build me a voice agent with the Cosmo SDK".
  • Need a key with a scope cosmo init doesn't grant — minting end-user tokens, say — or one for a server with no browser? Create it in the dashboard: API keys.

On this page