<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Troy Molander]]></title><description><![CDATA[I build AI-enabled software, cloud infrastructure, and automation systems. My work spans agentic AI, AWS architecture, and developer tooling. Off the laptop, I’m mountain biking and enjoying San Diego’s outdoors.]]></description><link>https://articles.agentience.ai</link><image><url>https://substackcdn.com/image/fetch/$s_!BF4t!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb262f8c2-7b35-4e5e-ac5a-279be314a3bc_1082x1082.png</url><title>Troy Molander</title><link>https://articles.agentience.ai</link></image><generator>Substack</generator><lastBuildDate>Fri, 09 Oct 2026 20:22:21 GMT</lastBuildDate><atom:link href="https://articles.agentience.ai/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Troy Molander]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[troymolander@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[troymolander@substack.com]]></itunes:email><itunes:name><![CDATA[Troy Molander]]></itunes:name></itunes:owner><itunes:author><![CDATA[Troy Molander]]></itunes:author><googleplay:owner><![CDATA[troymolander@substack.com]]></googleplay:owner><googleplay:email><![CDATA[troymolander@substack.com]]></googleplay:email><googleplay:author><![CDATA[Troy Molander]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[A librarian for your docs directory]]></title><description><![CDATA[Applying library science to a 136-document `docs/` tree &#8212; triage that measures instead of guessing, and a governance kit that keeps it clean afterwards]]></description><link>https://articles.agentience.ai/p/a-librarian-for-your-docs-directory</link><guid isPermaLink="false">https://articles.agentience.ai/p/a-librarian-for-your-docs-directory</guid><dc:creator><![CDATA[Troy Molander]]></dc:creator><pubDate>Tue, 01 Sep 2026 15:44:10 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!HDBZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2f3377e-bc2c-4985-9f5d-98bd698d0969_1640x1560.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A stale document costs me twice with an agent, once in the work it does wrong and again in the context that work is now sitting in. A document it cannot find costs me the same way, in everything it opens on the way to the one it needed.</p><p>My past two articles, on <a href="https://articles.agentience.ai/p/smoothing-the-seams-between-claude">smoothing the seams between sessions</a> and <a href="https://articles.agentience.ai/p/seeing-every-claude-session-at-once">seeing them all at once</a>, were inspired by my continual effort to get a grasp on the multitude of agents I have running across multiple projects and ultimately, grappling with <strong>my own limited context window</strong>. Part of that has been encouraging the agents to document and with the pace of change the agents afford, that's <strong>a lot</strong> of documentation. That can quickly get out of hand, disorganized, and stale.</p><p>There are more than a handful of solutions out there already that attempt to address this.  So many, in fact, that rather than picking one that didn't work out, I thought I'd engage Claude Opus to help me out. I'm not going to claim it beats them, because I haven't run them side by side. What I can show you is what this one measures, on a real 136-document tree, and you can decide from there whether it's the approach you want.</p><p>What came out of that is <code>doc-librarian</code>, a Claude Code skill that treats <code>docs/</code> as what it literally is, a small library, and applies the discipline libraries have used for well over a century: a taxonomy, a controlled vocabulary, a catalog, hub-and-spoke indexes, and a records lifecycle that ends in an archive rather than a delete.</p><p>The agent-builds-on-a-stale-document failure is the one I felt first. A person skimming a docs folder can usually smell that something has gone off: the screenshot is from an old UI, the command has a flag that no longer exists. An agent reads it at face value and starts building. So "which of these documents are still true" stops being a tidiness question and becomes a correctness one, and the answer that worked for me was structural: a document is either current, or it is visibly archived, and there is no third state where it sits in a live folder looking authoritative. That rule turned out to answer the other half as well, since a folder with the dead documents visibly out of it is a smaller thing to search.</p><p>Then I pointed it at my own worst case: a 9-package TypeScript monorepo, 136 markdown documents, frontmatter on none of them, and nobody who could say which of them were still true.</p><p>This is for people whose <code>docs/</code> has outgrown their memory of it, enough documents that "I'll just read them" has stopped being a plan. If yours is a dozen files you wrote this quarter, you don't have this problem yet.</p><h2>TL;DR</h2><ul><li><p><code>doc-librarian</code> is a Claude Code skill that audits, triages, reorganizes, indexes and weeds a <code>docs/</code> tree, and installs the enforcement that keeps it organized afterwards.</p></li><li><p>Every verdict is measured, not guessed: staleness from <code>git log</code>, orphanhood from a repo-wide referrer count that reads source and config as well as other docs, near-duplicates from TF-IDF cosine.</p></li><li><p>Cheap signal runs first and scores the whole tree in 11 seconds. Agents are spent reading only the pile it couldn't decide.</p></li><li><p>It never deletes a referenced document. The lifecycle is deprecate, archive, and much later dispose, and the step that moves and rewrites does nothing until you pass <code>--apply</code>.</p></li><li><p>The second half is a governance kit: a linter, an authoring-time guard that nudges any agent writing a non-conforming doc, and a commit-time gate.</p></li><li><p>Install and driving instructions: <a href="https://github.com/agentience/agentience-skills/blob/main/skills/doc-librarian/START-HERE.md">START-HERE.md</a>.</p></li></ul><h2>How a docs directory decays</h2><p>Sprawl, duplication, orphans, stale shelves, and no catalog: nothing that says what each document is <em>for</em>, so classification lives only in whoever wrote it. You have all five or you wouldn't be reading this.</p><p>The cost is in the deciding rather than the reshuffling. To know whether a document is still true, someone has to read it and then read the code it describes, and at 136 documents I'd put that at a week I didn't have. So the tree stays as it is, and each new document is filed by vibes into whichever folder looks least wrong.</p><p>There's a second cost that only shows up once you start moving things. Documentation gets cited from live source, tests, CI config, editor and agent config, and root-level <code>README</code> and <code>CLAUDE.md</code> files. On my corpus, <strong>56 of the 62 documents that moved had referrers outside </strong><code>docs/</code><strong>, and 30 of those were hard</strong>. An ESLint config naming a standards doc, a JSDoc comment citing a design doc, a <code>@see</code> on an exported function, a test asserting a filename. A docs reorganization is not a docs-only change, and finding that out halfway through a migration is a bad time to learn it.</p><h2>The methodology</h2><p>Library science already has answers for all five, and the skill is organized around them rather than around file operations. Documents are classified by <a href="https://diataxis.fr/">Di&#225;taxis</a>, which sorts by what the reader is <em>doing</em> rather than by subject and is mutually exclusive and collectively exhaustive, which is what stops folders multiplying. Tags come from a curated <code>TAGS.md</code> and nowhere else, because inventing one at write time gives you <code>auth</code>, <code>authentication</code> and <code>authn</code> as three separate facets. The rest is bookkeeping that pays for itself: frontmatter on every document so the corpus is queryable, a README in every folder so nothing is reachable only by grep, and a lifecycle that ends in an archive rather than a delete, because the archive is what makes weeding safe enough to actually do.</p><p>Underneath all five is the discipline that makes the rest trustworthy: <strong>every verdict has to cite something.</strong> A document is stale because git says when it last changed. It's an orphan because a repo-wide grep found nothing pointing at it, checked against source and config rather than just other documents. It's a near-duplicate because the TF-IDF cosine cleared a threshold you set, and without the optional Python pass installed that one degrades to matching normalized titles, which the report tells you.</p><p>The measurements are not automatically right, and mine were wrong. An early version of the referrer counter only looked at links between documents, so anything cited from source code counted as an orphan, and orphanhood feeds the WEED bucket. It was routing live documents toward deletion.</p><p>What saved it was that every row prints its evidence. The agents reading the REVIEW pile kept returning verdicts that contradicted the score. <em>This says orphaned, but it's cited from </em><code>AgentSpecGenerator.ts:456</code><em> and four other places.</em> They did that on five different documents, independently, without being told the bug existed.</p><p>The safety guarantees lean on that same counter. The rule that a referenced document is never deleted is enforced by the count that was wrong, so a miscounted document reads as unreferenced and the guard waves it through, which is why the WEED pile still goes to the reading agents and why I'd treat that guard as the second line rather than the first.</p><p>Fixing that counter and two related path-resolution bugs reclassified <strong>42 of the 136 documents</strong> as KEEP, cutting the pile that needed an agent to read it from 96 to 56.</p><h2>What a run looks like</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HDBZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2f3377e-bc2c-4985-9f5d-98bd698d0969_1640x1560.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HDBZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2f3377e-bc2c-4985-9f5d-98bd698d0969_1640x1560.png 424w, https://substackcdn.com/image/fetch/$s_!HDBZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2f3377e-bc2c-4985-9f5d-98bd698d0969_1640x1560.png 848w, https://substackcdn.com/image/fetch/$s_!HDBZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2f3377e-bc2c-4985-9f5d-98bd698d0969_1640x1560.png 1272w, https://substackcdn.com/image/fetch/$s_!HDBZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2f3377e-bc2c-4985-9f5d-98bd698d0969_1640x1560.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HDBZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2f3377e-bc2c-4985-9f5d-98bd698d0969_1640x1560.png" width="1640" height="1560" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a2f3377e-bc2c-4985-9f5d-98bd698d0969_1640x1560.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1560,&quot;width&quot;:1640,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:165065,&quot;alt&quot;:&quot;Triage measures all 136 documents; only the 60 it could not settle are ever read by an agent.&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Triage measures all 136 documents; only the 60 it could not settle are ever read by an agent." title="Triage measures all 136 documents; only the 60 it could not settle are ever read by an agent." srcset="https://substackcdn.com/image/fetch/$s_!HDBZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2f3377e-bc2c-4985-9f5d-98bd698d0969_1640x1560.png 424w, https://substackcdn.com/image/fetch/$s_!HDBZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2f3377e-bc2c-4985-9f5d-98bd698d0969_1640x1560.png 848w, https://substackcdn.com/image/fetch/$s_!HDBZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2f3377e-bc2c-4985-9f5d-98bd698d0969_1640x1560.png 1272w, https://substackcdn.com/image/fetch/$s_!HDBZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2f3377e-bc2c-4985-9f5d-98bd698d0969_1640x1560.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Triage measures all 136 documents; only the 60 it could not settle are ever read by an agent.</figcaption></figure></div><p>Triage is the cheap half, and <code>triage-docs.ts</code> scores every document on staleness, inbound references, dead code anchors, duplicate similarity and location, and drops each into one of three buckets: <strong>KEEP</strong>, <strong>WEED</strong>, or <strong>REVIEW</strong>, where REVIEW explicitly means "the signal could not decide this one." On my corpus that split the 136 into 76 KEEP, 56 REVIEW and 4 WEED, and the 76 never get read by anything. It prints its reasoning per row, in the tool's own words: <code>very stale (14mo)</code>, <code>orphaned (no inbound links anywhere)</code>, <code>dead code anchors (0% resolve)</code>, <code>in "migration/" (iterative/likely-completed)</code>.</p><p>The deep dive is the expensive half, and it runs only on what the score didn't settle: REVIEW, plus the small WEED pile, because nothing gets discarded on a score alone. <code>plan-review-batches.ts</code> packs that bucket into batches of <em>related</em> documents, so one agent reading a folder sees the whole folder, and writes a brief per batch. Then one agent per batch reads the documents and the code around them and returns a per-document verdict with evidence. On my corpus that was 15 batches for 102 documents, and that is the number to price it by rather than the 11 seconds, which only ever covered the cheap half. That 102 is what I actually paid, because I ran the appraisal before I had fixed the referrer counter, when triage was still handing it 96 REVIEW and 6 WEED. With the counter fixed the same corpus routes 60 documents to the agents instead, which is the figure to plan against.</p><p>Here is a real one, trimmed. This is the actual output row for a document in my repo:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;typescript&quot;,&quot;nodeId&quot;:&quot;1bc36e31-e2d6-4d70-b4d1-5b9e0808c1ae&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-typescript">doc_path:  migration/branded-ids.md
verdict:   ARCHIVE      confidence: high      inbound_links: 0

One-shot generated snapshot from 2026-05-13, never regenerated since. All 339
checkboxes are still unchecked (`grep -c '^- \[x\]'` &#8594; 0) despite active,
ongoing ID-branding work in the same area since. Spot-checked line-number
anchors have drifted: `orchestration-engine.ts:178` no longer contains the
cited `runId?: string;` snippet.

Flag for the librarian: that generator script's OUTPUT_PATH still points at
`docs/migration/branded-ids.md` &#8212; if anyone re-runs it, the file reappears at
this path, undoing an archive-move unless the script is also updated.</code></pre></div><p>That last paragraph is the reason the deep dive exists. No amount of scoring finds a script that will silently recreate a document you just archived. Somebody reading the code around it does, and that is the only thing that found it.</p><p>The verdicts roll up into a migration map, and <strong>the map is what you sign off on, rather than the migration itself.</strong> Here is how mine opens:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;markdown&quot;,&quot;nodeId&quot;:&quot;ef9c8f4a-9f97-46b2-af38-e496a6e21e3d&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-markdown">Proposed by `doc-librarian` Procedure B. **Nothing has been moved.** This is the
sign-off artifact: approve it, or amend it, before the first `git mv`.

## Shape

| | count |
|---|---:|
| documents today | 136 |
| stays put &#8212; `docs/TAGS.md`, the vocabulary | 1 |
| &#8594; `archive/` | 73 |
| &#8594; `tutorials/` | 1 |
| &#8594; `how-to/` | 13 |
| &#8594; `reference/` | 16 |
| &#8594; `explanation/` | 26 |
| &#8594; `decisions/` | 1 |
| &#8594; `project/` | 5 |
| frontmatter to author (every surviving doc has none) | 62 |
| moving docs with live non-docs referrers to rewrite | 22 |

## Needs your call &#8212; 5 items</code></pre></div><p>Those five are the things it would not decide for me, among them two duplicate pairs where one copy of each is regenerated by a skill, and a document whose generator hardcodes the old path in four places. The per-document tables come after all of that, current path to target path with the live referrers each move would break. The skill is explicit that you don't map and move at the same time. Read the map next to the verdicts rather than on its own, though: the map is destinations and counts, and the reasoning that caught my orphan bug lives in the verdict report beside it.</p><h2>What it writes, and how to undo it</h2><p>Worth having as a closed list before you point it at anything, because it is otherwise spread across three phases.</p><p>Installing the skill touches <code>~/.claude/skills/</code> and nothing else, so no repository and no <code>settings.json</code>.</p><p><code>/doc-librarian setup</code> writes six things into the repo you run it in, all tracked: <code>docs/scripts/lint-docs.ts</code>, <code>.claude/hooks/docs_structure_guard.py</code>, a starter <code>docs/TAGS.md</code> if you don't already have one, a hook entry in <code>.claude/settings.json</code>, npm scripts in <code>package.json</code>, and a <code>.doc-librarian/</code> line in <code>.gitignore</code>. The <code>settings.json</code> entry is the one your teammates inherit.</p><p>The migration moves documents with <code>git mv</code>, so every move lands as a rename with its history intact, and rewrites links inside <code>docs/</code>. It does nothing at all until you pass <code>--apply</code>.</p><p>Then run it on a branch and <code>git diff</code> each batch before you commit it. That is not me being careful for its own sake: it's how I caught the frozen-capture corruption in my own migration, and the tool never would have.</p><h2>Adopting it: the initial cleanup</h2><p>Install is a clone, a dry run, and an installer:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:&quot;16db9459-051d-411e-91fa-9fdff9bb62cd&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">git clone https://github.com/agentience/agentience-skills.git
cd agentience-skills/skills/doc-librarian
./install.sh --dry-run     # prints every path it would touch
./install.sh</code></pre></div><p>It symlinks into <code>~/.claude/skills/</code>, writes nothing to <code>settings.json</code>, and changes no repository. Then start a new session &#8212; a running one keeps the skill text it loaded at startup.</p><p>From inside the repo you want organized, <code>/doc-librarian setup</code> installs the governance kit. The recommended order for a neglected tree is then: bootstrap a tag vocabulary from the corpus's own language, weed, audit what survived, finalize governance, reorganize, index. That is <code>G &#8594; E &#8594; A &#8594; F &#8594; B &#8594; D</code> in the skill's own lettering. It reads one <code>docs/</code> tree, so on a monorepo you point it at the one you mean rather than at nine.</p><p>The order is not arbitrary, and weeding before reorganizing is the part I'd insist on: reshuffling documents you're about to discard is wasted work, and a clean new structure lends false authority to dead content. Audit after weeding too, so you're measuring the collection you're actually keeping.</p><p>Two things to do before the first <code>git mv</code>, both of which I'd have skipped if the skill hadn't insisted:</p><p>The first is the broken-link baseline. Run the linter before you touch anything and write the number down. Afterwards, an absolute count of broken links tells you nothing &#8212; a corpus that was already broken will still be broken, and without the baseline you cannot separate breakage you caused from breakage you inherited. Mine was 25 before and 13 after, every remaining one a strict subset of the original 25. The honest claim is "no <em>new</em> broken links," and you can only make it if you measured first. As a side effect the migration repaired 12 links that were already broken.</p><p>The second is the blast radius. For every document the map moves, <code>git grep -l "old/path.md" -- ':!docs'</code>, and classify each referrer as soft (only other docs) or hard (source, tests, config, root files), and report the split before you start. That split, 56 of 62 with 30 of them hard, is what told me the migration had to pass the test suite and not just the link checker.</p><p>Then migrate in batches, verify each, commit each, and never start a batch while the previous one has left new breakage. <code>apply-actions.ts</code> does the mechanical work and is dry-run by default; it refuses to delete a document with inbound links even when you ask it to.</p><p>One rule I'd put on a sticker: <strong>frozen artifacts are not documents.</strong> Test fixtures, captured model outputs, recorded HTTP sessions. These live under <code>docs/</code> in a lot of repos, and a link rewriter will happily rewrite them. Rewriting a captured output changes the thing it recorded. In my migration an early pass silently edited 22 frozen experiment captures, one set of which existed precisely to measure whether a model cites file paths that exist. It was caught by a <code>git diff</code> against those directories, not by anything in the tool, which is why it's now rule seven of the skill's safety rules. It stayed a rule rather than a guard: nothing in the tool excludes them for you.</p><h2>Adopting it: keeping it clean</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!udP3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaa8662d-a99c-499d-917a-2a5f8d8908fe_1640x840.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!udP3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaa8662d-a99c-499d-917a-2a5f8d8908fe_1640x840.png 424w, https://substackcdn.com/image/fetch/$s_!udP3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaa8662d-a99c-499d-917a-2a5f8d8908fe_1640x840.png 848w, https://substackcdn.com/image/fetch/$s_!udP3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaa8662d-a99c-499d-917a-2a5f8d8908fe_1640x840.png 1272w, https://substackcdn.com/image/fetch/$s_!udP3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaa8662d-a99c-499d-917a-2a5f8d8908fe_1640x840.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!udP3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaa8662d-a99c-499d-917a-2a5f8d8908fe_1640x840.png" width="1640" height="840" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/faa8662d-a99c-499d-917a-2a5f8d8908fe_1640x840.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:840,&quot;width&quot;:1640,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:85135,&quot;alt&quot;:&quot;The guard corrects a document in the same turn that wrote it; the commit gate catches whatever it missed.&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The guard corrects a document in the same turn that wrote it; the commit gate catches whatever it missed." title="The guard corrects a document in the same turn that wrote it; the commit gate catches whatever it missed." srcset="https://substackcdn.com/image/fetch/$s_!udP3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaa8662d-a99c-499d-917a-2a5f8d8908fe_1640x840.png 424w, https://substackcdn.com/image/fetch/$s_!udP3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaa8662d-a99c-499d-917a-2a5f8d8908fe_1640x840.png 848w, https://substackcdn.com/image/fetch/$s_!udP3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaa8662d-a99c-499d-917a-2a5f8d8908fe_1640x840.png 1272w, https://substackcdn.com/image/fetch/$s_!udP3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffaa8662d-a99c-499d-917a-2a5f8d8908fe_1640x840.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The guard corrects a document in the same turn that wrote it; the commit gate catches whatever it missed.</figcaption></figure></div><p>A one-shot cleanup has nothing holding it in place. The repo that produced those 136 documents is still producing them at the same rate, so the half I'd expect to matter more over time is the part that runs afterwards, and it's what <code>/doc-librarian setup</code> installs:</p><ul><li><p><code>lint-docs.ts</code>, copied into your repo as the single source of truth for every check: links, tags against the controlled vocabulary, frontmatter schema, bucket/type agreement.</p></li><li><p><strong>A </strong><code>PostToolUse</code><strong> guard hook</strong>, registered in that repo's <code>.claude/settings.json</code>, so it fires for everyone who works in the repo, not just you. When any agent writes a document that doesn't conform, the hook exits non-zero and hands the agent back the fix list: classify the Di&#225;taxis type, pick the one correct folder, add frontmatter, name it kebab-case, wire it into the index. The write has already happened at that point; what you get is the agent correcting it in the same turn rather than someone auditing it months later. It fails open on any error of its own, so a broken hook never blocks authoring.</p></li><li><p><strong>A commit-time gate</strong>: <code>lint-docs.ts --staged</code> in your pre-commit hook, blocking, plus <code>--staleness</code> as a non-blocking review report.</p></li><li><p><code>.doc-librarian/</code> gitignored, with the reports written there rather than into <code>docs/</code>. A report written into the tree becomes a document, and the next scan appraises the skill's own output alongside your corpus. That one isn't finished &#8212; <code>plan-review-batches.ts</code> still defaults its briefs into the tree it just read, so pass it an out-dir.</p></li></ul><p>The guard is Claude Code-specific; the linter and the pre-commit gate are not, so on a client without hooks you get the same rules one step later.</p><h2>What it won't do</h2><p>Named up front, because each of these bit mine:</p><ul><li><p><strong>Reference counting is liveness-blind.</strong> A citation from <code>specs/completed/</code> weighs exactly as much as one from live source, so a genuinely dead document can hold itself out of the WEED bucket on dead referrers. It errs toward human review rather than deletion, which is the safe direction &#8212; but a high inbound count is not proof of relevance.</p></li><li><p><strong>Nothing checks anchors.</strong> <code>guide.md#configuration</code> survives a move as a link to the right file and the wrong place in it. The linter sees paths, not fragments; the skill tells you to grep them by hand.</p></li><li><p><strong>It rewrites links inside </strong><code>docs/</code><strong> only.</strong> Referrers in source, tests and config are counted but not rewritten, so you get the list and the edits are yours to make.</p></li><li><p><strong>It can write to files under </strong><code>docs/</code><strong> that aren't documents.</strong> Anything in the docs tree that is a captured artifact rather than prose is fair game for the link rewriter, and excluding it is a rule the skill states rather than a check the code runs, which is how 22 of mine got rewritten.</p></li><li><p><strong>It cannot tell you what is true.</strong> It measures stale, orphaned and duplicated. Whether the content is still <em>correct</em> is a reading task &#8212; that's what the deep dive is for, and even that returns verdicts for a human to accept.</p></li></ul><p>The first three are open on purpose: design questions I'd have had to guess at, and a skill that quietly did the wrong thing in those places would be worse than one that names them. The fourth is not on purpose; it is unfinished, and it is the one I'd check by hand.</p><h2>Try it</h2><p>The fastest path is to hand an agent the bootstrap document and let it install and drive the skill itself:</p><blockquote><p>Read <a href="https://raw.githubusercontent.com/agentience/agentience-skills/main/skills/doc-librarian/START-HERE.md">https://raw.githubusercontent.com/agentience/agentience-skills/main/skills/doc-librarian/START-HERE.md</a> and follow it.</p></blockquote><p>It's written for an agent rather than a person, it's self-contained, and it ends with the rules that keep an enthusiastic agent from destroying a corpus quickly and plausibly. Everything else, the eight procedures and the scripts and the templates, is in <a href="https://github.com/agentience/agentience-skills/tree/main/skills/doc-librarian">the repo</a>.</p><p>Start with <code>audit</code>. It only counts things, so it's the one step I'd run without thinking twice about it.</p>]]></content:encoded></item><item><title><![CDATA[Seeing every Claude session at once]]></title><description><![CDATA[Moving a dozen-plus Claude sessions out of VS Code's terminal into one status list &#8212; and porting the workflow instead of replacing it]]></description><link>https://articles.agentience.ai/p/seeing-every-claude-session-at-once</link><guid isPermaLink="false">https://articles.agentience.ai/p/seeing-every-claude-session-at-once</guid><dc:creator><![CDATA[Troy Molander]]></dc:creator><pubDate>Mon, 24 Aug 2026 22:16:45 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!BF4t!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb262f8c2-7b35-4e5e-ac5a-279be314a3bc_1082x1082.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Three to five VS Code windows open in different projects, four to six Claude sessions running in each. Any one of them could be working, finished, blocked on a permission prompt, or waiting on a decision only I could make, and the only way to find out was to go and look. I found the ones that were waiting on my next pass through the windows, maybe every 20 minutes, sometimes much longer.</p><p>A friend (thanks <a href="https://www.linkedin.com/in/patrick-santora-jr/">Pat Santora</a>!) pointed me at <a href="https://herdr.dev">Herdr</a> and said it might get all of that into one place.</p><p>So I moved every session out of VS Code's integrated terminal into Herdr, running standalone in iTerm2, one workspace per repo. The editor is now purely for reading and editing code. What I get back is a sidebar that reports what every agent in every project is doing, without me going to look.</p><p>This is for people running more agents than they can hold in their head &#8212; several repos, several sessions in each. If you run one session in one repo, the terminal you already have is fine.</p><h2>TL;DR</h2><ul><li><p>With 12 to 30 sessions across 3 to 5 windows, I was the only thing that knew when one of them needed me, and I only knew by going and looking.</p></li><li><p>Herdr is a terminal multiplexer &#8212; tmux's category &#8212; that knows which of its panes are running agents. One workspace per repo, and the sidebar reports each agent as working, idle, done, blocked or unknown, across every project at once. There are audio cues too.</p></li><li><p>The lag from a session needing me to me knowing about it went from about 20 minutes &#8212; my next pass through the windows &#8212; to under a minute. <strong>Nothing became automatic</strong>: what I do when I get there is unchanged, and I still start every one of those actions myself. Only the noticing moved.</p></li><li><p>I didn't wait for the migration to break things. I listed the two workflows I refused to lose and solved both before switching: my tmuxp layouts, and Ctrl+Shift+W to jump between projects without touching the mouse.</p></li><li><p>One already existed as a plugin and needed two upstream PRs to fit; the other I wrote. Neither took a day.</p></li><li><p>Herdr: <strong><a href="https://herdr.dev">herdr.dev</a></strong>. The project-jump plugin: <strong><a href="https://github.com/agentience/herdr-plugin-ide-jump">github.com/agentience/herdr-plugin-ide-jump</a></strong></p></li></ul><div><hr></div><p>Here is the artifact, from this machine, right now &#8212; every pane in every project that has an agent in it:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:null,&quot;nodeId&quot;:&quot;0fd75df0-02bd-4613-b798-8200c99bb3aa&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-null">w8  client-a         w8:pP  claude  working  spreader-label-normalise
w8  client-a         w8:pD  claude  idle     Starting without starting
w8  client-a         w8:pH  claude  idle     Claude Code
w8  client-a         w8:pQ  claude  idle     Claude Code
wA  tribal-markdown  wA:p2  claude  idle     Startup baseline exploration
wH  client-b         wH:p7  claude  idle     Claude Code
wR  ide-jump         wR:p4  claude  idle     Plugin Windows compatibility verification
wS  herdr-spreader   wS:p1  claude  idle     Claude Code</code></pre></div><p>Twelve workspaces on this machine, one per repo. Eight panes had an agent in them at the moment I captured that. Client project names are redacted, nothing else is. In the terminal this is a sidebar rather than a list I ask for, and the fourth column is the whole point: one working, seven waiting on me.</p><h2>The noticing was the problem</h2><p>An agent session asks for you in several different ways. It finishes and sits idle. It stops on a permission prompt and waits. It reaches a decision it can't make &#8212; which of two approaches, whether to touch a file it wasn't asked to touch. It runs long enough that the useful thing to do is <a href="https://articles.agentience.ai/p/smoothing-the-seams-between-claude">end it and carry the state forward</a>, the one case I'd already built machinery for. Every one of those is the same event from where I sit: this session is now waiting on me.</p><p>With four to six sessions in a window and three to five windows, the only way to catch that event was to look. So I looked, in rounds: cycle the windows, read what each session was doing, deal with anything finished or blocked, go back to whatever I'd been doing. Between rounds, a session that stopped sat there. Twenty minutes was a good pass; some were much longer.</p><p>Now the state is reported to me instead. A session that goes quiet shows as idle in a list already on screen, and I answer it in under a minute &#8212; or I see it and know it's something to get to as soon as I can, which is a different and equally useful thing to know. Herdr classifies each agent pane as working, idle, done, blocked or unknown, and two of those carry most of the value. <code>done</code> is the same quiet pane as <code>idle</code>, labelled differently because the work finished while I wasn't looking at that tab. <code>blocked</code> means Herdr recognised an approval or question prompt on screen. "It finished" and "it's stuck on me" are the two things I most need to tell apart from across the room, and they're now different words in a list rather than two screens that look alike.</p><p>Nothing became automatic. Every action I take when I get there, I still start myself. What changed is when I find out. A session that wants an answer, a decision or a handoff now says so while it is waiting, rather than on my next lap through the windows. The improvement is entirely in the gap between a session needing me and my knowing about it, and that gap was the cost.</p><h2>Adapting to Herdr, and adapting Herdr to me</h2><p>The sessions moved out of the editor, one workspace per repo, and I learned Herdr's shape rather than reaching for the tmux commands I already knew. That part I just took.</p><p>But I wanted to keep some of the niceties of the workflow I already had. Before moving, I named the two things I use constantly and would notice losing, and went at them before they could become problems:</p><p><strong>My tmuxp layouts.</strong> I like being able to launch or re-establish the several windows I'm used to in a repo without re-initialising them each time. Herdr has no equivalent config file. The server persists workspaces, tabs, panes and their directories itself, which covers the normal day but not a machine that has just come up. I looked at how to solve that, checked the plugin marketplace, and found a near-exact solution already there: <a href="https://github.com/yuk1ty/herdr-spreader">herdr-spreader</a>, which applies tmuxinator-style layouts from YAML.</p><p>Near-exact, not exact. It could build a layout but not <em>re-apply</em> one &#8212; every run created a second copy of everything &#8212; and its layouts had to live in one central file rather than in the repos they describe. Both gaps went upstream as PRs: <code>--on-existing create|skip|sync</code> so a re-run adds only what's missing, and <code>include:</code> so the central config can point at a layout file that ships with each repo. A stranger was running the first one within a day and found a real defect in it: my tab matching compared labels exactly, so another plugin that renumbers tabs to <code>[1] name</code> made every tab look missing and duplicated the lot. They diagnosed it and proposed the fix, which is now in.</p><p><strong>Ctrl+Shift+W.</strong> In VS Code that hotkey is how I switch projects &#8212; pick the one I want from a list, no mouse, no hunting through windows. Nothing in Herdr did that, so I wrote <a href="https://github.com/agentience/herdr-plugin-ide-jump">ide-jump</a>: a plugin that raises the editor window for the project a pane belongs to, either directly or through a filterable picker with the current repo already selected. It was built before it became an issue, which is the part I'd repeat. It has since taken an outside contribution adding a Windows backend, and it works with editors other than VS Code.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0MIR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F936b1860-1b7e-4357-bcac-d3cd3970b07f_472x242.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0MIR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F936b1860-1b7e-4357-bcac-d3cd3970b07f_472x242.png 424w, https://substackcdn.com/image/fetch/$s_!0MIR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F936b1860-1b7e-4357-bcac-d3cd3970b07f_472x242.png 848w, https://substackcdn.com/image/fetch/$s_!0MIR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F936b1860-1b7e-4357-bcac-d3cd3970b07f_472x242.png 1272w, https://substackcdn.com/image/fetch/$s_!0MIR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F936b1860-1b7e-4357-bcac-d3cd3970b07f_472x242.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0MIR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F936b1860-1b7e-4357-bcac-d3cd3970b07f_472x242.png" width="472" height="242" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/936b1860-1b7e-4357-bcac-d3cd3970b07f_472x242.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:242,&quot;width&quot;:472,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:47648,&quot;alt&quot;:&quot;The ide-jump picker, with the current repo already selected: type to filter, enter to raise that project's editor window.&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The ide-jump picker, with the current repo already selected: type to filter, enter to raise that project's editor window." title="The ide-jump picker, with the current repo already selected: type to filter, enter to raise that project's editor window." srcset="https://substackcdn.com/image/fetch/$s_!0MIR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F936b1860-1b7e-4357-bcac-d3cd3970b07f_472x242.png 424w, https://substackcdn.com/image/fetch/$s_!0MIR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F936b1860-1b7e-4357-bcac-d3cd3970b07f_472x242.png 848w, https://substackcdn.com/image/fetch/$s_!0MIR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F936b1860-1b7e-4357-bcac-d3cd3970b07f_472x242.png 1272w, https://substackcdn.com/image/fetch/$s_!0MIR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F936b1860-1b7e-4357-bcac-d3cd3970b07f_472x242.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The ide-jump picker, with the current repo already selected: type to filter, enter to raise that project's editor window.</figcaption></figure></div><p>Two gestures, two solutions, neither of them a day's work. What made it cheap was that the platform had a seam wherever I needed one &#8212; a plugin marketplace with a maintained project already in it, and an upstream that takes PRs.</p><h2>What VS Code is for now</h2><p>Reading and editing code. That's it.</p><p>That reads like a small change and isn't: the integrated terminal was where every agent lived, which meant the editor window was also the session window, and the two were stuck together. Pulling them apart is what let the sessions be listed somewhere else. It's also why <code>ide-jump</code> had to exist before the move rather than after &#8212; with the terminal outside the editor, "get me to the code for this project" becomes a gesture that needs its own answer.</p><h2>What it still costs</h2><p>Jumping back and forth between the terminal window and each of my IDE sessions is a habit I'm still building. The plugin helps a lot &#8212; that's what it's for &#8212; but going from one window that held both to two windows that hold one each is a real change, and I notice it.</p><p>That's the trade the whole thing rests on: the terminal and the editor stopped being the same window, and in exchange every agent in every project reports its state to one place.</p><h2>Try it</h2><ul><li><p><strong>Herdr</strong> &#8212; <a href="https://herdr.dev">herdr.dev</a>. Start it, make a workspace per repo, and run your sessions in it. The status list is the feature; everything else here is me refusing to give up two gestures.</p></li><li><p><strong>herdr-spreader</strong> &#8212; <code>herdr plugin install yuk1ty/herdr-spreader</code>, if you want your layouts back. The idempotence and repo-local-layout PRs (<a href="https://github.com/yuk1ty/herdr-spreader/pull/17">#17</a>, <a href="https://github.com/yuk1ty/herdr-spreader/pull/18">#18</a>) are open at the time of writing, so check whether they've landed before you rely on <code>--on-existing sync</code>.</p></li><li><p><strong>ide-jump</strong> &#8212; <code>herdr plugin install agentience/herdr-plugin-ide-jump</code>. Note that title matching needs your editor to put the folder name in the window title; VS Code needs <code>"window.title": "${rootName}"</code> for this to work.</p></li></ul><p>If you're deciding whether it's worth it, the question I'd ask is the one Pat effectively asked me: how do you currently find out that a session needs you? If the answer is "I go and look," that's the thing this replaces.</p>]]></content:encoded></item><item><title><![CDATA[Smoothing the seams between Claude Code sessions]]></title><description><![CDATA[Using a handoff document and a tmux hook to keep your work running across multiple sessions]]></description><link>https://articles.agentience.ai/p/smoothing-the-seams-between-claude</link><guid isPermaLink="false">https://articles.agentience.ai/p/smoothing-the-seams-between-claude</guid><dc:creator><![CDATA[Troy Molander]]></dc:creator><pubDate>Fri, 14 Aug 2026 00:48:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!tIim!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3a92f90-f499-498b-a504-c3f453475388_588x731.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>'90% of your weekly limits are used, you have 3 days left before they reset.' I run Claude Code on a Max plan all day, and the 1M context window is how I got there. At first it was a relief. No more watching for the automated 'compact' run to condense the session and lose its nuances; I'd always been good at catching that and running my own handoff first. Then I got lazy with the 1M and stopped.</p><p>So I went back to the discipline I'd let slide. When I want to bring the context back down, I run <code>/handoff</code>. Everything after that call is automatic: the document gets written, and the next session opens already reading it. Two thousand words of state instead of the 500K-token session they came from.</p><p>This is for long sessions across several repos or more than one machine. If your sessions are short and single-threaded, you don't have this problem yet.</p><h2>TL;DR</h2><ul><li><p>When I want to manage the context down, I run <code>/handoff</code>. It writes a <strong>handoff document</strong> into the repo: decided vs. open, traps, don't-touch, decisions I owe, verification state.</p></li><li><p>The session writing it <strong>starts the fresh session</strong> &#8212; a hook replaces the tmux window with a fresh session that has already read the document and starts the work. This helps alleviate my brain's context overload with multiple sessions running.</p></li><li><p>Drafting is delegated to a cheap subagent working from a digested transcript, but the salience &#8212; what mattered, what to avoid &#8212; comes from the session that did the work, written out before it hands over. That split is the load-bearing part.</p></li><li><p>Versus <code>/compact</code>: you choose <em>when</em> it runs, never <em>what</em> survives, and you never see the result. A big window doesn't fix that, it postpones it. Nothing forces a checkpoint, so you carry the whole session all day, and that's what burns the limit.</p></li><li><p>Installable, degrades cleanly without tmux, and mostly portable to other agents: <strong><a href="https://github.com/agentience/agentience-skills">github.com/agentience/agentience-skills</a></strong></p></li></ul><div><hr></div><p>For work that runs across sessions and machines, I wanted a carry-forward I write, review and commit. Here's the actual artifact, from a real project, trimmed:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;markdown&quot;,&quot;nodeId&quot;:&quot;86eff78c-e773-4919-9ea4-b9df4934aec1&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-markdown"># /handoff &#8212; skill shipped and verified twice; only the post is left

## Work items
- [x] Built the relaunch chain &#8212; marker file + Stop hook &#8212; committed
      3ce9f60. Verified across 5 stubbed hook paths.
- [x] Verified the packaged skill end to end on a second machine, twice.
      Three defects found and fixed (f5475f5).
- [ ] **(in progress)** Retry the install on a machine with no nvm.
      Preflight passes there; the actual run has never been tried.

## Traps
- A running session keeps the command text it loaded at startup. Only a
  NEW session proves an edit works &#8212; testing in the session that made the
  edit tests the old text every time.
- The marker file must carry the `.claude/handoffs/` prefix, not a bare
  filename. Evidence in the log at 19:12:59: "named a missing doc &#8212;
  not relaunching."

## Don't touch
- The uncommitted work in the plugin repo &#8212; other sessions', not this
  one's. Commit path-scoped.

## Decisions needed
1. How much tmux-specificity to keep. Recommend: ship both halves, make
   the relaunch a clean no-op without tmux, say so in the README.</code></pre></div><p>That's what <code>/handoff</code> leaves behind when I call it. You can find plenty of handoff variants; what happens to it next is where this stops looking like just another handoff, so that's where I'll start.</p><h2>Closing the seam</h2><p>Every write-up on session handoffs I've read stops one step short of here: write a good summary for the next session, and you're done. But a document does nothing until someone opens it, and with several sessions going, that can be hours. The work wasn't waiting on the handoff. It was waiting on me.</p><p>So the last thing <code>/handoff</code> does is leave a marker file naming the document it just wrote. A hook picks that up as the session ends and replaces the tmux window with a fresh session that starts by reading the document. Same window, same place on screen. What's in it is a new session, several steps ahead of where I left off.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tIim!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3a92f90-f499-498b-a504-c3f453475388_588x731.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tIim!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3a92f90-f499-498b-a504-c3f453475388_588x731.png 424w, https://substackcdn.com/image/fetch/$s_!tIim!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3a92f90-f499-498b-a504-c3f453475388_588x731.png 848w, https://substackcdn.com/image/fetch/$s_!tIim!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3a92f90-f499-498b-a504-c3f453475388_588x731.png 1272w, https://substackcdn.com/image/fetch/$s_!tIim!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3a92f90-f499-498b-a504-c3f453475388_588x731.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tIim!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3a92f90-f499-498b-a504-c3f453475388_588x731.png" width="588" height="731" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a3a92f90-f499-498b-a504-c3f453475388_588x731.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:731,&quot;width&quot;:588,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:49980,&quot;alt&quot;:&quot;The relaunch loop&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The relaunch loop" title="The relaunch loop" srcset="https://substackcdn.com/image/fetch/$s_!tIim!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3a92f90-f499-498b-a504-c3f453475388_588x731.png 424w, https://substackcdn.com/image/fetch/$s_!tIim!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3a92f90-f499-498b-a504-c3f453475388_588x731.png 848w, https://substackcdn.com/image/fetch/$s_!tIim!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3a92f90-f499-498b-a504-c3f453475388_588x731.png 1272w, https://substackcdn.com/image/fetch/$s_!tIim!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3a92f90-f499-498b-a504-c3f453475388_588x731.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The relaunch loop</figcaption></figure></div><p>That matters more than it sounds, because I'm never running one session. There are usually several going across different repos &#8212; eight, one day last week &#8212; and I lose track of them. Now the work doesn't idle while I'm elsewhere: I come back an hour later and the session has already read the document and is waiting to start, or has already started, because I asked it to when the handoff was written. Writing the handoff was never the part I dropped. Picking it back up was.</p><p>And it closes. The session that gets started this way opens by reading the document, works, keeps it current as it goes, and ends by handing it on. That's why the command has three modes rather than one:</p><ul><li><p><code>/handoff</code> &#8212; write a new document and hand off.</p></li><li><p><code>/handoff --read &lt;path&gt;</code> &#8212; start a session by loading one, and own it from there.</p></li><li><p><code>/handoff --next</code> &#8212; bring the document you've been maintaining fully current and hand off on <em>it</em>, rather than writing a second document about the same work.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Rf4E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F990a85f1-8c58-4648-971d-d2974017fbf6_456x913.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Rf4E!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F990a85f1-8c58-4648-971d-d2974017fbf6_456x913.png 424w, https://substackcdn.com/image/fetch/$s_!Rf4E!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F990a85f1-8c58-4648-971d-d2974017fbf6_456x913.png 848w, https://substackcdn.com/image/fetch/$s_!Rf4E!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F990a85f1-8c58-4648-971d-d2974017fbf6_456x913.png 1272w, https://substackcdn.com/image/fetch/$s_!Rf4E!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F990a85f1-8c58-4648-971d-d2974017fbf6_456x913.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Rf4E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F990a85f1-8c58-4648-971d-d2974017fbf6_456x913.png" width="456" height="913" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/990a85f1-8c58-4648-971d-d2974017fbf6_456x913.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:913,&quot;width&quot;:456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:44494,&quot;alt&quot;:&quot;The three modes&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The three modes" title="The three modes" srcset="https://substackcdn.com/image/fetch/$s_!Rf4E!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F990a85f1-8c58-4648-971d-d2974017fbf6_456x913.png 424w, https://substackcdn.com/image/fetch/$s_!Rf4E!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F990a85f1-8c58-4648-971d-d2974017fbf6_456x913.png 848w, https://substackcdn.com/image/fetch/$s_!Rf4E!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F990a85f1-8c58-4648-971d-d2974017fbf6_456x913.png 1272w, https://substackcdn.com/image/fetch/$s_!Rf4E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F990a85f1-8c58-4648-971d-d2974017fbf6_456x913.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The three modes</figcaption></figure></div><p><code>--next</code> is what makes this a loop. A maintained document is only current as of the last time you touched it, which is never the moment you stop. So the last thing a session does is bring its own document up to date and pass it to the next one. Work that takes six sessions leaves one file behind, not six, and no session after the first one ever starts cold.</p><h2>Write what's true, not what happened</h2><p>The next session doesn't need the history. It needs to know what to do next, and enough context to do it well. Five headings cover that:</p><ul><li><p><strong>Decided vs. open.</strong> Split honestly. A question you can answer by running one command isn't open, it's unfinished. Answer it now, while you have the context, rather than handing it to a session with less.</p></li><li><p><strong>Traps.</strong> Ordering constraints, stale artifacts, a test that passes for the wrong reason. Everything learned the hard way in the last four hours.</p></li><li><p><strong>Don't touch.</strong> Deliberate non-goals. Half the value of a handoff is stopping the next session from helpfully "fixing" something that's that way on purpose.</p></li><li><p><strong>Decisions you owe.</strong> Real forks, options and a recommendation, in the file. The next session can't read your conversation.</p></li><li><p><strong>Verification state.</strong> What was actually run and observed, written precisely enough that nobody rounds "5 of 7 paths tested" up to "it works."</p></li></ul><p>The judgment isn't in the transcript to be summarized. A digest can tell you what was said and done; it can't tell you that one of those things was a dead end you'd rather never revisit. That distinction is why this is a document rather than a longer context window.</p><p>That list is the part worth stealing whether or not you install anything. It's five headings in a markdown file. Start writing them by hand at the end of your next long session and you'll get the document half of this, everything except the automatic pickup, without any of the machinery.</p><h2>What the subagent can't know</h2><p>Writing the document inside the session that's ending is the expensive way to do it: every turn re-sends the whole accumulated context, so the handoff costs the most exactly when that context is largest. So the work splits in two:</p><ul><li><p>First, the session that did the work writes out the salience: what's decided, what's open, what will bite, what not to touch, what it owes someone else. Two hundred words, no research. It already knows all of this.</p></li><li><p>Then a script reduces the transcript &#8212; main loop plus every subagent sidecar &#8212; to a timestamped timeline: tool calls as one-liners, errors kept, thinking blocks and successful tool output dropped. Roughly 1.5% of the original. A Sonnet subagent drafts the document from that plus the brief, in a fresh context, so none of it lands in the window I'm trying to empty.</p></li></ul><p>The digest gives coverage. Only the session that was there can give salience, and it's the one thing a fresh reader can't reconstruct from a transcript at any price. Skip that half and you get a document that's complete and unusable.</p><p>I measured this across the 66 handoff-writer runs on this machine: the writer takes a median of two minutes and spends about 9K output tokens. Its fresh input is a median of <em>fourteen tokens</em>. The digest is small and everything else is a cache read.</p><p>One side effect worth having: the digest is built from the transcript on disk, which still holds everything the live session compacted away. By hour four the subagent is reading hour one at full fidelity, while the session that lived through it is working from a compacted version of the same hour.</p><h2>Whoever reads it, owns it</h2><p>A handoff describes the moment it was written. The next session reads it, works three hours, learns six things. The file still says what it said this morning. By the third session it's lying.</p><p>So there's a rule: <strong>the session that reads the document maintains it while it works.</strong> Not at the end; sessions don't reliably get an end.</p><ul><li><p>Tick items as they're done. Mark in-progress ones with a line on where they stand, so an interrupted session leaves something that looks half-finished rather than untouched.</p></li><li><p>Append to a dated progress log instead of rewriting it, so a later reader can tell what each session actually did.</p></li><li><p>Put traps next to the item they bite.</p></li></ul><p>What makes it hold is that the document carries its own update instruction, in the file. It gets pasted into fresh sessions where nothing else would enforce it. That rule is what <code>--next</code> hands forward: not a snapshot of when the work started, but a document that's been true at every step since.</p><h2>Try it out</h2><p>One self-contained directory, opt-in and reversible installer:</p><p><strong><a href="https://github.com/agentience/agentience-skills">github.com/agentience/agentience-skills</a></strong></p><p>The relaunch half needs tmux. Without it nothing breaks, you just do the last step yourself: <code>/handoff</code> writes the document and tells you the path, and you open a session and run <code>/handoff --read &lt;path&gt;</code>. That's one line of typing standing between the no-tmux experience and the tmux one. Everything else, the document, the three modes, the ownership rule, is identical. Start a new session after installing. A running session keeps the skill text it loaded at startup, so the one you install from won't see it.</p><h2>If you're not on Claude Code</h2><p>I built and tested all of this on Claude Code, so that's what the repo installs. But almost nothing here depends on it. The parts that carry over as-is are the ones that matter: the section set, the rule that the reading session maintains the document, splitting a mechanical digest from hand-written salience, and leaving a marker file at the end of a session so the next one opens itself.</p><p>Two pieces would need porting. The digest script reads Claude Code's transcript format, so you'd rewrite it against whatever your agent writes to disk, or skip it and draft from live context instead. And something has to notice the marker file when a session ends. Claude Code is the only agent I've tried, but I'd expect any that can run a shell command at that point to work. If yours can't, a wrapper script that runs the agent and then checks for the file gets you there from the outside.</p><p>The document is just markdown in your repo. That part works everywhere, including for the humans on the project.</p><p>Changes are welcome as PRs: a different section set, a port to another agent, whatever you had to fix to make it work where you are. And if you've solved this a different way, put it in the comments &#8212; I'd like to know what I missed.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://articles.agentience.ai/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item></channel></rss>