Merge branch 'main' into fix/telemetry-opt-out
This commit is contained in:
@@ -162,6 +162,7 @@ npx @colbymchenry/codegraph
|
|||||||
```
|
```
|
||||||
|
|
||||||
The interactive installer will:
|
The interactive installer will:
|
||||||
|
- Prompt to install `codegraph` globally (needed for hooks & MCP server to work)
|
||||||
- Configure the MCP server in `~/.claude.json`
|
- Configure the MCP server in `~/.claude.json`
|
||||||
- Set up auto-allow permissions for CodeGraph tools
|
- Set up auto-allow permissions for CodeGraph tools
|
||||||
- Add global instructions to `~/.claude/CLAUDE.md` (teaches Claude how to use CodeGraph)
|
- Add global instructions to `~/.claude/CLAUDE.md` (teaches Claude how to use CodeGraph)
|
||||||
@@ -306,12 +307,13 @@ npx @colbymchenry/codegraph # Run via npx (no global install needed)
|
|||||||
```
|
```
|
||||||
|
|
||||||
The installer will:
|
The installer will:
|
||||||
1. Ask for installation location (global `~/.claude` or local `./.claude`)
|
1. Prompt to install `codegraph` globally (needed for hooks & MCP server)
|
||||||
2. Configure the MCP server in `claude.json`
|
2. Ask for installation location (global `~/.claude` or local `./.claude`)
|
||||||
3. Optionally set up auto-allow permissions
|
3. Configure the MCP server in `claude.json`
|
||||||
4. Add global instructions to `~/.claude/CLAUDE.md` (teaches Claude how to use CodeGraph)
|
4. Optionally set up auto-allow permissions
|
||||||
5. Install Claude Code hooks for automatic index syncing
|
5. Add global instructions to `~/.claude/CLAUDE.md` (teaches Claude how to use CodeGraph)
|
||||||
6. For local installs: initialize and index the current project
|
6. Install Claude Code hooks for automatic index syncing
|
||||||
|
7. For local installs: initialize and index the current project
|
||||||
|
|
||||||
### `codegraph init [path]`
|
### `codegraph init [path]`
|
||||||
|
|
||||||
|
|||||||
+13
-4
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
import { showBanner, showNextSteps, success, error, info, chalk } from './banner';
|
import { showBanner, showNextSteps, success, error, info, chalk } from './banner';
|
||||||
import { promptInstallLocation, promptAutoAllow, InstallLocation } from './prompts';
|
import { promptInstallLocation, promptAutoAllow, promptConfirm, InstallLocation } from './prompts';
|
||||||
import { writeMcpConfig, writePermissions, writeClaudeMd, writeHooks, hasMcpConfig, hasPermissions, hasHooks } from './config-writer';
|
import { writeMcpConfig, writePermissions, writeClaudeMd, writeHooks, hasMcpConfig, hasPermissions, hasHooks } from './config-writer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,9 +25,14 @@ export async function runInstaller(): Promise<void> {
|
|||||||
showBanner();
|
showBanner();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Step 1: Install codegraph globally.
|
// Step 1: Install codegraph globally (with user consent).
|
||||||
// Always run npm install -g — we can't use `command -v codegraph` to check
|
// The global install is needed because Claude Code hooks and the MCP server
|
||||||
// because npx puts a temporary binary in PATH that vanishes when npx exits.
|
// invoke `codegraph` by name — the temporary npx binary vanishes when npx exits.
|
||||||
|
console.log(chalk.bold(' Install codegraph globally?') + chalk.dim(' (Required for hooks & MCP server)'));
|
||||||
|
console.log();
|
||||||
|
const shouldInstallGlobally = await promptConfirm('Install globally via npm', true);
|
||||||
|
|
||||||
|
if (shouldInstallGlobally) {
|
||||||
console.log(chalk.dim(' Installing codegraph globally...'));
|
console.log(chalk.dim(' Installing codegraph globally...'));
|
||||||
try {
|
try {
|
||||||
execSync('npm install -g @colbymchenry/codegraph', { stdio: 'pipe' });
|
execSync('npm install -g @colbymchenry/codegraph', { stdio: 'pipe' });
|
||||||
@@ -36,6 +41,10 @@ export async function runInstaller(): Promise<void> {
|
|||||||
info('Could not install globally (permission denied)');
|
info('Could not install globally (permission denied)');
|
||||||
info('Try: sudo npm install -g @colbymchenry/codegraph');
|
info('Try: sudo npm install -g @colbymchenry/codegraph');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
info('Skipped global install — hooks and MCP server may not work without it');
|
||||||
|
info('You can install later: npm install -g @colbymchenry/codegraph');
|
||||||
|
}
|
||||||
console.log();
|
console.log();
|
||||||
|
|
||||||
// Step 2: Ask for installation location
|
// Step 2: Ask for installation location
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ import * as path from 'path';
|
|||||||
import { Node } from '../types';
|
import { Node } from '../types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common stop words to filter from search queries
|
* Common stop words to filter from search queries.
|
||||||
|
* Includes generic English + code-specific noise words.
|
||||||
*/
|
*/
|
||||||
export const STOP_WORDS = new Set([
|
export const STOP_WORDS = new Set([
|
||||||
|
// English
|
||||||
'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',
|
'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',
|
||||||
'of', 'with', 'by', 'from', 'is', 'it', 'that', 'this', 'are', 'was',
|
'of', 'with', 'by', 'from', 'is', 'it', 'that', 'this', 'are', 'was',
|
||||||
'be', 'has', 'had', 'have', 'do', 'does', 'did', 'will', 'would', 'could',
|
'be', 'has', 'had', 'have', 'do', 'does', 'did', 'will', 'would', 'could',
|
||||||
@@ -18,17 +20,41 @@ export const STOP_WORDS = new Set([
|
|||||||
'every', 'how', 'what', 'where', 'when', 'who', 'which', 'why',
|
'every', 'how', 'what', 'where', 'when', 'who', 'which', 'why',
|
||||||
'i', 'me', 'my', 'we', 'our', 'you', 'your', 'he', 'she', 'they',
|
'i', 'me', 'my', 'we', 'our', 'you', 'your', 'he', 'she', 'they',
|
||||||
'find', 'show', 'get', 'list', 'give', 'tell',
|
'find', 'show', 'get', 'list', 'give', 'tell',
|
||||||
|
'been', 'done', 'made', 'used', 'using', 'work', 'works', 'found',
|
||||||
|
'also', 'into', 'then', 'than', 'just', 'more', 'some', 'such',
|
||||||
|
'over', 'only', 'new', 'out', 'its', 'so', 'up', 'as', 'if',
|
||||||
|
// Code-specific noise
|
||||||
|
'code', 'file', 'files', 'function', 'method', 'class', 'type',
|
||||||
|
'build', 'run', 'test', 'fix', 'bug', 'call', 'called', 'set', 'add',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract meaningful search terms from a natural language query
|
* Extract meaningful search terms from a natural language query.
|
||||||
|
* Splits camelCase, PascalCase, snake_case, SCREAMING_SNAKE, and dot.notation
|
||||||
|
* into individual tokens before filtering.
|
||||||
*/
|
*/
|
||||||
export function extractSearchTerms(query: string): string[] {
|
export function extractSearchTerms(query: string): string[] {
|
||||||
return query
|
const tokens = new Set<string>();
|
||||||
.toLowerCase()
|
|
||||||
.replace(/[^\w\s-]/g, ' ')
|
// Split camelCase / PascalCase: "getUserName" → "get User Name"
|
||||||
.split(/\s+/)
|
const camelSplit = query
|
||||||
.filter(term => term.length > 1 && !STOP_WORDS.has(term));
|
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
||||||
|
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2');
|
||||||
|
|
||||||
|
// Replace underscores and dots with spaces (snake_case, dot.notation)
|
||||||
|
const normalised = camelSplit.replace(/[_.]+/g, ' ');
|
||||||
|
|
||||||
|
// Split on any non-alphanumeric character
|
||||||
|
const words = normalised.split(/[^a-zA-Z0-9]+/).filter(Boolean);
|
||||||
|
|
||||||
|
for (const word of words) {
|
||||||
|
const lower = word.toLowerCase();
|
||||||
|
if (lower.length < 3) continue;
|
||||||
|
if (STOP_WORDS.has(lower)) continue;
|
||||||
|
tokens.add(lower);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...tokens];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user