Skip to content
Z-M-Huang edited this page Apr 29, 2026 · 3 revisions

File logger (bundled)

The bundled file logger. Ships with stud-cli, always loaded, writes log records to disk under the user's global scope. This page is a reference extension description — it describes how the bundled file logger behaves, not a normative contract. Normative rules live at Loggers.


Role

The file logger is the default persistent sink. A stud-cli installation without any other logger still produces a durable trail through this logger. It is not configurable away in v1 — users may change its path or disable it through settings.json, but they cannot unbundle it.


Discovery and activation

Aspect Behavior
Category Logger.
Scope Bundled.
Loaded cardinality 1 (single instance).
Active cardinality 1.
Reload in-turn — a config change takes effect at the next record.
State slot Used for rotation counters. See Rotation.

Where the file lands

Platform Default path
Linux $XDG_CONFIG_HOME/stud/logs/session-<sessionId>.log if XDG_CONFIG_HOME is set, else $HOME/.stud/logs/session-<sessionId>.log.
macOS $HOME/.stud/logs/session-<sessionId>.log.
Windows %USERPROFILE%\.stud\logs\session-<sessionId>.log.

See Platform Integration § Directory resolution for the global-scope resolution rules. A user who prefers a different path overrides through the logger's configuration in settings.json.

One file per session. The file name embeds the session id so resumes land in the same file and concurrent sessions do not collide.


Format

One record per line, UTF-8, LF line endings on every platform. Records are serialized as newline-delimited JSON:

{"ts":"2026-04-19T14:22:07.412Z","kind":"event","sev":"info","name":"ProviderRequestStarted","sessionId":"…","payload":{…}}
Field Meaning
ts ISO-8601 timestamp, UTC, millisecond precision.
kind One of event, audit, diagnostic.
sev trace | debug | info | warn | error.
name Record type name.
sessionId The session this record belongs to.
payload Record-specific body. Subject to redaction.

Audit records pass through unredacted per Loggers § Security notes. Event and diagnostic records are subject to the redaction filter.


Levels and --debug

Default level is info. The --debug launch flag or logging.level: "debug" in settings.json lowers the threshold to debug. trace is reserved for implementation-detailed development builds; users do not enable it through configuration in v1.

flowchart LR
    Flag["CLI: --debug"] --> Level[effective level = debug]
    Settings["settings.json:<br/>logging.level = debug"] --> Level
    Default["default: info"] --> Level
    Level --> Filter[record severity >= level?]
    Filter -->|yes| Redact[redaction pipeline]
    Filter -->|no| Drop[drop]
    Redact --> Write[append line to file]
Loading

The precedence is Launch Arguments § Precedence: CLI flag beats settings.json beats default.


Redaction

The file logger runs every non-audit record through the same redaction pipeline used by every other logger. See Secrets Hygiene § Redaction pipeline and Loggers § Debug-level redaction.

Key rules for the bundled file logger specifically:

  • redactSecrets: false paired with level: debug is a validation error at load time — the logger refuses to activate. The session starts with a LoggerConfigRejected diagnostic and without this logger.
  • The redaction filter cannot be replaced through settings.json. Users may tighten (extend the deny-list) but not weaken.
  • Known env keys referenced in settings.json env are added to the redaction deny-list automatically. An API key referenced as env:ANTHROPIC_API_KEY never appears in log output, regardless of the record producer's discipline.
  • Audit records are written unredacted because they are the operator's accountability trail. If an audit record carries a resolved secret, the bug is in the audit event definition, not the logger — open an issue at the producer page.

Rotation

The bundled file logger rotates per-session by size. When the active file reaches rotateAtBytes (default 2 MiB), it is renamed to <file>.<ISO-timestamp> and a fresh file is opened. At most maxRotatedFiles rotated files (default 10) are retained per session; older rotated files are pruned in lexical order.

Concern v1 posture
Per-size rotation Default 2 MiB. Configurable via rotateAtBytes.
Per-time rotation (daily / hourly) Not supported in v1.
Per-session retention At most 10 rotated files per session by default. Configurable via maxRotatedFiles.
Cross-session retention Inactive session log directories are the user's responsibility — retention windows are out of scope for v1.

Rotation is per-session: each session writes its own file (session-<sessionId>.jsonl), so concurrent stud-cli instances cannot race on the rotation rename. The state slot reserves rotation counters for future rotation strategies (per-time, compressed) without requiring a contract-version bump.


Backpressure

The logger uses a bounded in-memory queue between the event bus and the file writer. Overflow drops the oldest non-audit record and emits a LoggerBackpressureDrop diagnostic. Audit records are never dropped — a full queue stalls non-audit drains first; if the audit sub-queue also fills, the session transitions to Degraded per Error Model.

See Loggers § Security notes — Backpressure.


Failure modes

Failure Behavior
Parent directory not writable Logger fails to init; session starts without it; diagnostic emitted once.
Disk full on append Pending record is dropped; diagnostic emitted; logger continues to retry on next record.
File already open by another process The logger uses a shared-append open mode on all platforms, so this is not a failure. If the OS rejects it, the session starts without the file logger and emits a diagnostic.
Process killed mid-write Filesystem is left with a partial last line. The logger writes one record per append call and never splits a record across appends, so a torn line indicates process termination mid-write, not mid-record corruption.

See Error Model for retry posture on transient I/O.


Configuration

Configurable fields on this logger, via settings.json:

Field Meaning Default
enabled Whether the file logger participates. true.
level Minimum severity. info (or debug under --debug).
redactSecrets Must remain true at debug level. true.
path Override the default file path. Must be an absolute path the user owns. Platform default above.
rotateAtBytes Size threshold (bytes) that triggers rotation of the active file. 2_097_152 (2 MiB).
maxRotatedFiles Number of rotated files to retain per session. Older rotated files are pruned. 10.
accepts.events Write event records. true.
accepts.audit Write audit records. true.
accepts.diagnostics Write diagnostic records. true.

A user who wants a compliance-only log can disable events and diagnostics; a user debugging a single session can raise level and leave accepts alone.


Known limitations

  • Per-size rotation only. Per-time rotation (daily / hourly) is not supported in v1. Users who need a different rotation strategy install an alternative logger.
  • No remote sink. Operators who want centralized logs install an extension logger that ships records to their observability system. The file logger stays on disk.
  • Single format. Records are NDJSON; no human-pretty mode in v1. The bundled TUI provides operator-facing rendering through a different channel.
  • No cross-session retention policy. Inactive session log directories accumulate until the user prunes them. A future version may add a max-age policy through additional config fields without bumping the contract version.

These are explicit v1 trade-offs. The state slot carries the rotation counters; further rotation strategies (per-time, compressed) can ship additively at the same contract version.


Related pages

Introduction

Reading

Core runtime

Contracts

Category contracts

Context

Security

Runtime behavior

Operations

Providers (bundled)

Integrations

Reference extensions

Tools

UI

Session Stores

Loggers

Providers

Hooks

Context Providers

Commands

Case studies

Flows

Maintainers

Clone this wiki locally