Skip to content

Add Windows support for Git Bash and PowerShell#114

Open
Fronix wants to merge 13 commits intosatococoa:mainfrom
Fronix:thoraxe-win-support
Open

Add Windows support for Git Bash and PowerShell#114
Fronix wants to merge 13 commits intosatococoa:mainfrom
Fronix:thoraxe-win-support

Conversation

@Fronix
Copy link
Copy Markdown

@Fronix Fronix commented Apr 10, 2026

Summary

Builds on #61 by @thoraxe — adds comprehensive Windows support with Git Bash and PowerShell shell integration, and fixes all CI failures on Windows.

Original changes (from #61)

  • Enable Windows AMD64 builds in .goreleaser.yml with zip packaging
  • Add PowerShell (pwsh) to supported shells in shell_init.go
  • Implement PowerShell completion script patching to fix command name resolution
  • Create PowerShell cd hook with smart executable path discovery
  • Fix path separator handling in tests for cross-platform compatibility
  • Re-enable windows-latest in GitHub Actions CI matrix
  • Add Git configuration for Windows CI to handle line endings
  • Update README with comprehensive Windows installation and setup instructions

Additional fixes

  • Resolve lint errors: variable shadowing in worktree_managed.go, line length in completion_config.go, goconst for "windows" string
  • Use shell: bash in CI test steps to prevent PowerShell arg splitting
  • Fix cross-platform path handling in unit and e2e tests (filepath.Join, platform-aware absolute paths, 8.3 short path resolution)
  • Add windows-latest to E2E test matrix with bash shell default
  • Normalize CRLF line endings in completion script patching and golden file comparison
  • Handle .exe extension for WTP binary in e2e test framework on Windows
  • Replace Unix-specific test commands (touch, sleep, pwd) with cross-platform alternatives

Summary by CodeRabbit

  • New Features

    • Official Windows builds (.exe) and ZIP packaging; PowerShell (pwsh) subcommand and hook for shell integration and cd behavior.
  • Documentation

    • Added Windows installation and PowerShell/Git Bash setup instructions.
  • Improvements

    • CI and release pipelines now run on Windows; added CRLF→LF normalization and cross-platform path handling for better Windows compatibility.
  • Tests

    • Test suite updated for OS-aware behavior and Windows-friendly assertions.

thoraxe and others added 10 commits April 10, 2026 11:33
- Add Windows (amd64/arm64) to CI workflow and GoReleaser config
- Fix shell detection and hook scripts for Git Bash and PowerShell
- Fix path separator handling in worktree management (git returns
  forward slashes on Windows, Go uses backslashes)
- Skip tests with hardcoded Unix paths on Windows

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix variable shadowing in EvalSymlinks calls and line length violation.
PowerShell splits -coverprofile=coverage.out into separate args.
Use filepath.Join, platform-aware commands, and .exe binary extension.
Use cross-platform command in shell executor test and add
windows-latest to e2e matrix with bash shell default.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 10, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 607659d2-cf6d-4901-a037-ab8ca09a9505

📥 Commits

Reviewing files that changed from the base of the PR and between 32b4408 and 44f5153.

📒 Files selected for processing (1)
  • cmd/wtp/hook.go

📝 Walkthrough

Walkthrough

Adds Windows/PowerShell support across CI, release packaging, docs, shell integration, completion patching, path normalization, and many tests; enables Windows builds and normalizes CRLF/LF and OS-specific path/command behavior.

Changes

Cohort / File(s) Summary
CI / E2E Workflows
\.github/workflows/ci.yml, \.github/workflows/e2e-test.yml
Add windows-latest to matrices, set default bash shell, configure Git line endings on Windows, and re-enable Windows build step.
Release Configuration
\.goreleaser.yml
Add windows target, ignore windows/arm64, and produce ZIP archives for Windows builds.
Documentation
README.md
Add Windows installation and PowerShell/Git Bash setup instructions plus Windows-specific shell integration examples.
PowerShell Shell Integration
cmd/wtp/hook.go, cmd/wtp/shell_init.go
Add pwsh subcommands/handlers and printPowerShellHook to emit a PowerShell hook that resolves wtp and forwards/intercepts cd/add.
Completion Script Handling
cmd/wtp/completion_config.go, cmd/wtp/completion_config_test.go
Normalize CRLF→LF, add pwsh case with patchPowerShellCompletionScript to hardcode command name, and adjust tests to canonicalize line endings.
Platform Constants & Path Normalization
cmd/wtp/add.go, cmd/wtp/worktree_managed.go
Add osWindows constant and clean/EvalSymlinks inputs before path comparisons for robust cross-platform detection.
Cross-Platform Test Adjustments
cmd/wtp/*.go tests, internal/*_test.go, cmd/wtp/testhelpers_test.go
Replace hardcoded POSIX paths with filepath helpers, add Windows skips for Unix-specific tests, and avoid Unix permission assertions on Windows.
E2E Framework & Tests
test/e2e/framework/*, test/e2e/*_test.go
Normalize paths with ToSlash/EvalSymlinks, handle wtp.exe on Windows (hard-linking when using WTP_E2E_BINARY), and use OS-specific hook/test commands.
Executor & Misc Tests
internal/command/executor_test.go, cmd/wtp/add_test.go, cmd/wtp/cd_test.go, cmd/wtp/list_test.go
Avoid hardcoded /tmp, use os.TempDir() and filepath-based expectations, add OS guards to problematic tests.

Sequence Diagram(s)

sequenceDiagram
    participant Shell as Shell (pwsh / bash)
    participant Profile as Hook function (profile)
    participant WTP as wtp executable
    participant FS as Filesystem / Git

    Shell->>Profile: user invokes wtp or sources hook
    Profile->>WTP: resolve executable (wtp.exe → wtp → ./wtp)
    Shell->>Profile: user runs "wtp cd <worktree>"
    Profile->>WTP: call `wtp cd <worktree>`
    WTP->>Profile: returns path / status
    Profile->>Shell: on success -> Set-Location (pwsh) / cd (bash)
    Shell->>Profile: user runs "wtp add ..."
    Profile->>WTP: forward args (honor help/redirected stdout)
    WTP->>Profile: returns output
    Profile->>Shell: when output includes target dir -> change dir if appropriate
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested labels

codex

Poem

🐰 I hopped from bash into pwsh light,
CRLF trimmed to LF by moonlit night,
zips and exes join the release,
paths cleaned up and tests find peace,
WTP leaps — tails high, take flight!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add Windows support for Git Bash and PowerShell' directly and clearly describes the main objective of the PR: adding Windows support with Git Bash and PowerShell integration. It is concise, specific, and accurately summarizes the primary change.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
cmd/wtp/testhelpers_test.go (1)

57-71: Input paths remain Unix-style while expected values use OS-specific separators.

The expected values correctly use filepath.Join for cross-platform compatibility, but the input paths (e.g., "/path/to/repo/.worktrees/feature/test") remain Unix-style with forward slashes. On Windows, these paths may not be recognized as absolute paths or may behave inconsistently.

If the function under test (fn) is expected to work with real filesystem paths, consider also constructing inputs with filepath.Join or documenting that the function handles both path formats.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/wtp/testhelpers_test.go` around lines 57 - 71, The test uses hard-coded
Unix-style paths as inputs which can fail on Windows; update the two t.Run cases
that call fn (the non-main and outside base_dir cases) to build input paths
using filepath.Join or convert with filepath.FromSlash so inputs are OS-native
(e.g., replace "/path/to/repo/.worktrees/feature/test" and
"/completely/different/path" with filepath.Join or filepath.FromSlash variants)
so fn is exercised with platform-correct absolute paths while keeping the
expected values using filepath.Join.
README.md (1)

125-146: Consider clarifying PATH persistence for PowerShell.

Line 137-138 mentions "add this line to your PowerShell profile for persistence" but only shows the session-level $env:PATH modification. Users may not know how to make this permanent.

📝 Suggested clarification
 # Add to PATH (add this line to your PowerShell profile for persistence)
 $env:PATH += ";$env:LOCALAPPDATA\wtp"
+
+# To persist the PATH change, add the above line to your PowerShell profile:
+# notepad $PROFILE
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 125 - 146, Clarify the PowerShell persistence step by
explaining how to make the $env:PATH change permanent: instruct the user to open
their PowerShell profile (referencing $PROFILE) and append a line that adds the
install directory to PATH, or alternatively use the user-level environment
setter ([System.Environment]::SetEnvironmentVariable) to persistently add
"$env:LOCALAPPDATA\wtp" to the PATH; mention which approach updates only the
current session (the existing $env:PATH example) versus persistent changes so
readers know to edit their PowerShell profile or use the environment API.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/wtp/completion_config.go`:
- Around line 259-271: Add a unit test for patchPowerShellCompletionScript that
verifies the replacement actually occurs (similar to
TestPatchCompletionScriptBashSanitizesDescriptions and
TestPatchCompletionScriptZshInjectsCompletionEnv): create an input PowerShell
completion script containing the original target snippet ("$fn =
$($MyInvocation.MyCommand.Name)..." / Register-ArgumentCompleter -CommandName
$name ...) and assert the output contains "Register-ArgumentCompleter -Native
-CommandName 'wtp' -ScriptBlock {"; optionally add a golden file
pwsh_expected.ps1 and a golden-file test to ensure future changes in urfave/cli
that alter the source format will fail the test. Ensure the test calls
patchPowerShellCompletionScript and checks the replaced string (or compares to
the golden file) so the patching cannot silently pass through unchanged.

In `@cmd/wtp/hook.go`:
- Around line 244-297: The PowerShell hook generated by printPowerShellHook is
missing the `wtp add` auto-cd behavior; update the function printPowerShellHook
to add an elseif branch for when $args[0] -eq "add" that mirrors other shells:
forward help flags to the real executable, detect interactive output with
[Console]::IsOutputRedirected (or its negation) to decide quiet invocation, call
& $__wtpPath `@args` --quiet capturing $targetDir and $LASTEXITCODE, and if exit
code is 0 and $targetDir is set call Set-Location $targetDir; otherwise invoke &
$__wtpPath `@args` normally. Ensure you reference $__wtpPath and preserve existing
completion and cd handling.
- Around line 283-293: The PowerShell handler currently errors when `wtp cd` has
no argument; make it match other shells by treating missing $args[1] as a
request for the main worktree. Change the block around $__wtpPath cd so that
when (-not $args[1]) you call `$targetDir = & $__wtpPath cd 2>$null` (instead of
Write-Error/return), otherwise call `$targetDir = & $__wtpPath cd $args[1]
2>$null`; then preserve the existing $LASTEXITCODE check and
Set-Location/$__wtpPath fallback behavior (referencing $__wtpPath and
$targetDir).

In `@cmd/wtp/list_test.go`:
- Around line 681-683: Replace the unconditional Windows skip around the
runtime.GOOS == osWindows / t.Skip call in cmd/wtp/list_test.go with OS-agnostic
test logic: remove the skip and normalize path handling in the affected tests by
using filepath.FromSlash/filepath.Join (or construct expected outputs using
os.PathSeparator) so the list-output and quiet-mode assertions compare
normalized paths on Windows and Unix; update the assertions in the same test(s)
that reference Unix-specific paths to generate their expected strings via
filepath utilities instead of hardcoded "/" separators (leave a conditional skip
only if a real platform limitation remains, otherwise remove it).

In `@internal/command/executor_test.go`:
- Around line 324-334: The test currently only asserts non-empty output so it
won't detect if workDir is ignored; change it to run a directory-sensitive
command and assert the output matches tmpDir: call shell.Execute with a
platform-specific command (use runtime.GOOS to pick "cmd /C cd" on windows and
"pwd" on unix-like systems) using tmpDir as the working directory, then assert
no error and that the trimmed output equals or contains the tmpDir path
(reference the tmpDir variable and the shell.Execute call).

---

Nitpick comments:
In `@cmd/wtp/testhelpers_test.go`:
- Around line 57-71: The test uses hard-coded Unix-style paths as inputs which
can fail on Windows; update the two t.Run cases that call fn (the non-main and
outside base_dir cases) to build input paths using filepath.Join or convert with
filepath.FromSlash so inputs are OS-native (e.g., replace
"/path/to/repo/.worktrees/feature/test" and "/completely/different/path" with
filepath.Join or filepath.FromSlash variants) so fn is exercised with
platform-correct absolute paths while keeping the expected values using
filepath.Join.

In `@README.md`:
- Around line 125-146: Clarify the PowerShell persistence step by explaining how
to make the $env:PATH change permanent: instruct the user to open their
PowerShell profile (referencing $PROFILE) and append a line that adds the
install directory to PATH, or alternatively use the user-level environment
setter ([System.Environment]::SetEnvironmentVariable) to persistently add
"$env:LOCALAPPDATA\wtp" to the PATH; mention which approach updates only the
current session (the existing $env:PATH example) versus persistent changes so
readers know to edit their PowerShell profile or use the environment API.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 47afe791-6539-43ab-9f68-f3dd8a0f80e0

📥 Commits

Reviewing files that changed from the base of the PR and between 842920d and 042c12f.

📒 Files selected for processing (23)
  • .github/workflows/ci.yml
  • .github/workflows/e2e-test.yml
  • .goreleaser.yml
  • README.md
  • cmd/wtp/add.go
  • cmd/wtp/add_test.go
  • cmd/wtp/cd_test.go
  • cmd/wtp/completion_config.go
  • cmd/wtp/completion_config_test.go
  • cmd/wtp/hook.go
  • cmd/wtp/init_test.go
  • cmd/wtp/list_test.go
  • cmd/wtp/shell_init.go
  • cmd/wtp/testhelpers_test.go
  • cmd/wtp/worktree_managed.go
  • internal/command/executor_test.go
  • internal/config/config_test.go
  • internal/git/repository_test.go
  • internal/git/worktree_test.go
  • test/e2e/framework/assertions.go
  • test/e2e/framework/framework.go
  • test/e2e/hook_streaming_test.go
  • test/e2e/worktree_test.go

Comment thread cmd/wtp/completion_config.go
Comment thread cmd/wtp/hook.go
Comment thread cmd/wtp/hook.go
Comment thread cmd/wtp/list_test.go Outdated
Comment thread internal/command/executor_test.go Outdated
Fronix added 2 commits April 10, 2026 13:12
Add PowerShell completion patching test, remove Windows skips in
list tests with cross-platform assertions, and assert working
directory in executor test.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/wtp/hook.go`:
- Around line 270-279: The wrapper currently emits numeric return values into
the PowerShell pipeline (e.g. in the error branch checking -not $__wtpPath and
in the completion/dispatch paths inside foreach ($arg in $args) where it uses
"return $LASTEXITCODE" or numeric returns); replace any "return 0"/"return
1"/"return $LASTEXITCODE" with a bare "return" after native invocations to avoid
writing numbers to the pipeline, and for the error case when $__wtpPath is
missing set $global:LASTEXITCODE = 1 before doing the bare return; update all
occurrences around $__wtpPath, the foreach ($arg in $args) completion branch,
and any other wrapper exit points accordingly.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: b18cf40c-dd5f-44a3-ae46-fbde399bfe26

📥 Commits

Reviewing files that changed from the base of the PR and between 042c12f and 32b4408.

📒 Files selected for processing (4)
  • cmd/wtp/completion_config_test.go
  • cmd/wtp/hook.go
  • cmd/wtp/list_test.go
  • internal/command/executor_test.go
✅ Files skipped from review due to trivial changes (2)
  • cmd/wtp/list_test.go
  • internal/command/executor_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/wtp/completion_config_test.go

Comment thread cmd/wtp/hook.go Outdated
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.

2 participants