Skip to content

BeastCLI — Macro System for Power Users

The BeastCLI (tb cli) is ToolBoxV2's interactive shell. Its macro system lets you record, build, share, and run multi-step automation — from a single keystroke or a Docker container.

Starting BeastCLI

tb cli

Profile developer or homelab opens it as default via bare tb.


Core Concepts

Concept What it is
Macro Named sequence of CLI commands, stored in cli/macros.json via BlobFile
Variable $r1, $r2 — auto-captured results; $arg1, $1 — macro arguments
MacroContext Isolated execution state per macro run (variables, loop vars, flags)
Workspace Named environment with its own modules + startup commands

Variable scope priority (highest wins):

loop vars  >  macro vars  >  CLI quick vars ($r1, $r2, ...)


Creating Macros

Method A — Interactive wizard

:macro create

Walks you through: name → description → commands (empty line ends) → tags → loop count.

Method B — Record live

:record my_deploy
# ... run commands normally ...
stop_recording

Every command you execute gets captured verbatim.

Method C — Import from file

:macro import /path/to/macros.json
# or
:macro import https://... (when registry sharing is set up)

File format (from _export_macros):

{
  "version": "1.0",
  "exported_at": "2025-01-01T00:00:00",
  "macros": {
    "my_macro": {
      "commands": ["echo hello", "DB get_status"],
      "description": "Example",
      "variables": {},
      "tags": ["example"],
      "loop_count": 1
    }
  }
}


Running Macros

:play my_macro          # interactive selector if no name
:play my_macro arg1 arg2   # with arguments → $1, $arg1
@my_macro               # shortcut prefix (same as :play my_macro)

Result is stored automatically:

💾 Macro result saved as $r3


Control Flow Reference

All of these work inside macro commands lists:

# This is a comment

set counter = 0
set items = ['a', 'b', 'c']

for item in $items: echo $item
for i in range(5): mymod process $i

while $counter < 10: set counter = $counter + 1

if $r1 == 'ok': echo success
if $r1 != 'ok': break

sleep 2.5
return $counter

Loop safety limit: 1000 iterations (hardcoded in _handle_macro_while).


Export & Share

Export to file

:macro export

Select which macros, enter output path → JSON file with schema above.

Share via Registry

# Pack macros as feature
tb manifest pack my_macros

# Upload
tb registry upload ./features_sto/tbv2-feature-my_macros-1.0.0.zip

# Others install:
tb fl unpack my_macros
# Then in BeastCLI:
:macro import ~/.local/share/ToolBoxV2/features/my_macros/macros.json

Pre-defined Macro Packs

server-ops — Server Admin Pack

{
  "macros": {
    "health_check": {
      "commands": [
        "echo '=== Service Health ==='",
        "DB get_status",
        "set db_ok = $r1",
        "if $db_ok != 'ok': echo 'WARNING: DB not healthy'",
        "echo '=== Worker Status ==='",
        "echo 'Health check done'"
      ],
      "description": "Quick server health check",
      "tags": ["server", "ops"]
    },
    "rotate_logs": {
      "commands": [
        "set date = '$(date +%Y%m%d)'",
        "echo 'Rotating logs for $date'",
        "sleep 1",
        "echo 'Log rotation complete'"
      ],
      "description": "Rotate and archive logs",
      "tags": ["server", "maintenance"]
    }
  }
}

dev-workflow — Developer Pack

{
  "macros": {
    "test_and_pack": {
      "commands": [
        "echo 'Running tests...'",
        "set mod = $arg1",
        "if $mod == '': return 'ERROR: provide mod name as arg1'",
        "echo 'Packing $mod...'",
        "echo 'Done: $mod'"
      ],
      "description": "Test then pack a mod. Usage: :play test_and_pack mymod",
      "tags": ["dev", "workflow"]
    }
  }
}

Multi-Instance: Each in its own Docker Container

Run isolated BeastCLI sessions — one per project, team member, or environment.

Setup

Dockerfile.minicli — place in repo root:

FROM python:3.12-slim

RUN useradd -m tbuser
WORKDIR /home/tbuser

# Install ToolBoxV2
RUN pip install --no-cache-dir ToolBoxV2

# Pre-load macros from a pack (optional)
COPY macros/ /home/tbuser/.local/share/ToolBoxV2/features/macros/

USER tbuser

# Data dir per container (macros, history, context persist in volume)
ENV TB_DATA_DIR=/home/tbuser/.local/share/ToolBoxV2/.data

CMD ["tb", "cli"]

Start isolated sessions:

# Instance 1 — Project A
docker run -it --rm \
  -v tb_proj_a:/home/tbuser/.local/share/ToolBoxV2/.data \
  --name tb_proj_a \
  toolbox-cli

# Instance 2 — Project B (completely separate macros + state)
docker run -it --rm \
  -v tb_proj_b:/home/tbuser/.local/share/ToolBoxV2/.data \
  --name tb_proj_b \
  toolbox-cli

Each container gets its own cli/macros.json and cli/context.c via the named volume. BlobFile writes to TB_DATA_DIR — so volumes cleanly isolate all state.

Execute a macro non-interactively

# Run macro and exit — useful for CI or scripting
docker run --rm \
  -v tb_proj_a:/home/tbuser/.local/share/ToolBoxV2/.data \
  toolbox-cli \
  tb cli -- :play health_check

Multiple sessions on the same machine (no Docker)

# Session 1: default workspace
TB_DATA_DIR=~/.tb/workspace_a tb cli

# Session 2: different data dir → completely separate macro set
TB_DATA_DIR=~/.tb/workspace_b tb cli

BlobFile("cli/macros.json", ...) resolves relative to TB_DATA_DIR, so this cleanly separates all state without Docker overhead.


Keyboard Shortcuts Reference

Shortcut Action
Ctrl+P Command palette
Ctrl+R History search
Ctrl+S Save last result as $rN
Ctrl+T Toggle compact mode
Alt+H Smart help for current input
Alt+V Show variables
:macro Macro manager
:record <name> Start recording
:play <name> Execute macro
:v View all $ variables