Replay NDJSON execution logs

NDJSON format

The replay panel expects one JSON object per line, in this order (the panel groups events by tick):

{"type":"tree","root":{...}}
{"type":"tick_begin","tick":1}
{"type":"transition","tick":1,"nid":0,"to":"RUNNING"}
{"type":"transition","tick":1,"nid":1,"to":"SUCCESS"}
{"type":"tick_end","tick":1,"result":"SUCCESS"}
{"type":"tick_begin","tick":2}
{"type":"transition","tick":2,"nid":0,"to":"RUNNING"}
{"type":"tick_end","tick":2,"result":"RUNNING"}

Field reference

Field Type Notes
type string tree, tick_begin, transition, or tick_end.
tick int Zero-indexed tick number.
nid int Node ID, assigned by pre-order DFS from the tree root.
to string New status: IDLE, RUNNING, SUCCESS, FAILURE.
result string Tick outcome (only on tick_end).
root object Tree definition (only on first tree event).

How to capture a run

The editor doesn't generate the log itself — it consumes logs produced by whatever behavior-tree engine you run in production (or in a test harness). Two common ways to get a log:

Option A: instrument a BehaviorTree.CPP runner

In your C++ code, hook the tree's tick callbacks and write JSON lines to a file:

// Pseudocode — adapt to your BTCPP version
BehaviorTree::Tree tree;
tree.tickWhile([&](const Tree& t) {
  int tick = t.tickCount();
  std::cout << R"({{"type":"tick_begin","tick":{}}})" << tick << "}\n";
  for (auto node : t.nodesInExecutionOrder()) {
    std::cout << R"({{"type":"transition","tick":{}})" << tick
              << R"(,"nid":)" << node->id()
              << R"(,"to":")" << to_string(node->status()) << "\"}\n";
  }
  std::cout << R"({{"type":"tick_end","tick":{}})" << tick
            << R"(,"result":")" << to_string(t.rootNode()->status()) << "\"}\n";
  return true;
});

Option B: stream via WebSocket

Use the editor's built-in WebSocket viewer to receive ticks live. See Live monitor via WebSocket.

Loading the log

  1. Click the 📊 Replay button in the header. The right drawer slides open.
  2. Under Load log, click Choose file and select your .jsonl.
  3. Or click Load example to load the bundled sample run.

Once loaded, the tree is drawn automatically and the playback controls activate.

Playback controls

Control Effect
▶ / ⏸ Play / pause auto-replay.
Stop and rewind to tick 0.
⏮ / ⏭ Step one tick back or forward.
Tick slider Scrub to any tick in the loaded range.
Speed dropdown 0.5x / 1x / 2x / 5x / 10x replay speed.

Reading the visualization

Each node on the canvas is overlaid with a status color:

When a node transitions to RUNNING / SUCCESS / FAILURE, the editor briefly flashes its border to draw your eye. The status bar at the top of the replay panel shows the current tick number and final result.

Tip — using replay to debug flaky behavior

Capture 5–10 runs of the same scenario. Replay each one and watch which nodes flash RUNNING or FAILURE at each tick. If the same node fails in 8 of 10 runs, that's your bug. The replay panel makes intermittent failures observable in a way that's hard to get from log scraping.

Sharing logs

The .jsonl log is a plain text file. Send it via Slack, email, or commit it to your repo. Recipients can open it in the same editor and see exactly what you saw — no out-of-band screenshots needed.

← Import & export WebSocket live monitor →