Tutorials 03–05 focused on direct reads and writes, with one preview of an action reminder. Memory that only answers when asked still depends on someone remembering to ask. This tutorial brings Loom's proactive behavior together: standing context that surfaces at the moment it can change what happens next.
Continue from Tutorial 05, with the palmerpenguins tutorial repository from Tutorial 03 checked out and [loom_demo] as the working store.
Before starting, ask the agent to verify all three deployment surfaces: [loom_demo] is present and writable; its live type catalog includes HookTrigger and a simulated pre-action advisory lookup succeeds; and the installed harness hook manifest includes the events used below (including PreCompact for §7). If any check fails, reinstall the current plugin/bundle or wait for the hosted store upgrade. Do not substitute mocked hook tests for this live gate.
loom_demo the session defaultloom_demo and make it the default for this session only. Confirm the effective session default, and do not edit ~/.loom/stores.toml.loom_demo store and changes only this session's default routing.loom_demo is now the default for this session. Persistent configuration was not changed.Loom pushes standing context on three distinct surfaces. Session-start priming: when a session opens, the goals, top directives, and open roadmap/handover items for the current scope are injected before the first exchange. Intent surfacing: when a request you type touches a subject that has standing context — a directive about pushing, a decision about a paid service — the relevant facts are injected alongside your prompt. Moment-of-action reminders: when the agent is about to run a command that matches a trigger you armed, the reminder appears as context on that very action.
All three arrive through the Loom plugin's trusted and enabled hooks from Tutorial 00; there is nothing else to wire. They are advisory: they inject context for the agent to judge, but never perform actions themselves.
Start a brand-new coding-harness session in the tutorial repository — a new Claude Code or Codex conversation, not a continuation of the current one.
Priming is ranked by importance and recency and capped to a top handful, so it stays an orientation, not a dump. The rules you saved in earlier tutorials are now simply present in every new session that opens in this scope.
Save a new project rule the normal way — with the author and scope edges from Tutorial 03.
[loom_demo], remember a Directive for this project: count penguins by writing and running a Python function. Never ask the LLM to count rows in the raw CSV.Directive("count penguins with a Python function, not by LLM inspection of raw CSV rows") with the GitUser derived from the repository's current git email and ['InScope()', 'Project("palmerpenguins")'].[loom_demo], not a note in this conversation.Now — later in the session, or in a different session entirely — mention the subject without mentioning the rule:
The injected block the agent sees is shaped like this — a small, ranked list, explicitly marked as context to judge rather than an instruction to obey blindly:
Similarity-matched standing context (verify relevance before relying on it):
• Directive: count penguins with a Python function, not by LLM inspection of raw CSV rowsYou never asked what the rules were. The request touched a known subject, and the rule showed up on its own.
HookTrigger)Intent surfacing keys off what you say. Sometimes the right moment is what the agent is about to do. For that, attach a HookTrigger to a fact — a value node naming the hook event and a needle to match against the upcoming action.
[loom_demo], remember this and make it appear whenever you're about to run the tests here: this package's tests depend on the bundled CSVs, so run pytest from the repository root or the data paths won't resolve.Repo("palmerpenguins") node still points through the complete scope chain. Then it performs two saves in order—first HookTrigger("PreToolUse", "pytest|python -m pytest"), then Recipe("run pytest from the repository root") with the path explanation, that trigger, ['InScope()', 'Repo("palmerpenguins")'], and the current git user's Author() edge.[loom_demo] reuses the verified Repo("palmerpenguins") node from Tutorial 03; the Recipe is scoped to it and authored by the current git user. The reminder will surface for pytest and python -m pytest commands in this repository.The needle is a case-insensitive literal substring match against the upcoming action's text (tool name plus command or arguments), with |-separated alternatives. Pick 2–4 discriminative literals that will actually appear—pytest|python -m pytest covers the realistic Python test forms here. Too broad (git) fires on almost everything; too narrow (one exact full command) misses variants.
Two honest caveats. On the advisory hook paths, trigger presence is cached per store (roughly a 2-minute TTL), so a freshly armed trigger can take up to about two minutes to start firing. And scope is enforced at fire time: a trigger fact scoped to this repository fires only in this repository — it cannot leak into a sibling repo sharing the same store.
You can check the arming without running anything, the same way Tutorial 05 §1 checked the push trigger:
pytest right now. Do not run it.pytest from the repository root so the bundled CSV paths resolve. No command was run.Wait a couple of minutes after arming (the cache TTL above), then ask for the matching action.
pytest. Before the command executes, the pre-action hook matches the pytest needle and injects the armed Recipe as context on that tool call. The agent reads it and runs from the repository root.pytest from the repository root so the bundled CSV paths resolve. I ran it from the root; the suite passes.The reminder is attached to the action, not to this conversation. Next month, in a different session, any agent about to run pytest in this repository gets the same context at the same moment.
Proactive memory also covers the seam between sessions. When you stop with work in flight, wrap up with the exit skill.
HandoffTask scoped to Repo("palmerpenguins"), with its own conversation id and a concrete next step written for a reader with zero memory of this session.HandoffTask("finish the species-count write-up") with my agent id and the next step: draft the counts section using the Python-verified totals from today (Adelie 152, Chinstrap 68, Gentoo 124). It will resurface automatically at the next session start for this repository.Start a fresh coding-harness session in the same repository:
HandoffTask for this repo: finish the species-count write-up, with the concrete next step and the previous session's agent id. Picking it up now — and once it's addressed, I'll supersede it so it stops resurfacing.The handover is a pull-free loop: exit saves it, priming resurfaces it, and superseding retires it.
Long sessions eventually compact: the harness replaces the conversation so far with a summary to reclaim context space. That summary is where unsaved knowledge dies — a decision you talked through but never saved exists only in the conversation, and after compaction it may not even be there. Constructing long-term useful memory therefore has one critical deadline: the moment right before compaction. Loom's hook treats it exactly that way.
The behavior is yours to control, with one line in ~/.loom/hooks.toml:
[capture]
precompact = "confirm" # "off" (default) | "confirm" | "auto"PreCompact capture defaults to off so Loom never interrupts the normal compaction flow unless you opt in. Once the rest of this tutorial feels familiar, you are encouraged to turn it on and experiment: start with confirm to inspect and approve each proposed save, then try auto if you want the sweep to run without a confirmation stop.
With confirm explicitly enabled as above, whenever compaction runs — automatically at the context limit, or manually via /compact — Loom preserves the full pre-compaction conversation for one last durable-memory sweep. The exact bridge is harness-specific: Claude adds the sweep to the compaction summarizer; Codex snapshots the transcript before history is replaced and injects the sweep as the first post-compaction action. In both cases, the saves happen immediately after compaction as the agent's first order of business. In confirm mode nothing is saved until you say so:
[loom_demo], none saved yet: 1. Decision: keep the species write-up in docs/analysis.md, not the README 2. Finding: the Python counting function returned Adelie 152, Chinstrap 68, and Gentoo 124 3. HandoffTask: the write-up's discussion section is still unfinished Confirm all three, or edit?Author() and usual scope edges after querying for equivalent current facts. It explains that a Directive about method and a Finding about measured counts have different sortals and claims.auto runs the same sweep but saves silently, without the confirmation stop; off disables the capture entirely. If you want to tune what the sweep looks for in a particular store, the mechanism is the same one as §4: a fact carrying HookTrigger("PreCompact", "auto|manual") replaces the built-in sweep instruction with your own wording — the confirm/auto behavior still applies on top.
HandoffTask carries unfinished work and a concrete next step into the next session.off; enable confirm or auto when you are ready to experiment with a final durable-memory sweep.Directive,” in Tutorial 05 for a dry-run of action-time surfacing, then see the benchmarks page for its measured effect on agent performance.