Skip to content

Per-tab Claude session resume#24

Draft
mvbmir wants to merge 2 commits into
mainfrom
mvbmir/claude-session-resume
Draft

Per-tab Claude session resume#24
mvbmir wants to merge 2 commits into
mainfrom
mvbmir/claude-session-resume

Conversation

@mvbmir
Copy link
Copy Markdown
Owner

@mvbmir mvbmir commented Apr 17, 2026

Summary

  • Each limux terminal tab remembers the Claude session it had open and auto-runs `claude --resume ` on next launch
  • Works per-tab even when multiple tabs share a cwd
  • Tracks `/resume` switches made inside Claude's UI via its `~/.claude/sessions/.json` status file

Mechanics

  1. Each tab generates a stable UUID, exported to the shell as `LIMUX_CLAUDE_SESSION_ID` (+ `LIMUX_TAB_ID` for tagging)
  2. A POSIX `claude` shim is installed to `~/.local/share/limux/bin/` and prepended to `PATH`. Plain `claude` gets `--session-id $LIMUX_CLAUDE_SESSION_ID`; explicit `--resume`/`--continue`/`--session-id`/`--from-pr` pass through untouched
  3. 1 Hz GTK poller finds each tab's `claude` PID via `/proc//environ` match on `LIMUX_TAB_ID`, reads Claude's own per-PID status file, and updates tab state
  4. Snapshot persists the live UUID (fallback: the pre-generated one); restore verifies the JSONL still exists before resuming, else plain shell

Test plan

  • `cargo test -p limux-host-linux` (132 tests pass)
  • `cargo clippy -p limux-host-linux --no-deps` clean
  • Manual: 2 tabs same cwd, each runs `claude`, `/resume` different sessions, quit, relaunch → each tab restored to its own session

Notes

  • Wrapper is idempotent (rewritten on launch only if body differs)
  • Wrapper install failure is non-fatal: limux logs a warning and falls through to normal shells
  • Removes earlier heuristic-based detection (`/proc//fd` scanning, JSONL mtime matching) — status-file approach is deterministic

@mvbmir mvbmir force-pushed the mvbmir/claude-session-resume branch from ac839ae to 6f2956a Compare April 17, 2026 22:25
Give each terminal tab its own Claude session that auto-resumes on next
launch, including `/resume` switches made from inside Claude's UI.

Mechanics:

- Each tab gets a pre-generated session UUID plus env vars
  `LIMUX_TAB_ID` and `LIMUX_CLAUDE_SESSION_ID`.
- A shim `claude` wrapper is installed to `~/.local/share/limux/bin/`
  and prepended to PATH. Plain `claude` invocations get
  `--session-id $LIMUX_CLAUDE_SESSION_ID` appended; `--resume`,
  `--continue`, `--session-id`, etc. pass through untouched.
- A 1 Hz GTK poller locates the tab's `claude` process via
  `/proc/<pid>/environ` and reads Claude's own
  `~/.claude/sessions/<pid>.json` status file to track the currently
  active session UUID (updates on `/resume`).
- Snapshot persists the live UUID (falling back to the pre-generated
  one); restore launches `claude --resume <uuid>` if the session JSONL
  still exists, otherwise boots a plain shell.

Two tabs in the same cwd now resume independently because each claude
process has a unique PID, inherits a unique tab ID, and writes its own
status file.
@mvbmir mvbmir force-pushed the mvbmir/claude-session-resume branch from 6f2956a to 9f8ce53 Compare April 17, 2026 22:39
@mvbmir mvbmir changed the base branch from mvbmir/dev to main April 17, 2026 22:39
Rust 1.95 stable (released between main's last green CI run and this
PR's) promotes collapsible_match to a warning, which the workspace's
check.sh treats as an error via -D warnings.

The flagged patterns in limux-core are `match combo_norm { pattern
=> { if palette_visible { … true } else { false } } … }` — they
collapse cleanly into match guards: `pattern if palette_visible =>
{ … true }`. Behavior is unchanged; any non-match combo hits the
catch-all `_ => false` arm.

Unrelated to the redesign; included here to keep CI green.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant