Comis writes detailed logs about everything it does — they are your primary tool
for understanding what is happening and diagnosing problems. Every message processed,
every agent execution, every health check, and every error is recorded.
Log file: ~/.comis/logs/daemon.log — A structured JSON file that is automatically
rotated when it gets too large (10 MB by default). The daemon keeps up to 5
rotated copies before deleting the oldest.
Console output: The same log data is also written to standard output. This is
what you see when using pm2 logs or journalctl.
Logs are in JSON format for machine readability. Each log line is a JSON object
with fields like level, msg, module, and timestamps. You typically view them
through pm2 or journalctl, which display them line by line.
"msg": "Tool execution complete" with "toolName": "bash"
trace
10
Most granular diagnostic level. Available but not used in the codebase by default.
(no standard examples — enable for deep protocol debugging)
The silent value exists at the logger API layer to suppress output, but the
daemon.logLevels configuration only accepts trace, debug, info, warn,
error, and fatal. To quiet a noisy module, raise its level (for example,
set it to error) rather than relying on silent.
Start with INFO (the default). Only switch to DEBUG when troubleshooting a specific
problem — DEBUG produces significantly more output. Use TRACE only for deep protocol
debugging. The FATAL and AUDIT levels are used by the system automatically — you
typically do not set them as module log levels.
Comis is organized into modules (daemon, agent, channels, scheduler, etc.), and you
can set a different log level for each one. This is useful when you want to debug a
specific part of the system without being overwhelmed by output from everything else.Add a logLevels section under daemon in your configuration:
Each module only logs messages at or above its configured level. In the example
above, the agent module logs everything including DEBUG messages, while the
channels module only logs warnings and errors.
The most common use case is setting agent: "debug" to see exactly what your agent
is doing during a conversation — which tools it calls, how long each LLM request
takes, and what context it retrieves from memory.
You can change log levels without restarting the daemon by using the
daemon.setLogLevel RPC command. This is useful for temporarily enabling DEBUG
logging to investigate an issue, then switching back to INFO when you are done.
# Enable debug logging for the agent modulecurl -X POST http://localhost:4766/rpc \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{"method":"daemon.setLogLevel","params":{"module":"agent","level":"debug"}}'
Runtime level changes take effect immediately and persist until the daemon restarts,
at which point the levels revert to whatever is in your configuration file.
Chat platform API errors (Discord, Telegram, Slack rate limits)
Check platform status and rate limit headers
Filter logs by errorKind to quickly find related problems. For example, to see
all authentication errors: grep '"errorKind":"auth"' ~/.comis/logs/daemon.log
The memory module (set its level under daemon.logLevels.memory, shown above)
emits two families of structured signal: step-tagged write/curation logs and
graceful-degradation WARNs.
Graceful-degradation WARNs (no silent degradation)
Recall degrades gracefully, and every degradation path logs a WARN carrying
the mandatory errorKind + hint pair (see Error Classification
above) — recall never drops to a cheaper path silently:
Degradation
WARN signal
Reranker unavailable / timed out → fusion-ranked fallback
WARN with errorKind + hint; corresponds to memory:reranked.fellBack / .timedOut
Vector index unavailable → FTS-only recall
WARN with errorKind + hint; corresponds to memory:recalled.vectorCandidates: 0
Candidate missing embedding, or invalid extraction/consolidation
WARN with errorKind + hint
As with all Comis logs, these never log secrets, message bodies, or absolute
paths — the per-recall ranking detail lives only in the opt-in, full-sanitized
recall-trace artifact,
never in daemon.log.
# Spot recall falling back to a cheaper pathgrep '"errorKind"' ~/.comis/logs/daemon.log | grep -i rerank
For the full “why did recall pick X / why is recall slow?” diagnosis flow, see the
Troubleshooting runbook.
Every log entry is a JSON object. Beyond the standard Pino fields (level, time,
msg, pid, hostname), Comis uses 48 canonical fields organized by category.
These are the fields you will see when reading JSON log output.
Comis automatically redacts sensitive information from log output. API keys, tokens,
passwords, and other credentials are replaced with [REDACTED] before being written
to the log file or console.The redaction engine covers all credential field name patterns across multiple nesting depths (top-level
through 3 levels of nesting):
Nested paths are also redacted: config.telegram.botToken, *.*.apiKey, etc.,
up to 4 levels deep (*.*.*.*).
You do not need to worry about sensitive data in logs. Comis automatically detects
and hides API keys, tokens, and passwords using a compiled redaction engine. The
redaction rules are compiled once at startup for zero runtime overhead.
Worst-case storage: 5 streams × 5 files × 50 MB = 1.25 GB.With compressAged: true (the default), gzipped JSON text compresses approximately 5×, so realistic steady-state is ~300 MB.Increase maxFiles or maxAgeDays if you need more history; reduce them on tight disks.
daemon.log — pino-roll handles size-based rotation in a worker thread; rotated files become daemon.1.log, daemon.2.log, etc. The daemon-startup sweep gzips any uncompressed rotated files and removes those beyond maxFiles or older than maxAgeDays.cache-trace.jsonl — a per-file cap (50 MB) prevents a single cache-trace file from growing unbounded. The startup sweep prunes accumulated history against maxFiles and maxAgeDays.config-audit.jsonl — a small (10 MB) rename-shift rotation runs on every append, keeping the active file write-friendly. The startup sweep gzips the resulting rotated copies and prunes them by count and age.session-index.YYYY-MM-DD.jsonl — a new file starts each UTC day (date-roll). Old dated files are pruned by the startup sweep against maxFiles and maxAgeDays. Only today’s dated file is treated as the active base and is never pruned.*.trajectory.jsonl — one file per agent session, with a 10 MB soft cap and a 50 MB hard cap applied in-session. Accumulated session files across past sessions are pruned by the startup sweep against maxFiles and maxAgeDays.
The legacy daemon.logging.maxSize and daemon.logging.maxFiles keys (documented below) continue to work for daemon.log specifically. When both are set, observability.logRotation takes precedence for the cross-stream sweep, and daemon.logging.maxSize retains its role as the pino-roll size threshold if you have not yet migrated to the new policy.
Operators are encouraged to migrate to observability.logRotation for a unified,
consistent rotation policy across all five log streams. The legacy daemon.logging
keys remain supported for backward compatibility but govern only daemon.log.
You can still customize per-file daemon-log rotation using the legacy keys:
# config.yamldaemon: logging: filePath: "~/.comis/logs/daemon.log" # where to write the active log file maxSize: "10m" # rotate when file reaches 10 MB maxFiles: 5 # keep up to 5 rotated copies
Setting
Default
What It Controls
filePath
~/.comis/logs/daemon.log
Path to the active log file. Supports ~ expansion.
maxSize
10m
Maximum file size before rotation. Supports k, m, g suffixes. When observability.logRotation.maxSizeBytes is set, it overrides this threshold for pino-roll.
maxFiles
5
Number of rotated files to keep. Older files are deleted.
With the new cross-stream policy active (the default), observability.logRotation
controls the 50 MB roll threshold and the 5-file / 30-day retention for all streams.
The daemon.logging.maxSize value still reaches pino-roll as the size threshold if
you have not set observability.logRotation.maxSizeBytes.
In addition to the main log file, Comis can write per-agent JSONL trace files that
capture detailed execution data. These are useful for debugging specific agent
conversations.
# config.yamldaemon: logging: tracing: outputDir: "~/.comis/traces" # directory for trace files maxSize: "5m" # rotate trace files at 5 MB maxFiles: 3 # keep 3 rotated trace files per session
Trace files are created automatically when an agent processes messages. They contain
the full execution timeline: prompts sent, responses received, tools called, and
timing data.
Daemon
How the daemon starts, runs, and shuts down.
Monitoring
Health checks that watch your system’s vital signs.
Observability
Token tracking, cost estimation, and performance data.