ingest-project
Skill2 starsChanged 2 months agoMITView on GitHub
Use when the friend wants to bring an EXISTING project (real code/git history) into their wiki as an L2 pointer-map. Triggers on the /ren:ingest-project slash command (optional [path]). A read-only scanner mines the repo for facts; the live session drafts compact knowledge + pointers from those facts; this skill assembles and queues the map, then shows the friend the first-session artifact — the visible proof memory was captured (spec §3.8 A-10). For a brand-new project with nothing to scan, use /ren:bootstrap-project instead.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- karrot0195/harness-agent-skillstheir own version, first seen Nov 8, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- karrot0195/harness-agent-skills★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository19 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- backupSkill
- bootstrap-projectSkill
- code-mapSkill
- distillSkill
- doctorSkill
- installSkill
- interviewSkill
- metric-watchSkill
- pinSkill
- recallSkill
- rememberSkill
- retrospectiveSkill
- routine-initSkill
- suggestionsSkill
- updateSkill
- wiki-healthSkill
- wiki-migrationSkill
- wrapSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 66
Call importlib.import_module("skills.ingest-project.lib").scan_repo(repo_root) — read-only facts: detected languages/package …
- Very specific: line 82
Do NOT draft project-specific pages into root-level decisions/ · patterns/ · research/.
- Distinctive: line 99
Ask a human to approve the map before it's saved.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
ingest-project
Bringing an existing repo's context into the wiki, in one visible artifact — in Karpathy order (spec 2026-08-31 §6): taxonomy first. scan_repo mines the repo for facts (never writes, never touches the project); the live session drafts a schema.md taxonomy tree and shows it to the friend in chat for a yes before anything is written (the one human gate); it then turns the facts into knowledge (compact facts), hub_pages (one folder-note per branch), and pointers (topic → wiki-path#anchor, rendered as [topic](wiki-path#anchor); external repo: references keep the arrow form); ingest validates the taxonomy, assembles the frozen L2 schema pointing at the hubs, and queues schema.md + hubs + map, then hands back the exact text to show the friend.
When to use this skill
- Friend invokes
/ren:ingest-project [path](path defaults to cwd) against a project with real code, a README, or git history - Friend says: "bring this existing project into the wiki", "set up memory for this codebase I already have"
When NOT to use this skill
- Brand-new, empty project →
/ren:bootstrap-project <slug>instead (empty map, no scan) - Friend wants to re-scan without changing anything → still this skill;
ingestproposes anUPDATEand the queue surfaces asupersedesconflict against the prior map for a human to reconcile, it never silently clobbers
Behavior
- Resolve the repo path (default cwd) and a project slug (kebab-case, from the repo's manifest name or directory name — caller's choice of derivation).
- Call
importlib.import_module("skills.ingest-project.lib").scan_repo(repo_root)— read-only facts: detected languages/package managers/frameworks, entry points, doc inventory, git history summary, size signals. Never writes to the project, never raises on a non-project path (see the carriedscan.py's own contract). Draft the project wiki from the facts — in a worker subagent when possible (
execution_tier: worker): the facts JSON is self-contained, so spawn a cheap worker-model subagent (worker-class or classifier-class) with the facts and the drafting spec below, and take its output back. Parse its returned JSON withlib.adapter.worker.parse_worker_json— it tolerates a ```json fence or leading prose despite raw-JSON-only instructions, and raisesWorkerOutputError(carrying the raw text) if the output still isn't valid JSON. Fall back to drafting inline only when subagents aren't available.The drafting model is Andrej Karpathy's LLM Wiki pattern — every future ingest session should hold these principles:
Three layers: raw sources, write-once by convention (
projects/<slug>/raw/) / LLM-maintained wiki pages dense with cross-references (knowledge/) / a SCHEMA document defining structure + conventions (schema.md). Ingest touches many pages and maintains cross-refs; lint (wiki-health) finds contradictions, stale claims, and orphans;index.md+log.mdare navigation aids. "The wiki is a persistent, compounding artifact — the cross-references are already there." The human curates sources; the LLM's job is everything else.Draft in this order (each stage feeds the next):
- Propose the taxonomy from what the repo/domain actually contains — which
knowledge/subdirectories exist and what belongs in each (e.g. a game project:knowledge/entities/characters/,knowledge/mechanics/; a web app:knowledge/api/,knowledge/infra/). Depth is project-determined; don't force flat, don't force deep — up to the 2-levels-below-knowledge/cap (lib.memory.taxonomy.MAX_DEPTH, permanent perdocs/decisions/2026-09-04-taxonomy-depth-cap.md: hierarchy deeper than that is carried by parent/child links inside pages, so leaf pages link their conceptual parent, not just their hub). - Show the friend the proposed tree in chat and wait for a yes — render the branches with a one-line "what belongs here" description each, and ask them to confirm before any write happens. This is the one human gate in ingest (spec §6): the initial taxonomy shapes everything drafted after it, so it's reviewed once, up front, as a ~10-line tree — not later as a pile of restructure suggestions. If they want changes, revise and re-show; nothing is queued until they confirm.
- Draft
schema_page— the full markdown body forprojects/<slug>/schema.md(type: project-schema,schema_version: 1,project: <slug>): the confirmed taxonomy as a ```taxonomy fence (parseable bylib.memory.taxonomy.parse_taxonomy) plus the per-branch prose descriptions. This is passed toingest()as theschema_pagestring — do NOT queue it directly;ingest()validates and queues it. - Draft
hub_pages— one folder-note per branch,{"<branch>": "<markdown>", ...}(type: hub,hub: truein frontmatter — the shipped folder-note convention,_ensure_hub/page_types.pyrule 2) that summarizes and will link its children. Also passed toingest(), not queued directly. - Leaf pages for the strongest scan facts, at their nested paths (
knowledge/<dir>/<topic>.md, any depth), frontmattertype: project-knowledge,schema_version: 1,project: <slug>. Cross-reference sibling pages and their hub — link related leaves to each other, not just up to the hub. Bounded (the existing ingest cap). Every leaf body MUST carry, after its H1: aParent: [[<stem>]]line naming its hub (or the concept page that is its real conceptual parent), and a## Relatedsection with at least one sibling bullet in the form- [[<stem>]] — <one clause saying why>. Hubs are the shelf, not a chain: a hub directly underknowledge/is the top of the shelf and carries NOParent:line, and neither does the projectmap.md. Only a NESTED hub carries one,Parent: [[<parent-hub-stem>]]. Leaves always carry aParent:line. Pass these toingest()asleaf_pages(step 5 below); do NOT queue them yourself withpropose_and_apply.ingest()queues them after the hubs, so the hub a leaf names asParent:is already on disk. The map never points at leaves (only hubs and top-levelknowledge/*.mdpages), so this ordering costs nothing.
What the worker returns:
knowledge: list[str](compact, general facts, e.g. "Python project using FastAPI + PostgreSQL", "138 commits since 2025-03"),schema_page: str(the drafted markdown body from step 3),hub_pages: dict[str, str](branch → markdown body, step 4),leaf_pages: list[dict]({"name": "<relative path under knowledge/>", "body": "<markdown>"}, step 5), andpointers: list[dict]({"topic": ..., "path": ..., "anchor": ..., "write_id": ...}) for any additional top-levelknowledge/*.mdpointer the session wrote directly and wants in the map (hub pointers are added automatically byingest()— see step 4 below).projects/<slug>/raw/is for the friend's source material (write-once by convention — nothing enforces it — and human-curated); ingest doesn't populate it, but pointers may target existing files there.- Pointer existence rule (founder ruling, issue #20): every pointer must target something that exists. Either (a) an in-wiki page that already exists or is being created in this same batch, or (b) an external repository reference written
repo:<name>:<path>(e.g.repo:flux:src/main.rs) — those are skipped by the dangling-pointer checks because they are not resolvable in-wiki. Never invent a future filename. A pointer at a page nobody has written is a dangling pointer, not a placeholder;write_id: None(unstamped) is only for a real page that has not been through the queue, never a licence to name a file that does not exist. - Do NOT draft project-specific pages into root-level
decisions/·patterns/·research/. Those are the instruction plane — general practice only, promotion-gated for every producer (docs/decisions/2026-08-01-global-tier-promotion-gate.md); a write there holds pending instead of applying. Project-specific durable knowledge goes underprojects/<slug>/knowledge/.
- Propose the taxonomy from what the repo/domain actually contains — which
- Call
importlib.import_module("skills.ingest-project.lib").ingest(project_slug, knowledge, pointers, session, schema_page=schema_page, hub_pages=hub_pages, leaf_pages=leaf_pages)— validatesschema_pagewithlib.memory.taxonomy.parse_taxonomyfirst: an unparseable/missing taxonomy fence (TaxonomyError) refuses the whole schema/hub write group (no partial tree — nothing is queued forschema.mdor any hub) and falls back to the existing map-only behavior, reporting why inresult["taxonomy_error"]. On a valid taxonomy, queuesschema.md, then each hub page (projects/<slug>/knowledge/<branch>/<branch>.md), then the L2 map — in that order, all through the data-plane door (producer="ingest",writer="llm-auto"(trust class"foreign") — scan-derived content is LLM-shaped, so it's quarantine-marked; every write auto-applies immediately since these are non-global pages, per the v2.2 pivot).ingest()adds one Decision-map pointer per hub automatically (- [architecture](projects/<slug>/knowledge/architecture/architecture.md)style, carrying the hub's realwrite_id) — don't hand-build those pointer entries yourself. Returns{"qid": ..., "write_id": ..., "artifact": ..., "taxonomy_error": ..., "schema_write_id": ..., "hub_write_ids": ..., "link_errors": ...}. Omittingschema_page/hub_pagesentirely (e.g. re-ingesting a project whose taxonomy is already stable) is a legacy call — behaves exactly as before this section existed. - Pass the drafted leaf pages to
ingest()asleaf_pages— a list of{"name": "<relative path under knowledge/>", "body": "<markdown>"}. Every leaf body MUST carry, after its H1: aParent: [[<stem>]]line naming its hub (or the concept page that is its real conceptual parent), and a## Relatedsection with at least one sibling bullet in the form- [[<stem>]] — <one clause saying why>. Hubs are the shelf, not a chain: a hub directly underknowledge/is the top of the shelf and carries NOParent:line, and neither does the projectmap.md. Only a NESTED hub carries one,Parent: [[<parent-hub-stem>]]. Leaves always carry aParent:line.ingest()validates each leaf withlib.memory.links.parse_page_linksand reports failures inresult["link_errors"]; the leaf is queued either way — missing links are lint's job to find, not a reason to lose knowledge. Do NOT queue leaves yourself withpropose_and_apply. - Pass
repo_root=toingest()(the path resolved in step 1) so the repo gets wired to its memory — two side-cars run after the map is applied (issues #15 + #19), both best-effort and neither able to break the ingest:<repo_root>/CLAUDE.mdgets the thin RenOS pointer block vialib.adapter.claude_md.write_project_claude_md(repo_root, project_slug)— same additiveren:marker-block contractbootstrap-projectuses: content outside the markers is byte-for-byte preserved, re-ingest is idempotent, torn markers are a"conflict"that touches nothing. The result string comes back asresult["claude_md"](Nonewhenrepo_rootis omitted,"error"if a side-car failed).- the repo-path↔slug pair is recorded in
state_dir()/projects.jsonviaren_paths.record_project_repo—ren_paths.detect_projectconsults that mapping BEFORE dir-name matching, so a checkout directory named differently from the manifest-derived slug (~/Dev/genshin-calculator-devvs. sluggenshin-calculator) still gets its memory injected at wake-up. Without it such a clone is silently orphaned forever;/ren:doctor'scheck_orphaned_projectswarns about exactly that state.
- Show the friend
artifactverbatim. This is the first-session artifact (exit criterion 6's "wow moment") — it always starts with the exact sentence"I set up your project memory — here's what I captured:"followed by the full map body, then a closing line confirming the map is already saved and one-step revertible (mentionswrite_id, not an approval command). - Offer to release the map from quarantine. The map just written is
writer="llm-auto", so it's quarantine-marked (step 4) — and per RenOS 0.4.1 trust hardening, a quarantined L2 map is held out ofwake-up's context injection until a human reviews it, unlike L1 which stays injected regardless. After showing the artifact, ask the friend whether it looks right; if they confirm, callimportlib.import_module("skills.wiki-health.lib").release_page("projects/<slug>/map.md", session)— the existing human-act exit from quarantine — and tell them the map is now released and will be pulled into future wake-ups. If they don't confirm (or say nothing), leave it quarantined; it's still saved and revertible, just held out of context until released later.
Why writer="llm-auto" (and bootstrap's is "human")
The knowledge/pointers here are synthesized from raw scan facts by the live session — an LLM inference, however deterministic-feeling. Per spec §3.10, LLM-authored content is data-not-instruction until a human reviews it; lib.memory.queue.apply quarantine-marks any writer="llm-auto" ADD/UPDATE automatically. bootstrap-project's empty map has no such content (nothing was inferred), so it stays writer="human".
What this skill does NOT do
- Modify anything in the scanned project during the scan.
scan_repois read-only, full stop — seescan.py's own INVARIANTS block. The single write into the repo is step 6's additiveCLAUDE.mdmarker block (only whenrepo_rootis passed); nothing outside those markers is ever touched. - Draft the knowledge/pointers itself. That synthesis is the live session's job (it has the facts JSON and the framework's judgment); this skill's
libonly assembles and queues what it's given. - Ask a human to approve the map before it's saved. Per the v2.2 data-plane pivot, a project map is a non-global page — it auto-applies immediately (quarantine-marked, since scan-derived content is LLM-shaped) and is one-step revertible, not queued pending for a human diff.
- Port the old ADR-014 7-file taxonomy. That's dead for 0.2; the L2 map is the whole per-project artifact now.
Failure-degradation modes
| Failure | Behavior | User-visible |
| Path isn't a project (no manifest/git/README) | scan_repo still returns a complete facts dict with looks_like_project: false | Session decides whether to proceed with a thin map or ask the friend to confirm |
| A map already exists for this slug | ingest proposes UPDATE; queue attaches a supersedes conflict against the prior map, then auto-applies (supersedes never holds auto-apply — lineage is recorded in the journal) | "Updating projects/<slug>/map.md — this supersedes the existing map (<write_id>)." |
| Pointer references a page never written through the queue | Renders (unstamped) in the Decision map, not a crash — but see the pointer existence rule: the target page must still EXIST, or /ren:doctor+/ren:wiki-health report it dangling | (visible in the rendered map itself) |
A knowledge/<topic>.md page already exists for that topic | The queue proposes an UPDATE and surfaces a supersedes conflict, same as the map — never a silent clobber | "Updating projects/<slug>/knowledge/<topic>.md — supersedes (<write_id>)." |
schema_page doesn't parse (TaxonomyError — no/broken ```taxonomy fence) | ingest refuses the whole schema/hub write group — no partial tree — and falls back to the existing map-only behavior; the fact is still saved | result["taxonomy_error"] carries the reason; schema_write_id/hub_write_ids come back empty |
A drafted leaf has no Parent: or no ## Related sibling | reported, leaf still written | result["link_errors"], and /ren:wiki-health's asymmetric_links/orphan_pages next sweep |
References
skills/ingest-project/lib/scan.py(carried from donorskills/ingest-project/scripts/scan.py) — the read-only scanner- Task 4.4 (
skills/bootstrap-project/lib) — the empty-map sibling skill - Spec §3.1 L2 + §3.8 A-10 — the pointer-map schema and the first-session artifact requirement
- Task 2.1 (
lib/memory/queue.py) — the single write-queue this skill's only write path docs/decisions/2026-08-01-project-knowledge-subtree.md(issue #20) — theprojects/<slug>/knowledge/subtree, the pointer existence rule, and the wake-up trust decisiondocs/decisions/2026-08-01-hierarchical-project-wiki.md(issue #20 amendment) — schema.md, nested knowledge/ with hubs, raw/, and the Karpathy LLM-wiki drafting order abovemigrations/project-knowledge-1/— relocates pre-0.6.2 flat project pages intoknowledge/- Task 2.2 (
lib/memory/semantics.py) — the supersedes/contradicts/duplicate conflict detection this skill's UPDATE path surfaces docs/superpowers/specs/2026-08-31-concept-tree-routing-design.md§3 + §6 — the```taxonomyfence contract (lib/memory/taxonomy.py) and the Karpathy-order drafting flow this section implements (Task 6)
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
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.

