agentmomo-cli
v0.1.2
Published
CLI for integrating with the AgentMomo 3D world — command avatars from your terminal with a local open model (Ollama)
Readme
agentmomo-cli
A terminal CLI for the AgentMomo 3D world. Talk to it in plain
language and it commands your world avatars — spawn them, walk them between
buildings, sit them at desks, travel between scenes, hand them vehicles — the
same things Claude Code does via /agentmomo, but driven by a local open
model instead of Claude.
By default it runs that model via Ollama (qwen2.5:7b)
through a pluggable LLMBackend interface; a zero-model rule-based stub is
the automatic fallback (and available on demand with --stub). It also carries
local coding tools (read/write/list/bash), and every tool call it makes is
mirrored into the world as an animated character.
Quick start
cd agentmomo-cli
npm install # installs dev deps (tsx, esbuild, typescript)
ollama serve # start the local Ollama server
npm run dev # banner → REPL (default model: qwen2.5:7b)On first run a short setup wizard checks Ollama, the model, and the bridge,
and offers to pull the model for you (re-run anytime with --setup). To pull
manually: ollama pull qwen2.5:7b (~4.7 GB).
Model & speed: the default is
qwen2.5:7bbecause it fits entirely in an 8 GB GPU (fast). Bigger models likegemma4:12bare stronger but spill to CPU on small GPUs and run much slower. Switch with--model <tag>.
Then just chat naturally:
what is this project?
list the files in src
read package.json and tell me the versionNo model installed yet? The CLI prints a note and falls back to the stub, where you can drive tools directly:
read package.json
list src
write notes.txt: hello from agentmomo-cli
run echo hiexit / quit / Ctrl+C to leave.
How it fits together
bin/cli.ts banner → readline REPL → runTurn() per line
src/brand.ts BRAND_NAME, ACCENT, GRADIENT, TAGLINE ← retheme here
src/colors.ts theme module: palette roles + gradient (TTY/NO_COLOR/FORCE_COLOR)
src/banner.ts printBanner(): box + gradient wordmark (uses colors.ts)
src/llm.ts LLMBackend interface + StubBackend (rule-based, zero model)
src/ollama.ts OllamaBackend — real local model via Ollama (tool-calling)
src/tools.ts coding tools: read_file / write_file / list_dir / bash
src/worldTools.ts world tools: spawn / walk / sit / enter / exit / travel / vehicle
src/agentLoop.ts chat → toolCalls → emit events → run tool → feed back → repeat
src/momoBridge.ts emitEvent(call_start|call_end) → POST /api/eventCommanding the 3D world (the open-model /agentmomo)
This is the same capability as agentmomo's /agentmomo Claude Code command, but
driven by the local open model instead of Claude + MCP. With the AgentMomo
bridge running and the world open in a browser, just describe what you want:
spawn an agent named scout in the forest
make scout walk to the library and sit down
travel scout to the city and give it a city-car
who is in the world right now?The model picks the right world tool and the avatar reacts live. World tools
(in src/worldTools.ts, mirroring the momo_* MCP tools):
| Tool | Bridge call | Does |
| ---- | ----------- | ---- |
| world_list_agents | GET /api/openworld/agents | list avatars + the active one |
| world_spawn_agent | POST /api/openworld/spawn-agent | place a standing avatar (biome, name, character) |
| world_walk_to | POST /api/openworld/agent-command walk_to | walk to a building / coords |
| world_enter_building| … enter_building | walk in and step inside |
| world_sit | … sit_at_workzone | find a desk and sit |
| world_exit_building | … exit_building | stand up and leave |
| world_travel_to | … travel_to_scene | move to city/forest/desert/ocean/palace |
| world_give_vehicle | … spawn_vehicle | spawn a vehicle and board it |
These throw on failure (bridge down, unknown agent, bad biome) so the model reports the problem, unlike the silent activity-event emission.
Like /agentmomo, if you don't specify a character when spawning or a
vehicle when boarding, the model asks you to pick from the roster first
(scene aliases work too — "neon"/"cyberpunk" → city).
The command pipeline works headlessly (avatars register on the server), but the visible animation needs the openworld open in a browser — it's WebSocket-driven.
Backends
The default is ollama (a real local model). The stub is the automatic
fallback and can be forced with --stub.
| Backend | Selected by | Needs |
| -------- | ----------- | ----- |
| ollama | default (no flag), --ollama, or MOMO_BACKEND=ollama | ollama serve + a pulled model |
| stub | --stub, MOMO_BACKEND=stub, or auto-fallback | nothing |
Flags: --stub (force the stub), --ollama (force Ollama), --model <tag>
(override the model), --setup (re-run the setup wizard). Precedence: flags >
MOMO_BACKEND env > ollama default.
Running with the default local model (Ollama)
Fully offline — no cloud key.
ollama serve # start the local server (if not already running)
ollama pull qwen2.5:7b # ~4.7 GB, one time (or let the wizard do it)
npm run dev # default backend = ollama, model = qwen2.5:7b
npm run dev -- --model gemma4:12b # stronger but needs more VRAMOn Windows cmd you can also use the env var (set MOMO_BACKEND=ollama).
If the server is unreachable or the model isn't pulled, the CLI prints a clear note and falls back to the stub so it's always usable.
Choosing a model for your GPU: the model must fit in VRAM or it offloads to
CPU and gets slow. qwen2.5:7b (~4.7 GB) fits an 8 GB GPU; qwen2.5:3b /
llama3.2:3b are even faster; gemma4:12b is stronger but needs ~10 GB+.
Ollama config (env, with defaults):
| Variable | Default | Purpose |
| -------------- | ------------------------- | ---------------------- |
| OLLAMA_HOST | http://localhost:11434 | Ollama server base URL |
| OLLAMA_MODEL | qwen2.5:7b | Model tag to run |
World integration
src/momoBridge.ts POSTs events to the bridge:
- Endpoint:
POST ${AGENTMOMO_BRIDGE_URL ?? "http://localhost:9001"}/api/event - Auth:
Authorization: Bearer $AGENTMOMO_API_KEYis sent only if that env var is set (the local bridge needs no auth). - Failure mode: if the bridge is down, events are silently dropped — the CLI still works standalone.
To see the character, run the AgentMomo bridge (npx agentmomo in the sibling
project), open the world, then issue commands here.
Environment variables
| Variable | Default | Purpose |
| ----------------------- | ------------------------ | ------------------------------------ |
| AGENTMOMO_BRIDGE_URL | http://localhost:9001 | Where to POST world events |
| AGENTMOMO_API_KEY | (unset) | Bearer token, only sent if set |
| AGENTMOMO_AGENT_ID | agentmomo-cli-local | Stable id → one character in world |
| NO_COLOR | (unset) | Disable all ANSI color (always wins) |
| FORCE_COLOR | (unset) | Force color even when piped/non-TTY |
Theming
All color lives in src/colors.ts, driven by the palette in src/brand.ts.
Edit ACCENT, ACCENT_MUTED, and the GRADIENT stops to retheme the whole CLI
(banner wordmark, prompt, status, tool activity). Color is on for interactive
TTYs, off when piped (or NO_COLOR), and forceable with FORCE_COLOR=1.
Adding another backend
Everything behind the LLMBackend interface (src/llm.ts) is swappable:
StubBackend(src/llm.ts) — deterministic rules, zero model.OllamaBackend(src/ollama.ts) — a real local model via Ollama.
To add a cloud provider (Anthropic/OpenAI-compatible) or a different runtime,
implement chat(messages, tools) returning { text } or { toolCalls }, then
select it in selectBackend() in bin/cli.ts. src/llm.ts has commented
sketches for a local GGUF (node-llama-cpp) and a cloud endpoint.
Caveat: the loop is model-agnostic, but agentic quality lives in the model's tool-calling. A small open model will be weaker at file editing than a frontier model — "offline" and "frontier-quality" pull in opposite directions. The interface lets you pick that trade-off;
OllamaBackendalso parses a JSON tool-call from plain text as a fallback for models with weak native function-calling.
Install & distribute
The CLI bundles to a single dependency-free file with esbuild, so it can be installed from npm.
npm run build # → dist/cli.js (single file, node shebang)
node dist/cli.js # run the built CLI directlypackage.json is publish-ready: bin → dist/cli.js, files → ["dist/",
"README.md"], and prepublishOnly runs typecheck + build. First publish:
npm login # one-time (CLI auth, separate from the website login)
npm publish --access public
# then anyone: npx agentmomo-cli (or npm i -g agentmomo-cli)Shipping updates
npm refuses to republish the same version, so each update needs a version bump. One command does bump → typecheck → build → publish:
npm run release # patch bump (0.1.0 → 0.1.1) and publish
npm run release:minor # 0.1.0 → 0.2.0
npm run release:major # 0.1.0 → 1.0.0If your npm account has 2FA-for-publishing, you'll be prompted for the 6-digit
code (or append -- --otp=123456). Run it in your own terminal so the prompt
works.
End users update with npm i -g agentmomo-cli@latest (or npm update -g
agentmomo-cli). npx agentmomo-cli always fetches the newest version.
What end users still need (agentmomo-cli is a front-end to local infra, not self-contained):
- Node 18+ — for
fetchand the bundle. - Ollama + a pulled model — the brain. The first-run wizard detects Ollama and offers to pull the model.
- The AgentMomo bridge (
npx agentmomo) — only for the 3D-world commands; the coding tools work without it.
The coding half works the moment Ollama is set up; the world half also needs the bridge running with the world open in a browser.
