fix(session): default an unstated spawn cwd to the user's home - #36
Merged
Conversation
A session spawned with no cwd handed the empty string to cmd.Dir, so the shell inherited the daemon's own working directory. Under launchd or systemd that directory is / — neither unit in internal/service sets one — so every plain new session opened at /; a hand-started daemon put them wherever it happened to be launched from, which is no better chosen. Registry.start now resolves an empty opts.Cwd to os.UserHomeDir(), the same call Revive already uses for a vanished directory, and feeds that one resolved value to both cmd.Dir and the recorded Info.Cwd — the old code seeded the record from os.Getwd() instead, a recorded-vs-actual split this closes. When home is unresolvable the empty string stands and the shell inherits, which is the old behaviour kept as the floor. Callers that state a cwd — group-heading spawns, restart with the exited session's cwd, revival from snapshot — are untouched; they all pass a non-empty value. Two registry tests pin each side: empty cwd lands the child in $HOME, a stated cwd is never contested by it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
The bug
A session spawned with no cwd opens at
/on service-managed machines.Registry.Spawnhandedopts.Cwdstraight tocmd.Dir, so an empty cwd — what the UI's plain New-session button sends — made the shell inherit the daemon's own working directory. A daemon under launchd or systemd runs at/(neither unit ininternal/service/unit.gosets a working directory), so every default session landed there; a daemon started from a terminal put them wherever it happened to be launched from, which is no better chosen.The fix
In
Registry.start, an emptyopts.Cwdnow resolves toos.UserHomeDir()— the default every terminal emulator and sshd picks, and the same callRevivealready uses for a snapshot whose directory has vanished. The one resolved value feeds bothcmd.Dirand the recordedInfo.Cwd; the old code seeded the record fromos.Getwd()instead, a recorded-vs-actual split this closes. When even home is unresolvable the empty string stands and the shell inherits — the old behaviour, kept as the floor rather than the default. ($HOMEis set by launchd user agents and systemd user managers alike, so the resolution works on exactly the path the bug describes; unlike$SHELL, no user-database fallback is needed.)Callers that state a cwd are untouched — they all pass a non-empty value:
spawnFromGroup→client.spawn({ cwd }))terminal.tsxhandleRestart)Registry.Revivepassessnap.Cwd, or home when it has vanished)Tests
Two new tests in
internal/session/registry_test.go, followingcwd_test.go's poll-and-resolve pattern against the real child process:TestSpawnDefaultsCwdToHome— empty cwd: the recordedInfo.Cwdis$HOMEandprocessCwdconfirms the child actually sits there.TestSpawnKeepsExplicitCwd— stated cwd (deliberately not$HOME): recorded and actual both stay put.Evidence:
make web relaythengo test ./...— all packages ok (includinginternal/session7.5s) — andgo vet ./...clean.🤖 Generated with Claude Code