Skip to content

Windows daemon support: Named Pipe transport and SCM service registration - #1440

Merged
malibio merged 3 commits into
mainfrom
worktree-issue-1439-windows-daemon-support
Jun 22, 2026
Merged

malibio merged 3 commits into
mainfrom
worktree-issue-1439-windows-daemon-support

Conversation

@malibio

@malibio malibio commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Closes #1439

Michael Libio and others added 3 commits June 22, 2026 12:50
…rix (closes #1439)

Phase 1 — daemon Named Pipe transport (packages/daemon/src/main.rs):
- Replace compile_error! guard with #[cfg(windows)] pipe_name() + serve_headless/serve_grpc
  variants using tokio::net::windows::named_pipe::ServerOptions + async_stream acceptor loop
- Add windows-service SCM entry point: define_windows_service!, run_as_service, SCM dispatch
  in main() so binary works as both a console process and an SCM-managed service
- Fix HOME env usage → dirs::home_dir() in resolve_model_path and capture_config_path

Phase 2 — Tauri gRPC client Named Pipe connection (grpc_client.rs):
- Add #[cfg(windows)] connect(), connect_lazy(), from_channel() variants
- Add pipe_channel() / pipe_channel_lazy() using ClientOptions + hyper-util TokioIo
- Add resolve_pipe_name() and Windows resolve_socket_path() delegating to it

Phase 3 — Windows daemon lifecycle (daemon_setup.rs):
- Split check_daemon_socket into #[cfg(unix)] (UnixStream) and #[cfg(windows)] (OpenOptions)
- Split kill_running_daemon into #[cfg(unix)] (SIGTERM/lsof) and #[cfg(windows)] (taskkill)
- Split set_executable into #[cfg(unix)] (chmod 755) and #[cfg(windows)] (no-op)
- Add Windows branch in ensure_daemon_running: spawn_daemon_windows + register_autorun_windows
  (HKCU Run key — no elevation required)

Phase 4 — CI matrix restored (.github/workflows/release.yml):
- Add windows-x86 to build-tauri and build-headless matrices
- Windows protobuf via choco, sidecar copy with .exe extension

Co-Authored-By: Claude <noreply@anthropic.com>
Multiline body with bare colons was parsed as YAML keys by both Python
and GitHub's validator. Collapsed to a single-line body string to avoid
the quoting hazard.

Co-Authored-By: Claude <noreply@anthropic.com>
1. Remove dead SCM service code (main.rs, daemon/Cargo.toml)
   The Tauri app uses direct spawn + HKCU autorun (no elevation needed),
   making the windows-service SCM entry point unreachable. Removed
   run_as_service, define_windows_service!, and the windows-service dep
   rather than leave misleading dead code.

2. Fix Named Pipe acceptor shutdown race (main.rs)
   server.connect().await blocked indefinitely after tonic stopped polling
   the stream. Thread a CancellationToken into both serve_headless and
   serve_grpc Windows acceptor loops so connect races against shutdown.

3. Fix socket_path in ensure_daemon_running on Windows (daemon_setup.rs)
   socket_path was home.join(".nodespace/daemon.sock") — a Unix path.
   wait_for_daemon probed that path via the Windows check_daemon_socket
   which opens it as a file, always returning NotRunning even when the
   daemon was healthy. Now uses resolve_pipe_name() on Windows.

4. Remove duplicated from_channel cfg gates (grpc_client.rs)
   Channel is platform-agnostic; both #[cfg(unix)] and #[cfg(windows)]
   variants were identical. Single unconditional implementation.

5. Treat ERROR_PIPE_BUSY (231) as Starting in check_daemon_socket Windows
   variant — daemon is healthy but all pipe instances are busy; returning
   NotRunning would cause a spurious second spawn.

Co-Authored-By: Claude <noreply@anthropic.com>
@malibio
malibio merged commit b59c40f into main Jun 22, 2026
@malibio
malibio deleted the worktree-issue-1439-windows-daemon-support branch June 22, 2026 11:02
mstomar125 added a commit that referenced this pull request Sep 14, 2026
* Add Named Pipe transport to nodespace CLI for Windows support

The nodespace CLI's run()/connect*() helpers were gated #[cfg(unix)]
around a Unix Domain Socket-only transport, with a Windows run()
falling straight to anyhow::bail!. Add a Windows Named Pipe client
transport that dials the same \\.\pipe\nodespace-daemon pipe the
daemon already serves (packages/daemon/src/main.rs, added in #1440),
mirroring the desktop app's own client-side pipe transport
(packages/desktop-app/src-tauri/src/services/grpc_client.rs).

- dial_channel() is now platform-gated internally (UnixStream on
  Unix, tokio::net::windows::named_pipe::ClientOptions on Windows)
  behind one shared signature, so connect()/connect_import()/
  connect_session()/connect_local_agent()/connect_database() and the
  run() dispatch stay a single, non-duplicated cross-platform
  implementation rather than parallel per-platform copies.
- resolve_pipe_name() resolves --socket/NODESPACED_SOCKET/default on
  Windows, mirroring resolve_socket_path()'s Unix-only override chain.
- Regenerated packages/skill/references/cli.md for the updated
  --socket flag help text.

Closes #1452.

* Correct stale Unix-only comment after Windows Named Pipe support landed

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.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.

Windows daemon support: Named Pipe transport and SCM service registration

1 participant