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
+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);
}
}