agentleFS
ZaxbyHubZaxbyHub/opencode-swarm/.claude/skills/graphify/SKILL.md

graphify

Skill517 starsChanged 3 days agoMITView on GitHub

Use for any question about a codebase, its architecture, file relationships, or project content — especially when graphify-out/ exists, where the question should be treated as a graphify query first. Turns any input (code, docs, papers, images, videos) into a persistent knowledge graph with god nodes, community detection, and query/path/explain tools.

  • Reads credentials
  • Installs packages

We split this skill into the rules it gives an agent

25 rules. 1 is common, 6 are distinctive, and 18 are very specific to this project.

  • 1

    Common

    Most of the 108 edited versions we read keep these.

  • 6

    Distinctive

    This author's own choices. Worth a look.

  • 18

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    If the user invoked /graphify --help or /graphify -h (with no other arguments), print the contents of the ## Usage section above verbatim …

    line 53
  2. Very specific:

    If no path was given, use .

    line 57
  3. Very specific:

    If the path argument starts with https://github.com/ or http://github.com/, treat it as a GitHub URL - run Step 0 before anything else, …

    line 59
  4. Common:

    Follow these steps in order.

    line 61
  5. Very specific:

    Only when the path is one or more https://github.com/...

    line 65
  6. Very specific:

    If total_files is 0: stop with "No supported files found in [path]."

    line 97
  7. Very specific:

    If skipped_sensitive is non-empty: mention file count skipped, not the file names.

    line 98
  8. Very specific:

    If total_words > 2,000,000 OR total_files > 500: show the warning.

    line 99
  9. Very specific:

    Read scan_root from the detect JSON (always an absolute path to the resolved INPUT_PATH).

    line 100
  10. Very specific:

    If all files are in (root) with no subdirectories, do not ask to narrow — no subfolders exist.

    line 104
  11. Very specific:

    Before dispatching subagents: check whether GEMINI_API_KEY or GOOGLE_API_KEY is set.

    line 118
  12. Very specific:

    If this step prints ERROR: Graph is empty, stop and tell the user what happened - do not proceed to labeling or visualization.

    line 252
  13. Very specific:

    Read graphify-out/.graphify_analysis.json.

    line 284
  14. Very specific:

    If --obsidian was given:

    line 327
  15. Very specific:

    If --obsidian-dir <path> was also given, pass it via --dir.

    line 329
  16. Very specific:

    Before running any subcommand below (--update, --cluster-only, query, path, explain, add), check that .graphify_python exists.

    line 355
  17. Very specific:

    When graphify-out/graph.json already exists and the user asks a question about the corpus, answer from the graph rather than rebuilding it:

    line 379
  18. Very specific:

    When the user asks to install the post-commit auto-rebuild hook or wire graphify into a project's CLAUDE.md, see references/hooks.md.

    line 397
  19. Very specific:

    If vertical scrolling breaks in PowerShell after running graphify, this is caused by ANSI escape sequences from the graspologic library.

    line 405
  20. Distinctive:

    Use Windows Terminal: instead of the legacy PowerShell console — Windows Terminal handles ANSI codes correctly

    line 408
  21. Distinctive:

    Never invent an edge. If unsure, use AMBIGUOUS.

    line 416
  22. Distinctive:

    Never skip the corpus check warning.

    line 417
  23. Distinctive:

    Always show token cost in the report.

    line 418
  24. Distinctive:

    Never hide cohesion scores behind symbols - show the raw number.

    line 419
  25. Distinctive:

    Never run HTML viz on a graph with more than 5,000 nodes without warning the user.

    line 420

“Common” is measured: kept by at least 6 in 10 of the 108 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

/graphify

Turn any folder of files into a navigable knowledge graph with community detection, an honest audit trail, and three outputs: interactive HTML, GraphRAG-ready JSON, and a plain-language GRAPH_REPORT.md.

Usage

/graphify                                             # full pipeline on current directory → Obsidian vault
/graphify <path>                                      # full pipeline on specific path
/graphify https://github.com/<owner>/<repo>           # clone repo then run full pipeline on it
/graphify https://github.com/<owner>/<repo> --branch <branch>  # clone a specific branch
/graphify <url1> <url2> ...                           # clone multiple repos, build each, merge into one cross-repo graph
/graphify <path> --mode deep                          # thorough extraction, richer INFERRED edges
/graphify <path> --update                             # incremental - re-extract only new/changed files
/graphify <path> --directed                            # build directed graph (preserves edge direction: source→target)
/graphify <path> --whisper-model medium                # use a larger Whisper model for better transcription accuracy
/graphify <path> --cluster-only                       # rerun clustering on existing graph
/graphify <path> --no-viz                             # skip visualization, just report + JSON
/graphify <path> --html                               # (HTML is generated by default - this flag is a no-op)
/graphify <path> --svg                                # also export graph.svg (embeds in Notion, GitHub)
/graphify <path> --graphml                            # export graph.graphml (Gephi, yEd)
/graphify <path> --neo4j                              # generate graphify-out/cypher.txt for Neo4j
/graphify <path> --neo4j-push bolt://localhost:7687   # push directly to Neo4j
/graphify <path> --falkordb                           # generate graphify-out/cypher.txt for FalkorDB
/graphify <path> --falkordb-push falkordb://localhost:6379   # push directly to FalkorDB
/graphify <path> --mcp                                # start MCP stdio server for agent access
/graphify <path> --watch                              # watch folder, auto-rebuild on code changes (no LLM needed)
/graphify <path> --wiki                               # build agent-crawlable wiki (index.md + one article per community)
/graphify <path> --obsidian --obsidian-dir ~/vaults/my-project  # write vault to custom path (e.g. existing vault)
/graphify add <url>                                   # fetch URL, save to ./raw, update graph
/graphify add <url> --author "Name"                   # tag who wrote it
/graphify add <url> --contributor "Name"              # tag who added it to the corpus
/graphify query "<question>"                          # BFS traversal - broad context
/graphify query "<question>" --dfs                    # DFS - trace a specific path
/graphify query "<question>" --budget 1500            # cap answer at N tokens
/graphify path "AuthModule" "Database"                # shortest path between two concepts
/graphify explain "SwinTransformer"                   # plain-language explanation of a node

What graphify is for

Drop any folder of code, docs, papers, images, or video into graphify and get a queryable knowledge graph. Persistent across sessions, honest audit trail (EXTRACTED/INFERRED/AMBIGUOUS), community detection surfaces cross-document connections you wouldn't think to ask about.

What You Must Do When Invoked

If the user invoked /graphify --help or /graphify -h (with no other arguments), print the contents of the ## Usage section above verbatim and stop. Do not run any commands, do not detect files, do not default the path to .. Just print the Usage block and return.

Fast path — existing graph: Before doing anything else, check whether graphify-out/graph.json exists. The expected location is graphify-out/graph.json relative to the current working directory (i.e. the project root where you are running commands). If it exists AND the user's request is a natural-language question about the codebase (e.g. "How does X work?", "What calls Y?", "Trace the data flow through Z") and NOT an explicit rebuild command (--update, --cluster-only, or a bare path/URL that implies fresh extraction): skip Steps 1–5 entirely and jump straight to ## For /graphify query. Run graphify query "<question>" immediately. Do not run detect. Do not check corpus size. Do not ask the user to narrow. The graph is already built — use it.

If no path was given, use . (current directory). Do not ask the user for a path.

If the path argument starts with https://github.com/ or http://github.com/, treat it as a GitHub URL - run Step 0 before anything else, then continue with the resolved local path.

Follow these steps in order. Do not skip steps.

Step 0 - GitHub repos and multi-path merge (only if a URL or several paths)

Only when the path is one or more https://github.com/... URLs, or several local subfolders to merge. See references/github-and-merge.md for the clone, cross-repo merge, and monorepo flow, then continue with the resolved local path. A plain local path skips this step.

Step 1 - Ensure graphify is installed

Interpreter detection and install flow moved to references/interpreter-detection.md (issue #2907 progressive-disclosure budget).

Step 2 - Detect files

$(cat graphify-out/.graphify_python) -c "
import json
from graphify.detect import detect
from pathlib import Path
result = detect(Path('INPUT_PATH'))
print(json.dumps(result, ensure_ascii=False))
" > graphify-out/.graphify_detect.json

Replace INPUT_PATH with the actual path the user provided. Do NOT cat or print the JSON - read it silently and present a clean summary instead:

Corpus: X files · ~Y words
  code:     N files (.py .ts .go ...)
  docs:     N files (.md .txt ...)
  papers:   N files (.pdf ...)
  images:   N files
  video:    N files (.mp4 .mp3 ...)

Omit any category with 0 files from the summary.

Then act on it:

  • If total_files is 0: stop with "No supported files found in [path]."
  • If skipped_sensitive is non-empty: mention file count skipped, not the file names.
  • If total_words > 2,000,000 OR total_files > 500: show the warning. Then compute the top 5 first-level subdirectories by file count:
    • Read scan_root from the detect JSON (always an absolute path to the resolved INPUT_PATH).
    • Concatenate all file lists across all types (code, document, paper, image, video).
    • Filter out any path that starts with scan_root + "/graphify-out/" to exclude converted sidecars.
    • For each file, strip the scan_root prefix and take the first path component. Files directly in scan_root with no subdirectory count as (root).
    • If all files are in (root) with no subdirectories, do not ask to narrow — no subfolders exist. Instead suggest --no-cluster to skip the expensive clustering step and proceed.
    • Otherwise rank by count, show the top 5 with file counts, then ask which subfolder to run on. Wait for the user's answer before proceeding.
  • Otherwise: proceed directly to Step 2.5 if video files were detected, or Step 3 if not.

Step 2.5 - Video and audio (only if video files detected)

Skip this step entirely if detect returned zero video files. When the corpus has video or audio, see references/transcribe.md to transcribe them to text first, then treat the transcripts as doc files in Step 3.

Step 3 - Extract entities and relationships

Before starting: note whether --mode deep was given. You must pass DEEP_MODE=true to every subagent in Step B2 if it was. Track this from the original invocation - do not lose it.

This step has two parts: structural extraction (deterministic, free) and semantic extraction (LLM, costs tokens).

Before dispatching subagents: check whether GEMINI_API_KEY or GOOGLE_API_KEY is set. If neither is set, print this one-liner to the user:

Tip: set GEMINI_API_KEY or GOOGLE_API_KEY to use Gemini for semantic extraction (pip install 'graphifyy[gemini]').

Print it once, then continue. If GEMINI_API_KEY or GOOGLE_API_KEY IS set, use graphify.llm.extract_corpus_parallel(files, backend="gemini") for semantic extraction instead of dispatching Claude subagents. The default Gemini model is gemini-3-flash-preview; set GRAPHIFY_GEMINI_MODEL or pass --model in headless CLI flows to override it.

No other API keys are read. If GEMINI_API_KEY/GOOGLE_API_KEY are unset, fall straight through to Claude Code subagent dispatch (Part B below) — the host session itself is the LLM. graphify does not read ANTHROPIC_API_KEY, OPENAI_API_KEY, or any other provider key from the environment. If a host agent prompts the user for ANTHROPIC_API_KEY to run extraction, that prompt is a misread of this skill — ignore it and dispatch subagents as written.

Run Part A (AST) and Part B (semantic) in parallel. Dispatch all semantic subagents AND start AST extraction in the same message. Both can run simultaneously since they operate on different file types. Merge results in Part C as before.

Note: Parallelizing AST + semantic saves 5-15s on large corpora. AST is deterministic and fast; start it while subagents are processing docs/papers.

Part A - Structural extraction for code files

For any code files detected, run AST extraction in parallel with Part B subagents:

$(cat graphify-out/.graphify_python) -c "
import sys, json
from graphify.extract import collect_files, extract
from pathlib import Path
import json

code_files = []
detect = json.loads(Path('graphify-out/.graphify_detect.json').read_text(encoding=\"utf-8\"))
for f in detect.get('files', {}).get('code', []):
    code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)])

if code_files:
    result = extract(code_files, cache_root=Path('INPUT_PATH'))
    Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\")
    print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges')
else:
    Path('graphify-out/.graphify_ast.json').write_text(json.dumps({'nodes':[],'edges':[],'input_tokens':0,'output_tokens':0}, ensure_ascii=False), encoding=\"utf-8\")
    print('No code files - skipping AST extraction')
"

Part B - Semantic extraction (parallel subagents)

Semantic-extraction subagent dispatch moved to references/semantic-extraction.md (issue #2907 progressive-disclosure budget).

Part C - Merge AST + semantic into final extraction

$(cat graphify-out/.graphify_python) -c "
import sys, json
from pathlib import Path

ast = json.loads(Path('graphify-out/.graphify_ast.json').read_text(encoding=\"utf-8\"))
sem = json.loads(Path('graphify-out/.graphify_semantic.json').read_text(encoding=\"utf-8\"))

# Merge: AST nodes first, semantic nodes deduplicated by id
seen = {n['id'] for n in ast['nodes']}
merged_nodes = list(ast['nodes'])
for n in sem['nodes']:
    if n['id'] not in seen:
        merged_nodes.append(n)
        seen.add(n['id'])

merged_edges = ast['edges'] + sem['edges']
merged_hyperedges = sem.get('hyperedges', [])
merged = {
    'nodes': merged_nodes,
    'edges': merged_edges,
    'hyperedges': merged_hyperedges,
    'input_tokens': sem.get('input_tokens', 0),
    'output_tokens': sem.get('output_tokens', 0),
}
Path('graphify-out/.graphify_extract.json').write_text(json.dumps(merged, indent=2, ensure_ascii=False), encoding=\"utf-8\")
total = len(merged_nodes)
edges = len(merged_edges)
print(f'Merged: {total} nodes, {edges} edges ({len(ast[\"nodes\"])} AST + {len(sem[\"nodes\"])} semantic)')
"

Step 4 - Build graph, cluster, analyze, generate outputs

Before starting: the code blocks below pass directed=IS_DIRECTED to build_from_json(). Replace IS_DIRECTED with True if --directed was given (builds a DiGraph preserving edge direction source→target), otherwise False (the default undirected Graph). Substitute it the same way you substitute INPUT_PATH — do not leave the literal IS_DIRECTED in the code.

mkdir -p graphify-out
$(cat graphify-out/.graphify_python) -c "
import sys, json
from graphify.build import build_from_json
from graphify.cluster import cluster, score_all
from graphify.analyze import god_nodes, surprising_connections, suggest_questions
from graphify.report import generate
from graphify.export import to_json
from pathlib import Path

extraction = json.loads(Path('graphify-out/.graphify_extract.json').read_text(encoding=\"utf-8\"))
detection  = json.loads(Path('graphify-out/.graphify_detect.json').read_text(encoding=\"utf-8\"))

# root= mirrors the --update runbook (#1361): relativize source_file to the same
# base so the full build and incremental --update never drift apart on re-extract.
G = build_from_json(extraction, root='INPUT_PATH', directed=IS_DIRECTED)
# Guard BEFORE any write: an empty extraction must not clobber a good graph.json /
# GRAPH_REPORT.md / analysis sidecar. Check immediately after build (#1392).
if G.number_of_nodes() == 0:
    print('ERROR: Graph is empty - extraction produced no nodes.')
    print('Possible causes: all files were skipped, binary-only corpus, or extraction failed.')
    raise SystemExit(1)
communities = cluster(G)
cohesion = score_all(G, communities)
tokens = {'input': extraction.get('input_tokens', 0), 'output': extraction.get('output_tokens', 0)}
gods = god_nodes(G)
surprises = surprising_connections(G, communities)
labels = {cid: 'Community ' + str(cid) for cid in communities}
# Placeholder questions - regenerated with real labels in Step 5
questions = suggest_questions(G, communities, labels)

# Export FIRST and honor the #479 shrink-guard: to_json returns False (writing
# nothing) when the new graph is smaller than the existing graph.json. Only write
# GRAPH_REPORT.md + the analysis sidecar when the graph was actually written, so
# they never describe a graph that graph.json doesn't contain (#1392).
wrote = to_json(G, communities, 'graphify-out/graph.json')
if not wrote:
    print('ERROR: refused to shrink graphify-out/graph.json (existing graph has more nodes; #479).')
    print('If this shrink is intentional (you deleted files), re-run a full build with --force.')
    raise SystemExit(1)
report = generate(G, communities, cohesion, labels, gods, surprises, detection, tokens, 'INPUT_PATH', suggested_questions=questions)
Path('graphify-out/GRAPH_REPORT.md').write_text(report, encoding=\"utf-8\")
analysis = {
    'communities': {str(k): v for k, v in communities.items()},
    'cohesion': {str(k): v for k, v in cohesion.items()},
    'gods': gods,
    'surprises': surprises,
    'questions': questions,
}
Path('graphify-out/.graphify_analysis.json').write_text(json.dumps(analysis, indent=2, ensure_ascii=False), encoding=\"utf-8\")
print(f'Graph: {G.number_of_nodes()} nodes, {G.number_of_edges()} edges, {len(communities)} communities')
"

If this step prints ERROR: Graph is empty, stop and tell the user what happened - do not proceed to labeling or visualization.

Replace INPUT_PATH with the actual path.

Step 4.5 - Graph health check (read-only integrity gate)

A non-destructive diagnostic on the extraction, before labeling. It surfaces edge collapse, dangling/missing endpoints, and self-loops — the silent-corruption modes of incremental updates and AST/LLM id mismatches. Read-only; never aborts.

$(cat graphify-out/.graphify_python) -c "
import json
from pathlib import Path
from graphify.diagnostics import diagnose_extraction, format_diagnostic_report

extraction = json.loads(Path('graphify-out/.graphify_extract.json').read_text(encoding=\"utf-8\"))
summary = diagnose_extraction(extraction, directed=IS_DIRECTED, root='INPUT_PATH')
print(format_diagnostic_report(summary))
flags = [f'{summary[k]} {label}' for k, label in (
    ('dangling_endpoint_edges', 'dangling-endpoint edges'),
    ('missing_endpoint_edges', 'missing-endpoint edges'),
    ('self_loop_edges', 'self-loop edges'),
    ('directed_same_endpoint_collapsed_edges', 'collapsed (directed) edges'),
    ('undirected_same_endpoint_collapsed_edges', 'collapsed (undirected) edges'),
) if summary.get(k, 0)]
print('GRAPH HEALTH WARNING: ' + '; '.join(flags) + ' - graph may be incomplete/corrupt.' if flags else 'Graph health: OK (no dangling/missing/collapsed edges).')
"

Substitute IS_DIRECTED and INPUT_PATH as in Step 4. If a GRAPH HEALTH WARNING prints, surface it in the final summary (do not abort — the graph is still usable, but the integrity issue must be visible, per the Honesty Rules).

Step 5 - Label communities

Read graphify-out/.graphify_analysis.json. For each community key, look at its node labels and write a 2-5 word plain-language name (e.g. "Attention Mechanism", "Training Pipeline", "Data Loading").

Then regenerate the report and save the labels for the visualizer:

$(cat graphify-out/.graphify_python) -c "
import sys, json
from graphify.build import build_from_json
from graphify.cluster import score_all
from graphify.analyze import god_nodes, surprising_connections, suggest_questions
from graphify.report import generate
from pathlib import Path

extraction = json.loads(Path('graphify-out/.graphify_extract.json').read_text(encoding=\"utf-8\"))
detection  = json.loads(Path('graphify-out/.graphify_detect.json').read_text(encoding=\"utf-8\"))
analysis   = json.loads(Path('graphify-out/.graphify_analysis.json').read_text(encoding=\"utf-8\"))

# root= as in Step 4 / the --update runbook (#1361) — same base for node-key parity.
G = build_from_json(extraction, root='INPUT_PATH', directed=IS_DIRECTED)
communities = {int(k): v for k, v in analysis['communities'].items()}
cohesion = {int(k): v for k, v in analysis['cohesion'].items()}
tokens = {'input': extraction.get('input_tokens', 0), 'output': extraction.get('output_tokens', 0)}

# LABELS - replace these with the names you chose above
labels = LABELS_DICT

# Regenerate questions with real community labels (labels affect question phrasing)
questions = suggest_questions(G, communities, labels)

report = generate(G, communities, cohesion, labels, analysis['gods'], analysis['surprises'], detection, tokens, 'INPUT_PATH', suggested_questions=questions)
Path('graphify-out/GRAPH_REPORT.md').write_text(report, encoding=\"utf-8\")
Path('graphify-out/.graphify_labels.json').write_text(json.dumps({str(k): v for k, v in labels.items()}, ensure_ascii=False), encoding=\"utf-8\")
print('Report updated with community labels')
"

Replace LABELS_DICT with the actual dict you constructed (e.g. {0: "Attention Mechanism", 1: "Training Pipeline"}). Replace INPUT_PATH with the actual path.

Step 6 - Generate Obsidian vault (opt-in) + HTML

Generate HTML always (unless --no-viz). Obsidian vault only if --obsidian was explicitly given — skip it otherwise, it generates one file per node.

If --obsidian was given:

  • If --obsidian-dir <path> was also given, pass it via --dir. Otherwise defaults to graphify-out/obsidian.
graphify export obsidian
# or with custom dir: graphify export obsidian --dir ~/vaults/my-project

Generate the HTML graph (always, unless --no-viz):

graphify export html  # auto-aggregates to community view if graph > 5000 nodes
# or: graphify export html --no-viz

Steps 6b-8 - Wiki, Neo4j, FalkorDB, SVG, GraphML, MCP, benchmark (only on their flags)

These run only when their flag is present (--wiki, --neo4j/--neo4j-push, --falkordb/--falkordb-push, --svg, --graphml, --mcp) or, for the token-reduction benchmark, when total_words exceeds 5,000. A default run with no export flags skips all of them. See references/exports.md for each one. Run any --wiki export before Step 9 cleanup so .graphify_labels.json is still available.


Step 9 - Save manifest, update cost tracker, clean up, and report

Manifest save, cost-tracker update, cleanup, and reporting moved to references/manifest-and-cleanup.md (issue #2907 progressive-disclosure budget).

Interpreter guard for subcommands

Before running any subcommand below (--update, --cluster-only, query, path, explain, add), check that .graphify_python exists. If it's missing (e.g. user deleted graphify-out/), re-resolve the interpreter first:

if [ ! -f graphify-out/.graphify_python ]; then
    GRAPHIFY_BIN=$(which graphify 2>/dev/null)
    if [ -n "$GRAPHIFY_BIN" ]; then
        PYTHON=$(head -1 "$GRAPHIFY_BIN" | tr -d '#!')
        case "$PYTHON" in *[!a-zA-Z0-9/_.-]*) PYTHON="python3" ;; esac
    else
        PYTHON="python3"
    fi
    mkdir -p graphify-out
    "$PYTHON" -c "import sys; open('graphify-out/.graphify_python', 'w', encoding='utf-8').write(sys.executable)"
fi

For --update and --cluster-only

Both are non-default subcommands. --update re-extracts only new or changed files; --cluster-only reruns clustering on the existing graph. See references/update.md for both flows.


For /graphify query

When graphify-out/graph.json already exists and the user asks a question about the corpus, answer from the graph rather than rebuilding it:

graphify query "<question>"

Before traversal, expand the question against the graph's own vocabulary so a wording mismatch does not collapse the answer to noise. If the graphify query CLI is unavailable, fall back to an inline NetworkX traversal of graphify-out/graph.json. Answer using only what the graph output contains, and quote source_location when citing a specific fact. For that vocab-expansion step, the BFS/DFS traversal modes, the --budget cap, the NetworkX fallback, save-result feedback, and the /graphify path and /graphify explain flows, see references/query.md.


For /graphify add and --watch

Neither is part of the default build. When the user runs /graphify add <url> to fetch a URL into the corpus, or passes --watch to auto-rebuild on file changes, see references/add-watch.md.


For the commit hook and native CLAUDE.md integration

When the user asks to install the post-commit auto-rebuild hook or wire graphify into a project's CLAUDE.md, see references/hooks.md.


Troubleshooting

PowerShell 5.1: Vertical scrolling stops working

If vertical scrolling breaks in PowerShell after running graphify, this is caused by ANSI escape sequences from the graspologic library. Graphify v0.3.10+ suppresses this output, but if you still see the issue:

  1. Upgrade graphify: pip install --upgrade graphifyy
  2. Use Windows Terminal instead of the legacy PowerShell console — Windows Terminal handles ANSI codes correctly
  3. Reset your terminal: close and reopen PowerShell
  4. Skip graspologic: uninstall it (pip uninstall graspologic) and graphify will fall back to NetworkX's built-in Louvain algorithm, which produces no ANSI output

Honesty Rules

  • Never invent an edge. If unsure, use AMBIGUOUS.
  • Never skip the corpus check warning.
  • Always show token cost in the report.
  • Never hide cohesion scores behind symbols - show the raw number.
  • Never run HTML viz on a graph with more than 5,000 nodes without warning the user.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.