NebulaNebula
CLI

Command reference

Every nebula-ai command and subcommand, plus the global flags, environment variables, JSON output for scripting, shell completion, and the logs.

Every nebula-ai command, what it does, and the flags that apply everywhere. Run nebula-ai <command> --help for the options on any one of them - that output is generated from the binary you have, so it's always current.

Not installed yet? Install the CLI first, then sign in with nebula-ai login.

Commands

CommandWhat it does
loginAuthenticate with Nebula via device-flow pairing
logoutClear stored credentials
statusShow CLI status overview
open <link>Open a nebula://open link in the full-screen app - --json prints the entity instead
chatSend a message to an agent DM and print the reply
callVoice calls - see below
channelsManage channels and how they're set up - see below
messagesSend, read, edit, share and react to messages, and title or close the thread under one - see below
inboxThe threads addressed to you, and their Done list - see below
tasksStart, follow and organise tasks - see below
jobsScheduled tasks - see below
agentsCreate, read and configure agents - see below
miniappsThe workspace's apps - see below
skillsWorkspace and personal skills - see below
workspaceManage workspaces - list, switch, create
local-deviceManage computer use and the local device daemon - see below
installSet up computer use - an alias of local-device enable
uninstallTurn off computer use, stop the daemon, and remove this device
capabilitiesProbe and print this host's capability snapshot
logsInspect Nebula log files on disk - logs path prints the directory
updateCheck for a newer CLI version and install it
completionGenerate a shell completion script
acpRun Nebula as an editor agent over the Agent Client Protocol

Run nebula-ai with no command at all to open the full-screen app.

Agents

Everything except list and create takes the agent's ID or handle as its first argument.

CommandWhat it does
agents create <name> -d <description>Create an agent and print its ID - --model, --channel <handle> to put it on a channel's team, --toolkit <slug> (repeat for more), and --access none|read|write for what the rest of the workspace may do with it
agents listList the workspace's agents
agents get <agent>Get an agent's details
agents update <agent>Update an agent - --name, --description, --model
agents enable <agent>Enable an agent
agents disable <agent>Disable an agent
agents remove-toolkit <agent> <toolkit>Take a toolkit away from an agent, by toolkit slug
agents delete <agent>Delete an agent
agents skills list <agent-id>List skills attached to an agent
agents skills detach <agent-id> <skill>Detach a skill from an agent

Asking Nebula for the agent you need in any conversation still works, and creates it with whatever detail you describe. Connected apps aren't managed from the shell either: connect them in the full-screen app under Settings → Integrations, or see Connections.

To give an agent a new skill, ask Nebula to install it from a link, or save one yourself with skills save. See Skills and slash commands.

Channels

channels manages channels and how they're set up - the same changes as a channel's settings in the full-screen app. Messages live under messages, and a channel's tasks and calls under tasks list --channel and call list --channel. Everything except list, create and archived takes the channel's handle as its first argument, and home names your own Nebula. (--help calls that argument <space>.)

CommandWhat it does
channels listList your channels, with handle, access, unread count, whether its heartbeat is on, and description
channels create <name>Create a channel - --kind private keeps it to invited members; shared is the default
channels join <channel>Join an open channel you aren't in yet, by handle or name
channels rename <channel> <new-name>Rename a channel
channels delete <channel>Delete a channel
channels archivedList archived channels
channels unarchive <channel>Bring an archived channel back
channels purpose <channel> <purpose>Set what a channel is for - its Purpose
channels heartbeat <channel> <on|off>Switch the channel's heartbeat on or off - its Autonomous mode
channels miniapps <channel>List the apps available from a channel
channels add-miniapp <channel> <miniapp>Put one of the workspace's apps on a channel, by ID or name
channels remove-miniapp <channel> <miniapp>Take an app off a channel - the app itself stays
channels model <channel> <model>Set the model for new tasks in a channel, or Home's own model with home
channels default-model <channel> <model>Set the default model for new tasks in a channel
channels appearance <channel>Set a channel's icon and colour - --icon and --color are both required
channels agents <channel>List a channel's agents
channels add-agent <channel> <agent>Add an agent to a channel, by agent ID
channels remove-agent <channel> <agent>Remove an agent from a channel
channels devices <channel>List the devices linked to a channel
channels add-device <channel>Add a cloud device to a channel - --size <size>, small by default - or this computer with --local
channels remove-device <channel> <device>Remove a device from a channel
channels default-device <channel> [device]Make one of a channel's linked devices the default for its new tasks, by device ID - leave the device off to clear the default
channels members <channel>List the members of a private channel
channels invite <channel> <member>Invite a workspace member to a private channel
channels remove-member <channel> <member>Remove a member from a private channel
channels member-role <channel> <member> <role>Make a private channel's member an admin or a member

Whether you can rename or delete a channel is Nebula's call for that channel, not the CLI's - when you can't, the command prints the reason it was given.

CLI 0.1.24 moved messages, and a channel's tasks and calls, out of channels. Scripts that sent or listed them there need messages send, messages list, tasks list --channel and call list --channel now. Start a call in a channel with call start --channel <handle>.

Messages

Every message command works in a channel - your own Nebula unless you pass --channel <handle> - or inside a task with --task <id>.

CommandWhat it does
messages send [text]Send a message - pipe it in on standard input when you leave the text off. --agent <handle> tags an agent in it
messages listRead recent messages - --limit <n>, 30 by default
messages replies <id>Read the replies to a message, oldest first - --limit <n>, 50 by default
messages edit <id> <text>Edit one of your messages
messages delete <id>Delete one of your messages
messages react <id> <emoji>React to a message with an emoji
messages unreact <id> <emoji>Take your reaction off a message
messages share <id> --to <channel>Share a message into another channel, or home - it shows there with the original's author and text
messages close <root-id>Close a thread for everyone in it - a reply or a new task reopens it. While any of its tasks are running it refuses, unless you pass --stop to stop them first
messages threadsList the threads you're part of - --channel <handle> for every one in a channel, --all adds the ones a reply only mentioned you in, --closed lists closed ones, --limit <n>
messages title <root-id> <title>Title a thread, for everyone in it
nebula-ai messages send --channel launch-team "@Release Manager is staging green?"
$ nebula-ai messages send --channel launch-team "@Release Manager is staging green?"
Sent to #launch-team.

A thread is addressed by the ID of the message that started it, which messages list prints.

Inbox

The inbox holds the threads addressed to you, the same list the full-screen app's rail shows. A thread marked Done leaves your inbox until something new arrives in it.

CommandWhat it does
inbox listList the threads in your inbox - ! needs you, * is unread. --sort created|updated picks arrival or latest activity, --limit <n> (50 by default)
inbox list --doneList the threads you marked Done instead, newest first
inbox done <root-id>Mark a thread Done - it leaves your inbox until something new arrives
inbox restore <root-id>Move a thread you marked Done back to the top of your inbox

Tasks

A task is one piece of work with its own conversation. Everything except list and create takes the task's ID as its first argument - tasks list prints it in the ID column, newest first.

CommandWhat it does
tasks listList your tasks - --channel <handle> for one channel's, --limit <n> (20 by default)
tasks create <message> --agent <handle>Start a task for an agent on the channel's team, and print its ID - --channel <handle> places it (your own Nebula when you leave it off)
tasks get <id>Show a task's title, channel, agent and work status, its number in its thread, and the thread it lives in
tasks rename <id> <title>Rename a task
tasks stop <id>Stop the work running on a task
tasks model <id> <model>Pin the model a task runs on
tasks read <id>Mark a task read
tasks archive <id>Archive a task

tasks list --json and tasks get --json also print task_number, thread_root_id, waiting_on_user_id and created_at.

Read a task's conversation with messages list --task <id>, and add to it with messages send --task <id>.

nebula-ai chat --task <id> "…" sends to a task without opening it, and nebula-ai chat --resume <task-id> opens that task directly in the full-screen app.

Calls

The calls page covers what each of these feels like to use.

CommandWhat it does
call startStart a call in --channel <slug> and open the call screen; --json returns its details without opening the app
call join <task>Join an existing call
call listList the workspace's calls, live ones first - --channel <handle> for one channel's, --limit <n> (20 by default)
call chat <task>Send a one-shot typed message into a call
call leave <task>Leave a call you're in

Scheduled tasks

The jobs commands manage scheduled tasks. Everything except list and create takes the job's ID or slug.

CommandWhat it does
jobs listList the scheduled tasks you can see
jobs get <job>Show one
jobs createCreate one as a draft - --name and --cron <expression> are required; --agent names the agent that runs it, --timezone the zone the schedule is read in, --description what it does
jobs update <job>Change its --name, --description, --cron or --agent
jobs run <job>Run it now
jobs pause <job>Pause it
jobs resume <job>Resume it
jobs delete <job>Delete it

A new job starts as a draft: its agent writes the steps, and jobs resume turns it on.

Apps

The miniapps commands work on the workspace's apps. Put one on a channel with channels add-miniapp.

CommandWhat it does
miniapps listList the workspace's apps
miniapps get <app>Show an app, by ID or name
miniapps create <name> --agent <agent>Create an app - the agent you name (not Nebula) builds it. --description says what it's for
miniapps delete <app>Delete an app

Skills

Skills for the whole workspace, or with --scope personal just for you.

CommandWhat it does
skills listList skills - a personal one that is one of your / commands prints as /name
skills save [name] --file <path>Create a skill from a SKILL.md, or replace the one with the same name. The name defaults to the one in the file. --command makes a personal one a / command, --no-command keeps it a plain skill
skills delete <name>Delete a skill

Local device

The computer use page explains when you'd reach for each.

CommandWhat it does
local-device enableTurn on computer use and start the daemon
local-device disableTurn off computer use and stop the daemon
local-device statusShow computer-use and daemon status, and check with the server which workspace this machine is bound to
local-device logsView daemon logs
local-device startStart the daemon
local-device stopStop the daemon
local-device restartRestart the daemon
local-device exec-mode getShow the current execution mode
local-device exec-mode set <mode>Set whether agents can run commands on this host
local-device claude-code getShow where claude resolves on this machine, and its version

Account and workspace settings

Your profile, billing, connected apps, models, variables and devices aren't shell commands since CLI 0.1.24. Change them in the full-screen app under Settings, or in the desktop or mobile app. Product analytics can be turned off under Settings → Preferences → Telemetry, or with the DO_NOT_TRACK environment variable.

Billing

Settings → Billing in the full-screen app shows the Nebula Credits balance with the Tool Credits row under it, the auto top-up settings, and the latest credit transactions. Three actions sit under them: Edit auto top-up, Add balance and Refresh.

Billing is owner-only here, as it is in the desktop app. Anyone else - and a member whose role hasn't loaded yet - still sees the screen, with Edit auto top-up and Add balance greyed out and "Only the workspace owner can manage billing." beside them, rather than hidden.

Edit auto top-up sets whether auto top-up runs, the balance it tops up at and how much it adds, then saves them for Nebula Credits through the same billing rules the desktop app uses. It needs a card Stripe has on file: until the workspace has one, the toggle stays locked and the form says to subscribe or make a top-up first. A workspace with nothing saved starts at the defaults, a $1 threshold and a $10 top-up amount.

Add balance opens the web billing page in your browser, and prints the address when no browser can be opened. Adding a card and buying credits stay on the web, so the terminal never asks for card details.

Using Nebula from your editor

nebula-ai acp runs Nebula as an agent over the Agent Client Protocol, speaking on standard input and output rather than drawing anything itself. Point an editor that speaks ACP at that command and Nebula answers inside the editor, with the same agents and channels you get everywhere else.

nebula-ai acp
$ nebula-ai acp
# no output - the editor drives it over stdin/stdout

Each session is scoped to the directory the editor opens it in, and that directory becomes the working folder the agent reads and writes in. The scoping comes from computer use, so run nebula-ai local-device enable first - without a registered device, sessions fail with "Nebula local device is not configured."

Run it by hand and it will sit there silently waiting for protocol messages. That's correct behaviour, not a hang - press Ctrl C to exit.

Global flags

These work on every command.

FlagWhat it does
--jsonOutput raw JSON
--workspace <id-or-slug>Run against a specific workspace, ignoring the active one
-v, --verboseVerbose output - the same as --log-level=debug
--log-level <level>One of error, warn, info, debug, trace
--no-colorDisable colours
--api-url <url>Point at a different API host

Environment variables

Useful when you can't pass flags - CI, containers, a shared shell profile.

VariableWhat it does
NEBULA_AUTH_TOKENUse a pre-minted token instead of the stored credential. Takes precedence over whatever login saved
NEBULA_API_BASEPoint at a different API host - the same thing --api-url does
NEBULA_WEB_URLPoint the links the CLI opens, such as sign-in, at a different Nebula host
NEBULA_HOMEOverride ~/.nebula, where credentials, settings, and logs live
NEBULA_LOG_LEVELOne of error, warn, info, debug, trace - the env form of --log-level
NEBULA_DEBUGSet to true for verbose logging - the same as -v
DO_NOT_TRACKSet to 1 to turn product analytics off. NEBULA_DO_NOT_TRACK works too
NEBULA_AI_NO_UPDATE_CHECKSet to 1 to skip the daily update check
NEBULA_AI_CACHE_DIROverride where npx nebula-ai caches the downloaded binary
NEBULA_AI_DOWNLOAD_BASEDownload that binary from a mirror instead - useful behind a strict firewall

NEBULA_AUTH_TOKEN is the one to reach for in CI. It skips the device-flow browser handoff entirely, which a build agent can't complete anyway.

Scripting

--json turns any command into something you can pipe. It's a global flag, so it works the same everywhere.

nebula-ai tasks list --json | jq -r '.[].title'
$ nebula-ai tasks list --json | jq -r '.[].title'
Launch retro
Design sync

tasks list --json emits a top-level array, so .[] works for the example above. A command that reads one thing, such as agents get, prints one object instead. Since CLI 0.1.22 the list and lookup commands print a fixed set of snake_case fields and nothing else, so a field the server adds later never shows up in your script; times are epoch milliseconds, and a field with no value is null. One that gets no answer within 30 seconds fails with "No answer came back in 30 seconds. Try again."

The columns a command prints don't always match its JSON field names. Run the command once with --json and read the shape before writing the jq.

Combine --json with --workspace in CI so a script never depends on whichever workspace happened to be active on that machine.

Exit codes and errors

A script can branch on the exit code instead of parsing what the command printed.

Exit codeWhat it means
0It worked
1Something failed - including a chat turn that failed
3You're not signed in, or the saved session can't be used. Run nebula-ai login
4chat stopped on a decision you have to make in Nebula, such as an approval - a question from the agent doesn't stop it
5The message went out, but what became of it isn't known

Exit 5 is the one to handle with care: sending again could repeat the work. Check nebula-ai messages list --task <id> first. nebula-ai status exits 3 when you're signed out, which makes it a cheap sign-in check.

Under --json, results stay on standard output and a failure is exactly one JSON line on standard error, with no colour codes:

nebula-ai status --json > /dev/null; echo $?
$ nebula-ai status --json > /dev/null; echo $?
3
# signed out - the status document still went to stdout
$ nebula-ai agents get nope --json
{"error":{"code":"error","message":"…"}}

The code is one of error, usage, auth_required or outcome_unknown. chat --json prints one object with thread_id, agent, status, final_message, events and pending - pending names the decision it's waiting on when status is waiting, and is null otherwise. A question the agent asks shows up in pending too, but status keeps reporting the turn itself and chat waits for the turn to finish instead of exiting 4 - the human-readable output tells you to answer it in Nebula or with nebula-ai chat --resume <id>.

Shell completion

nebula-ai completion prints a completion script for bash, zsh, or fish - source it from your shell profile.

nebula-ai completion zsh > ~/.nebula-completion.zsh
$ nebula-ai completion zsh > ~/.nebula-completion.zsh
# then add: source ~/.nebula-completion.zsh

When something goes wrong

nebula-ai status shows whether you're signed in and which workspace you're pointed at - most surprises are one of those two. nebula-ai capabilities reports what this machine supports, like whether ffmpeg is available for camera.

nebula-ai logs path prints the directory the log files live in (~/.nebula/logs/), ready to pipe into your pager. Re-run a failing command with -v for the detail.

nebula-ai update checks for a newer version and installs it. Worth trying before reporting anything.

Still stuck? Ask Nebula directly - it's good at drafting a support email with the right detail in it. For bugs or anything unresolved, email support@nebula.gg.

Put Nebula to work

Get Nebula on your computer or phone, then create your first channel and set its goal.

Get the apps

On this page