Project Learnings
SkillFiles & storageUse PROACTIVELY, without being asked, at the START of any multi-step task in a git repo, project folder, or vault (before reading files) and at the END of one (to reflect and save). Applies whenever the user asks to implement, fix, refactor, debug, or investigate something in a project, whenever a first attempt was wrong or the user corrected the agent, and whenever the agent rediscovers something a previous session should have known. Retrieves what earlier sessions learned about operating in the project and saves durable insights (locations, traps, conventions, decisions with rationale, workflows, open questions, what to do differently) to an opt-in, append-only InfraNodus graph named learn- plus the project name. Also on "what do we know about this repo?", "what did I learn?", "save learnings", "remember this about the project", "start keeping learnings", "/learnings". Load before calling get_project_learnings, add_project_learnings, or enable_project_learnings directly. Never writes without the user's explicit per-project opt-in and review of each batch. Project knowledge only, never anything about the person.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Project Learnings skill
What this skill tells your AI
The instructions your AI receives, as published by infranodus/skills in skill-project-learnings/SKILL.md and read by ahel’s review.
An agent that works in a project keeps rediscovering the same things: which
of nine files holds the model list, that the tests only exist as ad-hoc
scripts, why a cache is per-process, which command actually deploys. This
skill turns those rediscoveries into a learnings graph in the user's
InfraNodus account — learn-<project> — that the next session reads before
it starts and appends to when it finishes.
It is a graph rather than a notes file because learnings link to the same entities (file paths, modules, concepts) as everything else in the project: "which parts of the codebase accumulate traps" is a graph query, and the gaps between what is known and what the code contains show where nobody has looked yet.
Prerequisites
The connected InfraNodus MCP server must expose these three tools (added
after infranodus-mcp-server 1.7.4; hosted at https://mcp.infranodus.com or
the npm package):
get_project_learnings— read (by prompt, by entity, overview, or list)add_project_learnings— propose / write (dry run by default)enable_project_learnings— create the graph, only on the user's explicit request
If they are missing from the tool list, say so once ("the connected
InfraNodus server doesn't expose project learnings; update it or connect
https://mcp.infranodus.com") and continue the task without this skill. Do
not emulate the feature with memory_add_relations — that would bypass the
consent model.
Consent — read before anything else
- Nothing is written unless the user enabled learnings for this project.
add_project_learningsrefuses (enabled: false) when the graph does not exist and never creates it. Never callenable_project_learningson your own initiative — only when the user explicitly asks to start keeping learnings for a project. Before that call, tell them in two sentences what will be stored (project knowledge only), where (a private, append-only graph in their InfraNodus account that they can delete at any time), and that each batch is shown before it is saved. - Show every batch before it is written.
add_project_learningsis a dry run by default. Present the plan, ask, and only then call again withconfirm: true. If the client supports MCP elicitation the server asks the user itself and writes in the same call. Skip the question only when the user has said, in this conversation, that they do not want to be asked. - Project knowledge only. "The model list lives in nine files" is a learning. "The user prefers short answers" is not — that belongs in the client's own memory, never in a shared graph.
- No secrets, hostnames, env values, credentials, customer data, or verbatim error output. Paths and descriptions only. The server rejects secret-like statements and reports only their index.
- If
get_project_learningsreturnsenabled: false, carry on with the task without this skill. At the end of a substantive task, if you hold at least one learning that passes the admission criteria below, say once — one sentence — that learnings are not enabled for this project and can be turned on with "start keeping learnings". Never repeat that in the same session, and never enable on your own. With nothing worth keeping, stay silent.
Workflow
1. Start of a substantive task — retrieve
Call get_project_learnings with the project name and the task as prompt.
Use the same project name every time (the repo or folder name; call the tool
with no project to see which names already exist in the account). The
response carries the most relevant learnings, the areas that have
accumulated knowledge (knownAreas), and the gaps. Read them before
opening files. Skip for trivial tasks (a typo, a one-line answer).
2. Before touching an unfamiliar area — look up the entity
get_project_learnings with entity set to the file path, module, or
concept returns every learning that mentions it. Cheap; do it before the
first edit in an area this session has not visited.
3. End of a substantive task — reflect
A substantive task is multi-step, involved discovery, a correction from the user, or a non-obvious fix. Ask yourself four questions:
- What did I have to discover that was not in the docs or obvious from the code?
- Where did I go wrong first, and what was the actual cause?
- What decision did I make, and why that one?
- What would I check first next time?
- Self-assessment: what about my approach worked well in this project and
should be repeated, and what should I do differently next time — which
check would have caught a mistake earlier, which order of steps saved
effort, where did I over- or under-verify? Save these with type
approach. Be as honest about what went well as about what did not: both are equally useful to the next session.
Draft 0–5 statements. Zero is a normal answer; do not pad. Each must pass all five admission criteria:
- Not derivable from the code, docs, or git history in a few reads
- Would have saved time if known at the start
- Survived verification — only after the thing actually worked
- About the project, never about the person
- Adds insight, not just a fact: prefer learnings that connect things that are not obviously connected — a cross-module dependency, a pattern that recurs across files, the non-obvious consequence of a design choice, a hypothesis about why something is the way it is. A location fact is admissible; a location fact plus the reason it is scattered is better.
Then add_project_learnings (dry run) → show the plan → confirm: true
on agreement.
4. User-initiated
"Save what you learned", "remember this about the project", "/learnings": run step 3 immediately for the current session, whatever its size.
Statement contract
One statement per learning, at most two sentences, with at least two
[[wikilinked]] entities — file paths, modules, functions, concepts,
tools. Entities are what make the graph queryable, so link the things a
future session would search for.
Each statement carries one type:
| type | use for |
|---|---|
location | where X lives, especially when it is scattered or misnamed |
trap | what went wrong first and why |
convention | how things are done here that the code does not spell out |
decision | what was chosen and the rationale |
workflow | how to run, test, build, deploy, debug |
question | open, unresolved, worth a future session's attention |
approach | self-assessment: what worked well and should be repeated, or what to do differently next time |
Example (a real one):
The list of available AI model names is duplicated in 9 places: the modelToUse enums in [[src/schemas/index.ts]], [[src/instructions.ts]], [[src/resources/about.ts]], [[README.md]], and the tool defaults in [[generateOntologyGraph.ts]] and [[analyzeLlmResults.ts]]. Source of truth is [[infranodus-app]] routes/ai.js getModelsAvailable, which keeps old names as aliases.—location
Reading the tool responses
enabled: false→ not enabled for this project; nothing written. Carry on (or, if the user asked to save, tell them it is not enabled and offer to enable it — they decide).dryRun: truewithwouldWrite→ show it. Items markedreinforcedare near-duplicates of something already known; they are written as a short "Confirmed again" statement, which raises the weight of the same links. That is deliberate: things that keep being rediscovered become central.declined: truewith anote→ the user wants a change; adjust and try once more. Without a note → do not retry.dryRun: truewith anelicitationfield → the server tried to ask the user directly but could not (dialog dismissed, client error). Not a decline: show the plan and ask in chat as usual.rejectedwith indices → strip the secret-like content from those statements (the server never echoes it) and resubmit.- A stale learning is not deleted (the graph is append-only); it is superseded by a newer statement, and retrieval sorts newest first. If you find a learning that names a file that no longer exists, add the correction as a new statement.
Using the graph as a graph
Once a project has a few dozen learnings, the InfraNodus tools that work on
any saved graph work on learn-<project> too:
get_project_learningswith noprompt/entity→ overview: known areas, main concepts, gaps. Addtype: "trap"for the fragile parts of the project,type: "question"for what previous sessions left open,type: "approach"for what worked and what to do differently.analyze_existing_graph_by_nameon the graph name → clusters, gaps, and the most influential entities across all learnings.optimize_knowledge_basewithgraphName: "learn-<project>"andfocus: "codebase"(or"procedural"for a rule-heavy project) → structural feedback on the learnings themselves: which areas of the project dominate what was learned, which are under-developed, which clusters of learnings never connect. AddcompareWith: ["repo-<project>-structure"]when the infranodus skill built one to see the parts of the code base no learning has touched.- If the infranodus skill has built
repo-<project>-*graphs,difference_between_textswith{graphName}contexts shows modules that have code but no learnings — unexplored territory — and the learnings graph can be added to that project'sinfranodus/manifest.jsonas a scope withpolicy: "learnings"so question routing sees it. Optional; nothing here depends on the manifest.
The type of each learning is stored as statement metadata (a category on
the statement), not as a node — so the graph's nodes are only the real
entities and the structure is not distorted by the labels. Filter by type
through the tool's type parameter or the statement categories in the
InfraNodus UI.
Relationship to other skills
- infranodus — maps what a repo or vault contains (deterministic extraction). This skill records what an agent learned operating in it. They share entity names, so the graphs compose.
- llm-wiki — authored knowledge pages compounding over time. Route there when the user wants prose, not one-line operational learnings.
- Claude Code's own file memory — per-user, per-machine. Keep using it for user preferences and for project facts when learnings are not enabled; when they are, project-type facts go to both.
Who decides when this runs
This skill can only ask; every gate is the user's. Nothing here needs a hook or a CLAUDE.md entry to work, and the skill ships neither.
- The real gate is server-side. Until the user enables
learn-<project>, an automatic invocation is one read call that returnsenabled: false, after which the skill goes dormant for the session. Nothing is written, nothing is created. - Manual only. Set
disable-model-invocation: truein this file's frontmatter (the description leaves Claude's context; only/project-learningsinvokes it), or per project in.claude/settings.local.json:"skillOverrides": { "project-learnings": "user-invocable-only" }("off"hides it entirely). - Remove. Delete the skill folder or uninstall the plugin.
- Every session, guaranteed. The user's own choice, never the skill's: a
line in the project's
CLAUDE.mdsuch asBefore any multi-step task call get_project_learnings for project <name>, or aSessionStarthook that injects the same sentence (theupdate-configskill can add one).
Reference: https://code.claude.com/docs/en/skills ("Control who invokes a skill", "Restrict Claude's skill access").
Example
User: start keeping learnings for this repo
Agent: I'll create a private, append-only graph
learn-mcp-server-infranodusin your InfraNodus account. It will hold knowledge about operating in this project — where things live, traps, conventions, decisions — never anything about you, never secrets. I'll show each batch before saving, and you can delete the graph any time. Enabling now. (callsenable_project_learnings)…later, after a task…
Agent: Two things from this session worth keeping:
- [trap]
Reading a graph right after creating it can fail on infranodus.com: the app runs several instances with a per-process contexts-list cache ([[lib/middleware/getOwnerContextsList.js]]); [[src/utils/learnings.ts]] retries reads and treats any positive as authoritative.- [workflow]
There is no test runner in the repo; [[npm test]] builds with tsc and runs [[node --test]] over test/*.test.mjs against dist/.- [approach]
Testing the new tools through an in-memory [[MCP client]] with an intercepted [[fetch]] caught the body-shape and session-state bugs that unit tests of the pure helpers missed; do that before any live run in this project.Save these? (dry run shown; on "yes" →
confirm: true)
Signals
- GitHub stars
- 118
- Forks
- 30
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
project-learnings- Source
- github.com/infranodus/skills