Install any skill in seconds. Free to start, no credit card required.
Get Started Free →End-of-session ritual. Captures decisions, lessons, gotchas, and open threads. Writes a narrative session log to ~/.origin/sessions/ and stores granular memories via Origin MCP. Previews any unconfirmed captures from the current session before closing. Invoked as `/handoff`.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 86% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 160% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 85% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 103% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 108% | 0% |
End-of-session debrief. Three artifacts each pass:
~/.origin/sessions/<YYYY-MM-DD-HHmm>-<slug>.md.~/.origin/sessions/_status/.These are orthogonal: captures are queryable atoms, session log is the narrative thread, status file lets the next session see where we left off.
Bash: cd_repo=$(git -C "$PWD" rev-parse --show-toplevel 2>/dev/null); echo "${cd_repo:-no-git}"<project> (e.g. origin).no-git → use the cwd basename. Skip git steps below; rely entirelyon conversation context.
Read ~/.origin/sessions/_status/handoff-<project>.json for lastHandoff timestamp (ISO-8601). If file missing, default to "12 hours ago".
After establishing <lastHandoff>, call:
list_pending(limit=50)The MCP returns memory rows with source_id, content, created_at, and other metadata. Convert lastHandoff (ISO-8601 string, e.g. 2026-05-13T22:50:00Z) to a Unix epoch seconds integer before filtering:
Bash: date -j -f %Y-%m-%dT%H:%M:%SZ "$lastHandoff" +%sOr in your scripting language of choice (Python's datetime.fromisoformat, JavaScript's Date.parse, etc.). Save the result as lastHandoffEpoch.
Then filter the response rows: keep where row.created_at >= lastHandoffEpoch. These are captures this session produced that the quality gate left unconfirmed (untrusted-source captures).
If the filtered list is empty, say nothing. Proceed to Step 2.
If non-empty, render a preview block once, before the existing capture flow:
Pending captures this session (<N> total, top 3 shown):
1. mem_xyz789 "..." (untrusted source: <agent>)
2. ...
Default: proceed (captures stay pending). Opt in by running
`/review captures` before re-invoking /handoff if you want to walk them.Do NOT prompt for per-item action inline. The user proceeds with /handoff regardless; the preview is informational only.
Bash: git -C <repo> log --oneline --since=<lastHandoff>
Bash: git -C <repo> status --short
Bash: git -C <repo> diff --stat HEAD~5..HEAD 2>/dev/null
Bash: git -C <repo> worktree listCapture output. Use it alongside conversation history to infer what happened. If not a git repo, skip — conversation context is the source.
Synthesize silently from git output + conversation. Categorize each item into user-facing groups. Each maps to a daemon memory_type for the capture call:
| Display label | daemon memory_type | What belongs here | |---|---|---| | Decisions | decision | architectural choice, tool/pattern selection (with WHY) | | Lessons | lesson | root cause discovered, workaround found, technical insight | | Insights | gotcha | unexpected behavior, debugging discovery, sharp edge | | Corrections | preference | user pushed back, corrected approach or assumption | | Facts | fact | durable project/people/tool fact worth persisting |
Non-memory items (not stored, session-log only):
Skip purely mechanical facts already in git (file paths, function names, config values). The commit log preserves those.
For each non-trivial item, call with the mapped memory_type:
capture(content="<one self-contained sentence with WHY>", memory_type="<decision|lesson|gotcha|preference|fact>")Atomic: one decision per call. Don't merge multiple items into one memory. The daemon dedups against existing knowledge, so re-storing known facts is a no-op.
Only surface items to the user BEFORE storing if they meet one of these bars:
Otherwise just store and report counts at the end.
Bash heredoc to ~/.origin/sessions/<YYYY-MM-DD-HHmm>-<slug>.md:
markdown# Session <YYYY-MM-DD HH:MM> — <slug> **Project:** <project> **Range:** <lastHandoff> → <now> ## Accomplished - <item> ## Decisions - <decision and rationale> ## Lessons & Gotchas - <root cause / workaround> ## Open Threads - <what's unfinished> ## Captures stored - <source_id_or_brief_summary> ## Git summary <git log --oneline output>
<slug> = kebab-case 2-4 word summary (session-handoff-md-writer).
Overwrite ~/.origin/sessions/_status/<project>.md:
markdown# <Project> — Current Status ## Last session (<date>) - <accomplished bullet> ## Active <!-- Items touched/spawned in the last 1-2 sessions. Real next-move candidates. --> - <item> (added <YYYY-MM-DD>) - <blocked item> (added <YYYY-MM-DD>) (gated: <trigger>) ## Backlog <!-- Older accretion. Not gated, not picked. Promote back to Active when re-engaged. --> - <item> (added <YYYY-MM-DD>)
Single file per project. New session overwrites — this is the current state, not a log.
Two sections, not one flat list: ## Active and ## Backlog separate the two types of tasks that get mixed otherwise. Active = fresh signal worth picking next. Backlog = older parked items, kept for reference but not in the "what next?" frame.
Date stamp every bullet with (added <YYYY-MM-DD>). Use today's date when adding a new item; preserve the original date when carrying an item forward. Dates make age visible at a glance and avoid relative-time drift.
Gated items stay inline-tagged with (gated: <trigger>) — no separate section. The tag tells the reader why it can't move yet; the bullet stays in whichever section reflects its recency.
Promotion / demotion rules:
## Active with today's date## Active that wasn't touched this session AND wasn't touchedthe prior session → demote to ## Backlog (keep original date)
## Backlog that work resumed on → promote back to ## Active(keep original date — staleness is a property of the work, not the bullet text)
Overwrite ~/.origin/sessions/_status/handoff-<project>.json:
json{ "lastHandoff": "<ISO-8601 now>", "project": "<project>", "summary": "<one-line>" }
Per-project file prevents parallel sessions from clobbering each other.
After writing the files above, snapshot the change so the user can git log their memory's life timeline. Defensive — silent skip if git is missing or ~/.origin/ is not a repo yet.
Bash: git -C ~/.origin add -A && \
git -C ~/.origin -c user.name=Origin -c user.email=daemon@origin.local \
commit --quiet -m "session: <slug>" 2>/dev/null || \
(sleep 1 && git -C ~/.origin add -A && \
git -C ~/.origin -c user.name=Origin -c user.email=daemon@origin.local \
commit --quiet -m "session: <slug>" 2>/dev/null) || trueThe retry handles index.lock races — the daemon may be writing to ~/.origin/ at the same moment (auto-commit from captures). One-second wait is enough for the daemon to release the lock.
Print one summary block with captures grouped by display label:
Handoff stored.
Decisions: <N> (brief list)
Lessons: <N> (brief list)
Insights: <N> (brief list)
Corrections: <N> (brief list)
Facts: <N> (brief list)
Session: ~/.origin/sessions/<filename>
Status: ~/.origin/sessions/_status/<project>.md
Git: <commit hash> session: <slug>Show each label only if non-empty. List items as short phrases, not full sentences — the session log has the details.
/capture (single memory)./recall.a stability flag — they never get exported to md.
~/.origin/pages/ by thedaemon when /distill runs. Citations link back to source memory ids.
~/.origin/sessions/. They arethe narrative axis: chronological, not topical. Browse them as a changelog of your work.
Other measured skills in the registry, with their headline benchmark lift.