docs: Clean up README formatting and remove deprecated CLI hook commands

Removes crystal ball emoji and bullet formatting inconsistencies from README headers. Eliminates mark-dirty and sync-if-dirty CLI commands and related hook configuration code, simplifying the codebase after transitioning to file watcher-based auto-sync.
This commit is contained in:
Colby McHenry
2026-04-07 16:14:58 -05:00
parent a0a18b1913
commit 32f9cd460e
5 changed files with 121 additions and 661 deletions
+114 -444
View File
@@ -1,10 +1,10 @@
<div align="center">
# 🔮 CodeGraph
# CodeGraph
### Supercharge Claude Code with Semantic Code Intelligence
**94% fewer tool calls 77% faster exploration 100% local**
**94% fewer tool calls · 77% faster exploration · 100% local**
[![npm version](https://img.shields.io/npm/v/@colbymchenry/codegraph.svg)](https://www.npmjs.com/package/@colbymchenry/codegraph)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -28,15 +28,15 @@ npx @colbymchenry/codegraph
---
## 🚀 Why CodeGraph?
## Why CodeGraph?
When you ask Claude Code to work on a complex task, it spawns **Explore agents** that scan your codebase using grep, glob, and file reads. These agents consume tokens with every tool call.
When Claude Code explores a codebase, it spawns **Explore agents** that scan files with grep, glob, and Read — consuming tokens on every tool call.
**CodeGraph gives those agents a semantic knowledge graph** pre-indexed symbol relationships, call graphs, and code structure. Instead of scanning files, agents query the graph instantly.
**CodeGraph gives those agents a pre-indexed knowledge graph** — symbol relationships, call graphs, and code structure. Agents query the graph instantly instead of scanning files.
### 📊 Benchmark Results
### Benchmark Results
We tested exploration queries across 6 real-world codebases in different languages, comparing Claude Code's Explore agent **with** and **without** CodeGraph:
Tested across 6 real-world codebases comparing Claude Code's Explore agent **with** and **without** CodeGraph:
> **Average: 92% fewer tool calls · 71% faster**
@@ -94,100 +94,22 @@ All tests used Claude Opus 4.6 (1M context) with Claude Code v2.1.91. Each test
</details>
### 🔄 How It Works
---
```
┌─────────────────────────────────────────────────────────────────┐
│ Claude Code │
│ │
│ "Implement user authentication" │
│ │ │
│ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Explore Agent │ ──── │ Explore Agent │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
└───────────┼────────────────────────┼─────────────────────────────┘
│ │
▼ ▼
┌───────────────────────────────────────────────────────────────────┐
│ CodeGraph MCP Server │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Search │ │ Callers │ │ Context │ │
│ │ "auth" │ │ "login()" │ │ for task │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ SQLite Graph DB │ │
│ │ • 387 symbols │ │
│ │ • 1,204 edges │ │
│ │ • Instant lookups │ │
│ └───────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
```
## Key Features
**Without CodeGraph:** Explore agents use `grep`, `glob`, and `Read` to scan files → many API calls, high token usage
**With CodeGraph:** Explore agents query the graph via MCP tools → instant results, local processing, fewer tokens
| | |
|---|---|
| **Smart Context Building** | One tool call returns entry points, related symbols, and code snippets — no expensive exploration agents |
| **Full-Text Search** | Find code by name instantly across your entire codebase, powered by FTS5 |
| **Impact Analysis** | Trace callers, callees, and the full impact radius of any symbol before making changes |
| **Always Fresh** | File watcher uses native OS events (FSEvents/inotify/ReadDirectoryChangesW) with debounced auto-sync — the graph stays current as you code, zero config |
| **19+ Languages** | TypeScript, JavaScript, Python, Go, Rust, Java, C#, PHP, Ruby, C, C++, Swift, Kotlin, Dart, Svelte, Liquid, Pascal/Delphi |
| **100% Local** | No data leaves your machine. No API keys. No external services. SQLite database only |
---
## ✨ Key Features
<table>
<tr>
<td width="33%" valign="top">
### 🧠 Smart Context Building
One tool call returns everything Claude needs—entry points, related symbols, and code snippets. No more expensive exploration agents.
</td>
<td width="33%" valign="top">
### 🔍 Full-Text Search
Find code by name across your entire codebase instantly. Search for "auth" and find `authenticate`, `AuthService`, `validateToken` — powered by FTS5.
</td>
<td width="33%" valign="top">
### 📈 Impact Analysis
Know exactly what breaks before you change it. Trace callers, callees, and the full impact radius of any symbol.
</td>
</tr>
<tr>
<td width="33%" valign="top">
### 🌍 19+ Languages
TypeScript, JavaScript, Python, Go, Rust, Java, C#, PHP, Ruby, C, C++, Swift, Kotlin, Dart, Svelte, Liquid, Pascal/Delphi—all with the same API.
</td>
<td width="33%" valign="top">
### 🔒 100% Local
No data leaves your machine. No API keys. No external services. Everything runs on your local SQLite database.
</td>
<td width="33%" valign="top">
### ⚡ Always Fresh
The MCP server watches your files and auto-syncs on save — debounced, filtered to source files only, zero config. Your code intelligence is always up to date.
</td>
</tr>
</table>
---
## 📋 Requirements
- **Node.js >= 18.0.0**
---
## 🎯 Quick Start
## Quick Start
### 1. Run the Installer
@@ -195,11 +117,11 @@ The MCP server watches your files and auto-syncs on save — debounced, filtered
npx @colbymchenry/codegraph
```
The interactive installer will:
- Prompt to install `codegraph` globally (needed for the MCP server to work)
The installer will:
- Prompt to install `codegraph` globally (needed for the MCP server)
- Configure the MCP server in `~/.claude.json`
- 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`
- Optionally initialize your current project
### 2. Restart Claude Code
@@ -208,20 +130,16 @@ Restart Claude Code for the MCP server to load.
### 3. Initialize Projects
For each project you want to use CodeGraph with:
```bash
cd your-project
codegraph init -i
```
That's it! Claude Code will now use CodeGraph tools automatically when a `.codegraph/` directory exists.
That's it! Claude Code will use CodeGraph tools automatically when a `.codegraph/` directory exists.
<details>
<summary><strong>Manual Setup (Alternative)</strong></summary>
If you prefer manual configuration:
**Install globally:**
```bash
npm install -g @colbymchenry/codegraph
@@ -263,7 +181,7 @@ npm install -g @colbymchenry/codegraph
<details>
<summary><strong>Global Instructions Reference</strong></summary>
The installer automatically adds these instructions to `~/.claude/CLAUDE.md`. This is provided here for reference:
The installer automatically adds these instructions to `~/.claude/CLAUDE.md`:
```markdown
## CodeGraph
@@ -303,377 +221,147 @@ At the start of a session, ask the user if they'd like to initialize CodeGraph:
---
## 💻 CLI Usage
## How It Works
```bash
codegraph # Run interactive installer
codegraph install # Run interactive installer (explicit)
codegraph init [path] # Initialize in a project
codegraph uninit [path] # Remove CodeGraph from a project
codegraph index [path] # Full index
codegraph sync [path] # Incremental update
codegraph status [path] # Show statistics
codegraph query <search> # Search symbols
codegraph files [path] # Show project file structure
codegraph context <task> # Build context for AI
codegraph affected [files] # Find test files affected by changes
codegraph serve --mcp # Start MCP server
```
┌─────────────────────────────────────────────────────────────────┐
│ Claude Code │
│ │
│ "Implement user authentication" │
│ │ │
│ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Explore Agent │ ──── │ Explore Agent │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
└───────────┼────────────────────────┼─────────────────────────────┘
│ │
▼ ▼
┌───────────────────────────────────────────────────────────────────┐
│ CodeGraph MCP Server │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Search │ │ Callers │ │ Context │ │
│ │ "auth" │ │ "login()" │ │ for task │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ SQLite Graph DB │ │
│ │ • 387 symbols │ │
│ │ • 1,204 edges │ │
│ │ • Instant lookups │ │
│ └───────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
```
## 📖 CLI Commands
1. **Extraction** — [tree-sitter](https://tree-sitter.github.io/) parses source code into ASTs. Language-specific queries extract nodes (functions, classes, methods) and edges (calls, imports, extends, implements).
### `codegraph` / `codegraph install`
2. **Storage** — Everything goes into a local SQLite database (`.codegraph/codegraph.db`) with FTS5 full-text search.
Run the interactive installer for Claude Code integration. Configures MCP server and permissions automatically.
3. **Resolution** — After extraction, references are resolved: function calls → definitions, imports → source files, class inheritance, and framework-specific patterns.
4. **Auto-Sync** — The MCP server watches your project using native OS file events. Changes are debounced (2-second quiet window), filtered to source files only, and incrementally synced. The graph stays fresh as you code — no configuration needed.
---
## CLI Reference
```bash
codegraph # Run installer (when no args)
codegraph # Run interactive installer
codegraph install # Run installer (explicit)
npx @colbymchenry/codegraph # Run via npx (no global install needed)
codegraph init [path] # Initialize in a project (--index to also index)
codegraph uninit [path] # Remove CodeGraph from a project (--force to skip prompt)
codegraph index [path] # Full index (--force to re-index, --quiet for less output)
codegraph sync [path] # Incremental update
codegraph status [path] # Show statistics
codegraph query <search> # Search symbols (--kind, --limit, --json)
codegraph files [path] # Show file structure (--format, --filter, --max-depth, --json)
codegraph context <task> # Build context for AI (--format, --max-nodes)
codegraph affected [files...] # Find test files affected by changes (see below)
codegraph serve --mcp # Start MCP server
```
The installer will:
1. Prompt to install `codegraph` globally (needed for the MCP server)
2. Ask for installation location (global `~/.claude` or local `./.claude`)
3. Optionally set up auto-allow permissions
4. Configure the MCP server in `claude.json`
5. Add global instructions to `~/.claude/CLAUDE.md` (teaches Claude how to use CodeGraph)
6. For local installs: initialize and index the current project
### `codegraph affected`
### `codegraph init [path]`
Initialize CodeGraph in a project directory. Creates a `.codegraph/` directory with the database and configuration.
```bash
codegraph init # Initialize in current directory
codegraph init /path/to/project # Initialize in specific directory
codegraph init --index # Initialize and immediately index
```
### `codegraph uninit [path]`
Remove CodeGraph from a project. Deletes the `.codegraph/` directory and all indexed data.
```bash
codegraph uninit # Remove from current directory
codegraph uninit --force # Skip confirmation prompt
```
### `codegraph index [path]`
Index all files in the project. Extracts functions, classes, methods, and their relationships.
```bash
codegraph index # Index current directory
codegraph index --force # Force full re-index
codegraph index --quiet # Suppress progress output
```
### `codegraph sync [path]`
Incrementally sync changes since the last index. Only processes added, modified, or removed files.
```bash
codegraph sync # Sync current directory
codegraph sync --quiet # Suppress output
```
### `codegraph status [path]`
Show index status and statistics.
```bash
codegraph status
```
Output includes:
- Files indexed, nodes, edges
- Nodes by kind (functions, classes, methods, etc.)
- Files by language
- Pending changes (if any)
### `codegraph query <search>`
Search for symbols in the codebase by name.
```bash
codegraph query "authenticate" # Search for symbols
codegraph query "User" --kind class # Filter by kind
codegraph query "process" --limit 20 # Limit results
codegraph query "validate" --json # Output as JSON
```
### `codegraph files [path]`
Show the project file structure from the index. Faster than filesystem scanning since it reads from the indexed data.
```bash
codegraph files # Show file tree
codegraph files --format flat # Simple list
codegraph files --format grouped # Group by language
codegraph files --filter src/components # Filter by directory
codegraph files --pattern "*.test.ts" # Filter by glob pattern
codegraph files --max-depth 2 # Limit tree depth
codegraph files --no-metadata # Hide language/symbol counts
codegraph files --json # Output as JSON
```
### `codegraph context <task>`
Build relevant code context for a task. Uses full-text search to find entry points, then expands through the graph to find related code.
```bash
codegraph context "fix checkout bug"
codegraph context "add user authentication" --format json
codegraph context "refactor payment service" --max-nodes 30
```
### `codegraph affected [files...]`
Find test files affected by changed source files. Traces import dependencies transitively through the graph to discover which test files depend on the code you changed. Works with any test framework and any language CodeGraph supports.
Traces import dependencies transitively to find which test files are affected by changed source files.
```bash
codegraph affected src/utils.ts src/api.ts # Pass files as arguments
git diff --name-only | codegraph affected --stdin # Pipe from git diff
codegraph affected --stdin --json < changed.txt # JSON output
codegraph affected src/auth.ts --filter "e2e/*" # Custom test file pattern
codegraph affected src/lib.ts --depth 3 --quiet # Shallow search, paths only
```
**Options:**
| Option | Description | Default |
|--------|-------------|---------|
| `--stdin` | Read file list from stdin (one per line) | `false` |
| `--stdin` | Read file list from stdin | `false` |
| `-d, --depth <n>` | Max dependency traversal depth | `5` |
| `-f, --filter <glob>` | Custom glob to identify test files | auto-detect |
| `-j, --json` | Output as JSON | `false` |
| `-q, --quiet` | Output file paths only, no decoration | `false` |
| `-p, --path <path>` | Project path | auto-detect |
| `-q, --quiet` | Output file paths only | `false` |
**How it works:**
1. For each changed file, BFS-traverses its transitive dependents (files that import from it, directly or indirectly)
2. Filters results to test files using common conventions (`*.spec.*`, `*.test.*`, `e2e/`, `tests/`, `__tests__/`) or a custom `--filter` glob
3. Changed files that are themselves test files are always included
**Example: CI/hook integration**
**CI/hook example:**
```bash
#!/usr/bin/env bash
# In a pre-commit hook or CI step:
AFFECTED=$(git diff --name-only HEAD | codegraph affected --stdin --quiet)
if [ -n "$AFFECTED" ]; then
echo "Running affected tests..."
npx vitest run $AFFECTED
fi
```
### `codegraph serve`
---
Start CodeGraph as an MCP server for AI assistants.
## MCP Tools
```bash
codegraph serve # Show MCP configuration help
codegraph serve --mcp # Start MCP server (stdio)
codegraph serve --mcp --path /project # Specify project path
```
When running as an MCP server, CodeGraph exposes these tools to Claude Code:
## 🔌 MCP Tools Reference
| Tool | Purpose |
|------|---------|
| `codegraph_search` | Find symbols by name across the codebase |
| `codegraph_context` | Build relevant code context for a task |
| `codegraph_callers` | Find what calls a function |
| `codegraph_callees` | Find what a function calls |
| `codegraph_impact` | Analyze what code is affected by changing a symbol |
| `codegraph_node` | Get details about a specific symbol (optionally with source code) |
| `codegraph_files` | Get indexed file structure (faster than filesystem scanning) |
| `codegraph_status` | Check index health and statistics |
When running as an MCP server, CodeGraph exposes these tools to AI assistants. **These tools are designed to be used by Claude's Explore agents** for faster, more efficient codebase exploration.
---
### `codegraph_context`
Build context for a specific task. Good for focused queries.
```
codegraph_context(task: "fix checkout validation bug", maxNodes: 20)
```
### `codegraph_search`
Quick symbol search by name. Returns locations only.
```
codegraph_search(query: "UserService", kind: "class", limit: 10)
```
### `codegraph_callers` / `codegraph_callees`
Find what calls a function, or what a function calls.
```
codegraph_callers(symbol: "validatePayment", limit: 20)
codegraph_callees(symbol: "processOrder", limit: 20)
```
### `codegraph_impact`
Analyze what code would be affected by changing a symbol.
```
codegraph_impact(symbol: "UserService", depth: 2)
```
### `codegraph_node`
Get details about a specific symbol. Use `includeCode: true` only when needed.
```
codegraph_node(symbol: "authenticate", includeCode: true)
```
### `codegraph_files`
Get the project file structure from the index. Faster than filesystem scanning.
```
codegraph_files(path: "src/components", format: "tree", includeMetadata: true)
```
### `codegraph_status`
Check index health and statistics.
### How It Works With Claude Code
Claude's **Explore agents** use these tools instead of grep/glob/Read for faster exploration:
| Without CodeGraph | With CodeGraph | Benefit |
|-------------------|----------------|---------|
| `grep -r "auth"` | `codegraph_search("auth")` | Instant symbol lookup |
| Multiple `Read` calls | `codegraph_context(task)` | Related code in one call |
| Manual file tracing | `codegraph_callers/callees` | Call graph traversal |
| Guessing impact | `codegraph_impact(symbol)` | Know what breaks |
| `Glob`/`find` scanning | `codegraph_files(path)` | Indexed file structure |
This gives Explore agents **~94% fewer tool calls** and **~77% faster exploration** while producing equally thorough answers.
## 📚 Library Usage
CodeGraph can also be used as a library in your Node.js applications:
## Library Usage
```typescript
import CodeGraph from '@colbymchenry/codegraph';
// Initialize a new project
const cg = await CodeGraph.init('/path/to/project');
// Or: const cg = await CodeGraph.open('/path/to/project');
// Or open an existing one
const cg = await CodeGraph.open('/path/to/project');
// Index with progress callback
await cg.indexAll({
onProgress: (progress) => {
console.log(`${progress.phase}: ${progress.current}/${progress.total}`);
}
onProgress: (p) => console.log(`${p.phase}: ${p.current}/${p.total}`)
});
// Search for symbols
const results = cg.searchNodes('UserService');
const callers = cg.getCallers(results[0].node.id);
const context = await cg.buildContext('fix login bug', { maxNodes: 20, includeCode: true, format: 'markdown' });
const impact = cg.getImpactRadius(results[0].node.id, 2);
// Get callers of a function
const node = results[0].node;
const callers = cg.getCallers(node.id);
// Build context for a task
const context = await cg.buildContext('fix login bug', {
maxNodes: 20,
includeCode: true,
format: 'markdown'
});
// Get impact radius
const impact = cg.getImpactRadius(node.id, 2);
// Sync changes manually
const syncResult = await cg.sync();
// Or watch for changes and auto-sync
cg.watch(); // uses native OS file events, debounced
cg.watch(); // auto-sync on file changes
cg.unwatch(); // stop watching
// Clean up
cg.close();
```
## ⚙️ How It Works
---
### 1. Extraction
## Configuration
CodeGraph uses [tree-sitter](https://tree-sitter.github.io/) to parse source code into ASTs. Language-specific queries (`.scm` files) extract:
- **Nodes**: Functions, methods, classes, interfaces, types, variables
- **Edges**: Calls, imports, extends, implements, returns_type
Each node gets a unique ID based on its kind, file path, name, and line number.
### 2. Storage
All data is stored in a local SQLite database (`.codegraph/codegraph.db`):
- **nodes** table: All code entities with metadata
- **edges** table: Relationships between nodes
- **files** table: File tracking for incremental updates
- **unresolved_refs** table: References pending resolution
- **nodes_fts**: FTS5 virtual table for full-text search
- **schema_versions** table: Schema version tracking
- **project_metadata** table: Project-level key-value metadata
### 3. Reference Resolution
After extraction, CodeGraph resolves references:
1. Match function calls to function definitions
2. Resolve imports to their source files
3. Link class inheritance and interface implementations
4. Apply framework-specific patterns (Express routes, etc.)
### 4. File Watching
The MCP server automatically watches your project for file changes using native OS file events (FSEvents on macOS, inotify on Linux, ReadDirectoryChangesW on Windows):
1. File saves are detected instantly via OS-level events — no polling
2. Changes are **debounced** (2-second quiet window) so rapid saves don't thrash
3. Only source files matching your include/exclude patterns trigger a sync
4. Build outputs, node_modules, and `.codegraph/` changes are ignored
5. Incremental sync runs automatically — only changed files are re-parsed
No configuration needed. The graph stays fresh as you code.
### 5. Graph Queries
The graph structure enables powerful queries:
- **Callers/Callees**: Direct call relationships
- **Impact Radius**: BFS traversal to find all potentially affected code
- **Dependencies**: What a symbol depends on
- **Dependents**: What depends on a symbol
### 6. Context Building
When you request context for a task:
1. FTS search finds relevant entry points
2. Graph traversal expands to related code
3. Code snippets are extracted
4. Results are formatted for AI consumption
## ⚙️ Configuration
The `.codegraph/config.json` file controls indexing behavior:
The `.codegraph/config.json` file controls indexing:
```json
{
"version": 1,
"languages": ["typescript", "javascript"],
"exclude": [
"node_modules/**",
"dist/**",
"build/**",
"*.min.js"
],
"exclude": ["node_modules/**", "dist/**", "build/**", "*.min.js"],
"frameworks": [],
"maxFileSize": 1048576,
"extractDocstrings": true,
@@ -681,18 +369,16 @@ The `.codegraph/config.json` file controls indexing behavior:
}
```
### Options
| Option | Description | Default |
|--------|-------------|---------|
| `languages` | Languages to index (auto-detected if empty) | `[]` |
| `exclude` | Glob patterns to ignore | `["node_modules/**", ...]` |
| `frameworks` | Framework hints for better resolution | `[]` |
| `maxFileSize` | Skip files larger than this (bytes) | `1048576` (1MB) |
| `extractDocstrings` | Whether to extract docstrings from code | `true` |
| `trackCallSites` | Whether to track call site locations | `true` |
| `extractDocstrings` | Extract docstrings from code | `true` |
| `trackCallSites` | Track call site locations | `true` |
## 🌐 Supported Languages
## Supported Languages
| Language | Extension | Status |
|----------|-----------|--------|
@@ -714,33 +400,17 @@ The `.codegraph/config.json` file controls indexing behavior:
| Liquid | `.liquid` | Full support |
| Pascal / Delphi | `.pas`, `.dpr`, `.dpk`, `.lpr` | Full support (classes, records, interfaces, enums, DFM/FMX form files) |
## 🔧 Troubleshooting
## Troubleshooting
### "CodeGraph not initialized"
**"CodeGraph not initialized"** — Run `codegraph init` in your project directory first.
Run `codegraph init` in your project directory first.
**Indexing is slow** — Check that `node_modules` and other large directories are excluded. Use `--quiet` to reduce output overhead.
### Indexing is slow
**MCP server not connecting** — Ensure the project is initialized/indexed, verify the path in your MCP config, and check that `codegraph serve --mcp` works from the command line.
- Check if `node_modules` or other large directories are excluded
- Use `--quiet` flag to reduce console output overhead
- Consider increasing `maxFileSize` if you have large files to skip
**Missing symbols** — The MCP server auto-syncs on save (wait a couple seconds). Run `codegraph sync` manually if needed. Check that the file's language is supported and isn't excluded by config patterns.
### MCP server not connecting
1. Ensure the project is initialized and indexed
2. Check the path in your MCP configuration is correct
3. Verify `codegraph serve --mcp` works from the command line
4. Check Claude Code logs for connection errors
### Missing symbols in search
- The MCP server auto-syncs on file changes — wait a couple seconds after saving
- Run `codegraph sync` manually if needed
- Check if the file's language is supported
- Verify the file isn't excluded by config patterns
## 📄 License
## License
MIT
@@ -748,7 +418,7 @@ MIT
<div align="center">
**Made for the Claude Code community** 🤖
**Made for the Claude Code community**
[Report Bug](https://github.com/colbymchenry/codegraph/issues) · [Request Feature](https://github.com/colbymchenry/codegraph/issues)
+1 -89
View File
@@ -16,18 +16,12 @@
* codegraph files [options] Show project file structure
* codegraph context <task> Build context for a task
* codegraph affected [files] Find test files affected by changes
* codegraph mark-dirty [path] Mark project as needing sync (hooks)
* codegraph sync-if-dirty [path] Sync if marked dirty (hooks)
*
* Note: Git hooks have been removed. CodeGraph sync is triggered automatically
* through codegraph's Claude Code hooks integration.
*/
import { Command } from 'commander';
import * as path from 'path';
import * as fs from 'fs';
import { spawn } from 'child_process';
import { getCodeGraphDir, findNearestCodeGraphRoot, isInitialized } from '../directory';
import { getCodeGraphDir, isInitialized } from '../directory';
import { createShimmerProgress } from '../ui/shimmer-progress';
// Lazy-load heavy modules (CodeGraph, runInstaller) to keep CLI startup fast.
@@ -1078,88 +1072,6 @@ program
}
});
/**
* codegraph mark-dirty [path]
*
* Touches .codegraph/.dirty to signal that files have changed.
* Used by Claude Code PostToolUse hooks to batch syncs.
* Runs silently and always exits 0.
*/
program
.command('mark-dirty [path]')
.description('Mark project as needing sync (used by Claude Code hooks)')
.action(async (pathArg: string | undefined) => {
try {
const startPath = path.resolve(pathArg || process.cwd());
const projectRoot = findNearestCodeGraphRoot(startPath);
if (!projectRoot) {
// No .codegraph/ found — exit silently
process.exit(0);
}
const dirtyPath = path.join(getCodeGraphDir(projectRoot), '.dirty');
fs.writeFileSync(dirtyPath, Date.now().toString(), 'utf-8');
} catch {
// Never fail — this runs in the background during edits
}
process.exit(0);
});
/**
* codegraph sync-if-dirty [path]
*
* Checks if .codegraph/.dirty exists and, if so, spawns a detached
* background process to run `codegraph sync`. The hook process exits
* immediately so Claude Code's Stop hook never blocks.
*
* Removes the marker BEFORE spawning so edits during sync
* create a new marker for the next Stop event.
* Runs silently and always exits 0.
*/
program
.command('sync-if-dirty [path]')
.description('Sync if project was marked dirty (used by Claude Code hooks)')
.action(async (pathArg: string | undefined) => {
try {
const startPath = path.resolve(pathArg || process.cwd());
const projectRoot = findNearestCodeGraphRoot(startPath);
if (!projectRoot) {
process.exit(0);
}
const dirtyPath = path.join(getCodeGraphDir(projectRoot!), '.dirty');
// No marker → nothing to do (sub-ms exit)
if (!fs.existsSync(dirtyPath)) {
process.exit(0);
}
// Remove marker FIRST so edits during sync create a new one
try { fs.unlinkSync(dirtyPath); } catch { /* ignore */ }
// If not fully initialized (no DB), exit
if (!isInitialized(projectRoot!)) {
process.exit(0);
}
// 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(
process.argv[0]!,
[process.argv[1]!, 'sync', '--quiet', projectRoot!],
{
detached: true,
stdio: 'ignore',
windowsHide: true,
}
);
child.unref();
} catch {
// Never fail — this runs at the end of Claude responses
}
process.exit(0);
});
/**
* codegraph unlock [path]
*/
+2 -31
View File
@@ -6,7 +6,6 @@
* Removes all CodeGraph configuration from Claude Code:
* - MCP server entry from ~/.claude.json
* - Permissions from ~/.claude/settings.json
* - Hooks from ~/.claude/settings.json
* - CodeGraph section from ~/.claude/CLAUDE.md
*
* This script must never throw — a failed cleanup must not block uninstall.
@@ -51,22 +50,20 @@ function removeMcpConfig(): void {
}
/**
* Remove CodeGraph permissions and hooks from ~/.claude/settings.json
* Remove CodeGraph permissions from ~/.claude/settings.json
*/
function removeSettings(): void {
const filePath = path.join(os.homedir(), '.claude', 'settings.json');
const settings = readJson(filePath);
if (!settings) return;
let changed = false;
// Remove codegraph permissions
if (Array.isArray(settings.permissions?.allow)) {
const before = settings.permissions.allow.length;
settings.permissions.allow = settings.permissions.allow.filter(
(p: string) => !p.startsWith('mcp__codegraph__')
);
if (settings.permissions.allow.length !== before) changed = true;
if (settings.permissions.allow.length === before) return;
// Clean up empty allow array
if (settings.permissions.allow.length === 0) {
@@ -76,33 +73,7 @@ function removeSettings(): void {
if (Object.keys(settings.permissions).length === 0) {
delete settings.permissions;
}
}
// Remove codegraph hooks
if (settings.hooks) {
for (const event of Object.keys(settings.hooks)) {
if (!Array.isArray(settings.hooks[event])) continue;
const before = settings.hooks[event].length;
settings.hooks[event] = settings.hooks[event].filter((entry: any) => {
const json = JSON.stringify(entry);
return !json.includes('codegraph mark-dirty') && !json.includes('codegraph sync-if-dirty');
});
if (settings.hooks[event].length !== before) changed = true;
// Clean up empty event arrays
if (settings.hooks[event].length === 0) {
delete settings.hooks[event];
}
}
// Clean up empty hooks object
if (Object.keys(settings.hooks).length === 0) {
delete settings.hooks;
}
}
if (changed) {
writeJson(filePath, settings);
}
}
-88
View File
@@ -192,94 +192,6 @@ export function hasPermissions(location: InstallLocation): boolean {
return permissions.some((p: string) => p.startsWith('mcp__codegraph__'));
}
// =============================================================================
// Hooks Configuration
// =============================================================================
/**
* Get the hooks configuration for Claude Code auto-sync.
*
* PostToolUse(Edit|Write) → mark-dirty (async, non-blocking)
* Stop → sync-if-dirty (sync, ensures fresh index before next user turn)
*/
function getHooksConfig(): Record<string, any> {
const command = 'codegraph';
return {
PostToolUse: [
{
matcher: 'Edit|Write',
hooks: [
{
type: 'command',
command: `${command} mark-dirty`,
async: true,
},
],
},
],
Stop: [
{
matcher: '.*',
hooks: [
{
type: 'command',
command: `${command} sync-if-dirty`,
},
],
},
],
};
}
/**
* Check if Claude Code hooks already exist for CodeGraph
*/
export function hasHooks(location: InstallLocation): boolean {
const settingsPath = getSettingsJsonPath(location);
const settings = readJsonFile(settingsPath);
const hooks = settings.hooks;
if (!hooks) return false;
// Check if any hook command references codegraph
const json = JSON.stringify(hooks);
return json.includes('codegraph mark-dirty') || json.includes('codegraph sync-if-dirty');
}
/**
* Write Claude Code hooks to settings.json for auto-sync.
* Merges with existing hooks, deduplicating any previous codegraph entries.
*/
export function writeHooks(location: InstallLocation): void {
const settingsPath = getSettingsJsonPath(location);
const settings = readJsonFile(settingsPath);
if (!settings.hooks) {
settings.hooks = {};
}
const newHooks = getHooksConfig();
// For each hook event (PostToolUse, Stop), merge with existing entries
for (const [event, newEntries] of Object.entries(newHooks)) {
if (!Array.isArray(settings.hooks[event])) {
settings.hooks[event] = [];
}
// Remove any existing codegraph entries for this event
settings.hooks[event] = (settings.hooks[event] as any[]).filter((entry: any) => {
// Keep entries that don't reference codegraph
const entryJson = JSON.stringify(entry);
return !entryJson.includes('codegraph mark-dirty') && !entryJson.includes('codegraph sync-if-dirty');
});
// Add new codegraph entries
settings.hooks[event].push(...(newEntries as any[]));
}
writeJsonFile(settingsPath, settings);
}
/**
* Get the path to CLAUDE.md
* - Global: ~/.claude/CLAUDE.md
+4 -9
View File
@@ -8,8 +8,8 @@ import { execSync } from 'child_process';
import * as path from 'path';
import * as fs from 'fs';
import {
writeMcpConfig, writePermissions, writeClaudeMd, writeHooks,
hasMcpConfig, hasPermissions, hasHooks,
writeMcpConfig, writePermissions, writeClaudeMd,
hasMcpConfig, hasPermissions,
} from './config-writer';
import type { InstallLocation } from './config-writer';
@@ -50,7 +50,7 @@ export async function runInstaller(): Promise<void> {
// Step 1: Install globally
const shouldInstallGlobally = await clack.confirm({
message: 'Install codegraph globally? (Required for hooks & MCP server)',
message: 'Install codegraph globally? (Required for MCP server)',
initialValue: true,
});
@@ -70,7 +70,7 @@ export async function runInstaller(): Promise<void> {
clack.log.warn('Try: sudo npm install -g @colbymchenry/codegraph');
}
} else {
clack.log.info('Skipped global install — hooks and MCP server may not work without it');
clack.log.info('Skipped global install — MCP server may not work without it');
}
// Step 2: Installation location
@@ -140,11 +140,6 @@ function writeConfigs(
clack.log.success(`${permAction} permissions in ${locationLabel}/settings.json`);
}
// Hooks
const hookAction = hasHooks(location) ? 'Updated' : 'Added';
writeHooks(location);
clack.log.success(`${hookAction} auto-sync hooks in ${locationLabel}/settings.json`);
// CLAUDE.md
const claudeMdResult = writeClaudeMd(location);
const claudeMdPath = `${locationLabel}/CLAUDE.md`;