-
Notifications
You must be signed in to change notification settings - Fork 0
File
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.
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.
| 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. |
| 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.
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.
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]
The precedence is Launch Arguments § Precedence: CLI flag beats settings.json beats default.
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: falsepaired withlevel: debugis a validation error at load time — the logger refuses to activate. The session starts with aLoggerConfigRejecteddiagnostic 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.jsonenvare added to the redaction deny-list automatically. An API key referenced asenv:ANTHROPIC_API_KEYnever 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.
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.
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 | 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.
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.
- 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.
- Execution Model
- Message Loop
- Concurrency and Cancellation
- Error Model
- Event and Command Ordering
- Event Bus
- Command Model
- Interaction Protocol
- Hook Taxonomy
- Host API
- Extension Lifecycle
- Env Provider
- Prompt Registry
- Resource Registry
- Session Lifecycle
- Session Manifest
- Persistence and Recovery
- Stage Executions
- Subagent Sessions
- Contract Pattern
- Versioning and Compatibility
- Deprecation Policy
- Capability Negotiation
- Dependency Resolution
- Validation Pipeline
- Cardinality and Activation
- Extension State
- Conformance and Testing
- Providers
- Provider Params
- Tools
- Hooks
- UI
- Loggers
- State Machines
- SM Stage Lifecycle
- Stage Definitions
- Commands
- Session Store
- Context Providers
- Settings Shape
- Trust Model
- Project Trust
- Extension Isolation
- Extension Integrity
- LLM Context Isolation
- Secrets Hygiene
- Security Modes
- Tool Approvals
- MCP Trust
- Sandboxing
- Configuration Scopes
- Project Root
- Extension Discovery
- Extension Installation
- Extension Reloading
- Headless and Interactor
- Determinism and Ordering
- Launch Arguments
- Network Policy
- Platform Integration
Tools
UI
Session Stores
Loggers
Providers
Hooks
Context Providers
Commands
- First Run
- Default Chat
- Tool Call Cycle
- Hook Interception
- Guard Deny Reproposal
- State Machine Workflow
- SM Stage Retry
- Hot Model Switch
- Capability Mismatch Switch
- Session Resume
- Session Resume Drift
- Approval and Auth
- Interaction Timeout
- Headless Run
- Parallel Tool Approvals
- Subagent Delegation
- Scope Layering
- Project First-Run Trust
- Reload Mid-Turn
- Compaction Warning
- MCP Remote Tool Call
- MCP Prompt Consume
- MCP Resource Bind
- MCP Reconnect