The cb Helper CLI
ClaudusBridge auto-generates a Python helper script at Saved/ClaudusBridge/cb.py on every MCP initialize. It is the preferred interface for AI agents (and humans) — collapsing the JSON-RPC envelope + python -c '...' unwrap pattern into single-line subcommands with sane defaults.
If you find yourself writing this:
curl -sS -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":\
{"name":"spawn_basic_shape","arguments":{"shape":"Cube",\
"label":"Foo","location":[0,0,200]}}}' \
| python -c "import sys,json; r=json.loads(sys.stdin.read())\
['result']['content'][0]['text']; print(json.loads(r)['data'])"
…stop and use cb instead:
cb spawn Cube label=Foo location=[0,0,200]
Setup
The script is auto-generated and overwritten on every initialize. Don't edit it directly — extend the generator in Source/ClaudusBridge/Private/CBFileGenerators.cpp if you need a new subcommand.
# Convenience alias (Bash / Zsh)
CB='python "C:/Users/Diux/Documents/Unreal Projects/<YOUR_PROJECT>/Saved/ClaudusBridge/cb.py"'
eval "$CB topics"
# PowerShell
function cb { python "C:\Users\Diux\Documents\Unreal Projects\<YOUR_PROJECT>\Saved\ClaudusBridge\cb.py" @args }
cb topics
The script is pure stdlib (urllib.request + argparse + json); no pip install required. It works with any Python 3.8+.
Subcommand reference
cb call <tool> [json_args]
Generic MCP tool dispatch. Args is a JSON object string. Output is the unwrapped data section as JSON.
cb call get_current_map
cb call list_actors '{"class_filter":"StaticMeshActor"}'
cb call set_view_mode '{"mode":"wireframe"}'
The envelope ({result:{content:[{text:"<status/data JSON>"}]}}) is unwrapped automatically. You get the data block directly. On status:"error" from the tool, cb exits non-zero with the error message on stderr.
cb spawn <shape> [k=v ...]
Shorthand for spawn_basic_shape with smart value parsing.
cb spawn Cube label=MyCube location=[0,0,200] color=red
cb spawn Sphere x=420 y=69 z=180 scale=3 color=blue
Three layers of value parsing per k=v token: JSON first (so location=[0,0,200] is a real array, not a string), then float/int, then bare string fallback. Color names auto-expand to UE rgba strings:
| Name | Expanded value |
|---|---|
red | (R=1.0,G=0.1,B=0.1,A=1) |
green | (R=0.1,G=1.0,B=0.1,A=1) |
blue | (R=0.1,G=0.4,B=1.0,A=1) |
yellow | (R=1.0,G=0.9,B=0.1,A=1) |
orange | (R=1.0,G=0.5,B=0.1,A=1) |
purple | (R=0.6,G=0.2,B=0.8,A=1) |
white / black / gray | as expected |
Pass any other rgba string verbatim if you need a custom color.
cb tx <label>
get_actor_transform <label> — just the transform dict.
cb tx MyCube
Returns location, rotation, scale, bounds, and label.
cb capture [savepath] [--frame ACTOR] [--view MODE]
One-shot screenshot via the Codex in Chrome local bridge. Optional pre-framing:
cb capture
cb capture C:/tmp/shot.png
cb capture --frame MyCube --view lit /tmp/closeup.png
--frame ACTOR calls focus_viewport_on_actor first. --view MODE calls set_view_mode. Both apply BEFORE the capture so the PNG is on-target.
Returns {screenshotPath, bytes, existingTab}. If existingTab: true the user's already-open /preview tab was reused (zero UI activity for the user — preferred). Otherwise a fresh background tab was opened.
cb capture requires the Codex in Chrome local bridge running on 127.0.0.1:8791. If it isn't, fall back to your MCP client's browser automation (e.g. Claude in Chrome MCP computer screenshot tool).
cb verify <tool_call> <expected> [--frame ACTOR] [--view MODE]
The iterative verification round-trip in one command:
cb verify "spawn_basic_shape Sphere at [420,69,180]" \
"blue sphere visible at world (420,69,180)" \
--frame Parity_AB_Sphere --view lit
Internally:
- Drains primary's queue
- Publishes
verification.needed { tool_call, expected, framing } - Block-polls primary's queue for
verification.confirmed/verification.rejected - Prints
[CONFIRMED]or[REJECTED]followed by the watcher's plain-text observation
Exit code 0 on confirmed, 2 on rejected, 1 on timeout. Requires a watcher subscribed on session visual-watcher.
cb pub <channel> <json_payload>
publish_agent_event with sane defaults (from = primary).
cb pub screenshot.request '{"reason":"see what is selected in the outliner"}'
cb pub delegate.material '{"action":"recompile"}' --target visual-watcher
--target SESSION for targeted delivery; omit for broadcast (excludes the sender).
cb poll <session> [channel] [--timeout 60] [--clear|--no-clear]
Block until a matching event lands in <session>'s queue. Replaces the bash until grep ...; do sleep N; done regex loop pattern.
cb poll primary verification.confirmed --timeout 90
cb poll visual-watcher agent_message
Default --clear=true (drains the queue on poll, like the bridge's default).
cb stream
pixel_streaming_status — readiness check before any capture. Always run this if the editor was just relaunched.
cb stream
Returns {ready, signalling_running, streaming_started, viewer_url, preview_bare_url, hint}. Use ready=true as the gate before cb capture.
cb watcher-prompt
Print the canonical SYSTEM PROMPT block from Saved/ClaudusBridge/watcher_subagent.prompt.md (the inner ``` block), ready to pipe into your Agent-spawn primitive.
cb watcher-prompt > /tmp/wp.md
# Then pass /tmp/wp.md to Claude Code's Agent tool, Codex CLI's
# sub-agent spawn primitive, or any other equivalent.
cb sessions
Approximate active session count (via a no-op subscribe).
cb sessions
Memory subcommands
cb also exposes the persistent shared knowledge base. See Memory System for the full pattern.
cb remember <topic> "<summary>" [--body "..."] [--kind tip|gotcha|...] [--tags a,b]
cb recall [topic] # markdown content to stdout
cb topics # tabular listing
cb search <query> # full-text snippets
cb learn # alias for cb recall
Global options
All subcommands accept these:
| Flag | Default | Effect |
|---|---|---|
--bridge URL | http://localhost:3000/mcp | MCP HTTP endpoint |
--codex URL | http://127.0.0.1:8791 | Codex local bridge |
--from SESSION | primary (or subcommand-specific) | from_session for pub / remember |
--target SESSION | unset | target_session for pub |
--frame ACTOR | unset | pre-framing actor for capture / verify |
--view MODE | unset | pre-framing view mode for capture / verify |
--timeout SEC | 60 | HTTP / poll timeout |
--raw | off | print full JSON-RPC response (debugging) |
Why use cb instead of raw curl?
| Pain point with raw curl | How cb fixes it |
|---|---|
| ~250 chars per call (envelope + escape + unwrap) | ~50 chars per call |
JSON-shell-escape footguns (' inside ', etc.) | k=v parsing avoids most quoting |
Two-level JSON parsing (outer envelope + inner text) | Auto-unwrapped to data |
Easy to silently swallow events (grep regex bugs) | cb poll is timeout-aware and explicit |
| Color names need manual rgba expansion every time | Built-in name → rgba |
| Verification round-trip needs 5 calls + parser | cb verify collapses to 1 |
In a typical iterative session of 30 tool calls, cb saves several thousand characters of boilerplate and removes the most common parsing footguns. That's the difference between programming smoothly and fighting JSON-RPC escaping.
Extending cb
The script is generated by FCBToolMetadataRegistry::GenerateCBHelperScript() in Source/ClaudusBridge/Private/CBFileGenerators.cpp. The script body is split across multiple TEXT(R"PY(...)PY") raw-string chunks (each ≲ 8 KB) to stay under MSVC's 16 380-byte per-string-literal limit (C2026 error). FString += concatenates them at runtime; the on-disk cb.py is byte-identical to the source.
To add a new subcommand:
- Edit your local
Saved/ClaudusBridge/cb.pyand add the function. - Re-inject into the generator (the canonical pattern is a small Python script that reads
cb.py, splits into chunks ≲ 8 KB, and rewrites the generator function body inCBFileGenerators.cpp). - Rebuild the plugin (
Build.bat OCPROEditor Win64 Development …). - Relaunch the editor; the next
initializeregeneratescb.pybyte-identically to the source.
Next steps
- EYES MANDATORY — the foundational rule for any agent driving the editor
- Iterative Dialogue — how to talk to the watcher while you work
- Memory System — persistent shared knowledge across sessions and agents