@@ -376,111 +376,82 @@ int cbm_replace_binary(const char *path, const unsigned char *data, int len, int
376376
377377/* ── Skill file content (embedded) ────────────────────────────── */
378378
379- static const char skill_exploring_content [] =
379+ /* Consolidated from 4 separate skills into 1 with progressive disclosure.
380+ * This embedded version is the single source of truth for the CLI installer.
381+ * Based on PR #81 by @gdilla — factual corrections applied. */
382+ static const char skill_content [] =
380383 "---\n"
381- "name: codebase-memory-exploring\n"
382- "description: Codebase knowledge graph expert. ALWAYS invoke this skill when the user "
383- "explores code, searches for functions/classes/routes, asks about architecture, or needs "
384- "codebase orientation. Do not use Grep, Glob, or file search directly — use "
385- "codebase-memory-mcp search_graph and get_architecture first.\n"
384+ "name: codebase-memory\n"
385+ "description: Use the codebase knowledge graph for structural code queries. "
386+ "Triggers on: explore the codebase, understand the architecture, what functions exist, "
387+ "show me the structure, who calls this function, what does X call, trace the call chain, "
388+ "find callers of, show dependencies, impact analysis, dead code, unused functions, "
389+ "high fan-out, refactor candidates, code quality audit, graph query syntax, "
390+ "Cypher query examples, edge types, how to use search_graph.\n"
386391 "---\n"
387392 "\n"
388- "# Codebase Exploration \n"
393+ "# Codebase Memory — Knowledge Graph Tools \n"
389394 "\n"
390- "Use codebase-memory-mcp tools to explore the codebase: \n"
395+ "Graph tools return precise structural results in ~500 tokens vs ~80K for grep. \n"
391396 "\n"
392- "## Workflow\n"
393- "1. `get_graph_schema` — understand what node/edge types exist\n"
394- "2. `search_graph` — find functions, classes, routes by pattern\n"
395- "3. `get_code_snippet` — read specific function implementations\n"
396- "4. `get_architecture` — get high-level project summary\n"
397+ "## Quick Decision Matrix\n"
397398 "\n"
398- "## Tips\n"
399- "- Use `search_graph(name_pattern=\".*Pattern.*\")` for fuzzy matching\n"
400- "- Use `search_graph(label=\"Route\")` to find HTTP routes\n"
401- "- Use `search_graph(label=\"Function\", file_pattern=\"*.go\")` to scope by language\n" ;
402-
403- static const char skill_tracing_content [] =
404- "---\n"
405- "name: codebase-memory-tracing\n"
406- "description: Call chain and dependency expert. ALWAYS invoke this skill when the user "
407- "asks who calls a function, what a function calls, needs impact analysis, or traces "
408- "dependencies. Do not grep for function names directly — use codebase-memory-mcp "
409- "trace_path first.\n"
410- "---\n"
411- "\n"
412- "# Call Tracing & Impact Analysis\n"
413- "\n"
414- "Use codebase-memory-mcp tools to trace call paths:\n"
415- "\n"
416- "## Workflow\n"
417- "1. `search_graph(name_pattern=\".*FuncName.*\")` — find exact function name\n"
418- "2. `trace_path(function_name=\"FuncName\", direction=\"both\")` — trace callers + "
419- "callees\n"
420- "3. `detect_changes` — find what changed and assess risk_labels\n"
399+ "| Question | Tool call |\n"
400+ "|----------|----------|\n"
401+ "| Who calls X? | `trace_path(direction=\"inbound\")` |\n"
402+ "| What does X call? | `trace_path(direction=\"outbound\")` |\n"
403+ "| Full call context | `trace_path(direction=\"both\")` |\n"
404+ "| Find by name pattern | `search_graph(name_pattern=\"...\")` |\n"
405+ "| Dead code | `search_graph(max_degree=0, exclude_entry_points=true)` |\n"
406+ "| Cross-service edges | `query_graph` with Cypher |\n"
407+ "| Impact of local changes | `detect_changes()` |\n"
408+ "| Text search | `search_code` or Grep |\n"
421409 "\n"
422- "## Direction Options\n"
423- "- `inbound` — who calls this function?\n"
424- "- `outbound` — what does this function call?\n"
425- "- `both` — full context (callers + callees)\n" ;
426-
427- static const char skill_quality_content [] =
428- "---\n"
429- "name: codebase-memory-quality\n"
430- "description: Code quality analysis expert. ALWAYS invoke this skill when the user asks "
431- "about dead code, unused functions, complexity, refactor candidates, or cleanup "
432- "opportunities. Do not search files manually — use codebase-memory-mcp search_graph "
433- "with degree filters first.\n"
434- "---\n"
410+ "## Exploration Workflow\n"
411+ "1. `list_projects` — check if project is indexed\n"
412+ "2. `get_graph_schema` — understand node/edge types\n"
413+ "3. `search_graph(label=\"Function\", name_pattern=\".*Pattern.*\")` — find code\n"
414+ "4. `get_code_snippet(qualified_name=\"project.path.FuncName\")` — read source\n"
435415 "\n"
436- "# Code Quality Analysis\n"
416+ "## Tracing Workflow\n"
417+ "1. `search_graph(name_pattern=\".*FuncName.*\")` — discover exact name\n"
418+ "2. `trace_path(function_name=\"FuncName\", direction=\"both\", depth=3)` — trace\n"
419+ "3. `detect_changes()` — map git diff to affected symbols\n"
437420 "\n"
438- "Use codebase-memory-mcp tools for quality analysis:\n"
421+ "## Quality Analysis\n"
422+ "- Dead code: `search_graph(max_degree=0, exclude_entry_points=true)`\n"
423+ "- High fan-out: `search_graph(min_degree=10, relationship=\"CALLS\", "
424+ "direction=\"outbound\")`\n"
425+ "- High fan-in: `search_graph(min_degree=10, relationship=\"CALLS\", "
426+ "direction=\"inbound\")`\n"
439427 "\n"
440- "## Dead Code Detection\n"
441- "- `search_graph(max_degree=0, exclude_entry_points=true)` — find unreferenced functions\n"
442- "- `search_graph(max_degree=0, label=\"Function\")` — unreferenced functions only\n"
443- "\n"
444- "## Complexity Analysis\n"
445- "- `search_graph(min_degree=10)` — high fan-out functions\n"
446- "- `search_graph(label=\"Function\", sort_by=\"degree\")` — most-connected functions\n" ;
447-
448- static const char skill_reference_content [] =
449- "---\n"
450- "name: codebase-memory-reference\n"
451- "description: Codebase-memory-mcp reference guide. ALWAYS invoke this skill when the user "
452- "asks about MCP tools, graph queries, Cypher syntax, edge types, or how to use the "
453- "knowledge graph. Do not guess tool parameters — load this reference first.\n"
454- "---\n"
455- "\n"
456- "# Codebase Memory MCP Reference\n"
457- "\n"
458- "## 14 total MCP Tools\n"
459- "- `index_repository` — index a project\n"
460- "- `index_status` — check indexing progress\n"
461- "- `detect_changes` — find what changed since last index\n"
462- "- `search_graph` — find nodes by pattern\n"
463- "- `search_code` — text search in source\n"
464- "- `query_graph` — Cypher query language\n"
465- "- `trace_path` — call chain traversal\n"
466- "- `get_code_snippet` — read function source\n"
467- "- `get_graph_schema` — node/edge type catalog\n"
468- "- `get_architecture` — high-level summary\n"
469- "- `list_projects` — indexed projects\n"
470- "- `delete_project` — remove a project\n"
471- "- `manage_adr` — architecture decision records\n"
472- "- `ingest_traces` — import runtime traces\n"
428+ "## 14 MCP Tools\n"
429+ "`index_repository`, `index_status`, `list_projects`, `delete_project`,\n"
430+ "`search_graph`, `search_code`, `trace_path`, `detect_changes`,\n"
431+ "`query_graph`, `get_graph_schema`, `get_code_snippet`, `get_architecture`,\n"
432+ "`manage_adr`, `ingest_traces`\n"
473433 "\n"
474434 "## Edge Types\n"
475435 "CALLS, HTTP_CALLS, ASYNC_CALLS, IMPORTS, DEFINES, DEFINES_METHOD,\n"
476436 "HANDLES, IMPLEMENTS, CONTAINS_FILE, CONTAINS_FOLDER, CONTAINS_PACKAGE\n"
477437 "\n"
478- "## Cypher Examples\n"
438+ "## Cypher Examples (for query_graph) \n"
479439 "```\n"
440+ "MATCH (a)-[r:HTTP_CALLS]->(b) RETURN a.name, b.name, r.url_path, "
441+ "r.confidence LIMIT 20\n"
480442 "MATCH (f:Function) WHERE f.name =~ '.*Handler.*' RETURN f.name, f.file_path\n"
481443 "MATCH (a)-[r:CALLS]->(b) WHERE a.name = 'main' RETURN b.name\n"
482- "MATCH (a)-[r:HTTP_CALLS]->(b) RETURN a.name, b.name, r.url_path\n"
483- "```\n" ;
444+ "```\n"
445+ "\n"
446+ "## Gotchas\n"
447+ "1. `search_graph(relationship=\"HTTP_CALLS\")` filters nodes by degree — "
448+ "use `query_graph` with Cypher to see actual edges.\n"
449+ "2. `query_graph` has a 200-row cap — use `search_graph` with degree filters "
450+ "for counting.\n"
451+ "3. `trace_path` needs exact names — use `search_graph(name_pattern=...)` first.\n"
452+ "4. `direction=\"outbound\"` misses cross-service callers — use "
453+ "`direction=\"both\"`.\n"
454+ "5. Results default to 10 per page — check `has_more` and use `offset`.\n" ;
484455
485456static const char codex_instructions_content [] =
486457 "# Codebase Knowledge Graph\n"
@@ -496,11 +467,17 @@ static const char codex_instructions_content[] =
496467 "\n"
497468 "Always prefer graph tools over grep for code discovery.\n" ;
498469
470+ /* Old skill names — cleaned up during install to remove stale directories. */
471+ static const char * old_skill_names [] = {
472+ "codebase-memory-exploring" ,
473+ "codebase-memory-tracing" ,
474+ "codebase-memory-quality" ,
475+ "codebase-memory-reference" ,
476+ };
477+ enum { OLD_SKILL_COUNT = 4 };
478+
499479static const cbm_skill_t skills [CBM_SKILL_COUNT ] = {
500- {"codebase-memory-exploring" , skill_exploring_content },
501- {"codebase-memory-tracing" , skill_tracing_content },
502- {"codebase-memory-quality" , skill_quality_content },
503- {"codebase-memory-reference" , skill_reference_content },
480+ {"codebase-memory" , skill_content },
504481};
505482
506483const cbm_skill_t * cbm_get_skills (void ) {
@@ -577,6 +554,16 @@ int cbm_install_skills(const char *skills_dir, bool force, bool dry_run) {
577554 }
578555 int count = 0 ;
579556
557+ /* Clean up old 4-skill directories (consolidated into 1). */
558+ for (int i = 0 ; i < OLD_SKILL_COUNT ; i ++ ) {
559+ char old_path [CLI_BUF_1K ];
560+ snprintf (old_path , sizeof (old_path ), "%s/%s" , skills_dir , old_skill_names [i ]);
561+ struct stat st ;
562+ if (stat (old_path , & st ) == 0 && S_ISDIR (st .st_mode ) && !dry_run ) {
563+ rmdir_recursive (old_path );
564+ }
565+ }
566+
580567 for (int i = 0 ; i < CBM_SKILL_COUNT ; i ++ ) {
581568 char skill_path [CLI_BUF_1K ];
582569 snprintf (skill_path , sizeof (skill_path ), "%s/%s" , skills_dir , skills [i ].name );
0 commit comments