Skip to content

Support Windows #208

Open
Open

Description

@tresat

It would be nice to use this tool on Windows as well.

Activity

  1. frenchie4111 commented on Aug 3, 2026

    @frenchie4111
    Collaborator

    Agreed - I don't personally have any windows computers to test on but I would love to see a PR for support. It can't be that hard to support it, although windows has a much weirder shell environment which might cause issue

  2. frenchie4111 commented on Aug 13, 2026

    @frenchie4111
    Collaborator

    I did a pass over the codebase to scope this out. Here's what a native Windows port actually runs into.

    One piece of good news up front: @anthropic-ai/claude-code-win32-x64 is already published on npm (v2.1.229), and src/main/json-claude-manager.ts:135-144 already maps win32-x64/win32-arm64 → claude.exe. So the Chat-tab binary resolution story is essentially done. node-pty also supports Windows via ConPTY.

    Real blockers

    Area Where Problem
    Shell resolution src/main/user-shell.ts:13-21 Hardcoded /bin/zsh → /bin/sh candidate list; the final fallback is a path that cannot exist on Windows
    Login-shell flags user-shell.ts:26 + 7 callsites -ilc is bash/zsh-only. Used by json-claude-manager, editor, auto-approver, worktree setup scripts, github-auth, path-fix, and XTerminal
    PTY default shell pty-manager.ts:152 command || env.SHELL || '/bin/zsh' — $SHELL is unset on Windows
    Hooks hooks.ts:22,50-56 /tmp/harness-status plus an inline POSIX script wrapped in bash -c. This is the entire status-detection backbone — no hooks means no processing/waiting/needs-approval states
    Process kill pty-manager.ts:387-393 process.kill(-pid, …) process-group signalling; POSIX-only (relies on setsid())
    Approval bridge approval-bridge.ts:94-104 Unix domain socket; Windows needs a named pipe (\\.\pipe\…)
    Shell activity polling pty-manager.ts:315 Shells out to ps -A -o pid=,ppid=,comm=
    PATH merge path-fix.ts:100-112 Splits/joins on : instead of path.delimiter; whole function is also gated behind process.platform !== 'darwin' early-return
    Packaging package.json build block No win section, no .ico (only .icns/.png), no dist:win script, no windows-latest CI job
    Headless packaging scripts/pack-headless.mjs:45-60,215-227 Platform detection covers only darwin-arm64/linux-x64/linux-arm64; the launcher shim is a #!/bin/sh script; output is .tar.gz
    Dev/release scripts scripts/release.sh, smoke-headless.sh, install-headless.sh, several package.json scripts Bash-only, with hardcoded ~/Library/Application Support paths and tail -F/rm -f/awk/mktemp

    The difficulties worth flagging

    1. Verification is the actual bottleneck, not the code. Nobody on this thread has a Windows machine. A port touches ~25 files across shell spawning, PTY lifecycle, hooks IPC, sockets, and packaging, and none of it is verifiable past "it compiles and packages." Whatever lands first will need a volunteer with a Windows box to validate it — so it should ship explicitly labeled experimental, and CI should at minimum prove it typechecks, tests, and produces an installer on windows-latest.

    2. The hooks rewrite is the load-bearing risk. makeHookCommand emits an inline POSIX shell script, and /tmp/harness-status doubles as the dedupe signature that agents/{claude,codex,cursor}.ts use to recognize Harness-installed hook entries. Changing that path naively means Harness stops recognizing hooks it already installed on existing macOS setups and starts appending duplicates on every re-install. The cleanest fix is probably replacing the inline script with a small shipped JS hook invoked via ELECTRON_RUN_AS_NODE (there's precedent — resources/mcp-bridge.js already ships as extraResources), which would simplify all three platforms rather than forking the script per-OS. But it's a rewrite of the status-detection backbone, so it wants its own PR.

    3. The -ilc assumption is spread thin across the codebase. It isn't one function — it's a convention baked into eight call sites plus the renderer. This wants a src/main/platform/ abstraction (shell resolution, command-wrapping args, PATH delimiter, kill strategy, status dir, socket-vs-pipe) that everything routes through. Upside: that layer is pure logic and can be unit-tested on macOS, so most of the port becomes verifiable without a Windows machine.

    4. Code signing. There's no Windows certificate today. Unsigned NSIS installers trigger SmartScreen warnings for every user. That's a call to make before any Windows artifact goes on a release: ship unsigned-and-documented, or hold Windows releases until there's a cert.

    5. Graceful-degradation candidates. Shell activity polling (ps) and the .claude settings symlink (Windows needs Developer Mode or admin for symlinks) are both non-essential. Better to degrade cleanly on Windows — skip the poller, fall back to a file copy — than to block the port on them.

    6. There's a cheaper interim answer. Harness already has a headless server plus a web client. A Windows user can run harness-server under WSL2 today and drive it from a browser, which covers a meaningful chunk of this issue for the cost of a docs paragraph rather than a port. Worth doing regardless of whether the native port happens.

    Comment left on behalf of @frenchie4111 by Claude via Harness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions