/memory-onboard — repo-aware onboarding for memory
This skill is the way to seed a repo with lore. It earns its keep by
reading the repo first (README, ADRs, recent commits, deprecation
markers, in-flight migrations) so the proposed drafts are specific to
this codebase, with source citations — rather than inventing memory or
mechanically chunking every bullet in the docs (which produces mostly
noise and floods the review queue).
Output: DRAFT records with source citations, plus optional absence
markers and boundary edges. Everything lands in memory review for a
human to ratify — the skill never promotes its own records.
Hard rules
- Every lore record this skill produces is a DRAFT. Call
suggest_lore (or report_conflict for counter-claims — also drafts),
never any approval path. The human reviews with memory review.
Exception: record_absence does NOT create a draft — it records a
self-expiring "we checked, no policy" marker. Different primitive,
different gate (see rule 6).
- Every draft carries the tag
induction so it can be filtered later.
Layer topic-specific extras as appropriate (security, conventions,
migrations, incident-lessons, invariants, etc.). report_conflict
counter-drafts are auto-tagged conflict-report by the server.
- Cite sources in the body. When a draft comes from a file or commit,
include a one-line reference at the top of the
body — e.g.
Source: README.md L42–55 or Source: commit abc1234 "migrate accounts → organisations".
This is the trust signal a reviewer needs.
- Never put secrets, credentials, personal data, regulated data, or
anything that looks like a token into any lore record. If a candidate
item contains something like that, skip it and tell the user why.
- Skip the obvious. "We use TypeScript", "run the tests before
committing", and other things a model already knows about a typical
codebase belong in
CLAUDE.md (or nowhere), not in lore. Aim for
non-obvious, high-consequence knowledge.
- Use
record_absence sparingly. If the user explicitly confirms
"we don't have a policy on X yet, and that's intentional", that's
a legitimate absence marker — call record_absence({ query: "<topic>", reason: "<why no policy>", repo: <repo> }). Don't infer absence
from "I didn't find anything in the README"; the user has to confirm
it. Markers self-expire (14 days default) so they fade automatically
if the team takes a stance later.
- Use
report_conflict when you find a contradiction, not when you
find a duplicate. If search_lore returns an existing record and
the source-of-truth you just read disagrees with it (e.g. README
says "Argon2id", existing lore says "scrypt"), that's a report_conflict
moment. If the existing record just covers the same topic without
contradicting, leave it alone — possibleConflicts in search results
handles benign overlap.
Procedure
Follow these steps in order. Confirm with the user as the comments
indicate.
Step 1 — confirm scope
Detect the current repo's short name (from git config --get remote.origin.url
or, failing that, from the working directory name). Confirm with the user:
"I'll onboard <repo-name> to memory. Anything I should add to
that, or remove? (e.g. payments-svc, auth-svc for cross-repo notes)"
Capture the final repos array — every draft created in this session
will carry it.
Step 2 — survey the repo
Read these sources, in this order. Stop short of full-file reads when
you can — skim for signals.
CLAUDE.md / AGENTS.md / .claude/CLAUDE.md (any of these
agent-instruction files): highest-priority source. These already
contain content the team has hand-curated for agents — sections
like "Things That Catch People Out", "Conventions", "Gotchas",
"Architectural decisions", "Migrations", and similar are designed
for exactly the kind of content memory captures. Treat each
H2/H3 subsection (or each bullet under such a heading) as a
candidate. Your job is to triage durability — not just
transcribe the file verbatim. If a bullet reads as task-specific or
transient, skip it; if it reads as "this is how things are here
and will be in six months", capture it.
README.md — flag anything mentioning: "deprecated", "DO NOT USE",
"WARNING", "legacy", "see also ", "incident", architectural
choices, naming conventions, env vars with surprising defaults.
docs/, docs/adrs/, docs/architecture/, ADRs/, decisions/,
.architecture/ — if any exist, scan titles and final-decision
sections. ADRs are the cleanest source of "decisions that aren't
obvious from code".
MIGRATIONS.md / migrations/ / db/migrations/ — in-flight
migrations are gold for lore. Look for "TODO", recent file dates,
companion code that handles both old + new schemas.
- Top-level
package.json / pyproject.toml / go.mod / Cargo.toml —
service name, peer-repo dependencies that suggest cross-repo
conventions worth capturing.
git log --oneline -50 — recent commit subjects often hint at:
in-flight migrations ("migrate X to Y"), deprecations ("remove
legacy Z"), incident fixes ("fix INC-NNN: …"), policy decisions.
- Grep for
// DEPRECATED, // TODO: remove, // WARNING:, // HACK: —
these often mark non-obvious project knowledge.
Step 3 — surface candidate drafts
Build a list of 5–10 candidate drafts grounded in what you found.
Present them to the user as a numbered list with the source citation:
Found these candidate items. Want me to draft any of them as lore?
- Don't touch
legacy/auth.ts except for security fixes. Use
requireSession() for new auth gates. (Source: README.md L42–55;
grep finds 12 active call sites of requireSession.)
- In-flight migration: accounts → organisations. New code uses
org_id; reporting still joins on account_id. (Source: commit
a4f12c0 + migrations/0017_accounts_to_orgs.sql.)
- Webhook retries cap at 2h backoff to avoid downstream DoS.
(Source: docs/adrs/0009-webhook-retry-cap.md, INC-411.)
…
Reply with the numbers to draft (e.g. 1, 3, 5) or skip with none.
I can also propose more items if I missed anything.
Skip items that are:
- generic programming advice the model already knows
- obvious from a single file's contents
- task-specific or session-specific
- anything containing apparent secrets / PII / regulated data
- already covered by an existing lore record (run
search_lore for
near-duplicate titles before proposing)
Step 4 — draft via suggest_lore
For each item the user picks, call suggest_lore with this shape:
suggest_lore({
title: "<short title — what is the rule / fact?>",
summary: "<one-paragraph summary, stands alone>",
body: "Source: <file/line or commit sha or doc path>\n\n<full detail / reasoning / evidence>\n\n(onboarded via /memory-onboard, <iso date>)",
repos: <array confirmed in Step 1>,
tags: ["induction", <topic-specific extras>],
source: <PR/ADR/incident URL if you found one>,
confidence: <"medium" if source URL is present, else "low">,
team: <if obvious from CODEOWNERS or similar>
})
Drafts can't claim high confidence regardless — that invariant is
enforced server-side. Don't try.
After each call, note the returned id and any possibleDuplicates
the server flagged. If possibleDuplicateCount > 0 or
possibleDuplicates is non-empty, tell the user before continuing:
"Draft <new-id> created. Memory flagged 2 possible duplicates:
<id1>, <id2>. Worth reviewing those alongside this one."
Step 5 — wrap up
When the user is done picking, output a final summary:
Created N drafts in <repo>:
Counter-drafts (from report_conflict, if any):
<id3> challenges <existingId>
Absence markers (from record_absence, if any):
<query> — <reason> (expires in 14 days)
Next steps:
memory review — interactive triage of the drafts
memory hooks install — opt-in: a Stop-hook nudges you to
review pending drafts at session end so they don't rot in the
queue (one-time-per-session, never nags)
Drafts are invisible to default search until approved. Absence
markers surface only on zero-hit searches matching the same
normalised query.
If the user wants to keep iterating, loop back to Step 3 with a
different angle (e.g. "now let's look at the test suite for
authoritative-checks lore", or "let's scan for incident-lesson signals
in the issues tracker").
Step 6 — (when invoked mid/end-of-session) ground in THIS session's work
The repo survey in Step 2 is a cold read. The higher-signal source,
when you have it, is the work the current session just did — what you
learned debugging, migrating, or fixing something here over the last
hour is exactly the non-obvious knowledge the next agent will lack.
If this skill is invoked after real work in the session (not a
first-touch cold start), before wrapping up ask yourself:
- Did I hit a gotcha that wasted time and will bite again? (a
non-obvious constraint, a surprising default, an ordering rule)
- Did I discover a convention by reading code that isn't written
down? (naming, auth, timezone, data-modelling)
- Did I steer away from a deprecated pattern after spotting it?
- Did I learn why a past decision was made that the code alone
doesn't explain?
For each "yes", propose it as a candidate draft (same numbered-list +
confirm flow as Step 3) with the session as the citation — e.g.
Source: discovered while implementing <task> this session. Only
durable, project-specific findings; skip anything transient or
already-obvious (same Step 3 skip rules apply).
When a finding is already captured in a commit you made this session,
tell the user the cheaper path instead of re-drafting it by hand:
"I committed the rationale in a4f12c0. You can draft that straight
from the message with memory suggest --from-commit a4f12c0 (it
auto-derives the commit permalink as the source) rather than me
retyping it."
This session-grounded pass is the difference between transcribing a
repo and capturing what was actually learned working in it.
Step 7 — (optional) map cross-repo boundaries
While surveying the repo (Step 2) you'll often spot integration points:
an event this service publishes, an endpoint it serves, a queue or table
another team owns. These are boundary edges — the substrate of the
cross-repo impact map.
- When you find a producer/consumer relationship, check the map first
with
find_dependents({ contract }), then record what's missing with
declare_boundary({ repo, contract, role: "provides" | "consumes", kind?, detail?, source? }). Like lore, edges land as drafts — the
human ratifies via memory boundary review.
- Use
provides when this repo OWNS / produces the contract;
consumes when it depends on one owned elsewhere.
- Don't invent edges. Only declare integration points you actually saw
in code/config (publish calls, route definitions, client calls, schema
references). Cite the evidence in
detail or source.
This is how the "change this contract, what does it affect?" query gets
populated — one onboarding at a time, per repo, aggregated via sync.
A note on search results
When you call search_lore during onboarding to check for
near-duplicates, the server ranks hits by relevance adjusted for trust
(sourced, higher-confidence, non-stale records first), so the top hits
are the ones most worth comparing against. If a response includes a
truncated: { shown, total } block, more records matched than were
returned — narrow the query or raise limit before concluding a topic
is uncovered.
Out of scope for this skill
- Don't promote, deprecate, or supersede records. Those are CLI-only
by design.
- Don't bulk-import existing docs as lore. Onboarding is
selective — the value is judgement about what's durable and
non-obvious, not volume. Transcribing every bullet of a doc floods the
review queue with noise and degrades the trust gate. Propose a focused
set; let the human ratify via
memory review.
- Don't enable restricted records (
includeRestricted / setting
restricted: true). If the user wants restricted lore, they author
it via the CLI with memory add --restricted.
- Don't claim contradictions you can't prove. If
search_lore
returns existing records that overlap (possibleConflicts populated),
that's the runtime overlap heuristic — surface it but let the human
decide. Only call report_conflict when a source-of-truth you just
read explicitly disagrees with the existing record (see Hard rule 7).
- Don't blanket-record absences. A
record_absence marker is only
warranted when the user confirms "the team has intentionally not
taken a stance on X". Inferring absence from "I didn't find anything"
would seed wrong markers that mislead the next agent.
- Don't install the Stop-hook on the user's behalf. Mention it
exists at wrap-up so they can opt in (
memory hooks install),
but installing it silently changes their .claude/settings.json —
that's their decision.
1---2name: memory-onboard3description: Use this skill when the user types `/memory-onboard` (or asks "set up memory for this repo" / "onboard this repo to memory" / "what should be in lore for this repo?"). It runs a repo-aware onboarding interview that produces DRAFT lore records grounded in concrete repo signals (README, ADRs, recent commits, deprecation markers, in-flight migrations). Requires the memory-mcp MCP server to be configured. Uses these MCP tools: search_lore / get_lore / suggest_lore (core), and optionally report_conflict (when a candidate item contradicts existing lore) and record_absence (when the user confirms a topic has no team policy yet). All suggest_lore / report_conflict output lands as drafts — the human approves via `memory review` afterwards. record_absence markers self-expire (default 14 days) and don't need review.4---56# /memory-onboard — repo-aware onboarding for memory78This skill is **the** way to seed a repo with lore. It earns its keep by9**reading the repo first** (README, ADRs, recent commits, deprecation10markers, in-flight migrations) so the proposed drafts are specific to11*this* codebase, with source citations — rather than inventing memory or12mechanically chunking every bullet in the docs (which produces mostly13noise and floods the review queue).1415Output: DRAFT records with source citations, plus optional absence16markers and boundary edges. Everything lands in `memory review` for a17human to ratify — the skill never promotes its own records.1819## Hard rules20211. **Every lore record this skill produces is a DRAFT.** Call22 `suggest_lore` (or `report_conflict` for counter-claims — also drafts),23 never any approval path. The human reviews with `memory review`.24 Exception: `record_absence` does NOT create a draft — it records a25 self-expiring "we checked, no policy" marker. Different primitive,26 different gate (see rule 6).272. **Every draft carries the tag `induction`** so it can be filtered later.28 Layer topic-specific extras as appropriate (`security`, `conventions`,29 `migrations`, `incident-lessons`, `invariants`, etc.). `report_conflict`30 counter-drafts are auto-tagged `conflict-report` by the server.313. **Cite sources in the body.** When a draft comes from a file or commit,32 include a one-line reference at the top of the `body` — e.g.33 `Source: README.md L42–55` or `Source: commit abc1234 "migrate accounts → organisations"`.34 This is the trust signal a reviewer needs.354. **Never put secrets, credentials, personal data, regulated data, or36 anything that looks like a token** into any lore record. If a candidate37 item contains something like that, skip it and tell the user why.385. **Skip the obvious.** "We use TypeScript", "run the tests before39 committing", and other things a model already knows about a typical40 codebase belong in `CLAUDE.md` (or nowhere), not in lore. Aim for41 non-obvious, high-consequence knowledge.426. **Use `record_absence` sparingly.** If the user explicitly confirms43 "we don't have a policy on X yet, and that's intentional", that's44 a legitimate absence marker — call `record_absence({ query: "<topic>",45 reason: "<why no policy>", repo: <repo> })`. Don't infer absence46 from "I didn't find anything in the README"; the user has to confirm47 it. Markers self-expire (14 days default) so they fade automatically48 if the team takes a stance later.497. **Use `report_conflict` when you find a contradiction, not when you50 find a duplicate.** If `search_lore` returns an existing record and51 the source-of-truth you just read **disagrees** with it (e.g. README52 says "Argon2id", existing lore says "scrypt"), that's a `report_conflict`53 moment. If the existing record just covers the same topic without54 contradicting, leave it alone — `possibleConflicts` in search results55 handles benign overlap.5657## Procedure5859Follow these steps in order. Confirm with the user as the comments60indicate.6162### Step 1 — confirm scope6364Detect the current repo's short name (from `git config --get remote.origin.url`65or, failing that, from the working directory name). Confirm with the user:6667> "I'll onboard `<repo-name>` to memory. Anything I should add to68> that, or remove? (e.g. `payments-svc, auth-svc` for cross-repo notes)"6970Capture the final `repos` array — every draft created in this session71will carry it.7273### Step 2 — survey the repo7475Read these sources, in this order. Stop short of full-file reads when76you can — skim for signals.77781. **`CLAUDE.md` / `AGENTS.md` / `.claude/CLAUDE.md`** (any of these79 agent-instruction files): **highest-priority source.** These already80 contain content the team has hand-curated for agents — sections81 like "Things That Catch People Out", "Conventions", "Gotchas",82 "Architectural decisions", "Migrations", and similar are designed83 for exactly the kind of content memory captures. Treat each84 H2/H3 subsection (or each bullet under such a heading) as a85 candidate. Your job is to **triage durability** — not just86 transcribe the file verbatim. If a bullet reads as task-specific or87 transient, skip it; if it reads as "this is how things are here88 and will be in six months", capture it.892. **`README.md`** — flag anything mentioning: "deprecated", "DO NOT USE",90 "WARNING", "legacy", "see also <ADR>", "incident", architectural91 choices, naming conventions, env vars with surprising defaults.923. **`docs/`, `docs/adrs/`, `docs/architecture/`, `ADRs/`, `decisions/`,93 `.architecture/`** — if any exist, scan titles and final-decision94 sections. ADRs are the cleanest source of "decisions that aren't95 obvious from code".964. **`MIGRATIONS.md` / `migrations/` / `db/migrations/`** — in-flight97 migrations are gold for lore. Look for "TODO", recent file dates,98 companion code that handles both old + new schemas.995. **Top-level `package.json` / `pyproject.toml` / `go.mod` / `Cargo.toml`** —100 service name, peer-repo dependencies that suggest cross-repo101 conventions worth capturing.1026. **`git log --oneline -50`** — recent commit subjects often hint at:103 in-flight migrations ("migrate X to Y"), deprecations ("remove104 legacy Z"), incident fixes ("fix INC-NNN: …"), policy decisions.1057. **Grep for `// DEPRECATED`, `// TODO: remove`, `// WARNING:`, `// HACK:`** —106 these often mark non-obvious project knowledge.107108### Step 3 — surface candidate drafts109110Build a list of 5–10 *candidate* drafts grounded in what you found.111Present them to the user as a numbered list with the source citation:112113> Found these candidate items. Want me to draft any of them as lore?114>115> 1. **Don't touch `legacy/auth.ts` except for security fixes.** Use116> `requireSession()` for new auth gates. *(Source: README.md L42–55;117> grep finds 12 active call sites of `requireSession`.)*118> 2. **In-flight migration: accounts → organisations.** New code uses119> `org_id`; reporting still joins on `account_id`. *(Source: commit120> a4f12c0 + migrations/0017_accounts_to_orgs.sql.)*121> 3. **Webhook retries cap at 2h backoff** to avoid downstream DoS.122> *(Source: docs/adrs/0009-webhook-retry-cap.md, INC-411.)*123> …124>125> Reply with the numbers to draft (e.g. `1, 3, 5`) or skip with `none`.126> I can also propose more items if I missed anything.127128Skip items that are:129130- generic programming advice the model already knows131- obvious from a single file's contents132- task-specific or session-specific133- anything containing apparent secrets / PII / regulated data134- already covered by an existing lore record (run `search_lore` for135 near-duplicate titles before proposing)136137### Step 4 — draft via `suggest_lore`138139For each item the user picks, call `suggest_lore` with this shape:140141```ts142suggest_lore({143 title: "<short title — what is the rule / fact?>",144 summary: "<one-paragraph summary, stands alone>",145 body: "Source: <file/line or commit sha or doc path>\n\n<full detail / reasoning / evidence>\n\n(onboarded via /memory-onboard, <iso date>)",146 repos: <array confirmed in Step 1>,147 tags: ["induction", <topic-specific extras>],148 source: <PR/ADR/incident URL if you found one>,149 confidence: <"medium" if source URL is present, else "low">,150 team: <if obvious from CODEOWNERS or similar>151})152```153154Drafts can't claim `high` confidence regardless — that invariant is155enforced server-side. Don't try.156157After each call, note the returned `id` and any `possibleDuplicates`158the server flagged. If `possibleDuplicateCount > 0` or159`possibleDuplicates` is non-empty, tell the user before continuing:160161> "Draft `<new-id>` created. Memory flagged 2 possible duplicates:162> `<id1>`, `<id2>`. Worth reviewing those alongside this one."163164### Step 5 — wrap up165166When the user is done picking, output a final summary:167168> Created N drafts in `<repo>`:169>170> - `<id1>` <title1>171> - `<id2>` <title2>172> …173>174> Counter-drafts (from `report_conflict`, if any):175>176> - `<id3>` challenges `<existingId>` <one-line observation>177>178> Absence markers (from `record_absence`, if any):179>180> - `<query>` — `<reason>` (expires in 14 days)181>182> Next steps:183> - `memory review` — interactive triage of the drafts184> - `memory hooks install` — opt-in: a Stop-hook nudges you to185> review pending drafts at session end so they don't rot in the186> queue (one-time-per-session, never nags)187>188> Drafts are invisible to default search until approved. Absence189> markers surface only on zero-hit searches matching the same190> normalised query.191192If the user wants to keep iterating, loop back to Step 3 with a193different angle (e.g. "now let's look at the test suite for194authoritative-checks lore", or "let's scan for incident-lesson signals195in the issues tracker").196197### Step 6 — (when invoked mid/end-of-session) ground in THIS session's work198199The repo survey in Step 2 is a *cold* read. The higher-signal source,200when you have it, is the work the current session just did — what *you*201learned debugging, migrating, or fixing something here over the last202hour is exactly the non-obvious knowledge the next agent will lack.203204If this skill is invoked after real work in the session (not a205first-touch cold start), before wrapping up ask yourself:2062071. **Did I hit a gotcha that wasted time and will bite again?** (a208 non-obvious constraint, a surprising default, an ordering rule)2092. **Did I discover a convention by reading code that isn't written210 down?** (naming, auth, timezone, data-modelling)2113. **Did I steer away from a deprecated pattern after spotting it?**2124. **Did I learn why a past decision was made** that the code alone213 doesn't explain?214215For each "yes", propose it as a candidate draft (same numbered-list +216confirm flow as Step 3) with the session as the citation — e.g.217`Source: discovered while implementing <task> this session`. Only218durable, project-specific findings; skip anything transient or219already-obvious (same Step 3 skip rules apply).220221When a finding is already captured in a commit you made this session,222tell the user the cheaper path instead of re-drafting it by hand:223224> "I committed the rationale in `a4f12c0`. You can draft that straight225> from the message with `memory suggest --from-commit a4f12c0` (it226> auto-derives the commit permalink as the source) rather than me227> retyping it."228229This session-grounded pass is the difference between transcribing a230repo and capturing what was actually learned working in it.231232### Step 7 — (optional) map cross-repo boundaries233234While surveying the repo (Step 2) you'll often spot integration points:235an event this service publishes, an endpoint it serves, a queue or table236another team owns. These are **boundary edges** — the substrate of the237cross-repo impact map.238239- When you find a producer/consumer relationship, check the map first240 with `find_dependents({ contract })`, then record what's missing with241 `declare_boundary({ repo, contract, role: "provides" | "consumes",242 kind?, detail?, source? })`. Like lore, edges land as **drafts** — the243 human ratifies via `memory boundary review`.244- Use `provides` when this repo OWNS / produces the contract;245 `consumes` when it depends on one owned elsewhere.246- Don't invent edges. Only declare integration points you actually saw247 in code/config (publish calls, route definitions, client calls, schema248 references). Cite the evidence in `detail` or `source`.249250This is how the "change this contract, what does it affect?" query gets251populated — one onboarding at a time, per repo, aggregated via `sync`.252253### A note on search results254255When you call `search_lore` during onboarding to check for256near-duplicates, the server ranks hits by relevance *adjusted for trust*257(sourced, higher-confidence, non-stale records first), so the top hits258are the ones most worth comparing against. If a response includes a259`truncated: { shown, total }` block, more records matched than were260returned — narrow the query or raise `limit` before concluding a topic261is uncovered.262263## Out of scope for this skill264265- **Don't promote, deprecate, or supersede** records. Those are CLI-only266 by design.267- **Don't bulk-import** existing docs as lore. Onboarding is268 *selective* — the value is judgement about what's durable and269 non-obvious, not volume. Transcribing every bullet of a doc floods the270 review queue with noise and degrades the trust gate. Propose a focused271 set; let the human ratify via `memory review`.272- **Don't enable restricted records** (`includeRestricted` / setting273 `restricted: true`). If the user wants restricted lore, they author274 it via the CLI with `memory add --restricted`.275- **Don't claim contradictions you can't prove.** If `search_lore`276 returns existing records that overlap (`possibleConflicts` populated),277 that's the runtime overlap heuristic — surface it but let the human278 decide. Only call `report_conflict` when a source-of-truth you just279 read explicitly disagrees with the existing record (see Hard rule 7).280- **Don't blanket-record absences.** A `record_absence` marker is only281 warranted when the user confirms "the team has intentionally not282 taken a stance on X". Inferring absence from "I didn't find anything"283 would seed wrong markers that mislead the next agent.284- **Don't install the Stop-hook on the user's behalf.** Mention it285 exists at wrap-up so they can opt in (`memory hooks install`),286 but installing it silently changes their `.claude/settings.json` —287 that's their decision.