|
|
@@ -1,12 +1,17 @@
|
|
|
/**
|
|
|
* Config file writing for the CodeGraph installer
|
|
|
- * Writes to claude.json and settings.json
|
|
|
+ * Writes to claude.json, settings.json, and CLAUDE.md
|
|
|
*/
|
|
|
|
|
|
import * as fs from 'fs';
|
|
|
import * as path from 'path';
|
|
|
import * as os from 'os';
|
|
|
import { InstallLocation } from './prompts';
|
|
|
+import {
|
|
|
+ CLAUDE_MD_TEMPLATE,
|
|
|
+ CODEGRAPH_SECTION_START,
|
|
|
+ CODEGRAPH_SECTION_END,
|
|
|
+} from './claude-md-template';
|
|
|
|
|
|
/**
|
|
|
* Get the path to the Claude config directory
|
|
|
@@ -169,3 +174,101 @@ export function hasPermissions(location: InstallLocation): boolean {
|
|
|
// Check if at least one CodeGraph permission exists
|
|
|
return permissions.some((p: string) => p.startsWith('mcp__codegraph__'));
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Get the path to CLAUDE.md
|
|
|
+ * - Global: ~/.claude/CLAUDE.md
|
|
|
+ * - Local: ./.claude/CLAUDE.md
|
|
|
+ */
|
|
|
+function getClaudeMdPath(location: InstallLocation): string {
|
|
|
+ const configDir = getClaudeConfigDir(location);
|
|
|
+ return path.join(configDir, 'CLAUDE.md');
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Check if CLAUDE.md has CodeGraph section
|
|
|
+ */
|
|
|
+export function hasClaudeMdSection(location: InstallLocation): boolean {
|
|
|
+ const claudeMdPath = getClaudeMdPath(location);
|
|
|
+ try {
|
|
|
+ if (fs.existsSync(claudeMdPath)) {
|
|
|
+ const content = fs.readFileSync(claudeMdPath, 'utf-8');
|
|
|
+ return content.includes(CODEGRAPH_SECTION_START) || content.includes('## CodeGraph');
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ // Ignore errors
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Write or update CLAUDE.md with CodeGraph instructions
|
|
|
+ *
|
|
|
+ * If the file exists and has a CodeGraph section (marked or unmarked),
|
|
|
+ * it will be replaced. Otherwise, the template is appended.
|
|
|
+ */
|
|
|
+export function writeClaudeMd(location: InstallLocation): { created: boolean; updated: boolean } {
|
|
|
+ const claudeMdPath = getClaudeMdPath(location);
|
|
|
+ const configDir = getClaudeConfigDir(location);
|
|
|
+
|
|
|
+ // Ensure directory exists
|
|
|
+ if (!fs.existsSync(configDir)) {
|
|
|
+ fs.mkdirSync(configDir, { recursive: true });
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check if file exists
|
|
|
+ if (!fs.existsSync(claudeMdPath)) {
|
|
|
+ // Create new file with just the CodeGraph section
|
|
|
+ fs.writeFileSync(claudeMdPath, CLAUDE_MD_TEMPLATE + '\n');
|
|
|
+ return { created: true, updated: false };
|
|
|
+ }
|
|
|
+
|
|
|
+ // Read existing content
|
|
|
+ let content = fs.readFileSync(claudeMdPath, 'utf-8');
|
|
|
+
|
|
|
+ // Check for marked section (from previous installer)
|
|
|
+ if (content.includes(CODEGRAPH_SECTION_START)) {
|
|
|
+ // Replace the marked section
|
|
|
+ const startIdx = content.indexOf(CODEGRAPH_SECTION_START);
|
|
|
+ const endIdx = content.indexOf(CODEGRAPH_SECTION_END);
|
|
|
+
|
|
|
+ if (endIdx > startIdx) {
|
|
|
+ // Replace existing marked section
|
|
|
+ const before = content.substring(0, startIdx);
|
|
|
+ const after = content.substring(endIdx + CODEGRAPH_SECTION_END.length);
|
|
|
+ content = before + CLAUDE_MD_TEMPLATE + after;
|
|
|
+ fs.writeFileSync(claudeMdPath, content);
|
|
|
+ return { created: false, updated: true };
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check for unmarked "## CodeGraph" section (from manual setup)
|
|
|
+ const codegraphHeaderRegex = /\n## CodeGraph\n/;
|
|
|
+ const match = content.match(codegraphHeaderRegex);
|
|
|
+
|
|
|
+ if (match && match.index !== undefined) {
|
|
|
+ // Find the end of the CodeGraph section (next ## header or end of file)
|
|
|
+ const sectionStart = match.index;
|
|
|
+ const afterSection = content.substring(sectionStart + 1);
|
|
|
+ const nextHeaderMatch = afterSection.match(/\n## [^#]/);
|
|
|
+
|
|
|
+ let sectionEnd: number;
|
|
|
+ if (nextHeaderMatch && nextHeaderMatch.index !== undefined) {
|
|
|
+ sectionEnd = sectionStart + 1 + nextHeaderMatch.index;
|
|
|
+ } else {
|
|
|
+ sectionEnd = content.length;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Replace the section
|
|
|
+ const before = content.substring(0, sectionStart);
|
|
|
+ const after = content.substring(sectionEnd);
|
|
|
+ content = before + '\n' + CLAUDE_MD_TEMPLATE + after;
|
|
|
+ fs.writeFileSync(claudeMdPath, content);
|
|
|
+ return { created: false, updated: true };
|
|
|
+ }
|
|
|
+
|
|
|
+ // No existing section, append to end
|
|
|
+ content = content.trimEnd() + '\n\n' + CLAUDE_MD_TEMPLATE + '\n';
|
|
|
+ fs.writeFileSync(claudeMdPath, content);
|
|
|
+ return { created: false, updated: false };
|
|
|
+}
|