save
Skill2 starsChanged 23 days agoMITView on GitHub
Session summary extraction. review recent session, extract preferences/decisions/context/voice/learnings, write to the appropriate memory/ tier files.
36 other projects use a version of this.
Adopted by
Most recently taken up by
- FabianoArthur/claude-code-kitchentheir own version, first seen Nov 8, 2026
- paulogabriel/beryltheir own version, first seen Nov 8, 2026
- matthewwong525/WongStacktheir own version, first seen Nov 8, 2026
- pche-broken-artist/forge-of-thoughttheir own version, first seen Nov 6, 2026
- egregore-labs/egregoretheir own version, first seen Nov 6, 2026
- vidit19sharma/neogentstheir own version, first seen Nov 1, 2026
Used with
Projects with it also use load, ingest and 8 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
TheLatentSpaceLabSkillload
Load a document into memory for RAG
Also in 4 projects that use this
JaimeGBASkillingest
Digest an external source (article, paper, transcript, URL, book chapter) and integrate its content into the knowledge base
Also in 8 projects that use this
ArtemXTechSkillquery
Query data from this vault. USE WHEN user asks about projects, clients, tasks, daily notes. Use grep to extract frontmatter - do NOT read full files.
Also in 4 projects that use this
GoogleSkilldashboard
Configures and launches the GKE Capacity & Triage Dashboard scoped to a GCP project ID, GKE cluster name, or target ML workload ID. Uses the configure-and-launch-dashboard action and launch-workload-dashboard workflow to verify local dashboard health, discover cluster capacity, trigger live scans, and generate deep-linked URLs. Use when the user types "/dashboard", says "launch dashboard", "open dashboard", "show capacity", or "view triage dashboard" with a project, cluster, or workload. Don't use for general workload log querying or automated failure attribution (use the troubleshoot skill).
Also in 4 projects that use this
Microsoft AzureSkilllint
Run all linting and spell checking for TypeScript and Rust code. Run this before committing to catch style issues, clippy warnings, and misspellings.
Also in 5 projects that use this
AnthropicSkillstatus
Case status summary by audience — client-facing (plain language), internal (for the professor), or court-ready (formal caption format per local rules). Same facts, different framing and depth. Use when a student needs to update the client, brief the professor, or prepare a court status report.
Also in 6 projects that use this
Other versions36 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 36
- AgriciDaniel/claude-obsidian★ 16ksame name
- egregore-labs/egregore★ 293same name
- romarayt/raytsystem-public-os★ 140same name
- thiagofinch/mega-brain★ 95same name
- sturlese/hippocampus★ 28same name
- endlessblink/master-plan★ 26same name
- pche-broken-artist/forge-of-thought★ 12same name
- CarbeneAI/Forge★ 9same name
- seongjaeryu/bindly-claude-code★ 8same name
- ARCASSystems/FounderOS★ 7same name
26 more not listed
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 repository57 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- llms.txtllms.txt
- advisorSkill
- agent-dispatchSkill
- arenaSkill
- audit-pypi-model-packageSkill
- branching-workflowSkill
- code-reviewSkill
- criticSkill
- cron-child-oauth-auditSkill
- daily-forestSkill
- deep-researchSkill
- diagnose-cron-timeoutSkill
- dreamingSkill
- eod-summarySkill
- filingSkill
- forest-synthesisSkill
- goalsSkill
- graph-hygieneSkill
- ideaSkill
- inline-tagsSkill
- intel-analyzerSkill
- longformSkill
- loop-experimentSkill
- loop-librarySkill
- meta-memory-reviewSkill
- office-hoursSkill
- open-loopsSkill
- plan-ceo-reviewSkill
- plan-design-reviewSkill
- prdSkill
- progressive-disclosureSkill
- reality-feedback-createSkill
- reality-review-weeklySkill
- recallSkill
- reconcile-extractionSkill
- redactSkill
- repo-auditSkill
- research-digestSkill
- review-gateSkill
- run-long-job-detachedSkill
- scopeSkill
- self-auditSkill
- shadow-test-local-classifierSkill
- signal-scorerSkill
- skill-auditSkill
- skill-chainingSkill
- spawn-agent-in-tenantSkill
- spawn-tenantSkill
- split-log-rows-by-session-kindSkill
- subagent-delegationSkill
- telegram-dump-routerSkill
- telegram-reply-toolSkill
- verify-stackSkill
- wave-planSkill
- weekly-retroSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
34 rules. 0 are common, 20 are distinctive, and 14 are very specific to this project.
0
Common
Most of the 31 edited versions we read keep these.
20
Distinctive
This author's own choices. Worth a look.
14
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 10
Run this when the user types /save, when session rotation hits ~20 exchanges, or when the Stop-hook signal bridge dispatches /save to the …
- Distinctive: line 19
Look at the ACTUAL session transcript for this run.
- Very specific: line 56
If small: append to an existing memory/Context/<subject>.md or memory/Infra/<component>.md If a new subject is big enough: create a new file
- Distinctive: line 57
If a new subject is big enough: create a new file
- Distinctive: line 95
Non-reusable debugging traces: Read-only inspections and speculative diagnoses stored as durable knowledge.
- Distinctive: line 97
Write it only once you know what it WAS, and only if the mechanism generalises.
- Distinctive: line 99
When this was measured on a real corpus before adoption, hundreds of existing Learnings entries scored against the four traps came in very …
- Distinctive: line 125
Prefer UPDATING existing files over creating new ones
- Distinctive: line 127
Keep entries concise. future sessions pay cost to read them
- Very specific: line 128
Use the existing file format (key:: value for Preferences, dated entries for Decisions/Learnings)
- Very specific: line 133
When a new entry replaces or corrects an older one, the NEW entry gets supersedes:: <file> <date> "<old heading>".
- Very specific: line 136
Only mark the old entry when the edge is EXPLICIT (you read both and the new one clearly replaces the old).
- Distinctive: line 138
Contradiction check: Before writing any DECISION, CONTEXT or LEARNING that states a fact (a status, a number, a date, a who-did-what), run …
- Distinctive: line 151
Intentions: If a candidate is a PLAN or a promised follow-up with a date ("check X on Friday", "follow up if no reply by Monday"), it is …
- Very specific: line 155
Every NEW ## entry written to Learnings.md, Decisions.md, or a Context//Infra//Feedback/ dossier gets a provenance line on the line …
- Very specific: line 170
--ingest untrusted: when the entry's reasoning leaned on external content pulled this session (a fetched page, a paper, an email, OSINT, … - Distinctive: line 177
Do NOT backfill stamps onto older entries.
- Very specific: line 199
Check memory/session-bootstrap.md for an ## Active Handoff block:
- Distinctive: line 202
If the current /save run is mid-task and long work continues: update the block with the latest timestamp + revised status + revised …
- Very specific: line 203
If no handoff block exists and work is paused / long-running: write a fresh block using the template in session-bootstrap.md (## Active …
- Distinctive: line 204
If no handoff block exists and work is complete: do nothing. The block is only for ongoing work.
- Very specific: line 212
When found, draft a SKILL CANDIDATE at outputs/raw/skill-candidates/<slug>.md with frontmatter:
- Distinctive: line 244
After the write step, run:
- Very specific: line 251
If the script reports touched: [g-..., ...], include them in the Step 5 confirm message ("💾 saved.
- Very specific: line 253
Skip this step: if: no outputs/raw/ writes happened in the session (e.g.
- Distinctive: line 269
After extraction completes (Step 1-3) but BEFORE the Step 6 chat send, score the extraction on 3 dimensions.
- Very specific: line 283
If avg < 4: include a single-clause flag in the Step 6 chat reply, e.g.
- Distinctive: line 291
Boundary: if the session was brief / temp-mode was on / the "nothing worth saving" path triggered → skip Step 5.5 entirely.
- Very specific: line 299
Heads-up requirement: if ACTIVE_BYTES_SINCE_COMPACT is >8MB at the start of Step 5 (check via source scripts/session/lib_active_session.sh …
- Distinctive: line 307
No reply_to needed unless responding to a specific message.
- Distinctive: line 311
When writing a new fact, ask *what KIND of memory is it?*
- Distinctive: line 324
NEVER: create empty files or placeholder entries.
- Distinctive: line 329
If the session was brief / nothing substantive happened / temp mode was on: respond "nothing worth saving" and exit
- Distinctive: line 330
If the session was heavy (multiple decisions / substantive work): multiple categories will have entries, that's expected
“Common” is measured: kept by at least 6 in 10 of the 31 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
/save. Session Summary Extraction
Run this when the user types /save, when session rotation hits ~20 exchanges, or when the Stop-hook signal bridge dispatches /save to the live REPL.
What this does
Review the current session in memory and extract durable facts into the right tier of the memory system. This is the primary preservation step against context compression loss.
Procedure
Step 1. Scope the review
Look at the ACTUAL session transcript for this run. Focus on:
- User preferences expressed (explicit or implicit)
- Decisions made with context + reasoning
- Ongoing project / deal / relationship facts that changed
- New writing-style observations
- Insights or learnings worth remembering across sessions
Skip:
- Quick Q&A exchanges
- Ephemeral debugging output
- Things already documented in existing memory files
Step 1.7. Musing Harvest
Step 1's skip-rule ("skip quick Q&A / ephemeral chat") is correct for everything EXCEPT one signal class. The operator's offhand musings are the richest, most under-captured source of worldview + temperament + cognitive-style modeling (operators systematically under-rate their own tacit output). This step carves out that one exception.
Re-scan the transcript specifically for casual-register musings that reveal: how they think (cognitive style, mental models, what they reach for), what they value / how they decide (temperament, triggers, defaults), or a worldview/thesis position stated offhand rather than in a structured answer.
Operator-tacit filter (hard gate, this is the anti-bloat valve): capture a musing ONLY if "only someone in the operator's exact seat would think or say this." Generic offhand lines, reactions, logistics, jokes-without-signal → still skipped per Step 1. If a musing would be unremarkable coming from any operator, it is not signal.
Routing:
- worldview / thesis / market-position musing → append to
memory/projects/<active>.mdunder a## Voice Excerpts (verbatim worldview anchors)section (dated block, same format as the voice-authoring interview phase, INCLUDING thetopics:: [..]multi-tag line from the controlled vocab in your interview notes (optional, not bundled)). This feeds the interview-sharpening corpus, so it compounds into future interview questions automatically. - temperament / values / how-they-decide / communication-pattern →
memory/USER.md(durable model) and/ormemory/user-model.md(behavioral, dreaming-updated). - a falsifiable cross-session insight → the normal LEARNINGS path (Step 2 cat 5).
Discipline: every harvested musing still passes the Step 2.5 write-gate AND Step 2.6 confidence treatment. no bypass. Verbatim > paraphrase for worldview anchors (capture their actual phrasing). If nothing clears the operator-tacit filter, this step produces nothing. that is the correct outcome for a logistics-only session, not a failure.
Step 2. Extract into 5 categories
- PREFERENCES: workflow, formatting, behavior rules the user stated
Format:
key:: valuepairs, append tomemory/Preferences.md(dedup on key::) Wisdom-layer note: when adding a behavioral rule (port from arXiv 2604.11364), include anevidence::line tracking[applied_count, last_applied_date, outcome_distribution]. Initial state on first save:evidence:: [1, YYYY-MM-DD, untested]. graph-hygiene check #12 audits stale rules (zero recent evidence = speculative, may not be working). - DECISIONS: architectural / strategic / tactical choices with context
Format: dated block in
memory/Decisions.mdwithcontext::,decision::,reasoning::,status:: - CONTEXT: ongoing facts about subjects (deals, projects, relationships, systems)
If small: append to an existing
memory/Context/<subject>.mdormemory/Infra/<component>.mdIf a new subject is big enough: create a new file - VOICE: writing patterns: sentence length, word choice, tone, language mix, formatting habits
Append to
memory/Voice-Profile.md - LEARNINGS: insights worth remembering across sessions, tagged
Append to
memory/Learnings.mdwith date + tags Wisdom-layer note: like Preferences, learnings can carry anevidence::field. Optional, but useful when the learning makes a falsifiable claim ("X always causes Y"). Fix-owed tag: when a LEARNINGS entry names a SPECIFIC, SCOPED, un-shipped fix (not a pure observation), add the tagfix-owedto its tag line. Meta-memory-review's lens-D worklist is thengrep -l 'fix-owed' memory/Learnings.mdminus anything carrying aclosed_by::marker. Converts the weekly recurring-failure scan from a full re-read into a deterministic tag-grep. A pure observation ("X tends to cause Y") is NOT fix-owed; only an entry naming a concrete fix that has not shipped. Clear the tag (or addclosed_by::) once the fix ships. Recurrence tag: when a LEARNINGS entry is a REPEAT of a prior failure mode (not a first observation), tag it#recurrence-Nxon the tag line, where N = how many times this shape has now fired (e.g.#recurrence-4x). Optionalrecurrence:: Nfield mirrors it as structured data. Forward-only. no reformat of history. This makes the weekly recurrence scan a deterministicgrep '#recurrence-'sorted by N, instead of guessing from freeform prose ("4th occurrence", "again", "still"). A first-time observation gets NO tag; the tag appears only on the 2nd+ occurrence. Pairs withfix-owed: a recurring un-shipped fix carries both (fix-owed #recurrence-3x).
Step 2.5. Write-gate (MemReader port)
Adapted from MemReader (arXiv 2604.07877): actively decide whether to write each candidate, don't just dump everything Step 2 surfaced. Apply this 3-question gate to EVERY candidate before it goes to disk:
- Value: is this novel? Does it add information not already in the same file/section, OR materially refine what's there? If it duplicates an existing entry without adding nuance, DROP.
- Reference clarity: are the referents in this entry unambiguous to a future-agent with no session memory? "the operator said yes" without context = ambiguous, drop or expand. "the operator greenlit X for reason Y on 2026-MM-DD" = clear, keep.
- Completeness: is enough context attached for the entry to be useful 30 days later? If the entry is just a fragment that needs the current session to interpret, either expand it OR DROP.
Items failing the gate → don't write. Items passing → proceed to Step 3.
Anti-pattern this guards against: extracting "the operator was friendly today" / "good session, lots done" / "we discussed X". vague low-value chatter that bloats memory tier-2 without ever helping a future query. Memory should be expensive to write so it stays cheap to read.
4th question, the reject list (from GovMem arXiv 2607.02579). The three questions above catch vague chatter. They do NOT catch entries that look like solid technical lessons but transfer nothing. GovMem's external human adjudication rejected all 133 candidates it reviewed, and the failures clustered into four named shapes. That adjudication is the only part of that paper backed by real human review rather than synthetic data, so it is worth more than its scoring method. DROP if the candidate is:
- Boilerplate verification. Command echoes, test output, warning banners, or an exit code presented as if they were the finding. "Ran it, exit 0" is not a lesson. What the exit code let you CONCLUDE might be.
- Task-local narration. What was attempted in one specific task, in sequence. "First I tried X, then Y worked." Useful in the session, worthless 30 days out unless a transferable rule is stated explicitly.
- File dumps. A source listing, config block, or directory tree converted into a procedural memory without demonstrating that the procedure is correct or general.
- Non-reusable debugging traces. Read-only inspections and speculative diagnoses stored as durable knowledge. "Checked whether it was the cache, it wasn't" is a dead end, not a finding. Write it only once you know what it WAS, and only if the mechanism generalises.
When this was measured on a real corpus before adoption, hundreds of existing Learnings entries scored against the four traps came in very low, and the one high count collapsed to mostly legitimate entries on manual reading. So this is preventive, not remedial. Do not launch a cleanup pass over existing entries on the strength of this list.
Step 2.6. Confidence + promotion gate (atomic-instinct lift)
Lifted from a continuous-learning pattern (affaan-m/everything-claude-code). Closes the gap where a one-off Learnings entry carries the same weight as a 5-times-confirmed one.
Any LEARNINGS or PREFERENCES candidate that makes a falsifiable behavioral claim ("X causes Y", "always do Z", "pattern P recurs") gets two extra fields appended to its entry:
confidence:: <0.3-0.9>. start at 0.3 on the first single observation. On each independent re-confirmation in a later session, bump +0.1 to +0.2. Cap at 0.9, never 1.0 (predictive not certain, same collusion-floor reasoning as the content critic: an LLM-derived pattern is never proven).scope:: project:<name> | global.project:<name>if the claim was only observed inside one project/context (prevents cross-project contamination: a content pattern is not automatically a pipeline pattern).globalonly if observed across 2+ distinct contexts.
Promotion gate (atomic-instinct rule): a Learnings entry only hardens into a Preference (always-active rule) or a skill edit when ALL of:
confidence:: >=0.8scope:: global(observed across 2+ distinct projects/contexts)>=20cumulative observations OR explicit operator confirmation ("yes, always do this")
Until the gate passes, it stays an episodic Learnings entry (recall-fetched, not always-loaded). This keeps speculative single-observation patterns out of tier-1 reply-cost. The existing evidence:: [applied_count, last_date, outcome] array (Step 2 items 1+5) is the raw substrate; confidence:: is the derived scalar the gate reads. graph-hygiene check #12 already audits stale rules; this gate is the inbound side of the same discipline.
Skip for non-falsifiable entries (pure factual context, dated decisions, subject dossiers). Confidence only applies to claims that could later be proven wrong.
Step 3. Write
For each extracted item that passed the Step 2.5 gate:
- Prefer UPDATING existing files over creating new ones
- Dedup: check if the fact is already stored before writing
- Keep entries concise. future sessions pay cost to read them
- Use the existing file format (
key:: valuefor Preferences, dated entries for Decisions/Learnings)
Step 3.1. Validity fields and write-time contradiction check
Validity fields (PACMI convention, arXiv 2610.05732), for Decisions AND Learnings:
- When a new entry replaces or corrects an older one, the NEW entry gets
supersedes:: <file> <date> "<old heading>". If it builds on an older entry that could later turn out wrong, adddepends-on:: <same ref form>. - The OLD entry gets exactly one edit: a
status::line set tosuperseded,disputed(newer evidence contradicts it, not settled) orretracted(shown wrong). For a dated bullet, indent it under the bullet (status:: superseded). Keep the old heading and text: history is evidence. status::means "is this still true". Ship state goes inoutcome::. Legacy free-textstatus::values read as active, so never mass-migrate.- Only mark the old entry when the edge is EXPLICIT (you read both and the new one clearly replaces the old). A guess stays a note in the new entry. Check with
python3 scripts/memory/memory_supersession_check.py(read-only).
Contradiction check. Before writing any DECISION, CONTEXT or LEARNING that states a fact (a status, a number, a date, a who-did-what), run it past the existing memory:
python3 scripts/memory/memory_conflict_check.py --text "<the candidate entry>"Exit 0 = nothing related disagrees, write it. Exit 1 = one or more related entries are flagged (status flip, number drift, date drift, negation mismatch). For each flagged neighbour, decide now:
- the new entry supersedes it (the usual case: state changed): mark the old one per the validity fields above, then write the new entry;
- the old entry is right and the candidate is wrong: fix or drop the candidate;
- both are true (different scope, different date, different subject): make the scope explicit in the candidate so the two cannot be read as the same fact.
The script flags, it never decides. Flags are noisy on long blocks; read the quoted sentence before acting. It reads the live files, so it also sees what this same save already wrote. Why: two live versions of one fact (a count that read 88, 105 and 122 in three files) get picked up by a later session as current. Resolving at write time is cheaper than a cleanup pass.
Intentions. If a candidate is a PLAN or a promised follow-up with a date ("check X on Friday", "follow up if no reply by Monday"), it is not a fact. Record it with python3 scripts/memory/intentions.py add "<what>" --due YYYY-MM-DD --source "<file or message ref>". Close it with intentions.py done <id> in the same turn it is handled.
Step 3.2. Provenance stamp
Every NEW ## entry written to Learnings.md, Decisions.md, or a Context//Infra//Feedback/
dossier gets a provenance line on the line immediately BELOW its heading:
python3 scripts/memory/lib_provenance.py stamp --support once --ingest clean
# -> provenance:: agent=<name> session=2026-07-20 support=once ingest=cleanPlacement is not cosmetic: vector_brain chunks on ## boundaries, so a line directly under the
heading rides inside that chunk and shows up in recall output for free. Put it anywhere else and
the stamp can end up in a different chunk than the claim it describes, which is worse than no stamp.
Set the two fields honestly, they are the whole point:
--supportoncefor something observed one time.NxONLY when N independent incidents support it. Restating the same incident in three entries is stilloncein each. Do not inflate.--ingest untrustedwhen the entry's reasoning leaned on external content pulled this session (a fetched page, a paper, an email, OSINT, an external research digest).cleanwhen it came from your own code, data, files, or observed tool behaviour. This is the belief-path flag: "authority is the envelope" blocks the instruction path, but untrusted content can still shift what you CONCLUDE, and that conclusion then gets written with genuinely legitimate agent provenance that no provenance check can catch.
Do NOT backfill stamps onto older entries. Their true origin is unrecoverable and inventing one manufactures exactly the false confidence this exists to prevent. Unstamped means unknown.
Sanity check after a run: python3 scripts/memory/lib_provenance.py audit. It reports coverage
and, more usefully, same-session clusters: k entries sharing one session are k restatements of
one origin, not k independent confirmations. Expect your own run to appear there. That is correct.
Step 3.3. SHIPPED / LIVE requires a verified_working:: observation
BUILT and LIVE read the same in memory, so a later review cannot tell "code exists" from "code observed producing effect". Any entry that claims a system is SHIPPED, LIVE, or DEPLOYED MUST carry a verified_working:: line with a DATE plus the observation that proves EFFECT, not existence:
verified_working:: 2026-08-23: cron fired 4x, last_run 08-22T22:00, wrote 3 rows to reality_feedback.sqlite- The observation is an EFFECT (fired N times, produced N outputs, a counter moved), never "script exists" or "cron created". A scheduled task with
run_count: 0is BUILT by definition, never LIVE. - An artifact not yet observed running through its REAL trigger (the scheduler, the hook, the pipeline) is written as BUILT until an effect is seen. Downgrade the label rather than assert a state you have not observed.
- This binds the agent's own work in the same session: a script tested by hand is BUILT. A cron you just created is not LIVE; its first real firing is the earliest it can be.
- Cite the level from
knowledge/evidence-ladder.mdwith the observation (L4 ran it, L5 reproduced on the live surface).
Step 3.5. Active Handoff block management (GSD pattern)
Check memory/session-bootstrap.md for an ## Active Handoff block:
- If the current /save run is at task completion: clear the block (replace content with
(none. no active handoff)). The work is done, the extract went to Decisions/Learnings, the handoff is no longer needed. - If the current /save run is mid-task and long work continues: update the block with the latest timestamp + revised status + revised next_action. This is your resume anchor if a watchdog restart fires.
- If no handoff block exists and work is paused / long-running: write a fresh block using the template in session-bootstrap.md (
## Active Handoffsection### Handoff block format). Fill in task, status, artifacts, pending, relevant_paths, next_action. - If no handoff block exists and work is complete: do nothing. The block is only for ongoing work.
This keeps session-bootstrap.md's Active Handoff section synced with reality at every /save cycle.
Step 3.6. Skill crystallization check (GenericAgent-pattern port)
Scan the session for tasks where the agent executed 3+ novel steps that don't map to an existing skill in skills/_index.md. "Novel" = a sequence of tool calls / file ops / scripts figured out from scratch, not from following a documented skill procedure.
When found, draft a SKILL CANDIDATE at outputs/raw/skill-candidates/<slug>.md with frontmatter:
---
name: <slug>
description: <one-line. what task does this enable>
trigger: <natural-language phrases that should invoke it>
status: candidate (drafted by /save 2026-MM-DD, awaiting /review)
parent_session: <jsonl filename or short id>
---
# <Skill Name>
## When to use
<2-3 sentences>
## Procedure
1. Step description (with the actual tool/command used)
2. ...
3. ...
## Notes / gotchas
- <whatever surprised me / what I wish I'd known>Don't auto-promote to skills/. The candidate sits in outputs/raw/skill-candidates/ until /review approves and the operator moves it. Same review pipeline as raw outputs.
Skip if: the novel sequence was a one-time investigation (debugging, audit, sweep) unlikely to recur. Skill creation should serve future runs, not document one-off work.
Anti-pattern this guards against: institutional knowledge bleeding out on every compact. Without this check, the agent solves the same novel problem multiple times because the previous solve only existed in the transcript.
Step 3.7. Touch active goals (/goals integration)
After the write step, run:
python3 scripts/memory/goal_touch_session.py --since-hours 24The script scans outputs/raw/**/*.md modified in the last 24h for frontmatter goal: g-XXXX-XX-XX-NNN tags. For each unique goal id found, it bumps sessions_touched + last_advanced in memory/state/active_goals.json. Idempotent. Safe on an empty registry.
If the script reports touched: [g-..., ...], include them in the Step 5 confirm message ("💾 saved. ... touched goals: g-X, g-Y."). If touched is empty, no surface needed.
Skip this step if: no outputs/raw/ writes happened in the session (e.g. pure conversation, no substantive output). The goal-touch is for outputs that explicitly tag a goal, not session-level metadata.
Step 4. Log
Append a one-line summary to logs/session.jsonl:
{"ts":"<ISO>","level":"info","persona":"agent","category":"save","event":"session save. N items extracted","breakdown":{"preferences":X,"decisions":Y,"context":Z,"voice":A,"learnings":B}}Step 5. Confirm briefly
One short message (not a wall of text):
"💾 saved. N items across {categories with content}. {1-sentence highlight of the most important extract}."
Step 5.5. Self-Judge (LLM-as-Judge pattern, MVP spec)
After extraction completes (Step 1-3) but BEFORE the Step 6 chat send, score the extraction on 3 dimensions. This is a self-judgement, NOT a separate model call (the model is already running this skill, this just adds a meta-cognition step).
Dimensions to score (1-5 each):
- Completeness: did this run capture all preference shifts / decisions / context updates that happened in the session? Is anything important left in the transcript that should have been extracted? Be honest: 5 = full coverage, 3 = missed 1-2 minor items, 1 = missed something obvious.
- Dedup quality: did the writes correctly check existing files for duplicates before append? Are any new entries actually rephrased duplicates of existing entries? 5 = clean dedup, 3 = 1-2 near-duplicates slipped, 1 = significant duplication.
- Relevance: are the extracted items genuinely worth durable storage, or padding the count? 5 = every item earns its place, 3 = 1-2 borderline items, 1 = ≥3 items shouldn't have been saved.
Append a JSON block to logs/session.jsonl immediately after the Step 4 log line:
{"ts":"<ISO>","level":"info","persona":"agent","category":"save_judge","event":"self-judge complete","scores":{"completeness":N,"dedup":N,"relevance":N},"avg":N.N,"notes":"<one-line if avg <4>"}If avg < 4: include a single-clause flag in the Step 6 chat reply, e.g. "💾 saved. 2 items across {categories}. {highlight}. (self-judge avg 3.3, may need re-pass)". Don't dwell. If avg >= 4: skip the score mention in chat, just log it.
Why self-judge instead of a separate Judge model: per the LLM-as-Judge literature, scoring requires a model call, but external print-mode invocations can have harness boundary issues. Until that's solved, the cheap reliable path is self-judgement inside the running skill. Imperfect but ships now.
Future v0.2 (when external model invocations work cleanly): replace the self-judge with a separate sub-agent dispatch that scores against the original transcript + the saved files. More objective, more expensive.
Future v0.3 (when a skill-eval cron ships): aggregate save_judge scores over time. Surface the trend (is /save quality drifting?). Flag systemic dedup failures.
Boundary: if the session was brief / temp-mode was on / the "nothing worth saving" path triggered → skip Step 5.5 entirely. The judge has nothing to score.
Step 6. ALWAYS send a chat confirmation (mandatory)
Regardless of how /save was invoked (the operator typed it, the stop-hook dispatched it, or it self-initiated), end with a chat reply using mcp__plugin_telegram_telegram__reply to the operator's chat_id. This is non-negotiable.
Why: when save is dispatched via tmux send-keys (the stop-hook path), the REPL's terminal output doesn't reach the chat channel. Without this step, the operator sees nothing. and if native auto-compact fires right after save (common, because save's tool-call burst pushes the jsonl size over the native threshold), the conversation goes silent from their perspective.
Heads-up requirement: if ACTIVE_BYTES_SINCE_COMPACT is >8MB at the start of Step 5 (check via source scripts/session/lib_active_session.sh && find_active_session), append a note to the chat reply: "⚠️ session thick ({X}MB since compact), native auto-compact may fire next turn. I'll ping when I'm back."
Template:
💾 saved. {N items across categories}. {1-sentence highlight}.
[optional: ⚠️ session {X}MB, compact incoming.]No reply_to needed unless responding to a specific message.
Category discipline (from the 4-type mental model)
When writing a new fact, ask what KIND of memory is it?
- Behavior rule (always active) →
Preferences.md(a change toCLAUDE.mditself is operator-gated constitution: SURFACE it, never auto-write, see Rules) - Writing style pattern →
Voice-Profile.md - Decision with context/reasoning →
Decisions.md(episodic, recall-fetched) - Insight/learning tagged by topic →
Learnings.md(episodic, recall-fetched) - Subject dossier (deal, company, person) →
memory/Context/<subject>.md - Infra state change →
memory/Infra/<component>.md - Persona-specific →
memory/personas/<slug>.json
Rules
- NEVER store message content verbatim, API keys, credentials, or sensitive personal data
- NEVER create empty files or placeholder entries. if nothing new to save in a category, skip it
- NEVER duplicate existing entries. check Preferences.md / Decisions.md / Learnings.md first
- Maximum 5 new files per save run to avoid bloat (update existing files freely)
- NEVER auto-write the constitution (immutable-base invariant). /save writes ONLY the mutable supplement:
Preferences.md,Decisions.md,Voice-Profile.md,Learnings.md,Context/,Infra/,personas/, and skill candidates. It NEVER writesSOUL.md,USER.mdorCLAUDE.md. Those are the immutable base (mandates, not observations), operator-gated, and /save can run autonomously from cron or a Stop hook where no CONFIRM gate fires. If a save-worthy item belongs in the constitution, surface it to the operator. The same rule binds every other auto-writer (dreaming, future memory refiners). Pattern credit: the immutable-base, mutable-supplement split in PrimeIntellect-ai/prime-agent. - Retracted claims. When a correction retracts a claim that already appeared in an outbound artifact (a CV, a pitch, a client doc, a post), append a row to
knowledge/retracted-claims.json(format:knowledge/retracted-claims.example.json).scripts/pipeline/external_slop_gate.pythen HARD-blocks every stale copy at ship time. A text lesson alone does not stop a copied draft. - If the session was brief / nothing substantive happened / temp mode was on: respond "nothing worth saving" and exit
- If the session was heavy (multiple decisions / substantive work): multiple categories will have entries, that's expected
Why this skill exists
/save was originally a documented convention in CLAUDE.md without a registered skill file. When the Stop-hook signal bridge (scripts/session/stop_hook_save.sh + scripts/session/save_handler.sh) started dispatching /save to the live REPL, the CLI returned "Unknown skill: save" because the convention wasn't wired as an actual skill. This file closes that gap. /save is now a real command the REPL can resolve.
Reference: docs/session-management.md for the full Stop-hook → handler → send-keys chain.
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.

