Skip to content

feat: Windows support#45

Open
shakedarazi wants to merge 6 commits into
cloudmanic:mainfrom
shakedarazi:feat/windows-support
Open

feat: Windows support#45
shakedarazi wants to merge 6 commits into
cloudmanic:mainfrom
shakedarazi:feat/windows-support

Conversation

@shakedarazi

Copy link
Copy Markdown

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 <175728472+Copilot@users.noreply.github.com>
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