Skip to content

perf: claude_status stale-file sweep only runs at startup — accumulates over weeks-long sessions #567

@Axelj00

Description

@Axelj00

Problem

`src-tauri/src/main.rs:92-96` calls `sweep_stale_claude_status_files()` once at startup to clean up `.json` files in `/tmp/clawterm-status/` whose Claude Code process is dead. The comment says "Without this, the directory grows monotonically over time. (#521)" — but that fix only catches what's already accumulated when ClawTerm starts. It doesn't catch what accumulates during a running ClawTerm session.

For users who run ClawTerm for weeks without restarting (the real workflow this app advertises):

  • Every Claude session that ends or crashes leaves a stale `.json` behind.
  • Compacting (`/compact`) or restarting Claude Code spawns a new PID with a new file; the old PID's file lingers.
  • A typical heavy-use week might see 50-200 stale files accumulate per session.

Each file is small (1-5 KB), so disk pressure isn't the headline. But:

  1. `claude_status_path_if_fresh()` (`src-tauri/src/process_info.rs:131-138`) is called per pane per poll — that's a `stat()` + `pid_alive()` check against the disk. With hundreds of stale files lurking, the `/tmp/clawterm-status/` directory's metadata cache footprint grows.
  2. The next ClawTerm restart's startup sweep walks N files and calls `pid_alive` on each — `O(N)` syscalls during the perceived-slow startup window.
  3. `/tmp` is shared across the system. Polluting it with hundreds of orphaned files from a single app over weeks is impolite.

Fix

Add a periodic re-sweep during the running session. Cheapest implementation:

```rust
// In main.rs setup, after the initial sweep:
tauri::async_runtime::spawn(async {
let mut interval = tokio::time::interval(Duration::from_secs(60 * 60)); // 1h
interval.tick().await; // skip first immediate tick — initial sweep already ran
loop {
interval.tick().await;
tauri::async_runtime::spawn_blocking(|| {
process_info::sweep_stale_claude_status_files();
}).await.ok();
}
});
```

Hourly is plenty — files are cheap to sweep but agents come and go on a slow clock. Could also key it to `onCloseRequested` so a quit triggers a final sweep (and the next launch sees a clean dir), but that's a smaller win than the periodic version.

Alternative trigger: sweep on every `setup_claude_statusline` call (which fires when ClawTerm spawns a new Claude session). Lower latency to detect newly-orphaned files; more frequent under heavy usage. Both work.

References

Out of scope

  • Moving `/tmp/clawterm-status/` to an app-data dir (`~/Library/Application Support/ClawTerm/`). `/tmp` is deliberately ephemeral; the statusline.sh writer hardcodes it. A move would require a coordinated change to the writer script.
  • Garbage-collecting files older than X days (mtime-based). The PID-alive check is more precise and already implemented.

Metadata

Metadata

Assignees

No one assigned

    Labels

    performancePerformance improvementspriority: mediumImportant but not urgenttech-debtTechnical debt and code quality

    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