Skip to content
Documentation
Skill

/filetree

Use when running /filetree:init or /filetree:update — the shared rules those commands load before generating or syncing FILETREE.md. Not invoked directly.

BOOST
From plugin
filetree
1621 skill4 commands1 hook
Install
$ npx -y skills add nekocode/filetree-skill --skill filetree --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/filetree

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when running /filetree:init or /filetree:update — the shared rules those commands load before generating or syncing FILETREE.md. Not invoked directly.

SKILL.md

filetree.SKILL.md
name: filetree
description: >
  Use when running /filetree:init or /filetree:update — the shared rules those
  commands load before generating or syncing FILETREE.md. Not invoked directly.
license: MIT

Filetree Skill — Shared Rules

Cross-cutting rules used by `/filetree:init` and `/filetree:update`. The commands themselves contain step-by-step flows; this file holds rules that apply across modes so they're maintained in one place.

`/filetree:lint` is read-only script invocation and does not need these rules.

---

Summary style

One line, max 25 words, describes what the file is FOR (its role / purpose). Not what it implements internally.

  • Good: "JWT auth middleware; parses token from request header and injects user_id into context"
  • Bad: "Defines AuthMiddleware class with __init__ and __call__ methods"
  • Bad: "Handles auth" (too vague)

Present tense. No marketing words. For the language to write summaries in, see "Summary language" below — never pick per-file.

---

Summary language

One run, ONE language. Every summary in the manifest — and the command's own narration — uses it. Without a single anchor, parallel sub-agents each guess and the manifest ends up mixing Chinese and English.

The command resolves the canonical language ONCE, up front, by this priority:

0. `config.language` from the `todo` output (set when `.filetree.json` pins `language`). When present it is authoritative — skip the rest of the chain. 1. Else the dominant natural language of `CLAUDE.md` / `AGENTS.md` (the agent contract — most authoritative). 2. Else `README` (any localized variant). 3. Else (`/filetree:update` only) the dominant language of existing manifest entries. 4. Else English.

Then it passes that one language verbatim into EVERY sub-agent prompt ("Write all summaries in <language>"). Sub-agents never re-detect; they run in parallel and would diverge if left to choose.

---

UNCHANGED bias (for /filetree:update ONLY)

> **Scope.** This entire section applies to `/filetree:update` only. During `/filetree:init` the manifest starts empty, so there is no old summary to keep — `UNCHANGED` has nothing to refresh and `apply` will drop it. In init, every file gets a real summary. Do not apply this bias to init sub-tasks.

**Why this matters.** Hash changes trigger the LLM, but most code changes (typos, refactors, comments, small additions) don't change a file's purpose. Outputting `"UNCHANGED"` lets `cmd_apply` refresh just the hash and keep the existing summary — the manifest itself carries the memory of "I already reviewed this version". In a healthy update run, 80%+ of `changed` items should resolve to UNCHANGED. Writing a fresh 25-word summary when the old one still fits wastes ~100x more tokens than a 4-byte `"UNCHANGED"` reply.

**Decision rule.** You have: old summary, old hash, new hash, and the file's new content (prefer reading the `git diff` over the full file — diff is far denser per token and is all you need for purpose-level judgement). If the diff comes back EMPTY (the change was already committed, so working tree == HEAD), fall back to reading the file — the hash moved, so judging purpose from a blank diff would falsely yield UNCHANGED.

Output `"UNCHANGED"` if the old summary still describes the file's PURPOSE. Refactors, renames, bug fixes, test additions, formatting, comment changes, small additions — these almost always leave the purpose intact.

Output a new summary string only if:

  • A major new feature has been added that meaningfully expands purpose
  • A previously central concern has been removed
  • The file has been substantially rewritten for a different goal
  • **The old summary is in the wrong language** (not the run's canonical language — see "Summary language"). Rewrite it in the target language even if the purpose is unchanged; this is how a legacy mixed-language manifest converges — gradually, as each file's hash changes and re-enters the work plan. Language mismatch ALWAYS overrides the UNCHANGED bias.

When in doubt (and the language already matches), output UNCHANGED.

Rationalizations — every one resolves to UNCHANGED

The pressure to "be thorough" pushes toward rewriting. Each excuse below is a trap; the right answer is UNCHANGED.

| Excuse | Reality | |--------|---------| | "The diff is large, so I should rewrite" | Diff size ≠ purpose change. A 500-line refactor with the same role is UNCHANGED. | | "Let me polish the old summary while I'm here" | Polishing burns ~100x the tokens of UNCHANGED and isn't an exception. Only purpose change or wrong language qualifies. | | "It's slightly more accurate now" | "Slightly better wording" is not "purpose changed". UNCHANGED. | | "I'm not sure the purpose changed" | Not sure = it didn't. UNCHANGED. | | "New function added, must re-describe" | A helper added to the same role doesn't expand purpose. UNCHANGED. |

Red flags — STOP, you're about to waste tokens

  • About to write a summary that says the same thing as `old_summary` in new words
  • Justifying a rewrite by how much the code changed rather than whether the role changed
  • "Improving" or "tidying" a summary whose language already matches
  • Reading the full file when the `git diff` already answers the purpose question

**All of these mean: output `"UNCHANGED"`.**

---

Symlinks

Some `added` / `changed` items carry a `symlink_target` field. For those: **do not Read the file** — a Read follows the link to the target's content (wasteful, and fails on a broken link). Write exactly `symlink → <target>` using the supplied `symlink_target`; do not infer a role you can't see. The script already hashes symlinks correctly from the link string.

---

Processing the work plan (`todo --split`)

Always run `todo --split` (the script chunks the LLM work and writes it to files, so you never count, truncate, or hand-split). Output:

{ "stats": {...}, "removed": [...], "renamed": [...],
  "manifest_exists": true,
  "config": {"manifest_path": "FILET
Read more
Ships withfiletree

A Claude Code plugin that maintains FILETREE.md — a one-line description per file with content hashes for staleness detection. Lets the LLM grasp repo layout in a few hundred tokens before touching code.

Get the whole plugin
Stats
162
Stars
13
Forks
Maintained
Maintenance
Python
Language
3mo ago
Last commit
4mo ago
Created
2h ago
Added

Repo: nekocode/filetree-skill