Skip to content

Start a session in the user's home, from one place - #116

Merged
gmpassos merged 1 commit into
masterfrom
fix/session-start-in-home
Sep 13, 2026
Merged

gmpassos merged 1 commit into
masterfrom
fix/session-start-in-home

Conversation

@gmpassos

Copy link
Copy Markdown
Contributor

A shell opened wherever the node process happened to be standing. For an agent
installed as a service that is where its binary lives — /usr/local/bin — which
is nobody's idea of a starting point.

The behaviour existed, in the wrong place

omnyshell node start already passed workingDirectory: home
(bin/omnyshell.dart), but it did so in the CLI rather than in the backend.
An embedder building its own ProcessShellBackend — as OmnyServer does —
got neither that nor anything else:

omnyshell.ProcessShellBackend()     // no workingDirectory

A default that only one caller applies is not a default.

The fix

resolveStartDirectory now holds the decision, in the order of who is entitled
to make it:

  1. The client's request~ expanded; a directory that does not exist
    still fails loudly, which is the right answer to an explicit request that
    cannot be honoured.
  2. The node's configuration — for an embedder with an opinion.
  3. The user's home — resolved through existingUserHome, so it works on a
    service-run node that was handed no HOME (1.57.1).
  4. null — inherit the node's own directory, as before.

exec follows the same rule as an interactive shell, so the two agree; ssh
set that expectation long ago.

A home that does not exist is skipped rather than used: handing a missing
path to Process.start fails the session outright, which is worse than opening
somewhere unremarkable. A blank string falls through for the same reason.

Drift this turned up

Consolidating the three backends onto one function exposed that
ScriptPtyShellBackend — the default on Linux and macOS — never expanded a
leading ~.
So --cwd ~/project worked on the pipe and winpty backends and
silently did not on the one nearly everyone uses. They share the resolution now
and cannot diverge again.

The Windows MSYS path translation was duplicated in two backends; it is applied
once, where the decision is made.

_resolveNodeHome keeps only what is particular to it — the node profile's
HOME overriding the process environment — and defers the rest to
existingUserHome, so the password-database lookup a service-run node needs is
not reimplemented beside it.

Verified

The new backend test builds a bare ProcessShellBackend() from a process whose
cwd is the repo, and both an exec and an interactive session report the home
directory — the embedder shape that had nothing before. Unit tests cover the
precedence chain, the blank-string fall-through, the ~ expansion and the
refusal to use a home that is not on disk.

696 unit and 136 integration tests pass; dart analyze clean.

v1.57.1 is tagged, so this carries the bump to 1.57.2pubspec.yaml and
lib/src/version.dart, pinned together by version_test.dart — plus its
changelog section.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KdG8bDrddXkEkzgPq23D6q

A shell opened wherever the node process happened to be standing. For an agent
installed as a service that is where its binary lives — `/usr/local/bin` — which
is nobody's idea of a starting point.

The behaviour existed: `omnyshell node start` passed `workingDirectory: home`.
It did so in the CLI rather than in the backend, so an embedder building its own
ProcessShellBackend — as OmnyServer does — got neither that nor anything else.
A default that only one caller applies is not a default.

resolveStartDirectory now holds the decision, in the order of who is entitled
to make it: the client's request, then the node's configuration, then the user's
home, then the node's own directory. exec follows the same rule as an
interactive shell, so the two agree; ssh set that expectation long ago. A home
that does not exist is skipped rather than used — handing a missing path to
Process.start fails the session outright, which is worse than opening somewhere
unremarkable, and a blank string falls through for the same reason.

Moving it also closed the drift between the three backends. The script PTY
backend — the default on Linux and macOS — never expanded a leading `~`, so
`--cwd ~/project` worked on the pipe and winpty backends and not on it. The
Windows MSYS translation was duplicated in two of them and is now applied once,
where the decision is made. `_resolveNodeHome` keeps only what is particular to
it (the node profile's HOME overriding the environment) and defers the rest to
existingUserHome, so the password-database lookup a service-run node needs is
not reimplemented beside it.

Verified where it counts: the new backend test starts a bare
ProcessShellBackend from a process whose cwd is the repo, and both an exec and
an interactive session report the home directory — the embedder path that had
nothing before.

v1.57.1 is tagged, so this carries the bump to 1.57.2 and its changelog.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KdG8bDrddXkEkzgPq23D6q
@codecov

codecov Bot commented Sep 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.94737% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...frastructure/backend/pty/winpty_shell_backend.dart 0.00% 3 Missing ⚠️
...b/src/infrastructure/backend/shell_invocation.dart 83.33% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@gmpassos
gmpassos merged commit f1aa731 into master Sep 13, 2026
6 checks passed
@gmpassos
gmpassos deleted the fix/session-start-in-home branch September 13, 2026 07:47
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