Logging
Purpose
Clawperator logs every significant event to a local NDJSON file for post-run diagnostics. An agent can inspect this file after a timeout or failure to determine what happened step by step.
Log File Location
Logs are written to a daily file at:
~/.clawperator/logs/clawperator-YYYY-MM-DD.log
The path components are:
| Component | Value | Source |
|---|---|---|
| Base directory | ~/.clawperator/logs |
Default, or CLAWPERATOR_LOG_DIR env var |
| Filename prefix | clawperator- |
Hardcoded in formatLogPath() in contracts/logging.ts |
| Date format | YYYY-MM-DD |
Local calendar date of the log entry (from formatDate() in contracts/logging.ts) |
| Extension | .log |
Hardcoded in formatLogPath() in contracts/logging.ts |
Example path: /home/user/.clawperator/logs/clawperator-2026-03-28.log
To change the base directory, set the CLAWPERATOR_LOG_DIR environment variable. See Environment Variables for details.
NDJSON Format
Each line is a valid JSON object (NDJSON - Newline Delimited JSON). No wrapping array, no trailing commas. One event per line.
Required Fields
Every log event has these fields:
| Field | Type | Description |
|---|---|---|
ts |
string | ISO 8601 timestamp (e.g., 2026-03-28T12:34:56.789Z) |
level |
string | One of: debug, info, warn, error |
event |
string | Dot-separated event name (e.g., skills.run.start) |
message |
string | Human-readable summary |
Optional Context Fields
Events may include additional context fields:
| Field | Type | Present When |
|---|---|---|
commandId |
string | CLI command or execution has a correlation ID |
taskId |
string | Part of a larger task sequence |
deviceId |
string | Event targets a specific device |
skillId |
string | Skill execution event |
stream |
string | stdout or stderr for skill output lines |
status |
string | Completion status (e.g., pass, fail) |
durationMs |
number | Operation completed, measured in milliseconds |
exitCode |
number | Process exit code for skill/execution events |
Example Log Lines
{"ts":"2026-03-28T10:15:30.123Z","level":"info","event":"skills.run.start","message":"Skill com.example.app.get-status started","skillId":"com.example.app.get-status","commandId":"cmd-123"}
{"ts":"2026-03-28T10:15:30.456Z","level":"info","event":"skills.run.output","message":"Opening app...","skillId":"com.example.app.get-status","stream":"stdout"}
{"ts":"2026-03-28T10:15:32.789Z","level":"info","event":"skills.run.complete","message":"Skill com.example.app.get-status completed successfully in 2345ms","skillId":"com.example.app.get-status","durationMs":2345,"exitCode":0}
Log Levels
Four levels are available, in order of increasing severity:
| Level | Numeric Value | Use Case |
|---|---|---|
debug |
0 | Detailed diagnostic information |
info |
1 | Normal operational events |
warn |
2 | Unexpected but recoverable conditions |
error |
3 | Failures that prevent intended operation |
Threshold Behavior
The --log-level flag (or CLAWPERATOR_LOG_LEVEL env var) controls which events are written to the file. Events at or above the threshold are logged.
| Setting | Events Logged |
|---|---|
debug |
All events (debug, info, warn, error) |
info |
info, warn, error (default) |
warn |
warn, error |
error |
error only |
Default: info (from normalizeLogLevel() in adapters/logger.ts)
Valid values: debug, info, warn, error (case-insensitive)
Invalid values fall back silently to info.
Exception: Skill output events (skills.run.output) are always written to the file regardless of level threshold, so agents can diagnose timeouts even when --log-level error is set.
Event Naming Conventions
Events use dot-separated names with prefix-based categories:
| Prefix | Category | Example |
|---|---|---|
skills.run. |
Skill execution lifecycle | skills.run.start, skills.run.complete |
cli. |
CLI output | cli.banner |
doctor. |
Doctor diagnostics | doctor.check |
serve. |
HTTP/SSE server | serve.server.started, serve.http.request |
The clawperator logs Command
Stream the log file in real time.
Usage
clawperator logs
Behavior
- Dumps all existing content from the current daily log file to stdout
- Streams new lines as they are written
- Runs until interrupted
Interrupt
Press Ctrl+C (SIGINT) to stop. The command exits with code 0.
Output Format
Raw NDJSON lines on stdout. No formatting, no filtering, no color.
No Flags
The command accepts no flags. It always operates on the current daily log file determined by CLAWPERATOR_LOG_DIR (or the default ~/.clawperator/logs).
Missing File Behavior
If the log file does not exist, the command writes a message to stderr and exits with code 0:
No log file found at /home/user/.clawperator/logs/clawperator-2026-03-28.log
Fail-Open Behavior
If the log directory cannot be written to (permissions, disk full, path does not exist), Clawperator:
- Writes one warning to stderr
- Disables file logging for the remainder of the process
- Continues normal operation
Example warning (includes the error message when available):
[clawperator] WARN: logging disabled after write failure for /home/user/.clawperator/logs/clawperator-2026-03-28.log: EACCES: permission denied, mkdir '/home/user/.clawperator'
The command or skill still executes normally. Only the log file is affected.
Verification
Confirm logging is active:
# Check the log file exists and has recent content
ls -la ~/.clawperator/logs/
# Stream logs in real time
clawperator logs
Generate log entries:
# Skill runs produce lifecycle and output events
clawperator skills run <skill_id> --device <device_serial>
# Snapshot commands produce execution lifecycle events
clawperator snapshot --device <device_serial>
Verify entries appear:
# Check for skill lifecycle events
grep '"event":"skills.run.start"' ~/.clawperator/logs/clawperator-$(date +%F).log
# Check for the CLI banner (emitted at debug level during skill runs)
grep '"event":"cli.banner"' ~/.clawperator/logs/clawperator-$(date +%F).log
# Parse the NDJSON file with jq to see all events from a specific category
jq -c 'select(.event | startswith("skills.run."))' ~/.clawperator/logs/clawperator-$(date +%F).log
Note: cli.banner is logged at debug level. To see it in the file, use --log-level debug.
Environment Variables
See Environment Variables for complete details on:
CLAWPERATOR_LOG_DIR- Change the log directory base pathCLAWPERATOR_LOG_LEVEL- Set the file logging threshold
JSON Mode Cleanliness
When --json output mode is active, the unified logger never writes to stdout. Log events go only to the file. This ensures the JSON output stream remains parseable without interleaved log lines.