agents-context-router
Split a bloated AGENTS.md / CLAUDE.md / README into a small always-loaded kernel plus task-routed wiki topics, loaded on demand by a zero-dependency script (`scripts/ai-context.py list|<topic>|check`) with byte budgets, so agents stop burning their context window on docs unrelate
Install
npx skills add https://github.com/runkids/my-skills/tree/main/agents-context-router
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install runkids-my-skills@llmmart
git clone https://github.com/runkids/my-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole runkids/my-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Agents context router
Coding agents load the root instruction file (AGENTS.md, CLAUDE.md) on every task. As a project ages it collects milestone logs, tool catalogs, runbooks and one-off lessons, until every task pays tens of KB of context for text it does not need. The fix is a kernel + router layout:
AGENTS.md kernel: rules every task needs + how to load more (≤ 8 KB)
docs/ai-context.json topic → sources (whole file or one exact heading); the single truth
scripts/ai-context.py list | <topic> | check (bundled with this skill)
wiki/README.md human router table (mirrors the JSON)
wiki/ai-context.md in-repo maintenance manual (works without this skill)
wiki/<topic pages>.md how-to / reference, one per task seam
wiki/history/*.md milestone logs, verbatim, never loaded by default
README.md humans: what it is, quickstart, doc map
An agent reads the kernel, picks the one topic that matches its task, and runs python3 scripts/ai-context.py <topic> to print only those sections, each marked <!-- path § heading -->, so it knows where to edit.
The layout also maintains itself once this skill is gone, because every piece lives in the repo:
- The kernel's "Keep the docs true" rule makes every agent, on every task, fix a stale doc in the same change that makes it stale.
wiki/ai-context.mdis the procedure.checkfails on orphans and budget overruns.- CI runs
check, so drift breaks the build instead of rotting quietly.
Leaving out any one of these four is how routed docs decay back into a pile.
Before you start, read references/gotchas.md. It lists the traps that make this refactor quietly lose content or route agents to the wrong text. It is short, and every item came from a real split.
Workflow
1. Measure
List every file an agent loads automatically: root and nested AGENTS.md/CLAUDE.md, and anything they @import. Also list the files agents are told to read "first". Record their byte sizes (wc -c). These numbers go in your final report as before and after.
Keep a backup of each original outside the repo (or rely on git), because step 3 moves text and you will diff against it.
2. Classify every section
Read the whole file and put each section into exactly one bucket:
| Bucket | Test | Goes to |
|---|---|---|
| Kernel | Would a wrong action happen on any task if the agent did not know this? Examples: hard limits, safety rules, language rules, where outputs may go, the rule that says when to load a topic. | AGENTS.md |
| Topic | Needed only when doing one kind of task: build and deploy, debugging, a subsystem, a tool catalog. | wiki/<topic>.md |
| History | Dated milestone logs, acceptance runs, "what we did in M3". | wiki/history/<milestone>.md |
| Human | Intro, screenshots, setup for people. | README.md |
Some text changes buckets. A behaviour rule learned the hard way (for example "if every job fails the same way, suspect our code before the site") is kernel. The procedure for acting on it is topic. A history section that is still the operating manual (a "Usage" section in a milestone log) stays in history, and a topic references its exact heading.
3. Move, then write
- Before moving any log, pull out the live rules hidden in it. Old logs often contain a rule that is still in force, written as an aside ("note: never run X on shared"). Once the log moves to history, no agent will ever see that rule again. Grep each log for imperative words in every language it uses, for example
never|always|must|do not|don't|warning|note:|avoid|forbidden|required. For each hit that is still valid, copy it as a one-line rule into the kernel (if it applies to every task) or into its topic. List every promoted rule in your report. - Create
wiki/history/and move milestone logs there verbatim, in their original language. Do not translate or summarise while moving. Verbatim moves are diffable and lose nothing. - Design topics around tasks the agent will be doing, not around the old file order. Aim for 5–12 topics. Each one gets a kebab-case name and a single "use when…" line. Ask: "an agent is about to do X; which pages must it see?"
- Write the topic pages. Move reference text and runbooks in, and cut the duplication the old file had.
- Rewrite
AGENTS.mdas the kernel. Start fromassets/AGENTS.kernel.md. It holds:- the one-paragraph purpose;
- the language rules, stated once;
- the always-apply rules, including Keep the docs true, verbatim or adapted;
- the hard limits;
- the load-context block with a topic table;
- the verification commands.
- Slim
README.mdto intro, quickstart and a doc map pointing towiki/README.md.
4. Wire the router
Copy
scripts/ai-context.pyfrom this skill to<repo>/scripts/ai-context.py. It resolves the repo root as the script's parent's parent.Write
docs/ai-context.jsonfromassets/ai-context.json. Use{"path": ...}for a whole page. Use{"path": ..., "heading": "Exact Heading Text"}to pull one section out of a bigger page, such as a single tool group from a catalog.Write
wiki/README.mdfromassets/wiki-README.md: the topic table for humans, plus a history index.Copy
assets/wiki-ai-context.mdtowiki/ai-context.mdand keep theai-contexttopic that points at it. This is the manual any future agent loads to maintain the router, with or without this skill. Adapt the paths if the repo uses other directories.Run
python3 scripts/ai-context.py check. It fails when:- a path or heading is missing, or a heading is ambiguous;
AGENTS.mdis over its budget;- a topic is over its budget;
- a topic is not named in
AGENTS.md; - there is an orphan: a wiki page no topic loads, a history file missing from the
wiki/README.mdindex, or a nestedAGENTS.mdno topic loads.
Fix the docs, not the caps. When a topic is too big, split it. When a page really is human-only, list it under
"unrouted"with a reason, and remove the template's example entry.
4b. Make drift fail the build
Wire check into whatever the repo already runs on every change. Use the one that exists; do not add new tooling:
| Repo has | Add |
|---|---|
package.json |
"docs:check": "python3 scripts/ai-context.py check", chained into test |
Makefile |
a docs-check target, made a prerequisite of test or check |
.pre-commit-config.yaml |
a local hook: entry: python3 scripts/ai-context.py check, pass_filenames: false |
.github/workflows/*.yml |
a step run: python3 scripts/ai-context.py check in the existing test job |
| none of these | add the command to the kernel's Verification block and say so in the report |
5. Point every agent at the kernel
- One file for every agent. Keep the rules in
AGENTS.md. If an agent you use does not readAGENTS.mdnatively, make its file a one-line pointer instead of a copy (for Claude Code, aCLAUDE.mdholding@AGENTS.md). Two full copies drift apart within a week. Check each agent's current docs or version, because native support is changing fast. - Skills and scripts are adapters. If the repo has skills, commands or prompts that restated the old docs, cut them down to workflow steps that say "load topic X". The rules live only in the kernel and the wiki.
- Other agents' stale paths. If other agents or sessions are working in the repo, tell them the docs moved and which topic replaces what, because their context still holds the old paths.
6. Verify and report
- Run
checkand show its output. - Run
ai-context.py <topic>for two or three topics, and read the output as an agent would. Can you do the task from this alone? - Grep for links to old anchors and moved files, and fix them.
- Compare the byte totals between the backup and the new tree. A large drop in total bytes, not just kernel bytes, means content was lost rather than moved. Find out where it went.
Report in the user's language:
## Context split
- Always-loaded: <before> B → <after> B (<file list>)
- Topics: <n>; largest <name> <bytes> B; all under budget (check output below)
- Moved verbatim to wiki/history: <n> files
- Content kept: <total before> B → <total after> B (<explain any drop>)
- Adapters updated: <skills/CLAUDE.md/etc>
- Self-maintenance: kernel rule ✓, wiki/ai-context.md ✓, check in <CI/test/pre-commit> ✓
- Follow-ups: <e.g. translate zh pages, split topic X if it grows>
Maintaining it later
Upkeep is the job of the repo's own wiki/ai-context.md and the kernel rule, not this skill, so it happens on ordinary tasks too. When this skill is triggered for maintenance (for example "add this runbook", "check is failing" or "we finished M7"), load the ai-context topic and follow it:
- New knowledge: put it in the page for its topic. If no topic fits, add a page, map it in the JSON, add it to both tables and run
check. - New milestone: add
wiki/history/<m>.mdand one row in the history index. Nothing is added to the kernel unless it is a rule for every task. - Kernel near its budget: that is the signal to move something out, not to raise the cap.
- Orphan failure: map the page to a topic, index the history file, or, only if it is really human-only, list it under
"unrouted"with a reason.
Files (my-skills)
-
assets
-
AGENTS.kernel.md 2.4 KB
# AGENTS.md — <project> <One paragraph: what this repo is and its stack.> This file holds only the rules every task needs. Task details are loaded per topic, so the whole wiki never lands in one context. ## Language - Instruction files (this file, skills, wiki topic pages), code, identifiers, comments and commits: <English>. - Reply to the user in <language>. - Human docs (`README.md`, `wiki/history/`): <language>. Keep new milestone logs in the same language. ## Always Applies - **<Rule name>.** <A behaviour every task needs, with the one-line trigger for the topic that has the procedure, e.g. "If every run fails the same way, suspect our code first; load `debugging`."> - **Keep the docs true.** When a doc disagrees with the code, trust the code: verify, then fix the stale doc in the same task. When your change alters behaviour that a topic describes, update that topic page in the same change. Put a new lesson in the kernel as a one-line rule and in its topic as the procedure. Put a finished milestone in `wiki/history/` and add it to the index. Run `python3 scripts/ai-context.py check` after any doc change. The procedure is in the `ai-context` topic. - **Search before you edit, and change as little as possible.** Match the existing style. - **Helper files go in the repo.** Put helper scripts in `scripts/<area>/` and their state in `data/<area>/`. Never write them anywhere else. ## Hard Limits - <Things that must never happen: secrets, destructive commands, outputs outside allowed paths, ports, and so on.> ## Load Context Per Task ```sh python3 scripts/ai-context.py list # topics and when to pick them python3 scripts/ai-context.py <topic> # print only that topic's sections python3 scripts/ai-context.py check # validate paths, headings and byte budgets ``` | Topic | Use when | |---|---| | `<topic>` | <one line> | | `ai-context` | Adding, moving or splitting docs and topics; `check` failures | Pick the single closest topic. Load a second one only for a task that really crosses two seams. When no topic fits, read `wiki/README.md`. To add a topic: 1. Put the content in `wiki/`. 2. Map it in `docs/ai-context.json`. 3. List it in both tables. 4. Run `check`. If a topic goes over budget, split it rather than raising the cap. Skills are workflow adapters that load topics. They are not the source of truth. ## Verification ```sh <build/test/lint commands> python3 scripts/ai-context.py check # doc/topic changes ``` -
ai-context.json 991 B
{ "rootInstructions": "AGENTS.md", "budgets": { "rootInstructionsMaxBytes": 8192, "defaultTopicMaxBytes": 16384 }, "topics": { "build-deploy": { "description": "Repo layout, build and test commands, deploy procedure.", "sources": [ { "path": "wiki/build-and-deploy.md" } ] }, "debugging": { "description": "Something fails: triage order, logs, known failure codes.", "sources": [ { "path": "wiki/debugging.md" }, { "path": "wiki/tools.md", "heading": "Failure codes" } ] }, "ai-context": { "description": "Maintain the doc router: add, move or split topics and pages, and fix check failures.", "sources": [ { "path": "wiki/ai-context.md" } ] } }, "unrouted": { "wiki/example-human-only.md": "Replace with real exceptions, each with a reason; delete this line if none." } } -
wiki-ai-context.md 2.9 KB
# AI Context Router This page is the in-repo manual for keeping the agent docs routed and true. It works without any skill installed. Load it with `python3 scripts/ai-context.py ai-context`. ## Layers 1. **Kernel:** root `AGENTS.md`, loaded by every agent on every task. It holds only rules that every task needs, plus the one-line triggers that say which topic to load. 2. **Scoped instructions:** optional nested `AGENTS.md` files for one package or app. Every one of them must be loaded by some topic. 3. **Topics:** `docs/ai-context.json` maps each topic to whole files or exact headings. `scripts/ai-context.py <topic>` prints only those sections. 4. **History:** `wiki/history/`, holding milestone logs in their original language. They are never loaded by default and are indexed in `wiki/README.md`. `docs/ai-context.json` is the single source of truth. The tables in `AGENTS.md` and `wiki/README.md` mirror it for discovery. ## When docs must change Update docs **in the same change** that makes them stale: | You did this | Update this | |---|---| | Changed behaviour a topic describes | That topic's page | | Found a doc that contradicts the code | Fix the doc, because the code wins; mention it in your handoff | | Learned a lesson the hard way | A one-line kernel rule plus the procedure in its topic | | Finished a milestone | Add `wiki/history/<milestone>.md` and one index row in `wiki/README.md` | | Added a new kind of recurring task | Add a new topic: page, JSON entry, and both tables | | Added a nested `AGENTS.md` | Map it in some topic | Leave volatile state out of the docs: progress counts, who is doing what this week, today's blocker. Those belong in the tracker. ## Adding or changing a topic 1. Put the content in `wiki/<page>.md`. A topic should be a recognizable kind of work, not a single ticket or file. 2. Map it in `docs/ai-context.json`. Reference exact headings for large pages. 3. Add a row to the topic tables in `AGENTS.md` and `wiki/README.md`. 4. Run `python3 scripts/ai-context.py check`, then render the topic and read it as an agent would. ## What check enforces - Every path stays inside the repo and exists, and every heading matches exactly once. - `AGENTS.md` and every topic stay under their byte budgets. Over budget means split the topic. Do not raise the cap. - Every topic is listed in `AGENTS.md`. - **No orphans:** - every `wiki/` page (history excluded) is loaded by some topic; - every history file is indexed in `wiki/README.md`; - every nested `AGENTS.md` is loaded by some topic. A deliberate exception goes under `"unrouted"` in the JSON, with a reason. `check` runs in CI, so drift fails the build instead of rotting quietly. ## Skills Skills are workflow adapters. They may call `ai-context.py`, run checks and shorten steps, but no rule may live only in a skill. With no skill installed, this page and the kernel must still be enough. -
wiki-README.md 803 B
# <project> Wiki Router The wiki holds background, procedures, reference tables and history, and no task needs all of it at once. Rules for every task are in the root `AGENTS.md`. The topic-to-section map is in `docs/ai-context.json`. Load a topic with `python3 scripts/ai-context.py <topic>`. ## Task routing | Topic | Use when | Main sources | |---|---|---| | `<topic>` | <one line> | `<page>.md` (the `<heading>` section) | | `ai-context` | Maintaining this router: add, move or split docs, fix `check` | `ai-context.md` | `docs/ai-context.json` is the only source of truth. This table is the human entry point. After changing topics, run `python3 scripts/ai-context.py check`. ## History (milestone logs; read on demand) | File | Contents | |---|---| | `history/<milestone>.md` | <one line> |
-
-
evals
-
evals.json 1.8 KB
{ "skill_name": "agents-context-router", "evals": [ { "id": 1, "prompt": "Our AGENTS.md is already 14 KB. Every agent task loads a lot of context, including milestone logs. Split it into a compact kernel and on-demand wiki topics. The repo is at ./tidepool.", "expected_output": "Kernel AGENTS.md under 8 KB with every hard limit kept (incl. the reset-db rule hidden in M3 and the ECONNREFUSED lesson); milestone logs moved verbatim to wiki/history in Chinese; docs/ai-context.json + scripts/ai-context.py with check passing; wiki/README.md router; volatile status removed; CLAUDE.md drift and deploy skill handled.", "files": ["fixtures/tidepool"] }, { "id": 2, "prompt": "CLAUDE.md and AGENTS.md in ./tidepool have drifted apart (different port range, different Friday rule). Consolidate them so Claude Code and Codex share one set of rules, and stop loading the whole milestone history every session. Keep the deploy skill working.", "expected_output": "Single source of rules in AGENTS.md; CLAUDE.md removed or a one-line @AGENTS.md pointer; drift conflicts surfaced to the user rather than silently resolved; history split out; deploy skill slimmed to load a topic instead of copying rules.", "files": ["fixtures/tidepool"] }, { "id": 3, "prompt": "Using the existing documentation structure in this repo (./routed), put the acceptance log notes/m5-draft.md and the new operations manual notes/retry-policy.md in the right places without bloating AGENTS.md.", "expected_output": "wiki/history/m5.md added (verbatim, zh) and indexed in wiki/README.md; retry policy added to an existing or new topic page mapped in docs/ai-context.json; any new topic listed in both tables; AGENTS.md not grown beyond a table row; check passes.", "files": ["fixtures/routed"] } ] } -
trigger-evals.json 3.7 KB
[ {"query": "our AGENTS.md in ~/code/payments-api is like 38KB now, half of it is old sprint notes and a giant table of every make target. codex keeps ignoring the rules at the top. can you restructure it so agents only load what they need per task?", "should_trigger": true}, {"query": "CLAUDE.md and AGENTS.md have drifted: one says ports 3000-3099 and the other says 3000-3050. I want Claude Code and Codex to share one set of rules, and I want to move the milestone acceptance logs out so they are not loaded every time.", "should_trigger": true}, {"query": "Every Claude Code session in this monorepo starts by reading a 60 KB README because AGENTS.md says 'read README first'. Tokens are burning before anyone types. Design me a better doc layout for agents with some kind of size limit we can enforce in CI.", "should_trigger": true}, {"query": "I keep appending post-mortems to AGENTS.md after every incident, it's getting unreadable. whats a sane way to keep the lessons but not make every agent read 12 incident writeups", "should_trigger": true}, {"query": "Our repo already uses docs/ai-context.json and scripts/ai-context.py to load topics on demand. I need to add a Kafka replay runbook and the M9 acceptance log; put them in the right places without bloating AGENTS.md.", "should_trigger": true}, {"query": "can you wiki-fy the agent instructions in ./infra? right now it's one flat CLAUDE.md with deploy steps, terraform gotchas, oncall runbook and a changelog all mixed together", "should_trigger": true}, {"query": "the context window fills up fast with gemini cli and cursor in this repo, I think it's the huge GEMINI.md + .cursorrules we copy-pasted from AGENTS.md. consolidate and slim these down", "should_trigger": true}, {"query": "python3 scripts/ai-context.py check is failing with 'deploy: 21003 B > 16384', what should I do? I was going to just bump the cap to 32k", "should_trigger": true}, {"query": "Our team skills in .claude/skills each restate half of AGENTS.md and they've drifted. Want a single source of truth where skills just point to the right doc section.", "should_trigger": true}, {"query": "set up progressive disclosure for our coding agent docs — tiny always-on rules file, then topic pages loaded on demand. repo is at ~/work/ledger", "should_trigger": true}, {"query": "run /init style thing: this new repo has no AGENTS.md at all, write me a starter one covering build, test, lint for a small Go CLI", "should_trigger": false}, {"query": "summarize what our README says about deployment, I just need the three commands to ship to staging", "should_trigger": false}, {"query": "my RAG chatbot stuffs 40 documents into the prompt and hits the context limit, how do I chunk and retrieve only the relevant ones?", "should_trigger": false}, {"query": "migrate our docs/ folder from plain markdown to a Docusaurus site with sidebar navigation and versioning", "should_trigger": false}, {"query": "this conversation is getting long, can you compact/summarize what we've done so far so I can paste it into a new session", "should_trigger": false}, {"query": "split src/utils.py (2400 lines) into separate modules by responsibility and fix the imports", "should_trigger": false}, {"query": "write a new Claude skill that generates release notes from git log between two tags", "should_trigger": false}, {"query": "add a rule to AGENTS.md: never run database migrations against prod without a ticket number in the commit message", "should_trigger": false}, {"query": "translate our Chinese README.md into English for the open-source release, keep the code blocks as-is", "should_trigger": false}, {"query": "our system prompt for the customer-support LLM is 9k tokens, can you tighten the wording without losing any policy?", "should_trigger": false} ]
-
-
references
-
gotchas.md 5.7 KB
# Gotchas Each item below is a trap from a real split of an 85 KB README plus AGENTS.md into a 5 KB kernel and 9 topics. Each one says why it matters. ## Content 1. **Keep "every task" and "important" apart.** The kernel test is whether an agent would do something wrong on an unrelated task without this line. Important but task-specific text, like the whole debugging runbook, belongs in a topic. The kernel keeps only the one-line trigger: "if every job fails the same way, suspect our code; load `debugging`". Without the trigger, the agent never loads the topic. 2. **Put lessons in the kernel as behaviour, not as story.** When a user corrects the agent ("it wasn't the site, our code was broken"), turn that into a one-line rule. The incident write-up goes to history. 3. **Move verbatim first, edit second.** Rewriting while moving is how paragraphs vanish. Move whole sections into the history and topic pages in the original language. Then prune duplicates in a separate pass, and compare total bytes against the backup at the end. 4. **Keep history in its original language.** Milestone logs are the evidence trail for humans, so translating them adds risk and helps nobody. Instruction pages that agents read can be English. Human docs can stay in the team's language. State the language rules once, in the kernel. 5. **Leave volatile state out of the docs.** Progress counts, "currently running batch", today's blocker: these belong in a state file or the tracker. A doc that says "7 of 256 done" is wrong by tomorrow and misleads the next agent. 6. **Let a history section be an operating manual when it really is one.** Sometimes a milestone log's "Usage" or "Safety" section is the only precise description of a tool. Do not duplicate it. Reference its exact heading from the topic. ## Routing 7. **Route topics by task, not by file.** "calibration", "debugging" and "export" beat "architecture.md part 2". The agent chooses by what it is about to do. Put a single "use when…" line on each topic. 8. **One topic per task by default.** Say so in the kernel: "pick the single closest topic; load a second only when the task crosses two seams." Otherwise agents load everything "to be safe" and the split buys nothing. 9. **The JSON is the only truth. The tables are mirrors.** `docs/ai-context.json` decides what loads. The tables in `AGENTS.md` and `wiki/README.md` are for discovery. `check` fails when a topic is missing from the kernel table, because an agent cannot choose a topic it has never heard of. 10. **Prefer exact headings to line ranges.** Line numbers break on every edit. A heading reference survives edits, and the script **fails closed** when the heading is missing or appears twice. Duplicate headings such as "Usage" in two sections of one page would otherwise load the wrong text without any warning. 11. **Ignore headings inside code fences.** A shell comment like `# install deps` inside a fence looks like an H1. A naive parser ends the section there or matches it. The bundled script tracks both ``` and ~~~ fences. 12. **A section ends at the next heading of the same or higher level.** So pulling `## Read-only` includes its `###` children and stops at the next `##`. Structure pages so each heading you reference is a self-contained unit. 13. **Mark the source in the output.** Every rendered section starts with `<!-- path § heading -->`. The agent then knows which file to edit, and nobody edits the rendered text by mistake. ## Budgets 14. **Split instead of raising the cap.** The defaults are 8 KB for the kernel and 16 KB per topic. A topic over budget is covering two tasks, so split it. Allow a per-topic `maxBytes` only for real reference catalogs, and write down why. 15. **Budgets are bytes, not lines.** CJK text is 3 bytes a character, and tokens follow bytes more closely than lines do. Measure with `wc -c`, which is what `check` does. ## Agents and adapters 16. **Keep one instruction file.** Two full copies (AGENTS.md and CLAUDE.md) drift. Keep the rules in AGENTS.md. For an agent without native support, use a one-line pointer file (for Claude Code, a CLAUDE.md with `@AGENTS.md`). Delete the pointer once the agent reads AGENTS.md natively; check its current docs or version rather than assuming. 17. **Skills are adapters, not sources of truth.** A skill that restates the rules forks them. Slim skills to workflow phases that each say "load topic X". Keep the skill's own value, meaning phases, report templates and helper scripts, and nothing more. 18. **Tell the agents that are still running.** Agents that are mid-task in the repo hold the old paths in their context. Before moving files, tell them which topic replaces which section, or they will recreate the old file. 19. **Tell agents where helper files go.** State in the kernel where helper scripts and their state live, such as `scripts/<area>/` and `data/<area>/`. Otherwise agents write them wherever their context last pointed, including old directories outside the repo. ## Staying true 20. **A split without upkeep rots within weeks.** A refactor done once goes stale as soon as the code changes and nobody updates the topic. Self-maintenance needs all four parts: - the kernel rule, which makes every task fix stale docs in the same change; - the in-repo manual `wiki/ai-context.md`, so no skill is needed; - orphan checks; - `check` in CI. Any part missing and the docs drift back. 21. **An orphan is drift you cannot see.** A new wiki page that no topic loads, or a new history file missing from the index, is invisible to agents but looks fine to humans. `check` fails on both, and on a nested `AGENTS.md` that no topic loads. Real exceptions go under `"unrouted"` with a reason, so each one is a decision rather than an accident.
-
-
scripts
-
ai-context.py 5.9 KB
#!/usr/bin/env python3 """Print only the doc sections a task needs. usage: ai-context.py list | <topic> [<topic>...] | check Topics live in docs/ai-context.json. A source is a whole file or one exact heading (the section runs to the next heading of the same or higher level). check also fails on orphans, so docs cannot silently drift out of the router: wiki pages no topic loads, history files missing from the router index, and nested AGENTS.md files no topic loads. List deliberate exceptions under "unrouted" in the config, each with a reason. Copy this file to <repo>/scripts/ai-context.py; the repo root is its parent's parent. No dependencies beyond the Python 3.8+ standard library. """ import json, os, re, sys ROOT = os.path.realpath(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) CFG_PATH = os.path.join(ROOT, 'docs', 'ai-context.json') HEAD = re.compile(r'^(#{1,6})\s+(.+?)\s*#*\s*$') FENCE = re.compile(r'^\s{0,3}(`{3,}|~{3,})') def load_cfg(): if not os.path.exists(CFG_PATH): sys.exit(f'missing {CFG_PATH}; copy this script to <repo>/scripts/ and create docs/ai-context.json') with open(CFG_PATH, encoding='utf-8') as f: return json.load(f) def headings(lines): """Yield (index, level, text), skipping headings inside fenced code (e.g. shell comments).""" fence = None for i, ln in enumerate(lines): m = FENCE.match(ln) if m: mark = m.group(1) if fence is None: fence = mark[0] * len(mark) elif mark.startswith(fence): fence = None continue if fence is None and (h := HEAD.match(ln)): yield i, len(h.group(1)), h.group(2) def section(src): path = os.path.realpath(os.path.join(ROOT, src['path'])) if not path.startswith(ROOT + os.sep): raise ValueError(f'{src["path"]}: outside repo') with open(path, encoding='utf-8') as f: lines = f.read().split('\n') if 'heading' not in src: return '\n'.join(lines).strip() hs = list(headings(lines)) hits = [(i, lv) for i, lv, t in hs if t == src['heading']] if len(hits) != 1: # fail closed: a renamed or duplicated heading must not load the wrong text raise ValueError(f'{src["path"]}: heading {src["heading"]!r} found {len(hits)}x') start, level = hits[0] end = next((i for i, lv, _ in hs if i > start and lv <= level), len(lines)) return '\n'.join(lines[start:end]).strip() def render(cfg, name): out = [] for s in cfg['topics'][name]['sources']: where = s['path'] + (f' § {s["heading"]}' if 'heading' in s else '') out.append(f'<!-- {where} -->\n{section(s)}') return '\n\n'.join(out) def orphans(cfg): """Docs that exist on disk but that no agent can reach through the router.""" wiki = cfg.get('wikiDir', 'wiki') history = cfg.get('historyDir', f'{wiki}/history') router = cfg.get('routerFile', f'{wiki}/README.md') root_file = cfg.get('rootInstructions', 'AGENTS.md') routed = {s['path'] for t in cfg['topics'].values() for s in t['sources']} allowed = set(cfg.get('unrouted', {})) router_text = open(os.path.join(ROOT, router), encoding='utf-8').read() if os.path.exists(os.path.join(ROOT, router)) else '' bad = [] skip = {'.git', 'node_modules', 'dist', 'build', 'vendor', '.venv', 'target'} for d, dirs, files in os.walk(ROOT): dirs[:] = [x for x in dirs if x not in skip and not x.startswith('.')] for f in files: rel = os.path.relpath(os.path.join(d, f), ROOT) if rel in allowed or not f.endswith('.md'): continue if rel.startswith(history + os.sep): if os.path.relpath(rel, wiki) not in router_text and rel not in router_text: bad.append(f'{rel}: history file not indexed in {router}') elif rel.startswith(wiki + os.sep): if rel != router and rel not in routed: bad.append(f'{rel}: wiki page no topic loads (map it, or list it under "unrouted" with a reason)') elif f == 'AGENTS.md' and rel != root_file and rel not in routed: bad.append(f'{rel}: scoped instructions no topic loads') return bad def check(cfg): bad = orphans(cfg) budgets = cfg.get('budgets', {}) root_file = cfg.get('rootInstructions', 'AGENTS.md') root_text = open(os.path.join(ROOT, root_file), encoding='utf-8').read() root_size = len(root_text.encode()) root_cap = budgets.get('rootInstructionsMaxBytes', 8192) print(f'{root_file:18} {root_size:6} B (cap {root_cap})') if root_size > root_cap: bad.append(f'{root_file} {root_size} B > {root_cap}') for name, t in cfg['topics'].items(): if f'`{name}`' not in root_text: bad.append(f'{name}: not listed in {root_file} (agents will not know it exists)') try: size = len(render(cfg, name).encode()) except (ValueError, OSError) as e: bad.append(f'{name}: {e}') continue cap = t.get('maxBytes', budgets.get('defaultTopicMaxBytes', 16384)) print(f'{name:18} {size:6} B (cap {cap})') if size > cap: bad.append(f'{name}: {size} B > {cap} (split the topic; do not raise the cap)') for b in bad: print('FAIL', b) print('ok' if not bad else f'{len(bad)} problem(s)') return 1 if bad else 0 def main(argv): cfg = load_cfg() args = argv[1:] or ['list'] if args == ['list']: for n, t in cfg['topics'].items(): print(f'{n:18} {t["description"]}') return 0 if args == ['check']: return check(cfg) unknown = [a for a in args if a not in cfg['topics']] if unknown: sys.exit(f'unknown topic {unknown[0]!r}; run: python3 scripts/ai-context.py list') print('\n\n'.join(render(cfg, a) for a in args)) return 0 if __name__ == '__main__': sys.exit(main(sys.argv))
-
-
SKILL.md 10 KB
--- name: agents-context-router description: Split a bloated AGENTS.md / CLAUDE.md / README into a small always-loaded kernel plus task-routed wiki topics, loaded on demand by a zero-dependency script (`scripts/ai-context.py list|<topic>|check`) with byte budgets, so agents stop burning their context window on docs unrelated to the task. Use this skill whenever the user says AGENTS.md or CLAUDE.md is too long, too big or loads too much context; asks to split, slim, reorganize, route or "wiki-fy" repo docs or agent instructions; wants a docs router, progressive disclosure or context budget for coding agents; mentions milestone logs piling up in the README; or wants multiple agents (Claude Code, Codex, Cursor, Gemini) to share one instruction file, even if they never say "router". --- # Agents context router Coding agents load the root instruction file (AGENTS.md, CLAUDE.md) on every task. As a project ages it collects milestone logs, tool catalogs, runbooks and one-off lessons, until every task pays tens of KB of context for text it does not need. The fix is a **kernel + router** layout: ``` AGENTS.md kernel: rules every task needs + how to load more (≤ 8 KB) docs/ai-context.json topic → sources (whole file or one exact heading); the single truth scripts/ai-context.py list | <topic> | check (bundled with this skill) wiki/README.md human router table (mirrors the JSON) wiki/ai-context.md in-repo maintenance manual (works without this skill) wiki/<topic pages>.md how-to / reference, one per task seam wiki/history/*.md milestone logs, verbatim, never loaded by default README.md humans: what it is, quickstart, doc map ``` An agent reads the kernel, picks the one topic that matches its task, and runs `python3 scripts/ai-context.py <topic>` to print only those sections, each marked `<!-- path § heading -->`, so it knows where to edit. The layout also **maintains itself** once this skill is gone, because every piece lives in the repo: - The kernel's "Keep the docs true" rule makes every agent, on every task, fix a stale doc in the same change that makes it stale. - `wiki/ai-context.md` is the procedure. - `check` fails on orphans and budget overruns. - CI runs `check`, so drift breaks the build instead of rotting quietly. Leaving out any one of these four is how routed docs decay back into a pile. Before you start, read `references/gotchas.md`. It lists the traps that make this refactor quietly lose content or route agents to the wrong text. It is short, and every item came from a real split. ## Workflow ### 1. Measure List every file an agent loads automatically: root and nested `AGENTS.md`/`CLAUDE.md`, and anything they `@import`. Also list the files agents are told to read "first". Record their byte sizes (`wc -c`). These numbers go in your final report as before and after. Keep a backup of each original outside the repo (or rely on git), because step 3 moves text and you will diff against it. ### 2. Classify every section Read the whole file and put each section into exactly one bucket: | Bucket | Test | Goes to | |---|---|---| | **Kernel** | Would a wrong action happen on *any* task if the agent did not know this? Examples: hard limits, safety rules, language rules, where outputs may go, the rule that says when to load a topic. | `AGENTS.md` | | **Topic** | Needed only when doing one kind of task: build and deploy, debugging, a subsystem, a tool catalog. | `wiki/<topic>.md` | | **History** | Dated milestone logs, acceptance runs, "what we did in M3". | `wiki/history/<milestone>.md` | | **Human** | Intro, screenshots, setup for people. | `README.md` | Some text changes buckets. A behaviour rule learned the hard way (for example "if every job fails the same way, suspect our code before the site") is kernel. The procedure for acting on it is topic. A history section that is still the operating manual (a "Usage" section in a milestone log) stays in history, and a topic references its exact heading. ### 3. Move, then write 1. **Before moving any log, pull out the live rules hidden in it.** Old logs often contain a rule that is still in force, written as an aside ("note: never run X on shared"). Once the log moves to history, no agent will ever see that rule again. Grep each log for imperative words in every language it uses, for example `never|always|must|do not|don't|warning|note:|avoid|forbidden|required`. For each hit that is still valid, copy it as a one-line rule into the kernel (if it applies to every task) or into its topic. List every promoted rule in your report. 2. Create `wiki/history/` and move milestone logs there **verbatim**, in their original language. Do not translate or summarise while moving. Verbatim moves are diffable and lose nothing. 3. Design topics around **tasks the agent will be doing**, not around the old file order. Aim for 5–12 topics. Each one gets a kebab-case name and a single "use when…" line. Ask: "an agent is about to do X; which pages must it see?" 4. Write the topic pages. Move reference text and runbooks in, and cut the duplication the old file had. 5. Rewrite `AGENTS.md` as the kernel. Start from `assets/AGENTS.kernel.md`. It holds: - the one-paragraph purpose; - the language rules, stated once; - the always-apply rules, including **Keep the docs true**, verbatim or adapted; - the hard limits; - the load-context block with a topic table; - the verification commands. 6. Slim `README.md` to intro, quickstart and a doc map pointing to `wiki/README.md`. ### 4. Wire the router 1. Copy `scripts/ai-context.py` from this skill to `<repo>/scripts/ai-context.py`. It resolves the repo root as the script's parent's parent. 2. Write `docs/ai-context.json` from `assets/ai-context.json`. Use `{"path": ...}` for a whole page. Use `{"path": ..., "heading": "Exact Heading Text"}` to pull one section out of a bigger page, such as a single tool group from a catalog. 3. Write `wiki/README.md` from `assets/wiki-README.md`: the topic table for humans, plus a history index. 4. Copy `assets/wiki-ai-context.md` to `wiki/ai-context.md` and keep the `ai-context` topic that points at it. This is the manual any future agent loads to maintain the router, with or without this skill. Adapt the paths if the repo uses other directories. 5. Run `python3 scripts/ai-context.py check`. It fails when: - a path or heading is missing, or a heading is ambiguous; - `AGENTS.md` is over its budget; - a topic is over its budget; - a topic is not named in `AGENTS.md`; - there is an **orphan**: a wiki page no topic loads, a history file missing from the `wiki/README.md` index, or a nested `AGENTS.md` no topic loads. Fix the docs, not the caps. When a topic is too big, split it. When a page really is human-only, list it under `"unrouted"` with a reason, and remove the template's example entry. ### 4b. Make drift fail the build Wire `check` into whatever the repo already runs on every change. Use the one that exists; do not add new tooling: | Repo has | Add | |---|---| | `package.json` | `"docs:check": "python3 scripts/ai-context.py check"`, chained into `test` | | `Makefile` | a `docs-check` target, made a prerequisite of `test` or `check` | | `.pre-commit-config.yaml` | a local hook: `entry: python3 scripts/ai-context.py check`, `pass_filenames: false` | | `.github/workflows/*.yml` | a step `run: python3 scripts/ai-context.py check` in the existing test job | | none of these | add the command to the kernel's Verification block and say so in the report | ### 5. Point every agent at the kernel - **One file for every agent.** Keep the rules in `AGENTS.md`. If an agent you use does not read `AGENTS.md` natively, make its file a one-line pointer instead of a copy (for Claude Code, a `CLAUDE.md` holding `@AGENTS.md`). Two full copies drift apart within a week. Check each agent's current docs or version, because native support is changing fast. - **Skills and scripts are adapters.** If the repo has skills, commands or prompts that restated the old docs, cut them down to workflow steps that say "load topic X". The rules live only in the kernel and the wiki. - **Other agents' stale paths.** If other agents or sessions are working in the repo, tell them the docs moved and which topic replaces what, because their context still holds the old paths. ### 6. Verify and report - Run `check` and show its output. - Run `ai-context.py <topic>` for two or three topics, and read the output as an agent would. Can you do the task from this alone? - Grep for links to old anchors and moved files, and fix them. - Compare the byte totals between the backup and the new tree. A large drop in total bytes, not just kernel bytes, means content was lost rather than moved. Find out where it went. Report in the user's language: ``` ## Context split - Always-loaded: <before> B → <after> B (<file list>) - Topics: <n>; largest <name> <bytes> B; all under budget (check output below) - Moved verbatim to wiki/history: <n> files - Content kept: <total before> B → <total after> B (<explain any drop>) - Adapters updated: <skills/CLAUDE.md/etc> - Self-maintenance: kernel rule ✓, wiki/ai-context.md ✓, check in <CI/test/pre-commit> ✓ - Follow-ups: <e.g. translate zh pages, split topic X if it grows> ``` ## Maintaining it later Upkeep is the job of the repo's own `wiki/ai-context.md` and the kernel rule, not this skill, so it happens on ordinary tasks too. When this skill is triggered for maintenance (for example "add this runbook", "check is failing" or "we finished M7"), load the `ai-context` topic and follow it: - **New knowledge:** put it in the page for its topic. If no topic fits, add a page, map it in the JSON, add it to both tables and run `check`. - **New milestone:** add `wiki/history/<m>.md` and one row in the history index. Nothing is added to the kernel unless it is a rule for every task. - **Kernel near its budget:** that is the signal to move something out, not to raise the cap. - **Orphan failure:** map the page to a topic, index the history file, or, only if it is really human-only, list it under `"unrouted"` with a reason.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.