fix(hooks): hide console windows for detached spawns on Windows#1
Open
nboute wants to merge 9 commits into
Open
fix(hooks): hide console windows for detached spawns on Windows#1nboute wants to merge 9 commits into
nboute wants to merge 9 commits into
Conversation
On Windows, spawning a detached child process (`detached: true`) without `windowsHide: true` opens a new console window each time. The PostToolUse hook fires on every Write/Edit and spawns the reingest + resolver workers detached, so a burst of edits produced a stream of flashing/persistent cmd windows. Add `windowsHide: true` to the detached spawns in: - scripts/lib/memory.js (spawnDetached — reingest/resolve) - scripts/on-post-tool.js (resolver-debounce worker) No behavior change on macOS/Linux; the flag is Windows-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Installs the process-wide CREATE_NO_WINDOW default (_proc.py) in the CLI and MCP server entry points, points the scheduled watcher task at pythonw.exe so logon spawns stay windowless, and hides plugin hook spawns in memory.js. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Any working docker engine is now accepted, resolved once per process: native `docker` on PATH first (Docker Desktop keeps working), then docker-ce inside WSL2 via `wsl -e docker` on Windows. - new code_memory/_docker.py: resolution (native/wsl/daemon-down/none), wslpath translation for compose -f/--project-directory, WSL_UTF8, CODEMEMORY_WSL_DISTRO override, per-process cache - updater.py: docker calls go through the resolved prefix; `docker inspect` switched from Go templates to plain JSON (wsl.exe argument re-parsing hazard); label compose paths passed verbatim daemon-side - install.ps1: offers to provision docker-ce in the default WSL2 distro (systemd, get.docker.com, docker group, optional ONLOGON boot task) and verifies 127.0.0.1:6333 reachability from Windows - install.sh: offers Colima (macOS, brew + compose cli-plugin symlink, brew services autostart) or docker-ce (Linux, get.docker.com); new --colima/--docker-ce flags for non-interactive installs - contributor scripts: same resolution, neutral messages, JSON inspect - README: new "Docker without Docker Desktop" section; .env.example aligned on 127.0.0.1 defaults Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`claude plugin list` prints a U+276F arrow and wsl/docker emit UTF-8; under cp1252 the reader thread raised UnicodeDecodeError, leaving stdout=None and crashing `update --check` on Windows. Decode UTF-8 with errors=replace and export WSL_UTF8=1 so wsl.exe diagnostics stay decodable too. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
WSL2 stops the VM about a minute after the last session detaches, even with systemd services running — dockerd and the cm-* containers go down with it and the runtime sees connection-refused. The logon task now holds a hidden persistent session (`wsl.exe -e sleep infinity`) instead of a one-shot boot, and the installer starts the same keepalive for the current session. Verified: ports 6333/6379 stay reachable past the idle timeout with the keepalive; without it the VM stopped within minutes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… schtasks
`schtasks /SC ONLOGON` requires an elevated shell ("Access is denied"
otherwise), which the one-liner installer cannot assume. A wscript .vbs
in the user Startup folder needs no elevation and launches the hidden
`wsl.exe -e sleep infinity` keepalive with window style 0 (no flash).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fmflurry
pushed a commit
that referenced
this pull request
Jul 8, 2026
Detached hook spawns, the pythonw watcher, the MCP server, and the schtasks daemon each allocated a visible cmd window on Windows. - JS: windowsHide on detached spawns; route spawnDetached through pythonw.exe when resolvable (_windowlessPythonw). - Python: install_windows_no_window_default() wraps subprocess.Popen with CREATE_NO_WINDOW at the cli.py and mcp_server.py entry points. - schtasks: register the LIVE daemon task (install_daemon / _daemon_task_xml) through a windowless pythonw command, not only the legacy per-repo install path. launchd/systemd unchanged (POSIX has no console allocation). Reconstructed from PR #1 (fix/windows-hide-detached-spawns), rebased onto v0.9.0, with the daemon-path gap fixed and tests added.
The keepalive was only reachable through the docker-ce provisioning path, so machines where docker already answers via `wsl -e docker` never got it and lost dockerd to WSL idle-shutdown between sessions. Extract it into Install-WslKeepalive (idempotent, offered once) and call it from both the provisioning step and the plain wsl-resolution path; the contributor script warns when the keepalive is missing. Windows-only files — no behavior change for macOS/Linux installs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Verify section told fresh installs to run `code-memory health`, which the CLI has never shipped; point it at `update --check` and describe the expected output (incl. the WSL variant). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Installs predating the 127.0.0.1 default ship ~/.code-memory/.env with `localhost`, which Windows resolves to ::1 while the containers (and WSL2 localhost forwarding) publish IPv4-only ports — every connection is refused after switching engines. `code-memory update` now rewrites the three exact legacy lines (backup kept as .env.bak); hand-edited values and unix installs are left untouched. README gains a "Switching engines" section: re-ingest as the simple path, optional volume export/import to carry episodes over. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On Windows, every
Write/Editfires thePostToolUsehook, which spawns the reingest and cross-file resolver workers as detached child processes. Node'sspawn(..., { detached: true })opens a new console window for each child unlesswindowsHide: trueis set. A burst of edits therefore produces a stream of flashing/persistentcmdwindows.Fix
Add
windowsHide: trueto the two detached spawns:plugins/claude-code/scripts/lib/memory.js—spawnDetached()(reingest / resolve)plugins/claude-code/scripts/on-post-tool.js— theresolver-debounce.jsworkerwindowsHideis a no-op on macOS/Linux, so there is no behavior change off Windows. Verified locally: after the change, editing files no longer opens console windows, andcode-memory reingeststill runs correctly (symbols + imports written to FalkorDB/Qdrant).🤖 Generated with Claude Code