feat(worktrees): run a post-create setup script in new worktrees - #1306
feat(worktrees): run a post-create setup script in new worktrees#1306pedramamini wants to merge 1 commit into
Conversation
A fresh worktree only contains what git tracks, so gitignored files (.env.local, generated config, installed deps) have to be recreated by hand every time. Add a per-agent "Setup Script" that runs inside each worktree Maestro creates. - Worktree Configuration modal gains a Setup Script field, stored on the parent agent's worktreeConfig - New git:worktreeRunSetup IPC runs the command with the new worktree as cwd, exposing MAESTRO_WORKTREE_PATH / _WORKTREE_BRANCH / _MAIN_REPO_PATH / _BASE_BRANCH, with a 10 minute cap and truncated output - Runs on the remote host over SSH when the parent agent uses SSH remote execution - Wired into all four creation paths (config modal, create-worktree modal, Auto Run spawn, batch runner), gated on a freshly created worktree so reused/re-attached worktrees don't re-run it - Failures surface as a toast and never block worktree creation execFileNoThrow's ExecOptions form now accepts env alongside timeout, so the runner can inherit the login-shell PATH and still be bounded. Closes #409
📝 WalkthroughWalkthroughAdds per-agent worktree setup scripts with UI configuration, local and SSH execution, environment variables, timeout handling, IPC contracts, and invocation after newly created worktrees are prepared. ChangesWorktree setup script
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant WorktreeCreation
participant SetupRunner
participant GitIPC
participant Shell
WorktreeCreation->>SetupRunner: run setup after worktree creation
SetupRunner->>GitIPC: worktreeRunSetup(script, context, sshRemoteId)
GitIPC->>Shell: execute locally or over SSH
Shell-->>GitIPC: return status and output
GitIPC-->>SetupRunner: return setup result
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryAdds configurable post-create setup scripts for newly created local and SSH worktrees.
Confidence Score: 4/5The batch setup path needs correction before merging because it can run the wrong agent’s setup command when parent agents share a repository. The batch manager identifies setup configuration only by repository path, while the lookup returns the first matching parent session; per-agent scripts therefore lose their ownership boundary for duplicate repository sessions. Files Needing Attention: src/renderer/utils/worktreeSetupScript.ts and src/renderer/hooks/batch/useWorktreeManager.ts Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant Renderer
participant GitIPC as Git IPC
participant Git
participant Runner as Setup Runner
participant Shell as Local/SSH Shell
User->>Renderer: Create worktree
Renderer->>GitIPC: worktreeSetup(...)
GitIPC->>Git: git worktree add
Git-->>GitIPC: "created=true"
GitIPC-->>Renderer: Setup result
Renderer->>GitIPC: worktreeRunSetup(script, context)
GitIPC->>Runner: runWorktreeSetupScript(...)
Runner->>Shell: Execute with cwd, env, timeout
Shell-->>Runner: stdout, stderr, exit code
Runner-->>Renderer: Truncated result
Renderer->>Renderer: Create and start child agent
Reviews (1): Last reviewed commit: "feat(worktrees): run a post-create setup..." | Re-trigger Greptile |
There was a problem hiding this comment.
Pull request overview
This PR adds a per-agent "Setup Script" hook that runs immediately after Maestro creates a new git worktree, so repo-local bootstrap steps (copying gitignored env files, generating config, installing deps) can be automated without wrapping git worktree add outside the app. It introduces a new git:worktreeRunSetup IPC that executes locally (OS-specific shell) or over SSH, exposes a small MAESTRO_* env context to the script, and wires the runner into all worktree creation flows.
Changes:
- Add a Worktree Config modal field to persist a per-agent setup command and run it only for freshly created worktrees.
- Implement
git:worktreeRunSetupIPC with local and SSH execution, runtime caps, and output truncation. - Expand types, preload surface, and tests to cover setup-script behavior end to end.
Reviewed changes
Copilot reviewed 18 out of 19 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/renderer/utils/worktreeSpawn.ts | Runs setup script after worktree creation in the Auto Run spawn path. |
| src/renderer/utils/worktreeSetupScript.ts | New renderer helper that resolves the owning parent agent and invokes the IPC, surfacing toasts. |
| src/renderer/types/index.ts | Adds SessionWorktreeConfig (including setupScript) and wires it into Session. |
| src/renderer/hooks/worktree/useWorktreeHandlers.ts | Runs setup script after create flows and preserves setupScript when auto-filling basePath. |
| src/renderer/hooks/batch/useWorktreeManager.ts | Runs setup script before starting a batch run in a newly created worktree. |
| src/renderer/global.d.ts | Extends window.maestro.git typing with worktreeRunSetup and related types. |
| src/renderer/components/WorktreeConfigModal.tsx | Adds UI for editing the setup script and saving it into the agent worktree config. |
| src/renderer/components/AppModals/AppWorktreeModals.tsx | Updates modal prop typing to use SessionWorktreeConfig. |
| src/renderer/components/AppModals/AppModals.tsx | Threads SessionWorktreeConfig type into AppModals props. |
| src/main/utils/worktree-setup-script.ts | New main-process runner for local or SSH setup-script execution, env injection, timeouts, output tailing. |
| src/main/utils/remote-git.ts | Exports execShellRemote and adds options for cwd/env/timeout. |
| src/main/utils/execFile.ts | Extends ExecOptions to support env alongside timeout and plumbs env to spawn-with-stdin path. |
| src/main/preload/git.ts | Adds new preload API and types for worktreeRunSetup. |
| src/main/ipc/handlers/git.ts | Registers git:worktreeRunSetup handler and resolves SSH remotes for it. |
| src/tests/renderer/utils/worktreeSetupScript.test.ts | Adds renderer tests for script resolution, no-op behavior, and toast surfaces. |
| src/tests/main/utils/worktree-setup-script.test.ts | Adds main-process tests for env exposure, local vs SSH execution, timeout and truncation behavior. |
| src/tests/main/ipc/handlers/git.test.ts | Updates IPC handler registry expectations to include the new channel. |
| docs/git-worktrees.md | Documents setup scripts, env vars, and Windows usage notes. |
| CLAUDE-IPC.md | Updates IPC surface documentation to include worktreeRunSetup. |
Comments suppressed due to low confidence (2)
src/renderer/hooks/worktree/useWorktreeHandlers.ts:383
- This comment uses an em-dash character, which the repo style guide explicitly forbids (see CLAUDE.md). Please replace it with a normal hyphen or punctuation.
// Fresh worktree on disk — bootstrap it with the agent's setup script.
src/renderer/hooks/worktree/useWorktreeHandlers.ts:509
- This comment uses an em-dash character, which the repo style guide explicitly forbids (see CLAUDE.md). Please replace it with a normal hyphen or punctuation.
// Fresh worktree on disk — bootstrap it with the agent's setup script.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| if (options) { | ||
| if ('input' in options || 'timeout' in options) { | ||
| if ('input' in options || 'timeout' in options || 'env' in options) { |
| // Fresh worktree on disk — run the parent agent's setup script before the | ||
| // agent spawns so .env files and generated config are already in place. |
| // Fresh worktree on disk — run the owning agent's setup script before the | ||
| // batch run starts, so generated env files exist for the first prompt. |
| @@ -381,6 +379,15 @@ export function useWorktreeHandlers(): WorktreeHandlersReturn { | |||
| // avoid re-marking — there was nothing newly created on disk to race with. | |||
| .getState() | ||
| .sessions.find( | ||
| (s) => !s.parentSessionId && s.worktreeConfig && normalizePath(s.cwd) === normalized | ||
| ); | ||
| } |
There was a problem hiding this comment.
Setup script owner is ambiguous
When multiple parent agents use the same repository with different worktree setup scripts, this lookup selects the first matching session rather than the agent starting the batch. The batch path can therefore execute another agent’s setup command in the new worktree, producing the wrong generated files or dependencies.
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/renderer/hooks/worktree/useWorktreeHandlers.ts (1)
1-1: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winEm-dash used in new comments across all four worktree-setup call sites.
Each of the four newly-added "run the setup script" call sites uses the same comment template containing an em-dash (
—), which violates the repository guideline against em-dashes/en-dashes in authored text.
src/renderer/hooks/worktree/useWorktreeHandlers.ts#L382-391: replace// Fresh worktree on disk — bootstrap it with the agent's setup script.with a plain-hyphen or colon phrasing (e.g.// Fresh worktree on disk: bootstrap it with the agent's setup script.).src/renderer/hooks/worktree/useWorktreeHandlers.ts#L508-518: same fix for the duplicate comment inhandleCreateWorktree.src/renderer/hooks/batch/useWorktreeManager.ts#L268-279: same fix for// Fresh worktree on disk — run the owning agent's setup script before the batch run starts, ....src/renderer/utils/worktreeSpawn.ts#L113-124: same fix for// Fresh worktree on disk — run the parent agent's setup script before the agent spawns ....🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/renderer/hooks/worktree/useWorktreeHandlers.ts` at line 1, Replace the em-dash in all four newly added “Fresh worktree on disk” comments across the worktree setup call sites with a colon or plain hyphen, preserving the existing comment wording and intent.Source: Coding guidelines
🧹 Nitpick comments (2)
src/renderer/components/WorktreeConfigModal.tsx (1)
334-363: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winApply the modal text-selection classes to the new script editor.
This is a click-driven modal. Add
select-noneto its root container andselect-textto this textarea and the other editable controls so text selection remains intentional.As per coding guidelines, click-driven TSX modals must use
select-noneon the root andselect-texton nested content-driven areas.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/renderer/components/WorktreeConfigModal.tsx` around lines 334 - 363, Update the WorktreeConfigModal root container to include select-none, then add select-text to the setup-script textarea and every other editable content-driven control in the modal. Preserve selection behavior so modal text is non-selectable by default while inputs and textareas remain selectable.Source: Coding guidelines
src/main/ipc/handlers/git.ts (1)
798-822: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReuse
WorktreeSetupContextinstead of redeclaring the shape inline.The
contextparameter type here duplicatesWorktreeSetupContext(exported fromworktree-setup-script.ts). Importing it keeps the IPC contract and the execution utility's type in sync if the shape changes later.♻️ Proposed refactor
-import { runWorktreeSetupScript } from '../../utils/worktree-setup-script'; +import { runWorktreeSetupScript, type WorktreeSetupContext } from '../../utils/worktree-setup-script'; ... async ( script: string, - context: { - worktreePath: string; - branchName: string; - mainRepoPath: string; - baseBranch?: string; - }, + context: WorktreeSetupContext, sshRemoteId?: string ) => {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/ipc/handlers/git.ts` around lines 798 - 822, Update the git:worktreeRunSetup handler to import and use the exported WorktreeSetupContext type for its context parameter instead of redeclaring the object shape inline. Keep the existing handler behavior and runWorktreeSetupScript invocation unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/git-worktrees.md`:
- Around line 117-123: Update the Windows setup guidance around the
`MAESTRO_MAIN_REPO_PATH` command to reference a checked-in `.cmd` or `.bat`
script executable by `cmd.exe`, rather than `./scripts/setup.sh`; keep the setup
field as a one-liner and retain the Windows-specific environment-variable
syntax.
In `@src/main/utils/worktree-setup-script.ts`:
- Around line 78-93: Update resolveSetupShell for Windows so multiline setup
scripts are converted into cmd.exe-compatible command separators or executed
through a temporary .bat/.cmd file instead of being passed raw inline. Preserve
the existing ComSpec selection and /d /s /c invocation behavior for single-line
scripts and keep non-Windows shell handling unchanged.
In `@src/renderer/utils/worktreeSetupScript.ts`:
- Around line 68-100: Report the caught worktreeRunSetup IPC exception to Sentry
before showing the error toast and returning false. Update the catch block in
the worktree setup flow to call the existing captureException utility with err,
following the pattern used by createPR in useWorktreeManager.ts, while
preserving the current user-facing error handling.
---
Outside diff comments:
In `@src/renderer/hooks/worktree/useWorktreeHandlers.ts`:
- Line 1: Replace the em-dash in all four newly added “Fresh worktree on disk”
comments across the worktree setup call sites with a colon or plain hyphen,
preserving the existing comment wording and intent.
---
Nitpick comments:
In `@src/main/ipc/handlers/git.ts`:
- Around line 798-822: Update the git:worktreeRunSetup handler to import and use
the exported WorktreeSetupContext type for its context parameter instead of
redeclaring the object shape inline. Keep the existing handler behavior and
runWorktreeSetupScript invocation unchanged.
In `@src/renderer/components/WorktreeConfigModal.tsx`:
- Around line 334-363: Update the WorktreeConfigModal root container to include
select-none, then add select-text to the setup-script textarea and every other
editable content-driven control in the modal. Preserve selection behavior so
modal text is non-selectable by default while inputs and textareas remain
selectable.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: a4270b1a-94ff-4856-a1a1-3043e10da627
📒 Files selected for processing (19)
CLAUDE-IPC.mddocs/git-worktrees.mdsrc/__tests__/main/ipc/handlers/git.test.tssrc/__tests__/main/utils/worktree-setup-script.test.tssrc/__tests__/renderer/utils/worktreeSetupScript.test.tssrc/main/ipc/handlers/git.tssrc/main/preload/git.tssrc/main/utils/execFile.tssrc/main/utils/remote-git.tssrc/main/utils/worktree-setup-script.tssrc/renderer/components/AppModals/AppModals.tsxsrc/renderer/components/AppModals/AppWorktreeModals.tsxsrc/renderer/components/WorktreeConfigModal.tsxsrc/renderer/global.d.tssrc/renderer/hooks/batch/useWorktreeManager.tssrc/renderer/hooks/worktree/useWorktreeHandlers.tssrc/renderer/types/index.tssrc/renderer/utils/worktreeSetupScript.tssrc/renderer/utils/worktreeSpawn.ts
| On Windows the command runs through `cmd.exe`, so reference the variables as `%MAESTRO_MAIN_REPO_PATH%`: | ||
|
|
||
| ```bat | ||
| copy "%MAESTRO_MAIN_REPO_PATH%\.env.local" . && npm install | ||
| ``` | ||
|
|
||
| Keep the platform-specific logic in a checked-in script (`./scripts/setup.sh`) and point the field at it - that way the setup steps live with the repo and the field stays a one-liner. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Make the Windows setup-script guidance shell-compatible.
The docs say Windows runs through cmd.exe but then recommend pointing the field at ./scripts/setup.sh, which cmd.exe cannot execute by default. Recommend a .cmd or .bat script for Windows, or explicitly invoke Bash when it is guaranteed to exist.
Suggested wording
-On Windows the command runs through `cmd.exe`, so reference the variables as `%MAESTRO_MAIN_REPO_PATH%`:
+On Windows the command runs through `cmd.exe`. Use a `.cmd` or `.bat` script, or explicitly invoke Bash if it is installed:
...
-Keep the platform-specific logic in a checked-in script (`./scripts/setup.sh`) and point the field at it - that way the setup steps live with the repo and the field stays a one-liner.
+Keep platform-specific logic in a checked-in script matching the target shell, such as `./scripts/setup.cmd` on Windows or `./scripts/setup.sh` on POSIX systems.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| On Windows the command runs through `cmd.exe`, so reference the variables as `%MAESTRO_MAIN_REPO_PATH%`: | |
| ```bat | |
| copy "%MAESTRO_MAIN_REPO_PATH%\.env.local" . && npm install | |
| ``` | |
| Keep the platform-specific logic in a checked-in script (`./scripts/setup.sh`) and point the field at it - that way the setup steps live with the repo and the field stays a one-liner. | |
| On Windows the command runs through `cmd.exe`. Use a `.cmd` or `.bat` script, or explicitly invoke Bash if it is installed: | |
| copy "%MAESTRO_MAIN_REPO_PATH%\.env.local" . && npm install | |
| Keep platform-specific logic in a checked-in script matching the target shell, such as `./scripts/setup.cmd` on Windows or `./scripts/setup.sh` on POSIX systems. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/git-worktrees.md` around lines 117 - 123, Update the Windows setup
guidance around the `MAESTRO_MAIN_REPO_PATH` command to reference a checked-in
`.cmd` or `.bat` script executable by `cmd.exe`, rather than
`./scripts/setup.sh`; keep the setup field as a one-liner and retain the
Windows-specific environment-variable syntax.
| /** | ||
| * Shell used to interpret the configured command. `cmd.exe /d /s /c` on Windows, | ||
| * the user's login shell (falling back to `/bin/sh`) everywhere else. | ||
| */ | ||
| export function resolveSetupShell(): { command: string; args: (script: string) => string[] } { | ||
| if (isWindows()) { | ||
| return { | ||
| command: process.env.ComSpec || 'cmd.exe', | ||
| args: (script) => ['/d', '/s', '/c', script], | ||
| }; | ||
| } | ||
| return { | ||
| command: process.env.SHELL || '/bin/sh', | ||
| args: (script) => ['-c', script], | ||
| }; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
fd -i WorktreeConfigModal
rg -n -A5 -B5 'setupScript' -g 'WorktreeConfigModal*'Repository: RunMaestro/Maestro
Length of output: 204
🏁 Script executed:
#!/bin/bash
set -e
echo "== files =="
git ls-files | rg '(^|/)WorktreeConfigModal\.tsx$|worktree-setup-script\.ts$|worktree' | sed -n '1,120p'
echo
echo "== WorktreeConfigModal outline =="
ast-grep outline src/renderer/components/WorktreeConfigModal.tsx --view compact 2>/dev/null || true
echo
echo "== setupScript references in WorktreeConfigModal =="
rg -n -C 4 'setupScript|multiline|textarea|multi' src/renderer/components/WorktreeConfigModal.tsx
echo
echo "== worktree setup script relevant lines =="
sed -n '1,180p' src/main/utils/worktree-setup-script.ts
echo
echo "== imports and setupScript data model =="
rg -n -C 3 'setupScript|Worktree|worktreeSetup|setup-script' src -g '*.ts' -g '*.tsx' | sed -n '1,240p'Repository: RunMaestro/Maestro
Length of output: 28826
🌐 Web query:
cmd.exe /c multi-line command newline behavior CreateProcess argv embedded newline
💡 Result:
The cmd.exe /c command processor does not support passing literal multi-line commands directly [1][2]. When cmd.exe /c is invoked, it treats the provided string as a single command line and strictly ignores or truncates any embedded newline characters [1]. Key technical constraints and behaviors: 1. CMD Parsing Logic: When using /c or /k, cmd.exe processes the remainder of the command line after the switch [3][4]. If this string contains newline characters, they are not interpreted as command separators; instead, the command line is terminated or broken at the newline, effectively causing the parser to ignore subsequent lines [1]. 2. CreateProcess argv Handling: CreateProcess accepts a command-line string (lpCommandLine) [5]. While the Windows API technically allows null characters within a string, cmd.exe itself is fundamentally designed around line-based processing [1]. Even if you successfully pass a string with an embedded newline character via the CreateProcess API, cmd.exe will truncate execution at the first newline it encounters [1]. 3. Workarounds for Multi-line Commands: - Use Command Separators: Multiple commands can be executed in one line by using the && or | operators [6][7]. - Use Temporary Batch Files: For complex scripts, write the commands to a temporary.bat or.cmd file and then invoke that file using cmd.exe /c [2]. - Leverage Escaping for Line Continuation: In some specific contexts, using the caret (^) character followed by a newline allows for visual multi-line formatting in batch files, but this is a pre-processing feature of the batch parser, not a mechanism to pass multi-line strings through the cmd /c argument [2]. - PowerShell Alternative: If you are attempting to run multi-line code, consider using powershell -Command or powershell -EncodedCommand, which support more robust handling of multi-line input when properly quoted or encoded [1][2].
Citations:
- 1: https://stackoverflow.com/questions/78840147/powershell-escaping-rules-for-cli-calls-with-special-character-sequences
- 2: https://stackoverflow.com/questions/45224759/using-multi-line-powershell-commands-from-cmd-exe
- 3: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/cmd
- 4: https://github.com/johnstevenson/winbox-args/wiki/How-cmd.exe-extracts-a-command
- 5: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
- 6: https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-xp/bb490880%28v=technet.10%29
- 7: https://www.computerhope.com/cmd.htm
Handle multiline setup scripts before passing them to cmd.exe.
WorktreeConfigModal reads the raw setupScript from a multiline <textarea> and sends it to resolveSetupShell(). On Windows, cmd.exe /d /s /c "<script>" does not treat embedded newlines as command separators, so a valid multiline POSIX script can stop after the first line or fail. Use Windows command separators (&&/&) or a temp .bat/.cmd invocation instead of passing the raw multiline string inline.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/utils/worktree-setup-script.ts` around lines 78 - 93, Update
resolveSetupShell for Windows so multiline setup scripts are converted into
cmd.exe-compatible command separators or executed through a temporary .bat/.cmd
file instead of being passed raw inline. Preserve the existing ComSpec selection
and /d /s /c invocation behavior for single-line scripts and keep non-Windows
shell handling unchanged.
| try { | ||
| const result = await window.maestro.git.worktreeRunSetup( | ||
| script, | ||
| { worktreePath, branchName, mainRepoPath, baseBranch }, | ||
| sshRemoteId | ||
| ); | ||
|
|
||
| if (!result.ran) return false; | ||
|
|
||
| if (!result.success) { | ||
| notifyToast({ | ||
| type: 'error', | ||
| title: 'Worktree Setup Script Failed', | ||
| message: result.error || 'Setup script exited with an error', | ||
| }); | ||
| return false; | ||
| } | ||
|
|
||
| notifyToast({ | ||
| type: 'success', | ||
| title: 'Worktree Setup Complete', | ||
| message: `Setup script finished for ${branchName}`, | ||
| }); | ||
| return true; | ||
| } catch (err) { | ||
| notifyToast({ | ||
| type: 'error', | ||
| title: 'Worktree Setup Script Failed', | ||
| message: err instanceof Error ? err.message : String(err), | ||
| }); | ||
| return false; | ||
| } | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Report the swallowed IPC exception to Sentry.
The catch block here intentionally swallows the worktreeRunSetup IPC failure (shows a toast, returns false) but never calls captureException. Per the coding guideline for .ts/.tsx files, intentional catches should still go through the Sentry reporting utilities — otherwise a regressed IPC channel or main-process crash here would be invisible in Sentry. Note the same PR already does this correctly elsewhere (useWorktreeManager.ts's createPR, which calls captureException for its own "nice-to-have" git.log failure).
🩹 Proposed fix
+import { captureException } from '../services/sentry'; // adjust to the actual Sentry utility import path
...
} catch (err) {
+ captureException(err, { extra: { worktreePath, branchName, mainRepoPath } });
notifyToast({
type: 'error',
title: 'Worktree Setup Script Failed',
message: err instanceof Error ? err.message : String(err),
});
return false;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| try { | |
| const result = await window.maestro.git.worktreeRunSetup( | |
| script, | |
| { worktreePath, branchName, mainRepoPath, baseBranch }, | |
| sshRemoteId | |
| ); | |
| if (!result.ran) return false; | |
| if (!result.success) { | |
| notifyToast({ | |
| type: 'error', | |
| title: 'Worktree Setup Script Failed', | |
| message: result.error || 'Setup script exited with an error', | |
| }); | |
| return false; | |
| } | |
| notifyToast({ | |
| type: 'success', | |
| title: 'Worktree Setup Complete', | |
| message: `Setup script finished for ${branchName}`, | |
| }); | |
| return true; | |
| } catch (err) { | |
| notifyToast({ | |
| type: 'error', | |
| title: 'Worktree Setup Script Failed', | |
| message: err instanceof Error ? err.message : String(err), | |
| }); | |
| return false; | |
| } | |
| } | |
| try { | |
| const result = await window.maestro.git.worktreeRunSetup( | |
| script, | |
| { worktreePath, branchName, mainRepoPath, baseBranch }, | |
| sshRemoteId | |
| ); | |
| if (!result.ran) return false; | |
| if (!result.success) { | |
| notifyToast({ | |
| type: 'error', | |
| title: 'Worktree Setup Script Failed', | |
| message: result.error || 'Setup script exited with an error', | |
| }); | |
| return false; | |
| } | |
| notifyToast({ | |
| type: 'success', | |
| title: 'Worktree Setup Complete', | |
| message: `Setup script finished for ${branchName}`, | |
| }); | |
| return true; | |
| } catch (err) { | |
| captureException(err, { extra: { worktreePath, branchName, mainRepoPath } }); | |
| notifyToast({ | |
| type: 'error', | |
| title: 'Worktree Setup Script Failed', | |
| message: err instanceof Error ? err.message : String(err), | |
| }); | |
| return false; | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/renderer/utils/worktreeSetupScript.ts` around lines 68 - 100, Report the
caught worktreeRunSetup IPC exception to Sentry before showing the error toast
and returning false. Update the catch block in the worktree setup flow to call
the existing captureException utility with err, following the pattern used by
createPR in useWorktreeManager.ts, while preserving the current user-facing
error handling.
Source: Path instructions
Closes #409
Problem
A fresh worktree only contains what git tracks. Anything gitignored -
.env.local, generated config, installed dependencies - is missing until you recreate it by hand, every single time. Issue #409 asked for a hook to run an OS-specific script after worktree creation, and the workaround people landed on was a shell script that wrapsgit worktree addentirely, which means giving up Maestro's worktree UI.What this adds
A per-agent Setup Script in the Worktree Configuration modal. It runs inside each worktree Maestro creates, with the new worktree as its working directory.
Available to the script:
MAESTRO_WORKTREE_PATHMAESTRO_WORKTREE_BRANCHMAESTRO_MAIN_REPO_PATHMAESTRO_BASE_BRANCHSo the two use cases from the issue become:
OS-specific logic stays in a checked-in script that the field points at, so it lives with the repo rather than in app config.
Implementation
git:worktreeRunSetupIPC (src/main/utils/worktree-setup-script.ts) runs the command throughcmd.exe /d /s /con Windows and the login shell elsewhere, with a 10 minute cap and stdout/stderr truncated to a 4k tail.git:createPRgivesgh), so GUI-launched Electron on macOS doesn't losenode/npm.execShellRemoteinremote-git.ts; the privateexecRemoteShellCommandnow delegates to it.worktreeSpawn.ts), batch runner (useWorktreeManager) - through one renderer helper, gated onresult.createdso reused or re-attached worktrees never re-run it.execFileNoThrow'sExecOptionsform now acceptsenvalongsidetimeout(previously mutually exclusive), which the runner needs.Design notes
The script is stored per parent agent rather than read from a file in the repo. Auto-executing a checked-in script on
git worktree addwould mean any cloned repo could run code the moment you make a worktree; requiring the user to type the command keeps that surface closed while still letting the command be./scripts/setup.sh.Notes for review
useWorktreeHandlers.tsshows ~85 lines of reindentation: shortening thehandleSaveWorktreeConfigparameter type let Prettier collapse theuseCallback(wrapper onto one line.git diff -won that file is 27 insertions / 8 deletions.Testing
src/__tests__/main/utils/worktree-setup-script.test.ts- 13 tests: no-op paths, env exposure, local vs SSH dispatch, exit-code/timeout reporting, output truncation, PATH-probe failuresrc/__tests__/renderer/utils/worktreeSetupScript.test.ts- 7 tests: script resolution by session and by repo path, child-agent exclusion, toast surfaces, IPC rejection handlingnpm run lint(all three configs) andprettier --checkclean on the changed filesSummary by CodeRabbit
New Features
Documentation
Tests