NebulaNebula
CLI

Calls from the terminal

Start, join, and run Nebula calls from your shell. Chat-first by default, with voice as a two-step opt-in and a headless mode for servers.

You can take a call entirely from the terminal — start one, join one already running, or send a message into it without opening the room. The CLI joins chat-first: you're connected and reading, but not broadcasting, until you say so.

nebula-ai call join thr_8f2a1c
● LIVE Call ✎ chat 12:04 · connected
Nebula [active] working… You Priya Sam
⚙ 2 in flight Draft the retro notes · Pull last week's numbers w all
Priya: can we ship the retro notes today?
Nebula: yes — drafting them now.
sse connected · 14 ev · engine connected
type to chat during the call…
NAVHome › Calli type r recap w work v voice c camera p active/bg ^P hang up E end Esc back? helpMaya

Starting a call

nebula-ai call start starts a new call and opens it straight away in the call screen. From a script, add --json: the call starts without opening the app, and the output carries the call's thread ID, which you pass to nebula-ai call join to open it later.

Add --title to name it, --private to keep it to you and whoever you invite, or --thread to seed it from an existing conversation so the agents arrive with that context.

--thread on start and the thread ID everywhere else are different things. On start it's an option naming the conversation an agent should read for context. On every other call command it's the required first argument naming which call you mean.

Hold on to that ID — every other call command takes it. If you've lost it, nebula-ai channels list lists your conversations with an ID column.

Joining and checking

nebula-ai call join <thread> drops you into a call that's already running.

nebula-ai call list <thread> shows that channel's calls, live ones first; nebula-ai call status <thread> reports on one you're in.

nebula-ai call leave <thread> takes you out. nebula-ai call end <thread> ends it for everyone, so reach for that one deliberately.

Talking without joining

nebula-ai call chat <thread> sends a message into a call and returns — useful from a script, or when you just want to answer a question without putting on a headset.

nebula-ai call chat thr_8f2a1c -m "ship it once staging is green"
$ nebula-ai call chat thr_8f2a1c -m "ship it once staging is green"
Sent.

It reads standard input when you leave -m off, so you can pipe into it — tail -f build.log | nebula-ai call chat thr_8f2a1c reads the pipe once, to the end, rather than flooding the call line by line.

Voice is a two-step opt-in

Because the CLI joins muted and data-only, getting your voice into the room takes two keys, in this order.

Press v to enter listening mode. The chip beside the call's title moves from ✎ chat to ◎ listening, and call audio starts playing.

Press m to unmute your microphone. The chip becomes ● voice and the room can hear you.

The chip is always the honest answer to "can anyone hear me?" — ✎ chat and ◎ listening both mean your mic is off. ● cam means your camera is on as well.

Reading the room

Everyone on the call gets a glyph, so you can follow along without audio at all. Agents get the fuller vocabulary, because there's more to say about what an agent is doing.

GlyphMeaning
Speaking now
Connected and listening
Disconnected

Agents add three more — working (running a tool), thinking, and in the background (working, but not speaking) — plus an [active] or [background] posture, and a written state beside the name while they're speaking, working or thinking. p switches an agent between the two. People show a glyph and a name only.

Keys inside a call

KeyWhat it does
iType a message
vEnter or leave voice
mMute or unmute your mic
oToggle the agent's audio
cCamera on or off
pSwitch the agent between active and background
r / wRecap / dispatched work
RReconnect
^PHang up
EEnd the call for everyone
EscBack

Running without a screen

--headless runs the audio engine with no interface at all, which is what you want on a server or in a container.

It's a machine interface rather than a readable one: instead of printing a confirmation and returning, it streams one JSON object per line to standard output and stays in the foreground until the call ends.

nebula-ai call join thr_8f2a1c --headless --chat
$ nebula-ai call join thr_8f2a1c --headless --chat
{"kind":"state","state":{"status":"connected","muted":true}}
{"kind":"log","level":"info","message":"joined data-only"}
…stays in the foreground; exits with a final {"kind":"exit"} line

Pair it with --chat to join data-only with no audio, or --muted to connect audio but never publish your microphone. Because it holds the terminal, run it under whatever keeps long-lived processes alive on that box.

Before you rely on it

Voice needs a working audio backend, and the camera needs ffmpeg on your PATH. Rather than finding out mid-call, ask the CLI what this machine can actually do.

nebula-ai capabilities
$ nebula-ai capabilities
Vision
camera gated (ffmpeg not found on PATH)
Audio
microphone available
speaker available
Call
mode voice
mic capture ffmpeg -f avfoundation -i :0 …
agent playback ffplay -nodisp -autoexit -

Every line under Vision and Audio reads available, gated or unsupportedgated means the machine could do it but something's in the way, and the note in parentheses says what. The Call block is different: it doesn't grade anything, it shows the mode the engine would pick and the exact commands it would run to reach your mic and speaker. That's the block to read when audio works elsewhere but not here.

Camera sits under Vision, not Call — a call uses it, but it's the machine's capability, and nebula-ai capabilities groups by what the machine has rather than by what wants it.

A call costs the same Nebula Credits per active minute whether you join from the terminal, the desktop app or your phone — it's billed once per call, not per person.

On this page