Commit 2d85a6c
feat(resume): session resume dropdown with terminal launch and directory actions (wesm#120)
## Summary
Adds a session action dropdown to the breadcrumb bar that lets users
resume sessions in a terminal, open the project directory in editors or
file managers, and copy paths and commands to the clipboard.
### Backend
- **`POST /sessions/{id}/resume`** — Builds the agent-specific resume
command (`claude --resume`, `codex resume`, etc.), optionally launches
it in a detected or user-specified terminal. Supports `command_only` for
clipboard copy, `opener_id` for launching in a specific terminal, and
flags like `skip_permissions` and `fork_session` for Claude.
- **`GET /sessions/{id}/directory`** — Agent-agnostic directory
resolution. Prefers the embedded `cwd` from the session file, falls back
to the session's `project` field. Used by the frontend to determine
dropdown visibility and copy the directory path.
- **`GET /openers`** — Detects installed applications (terminals,
editors, file managers) via app bundle paths on macOS and `PATH` lookup
on Linux. Results are cached with a 60s TTL.
- **`POST /sessions/{id}/open`** — Launches a detected opener with the
session's resolved project directory.
- **Terminal config** (`GET/POST /config/terminal`) — Persisted `auto`,
`custom`, or `clipboard` mode. Custom mode supports a user-specified
binary and argument template with `{cmd}` placeholder.
- **macOS launch** uses `open -na <app>` for `.app` bundles and direct
binary execution for PATH-detected installs, keeping detection and
launch consistent. AppleScript for iTerm2 and Terminal.app.
- **Session directory resolution** reads the first 20 lines of the
session JSONL file for an embedded `cwd` field, with fallback to the
session's `project` field. Both must be absolute paths pointing to
existing directories.
### Frontend
- **Resume dropdown** on the session breadcrumb bar, visible when the
session has resume support, detected openers, or a resolvable directory:
- Terminal openers (Ghostty, kitty, iTerm2, etc.) — launches the resume
command directly
- "Default terminal" — uses the server's auto-detect or custom terminal
config
- "Copy command" — copies the resume command to clipboard
- "Copy directory path" — copies the resolved project directory
- "Open in" section — detected editors (VS Code, Cursor, Zed, etc.) and
file managers (Finder, etc.)
- **Keyboard shortcut** `c` copies the resume command to clipboard from
the session detail view.
- **`resume.ts`** utility with per-agent command templates and POSIX
shell quoting.
- **Dropdown visibility** is based on actual capabilities: cached
server-side directory resolution, detected openers, and agent resume
support. No dropdown renders for sessions with nothing actionable.
### Supported agents
| Agent | Resume command |
|-------|---------------|
| Claude | `claude --resume <id>` |
| Codex | `codex resume <id>` |
| Gemini | `gemini --resume <id>` |
| OpenCode | `opencode --session <id>` |
| Amp | `amp --resume <id>` |
### Detected terminals (macOS)
Ghostty, iTerm2, kitty, Alacritty, WezTerm, Terminal.app — detected via
app bundle path with PATH binary fallback for non-default installs.
### Detected terminals (Linux)
Ghostty, kitty, Alacritty, WezTerm, GNOME Terminal, Konsole, Xfce
Terminal, Tilix, xterm — detected via `PATH`. Respects `$TERMINAL`
environment variable.
---------
Co-authored-by: userFRM <frederic.miesegaes@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>1 parent b31cfcc commit 2d85a6c
File tree
24 files changed
+2320
-15
lines changed- frontend/src/lib
- api
- components
- layout
- modals
- utils
- internal
- config
- db
- parser
- server
- sync
- timeutil
24 files changed
+2320
-15
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
330 | 330 | | |
331 | 331 | | |
332 | 332 | | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
333 | 361 | | |
334 | 362 | | |
335 | 363 | | |
| |||
392 | 420 | | |
393 | 421 | | |
394 | 422 | | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
395 | 487 | | |
396 | 488 | | |
397 | 489 | | |
| |||
0 commit comments