Skip to content

feat: inherit the focused session's working directory in boo ui#78

Merged
kylecarbs merged 1 commit into
mainfrom
feat/ui-inherit-cwd
Jun 18, 2026
Merged

feat: inherit the focused session's working directory in boo ui#78
kylecarbs merged 1 commit into
mainfrom
feat/ui-inherit-cwd

Conversation

@kylecarbs

Copy link
Copy Markdown
Member

In boo ui, C-a c now creates the new session in the focused session's working directory, like Ghostty's new windows, instead of inheriting the boo ui process's directory.

How it works

  • The daemon resolves the live working directory of the session's child process and exposes it through a new cwd control command. Resolution reads the OS directly: /proc/<pid>/cwd on Linux, proc_pidinfo(PROC_PIDVNODEPATHINFO) on macOS.
  • boo new gains a --cwd <dir> flag (validated, must be an existing directory). The child chdirs there before exec.
  • The UI queries the focused session's cwd and passes it through to boo new --cwd. If the directory can't be resolved or used, it falls back to a plain new, so the keybind always works.

The directory comes from the live child process rather than OSC 7 shell integration: boo doesn't inject shell integration, and a process cwd is always a valid local path for chdir (OSC 7 can be empty, or describe a remote directory over ssh). See the decision log below.

boo new --cwd is also useful on its own, e.g. boo new build -d --cwd /srv/app -- make.

Decision log
  • Mechanism: process cwd, not OSC 7. OSC 7 / term.getPwd() matches Ghostty and is portable, but boo never injects shell integration so it is usually empty, and under ssh it can report a remote path that is wrong for a local chdir. The child process cwd works without shell integration and is always a valid local path. OSC 7 could be added later as a fallback.
  • Where it is resolved. Each session is its own daemon that owns the child pid, so the daemon answers a new cwd control command; the UI (a client) cannot read the child pid itself. cwd is its own command rather than a field on info so the extra syscall only happens on create, not on every ls/wait poll.
  • macOS layout. proc_pidinfo only fills the buffer when its size exactly matches struct proc_vnodepathinfo, so the full <sys/proc_info.h> layout is reproduced. The size (2352) and the cdir path offset (152) were verified against the system headers and are locked with comptime asserts that run on every target.
  • Validation and fallback. boo new --cwd resolves the path to an absolute, openable directory up front and fails with a clear error if it can't, so a bad value never produces a dead session. The UI retries without --cwd if the inherited create fails (e.g. the directory vanished).
  • Naming unchanged. The default session name still derives from the creating process's directory; only the child's working directory is inherited.

Testing

  • zig build (native Linux) and zig build -Dtarget=aarch64-macos (cross) both succeed; the macOS cross build exercises the proc_pidinfo path and the comptime layout asserts.
  • zig build test (130/130) and zig build test-integration (76/76) pass; zig build test-all -Doptimize=ReleaseSafe passes (206/206). zig fmt --check is clean.
  • New tests: cwd.ofPid against a child spawned in a temp dir; boo new --cwd starts the command in that directory; invalid --cwd exits non-zero; and a boo ui end-to-end test asserting C-a c lands the new session in the focused session's directory and not the UI's.

Generated with Coder Agents on behalf of @kylecarbs.

In `boo ui`, C-a c now creates the new session in the focused session's
working directory, like Ghostty's new windows, instead of inheriting the
UI process's directory.

The daemon resolves the live working directory of the session's child
process (Linux /proc/<pid>/cwd, macOS proc_pidinfo) and exposes it via a
new `cwd` control command. `boo new` gains a `--cwd` flag that the UI
passes through; the child chdir's there before exec. Creation falls back
to a plain `new` when the directory cannot be resolved or used.
@kylecarbs kylecarbs merged commit 42eff58 into main Jun 18, 2026
5 checks passed
@kylecarbs kylecarbs mentioned this pull request Jun 18, 2026
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