agentleFS
jayantakjayantak/vaultmem/skills/session/SKILL.md

session

Skill3 starsChanged 4 months agoMITView on GitHub

Always-active cross-session working memory. Auto-activates every conversation to offer resuming or starting a session. Also triggers on "start a session", "resume", "park this", "save this", "wrapping up", or multi-session/multi-repo work. Routes work to the correct Obsidian vault, groups sessions under a parent Project (epic), and distills durable insights up into the Project note and MOCs at stopping points.

17 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use debug, release and 1 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.
  • AnthropicSkill

    debug

    Structured debugging session — reproduce, isolate, diagnose, and fix. Trigger with an error message or stack trace, "this works in staging but not prod", "something broke after the deploy", or when behavior diverges from expected and the cause isn't obvious.

    Also in 3 projects that use this

  • MicrosoftSkill

    release

    Use ONLY when the user explicitly asks to cut/publish a Huabu desktop release or tag a version. Performs an outward action — bumps the version in apps/desktop/package.json, commits + annotated-tags vX.Y.Z, and pushes the branch + tag. That tag push auto-builds the macOS/Windows installers and publishes a GitHub Release. Provides `status`, `bump`, `tag-push`, and a one-command `run` (bump → tag-push).

    Also in 4 projects that use this

  • GoogleSkill

    tdd

    Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.

    Also in 3 projects that use this

The file

Show its rules and text

We split this skill into the rules it gives an agent

21 rules. 0 are common, 8 are distinctive, and 13 are very specific to this project.

  • 0

    Common

    Most of the 14 edited versions we read keep these.

  • 8

    Distinctive

    This author's own choices. Worth a look.

  • 13

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Trivial one-shot exception: if the first user message is a quick question or a single read-only lookup answerable in one reply, skip this …

    line 35
  2. Distinctive:

    Always resolve the vault through the router:

    line 42
  3. Very specific:

    Create <vault_path>/Tasks/<slug>.md (flat folder, no per-task directory):

    line 91
  4. Distinctive:

    Use a task for work you don't want in the tracker, or to hold the agent-ready brief for a ticket that is already there.

    line 113
  5. Very specific:

    Run vaultmem which for the vault, then vaultmem projects to see candidates.

    line 146
  6. Very specific:

    If exactly one fits, use it.

    line 149
  7. Very specific:

    If a new Project is needed, create Projects/🟢 <name>.md from the Project shape (below) with type: project, status: active, repos:, and …

    line 151
  8. Very specific:

    Write <vault_path>/Sessions/<thread>/_index.md from the template, stamping project:, aliases: [<thread>] (so the Project's back-link …

    line 155
  9. Very specific:

    Every Project and Session carries a status glyph so the Obsidian file-tree sidebar shows state at a glance.

    line 243
  10. Very specific:

    NEVER glyph the session *folder* name — vaultmem keys sessions by folder basename == the thread: field, so a glyphed folder desyncs them …

    line 253
  11. Very specific:

    Keep it in sync on every transition: When a status flips (active→parked at park, →done at retire), update the glyph in the same write: the …

    line 264
  12. Distinctive:

    Read tool. Use them for cheap inspection (resume, re-anchoring, checking a section before deciding), and Read the file itself before the …

    line 282
  13. Very specific:

    If git state moved (branch, PR, worktree, merge/push), refresh ## Git state

    line 288
  14. Very specific:

    Add or correct a ## Pinned constant if this turn surfaced one (a gotcha, a binding decision, the canonical command/path).

    line 294
  15. Very specific:

    Keep header wikilinks current ([[MOC]], [[repo]], [[person]], [[prior-session]]).

    line 296
  16. Distinctive:

    Never keep durable results only in conversation memory.

    line 299
  17. Very specific:

    Run vaultmem bookmark <thread> — it prints exactly the ## Bookmark + ## Pinned blocks, not the whole file.

    line 310
  18. Distinctive:

    Resume-time verification fans out; it never runs inline: When the next step requires re-establishing facts against a repo — verifying a …

    line 321
  19. Distinctive:

    When the user says "park", "wrapping up", "let's clear", OR you detect a natural stopping point (task list drained AND a coherent unit …

    line 353
  20. Distinctive:

    ONLY for work that will genuinely resume — a real next action you expect to pick up.

    line 363
  21. Very specific:

    Never read a full file when a section will do — vaultmem cat <note> --section '## <Heading>' extracts one heading block without guessing …

    line 438

“Common” is measured: kept by at least 6 in 10 of the 14 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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md
<!-- CANONICAL SOURCE: this repo (jayantak/vaultmem). The dotfiles copy under agents-source/skills/ is synced FROM here — edit this file, not that one. -->

session — cross-session working memory

The hot layer above the durable Obsidian vaults. Sessions are per-thread worklogs that survive /clear. The conversation is disposable; the session file is the state. Pairs with vaultmem (search/registry/router), vault-recall (finding what's already written), and vault-capture (durable capture).

The vault layout, frontmatter fields, status vocabulary, and glyph convention this skill writes are the normative contract in SCHEMA.md (run vaultmem vaults for the live registry). The templates below are the operational shapes; SCHEMA.md is the reference when they disagree.

Always-on activation

The SessionStart hook prints a picker line (vaultmem sessions) ending in an AGENT DIRECTIVE — the trailing prompt that tells the agent what to do with the picker. Its wording is configurable (the registry's directive_file); the default asks the agent to route session handling through this skill. That directive is binding: invoke this skill FIRST, every conversation, before any other skill, tool call, or reply. Memory lookups (vault-recall, vaultmem) do NOT substitute — even when they read the same session file, route through this skill first, then continue. Be concise; never block the user's actual task. If the user skips, do NOT re-ask this conversation.

Trivial one-shot exception: if the first user message is a quick question or a single read-only lookup answerable in one reply, skip this skill silently and just answer. The moment the thread turns into real work (edits, a task, a second substantive turn), invoke the skill then. Never announce the skip.

Vault routing (never hardcode a vault)

Always resolve the vault through the router:

  • Guess: vaultmem which (prints the routed vault id).
  • Confirm with one line: "New session in the <vault> vault — ok? (or say the other)".
  • Registry facts (paths, sessions root, default MOC): vaultmem vaults.

Resolve <vault_path> with vaultmem path <vault> (bare path on stdout — use it directly in scripts as V="$(vaultmem path <vault>)"; vaultmem vaults still prints the full registry).

A session is one task, not one project

A session = one focused unit of work (a feature, a bug, an investigation). The tier above a session is a Project (Projects/<name>.md) — that is where cross-session state accumulates. When the unit of work closes, park the session and open a fresh one under the same Project; do not keep one session open as a stand-in for the whole project (that is what makes _index.md balloon). Tiers: MOC (domain map) → Project (epic, owns repos + cross-session state) → Session (one thread).

A Task (Tasks/<slug>.md) is the state before a session: work that is planned but not started. A session is created when work starts, so intent that predates it has nowhere to live — that is what a task is for. See § The backlog below.

List projects with vaultmem projects; see one with vaultmem project <name> (its repos, linear pointer, MOC, and sessions by status).

The backlog (Tasks/)

A Task is a spec, not a worklog: enough context that an agent (or you, in three weeks) can start cold without asking a follow-up question. It is the answer to "I want to plan this now and have something pick it up later."

  • vaultmem next — the ready queue, most-ready first. This is the "what should I pick up" surface. Blocked tasks are listed separately, never mixed into the ready set.
  • vaultmem task <slug> — one task in full: its facts plus the brief.
  • vaultmem task <slug> --promote — prints the exact edits that convert the task into an active session. Read-only; you apply them.

Task status is its own vocabulary — backlog | next | active | done. There is no parked: an unstarted thing pausing is just backlog. next means explicitly queued; active means it was promoted and its session now owns the state.

Write a task

Create <vault_path>/Tasks/<slug>.md (flat folder, no per-task directory):

---
type: task
status: backlog       # backlog | next | active | done
project: <plain project name>
repos: [<repo>]       # so an agent knows where to work
linear:               # OUTBOUND pointer only — never synced back
blocked_by:           # slug of a task that must land first (omit when unblocked)
updated: <YYYY-MM-DD HH:MM>
---
# <task title>

<Why this needs doing, and the context needed to start cold.>

## Acceptance criteria
- [ ] <verifiable outcome, not an activity>

linear: is a one-way pointer. Linear/Jira stays the canonical team surface; the vault never syncs status back, so the two can't fight over truth. Use a task for work you don't want in the tracker, or to hold the agent-ready brief for a ticket that is already there.

Promote a task into a session

Task → session is a conversion, not a copy: one unit of work keeps one identity from planned → active → done. Run vaultmem task <slug> --promote and apply what it prints — it creates Sessions/<slug>/ with a task: <slug> backlink, flips the task to status: active with a session: <slug> pointer, and registers the session on the Project.

Do not restate the brief in the session. The task note remains the spec; link it ([[<slug>]]) and let ## Bookmark carry live state. Duplicating it is how the two drift.

vaultmem task <slug> --promote --apply performs the same recipe itself (session note, then Project index, then the task's own fields — in that order, so a mid-failure never leaves a task pointing at a session that doesn't exist) for a caller that needs it done non-interactively rather than applied by hand.

Keep the backlog honest

An unstarted task has no forcing function — nothing fails when it rots — and a stale backlog makes next untrustworthy, which defeats the point. groom and the SessionStart nudge flag tasks untouched past VAULTMEM_TASK_STALE_DAYS (default 14). When one surfaces: promote it, re-scope it, or delete it. Leaving it is the one option that costs you the tool.

Create a session

  1. Route + confirm vault (above).
  2. Attach to a Project. Resolve the parent epic:
    • Run vaultmem which for the vault, then vaultmem projects to see candidates. If the cwd is a repo, prefer the Project whose repos: lists it.
    • If exactly one fits, use it. If ambiguous or none, ask one line: "Which project does this belong to — <a> / <b> / new / none?".
    • If a new Project is needed, create Projects/🟢 <name>.md from the Project shape (below) with type: project, status: active, repos:, and aliases: ["<name>"] (glyph on filename + H1; see Status glyphs below).
  3. Pick a short kebab <thread> from the task.
  4. Write <vault_path>/Sessions/<thread>/_index.md from the template, stamping project:, aliases: [<thread>] (so the Project's back-link resolves), + inheriting repos: from the Project, and auto-linking MOCs/repos/people inferred from the opening context.
  5. Register the session on the Project. Append a line to the Project note's ## Sessions index: - [[<thread>]] — <one-line> (status: active) (+ the tracker issue id if the project has one, e.g. (PROJ-1234, active)). This [[<thread>]] only resolves because step 4 gave the session an aliases: [<thread>] entry.

_index.md template

---
thread: <thread>
project: <project-or-blank>
vault: <vault-id>
status: active
aliases: [<thread>]   # REQUIRED — so [[<thread>]] back-links resolve (the file is _index.md, basename ≠ thread)
updated: <YYYY-MM-DD HH:MM>
---
# 🟢 <thread>
**Goal:** <one line>   **Project:** [[<project>]]   **MOCs:** [[<moc>]]   **People:** [[<person>]]
**Repos:** [[<repo>]] (branch <branch>)   **Related:** [[<prior-session>]]

## Bookmark
Last: <what just happened> · Next: <next action> · Open: <unresolved>

## Pinned

## Work log

## Decisions

## Git state
| Repo | Branch / worktree | PR | State |
|---|---|---|---|

Parent Project. project: is the session's parent epic — a Projects/<name>.md note. The picker groups sessions by it, and distill promotes durable bits up to it. Leave it blank only for genuinely one-off work with no home. repos: default- inherit from the Project note; restate them in the header (override only if this session touches a different repo).

The spine is fixed; topical sections are free-form. Bookmark, Pinned, Work log, Decisions, Git state are the required skeleton. Add your own ## <topic> working sections as the task needs them (an analysis in progress, a decomposed plan, a verdict) — real sessions grow these, and distill collapses them. Don't force everything into the work log.

## Pinned = load-bearing constants that must survive distill. The handful of facts you'd be annoyed to re-derive: the stage/env gotcha, the one binding constraint, the non-obvious command, the canonical file to edit, the worktree layout. Keep it short (≤6 lines); it is re-read first on resume. Distill never strips it — correct it in place when a constant changes. (Leave the heading empty until you have a constant worth pinning.)

Link targets must resolve. The [[<moc>]] / [[<repo>]] / [[<person>]] placeholders are not free text — a wikilink works only if a note's exact basename or alias matches. Link MOCs by filename [[MOC - <Topic>]] (or a declared alias like [[Payments]]); for a repo/person, link only if a real note exists (vaultmem mocs / index to check), else use plain text. Never wikilink repo artifacts (ADR IDs, file paths, PR numbers). Full rules: vault-capture § Linking Rules.

The Project note (Projects/<name>.md)

The long-lived epic. Frontmatter:

---
type: project
status: active            # active | parked | done
vault: <vault-id>
repos: [<repo>]           # sessions inherit this
linear: <url>             # optional, if the project tracks tickets (read for context; never a worklog)
moc: "[[MOC - <Topic>]]"  # optional — the domain map above this project
updated: <YYYY-MM-DD>
---

Body spine: ## Sessions (the index, grouped by status) · ## Pinned (cross-session load-bearing constants) · ## Decisions (durable cross-session decisions) · free-form topical sections. Keep it lean the same way _index.md is — distill (below) is what keeps it that way.

Status glyphs (sidebar self-sorts by state)

Every Project and Session carries a status glyph so the Obsidian file-tree sidebar shows state at a glance. The glyph maps 1:1 to the status: field:

statusglyph
active🟢
parked💤
done / shipped✅
  • Session (_index.md): glyph goes on the H1 only (# 🟢 <thread>). NEVER glyph the session folder name — vaultmem keys sessions by folder basename == the thread: field, so a glyphed folder desyncs them and breaks the picker/groom. Sessions churn fast and their status shows in the picker anyway, so the H1 glyph is enough.
  • Project (Projects/<name>.md): glyph goes on both the filename and the H1 (🟢 <name>.md / # 🟢 <name>) — the filename is what the sidebar sorts. Renaming a flat project file is safe as long as you first add the plain name as a frontmatter aliases: entry (aliases: ["<name>"]) so every existing [[<name>]] link keeps resolving. vaultmem strips the leading glyph when matching a project to its sessions, so sessions keep the plain project: name — never write the glyph into a session's project:.
  • Keep it in sync on every transition. When a status flips (active→parked at park, →done at retire), update the glyph in the same write: the H1 for a session; the H1 and the filename for a project (re-mv + keep the alias). A stale glyph is a lie the sidebar tells — treat it like a stale ## Bookmark.
  • Non-status notes (references, reviews, 2026 Review) take no status glyph.

Indexed mode (auto-persist, no prompts)

Once a session is active, after every few tool calls (or whenever you produce durable content — decisions, findings, plans):

First edit of the conversation: Read _index.md before editing it (a section read via offset/limit satisfies this). The Edit tool rejects writes to never-read files — this is the top recorded tool error in past sessions. The same applies to the Project note and MEMORY.md.

vaultmem cat/bookmark do NOT satisfy that precondition. They are separate processes; the Edit tool only counts a file as read when you read it with the Read tool. Use them for cheap inspection (resume, re-anchoring, checking a section before deciding), and Read the file itself before the first edit.

  1. Append a timestamped bullet to ## Work log. Lead it with a status marker when it helps scanning — DONE / BLOCKED / DECISION / NEXT.
  2. Rewrite ## Bookmark (Last / Next / Open) — always current, never stale.
  3. If git state moved (branch, PR, worktree, merge/push), refresh ## Git state in the same write. The work log is the source of truth for what happened; the table is just the at-a-glance index — never let it contradict the log. vaultmem worktrees [thread] [--format json] reads this table back out (one thread, or every active session) for a consumer that needs "which worktree is thread X on" without parsing markdown itself.
  4. Add or correct a ## Pinned constant if this turn surfaced one (a gotcha, a binding decision, the canonical command/path).
  5. Keep header wikilinks current ([[MOC]], [[repo]], [[person]], [[prior-session]]); bump updated:.

Never keep durable results only in conversation memory. The write is atomic: content + Bookmark (+ Git state if it moved), same turn. Corrections edit the existing section in place rather than appending.

Re-anchor periodically. On a long thread, every ~5–6 substantive turns re-read your own ## Bookmark + ## Pinned (vaultmem bookmark <thread>) before deciding the next move — it keeps you on the task instead of drifting with the conversation, and it surfaces when the file has bloated enough to checkpoint (below).

Resume

Run vaultmem bookmark <thread> — it prints exactly the ## Bookmark + ## Pinned blocks, not the whole file. Those two are the resumable state (what just happened / what's next / the load-bearing constants). Read further sections only if the next action needs them, with vaultmem cat <note> --section '## <Heading>'. The picker's number/name selects the thread; resolve its _index.md path.

If the bookmark already declares completion (Next: none / done / shipped, or the only Open item is a tracker link), don't resume it as if there's work left — flip status: done + ✅ right then and tell the user, rather than reopening a finished unit.

Resume-time verification fans out; it never runs inline. When the next step requires re-establishing facts against a repo — verifying a ticket's claims, grep sweeps, multi-file reads, git show archaeology — delegate the whole read phase to one read-only subagent (Explore / general-purpose) carrying the claim list and repo paths; only verdicts with file:line evidence return. The main context keeps the judgment work (rulings, ticket patches, logging). Inline verification is the top context burner on resume (measured: 125k of a 200k window on a single step). Same rule mid-session for any bulk read phase.

Checkpoint (distill in place, keep going)

Checkpoint is the pressure-release valve that keeps _index.md lean without needing a stopping point. Trigger it on the FIRST of these — don't wait for the user to ask:

  • the user says "checkpoint" / "distill but keep going"; OR
  • _index.md drifts past ~150 lines (the work log is dense — it bloats fast); OR
  • the conversation has run long / context is filling AND you've produced durable content (a decision, a finished analysis, a shipped change) since the last distill — checkpoint at the next turn boundary rather than riding context to the edge. Catching it early beats an emergency compaction that loses the trail.

Then load references/distill.md and run the checkpoint flow: promote durable bits to the vault, collapse the promoted work-log entries to → promoted to [[note]] pointers, leave ## Pinned intact, and keep status: active. No _meta.md event, no clear — the conversation continues. It is the lighter alternative to park when there's no stopping point yet. A one-line confirm is enough; don't interrupt the user's flow to ask permission for an in-place checkpoint.

Park / end + distill

When the user says "park", "wrapping up", "let's clear", OR you detect a natural stopping point (task list drained AND a coherent unit closed AND context growing), load references/distill.md and run the park flow (checkpoint + _meta.md event + clear-safe). Offer: "Natural stopping point — distill durable bits into the vault and clear?"

At park time, decide done vs parked — don't default to parked. If the unit of work is complete (the bookmark says shipped/done/nothing next, or the only remainder is tracked on GitHub/Linear), set status: done + ✅ immediately in the same write, not "parked" as a placeholder for later cleanup. parked/💤 is ONLY for work that will genuinely resume — a real next action you expect to pick up. Sessions are not ticket trackers: an open PR review, a follow-up issue, or a "waiting on review" state tracked on GitHub/Linear does not keep a session alive on its own — leave a pointer to the tracker item and retire the session as done.

Lifecycle & grooming

A session moves active → parked → done, then is archived — archived is a location, not a status: archived sessions live under Sessions/_archive/<thread>/ and drop out of every listing surface (picker, projects, project). Wikilinks resolve by basename, so [[<thread>]] keeps working after the move. The picker shows active + parked only (resumable work); done is hidden, awaiting groom. On each transition, update the session H1 glyph (🟢→💤→✅) in the same write — and when a Project's own status changes, re-mv its file to the new glyph (💤 when parked, ✅ when shipped) and fix its H1, keeping the plain-name alias.

The SessionStart picker appends a ⚠ … run vaultmem groom nudge when a vault has done sessions (ready to archive), parked sessions untouched past OBSIDIAN_SESSION_COLD_DAYS (default 21), active sessions untouched past VAULTMEM_STALE_ACTIVE_DAYS (default 7), or backlog/next tasks untouched past VAULTMEM_TASK_STALE_DAYS (default 14). vaultmem status surfaces the same nudge in short form. When you see it:

  • vaultmem groom mechanically moves every done session into _archive/ and flips its parent Project's ## Sessions line to archived. Safe to run anytime (done was already distilled at park). Scope with -v <vault>. It also archives every done Project into Projects/_archive/ — unless a session outside _archive/ still points at it, in which case groom prints a warning naming the blocking session(s) instead of moving it. Clear those first (archive or reassign the session) and re-run groom.
  • It also lists cold-parked sessions for triage — it never auto-retires them. For each, drive the decision with the user: resume (open it, status back to active), or retire. To retire: confirm it was distilled at its last park (it has a _meta park event / → promoted pointers — cold means untouched since park, so normally yes); if not, run the distill loop (references/distill.md) first; then set status: done so the next groom archives it.
  • It also lists stale-active sessions for triage — an active session that has gone untouched this long likely stalled. Triage it the same way as cold-parked, just from the other side of the fence: either the work actually finished (a bookmark that was never flipped — set status: done per the park-time rule above, so the next groom archives it), or it is genuinely still live (park it if paused but not abandoned, or touch updated: and keep it active). A stale-active entry is usually the symptom this whole rule set exists to catch — the park-time done/parked decision above is what prevents it from recurring.
  • It also archives done tasks into Tasks/_archive/ (a done task has no dependents to strand, so nothing blocks the move) and lists stale backlog for triage. Drive that decision too: promote, re-scope, or delete. Do not leave it — see § Keep the backlog honest.

Project retirement

Projects get the same active → done → archived lifecycle as sessions, with one added precondition: a Project can only retire once its goal is met and every session under it is done or already archived — a Project with a live session is not done, no matter how old it looks (groom enforces this too: it refuses to archive a done Project a live session still points at, and names the blockers). When that holds:

  1. Distill any remaining durable content (open ## Pinned constants, unresolved ## Decisions) up to the vault's MOC tree, same as a session distill — the Project note disappears from active listings after this, so nothing should be left only there.
  2. Set status: done in frontmatter.
  3. Glyph both the filename and the H1 (✅), keeping the plain-name aliases: entry so existing [[<name>]] links keep resolving — same rule as any other Project status transition (see Status glyphs above).
  4. vaultmem groom moves it into Projects/_archive/ on its next run. Archived is a location, not a status, exactly like sessions — wikilinks keep resolving via basename/alias after the move.

Frugality rule

Never read a full file when a section will do — vaultmem cat <note> --section '## <Heading>' extracts one heading block without guessing offsets, and vaultmem bookmark <thread> is the pre-cut Bookmark+Pinned pair (measured on a real vault: 2568 bytes vs 11950 for the whole _index.md, 4.7x cheaper). Both are read-only inspection — they do not satisfy the Edit tool's read-before-write precondition (see Indexed mode). The _index.md IS the state; keep it ~100–150 lines — when it grows past that, checkpoint (see above) to promote and collapse rather than letting it bloat. Search across everything with vaultmem <query> — run 2–3 pattern variants (exact term, synonym, adjacent concept), and treat match lines as leads: read the note (or its section) before answering, never answer from search output alone. Follow [[links]] between notes with vaultmem links / backlinks (see vault-recall § Researching by following wikilinks) instead of reading whole folders.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.