Forráskód Böngészése

fix: Always use npx — stop silent global install failures

Remove the npm install -g attempt from the installer that silently
fails on many systems (permissions, PATH, node version managers).
All configs (MCP server, hooks, next-steps) now always use
npx @colbymchenry/codegraph. Global install offered as an optional tip.

Fixes #37, #38
Colby McHenry 4 hónapja
szülő
commit
675aab386a
4 módosított fájl, 26 hozzáadás és 73 törlés
  1. 6 6
      src/bin/codegraph.ts
  2. 5 3
      src/installer/banner.ts
  3. 6 25
      src/installer/config-writer.ts
  4. 9 39
      src/installer/index.ts

+ 6 - 6
src/bin/codegraph.ts

@@ -1015,17 +1015,17 @@ program
         process.exit(0);
       }
 
-      // Spawn `codegraph sync` as a detached background process
-      // so this hook exits immediately and doesn't block Claude Code
-      const isWindows = process.platform === 'win32';
+      // Spawn sync as a detached background process
+      // so this hook exits immediately and doesn't block Claude Code.
+      // Uses process.argv[0]/[1] (e.g. node /path/to/codegraph.js) so it
+      // works whether invoked via global install, npx, or directly.
       const child = spawn(
-        isWindows ? 'codegraph' : process.argv[0]!,
-        isWindows ? ['sync', '--quiet', projectRoot!] : [process.argv[1]!, 'sync', '--quiet', projectRoot!],
+        process.argv[0]!,
+        [process.argv[1]!, 'sync', '--quiet', projectRoot!],
         {
           detached: true,
           stdio: 'ignore',
           windowsHide: true,
-          shell: isWindows,
         }
       );
       child.unref();

+ 5 - 3
src/installer/banner.ts

@@ -113,16 +113,18 @@ export function warn(message: string): void {
 /**
  * Show the "next steps" section after installation
  */
-export function showNextSteps(location: 'global' | 'local', useNpx?: boolean): void {
+export function showNextSteps(location: 'global' | 'local'): void {
   console.log();
   console.log(chalk.bold('  Done!') + ' Restart Claude Code to use CodeGraph.');
   console.log();
 
   if (location === 'global') {
-    const cmd = useNpx ? 'npx @colbymchenry/codegraph' : 'codegraph';
     console.log(chalk.dim('  Quick start:'));
     console.log(chalk.dim('    cd your-project'));
-    console.log(chalk.cyan(`    ${cmd} init -i`));
+    console.log(chalk.cyan('    npx @colbymchenry/codegraph init -i'));
+    console.log();
+    console.log(chalk.dim('  Tip: For a shorter command, install globally:'));
+    console.log(chalk.dim('    npm install -g @colbymchenry/codegraph'));
   } else {
     console.log(chalk.dim('  CodeGraph is ready to use in this project!'));
   }

+ 6 - 25
src/installer/config-writer.ts

@@ -98,28 +98,9 @@ function writeJsonFile(filePath: string, data: Record<string, any>): void {
 }
 
 /**
- * When true, all configs use `npx @colbymchenry/codegraph` instead of the
- * bare `codegraph` command.  Set by the installer when global install fails.
+ * Get the MCP server configuration — always uses npx for reliability
  */
-let useNpxFallback = false;
-
-export function setUseNpxFallback(value: boolean): void {
-  useNpxFallback = value;
-}
-
-/**
- * Get the MCP server configuration for the given location
- */
-function getMcpServerConfig(location: InstallLocation): Record<string, any> {
-  if (location === 'global' && !useNpxFallback) {
-    // Global: use 'codegraph' command directly (globally installed and in PATH)
-    return {
-      type: 'stdio',
-      command: 'codegraph',
-      args: ['serve', '--mcp'],
-    };
-  }
-  // Local or npx fallback: use npx to run the package
+function getMcpServerConfig(): Record<string, any> {
   return {
     type: 'stdio',
     command: 'npx',
@@ -140,7 +121,7 @@ export function writeMcpConfig(location: InstallLocation): void {
   }
 
   // Add or update codegraph server
-  config.mcpServers.codegraph = getMcpServerConfig(location);
+  config.mcpServers.codegraph = getMcpServerConfig();
 
   writeJsonFile(claudeJsonPath, config);
 }
@@ -221,8 +202,8 @@ export function hasPermissions(location: InstallLocation): boolean {
  * PostToolUse(Edit|Write) → mark-dirty (async, non-blocking)
  * Stop → sync-if-dirty (sync, ensures fresh index before next user turn)
  */
-function getHooksConfig(location: InstallLocation): Record<string, any> {
-  const command = (location === 'global' && !useNpxFallback) ? 'codegraph' : 'npx @colbymchenry/codegraph';
+function getHooksConfig(): Record<string, any> {
+  const command = 'npx @colbymchenry/codegraph';
 
   return {
     PostToolUse: [
@@ -277,7 +258,7 @@ export function writeHooks(location: InstallLocation): void {
     settings.hooks = {};
   }
 
-  const newHooks = getHooksConfig(location);
+  const newHooks = getHooksConfig();
 
   // For each hook event (PostToolUse, Stop), merge with existing entries
   for (const [event, newEntries] of Object.entries(newHooks)) {

+ 9 - 39
src/installer/index.ts

@@ -5,10 +5,9 @@
  * with Claude Code.
  */
 
-import { execSync } from 'child_process';
 import { showBanner, showNextSteps, success, error, info, chalk } from './banner';
 import { promptInstallLocation, promptAutoAllow, InstallLocation } from './prompts';
-import { writeMcpConfig, writePermissions, writeClaudeMd, writeHooks, hasMcpConfig, hasPermissions, hasHooks, setUseNpxFallback } from './config-writer';
+import { writeMcpConfig, writePermissions, writeClaudeMd, writeHooks, hasMcpConfig, hasPermissions, hasHooks } from './config-writer';
 
 /**
  * Format a number with commas
@@ -25,40 +24,11 @@ export async function runInstaller(): Promise<void> {
   showBanner();
 
   try {
-    // Step 1: Check if codegraph is available (skip install if already there)
-    let codegraphAvailable = false;
-    try {
-      const checkCmd = process.platform === 'win32' ? 'where codegraph' : 'command -v codegraph';
-      execSync(checkCmd, { stdio: 'pipe' });
-      codegraphAvailable = true;
-    } catch {
-      // Not installed globally yet
-    }
-
-    if (!codegraphAvailable) {
-      console.log(chalk.dim('  Installing codegraph globally...'));
-      try {
-        execSync('npm install -g @colbymchenry/codegraph', { stdio: 'pipe' });
-        success('Installed codegraph command globally');
-        codegraphAvailable = true;
-      } catch {
-        // May fail if no permissions, but that's ok - npx still works
-        info('Could not install globally — will use npx instead');
-        info('(MCP server and hooks will use npx @colbymchenry/codegraph)');
-      }
-      console.log();
-    }
-
-    // If codegraph binary isn't in PATH, tell config-writer to use npx for everything
-    if (!codegraphAvailable) {
-      setUseNpxFallback(true);
-    }
-
-    // Step 2: Ask for installation location
+    // Step 1: Ask for installation location
     const location = await promptInstallLocation();
     console.log();
 
-    // Step 3: Write MCP configuration
+    // Step 2: Write MCP configuration
     const alreadyHasMcp = hasMcpConfig(location);
     writeMcpConfig(location);
 
@@ -68,7 +38,7 @@ export async function runInstaller(): Promise<void> {
       success(`Added MCP server to ${location === 'global' ? '~/.claude.json' : './.claude.json'}`);
     }
 
-    // Step 4: Ask about auto-allow permissions
+    // Step 3: Ask about auto-allow permissions
     const autoAllow = await promptAutoAllow();
     console.log();
 
@@ -83,7 +53,7 @@ export async function runInstaller(): Promise<void> {
       }
     }
 
-    // Step 5: Write auto-sync hooks
+    // Step 4: Write auto-sync hooks
     const alreadyHasHooks = hasHooks(location);
     writeHooks(location);
 
@@ -93,7 +63,7 @@ export async function runInstaller(): Promise<void> {
       success(`Added auto-sync hooks to ${location === 'global' ? '~/.claude/settings.json' : './.claude/settings.json'}`);
     }
 
-    // Step 6: Write CLAUDE.md instructions
+    // Step 5: Write CLAUDE.md instructions
     const claudeMdResult = writeClaudeMd(location);
     const claudeMdPath = location === 'global' ? '~/.claude/CLAUDE.md' : './.claude/CLAUDE.md';
 
@@ -105,13 +75,13 @@ export async function runInstaller(): Promise<void> {
       success(`Added CodeGraph instructions to ${claudeMdPath}`);
     }
 
-    // Step 7: For local install, initialize the project
+    // Step 6: For local install, initialize the project
     if (location === 'local') {
       await initializeLocalProject();
     }
 
     // Show next steps
-    showNextSteps(location, !codegraphAvailable);
+    showNextSteps(location);
   } catch (err) {
     console.log();
     if (err instanceof Error && err.message.includes('readline was closed')) {
@@ -137,7 +107,7 @@ async function initializeLocalProject(): Promise<void> {
   } catch (err) {
     const msg = err instanceof Error ? err.message : String(err);
     error(`Could not load native modules: ${msg}`);
-    info('Skipping project initialization. You can run "codegraph init -i" later.');
+    info('Skipping project initialization. You can run "npx @colbymchenry/codegraph init -i" later.');
     info('If this persists, try a Node.js LTS version (20 or 22).');
     return;
   }