Shell & CLI Tools

Use cb-cli, cb-tree, cb-select and the browser Shell to inspect the Store.

Prefer a guided tutorial?

Follow the Inspect the Store from the Shell hands-on tutorial, then return here for the full reference.

ControlBird ships a family of command-line tools for inspecting and operating the in-memory Store directly, plus a browser-based Shell app that runs them inside the platform UI. Together they give operators and developers a fast, scriptable way to read and write entities, visualize the entity hierarchy, run filtered queries, and inspect logs and snapshots, all without leaving the running system.

Every tool connects to the kernel the same way as a service: through the Store client pointed at KERNEL_ADDRESS. When you launch a tool from the Shell app, the kernel address, node identity, data directory, and user attribution are all pre-configured for you, so the tools are immediately usable with no flags.

The Toolset

ToolPurpose
cb-cliInteractive REPL and one-shot client for store queries (read/write/create/delete/find/notifications/pipelines)
cb-treeHierarchical entity tree visualization with ASCII art and depth control
cb-selectCEL-filtered entity queries with pagination, field selection, and multiple output formats
cb-walChange-log inspection with timestamp filtering and follow mode
cb-snapshotSnapshot capture, restore, validation, diff reporting, and export

The Browser Shell

The Shell app opens a real terminal in your browser and relays input and output over the existing WebSocket connection. Access requires the app.shell permission, which is granted to the Owner role.

How Sessions Work

  • Access enforced continuously: the app.shell permission is required to open a session, and revoking a user's access takes effect immediately.
  • Sandboxed: terminal sessions run with restricted privileges so terminal access cannot reach beyond what the tools need.
  • UTF-8 ready: the terminal supports 256-color, UTF-8 output so box-drawing glyphs in text-based apps render correctly.

Environment Variables

Every Shell session and every tool it launches inherits a pre-configured environment so the tools find the kernel and identify the writer automatically.

VariablePurpose
KERNEL_ADDRESSKernel connection used as a fallback when no explicit host/port is given
NODE_IDNode identifier (used by cb-wal and cb-snapshot to locate data)
DATA_DIRRoot data directory for log files and snapshots
RUST_LOGLog level for the tools
CB_USER_IDCurrent user's entity ID, used for writer attribution in the audit trail
CB_USER_NAMECurrent user's name for the audit trail
CB_BIN_DIRDirectory of the cb-* binaries, prepended to PATH

CB_BIN_DIR is added to PATH so that cb-cli, cb-tree, cb-select, and cb-wal are immediately discoverable in a Shell session.

# Inside a Shell session, the environment is already wired up
echo $KERNEL_ADDRESS    # prints the kernel address
echo $CB_USER_ID        # your user entity ID, used for write attribution
cb-cli                  # launches the REPL with no flags needed

Session limits

Each connection supports up to 4 concurrent terminal sessions, with up to 20 sessions in total across all users. These limits keep terminal usage from exhausting platform resources.

AI Tool Sessions

Beyond a plain bash shell, the Shell app can launch AI coding tools (Claude Code, Codex, OpenCode) in dedicated sessions. These run non-interactively for safety. An AI tool session replaces the shell context for that session rather than nesting inside an existing one.

cb-cli: Interactive Store Client

cb-cli is the primary tool for reading and writing the store. It runs as an interactive REPL (prompt kernel>) or executes a single command in one-shot mode. Interactive history is stored in ~/.kernel_history.

# Launch the REPL (explicit host/port, or rely on KERNEL_ADDRESS)
cb-cli --host localhost --port 9100

# Read the Name and Status fields from entity 42
GET 42 name status

# Find Device entities matching a CEL filter
FIND Device 'Name == "Motor-1"'

# Subscribe to Status changes on entity 42, fetching parent atomically
LISTEN @42 Status CHANGE parent
POLL 100

The REPL groups its commands by purpose. Key commands include:

GroupCommands
Entity CRUDGET, SET, CREATE, DELETE, EXISTS
Type / field resolutionGETTYPE/RESTYPE, GETFLD/RESFLD
QueriesFIND, FINDPAG, FINDEX, TYPES, TYPEPAG (CEL filters supported)
SchemaGETSCH, GETCSCH, SETSCH
NotificationsLISTEN, UNLISTEN, POLL
Indirection & miscRESOLVE, PIPELINE, SNAP, NODE, INFO, LOGS, HQUERY, PING
SessionHELP, HISTORY, CLEAR, EXIT/QUIT

Output formatting is controlled with --format human|json|csv. The --raw flag prints the raw, unformatted response for debugging, and --eval <file> runs a batch of commands from a file.

cb-tree: Entity Hierarchy

cb-tree builds and prints the entity hierarchy starting from the Root entity. It walks each entity's children recursively and renders the result as an ASCII tree. The Root is discovered automatically; if more than one Root is found, the tool warns.

# Show the tree two levels deep with entity IDs appended
cb-tree --max-depth 2 --show-ids
FlagEffect
--max-depthMaximum levels to descend (0 means unlimited)
--show-idsAppend each entity's ID to its name
--show-typesShow the entity type alongside each node
--verboseShow additional detail per node

Deep hierarchies can be slow

With --max-depth 0 there is no depth cap. Trees with very deep nesting or many children at each level may take time to build and render. Set a depth limit when you only need the top of the tree.

cb-select: Filtered Queries

cb-select queries entities of a given type, optionally filtered by a CEL expression, and prints selected fields in your chosen format. It is the right tool for reporting and bulk inspection. By default it returns the Name field if you do not specify --fields.

# Active devices, CSV output with IDs, showing Name and Status
cb-select --entity-type Device \
  --filter 'IsActive == true' \
  --fields Name,Status \
  --format csv --show-ids
FlagEffect
--entity-typeEntity type to query (required)
--filterCEL expression; supports indirection, e.g. "Parent->Name"
--exactMatch the exact type only (no subtypes)
--fieldsComma-separated field list with -> indirection support
--limit / --page-sizeCap results (0 = unlimited) and control pagination
--formatOne of table, json, csv, ids, count
--show-ids / --show-typesInclude the entity ID / type columns
--exportWrite results to a JSON file
--metricsReport per-page and per-field timing and throughput

Field indirection like Parent->Name is resolved recursively. Note that per-field resolution happens sequentially across entities, so queries returning thousands of entities with many fields can be slow.

cb-wal: Change Log

The change log records every store mutation. cb-wal reads the log files in data/<node>/wal/ and prints each recorded change. Use --follow to stream new entries as they are written.

# Stream change-log entries from node-a in real time
cb-wal --node node-a --follow --format compact
FlagEffect
--nodeNode whose log directory to read
--followWatch the log for growth and stream new entries
--start-time / --end-timeRFC3339 timestamp filters
--formatcompact or json output
--infoShow log file metadata

Follow granularity

--follow checks for new entries frequently, so it is near-realtime. A corrupted entry stops parsing at that point, and the rest of the file is not read.

cb-snapshot: Point-in-Time State

cb-snapshot captures and restores the entire store as a single snapshot file, and can validate, diff, and export snapshots. Snapshots are the foundation of backup and disaster recovery for a node.

# Capture the live store to a snapshot file
cb-snapshot take --output snapshot.db --core-url localhost:9100

# Compare the live store against a snapshot and write a diff report
cb-snapshot report --input snapshot.db --core-url localhost:9100 \
  --output diff.txt --format text
SubcommandPurpose
takeCapture the current store state to a .db snapshot file
factory-restoreRestore by recreating the data directory and node (requires --force if targets exist)
normal-restoreApply a snapshot to a live store
reportGenerate a diff report (text or JSON) against the live store
validateCheck snapshot integrity
exportExport the snapshot to SQL dumps

Restore is not atomic

Snapshot and factory-restore operations are not atomic. A partial failure can leave the data directory and node structure in an inconsistent state. Verify backups with validate and treat restores as maintenance operations.

Connection & Attribution

All tools share the same connection logic. They read KERNEL_ADDRESS as a comma-separated failover list, connect to the kernel, resolve entity and field types, and enable pagination and CEL filtering. Writes are attributed to CB_USER_ID, so changes made from a Shell session are recorded against the user who made them in the audit trail.

Limitations

  • Up to 4 terminal sessions per connection, and up to 20 in total across all users.
  • Terminal input is sent in frames of up to 64KB; split large pastes or pipe via file redirects.
  • Terminal dimensions range from 4 to 500 rows and columns.
  • cb-tree --max-depth 0 and cb-select --limit 0 are unlimited and can be slow or memory-heavy on large data.
  • cb-select resolves fields one at a time, with no batching across entities.
  • cb-wal --follow is near-realtime; a corrupted entry halts parsing at that point.
  • Restore operations are not atomic; partial failures can leave inconsistent state.
  • CLI tools cannot be nested inside other sessions; AI tool spawns replace the shell context.

For deploying a node where these tools run, see the configuration walkthrough. To secure the endpoints the tools connect through, see the certificates guide.