import * as fs from 'node:fs'; import * as path from 'node:path'; import { log } from './logger.js'; import { getAssetsPath } from './assets-path.js'; export function generateTemplates(targetDir, type) { const absoluteDir = path.resolve(targetDir); if (!fs.existsSync(absoluteDir)) { return { success: false, filesCreated: [], error: `Target directory does not exist: ${targetDir}` }; } // Create .understand-anything directory structure const uaDir = path.join(absoluteDir, '.understand-anything'); const intermediateDir = path.join(uaDir, 'intermediate'); const tmpDir = path.join(uaDir, 'tmp'); fs.mkdirSync(intermediateDir, { recursive: true }); fs.mkdirSync(tmpDir, { recursive: true }); // Generate .understandignore if it doesn't exist const ignorePath = path.join(uaDir, '.understandignore'); if (!fs.existsSync(ignorePath)) { const ignoreContent = generateUnderstandIgnore(absoluteDir); fs.writeFileSync(ignorePath, ignoreContent, 'utf-8'); } const scriptsDir = getScriptsDir(type); const templates = getTemplatesForType(type); const allTemplates = templates; const filesCreated = []; // Files that should always be overwritten (steering files with knowledge graph docs) const alwaysOverwrite = new Set(['AGENTS.md', 'openspec/AGENTS.md', '.agent/AGENT.md', '.claude-plugin/plugin.json']); for (const template of allTemplates) { const filePath = path.join(absoluteDir, template.relativePath); const dir = path.dirname(filePath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } if (fs.existsSync(filePath) && !alwaysOverwrite.has(template.relativePath)) { log('warn', `Skipping existing file: ${template.relativePath}`); continue; } // Replace {{SCRIPTS_DIR}} placeholder with actual path const content = template.content.replace(/\{\{SCRIPTS_DIR\}\}/g, scriptsDir); fs.writeFileSync(filePath, content, 'utf-8'); filesCreated.push(template.relativePath); } // Copy bundled asset files (Python scripts, frameworks, languages docs) const assetsCopied = copyAssetsToTarget(absoluteDir, type, scriptsDir); filesCreated.push(...assetsCopied); return { success: true, filesCreated }; } /** * Copy bundled asset files from dist/assets/ to the target project. * Maps asset paths to the correct location based on platform type. */ function copyAssetsToTarget(targetDir, type, scriptsDir) { let assetsPath; try { assetsPath = getAssetsPath(); } catch { log('warn', 'Assets directory not found — skipping bundled scripts/frameworks/languages copy'); return []; } const copied = []; const skillsBaseDir = getSkillsBaseDir(type); // Define asset mappings: source (relative to assets/) → target (relative to targetDir) const assetMappings = [ // agents definitions (referenced by skills) { srcDir: 'agents', destDir: `${skillsBaseDir}/understand/agents` }, // understand skill: scripts + frameworks + languages { srcDir: 'skills/understand', destDir: `${skillsBaseDir}/understand`, pattern: /\.(py|mjs)$/ }, { srcDir: 'skills/understand/frameworks', destDir: `${skillsBaseDir}/understand/frameworks` }, { srcDir: 'skills/understand/languages', destDir: `${skillsBaseDir}/understand/languages` }, // understand-domain script { srcDir: 'skills/understand-domain', destDir: `${skillsBaseDir}/understand-domain`, pattern: /\.py$/ }, // understand-knowledge scripts { srcDir: 'skills/understand-knowledge', destDir: `${skillsBaseDir}/understand-knowledge`, pattern: /\.py$/ }, // understand-baseline script { srcDir: 'skills/understand-baseline', destDir: `${skillsBaseDir}/understand-baseline`, pattern: /\.py$/ }, // understand-report script { srcDir: 'skills/understand-report', destDir: `${skillsBaseDir}/understand-report`, pattern: /\.py$/ }, // understand-mermaid script { srcDir: 'skills/understand-mermaid', destDir: `${skillsBaseDir}/understand-mermaid`, pattern: /\.py$/ }, // understand-export scripts + css { srcDir: 'skills/understand-export', destDir: `${skillsBaseDir}/understand-export`, pattern: /\.(py|css)$/ }, // hooks (auto-update prompt) { srcDir: 'hooks', destDir: `${skillsBaseDir}/understand/hooks`, pattern: /\.md$/ }, ]; for (const mapping of assetMappings) { const srcFullDir = path.join(assetsPath, mapping.srcDir); if (!fs.existsSync(srcFullDir)) continue; const entries = fs.readdirSync(srcFullDir, { withFileTypes: true }); for (const entry of entries) { if (!entry.isFile()) continue; if (mapping.pattern && !mapping.pattern.test(entry.name)) continue; // Skip SKILL.md — we generate those from templates if (entry.name === 'SKILL.md') continue; const srcFile = path.join(srcFullDir, entry.name); const relativeDest = `${mapping.destDir}/${entry.name}`; const destFile = path.join(targetDir, relativeDest); const destDir = path.dirname(destFile); if (!fs.existsSync(destDir)) { fs.mkdirSync(destDir, { recursive: true }); } fs.copyFileSync(srcFile, destFile); copied.push(relativeDest); } } return copied; } /** Get the skills base directory for each type (where skill subdirs go) */ function getSkillsBaseDir(type) { switch (type) { case 'kiro': return '.kiro/skills'; case 'codex': return '.codex/skills'; case 'opencode': return '.opencode/skills'; case 'claude-code': return '.claude-plugin/skills'; case 'openclaw': return '.agent/skills'; case 'cursor': return '.cursor/skills'; case 'openspec': return '.github/prompts'; } } /** Get the scripts directory path relative to project root for each type */ function getScriptsDir(type) { // Scripts now live inside skills directories const base = getSkillsBaseDir(type); return base; } /** * Generate .understandignore content based on the project's .gitignore and detected directories. * This runs deterministically without AI — saves tokens. */ function generateUnderstandIgnore(projectRoot) { const defaults = [ 'node_modules/', 'node_modules', '.git/', 'vendor/', 'venv/', '.venv/', '__pycache__/', 'dist/', 'dist', 'build/', 'build', 'out/', 'coverage/', 'coverage', '.next/', '.cache/', '.turbo/', 'target/', 'obj/', '*.lock', 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', '*.png', '*.jpg', '*.jpeg', '*.gif', '*.svg', '*.ico', '*.woff', '*.woff2', '*.ttf', '*.eot', '*.mp3', '*.mp4', '*.pdf', '*.zip', '*.tar', '*.gz', '*.min.js', '*.min.css', '*.map', '*.generated.*', '.idea/', '.vscode/', 'LICENSE', '.gitignore', '.editorconfig', '.prettierrc', '.eslintrc*', '*.log', ]; const norm = (p) => p.replace(/\/+$/, ''); const defaultSet = new Set(defaults.map(norm)); const header = [ '# .understandignore — patterns for files/dirs to exclude from analysis', '# Syntax: same as .gitignore (globs, # comments, ! negation, trailing / for dirs)', '# Lines below are suggestions — uncomment to activate.', '# Use ! prefix to force-include something excluded by defaults.', '#', '# Built-in defaults (always excluded unless negated):', '# node_modules/, .git/, dist/, build/, obj/, *.lock, *.min.js, etc.', '#', '', ].join('\n'); let body = ''; // Read .gitignore and add non-default patterns as suggestions const gitignorePath = path.join(projectRoot, '.gitignore'); if (fs.existsSync(gitignorePath)) { const gi = fs.readFileSync(gitignorePath, 'utf-8') .split('\n') .map(l => l.trim()) .filter(l => l && !l.startsWith('#')) .filter(p => !defaultSet.has(norm(p))); if (gi.length) { body += '# --- From .gitignore (uncomment to exclude) ---\n\n'; body += gi.map(p => '# ' + p).join('\n') + '\n\n'; } } // Detect common directories that might be excluded const dirs = ['__tests__', 'test', 'tests', 'fixtures', 'testdata', 'docs', 'examples', 'scripts', 'migrations', '.storybook']; const found = dirs.filter(d => fs.existsSync(path.join(projectRoot, d))); if (found.length) { body += '# --- Detected directories (uncomment to exclude) ---\n\n'; body += found.map(d => '# ' + d + '/').join('\n') + '\n\n'; } body += '# --- Test file patterns (uncomment to exclude) ---\n\n# *.test.*\n# *.spec.*\n# *.snap\n'; return header + body; } function getTemplatesForType(type) { switch (type) { case 'kiro': return getKiroTemplates(); case 'codex': return getCodexTemplates(); case 'opencode': return getOpenCodeTemplates(); case 'claude-code': return getClaudeCodeTemplates(); case 'openclaw': return getOpenClawTemplates(); case 'cursor': return getCursorTemplates(); case 'openspec': return getOpenSpecTemplates(); } } /** Scripts shared across all platform types — copied from dist/assets/ */ // Shared knowledge graph documentation content const GRAPH_DOCS = `## Knowledge Graph The knowledge graph is at \`.understand-anything/knowledge-graph.json\`. ### Structure - \`project\` — {name, description, languages, frameworks, analyzedAt, gitCommitHash} - \`nodes[]\` — {id, type, name, filePath, summary, tags[], complexity} - \`edges[]\` — {source, target, type, direction, weight} - \`layers[]\` — {id, name, description, nodeIds[]} - \`tour[]\` — {order, title, description, nodeIds[]} ### Node Types file, function, class, config, document, service, pipeline, table, schema, resource, endpoint ### Edge Types imports, contains, calls, depends_on, configures, deploys, triggers, documents, migrates, defines_schema ### Node ID Format - \`file:src/path.ts\` — source files - \`function:src/path.ts:funcName\` — functions - \`class:src/path.ts:ClassName\` — classes - \`config:tsconfig.json\` — configuration files - \`document:README.md\` — documentation files ### How to Use 1. Search the graph JSON for relevant nodes before reading source files 2. Follow edges to trace dependencies and understand relationships 3. Use layers to understand architectural boundaries 4. Reference tour steps for onboarding context `; const SKILL_UNDERSTAND_CHAT = `# understand-chat Answer questions about this codebase using the knowledge graph. ## Instructions 1. Check that \`.understand-anything/knowledge-graph.json\` exists 2. Search the graph for nodes matching the query keywords 3. Find connected edges (1-hop neighborhood) for context 4. Identify which architectural layers are relevant 5. Answer using specific file paths and relationships from the graph `; const SKILL_UNDERSTAND_DIFF = `# understand-diff Analyze code changes against the knowledge graph to identify affected components and risks. ## Instructions 1. Get changed files from git diff 2. Find matching nodes in the knowledge graph 3. Follow edges to find affected components (upstream callers, downstream dependencies) 4. Identify affected architectural layers 5. Provide risk assessment based on complexity and blast radius `; const SKILL_UNDERSTAND_DOMAIN = `# understand-domain Extract business domain knowledge from the codebase and identify domains, business flows, and process steps. ## Instructions 1. Check if \`.understand-anything/knowledge-graph.json\` exists 2. If it exists, derive domain knowledge from the graph (nodes, edges, layers) 3. If not, perform a lightweight scan: file tree + entry point detection 4. Identify business domains, flows (user journeys, data pipelines), and process steps 5. Map domains to architectural layers and code components 6. Output: list of domains, their flows, and which files/functions implement each step `; const SKILL_UNDERSTAND_EXPLAIN = `# understand-explain Provide a thorough, in-depth explanation of a specific file, function, or module. ## Instructions 1. Check that \`.understand-anything/knowledge-graph.json\` exists 2. Find the target node by searching for the file path or function name in the graph 3. Find all connected edges (incoming and outgoing) to build the component's neighborhood 4. Identify which architectural layer the component belongs to 5. Read the actual source file for deep-dive analysis 6. Explain: role in architecture, internal structure, external connections, data flow 7. Highlight patterns, idioms, or complexity worth understanding `; const SKILL_UNDERSTAND_KNOWLEDGE = `# understand-knowledge Analyze a knowledge base (wiki with markdown files and wikilinks) and generate a knowledge graph with entity extraction and topic clustering. ## Instructions 1. Detect the knowledge base format (markdown files with wikilinks, index.md, optional raw/ sources) 2. Parse all markdown files: extract wikilinks, headings, frontmatter 3. Build nodes for articles, topics (from index.md sections), and sources 4. Build edges from wikilinks (related), index categories (categorized_under) 5. Analyze articles for implicit relationships and entity extraction 6. Save the knowledge graph to \`.understand-anything/knowledge-graph.json\` `; const SKILL_UNDERSTAND_ONBOARD = `# understand-onboard Generate a comprehensive onboarding guide for new team members from the knowledge graph. ## Instructions 1. Check that \`.understand-anything/knowledge-graph.json\` exists 2. Read project metadata (name, languages, frameworks, description) 3. Read layers to understand architectural structure 4. Read the tour for the recommended learning path 5. Read file-level nodes to build a file map organized by layer 6. Identify complexity hotspots (high-complexity files) 7. Generate onboarding guide with: Project Overview, Architecture Layers, Key Concepts, Guided Tour, File Map, Complexity Hotspots 8. Offer to save as \`docs/ONBOARDING.md\` `; const SKILL_UNDERSTAND = `# understand Analyze the current codebase and produce a knowledge-graph.json file in \`.understand-anything/\`. This file powers all other understand-* skills by mapping the project's architecture, components, and relationships. ## Instructions 1. Scan the project directory to discover all source files, detect languages and frameworks 2. Batch files and analyze each batch to extract nodes (files, functions, classes) and edges (imports, calls, depends_on) 3. Merge batch results, deduplicate nodes and edges, remove dangling references 4. Identify architectural layers by grouping files based on directory structure and import patterns 5. Build a guided tour (learning path) through the codebase based on entry points and layers 6. Assemble the final knowledge graph JSON with: project metadata, nodes, edges, layers, tour 7. Write to \`.understand-anything/knowledge-graph.json\` 8. Write metadata to \`.understand-anything/meta.json\` (timestamp, git commit hash, version, file count) ## Options - \`--full\` — Force a full rebuild, ignoring any existing graph - \`--auto-update\` — Enable automatic graph updates on commit - \`--no-auto-update\` — Disable automatic graph updates - A directory path — Analyze the given directory instead of current working directory `; // (Steering content removed — now lives in SKILL.md files directly) const SKILL_UNDERSTAND_BASELINE = `# understand-baseline Create a baseline snapshot of spec files for later comparison and progress tracking. ## Instructions 1. Run: \`python {{SCRIPTS_DIR}}/understand-baseline/baseline.py\` 2. Optionally add a label: \`python {{SCRIPTS_DIR}}/understand-baseline/baseline.py --label "v1.0"\` 3. To list all baselines: \`python {{SCRIPTS_DIR}}/understand-baseline/baseline.py --list\` 4. Baselines are saved to \`baselines/{timestamp}/\` with metadata `; const SKILL_UNDERSTAND_REPORT = `# understand-report Generate a progress report comparing current spec files against the most recent baseline. ## Instructions 1. Run: \`python {{SCRIPTS_DIR}}/understand-report/report.py\` 2. Report includes: file changes, requirements count, task progress, velocity, ETA 3. Reports are saved to \`reports/{timestamp}.md\` 4. Compare with specific baseline: \`python {{SCRIPTS_DIR}}/understand-report/report.py --baseline TIMESTAMP\` 5. Requires at least one baseline (run understand-baseline first) `; const SKILL_UNDERSTAND_MERMAID = `# understand-mermaid Render Mermaid diagrams from diagrams.mermaid.md to PNG images offline. ## Instructions 1. Run: \`python {{SCRIPTS_DIR}}/understand-mermaid/render_mermaid.py\` 2. Reads \`diagrams.mermaid.md\` and extracts mermaid code blocks 3. Renders each to PNG in \`images/diagrams/diagram_XX.png\` 4. Single diagram: \`python {{SCRIPTS_DIR}}/understand-mermaid/render_mermaid.py --only 01\` 5. Requires: \`npm install -g @mermaid-js/mermaid-cli\` `; const SKILL_UNDERSTAND_EXPORT = `# understand-export Export spec markdown files to PDF with styled formatting. ## Instructions 1. Run: \`python {{SCRIPTS_DIR}}/understand-export/md_to_pdf.py\` 2. Converts all .md spec files to PDF in \`pdf/\` folder 3. Single file: \`python {{SCRIPTS_DIR}}/understand-export/md_to_pdf.py design.md\` 4. Format: A4 landscape, page numbers, styled tables, embedded images 5. Requires: \`npm install -g md-to-pdf\` `; // ============================================================ // KIRO — .kiro/steering/, .kiro/skills/, .kiro/hooks/ // ============================================================ function getKiroTemplates() { return [ { relativePath: '.kiro/steering/understand-project.md', content: `--- inclusion: auto --- # Project Understanding This project has a knowledge graph that maps its architecture, components, and relationships. Use it to answer questions about the codebase without reading every source file. ${GRAPH_DOCS} `, }, { relativePath: '.kiro/skills/understand.md', content: `--- inclusion: manual --- ${SKILL_UNDERSTAND}`, }, { relativePath: '.kiro/skills/understand-chat.md', content: `--- inclusion: manual --- ${SKILL_UNDERSTAND_CHAT}`, }, { relativePath: '.kiro/skills/understand-diff.md', content: `--- inclusion: manual --- ${SKILL_UNDERSTAND_DIFF}`, }, { relativePath: '.kiro/skills/understand-domain.md', content: `--- inclusion: manual --- ${SKILL_UNDERSTAND_DOMAIN}`, }, { relativePath: '.kiro/skills/understand-explain.md', content: `--- inclusion: manual --- ${SKILL_UNDERSTAND_EXPLAIN}`, }, { relativePath: '.kiro/skills/understand-knowledge.md', content: `--- inclusion: manual --- ${SKILL_UNDERSTAND_KNOWLEDGE}`, }, { relativePath: '.kiro/skills/understand-onboard.md', content: `--- inclusion: manual --- ${SKILL_UNDERSTAND_ONBOARD}`, }, { relativePath: '.kiro/skills/understand-baseline.md', content: `--- inclusion: manual --- ${SKILL_UNDERSTAND_BASELINE}`, }, { relativePath: '.kiro/skills/understand-report.md', content: `--- inclusion: manual --- ${SKILL_UNDERSTAND_REPORT}`, }, { relativePath: '.kiro/skills/understand-mermaid.md', content: `--- inclusion: manual --- ${SKILL_UNDERSTAND_MERMAID}`, }, { relativePath: '.kiro/skills/understand-export.md', content: `--- inclusion: manual --- ${SKILL_UNDERSTAND_EXPORT}`, }, { relativePath: '.kiro/hooks/post-commit-update.json', content: JSON.stringify({ name: 'Auto-update knowledge graph', version: '1.0.0', description: 'Checks if knowledge graph needs updating after code changes', when: { type: 'userTriggered', }, then: { type: 'askAgent', prompt: 'Check if .understand-anything/knowledge-graph.json exists and if the git commit hash in .understand-anything/meta.json differs from HEAD. If so, suggest running the knowledge graph update.', }, }, null, 2) + '\n', }, { relativePath: '.kiro/hooks/baseline-spec.json', content: JSON.stringify({ name: 'Baseline Spec Status', version: '1.0.0', description: 'Create a baseline snapshot of all spec files for later comparison', when: { type: 'userTriggered' }, then: { type: 'runCommand', command: 'python {{SCRIPTS_DIR}}/understand-baseline/baseline.py', timeout: 30 }, }, null, 2) + '\n', }, { relativePath: '.kiro/hooks/spec-progress-report.json', content: JSON.stringify({ name: 'Spec Progress Report', version: '1.0.0', description: 'Generate a progress report comparing current spec against the most recent baseline', when: { type: 'userTriggered' }, then: { type: 'runCommand', command: 'python {{SCRIPTS_DIR}}/understand-report/report.py', timeout: 30 }, }, null, 2) + '\n', }, { relativePath: '.kiro/hooks/export-spec-pdf.json', content: JSON.stringify({ name: 'Export Spec to PDF', version: '1.0.0', description: 'Export all spec markdown files to PDF', when: { type: 'userTriggered' }, then: { type: 'runCommand', command: 'python {{SCRIPTS_DIR}}/understand-export/md_to_pdf.py', timeout: 300 }, }, null, 2) + '\n', }, { relativePath: '.kiro/hooks/render-mermaid-diagrams.json', content: JSON.stringify({ name: 'Render Mermaid Diagrams', version: '1.0.0', description: 'Render Mermaid diagrams to PNG when diagrams.mermaid.md is edited', when: { type: 'fileEdited', patterns: ['**/diagrams.mermaid.md'] }, then: { type: 'runCommand', command: 'python {{SCRIPTS_DIR}}/understand-mermaid/render_mermaid.py', timeout: 120 }, }, null, 2) + '\n', }, ]; } // ============================================================ // CODEX (OpenAI) — AGENTS.md + .codex/skills/ // ============================================================ function getCodexTemplates() { return [ { relativePath: 'AGENTS.md', content: `# Project Agent Instructions This project has a knowledge graph that maps its architecture, components, and relationships. Use it to answer questions about the codebase without reading every source file. ${GRAPH_DOCS} `, }, { relativePath: '.codex/skills/understand.md', content: SKILL_UNDERSTAND, }, { relativePath: '.codex/skills/understand-chat.md', content: SKILL_UNDERSTAND_CHAT, }, { relativePath: '.codex/skills/understand-diff.md', content: SKILL_UNDERSTAND_DIFF, }, { relativePath: '.codex/skills/understand-domain.md', content: SKILL_UNDERSTAND_DOMAIN, }, { relativePath: '.codex/skills/understand-explain.md', content: SKILL_UNDERSTAND_EXPLAIN, }, { relativePath: '.codex/skills/understand-knowledge.md', content: SKILL_UNDERSTAND_KNOWLEDGE, }, { relativePath: '.codex/skills/understand-onboard.md', content: SKILL_UNDERSTAND_ONBOARD, }, { relativePath: '.codex/skills/understand-baseline.md', content: SKILL_UNDERSTAND_BASELINE, }, { relativePath: '.codex/skills/understand-report.md', content: SKILL_UNDERSTAND_REPORT, }, { relativePath: '.codex/skills/understand-mermaid.md', content: SKILL_UNDERSTAND_MERMAID, }, { relativePath: '.codex/skills/understand-export.md', content: SKILL_UNDERSTAND_EXPORT, }, ]; } // ============================================================ // OPENCODE — .opencode/skills/ + AGENTS.md // ============================================================ function getOpenCodeTemplates() { return [ { relativePath: 'AGENTS.md', content: `# Project Agent Instructions This project has a knowledge graph that maps its architecture, components, and relationships. Use it to answer questions about the codebase without reading every source file. ${GRAPH_DOCS} `, }, { relativePath: '.opencode/skills/understand/SKILL.md', content: SKILL_UNDERSTAND, }, { relativePath: '.opencode/skills/understand-chat/SKILL.md', content: SKILL_UNDERSTAND_CHAT, }, { relativePath: '.opencode/skills/understand-diff/SKILL.md', content: SKILL_UNDERSTAND_DIFF, }, { relativePath: '.opencode/skills/understand-domain/SKILL.md', content: SKILL_UNDERSTAND_DOMAIN, }, { relativePath: '.opencode/skills/understand-explain/SKILL.md', content: SKILL_UNDERSTAND_EXPLAIN, }, { relativePath: '.opencode/skills/understand-knowledge/SKILL.md', content: SKILL_UNDERSTAND_KNOWLEDGE, }, { relativePath: '.opencode/skills/understand-onboard/SKILL.md', content: SKILL_UNDERSTAND_ONBOARD, }, { relativePath: '.opencode/skills/understand-baseline/SKILL.md', content: SKILL_UNDERSTAND_BASELINE, }, { relativePath: '.opencode/skills/understand-report/SKILL.md', content: SKILL_UNDERSTAND_REPORT, }, { relativePath: '.opencode/skills/understand-mermaid/SKILL.md', content: SKILL_UNDERSTAND_MERMAID, }, { relativePath: '.opencode/skills/understand-export/SKILL.md', content: SKILL_UNDERSTAND_EXPORT, }, ]; } // ============================================================ // CLAUDE CODE — .claude-plugin/ with plugin.json + skills/ + hooks // ============================================================ function getClaudeCodeTemplates() { return [ { relativePath: '.claude-plugin/plugin.json', content: JSON.stringify({ name: 'project-understand', version: '1.0.0', description: 'Knowledge graph-powered project understanding', skills: [ 'skills/understand', 'skills/understand-chat', 'skills/understand-diff', 'skills/understand-domain', 'skills/understand-explain', 'skills/understand-knowledge', 'skills/understand-onboard', 'skills/understand-baseline', 'skills/understand-report', 'skills/understand-mermaid', 'skills/understand-export', ], hooks: { PostToolUse: [ { matcher: 'Bash', hooks: [ { type: 'command', command: 'echo "[project-understand] Check if knowledge graph needs updating after code changes"', }, ], }, ], }, }, null, 2) + '\n', }, { relativePath: '.claude-plugin/skills/understand/SKILL.md', content: `--- name: understand description: Analyze the codebase and produce a knowledge-graph.json argument-hint: [path] [--full|--auto-update] --- ${SKILL_UNDERSTAND}`, }, { relativePath: '.claude-plugin/skills/understand-chat/SKILL.md', content: `--- name: understand-chat description: Answer questions about the codebase using the knowledge graph argument-hint: [query] --- ${SKILL_UNDERSTAND_CHAT}`, }, { relativePath: '.claude-plugin/skills/understand-diff/SKILL.md', content: `--- name: understand-diff description: Analyze code changes against the knowledge graph --- ${SKILL_UNDERSTAND_DIFF}`, }, { relativePath: '.claude-plugin/skills/understand-domain/SKILL.md', content: `--- name: understand-domain description: Extract business domain knowledge from the codebase argument-hint: [--full] --- ${SKILL_UNDERSTAND_DOMAIN}`, }, { relativePath: '.claude-plugin/skills/understand-explain/SKILL.md', content: `--- name: understand-explain description: Deep-dive explanation of a specific file, function, or module argument-hint: [file-path] --- ${SKILL_UNDERSTAND_EXPLAIN}`, }, { relativePath: '.claude-plugin/skills/understand-knowledge/SKILL.md', content: `--- name: understand-knowledge description: Analyze a knowledge base and generate a knowledge graph argument-hint: [wiki-directory] --- ${SKILL_UNDERSTAND_KNOWLEDGE}`, }, { relativePath: '.claude-plugin/skills/understand-onboard/SKILL.md', content: `--- name: understand-onboard description: Generate an onboarding guide for new team members --- ${SKILL_UNDERSTAND_ONBOARD}`, }, { relativePath: '.claude-plugin/skills/understand-baseline/SKILL.md', content: `--- name: understand-baseline description: Create a baseline snapshot of spec files argument-hint: [--list|--label "name"] --- ${SKILL_UNDERSTAND_BASELINE}`, }, { relativePath: '.claude-plugin/skills/understand-report/SKILL.md', content: `--- name: understand-report description: Generate progress report comparing against baseline argument-hint: [--baseline TIMESTAMP] --- ${SKILL_UNDERSTAND_REPORT}`, }, { relativePath: '.claude-plugin/skills/understand-mermaid/SKILL.md', content: `--- name: understand-mermaid description: Render Mermaid diagrams to PNG offline argument-hint: [--only NN] --- ${SKILL_UNDERSTAND_MERMAID}`, }, { relativePath: '.claude-plugin/skills/understand-export/SKILL.md', content: `--- name: understand-export description: Export spec markdown files to PDF argument-hint: [filename.md] --- ${SKILL_UNDERSTAND_EXPORT}`, }, ]; } // ============================================================ // OPENCLAW — .agent/AGENT.md + .agent/skills/ + .agent/hooks/ // ============================================================ function getOpenClawTemplates() { return [ { relativePath: '.agent/AGENT.md', content: `# Project Agent Instructions This project has a knowledge graph that maps its architecture, components, and relationships. Use it to answer questions about the codebase without reading every source file. ${GRAPH_DOCS} `, }, { relativePath: '.agent/skills/understand/SKILL.md', content: SKILL_UNDERSTAND, }, { relativePath: '.agent/skills/understand-chat/SKILL.md', content: SKILL_UNDERSTAND_CHAT, }, { relativePath: '.agent/skills/understand-diff/SKILL.md', content: SKILL_UNDERSTAND_DIFF, }, { relativePath: '.agent/skills/understand-domain/SKILL.md', content: SKILL_UNDERSTAND_DOMAIN, }, { relativePath: '.agent/skills/understand-explain/SKILL.md', content: SKILL_UNDERSTAND_EXPLAIN, }, { relativePath: '.agent/skills/understand-knowledge/SKILL.md', content: SKILL_UNDERSTAND_KNOWLEDGE, }, { relativePath: '.agent/skills/understand-onboard/SKILL.md', content: SKILL_UNDERSTAND_ONBOARD, }, { relativePath: '.agent/skills/understand-baseline/SKILL.md', content: SKILL_UNDERSTAND_BASELINE, }, { relativePath: '.agent/skills/understand-report/SKILL.md', content: SKILL_UNDERSTAND_REPORT, }, { relativePath: '.agent/skills/understand-mermaid/SKILL.md', content: SKILL_UNDERSTAND_MERMAID, }, { relativePath: '.agent/skills/understand-export/SKILL.md', content: SKILL_UNDERSTAND_EXPORT, }, { relativePath: '.agent/hooks/post-commit-update.md', content: `# Post-Commit: Update Knowledge Graph ## Trigger PostToolUse — after git commit, merge, or rebase ## Condition - \`.understand-anything/knowledge-graph.json\` exists - \`.understand-anything/meta.json\` exists - Git commit hash in meta.json differs from current HEAD ## Action Suggest running knowledge graph update to reflect structural changes. `, }, { relativePath: '.agent/hooks/baseline-spec.md', content: `# Baseline Spec Status ## Trigger UserTriggered — when user says "baseline" or "snapshot spec" ## Action Run: \`python {{SCRIPTS_DIR}}/understand-baseline/baseline.py\` Creates a timestamped snapshot of all spec files in baselines/ folder. `, }, { relativePath: '.agent/hooks/render-mermaid.md', content: `# Render Mermaid Diagrams ## Trigger FileEdited — when \`**/diagrams.mermaid.md\` is modified ## Action Run: \`python {{SCRIPTS_DIR}}/understand-mermaid/render_mermaid.py\` Renders all Mermaid diagrams to PNG in images/diagrams/ folder. `, }, ]; } // ============================================================ // CURSOR — .cursor/rules/ (no official skills, uses rules + tools.json) // ============================================================ function getCursorTemplates() { return [ { relativePath: '.cursor/rules/understand-project.mdc', content: `--- description: Project understanding via knowledge graph globs: alwaysApply: true --- # Project Understanding This project has a knowledge graph that maps its architecture, components, and relationships. Use it to answer questions about the codebase without reading every source file. ${GRAPH_DOCS} `, }, { relativePath: '.cursor/rules/understand-conventions.mdc', content: `--- description: Conventions for working with the knowledge graph globs: alwaysApply: false --- # Knowledge Graph Conventions ## After Structural Changes If files are added/removed/renamed or exports change significantly, the knowledge graph at \`.understand-anything/knowledge-graph.json\` may need regeneration. ## Utility Scripts - Baseline spec: \`python {{SCRIPTS_DIR}}/understand-baseline/baseline.py\` - Progress report: \`python {{SCRIPTS_DIR}}/understand-report/report.py\` - Render diagrams: \`python {{SCRIPTS_DIR}}/understand-mermaid/render_mermaid.py\` - Export PDF: \`python {{SCRIPTS_DIR}}/understand-export/md_to_pdf.py\` `, }, ]; } // ============================================================ // OPENSPEC — openspec/AGENTS.md + .github/instructions/ + .github/prompts/ // ============================================================ function getOpenSpecTemplates() { return [ { relativePath: 'openspec/AGENTS.md', content: `# Project Agent Instructions This project has a knowledge graph that maps its architecture, components, and relationships. Use it to answer questions about the codebase without reading every source file. ${GRAPH_DOCS} `, }, { relativePath: '.github/instructions/understand-project.instructions.md', content: `# Project Understanding Instructions This project has a knowledge graph at \`.understand-anything/knowledge-graph.json\`. ### How to Use 1. Search the JSON for relevant nodes before reading source files 2. Node summaries provide quick understanding of each component 3. Follow edges to trace dependency chains 4. Use layers to understand architectural boundaries ### Node ID Conventions - \`file:src/path.ts\` — source files - \`function:src/path.ts:funcName\` — functions - \`class:src/path.ts:ClassName\` — classes - \`config:tsconfig.json\` — configuration files - \`document:README.md\` — documentation files `, }, { relativePath: '.github/prompts/understand.prompt.md', content: SKILL_UNDERSTAND, }, { relativePath: '.github/prompts/understand-chat.prompt.md', content: SKILL_UNDERSTAND_CHAT, }, { relativePath: '.github/prompts/understand-diff.prompt.md', content: SKILL_UNDERSTAND_DIFF, }, { relativePath: '.github/prompts/understand-domain.prompt.md', content: SKILL_UNDERSTAND_DOMAIN, }, { relativePath: '.github/prompts/understand-explain.prompt.md', content: SKILL_UNDERSTAND_EXPLAIN, }, { relativePath: '.github/prompts/understand-knowledge.prompt.md', content: SKILL_UNDERSTAND_KNOWLEDGE, }, { relativePath: '.github/prompts/understand-onboard.prompt.md', content: SKILL_UNDERSTAND_ONBOARD, }, { relativePath: '.github/prompts/understand-baseline.prompt.md', content: SKILL_UNDERSTAND_BASELINE, }, { relativePath: '.github/prompts/understand-report.prompt.md', content: SKILL_UNDERSTAND_REPORT, }, { relativePath: '.github/prompts/understand-mermaid.prompt.md', content: SKILL_UNDERSTAND_MERMAID, }, { relativePath: '.github/prompts/understand-export.prompt.md', content: SKILL_UNDERSTAND_EXPORT, }, ]; }