Skip to main content

understand

Analyze a codebase to produce an interactive knowledge graph for understanding architecture, components, and relationships

Jump to install

Source facts

Repository
Egonex-AI/Understand-Anything
Last source activity
September 11, 2026 at 12:54
Detected SKILL.md language
English
Stars
83,219
Forks
7,018

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
54 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
understand
description
Analyze a codebase to produce an interactive knowledge graph for understanding architecture, components, and relationships
argument-hint
["[path] [--full|--auto-update|--no-auto-update|--review|--language <lang>|--exclude <patterns>]"]
# /understand Analyze the current codebase and produce a `knowledge-graph.json` file in the project's data directory (`.ua/`, or the legacy `.understand-anything/` when it already exists). This file powers the interactive dashboard for exploring the project's architecture. ## Options - `$ARGUMENTS` may contain: - `--full` — Force a full rebuild, ignoring any existing graph - `--auto-update` — Enable automatic graph updates on commit (writes `autoUpdate: true` to `$UA_DIR/config.json`) - `--no-auto-update` — Disable automatic graph updates (writes `autoUpdate: false` to `$UA_DIR/config.json`) - `--review` — Run full LLM graph-reviewer instead of inline deterministic validation - `--language <lang>` — Generate all textual content (summaries, descriptions, tags, titles, languageNotes, languageLesson) in the specified language. Accepts ISO 639-1 codes (`zh`, `ja`, `ko`, `en`, `es`, `fr`, `de`, etc.) or friendly names (`chinese`, `japanese`, `korean`, `english`, `spanish`, etc.). Locale variants supported: `zh-TW`, `zh-HK`, etc. Defaults to `en` (English). Stores preference in `$UA_DIR/config.json` for consistency across incremental updates. - `--exclude <patterns>` — Comma-separated glob patterns for additional files/directories to exclude from analysis (e.g., `--exclude "tests/*,docs/*"`). These patterns take highest priority over built-in defaults and `.understandignore` rules. Supports gitignore syntax including `!` negation. - A directory path (e.g. `/path/to/repo` or `../other-project`) — Analyze the given directory instead of the current working directory --- ## Progress Reporting Throughout execution, report progress to the user at each phase transition and during batch processing. This keeps users informed on large codebases where analysis can take a long time. - **Phase transitions:** At the start of each phase, print a status line: > `[Phase N/7] <phase name>...` > > Example: `[Phase 2/7] Analyzing files (12 batches)...` - **Batch progress:** During Phase 2, report each batch with its index and total: > `Analyzing batch X/N (files: foo.ts, bar.ts, ...)` (list up to 3 filenames, then `...` if more) - **Phase completion:** When a phase finishes, briefly confirm: > `Phase N complete. <one-line summary of result>` > > Example: `Phase 1 complete. Found 247 files across 3 languages.` --- ## Phase 0 — Pre-flight Determine whether to run a full analysis or incremental update. 1. **Resolve `PROJECT_ROOT`:** - Parse `$ARGUMENTS` for a non-flag token (any argument that does not start with `--`). If found, treat it as the target directory path. - If the path is relative, resolve it against the current working directory. - Verify the resolved path exists and is a directory (run `test -d <path>`). If it does not exist or is not a directory, report an error to the user and **STOP**. - Set `PROJECT_ROOT` to the resolved absolute path. - If no directory path argument is found, set `PROJECT_ROOT` to the current working directory. - **Worktree redirect.** If `PROJECT_ROOT` is inside a git worktree (not the main checkout), redirect output to the main repository root. Worktrees managed by Claude Code are ephemeral — the data directory (`.ua/`, or legacy `.understand-anything/`) written there is destroyed when the session ends, taking the knowledge graph with it (issue #133). Detect a worktree by comparing `git rev-parse --git-dir` against `git rev-parse --git-common-dir`; in a normal checkout or submodule they resolve to the same path, in a worktree they differ and the parent of `--git-common-dir` is the main repo root. ```bash COMMON_DIR=$(git -C "$PROJECT_ROOT" rev-parse --git-common-dir 2>/dev/null) GIT_DIR=$(git -C "$PROJECT_ROOT" rev-parse --git-dir 2>/dev/null) if [ -n "$COMMON_DIR" ] && [ -n "$GIT_DIR" ]; then COMMON_ABS=$(cd "$PROJECT_ROOT" && cd "$COMMON_DIR" 2>/dev/null && pwd -P) GIT_ABS=$(cd "$PROJECT_ROOT" && cd "$GIT_DIR" 2>/dev/null && pwd -P) if [ -n "$COMMON_ABS" ] && [ "$COMMON_ABS" != "$GIT_ABS" ]; then MAIN_ROOT=$(dirname "$COMMON_ABS") if [ -d "$MAIN_ROOT" ] && [ "${UNDERSTAND_NO_WORKTREE_REDIRECT:-0}" != "1" ]; then echo "[understand] Detected git worktree at $PROJECT_ROOT" echo "[understand] Redirecting output to main repo root: $MAIN_ROOT" echo "[understand] (Set UNDERSTAND_NO_WORKTREE_REDIRECT=1 to keep PROJECT_ROOT as the worktree.)" PROJECT_ROOT="$MAIN_ROOT" fi fi fi ``` Set `UNDERSTAND_NO_WORKTREE_REDIRECT=1` if you intentionally want a per-worktree graph (rare — most users want the redirect). 1.5. **Ensure the plugin is built.** Later phases invoke Node scripts that import `@understand-anything/core`. On a fresh install `packages/core/dist/` does not exist yet — build once. **Important:** do **not** assume the plugin root is simply two directories above the skill path string. In many installations `~/.agents/skills/understand` is a symlink into the real plugin checkout. Prefer runtime-provided plugin roots first (for Claude), then fall back to universal symlinks, skill symlink resolution, and common clone-based install paths. Resolve the plugin root like this: ```bash SKILL_REAL=$(realpath ~/.agents/skills/understand 2>/dev/null || readlink -f ~/.agents/skills/understand 2>/dev/null || echo "") SELF_RELATIVE=$([ -n "$SKILL_REAL" ] && cd "$SKILL_REAL/../.." 2>/dev/null && pwd || echo "") COPILOT_SKILL_REAL=$(realpath ~/.copilot/skills/understand 2>/dev/null || readlink -f ~/.copilot/skills/understand 2>/dev/null || echo "") COPILOT_SELF_RELATIVE=$([ -n "$COPILOT_SKILL_REAL" ] && cd "$COPILOT_SKILL_REAL/../.." 2>/dev/null && pwd || echo "") PLUGIN_ROOT="" for candidate in \ "${CLAUDE_PLUGIN_ROOT}" \ "$HOME/.understand-anything-plugin" \ "$SELF_RELATIVE" \ "$COPILOT_SELF_RELATIVE" \ "$HOME/.codex/understand-anything/understand-anything-plugin" \ "$HOME/.opencode/understand-anything/understand-anything-plugin" \ "$HOME/.pi/understand-anything/understand-anything-plugin" \ "$HOME/understand-anything/understand-anything-plugin"; do if [ -n "$candidate" ] && [ -f "$candidate/package.json" ] && [ -f "$candidate/pnpm-workspace.yaml" ]; then PLUGIN_ROOT="$candidate" break fi done if [ -z "$PLUGIN_ROOT" ]; then echo "Error: Cannot find the understand-anything plugin root." echo "Checked:" echo " - ${CLAUDE_PLUGIN_ROOT:-<unset CLAUDE_PLUGIN_ROOT>}" echo " - $HOME/.understand-anything-plugin" echo " - ${SELF_RELATIVE:-<unresolved path derived from ~/.agents/skills/understand>}" echo " - ${COPILOT_SELF_RELATIVE:-<unresolved path derived from ~/.copilot/skills/understand>}" echo " - $HOME/.codex/understand-anything/understand-anything-plugin" echo " - $HOME/.opencode/understand-anything/understand-anything-plugin" echo " - $HOME/.pi/understand-anything/understand-anything-plugin" echo " - $HOME/understand-anything/understand-anything-plugin" echo "Make sure the plugin is installed correctly." exit 1 fi if [ ! -f "$PLUGIN_ROOT/packages/core/dist/index.js" ]; then cd "$PLUGIN_ROOT" && (pnpm install --frozen-lockfile 2>/dev/null || pnpm install) && pnpm --filter @understand-anything/core build fi ``` If `pnpm` is missing, report to the user: "Install Node.js ≥ 22 and pnpm ≥ 10, then re-run `/understand`." 1.7. **Resolve the data directory `$UA_DIR`.** All Understand-Anything artifacts live in the project's data directory. Resolve it once, now that `$PROJECT_ROOT` is known, and reuse `$UA_DIR` for every read and write in later phases: ```bash UA_DIR="$PROJECT_ROOT/$([ -d "$PROJECT_ROOT/.understand-anything" ] && echo .understand-anything || echo .ua)" ``` This keeps the legacy `.understand-anything/` directory when it already exists (existing projects keep working with no migration) and uses the new `.ua/` otherwise. Because each phase may run in a fresh shell, treat `$UA_DIR` — like `$PROJECT_ROOT` — as a value you carry forward and substitute; re-resolve it with the line above if a later command block needs it in a new shell. 2. Get the current git commit hash: ```bash git rev-parse HEAD ``` 3. Create the intermediate and temp output directories: ```bash mkdir -p "$UA_DIR/intermediate" mkdir -p "$UA_DIR/tmp" ``` 3.1. **Purge stale trash dirs.** Phase 7 cleanup `mv`s scratch dirs into `.trash-<timestamp>/` rather than `rm -rf`ing them directly (see issue #301), so that destructive-action gates on hardened hosts don't trip on just-created paths. Reclaim the space here once the trash is older than 7 days — by this point any freshness-window check has long since stopped caring about those dirs: ```bash find "$UA_DIR/" -maxdepth 1 -type d -name '.trash-*' -mtime +7 -exec rm -rf {} + 2>/dev/null || true ``` 3.5. **Auto-update configuration:** - If `--auto-update` is in `$ARGUMENTS`: write `{"autoUpdate": true}` to `$UA_DIR/config.json` - If `--no-auto-update` is in `$ARGUMENTS`: write `{"autoUpdate": false}` to `$UA_DIR/config.json` - These flags only set the config — analysis proceeds normally regardless. 3.6. **Language configuration:** - Parse `$ARGUMENTS` for `--language <lang>` flag. If found, extract the language code. - **Language code normalization:** Map friendly names to ISO codes: - `chinese` → `zh`, `japanese` → `ja`, `korean` → `ko`, `english` → `en`, `spanish` → `es`, `french` → `fr`, `german` → `de`, `portuguese` → `pt`, `russian` → `ru`, `arabic` → `ar`, etc. - Locale variants: `zh-TW`, `zh-HK`, `zh-CN`, `pt-BR`, etc. are preserved as-is. - If `--language` is NOT specified: - **Stored preference wins.** If `$UA_DIR/config.json` has an `outputLanguage` field, set `$OUTPUT_LANGUAGE` to it and skip the rest. - **Otherwise detect (first run only).** Infer the predominant language of the user's conversation as an ISO 639-1 code (`$DETECTED_LANG`). If it is `en` or cannot be confidently determined, set `$OUTPUT_LANGUAGE=en` and proceed silently — no prompt (English users see no change). - **If `$DETECTED_LANG` ≠ `en`, confirm once before analyzing:** tell the user you detected `<language>` and ask whether to generate all content in it; they press Enter/"yes" to accept, or type another language code/name to override (normalize via the friendly-name map above). If running non-interactively (no reply possible), skip the wait, use `$DETECTED_LANG`, and print a one-line notice instead of blocking. - **Persist** the resolved `$OUTPUT_LANGUAGE` (including `en`) into `config.json` so it never re-prompts for this project. - If `--language` IS specified: - Update `$UA_DIR/config.json` with the new language: merge `{"outputLanguage": "<lang>"}` into existing config. - Store as `$OUTPUT_LANGUAGE` for use throughout all phases. - **Language directive template:** Store as `$LANGUAGE_DIRECTIVE`: ```markdown > **Language directive**: Generate all textual content (summaries, descriptions, tags, titles, languageNotes, languageLesson) in **{language}**. Maintain technical accuracy while using natural, native-level phrasing in the target language. Keep technical terms in English when no standard translation exists (e.g., "middleware", "hook", "barrel"). ``` 3.7. **Exclude patterns:** - Parse `$ARGUMENTS` for `--exclude <patterns>` flag. If found, extract the comma-separated patterns string. - Split on commas, trim whitespace from each pattern, and filter out empty entries. - Store the patterns as `$EXCLUDE_PATTERNS` (comma-joined for passing to downstream scripts: `"tests/*,docs/*"`). - These patterns take highest priority — they are applied on top of default patterns and `.understandignore` rules. Use `!` prefix to force-include files that would otherwise be excluded. - Incremental preparation re-scans the current inventory, so newly supplied exclusions take effect immediately and remove any previously analyzed files they now cover. 4. **Check for subdomain knowledge graphs to merge:** List all `*knowledge-graph*.json` files in `$UA_DIR/` **excluding** `knowledge-graph.json` itself (e.g. `frontend-knowledge-graph.json`, `backend-knowledge-graph.json`). If any subdomain graphs exist, run the merge script bundled with this skill (located next to this SKILL.md file — use the skill directory path, not the project root): ```bash python "<SKILL_DIR>/merge-subdomain-graphs.py" "$PROJECT_ROOT" ``` The script discovers subdomain graphs, loads the existing `knowledge-graph.json` as a base (if present), and merges everything into `knowledge-graph.json` (deduplicating nodes and edges). Report the merge summary to the user, then continue with the merged graph. 5. Check if `$UA_DIR/knowledge-graph.json` exists. If it does, read it. 6. Check if `$UA_DIR/meta.json` exists. If it does, read its `gitCommitHash` and store it as `$LAST_COMMIT_HASH`. 7. **Decision logic:** | Condition | Action | |---|---| | `--full` flag in `$ARGUMENTS` | Full analysis (all phases) | | No existing graph or meta | Full analysis (all phases) | | Existing graph + explicit `--exclude` | Run deterministic incremental preparation even when the commit hash is unchanged, so the new inventory rules take effect immediately | | `--review` flag + existing graph + unchanged commit hash | Skip to Phase 6 (review-only — reuse existing assembled graph) |
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub