From claude-mem
Build a queryable code-structure graph for a codebase using graphify (AST + optional semantic extraction), then file the result into the claude-mem wiki at wiki/code/. Trigger phrases - graphify this codebase, build the code graph, ingest the code, /graphify-ingest, refresh the graph.
How this skill is triggered — by the user, by Claude, or both
Slash command
/claude-mem:graphify-ingestThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Build a structural knowledge graph for a code repository and integrate it with the claude-mem wiki.
Build a structural knowledge graph for a code repository and integrate it with the claude-mem wiki.
This skill is the structural layer of claude-mem. It produces:
graphify-out/graph.json — queryable NetworkX graph (committed)graphify-out/GRAPH_REPORT.md — god nodes, surprising connections, suggested questions, audit trailgraphify-out/graph.html — interactive viz, open in browserwiki/code/_COMMUNITY_NN_<slug>.md — one summary page per meaningful clusterwiki/code/graph.canvas — visual layer for Obsidianwiki/hot.md — rewritten with the graph snapshot at the topThe narrative layer (wiki/decisions/, wiki/concepts/, wiki/sources/) stays human-owned. Use /save and wiki-ingest for that.
Run this skill when:
graphify-out/ and wiki/code/Do NOT invoke for non-code corpuses (docs-only, research wikis). Use wiki-ingest instead.
| Mode | What runs | Cost | Use when |
|---|---|---|---|
| A | AST extraction only (tree-sitter) | $0 | First test, sparse exploration, languages tree-sitter handles well |
| B | A + semantic extraction via parallel subagents on docs and code | ~$1–3 (Sonnet) | Default. Densifies the graph, finds INFERRED edges, names hyperedge patterns |
| B+images | B + per-image vision subagent (1 per image) | ~$6–18 extra | Only when image content carries codebase concepts (rare for pure code repos) |
Default to B. Switch to A if user says "no LLM" / "free only" / "AST only". Add images only on explicit request.
If the user gave a path, use it. Otherwise use the current working directory.
TARGET="${1:-$PWD}"
TARGET=$(cd "$TARGET" && pwd) # absolutize
If $TARGET/wiki/ doesn't exist, scaffold it first (this is a fresh project):
mkdir -p "$TARGET/wiki/code" "$TARGET/wiki/decisions" "$TARGET/wiki/concepts" "$TARGET/wiki/sources"
If the user has not yet seen the wiki layer, briefly tell them what you're about to create and where.
Delegate to the bundled installer. It detects the best Python (>=3.10,<3.14), installs graphifyy via the right strategy (pip, --user, --break-system-packages), verifies the import, and pins the interpreter for this project.
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d "$HOME"/.claude/plugins/cache/*/claude-mem/*/ 2>/dev/null | sort -V | tail -1 | sed 's:/$::')}"
[ -z "$PLUGIN_ROOT" ] && PLUGIN_ROOT="$HOME/.claude/plugins/claude-mem"
SETUP="$PLUGIN_ROOT/bin/setup-graphify.sh"
bash "$SETUP" "$TARGET"
PYTHON=$(cat "$TARGET/graphify-out/.graphify_python")
PLUGIN_ROOT is reused in later steps. If CLAUDE_PLUGIN_ROOT is unset (it should be set by Claude Code at skill invocation, but isn't always), the snippet locates the newest install under ~/.claude/plugins/cache/*/claude-mem/*/.
If the script exits non-zero (no compatible Python, install failure), it tells the user exactly what to do next (install Python 3.13 via pyenv or Homebrew). Stop here and surface that message — don't try to recover automatically.
SKILL_DIR="$PLUGIN_ROOT/skills/graphify-ingest"
"$PYTHON" "$SKILL_DIR/scripts/chunks.py" "$TARGET" --mode B
This prints the corpus summary (file counts by category, exclusions). Show the output to the user verbatim — don't paraphrase. It tells them what's about to be processed.
If the user asked for mode A, pass --mode A. If they asked for images, add --include-images.
If the corpus is huge (>2M words OR >500 files), pause and ask which subdirectory to scope to. Don't burn tokens silently on a giant corpus.
Read $TARGET/graphify-out/.path_b_chunks.json. For each chunk in the plan, dispatch ONE graphify-extract-subagent (defined in agents/graphify-extract-subagent.md). The subagent already knows the extraction rules, schema, and output format — you just hand it its chunk.
All Agent tool calls in a single message so they run concurrently. Use model: "sonnet" for cost.
For each chunk in the plan:
Agent tool call:
subagent_type: "graphify-extract-subagent"
description: "Graphify extract chunk N/TOTAL (KIND)"
model: "sonnet"
prompt: |
chunk_num: <N>
total_chunks: <TOTAL>
kind: <docs | code | image>
deep_mode: <true | false>
output_path: <absolute path to graphify-out/.graphify_chunk_NN.json>
files:
<one absolute path per line>
ast_ids:
<one ID per line, or 'none' if empty>
Why a custom subagent (not general-purpose): graphify-extract-subagent centralizes the ~120-line extraction prompt — schema, ID format rules, confidence tagging, hyperedge guidance. Keeping it in agents/graphify-extract-subagent.md means the skill stays small and the worker definition can evolve independently.
Wait for all subagents. Verify each graphify-out/.graphify_chunk_NN.json exists on disk — that's the success signal, not the return message. If a chunk file is missing, re-dispatch just that one (the worker prompt is idempotent and safe to re-run).
"$PYTHON" "$SKILL_DIR/scripts/merge.py" "$TARGET"
This reads .ast_extract.json + all .graphify_chunk_*.json, merges, drops edges with unknown endpoints, builds the NetworkX graph, runs Louvain clustering, computes cohesion + god nodes + surprises + suggested questions, writes .graphify_analysis.json, and emits a placeholder report.
After this step, .graphify_chunk_*.json files are cleaned up (data is now in .graphify_extract.json).
Show the merge output verbatim. Note the dropped-edge count — if it's >25% of total edges, the AST IDs hint pass didn't help enough; investigate.
Read $TARGET/graphify-out/.graphify_analysis.json and $TARGET/graphify-out/.graphify_extract.json.
The communities field is a dict of {community_id: [node_id, node_id, ...]} — each value is a plain list of member node IDs, NOT a dict with size/members keys. Iterate as:
for cid, members in analysis["communities"].items():
if len(members) >= 3:
...
For each community with size ≥ 3, look at the node labels (you can quickly scan them). Write a 2-5 word plain-language name that captures what the cluster IS — focus on the dominant concept, not every member.
Examples (from a real Next.js test run):
Write the labels to $TARGET/graphify-out/labels.json (committed file — graphify-update will read it on subsequent runs to preserve cluster names):
{"0": "About Page Carousel Sections", "1": "Blog and Home Editorial", ...}
Cover every community with size ≥ 3. Skip the rest — regenerate.py calls them "Cluster N" and skips them anyway.
"$PYTHON" "$SKILL_DIR/scripts/regenerate.py" "$TARGET" "$TARGET/graphify-out/labels.json"
This regenerates GRAPH_REPORT.md with real labels, writes wiki/code/_COMMUNITY_*.md pages, regenerates graph.canvas, rewrites wiki/hot.md with the snapshot, and appends a line to wiki/log.md.
regenerate.py defaults to --min-members 3. Pass a different value if the user wants tighter or looser pages.
After the pipeline finishes, paste these sections from GRAPH_REPORT.md into chat:
Then offer one of the suggested questions to traverse via wiki-query or by reading graph.json directly. Keep it conversational — the graph is the map, your job after the pipeline is to be the guide.
If $TARGET/AGENTS.md exists but lacks a ## Wiki + Graph section, append (or create the file if missing):
## Wiki + Graph
This project uses claude-mem (narrative wiki) + graphify (structural code graph). Both layers are committed.
**Vault**: `wiki/`
**Code graph**: `graphify-out/graph.json`
**Query order when answering questions about this codebase**:
1. `wiki/hot.md` — recent context + graph snapshot
2. `wiki/index.md` — vault entry point
3. `graphify-out/graph.json` — for structural questions (who calls X? what's connected?)
4. `wiki/code/_COMMUNITY_*.md` — cluster summaries with source links
5. Raw source files — last resort
**What goes where**:
- Structural facts (calls, types, imports): graphify writes them
- Decisions, rationale: save to `wiki/decisions/` via `/save`
- External docs / RFCs: ingest into `wiki/sources/` via `wiki-ingest`
`wiki/code/` is graphify-owned — do not hand-edit.
Append if not already present:
# claude-mem + graphify (per-developer state, transient flags)
graphify-out/cost.json
graphify-out/.graphify_python
wiki/.needs_graph_update
# Obsidian per-user state
.obsidian/workspace.json
.obsidian/workspace-*.json
.obsidian/cache
If $TARGET/.obsidian/app.json is {} or missing, write a sensible default that hides non-wiki content from the Obsidian sidebar. Pick paths that exist in the project — at minimum: src/, node_modules/, .next/, .git/, graphify-out/, top-level config files.
_COMMUNITY_*.md later.graphify update).Throwaway intermediate files written under graphify-out/. (dotfiles) are cleaned up by merge.py once they've been folded into .graphify_extract.json. The script-managed .graphify_python and .labels.json are gitignored.
npx claudepluginhub kornevdima/claude-mem --plugin claude-memFetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
Applies a firm's KYC/AML rules grid to parsed onboarding records: assigns risk rating, checks required documents, outputs rule outcomes with citations, and routes for escalation.
Generates daily or weekly digests of activity from connected sources (chat, email, docs, tasks, CRM), highlighting action items, decisions, mentions, and project updates.