Skip to content

TUI chat doesn't persist USAGE/cache lines to per-session log #1173

Description

@Aaronontheweb

Severity

Minor — observability gap. Data is not lost (still available in the daemon-side audit log at ~/.netclaw/logs/sessions/{sanitized_id}/session.log), but the per-session log file used by tooling and headless-mode workflows is missing USAGE entries when the session is driven by Termina.

Summary

In TUI (netclaw chat) mode, the per-session log file at ~/.netclaw/logs/signalr-{sessionId}.log does not receive USAGE: in=… cached=… … lines after each LLM turn. In headless -p mode it does.

Impact

  • Post-hoc KV cache hit-rate analysis on interactive sessions can't use the per-session signalr log — it stops mid-session whenever the user switches from headless to TUI on the same session ID.
  • Tooling and eval scripts that anchor on ^[usage] / USAGE: lines in the per-session log silently get no data from TUI-driven turns.
  • Hides regressions in cache-prefix stability when the analyst grabs the "obvious" log file.

Repro

  1. Start a TUI session: netclaw chat
  2. Send 2–3 prompts; let the model respond.
  3. grep "USAGE:" ~/.netclaw/logs/signalr-{sessionId}.log → empty.
  4. Compare with netclaw chat -p "…": same file location, USAGE lines are present.

Root cause

  • src/Netclaw.Cli/HeadlessChannel.cs:268 writes the USAGE: in=… cached=… reasoning=… context_window=… prompt_ms=… predicted_tok_s=… line to the per-session log via Log(log, …).
  • src/Netclaw.Cli/Tui/ChatPage.cs:443 (the TUI handler for UsageOutput) only updates the live status bar via ViewModel.UsageDisplay.Value = "in=… out=… (…% ctx)". There is no Log(...) call.

Both code paths receive the same UsageOutput DTO from the daemon — the asymmetry is purely client-side persistence.

Suggested fix

Either:

  1. Mirror the HeadlessChannel's Log(...) call in ChatPage's UsageOutput handler (write the same line shape to the same per-session log file so existing tooling Just Works), or
  2. Promote per-session USAGE persistence out of the client into a shared CLI service so both channels write identically without duplication.

Option 1 is the smaller diff; option 2 is the more durable fix.

Notes

The daemon-side audit log (~/.netclaw/logs/sessions/{sanitized_id}/session.log, written by SessionLogActor) does record USAGE in a different format:

[2026-…Z] Usage: in=… out=… cached=… reasoning=… context=…%

So data is recoverable, just not in the format/location that existing scripts expect.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtuiTerminal UI (Termina) issues

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions