A ANDROMEDADocumentation › Guides

Using the CLI

The bun run main.ts assistant is a local coding and personal assistant. Its commands and keys follow Claude Code and the Codex CLI, and it works with Ollama, Docker Model Runner, or llama.cpp.

Launching

bun run main.ts                 # full-screen TUI; the current directory is the workspace
bun run main.ts --plain         # line REPL (automatic when stdin/stdout isn't a terminal)
bun run main.ts --model qwen3:8b
bun run main.ts --add-dir ~/notes
bun run main.ts --listen        # start in hands-free voice mode
bun run main.ts whatsapp link   # chat from WhatsApp (see below)

From another directory, run bun ~/path/to/andromeda-js/main.ts (or an alias for it) so that directory becomes the workspace. Every option is listed under Command-line flags.

MCP servers, the knowledge graph and other slow services connect in the background after the UI opens, so you can start typing straight away. /doctor checks the configured model server and reports model capabilities.

The terminal UI

The TUI is a scrolling transcript with • replies and tool calls, a Working (12s • esc to interrupt) status line and a › composer. Tool calls show what they do: a red/green diff with line numbers for edits, the start of a new file, the command for shell calls. When they finish, a one-line summary replaces the raw output, such as "Read 120 lines", "Updated app.py · +3 −1" or "Found 14 matches".

KeyAction
EnterSend. Prompts typed while a turn runs are queued.
↑ / ↓Recall earlier prompts, or move through the / command popup
/ then TabComplete a slash command
EscInterrupt the running turn (or stop a spoken reply)
Shift+TabCycle permission mode: auto → plan → ask
← on an empty promptLive view of subagents and background tasks
Ctrl+TFull transcript: complete tool output and reasoning
Ctrl+RToggle hands-free voice mode
Ctrl+C / Ctrl+DQuit

Set OLLAMA_CONTEXT_WINDOW to your server's context size to see context-used percentages. At 90% the conversation is summarized automatically and the turn continues; see Context compaction.

Permission modes

The mode decides which tool calls need your approval. Switch with Shift+Tab or /permissions auto|plan|ask, and set the default with agent.permission_mode.

ModeBehavior
autoTools run freely, except the always-ask calls below.
planRead-only. Edits, commands, downloads, browser clicks and generation are refused. The agent investigates and writes a plan for you to review.
askEvery tool that changes something (writes, commands, non-read-only MCP tools, browser actions) asks first.

In every mode, the CLI asks before a destructive or outward-facing shell command (rm, sudo, git push, git reset --hard, curl … | sh, DROP TABLE, …) and before creating or running a tool the model wrote. Answering always approves only that exact command or tool for the rest of the session. Turn this off with agent.confirm_destructive: false.

Plan, review, then build

  1. Switch to plan and describe the change. The agent reads and searches, writes a plan with update_plan and summarizes it, leaving the steps open.
  2. Read it with /plan (or open the Markdown file under .andromeda/plans/), edit it if you like, and ask for changes until it's right.
  3. Switch back to auto and say "go ahead". The agent carries the saved plan out step by step, and a turn can't end with steps left undone.

See Planning & verification for how plans and the verifier work.

Slash commands

Read-only commands (/status, /context, /usage, /diff, /plan, …) run immediately, even while a turn is in progress. Others queue behind it.

Session and model

CommandAction
/helpCommands and keyboard shortcuts
/statusModel, context window, token usage, MCP and session status
/model [name]List installed models, or switch. The switch reaches every running Andromeda process (TUI, REPL, background service, voice server) within a fraction of a second, moves subagents with it, unloads the old model and warms the new one
/config [key value]Show settings, or change reasoning and UI preferences (thinking on|off|auto, reasoning low|medium|high|…, show-thinking, recaps, tips, recap-after <seconds>)
/doctorCheck the configured model server, tool support, and context size
/permissions [auto|plan|ask]Show or change the permission mode (also /approvals)
/shortcutsKeyboard shortcuts
/exit, /quitQuit

Conversations and context

CommandAction
/clear (/new)Start a new conversation; the old one stays in /resume
/resume [id]List saved conversations, or resume one (also /threads)
/forgetPermanently delete the current conversation
/compact [focus]Summarize the conversation to free context. With memory, continue in a new thread seeded with the summary.
/contextWhat is filling the context window
/usage (/cost)Session token totals
/plan [clear]Show this conversation's saved plan, or delete it
/memoryShow working memory
/reindexRebuild semantic-recall vectors from saved history
/export [file]Save the conversation as Markdown in the workspace
/steer <context>Add information to the running task at its next model step
/btw <question>A side answer that doesn't enter the main conversation

Working on code

CommandAction
/initHave the agent create or improve AGENTS.md
/review [focus]Have the agent review uncommitted changes (read-only)
/diffShow uncommitted changes, including new files
/mention <path>Attach a workspace file to your next message
/add-dir [path]Let tools read and write another folder this session

Tools, agents and media

CommandAction
/toolsCore tools and on-demand tool groups
/skills [query]List or search skills
/agentsSubagent profiles and this session's subagents
/tasks [cancel <id>]Running and recent background tasks, or cancel one
/mcpMCP servers, their status and tools
/voice [on|off]Listen continuously and speak replies (also Ctrl+R)
/voice kokoro, /voice qwen [VOICE]Pick the speaking engine and Qwen voice
/plugin (/plugins)Loaded plugins and any that failed
/hooksConfigured shell hooks
/image <prompt>Generate an image without going through the model (also /imagine)
/image edit <change>Edit the last image; each edit becomes the new last image
/image qwen|ollamaSwitch image provider; /image alone shows status

Claude Code-style commands

Commands from Claude Code work too: /effort, /fast, /output-style, /rename, /fork (/branch), /rewind (/checkpoint), /copy, /security-review, /simplify, /pr-comments, /loop, /schedule, /artifacts, /insights, /theme, /vim, /statusline and more, with aliases such as /todos, /stats, /code-review and /settings. Ones that need an Anthropic account (/install-github-app, /mobile, …) say what to use instead.

Learning

CommandAction
/good, /badRate the last answer, so its recipe is reused or dropped
/learned [delete <id>]List learned recipes and stats, or delete one
/teach …Record a task you demonstrate and turn it into a skill (below)

Shell & teach mode

Start a line with ! to run a shell command in the workspace yourself. The output is shown and sent along with your next message, so you can say "fix this" after a failing test run:

› !bun test tests/calc.test.ts
› the divide test fails, fix it

Teach mode turns a task you do yourself into a reusable skill:

› /teach release-notes write release notes from git
› !git log --oneline v1.2..HEAD
› /teach note fixes go before features
  … edit files in your editor …
› /teach stop          # shows the drafted SKILL.md
› /teach save          # keeps it under skills/learned/ (or /teach discard)

Only ! commands and file changes inside the workspace are recorded; nothing watches in the background. /teach cancel stops without drafting.

Command-line flags

FlagEffect
--model NAMEOverride OLLAMA_MODEL
--config PATHYAML settings file (default ANDROMEDA_CONFIG or ./andromeda.yml)
--workspace PATHWorkspace for tools, skills, personality and outputs (default: current directory)
--add-dir DIRAlso let tools use DIR (repeatable)
--plainLine REPL instead of the TUI
--no-streamWait for each complete model response
--think / --no-thinkEnable or disable model reasoning
--quietHide progress and metrics
--memory none|local|qdrantMemory provider (default MEMORY_PROVIDER)
--resource-id IDIdentity that scopes long-term memory (default local-user)
--thread-id IDConversation identity (default default)
--listenStart in hands-free voice mode
--no-audio, --no-images, --no-videosLeave out voice, image generation or video generation
--browser / --no-browserLet the assistant drive a real browser
--browser-visibleShow the Playwright browser window (the default here)
--heartbeat / --no-heartbeatSelf-started check-ins

Managing MCP servers

Add Model Context Protocol servers the same way as claude mcp or codex mcp. Servers connect the next time Andromeda starts.

# stdio: everything after -- is the command line
bun run main.ts mcp add playwright -- npx -y @playwright/mcp@latest
bun run main.ts mcp add -e API_KEY='${MY_KEY}' myserver -- bunx my-mcp-server

# remote (Streamable HTTP by default; --transport sse for legacy servers)
bun run main.ts mcp add --transport http postman https://mcp.postman.com/minimal \
    --header 'Authorization: Bearer ${POSTMAN_API_KEY}'

bun run main.ts mcp list    # connects to each server and reports ✓/✗
bun run main.ts mcp get postman
bun run main.ts mcp remove postman

Project servers are written to mcp.json; without one, the JSON files under mcp/ are the project list (see bundled MCP servers).

Put single quotes around ${VAR} so your shell doesn't expand it; the config then stores the reference, not the secret. Other options: --scope project|user, --description, --always-loaded and --force. See MCP servers for the config files and per-server options.

Agent API and web chat

The TypeScript app can serve its configured agent over an OpenAI Chat Completions-compatible HTTP API. The API uses the same tools, memory and permission rules as the terminal app, and it supports streamed replies, conversation IDs, per-turn model and sampling settings, tool selection, and retrieval controls.

API_HOST=127.0.0.1 API_PORT=8791 bun run main.ts api serve
# For a network interface, set a private token:
API_HOST=0.0.0.0 API_TOKEN=your-long-random-token bun run main.ts api serve

Clients send POST /v1/chat/completions with a Bearer token and a messages array. Use stream: true for server-sent events and pass the returned conversation_id on later turns. GET /v1/models lists available models; GET /v1/settings reports active defaults. Requests can set model, system_prompt, sampling values, tools, permission_mode (auto, ask, plan) and retrieval (auto, on, off). Configured server permissions remain in force.

When an action needs approval, the stream sends a andromeda.approval event. Clients can also check GET /v1/approvals?conversation_id=… and answer with POST /v1/approvals/:id using approve, always or deny. An unanswered approval expires after five minutes.

Attachments, audio and browser UI

Chat requests can use multipart form data with a JSON payload and repeated attachments fields: up to eight files, 12 MiB each and 24 MiB total. Uploaded files are saved in the API workspace under .andromeda/web-uploads/ for the agent to inspect. Audio endpoints list configured voices at GET /v1/audio/voices, synthesize speech at POST /v1/audio/speech and transcribe multipart audio at POST /v1/audio/transcriptions.

The standalone React chat in web/ connects to this API, stores conversations and connection settings in browser storage, and supports attachments, microphone input, spoken replies, approvals, and inline weather, image, audio, YouTube and map cards. Run it with cd web && bun install && bun run dev; allow its exact origin in api.cors_origins (or API_CORS_ORIGINS). Keep the API on loopback for local use. Binding to a network interface requires api.token; use HTTPS when exposing it beyond a trusted local network.

Configure api.host, api.port, api.token and api.cors_origins in andromeda.yml, or use API_HOST, API_PORT, API_TOKEN and API_CORS_ORIGINS.

One turn path for terminal and web

The TUI, the REPL and both API chat endpoints run a turn through the same code (runTurn in src/app/turn.ts). Web chats now get what the terminal always had: the workspace refresh, UserPromptSubmit and Stop hooks, file checkpoints for /rewind, and the "Keep going?" question when a turn reaches the tool-call limit, answered through the approval broker. Attachments are read the same way everywhere: text, PDF and Office files go inline, images go to vision models (or to view_image for models without vision), and other files are passed by path. Each web conversation keeps its own checkpoint turn, so concurrent chats no longer share one. reasoning_effort (none to max) picks a thinking level, and GET /v1/models reports the levels each model accepts.

Web app pages and accounts

Besides chat, the web app has a Command Center (every live run and subagent shown as a crew member at a station, with what it is doing and who it reports to), Code Review (review picked paths, local changes or a pull request; findings come with a suggested fix you approve or reject, plus optional Snyk and SonarQube scans), Library, Memory (browse, search and prune what is stored in Qdrant), Skills (install from a repository or folder, including every skill in it at once, and switch skills on or off), Scheduled, Images and Settings.

The API supports password accounts for the web app: POST /v1/auth/signup, /v1/auth/login and /v1/auth/logout, GET /v1/auth/me, and GET/PATCH /v1/auth/users for admins. The first account becomes an admin and owns conversations from before accounts existed. Passwords are hashed with scrypt and only a hash of each 30-day session token is stored, in .andromeda/web-auth.db (see Database). Users see only their own memories; admins can see everyone's.

Chat from WhatsApp

Message Andromeda from your phone. It links to your own account like WhatsApp Web, using an unofficial client (Baileys).

Unofficial clients are against WhatsApp's terms, and the number could be banned.

bun run main.ts whatsapp link      # scan the QR code: WhatsApp → Settings → Linked devices
bun run main.ts whatsapp status
bun run main.ts whatsapp unlink

Then set whatsapp.enabled: true in andromeda.yml, start Andromeda, and message yourself:

whatsapp:
  enabled: true
  primary_user: "+27810000000"  # only this identity receives owner memory and private tools
  
  allowed: []        # other numbers, digits with country code, e.g. ["447700900123"]
  notify: true       # also send schedule results and check-ins to your own chat
  reply_prefix: "🤖 "
  • Who it answers: your own "Message yourself" chat and the numbers in allowed. Everyone else is ignored. Set primary_user to your exact phone number; allowed contacts get separate conversations and do not receive owner memory or private tools.
  • Conversations: each chat is its own thread, sharing long-term memory with the terminal. Replies start with the prefix so you can tell them apart in your own chat.
  • Approvals: anything that needs approval is asked in the chat; reply yes, always or no (no answer in five minutes means no).
  • Media: images, documents and voice notes are supported; voice notes can receive spoken replies. Contacts and outgoing messages are available through tools, with approval required before sending.

Catching up: messages that arrive while the PC sleeps or Andromeda is stopped are answered when it reconnects, if they are within whatsapp.catchup_hours (default 24). A backlog in one chat gets a single reply that says how late it is, and a reply cut off by a restart is answered again. Ask Andromeda to "catch up on WhatsApp" to run the whatsapp_catch_up tool by hand. Images now reach the model directly, without a tool call.

Voice calls

Live calls use Meta's WhatsApp Business Calling API on a separate business number; linked-device chat cannot carry call audio. Configure whatsapp.calls, with the Meta app secrets in .env or under whatsapp.calls in andromeda.yml. Andromeda only answers calls you start; it refuses requests that could place a billed call and hangs up if a call is reported as business-initiated. Calls that need tool approval are declined because nobody can approve them by voice.

Always-on service and triggers

Schedules, event triggers and heartbeat check-ins only run while Andromeda is active. The background daemon keeps them running after you close the terminal:

./start.sh background             # start detached
./start.sh status
./start.sh logs 50
./start.sh stop
bun run main.ts daemon install    # start at login
bun run main.ts daemon uninstall

The installed service starts with your user session on macOS, Ubuntu or Windows. It owns WhatsApp, schedules, triggers, webhooks and heartbeat while it runs; a TUI or REPL opened alongside it leaves those services to the daemon. Use /daemon to inspect its status.

Event triggers

Ask Andromeda to run a prompt when new mail arrives, an event is approaching, files change, or a webhook fires. Manage configured triggers with /triggers. Gmail and calendar triggers use the Google MCP login; file triggers watch workspace paths; webhook triggers accept a secret token on the local endpoint. The first polling check records existing state, so old mail or files do not fire as new events.

Trigger runs are unattended: event content is treated as untrusted input, tool approvals are enforced, and each trigger is rate limited. The daemon log records results without saving prompts or event contents. Plugins can add trigger kinds of their own.

Web app and usage dashboard

Run the web client in development with bun run main.ts:web and the API with bun run main.ts:api. After bun run build:web, the API serves the built web app itself. The API starts the usage dashboard at http://127.0.0.1:8790 by default; run it separately with bun run main.ts:dashboard, or pass --no-dashboard to api serve to suppress it.

See Web app & dashboard for the current navigation, live-session and history views, Model Hub, memory and library, automations, dashboard Playground and Flows, traces, connected devices, and safe remote access.