Skip to content

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

@Aaronontheweb

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions