Skip to content

feat: Windows support#45

Merged
cloudmanic merged 6 commits into
cloudmanic:mainfrom
shakedarazi:feat/windows-support
Jul 22, 2026
Merged

feat: Windows support#45
cloudmanic merged 6 commits into
cloudmanic:mainfrom
shakedarazi:feat/windows-support

Conversation

@shakedarazi

Copy link
Copy Markdown
Contributor

Adds Windows support to the herdr-plus plugin. Verified end-to-end against a live herdr 0.7.4-preview on Windows 11 (Go 1.26.2); Linux/macOS behaviour unchanged.

What was needed on Windows

Three platform differences drove the change:

  1. IPC is a named pipe, not a unix socket. herdr on Windows exposes its socket API as a named pipe at \\.\pipe\<socketPath> (the on-disk herdr.sock is just a liveness marker). Protocol is identical newline-delimited JSON, no token handshake. Added build-tagged dialHerdr: named pipe on Windows (retrying on ERROR_PIPE_BUSY), unix socket elsewhere. Stdlib only, no new deps.
  2. Can't spawn an extensionless PE. CreateProcessW appends .exe, so the binary is herdr-plus.exe and each action/pane gets a -windows twin (herdr requires unique action/pane ids; duplicate event on= differentiated by platforms is allowed). Relative-path spawn resolves against herdr's cwd, so Windows entries shell through powershell -Command "& .\bin\herdr-plus.exe <sub>". Panes omit -NonInteractive (interactive TUIs); actions/events keep it.
  3. Shell + quoting differ. Centralized every OS difference into one platform descriptor in shell.go (PowerShell vs sh, PowerShell vs POSIX quoting, pane suffix, {{opener}} = Start-Process/open/xdg-open) — no scattered runtime.GOOS.

Verified

  • Cross-OS go build (windows/linux/darwin), go vet ./..., go test ./... all green.
  • Plugin links + enables with platforms = [linux, macos, windows].
  • Named-pipe transport, action spawn, Projects workspace open (tabs + split panes + startup commands, hostile-value quoting round-trip), and worktree.created → auto-layout all exercised on the live host.
  • ~/$VARS expansion unit-tested on Windows.

Also

  • expandedWorkingDir now surfaces a home-dir resolution error instead of silently discarding it (a missing USERPROFILE would have resolved ~ to a wrong path).
  • goreleaser ships Windows amd64 binaries as .zip.

🤖 Generated with Claude Code

herdr's IPC on Windows is a named pipe at \.\pipe\<socketPath>, not a unix socket. Add build-tagged dialHerdr: named pipe on Windows (retrying on ERROR_PIPE_BUSY), unix socket elsewhere. Stdlib only.
One platform descriptor selected once replaces scattered runtime.GOOS checks: PowerShell vs sh, powershellQuote vs posixQuote, pane -windows suffix, and the {{opener}} command (Start-Process/open/xdg-open). Quick-action examples use {{opener}} so they work cross-OS.
Windows can't spawn the extensionless PE, so each action/pane gets a -windows twin running herdr-plus.exe via a powershell wrapper (relative-path spawn needs a shell). Panes omit -NonInteractive (interactive TUIs); actions/events keep it. manifest_test scans command args for the .exe.
os.UserHomeDir error was silently discarded; on Windows a missing USERPROFILE would resolve ~ to a wrong path. Return the error when the path needs home; add displayWorkingDir for UI paths that can't surface one. Also routes pane opens through paneEntrypoint.
Add windows/amd64 to goreleaser (skip windows/arm64) and override the archive format to .zip for Windows.
Copilot AI review requested due to automatic review settings July 20, 2026 17:12

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds first-class Windows support to the herdr-plus plugin by introducing Windows-specific IPC dialing (named pipes), centralizing shell/quoting behavior behind a platform descriptor, and updating the plugin manifest and release packaging to include Windows binaries and entrypoints.

Changes:

  • Add OS-specific abstractions for shell execution/quoting, pane entrypoint selection, and “open” command templating ({{opener}}).
  • Add build-tagged IPC dialing to support Windows named pipes while preserving Unix domain socket behavior elsewhere.
  • Update plugin manifest, examples, tests, and GoReleaser packaging to support Windows install/run flows.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
util.go Removes POSIX-only shellQuote helper now centralized elsewhere.
shell.go Introduces platform descriptor (shell, quoting, pane suffix, opener) and helpers.
shell_test.go Adds cross-platform unit tests for quoting/shell dispatch/entrypoint/opener.
quickactions.go Uses paneEntrypoint() so the correct pane id is opened per OS.
projectsmodel.go Switches UI display to use displayWorkingDir() for non-error UI contexts.
projectsmodel_test.go Adjusts assertions for platform-native path normalization.
projects.go Uses paneEntrypoint() and propagates expandedWorkingDir() errors when opening projects.
project.go Makes expandedWorkingDir() return (string, error), adds displayWorkingDir() helper.
project_test.go Updates tests for expandedWorkingDir() error return and separator normalization.
manifest_test.go Adds test ensuring manifest includes required Windows entries/commands.
herdrdial_windows.go Adds Windows dialHerdr() using named pipes with retry on ERROR_PIPE_BUSY.
herdrdial_other.go Adds non-Windows dialHerdr() using unix domain sockets.
herdr.go Switches client transport to dialHerdr() to unify Windows/Unix IPC.
herdr-plugin.toml Adds Windows platform + build step + windows-twin actions/panes/events.
examples/quick-actions/open-working-dir.toml Uses {{opener}} and updates description to be cross-platform.
examples/quick-actions/open-repo.toml Replaces hardcoded open with {{opener}}.
examples/quick-actions/google.toml Replaces hardcoded open with {{opener}}.
examples/quick-actions/google-search.toml Replaces hardcoded open with {{opener}}.
examples/quick-actions/github.toml Replaces hardcoded open with {{opener}} and documents it.
action.go Adds template funcs ({{opener}}) and routes execution via shellCommand().
action_test.go Updates expected quoting to be OS-specific; adds opener helper test.
action_run_integration_test.go Adds integration test to validate quoting round-trip through real shells.
.goreleaser.yml Adds Windows builds and ships Windows archives as .zip.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread herdr.go
Comment thread project.go
Comment on lines 216 to 219
// expandedWorkingDir resolves the project's working directory to an absolute
// path, expanding a leading ~ to the home directory and any $VARS in the path.
// An empty working_dir defaults to the user's home directory, so a minimal
// project still opens somewhere sensible.
Co-authored-by: Copilot Autofix powered by AI <[email protected]>

@cloudmanic cloudmanic left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for this, @shakedarazi — this is exactly the work that was missing. When Windows got dropped back in #20 it was specifically because the socket client and the sh-based build step had never been validated there, so declaring the platform would have been dishonest. This resolves precisely that: a real named-pipe transport (with the ERROR_PIPE_BUSY retry), a Windows build step, and end-to-end validation against the herdr Windows beta.

The engineering is clean. Centralizing every OS difference into the platform descriptor in shell.go rather than scattering runtime.GOOS checks is the right call, the PowerShell single-quote-doubling keeps injected quick-action values safe, and the build-tagged dialHerdr keeps the unix path untouched — I ran the Mac suite with -race and it's green, and it cross-compiles for all three OSes. Approving, and glad to have Windows back.

One non-blocking follow-up: the README doesn't yet mention that Windows installs need Go on PATH (the Windows build step has no prebuilt-binary fallback like the sh script does). Worth a short note there.

@cloudmanic
cloudmanic merged commit 987d579 into cloudmanic:main Jul 22, 2026
2 checks passed
cloudmanic added a commit that referenced this pull request Jul 22, 2026
The Windows build step compiles from source with the Go toolchain and has no
prebuilt-binary fallback like the Linux/macOS sh script, so Windows installs
require Go on PATH. Document that in the README and the installation docs, and
refresh the now-stale "not tested on Windows" / Linux+macOS-only platform lines
now that Windows is supported and validated against herdr's Windows beta.
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.

3 participants