feat(THI-244): default cwd setting + new-pane cwd inheritance (sessions mode) - #112
Merged
Conversation
…ns mode)
Today the "+session" / "+window" overlays start panes wherever tmux
decides (usually the server-process cwd), so users routinely retype
the same paths. This PR adds a configurable default cwd plus the
"+window inherits its session's cwd" behavior.
Resolution order (matches the spec's sessions-mode rules):
1. Per-modal override (one-shot input on each overlay).
2. For "+window": the launching session's first window cwd, looked up
server-side. Matches the user's expectation that "+" lands next to
peers.
3. For "+session": the configured Default directory setting.
4. Otherwise None — tmux uses its own default.
Backend:
- POST /window and POST /session accept an optional CwdBody (`{cwd}`).
- _resolve_cwd validates: ~-expansion against the server's $HOME,
must be an existing absolute directory. Anything invalid silently
resolves to None so a bad setting never breaks new-pane creation
with a 4xx.
- _first_window_cwd looks up the launching session's first window cwd
via libtmux; the route uses it when the body has no explicit cwd.
- 8 new test cases cover the resolver + both routes' threading paths.
Frontend:
- New `defaultDirectory: string` setting (empty default). Persisted
to localStorage like every other setting.
- New "Defaults" section in SettingsModal with the text input.
- createSession / createWindow API helpers accept an optional cwd
and body-encode it as JSON when provided.
- NewSessionOverlay prefills its cwd input from settings; the user
can override per-modal without mutating the saved setting.
- NewWindowOverlay adds the same one-shot cwd input; blank means
"let the backend fall back to this session's first window cwd".
- 4 new tests (2 for settings round-trip, 2 for client.ts cwd
threading).
Discovery-mode auto-derive (the half of the spec that uses THI-243's
repo-group launch context) is explicitly deferred — THI-243's MVP
doesn't yet expose per-repo "+" buttons, so the spec hook isn't
reachable. Lands as an additive change in a follow-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…default-cwd # Conflicts: # frontend/src/lib/settings.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Today the
+session/+windowoverlays start panes wherever tmux decides (usually the server-process cwd), so users routinely retype the same paths. This PR ships the Sessions-mode half of THI-244: a configurable default cwd plus the "+window inherits its session's cwd" behavior.Resolution order (matches the spec's sessions-mode rules):
+window: the launching session's first window cwd, looked up server-side. Matches the user's expectation that "+" lands next to peers.+session: the configured Default directory setting.None— tmux uses its own default.What ships
Backend
POST /windowandPOST /sessionaccept an optionalCwdBody({cwd})._resolve_cwdvalidates:~-expansion against the server's$HOME, must be an existing absolute directory. Anything invalid silently resolves toNoneso a bad setting never breaks new-pane creation with a 4xx._first_window_cwdlooks up the launching session's first window cwd via libtmux; used as the fallback when the body has no explicit cwd.~expansion, first-window fallback).Frontend
defaultDirectory: stringsetting (empty default). Persisted to localStorage like every other setting.SettingsModalwith the text input.createSession/createWindowAPI helpers accept an optionalcwdand body-encode it as JSON when provided.NewSessionOverlayprefills its cwd input from settings; the user can override per-modal without mutating the saved setting.NewWindowOverlayadds the same one-shot cwd input; blank means "let the backend fall back to this session's first window cwd".Explicitly deferred
The discovery-mode auto-derive half of the spec ("in discovery mode, ignore the global default; use the owning repo's path") depends on:
+buttons.THI-243's MVP doesn't yet expose those (ListView only renders headers, no per-repo create affordance). The hook isn't reachable, so the discovery branch lands as a small additive change in a follow-up. This PR's resolution function already has the right shape — adding a
(repoKey?: string) => stringbranch on top will be a one-liner.Test plan (automated)
uv run pytest).ruff check+ruff format --check: clean.npm test). Typecheck + build: clean.Manual smoke (needs a live tmux server — only the user can run this)
Settings UI
~/dev(or some path you have). Close + reopen Settings: the value persists./nope/nope/nope. Save it. (Backend will silently drop on use — no toast / error in Settings itself.)New session
tmux attach), runpwd. It should be the configured directory (or$HOMEif you used~).pwdmatches the override, not the saved default.New window
~/foo).tmux attach, jump to the new window,pwd. It should match the launching session's first window cwd.pwdmatches the override./nope/nope. Confirm the window is created (no error) and lands in tmux's fallback.Edge cases
~only. New session lands in$HOME(server-side expansion).subdir. New session falls through to tmux's default (relative paths rejected server-side).🤖 Generated with Claude Code