Logging
NimbleBrain writes a structured workspace event log as JSONL (one JSON object per line) to daily rolling log files. These logs capture workspace-level events — bundle lifecycle, skill and file changes, data and config mutations, tool-surface changes, and audit signals.
Configuration
Section titled “Configuration”Control logging through the logging object in nimblebrain.json:
{ "logging": { "dir": "~/.nimblebrain/logs", "disabled": false, "level": "normal", "retentionDays": 30 }}| Field | Type | Default | Description |
|---|---|---|---|
dir | string | {workDir}/logs | Directory where log files are written. Created automatically if it does not exist. |
disabled | boolean | false | Set to true to disable structured logging entirely. |
level | "normal" | "debug" | "normal" | "debug" persists additional verbose fields (full tool inputs/outputs, raw provider responses). Larger files. |
retentionDays | integer | — | Auto-delete log files older than N days on startup. Omit for no cleanup. |
Structured logging is enabled by default. To disable it:
{ "logging": { "disabled": true }}Log file naming
Section titled “Log file naming”Log files follow a daily rolling pattern under a workspace/ subdirectory of dir:
{dir}/workspace/YYYY-MM-DD.jsonlA new file is created automatically each day. Examples:
~/.nimblebrain/logs/workspace/2026-03-25.jsonl~/.nimblebrain/logs/workspace/2026-03-26.jsonlLog entry format
Section titled “Log entry format”Every log line is a JSON object: a timestamp, the event type, and the event’s own data fields spread alongside them.
{"ts":"2026-03-25T14:30:00.123Z","event":"bundle.installed","serverName":"postgres","bundleName":"@nimblebraininc/postgres","version":"1.2.0"}Common fields
Section titled “Common fields”| Field | Type | Description |
|---|---|---|
ts | string | ISO 8601 timestamp of when the event was recorded. |
event | string | Event type (e.g., bundle.installed, data.changed, audit.permission_denied). |
Remaining fields vary by event type — they are the event’s payload, written inline.
Event types
Section titled “Event types”Only workspace-level events are written to this log; conversation streaming events (text.delta, tool.start, and the like) are not.
Bundle lifecycle — bundle.installed, bundle.uninstalled, bundle.upgraded. Track connectors entering, leaving, and upgrading in the workspace.
{"ts":"2026-03-25T14:30:00.123Z","event":"bundle.installed","wsId":"ws_product","serverName":"postgres","bundleName":"@nimblebraininc/postgres","version":"1.2.0","trustScore":92}data.changed — A tool mutated workspace data. Carries the server and tool that wrote, and source: "agent" when emitted from the agent’s tool dispatch.
{"ts":"2026-03-25T14:30:01.200Z","event":"data.changed","source":"agent","server":"tasks","tool":"create_task"}config.changed — Workspace configuration was modified.
skill.created, skill.updated, skill.deleted — A workspace skill or context file changed. Carry the skill’s id (filesystem path), name, and scope.
{"ts":"2026-03-25T14:30:02.000Z","event":"skill.created","id":"/skills/triage/SKILL.md","name":"triage","scope":"workspace","type":"skill"}file.created, file.deleted — A workspace file was added or removed. file.created carries id, filename, mimeType, and size.
{"ts":"2026-03-25T14:30:03.000Z","event":"file.created","id":"file_abc","filename":"report.pdf","mimeType":"application/pdf","size":20184}tool.promoted, tool.released — A tool entered or left the active tool set. Carry the runId and toolName; tool.released adds reason: "evicted" when the engine reclaimed a slot under the active-tool cap.
{"ts":"2026-03-25T14:30:04.000Z","event":"tool.promoted","runId":"abc123","toolName":"postgres__query"}bridge.tool.done — A bridged tool call completed.
http.error — An HTTP-level error surfaced in the workspace.
audit.auth_failure — Authentication failed for a request. Carries ip, method, and path.
{"ts":"2026-03-25T14:30:05.000Z","event":"audit.auth_failure","ip":"203.0.113.7","method":"POST","path":"/api/chat"}audit.permission_denied — A user declined a tool’s confirmation prompt. Carries the tool, the unprefixed action, and the target (or null).
{"ts":"2026-03-25T14:30:06.000Z","event":"audit.permission_denied","tool":"tasks__delete","action":"delete","target":"task-42"}Querying logs
Section titled “Querying logs”Log files are plain JSONL, so you can use standard command-line tools:
# Bundles installed todaycat ~/.nimblebrain/logs/workspace/2026-03-25.jsonl \ | jq 'select(.event == "bundle.installed") | {bundleName, version}'
# Audit events onlycat ~/.nimblebrain/logs/workspace/2026-03-25.jsonl \ | jq 'select(.event | startswith("audit."))'
# Count events by typecat ~/.nimblebrain/logs/workspace/2026-03-25.jsonl \ | jq -s 'group_by(.event) | map({event: .[0].event, count: length})'Log rotation
Section titled “Log rotation”A new file is created each day. Set retentionDays to have NimbleBrain delete log files older than that threshold on startup. Without it, files accumulate and you can manage retention with standard tools:
# Delete workspace logs older than 30 daysfind ~/.nimblebrain/logs/workspace -name "*.jsonl" -mtime +30 -delete