* fix(upgrade): a Windows upgrade no longer breaks the install while CodeGraph is running (#2185)
On Windows, `codegraph upgrade` renamed only node.exe aside and then
Copy-Item'd the new bundle over current\. Any open agent session runs a
CodeGraph MCP server from current\, which keeps the native kernel loaded, so
the copy failed on lib\kernel\codegraph-kernel.node halfway through, leaving
no node.exe and a mix of versions that no codegraph command could repair.
Re-running install.ps1 failed the same way, because it Remove-Items current\.
Both now share one PowerShell function (a test pins the two copies equal).
The bundle is unpacked next to current\ (same volume), then swapped in file
by file: every file being replaced or dropped is first renamed aside (Windows
allows renaming a running exe or a loaded DLL, just not overwriting or
deleting it), then the staged file is moved in. Any failure or interruption
undoes every step. Renamed-aside files, including the node.exe.old-* left by
earlier upgrades, are deleted on the next successful run once nothing holds
them. The upgrade's exit code now tells whether the install was left
unchanged or needs a reinstall, and the message says which.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(changelog): Windows upgrade with CodeGraph running (#2185)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Running the suite on a machine with Claude Code configured could wire the
CodeGraph prompt hook into the developer's own ~/.claude/settings.json:
every upgrade test whose fake upgrade succeeded ran the real post-upgrade
prompt-hook self-heal, which detected the real global Claude profile and
wrote it. Daemon suites likewise left records in the real
~/.codegraph/daemons. On Windows a HOME-only redirect would not have
helped, since os.homedir() reads USERPROFILE there.
- The prompt-hook writer is now injected through UpgradeDeps
(wirePromptHook); the CLI passes the real defaultWirePromptHook and the
upgrade tests a recorder. New tests pin that a successful upgrade calls
the recorder and that the real writer never touches a configured profile.
- A vitest setupFiles entry gives every engine test file a throwaway home:
HOME/USERPROFILE (plus HOMEDRIVE/HOMEPATH/APPDATA/LOCALAPPDATA on
Windows), XDG_CONFIG_HOME, and GIT_CONFIG_GLOBAL (seeded with a dummy
identity) point into it, and CLAUDE_CONFIG_DIR/CODEX_HOME/COPILOT_HOME/
HERMES_HOME are cleared. Spawned CLI/MCP children inherit it. A sandbox
test asserts os.homedir(), the Claude profile, the daemon registry, a
child process and git's global config all resolve inside it.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
One-time, strictly opt-in prompt at the end of codegraph install and
codegraph upgrade to join the CodeGraph Pro beta waitlist (same list as
the getcodegraph.com homepage form). Nothing is sent unless the user
answers yes AND enters an email; either answer is recorded machine-wide
so no later install or upgrade re-asks, and --yes / non-interactive / CI
runs never see the prompt.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(uninstall): remove the CLI binaries too, not just agent configs (#1071)
`codegraph uninstall` swept agent configurations and stopped — every
installed binary stayed behind, so `codegraph` still ran afterward. Three
disconnected paths each removed a fraction of an installation (uninstall:
configs; install.sh --uninstall: the bundle; npm preuninstall: configs +
npm's own package), and none cleared a shadowed second install — the
uninstall edition of the #1071 PATH shadow.
The uninstall now PLANS every install present on the machine — the bundle
layout(s) (running binary's own, the platform default, a custom
CODEGRAPH_INSTALL_DIR), the npm global package (found by asking
`npm root -g`, so nvm/fnm/volta prefixes resolve correctly), and the
bin-dir launcher link (only when it verifiably points into a detected
install) — confirms with the user, then removes them all. `--yes` skips
the prompt; the new `--keep-cli` flag keeps the old configs-only behavior.
Safety rules: a source checkout is reported, never deleted; a
project-local npm install is left to the project; on unix the default
install dir doubles as the machine state dir, so only the install
artifacts (versions/, current) are removed there — telemetry choice and
daemon records survive. Windows can't delete a running exe but can rename
it (the in-place upgrade's trick): a locked node.exe is renamed aside and
surfaced as a one-file leftover instead of failing the removal, and npm
is routed through cmd.exe (a direct .cmd spawn EINVALs on modern Node).
Planner/executor are split with injected side effects (the upgrade
orchestrator's convention) and unit-tested across the shadow case,
state-dir preservation, custom dirs, foreign-shim protection, and the
locked-exe dance; validated end-to-end on macOS against a fake HOME.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(uninstall): key path math on the target platform, not the host
Real-Windows validation caught it: the planner/executor used the host
path module, so win32 fixtures were meaningless on a POSIX host and
POSIX fixtures failed on the Windows VM. Same convention as
detectInstallMethod now — path.win32/path.posix chosen by the injected
platform.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(upgrade): route npm through cmd.exe on Windows — a direct npm.cmd spawn EINVALs on modern Node
Found while validating the uninstall change on the Windows VM: upgradeNpm
spawned npm.cmd without a shell, which every current Node rejects with
EINVAL (the CVE-2024-27980 hardening) — so `codegraph upgrade` on a
Windows npm install failed before doing anything. Verified live on the VM:
spawnSync('npm.cmd') → EINVAL; cmd.exe /d /s /c npm → works.
npmInvocation moves into the upgrade orchestrator (remove-binary imports
it from there — same direction as its existing imports, no cycle), and the
win32 test now pins the WORKING invocation instead of the broken one.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(upgrade): refresh installer-written agent surfaces after a binary upgrade
codegraph upgrade swapped the binary but never revisited what earlier
installs wrote into CLAUDE.md / AGENTS.md / GEMINI.md and the agent
configs, so sections written by a pre-1.0 installer kept teaching agents
a multi-tool surface (including tools that no longer exist) months of
releases later. The install path already self-heals everything it owns,
but nothing ever called it on upgrade.
- codegraph install --refresh: non-interactive sweep that re-runs
install() for already-configured targets only — never a first
install; permissions and prompt-hook choices are preserved.
- codegraph upgrade spawns it via the freshly-installed binary after a
successful swap (the still-running old process would only rewrite its
own stale template). Gated on PATH resolution and the
CODEGRAPH_NO_INSTALL_REFRESH=1 kill-switch; never fatal to the
upgrade.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(installer): clarify refresh change reporting
---------
Co-authored-by: xuing <np2v9bvbbs@privaterelay.appleid.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Colby McHenry <me@colbymchenry.com>
Two fixes to make `codegraph upgrade` trustworthy in the terminal it ran in:
1. detectInstallMethod checked the bundle layout before the node_modules
path check, but the npm thin-installer's per-platform package IS a
complete bundle inside node_modules — so every npm install misdetected
as a standalone bundle, and upgrade curled install.sh into ~/.codegraph:
a second install that never wins the PATH race against npm's shim,
leaving `codegraph -v` permanently on the old version. Path-based
checks (_npx, node_modules) now win over layout sniffing, so npm
installs upgrade through npm again, in place.
2. After a successful swap, runUpgrade now probes the PATH-resolved
`codegraph --version` and reports the real outcome: a green
confirmation that this terminal already serves the new version, a
loud shadow warning naming the fix (`which -a codegraph`) on
mismatch, or the old soft new-terminal hint only when the probe is
inconclusive. Replaces the unconditional "open a new terminal if the
version looks unchanged" hedge. Skipped for npm-local installs, whose
binary PATH never serves.
Companion to #1239: the misdetection also broke its post-upgrade
`install --refresh` for npm users (the spawn resolved the stale shim).
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
`codegraph upgrade [version]` detects how the CLI was installed — the standalone
install.sh/install.ps1 bundle, npm-global, npx, or a source checkout — and
updates in place: re-running the canonical install.sh on macOS/Linux, an
in-place rename-and-extract swap on Windows (a running node.exe can't be
deleted, only renamed, so the detached-helper approach is avoided), and
npm/npx/source-specific guidance otherwise. Flags: `--check` (report only),
`--force`, and a positional version to pin.
Each full index is now stamped with the engine's EXTRACTION_VERSION in
project_metadata; `codegraph status` (and `--json`) flags an index built by an
older engine and recommends re-indexing, and `upgrade` prints the same reminder.
Gated on EXTRACTION_VERSION so it never nags on extraction-neutral releases.
Validated end-to-end on macOS (real bundle upgrade), Linux (Docker, real
curl|sh) and Windows (Parallels VM, real in-place swap). 32 new unit tests.
Closes#679
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>