feat(installer): stop auto-indexing on install + ship opt-in front-load prompt hook
`codegraph install` no longer indexes the current directory — it wires up agents only, and building a project's graph is always the explicit `codegraph init` / `index`. Removes the global-vs-local inconsistency (a local install silently indexed, a global one didn't) and the docs/behavior mismatch (#826). README updated to match; the stale `init --index` note (indexing is default now) fixed. Adds an opt-in Claude Code front-load hook: a `UserPromptSubmit` hook that runs the new hidden `codegraph prompt-hook`, which injects codegraph_explore context for structural ("how / where / trace / impact") prompts so the agent answers from the graph instead of grepping to rebuild it. Prompted at install (default-yes; Claude-only — the only agent with prompt hooks), removed on uninstall, and `codegraph upgrade` self-heals it onto an already-configured global Claude install. Strictly additive + degradable: non-structural prompts, un-indexed projects, and any failure are silent no-ops. Disable without uninstalling via CODEGRAPH_NO_PROMPT_HOOK=1. 7 new installer-targets contract tests (write / idempotent / opt-out round-trip / sibling-preserved / uninstall / legacy-independent). Full suite green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
212dfc4b6a
commit
bd4814d8c1
+41
-4
@@ -340,16 +340,21 @@ export async function runUpgrade(opts: UpgradeOptions, deps: UpgradeDeps): Promi
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Dispatch by install method.
|
||||
// Dispatch by install method. bundle/npm perform a real binary update, so
|
||||
// after they succeed we self-heal the front-load hook (below); npx/source/
|
||||
// unknown don't update anything here, so they return directly.
|
||||
let code: number;
|
||||
switch (method.kind) {
|
||||
case 'bundle':
|
||||
return method.os === 'windows'
|
||||
code = await (method.os === 'windows'
|
||||
? upgradeWindowsBundle(method, latest, deps)
|
||||
: upgradeUnixBundle(method, opts.version ? latest : undefined, deps);
|
||||
: upgradeUnixBundle(method, opts.version ? latest : undefined, deps));
|
||||
break;
|
||||
case 'npm':
|
||||
// npm version specs have no leading "v" (`@0.9.8`, not `@v0.9.8` — the
|
||||
// latter resolves as a nonexistent dist-tag).
|
||||
return upgradeNpm(method, opts.version ? stripV(latest) : 'latest', deps);
|
||||
code = await upgradeNpm(method, opts.version ? stripV(latest) : 'latest', deps);
|
||||
break;
|
||||
case 'npx':
|
||||
deps.log(c.green('npx always runs the latest version on demand — nothing to upgrade.'));
|
||||
deps.log(c.dim(`Force a fresh fetch with: npx ${NPM_PACKAGE}@latest`));
|
||||
@@ -363,6 +368,38 @@ export async function runUpgrade(opts: UpgradeOptions, deps: UpgradeDeps): Promi
|
||||
deps.log(c.dim(`Reinstall manually — see https://github.com/${REPO}#install`));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// After a successful update, ensure the front-load prompt hook is wired for an
|
||||
// already-configured global Claude install — so existing users pick it up on
|
||||
// upgrade, not only on a fresh `install` (the hook config is version-agnostic,
|
||||
// so the still-running old binary can write it safely). Idempotent + gated on
|
||||
// an existing Claude config, and skipped entirely by the kill-switch. Never
|
||||
// fatal to the upgrade.
|
||||
if (code === 0) {
|
||||
try {
|
||||
await selfHealPromptHook(deps);
|
||||
} catch {
|
||||
/* a hook-wiring hiccup must not fail the upgrade */
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wire the Claude `UserPromptSubmit` front-load hook on upgrade for an
|
||||
* already-configured global Claude install. No-op when Claude isn't configured,
|
||||
* when the hook is already present, or when the kill-switch is set.
|
||||
*/
|
||||
async function selfHealPromptHook(deps: UpgradeDeps): Promise<void> {
|
||||
if (process.env.CODEGRAPH_NO_PROMPT_HOOK === '1' || process.env.CODEGRAPH_PROMPT_HOOK === '0') return;
|
||||
const { claudeTarget, writePromptHookEntry } = await import('../installer/targets/claude');
|
||||
if (!claudeTarget.detect('global').alreadyConfigured) return;
|
||||
const res = writePromptHookEntry('global');
|
||||
if (res.action === 'created' || res.action === 'updated') {
|
||||
deps.log(
|
||||
c.dim('Enabled the CodeGraph front-load hook for Claude Code (structural prompts). Disable any time: CODEGRAPH_NO_PROMPT_HOOK=1'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function upgradeUnixBundle(
|
||||
|
||||
Reference in New Issue
Block a user