Repository navigation
fix(server): worktree setup no longer hangs when the shell is Nushell - #29461
KenDJohnson wants to merge 4 commits into
Conversation
Setup and settle actions typed a POSIX completion wrapper into Nushell, which passes "$?" to printf literally, so the completion marker never carried an exit code and synchronous setup waited forever. Nushell now gets its own wrapper that reports the exit code through try/catch.
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — Adds Nushell-compatible completion and error reporting for existing project setup scripts, preventing completion tracking from hanging. The change leaves script selection, execution triggers, and other shells’ behavior unchanged. You can add or adjust custom eligibility rules. Learn more. |
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
Run observed scripts in a child of the current Nushell executable, loading
its login configuration. The parent reports LAST_EXIT_CODE after the child
finishes, including explicit exit commands, without relying on catch-record
fields that differ between Nushell versions.
Extend the existing mocked-terminal test to assert the complete wrapper,
including the failure fallback, sentinel, and quoting of multiline input.
The expanded test fails before the change.
Validation: vp run check:changed passes. Real PTY verification passed 40
cases across Nu 0.97.1, 0.98.0, 0.99.1, and 0.116.1 on macOS:
echo setup-ok -> completion sentinel:0
node -e "process.exit(7)" -> completion sentinel:7
open /t3-review-does-not-exist -> error shown, completion sentinel:1
error make {msg: "boom"} -> error shown, completion sentinel:1
exit 0 -> completion sentinel:0
exit 7 -> completion sentinel:7
Configured commands, multiline input, quoting, and stdin/stdout/stderr TTY
behavior also passed on each version.
Model and harness: GPT-6.1 Sol through Codex in T3 Code.
|
Note Written by Verified in a real dev environmentverified on a linux boat vm with nushell 0.116.1, the dev web client in
short runtime transcript: before on main: after on the final head: inspected the screenshots and recording, and exercised uploaded video playback and seeking. Not verifiednative desktop, ios, android, macos, windows, and scheduled-task launches were not exercised on this linux vm. older nushell received direct wrapper checks rather than a full client/provider pass. no performance comparison is claimed. |
Nushell parses --commands before evaluating its leading cd. If login.nu changes directories, relative source and use statements can select files from the login directory even when the action runs in the worktree. Use Nu's mktemp, save, to nuon, source, and rm commands to load the action from a temporary .nu file in the worktree. Relative imports resolve against that file's directory, and the child retains the user's login definitions. Remove the file before the action runs so it does not appear in git status; clean it up in the parent when parsing fails. Preparation errors still report a numeric completion status. Guard null catch arguments on older Nu. Extend the existing mocked-terminal table with source/use input and assert the complete native wrapper. The expanded assertion fails before the fix. vp run check:changed passes, including 12 tests in two affected files. Runtime: 60 PTY cases and eight preparation-failure cases passed on macOS with Nushell 0.97.1, 0.98.0, 0.99.1, and 0.116.1. Login startup changes cwd; both directories contain conflicting setup.nu and module.nu files: before: source ./setup.nu -> SOURCE-WRONG, status 0 before: use ./module.nu *; location -> MODULE-WRONG, status 0 after: source ./setup.nu -> SOURCE-WORKTREE, status 0 after: use ./module.nu *; location -> MODULE-WORKTREE, status 0 file present only in login cwd -> diagnostic, status 1, no leftover exit 0 / exit 7 / error make -> statuses 0 / 7 / 1 Nested imports, login-defined commands, multiline quoting, paths with spaces and quotes, TTY input/output, and cleanup passed. Creation and save errors show diagnostics and report status 1 without running the action. Model and harness: GPT-6.1 Sol through Codex in T3 Code.
|
@maria-rcks thanks for the review and tests on this, anything else that needs to happen here? |



Problem
When the setup terminal's shell is Nushell, worktree setup and settle actions never finish. T3 types a POSIX wrapper,
( <command> ); printf '\n<sentinel>%s\n' "$?", and nu passes"$?"toprintfliterally, so the terminal prints__T3_SETUP_DONE___<token>:$?, which never matches the numeric completion pattern. When the command fails, nu stops beforeprintfand prints nothing. Either way, a synchronous setup holds the thread forever.Fixes https://git.cafe/pingdotgg/t3code/issues/24423 (reported on Linux; reproduced here on macOS with T3 Code v0.1.6 and Nushell 0.116.1).
Change
ProjectSetupScriptRunnernow treatsnuas its own completion shell and wraps the action in Nushell syntax:Nu skips the rest of the input after a failing command, so the status print only runs behind
try. A failing external reports its own exit code ($e.exit_code). Other errors (command not found,error make) report 1 and are printed, sincecatchwould otherwise hide them.Like zsh and fish, nu's line editor enables bracketed paste, so the command is still typed only after that signal. The readiness check now names the shells that lack the signal (PowerShell, cmd) instead of the ones that have it.
Scope and approval
https://git.cafe/pingdotgg/t3code/issues/24423 reports this bug; it has not been triaged yet. This is a small, focused fix for an obvious bug: one new case in the existing shell switch, plus keeping nu on the existing line-editor wait. Setup and settle actions, including thread launches from MCP and scheduled tasks, all go through this runner. No contract, client, or docs changes are needed.
Verification
ProjectSetupScriptRunner.test.tschecks that nu waits for its line editor and receives the Nushell wrapper. It fails on main, where nu gets( vp i\r); printf … "$?", and passes here. Reverting only the readiness change also fails it, because the command is typed before the line editor starts.vp run check:changedpasses.echo setup-ok→ 0;node -e "process.exit(7)"→ 7error make {msg: "boom"}→ 1# comment→ 0SHELLset to a Nushell login wrapper, Replay provider), with a synchronous setup action on a scrap repo, viat3 thread start --worktree main --wait:Not checked: Nushell on Linux or Windows, and Nushell versions older than 0.116. Setup actions must still be valid Nushell: POSIX-only syntax such as
a && bfails to parse, so no status is printed, the same as a syntax error in a POSIX shell.Model and harness: Claude Opus 5.5 through Claude Code in T3 Code.
Fixes #24423