<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nino Chavez</title>
    <description>The latest articles on DEV Community by Nino Chavez (@ninochavez).</description>
    <link>https://dev.to/ninochavez</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4061047%2Fb3940188-1195-40d9-9814-08f97eefbe9a.png</url>
      <title>DEV Community: Nino Chavez</title>
      <link>https://dev.to/ninochavez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ninochavez"/>
    <language>en</language>
    <item>
      <title>The Cut You'll Make Twice</title>
      <dc:creator>Nino Chavez</dc:creator>
      <pubDate>Fri, 07 Aug 2026 15:18:53 +0000</pubDate>
      <link>https://dev.to/ninochavez/the-cut-youll-make-twice-308b</link>
      <guid>https://dev.to/ninochavez/the-cut-youll-make-twice-308b</guid>
      <description>&lt;p&gt;There is a file in this blog's repo called &lt;code&gt;tags.ts&lt;/code&gt;. Eight lines in, it says this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IMPORTANT: Do not add new tags without updating this file.&lt;br&gt;
Build validation will reject posts with unapproved tags.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wrote that. It's addressed to an agent, and every agent that writes a post here reads it.&lt;/p&gt;

&lt;p&gt;The schema that would do the rejecting is one line in a different file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;optional&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any array of any strings. It appears eight times, once per content collection. There is no validation anywhere that compares a post's tags against the approved list.&lt;/p&gt;

&lt;p&gt;So I counted. Two hundred seventy-seven files carry tags. The approved list has eighteen entries. Forty-nine distinct tags are actually in use — thirty-two of them off-list, across sixty-four uses.&lt;/p&gt;

&lt;p&gt;The worst one is instructive. &lt;code&gt;ai-development&lt;/code&gt; declares a &lt;code&gt;replaces&lt;/code&gt; array, a list of the sloppy tags it exists to absorb. &lt;code&gt;'AI'&lt;/code&gt; is in that list by name. &lt;code&gt;AI&lt;/code&gt; appears as a live tag on four posts.&lt;/p&gt;

&lt;p&gt;The file names the exact mistake. The mistake is in the repo four times. The build has been green the entire time.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Rule in a File Is a Request
&lt;/h2&gt;

&lt;p&gt;That file is a warning label. It works by being read and agreed with.&lt;/p&gt;

&lt;p&gt;Most of what any of us gives a coding agent is a warning label. &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;.cursorrules&lt;/code&gt;, the system prompt, the paragraph you paste at the top of a session. All of it is text the model reads and mostly honors. Mostly is the operative word, and mostly is worse than it sounds. When a rule gets skipped and the work still looks fine, what tells you? The green build told me my tags were clean for two hundred seventy-seven files.&lt;/p&gt;

&lt;p&gt;There are two other things you can build instead, and I had them filed under one name.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Defined the Jig by Half
&lt;/h2&gt;

&lt;p&gt;In March I reached for carpentry and defined the one I keep coming back to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A master carpenter doesn't build every piece from scratch. They build &lt;em&gt;jigs&lt;/em&gt;—custom tools that hold material at the right angle, guide a cut along a precise line, make a repeatable operation fast and accurate. The jig isn't the product. It's the thing that accelerates the real work of making the product.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Read the clauses. &lt;em&gt;Accelerates. Fast and accurate. Repeatable.&lt;/em&gt; Every one is about speed.&lt;/p&gt;

&lt;p&gt;Everything after that sentence was about proliferation — agents make jigs cheap, cheap jigs breed, you end up curating a drawer of one-off fixtures instead of doing the work. I still think that's right. Eleven weeks later I described asking an agent to extract a whole methodology into a reusable template, and called that a jig too. Same definition. Same direction.&lt;/p&gt;

&lt;p&gt;A jig has two jobs. That definition covers one of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two Directions, and I Only Named One
&lt;/h2&gt;

&lt;p&gt;In March, every jig I named was something an agent built for me. A script to reformat data. A workflow to pre-screen inputs. A template to scaffold a document. Agent makes the fixture, human does the work.&lt;/p&gt;

&lt;p&gt;The other direction is the one I never defined. I build the fixture. The agent works inside it.&lt;/p&gt;

&lt;p&gt;Both kinds have been in my repos the whole time. Only one ever got a word. That's the tell — I had a name for the fixtures that save me time, and none for the fixtures that take away the agent's options.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Catalog That Makes a Cut Impossible
&lt;/h2&gt;

&lt;p&gt;Before writing this I went and counted the second kind rather than trusting my memory of it.&lt;/p&gt;

&lt;p&gt;It's a retail storefront where a model composes the page layout. A catalog file declares every named place that model may write. Twenty-eight zones across ten surfaces — home, product listing, product detail, cart, checkout, search, account, store locator, and two error states. Each entry carries two booleans: whether the composition engine may target it, and whether a merchant may author there by hand.&lt;/p&gt;

&lt;p&gt;Twenty-seven are open to the engine. Twenty-seven are open to the merchant. They are not the same twenty-seven.&lt;/p&gt;

&lt;p&gt;One zone under a product grid is open to the merchant and closed to the engine. One zone on the product page is open to the engine and closed to the merchant. Two booleans, two exceptions, and the reason each exception exists is that a person sat down and decided this one thing the model shouldn't touch, and this other thing the merchant shouldn't. The entire governance model for the surface is two flags in a config file that disagree exactly twice.&lt;/p&gt;

&lt;p&gt;The cart has three zones. One above the checkout button. One below the fold, capped at two items. One empty state.&lt;/p&gt;

&lt;p&gt;Line items, order totals, promo entry, the checkout button itself — none of them are zones. There is no address for them.&lt;/p&gt;

&lt;p&gt;That catalog accelerates nothing. Composing a page through it is slower than letting the model emit whatever markup it wants. What it does is remove a cut.&lt;/p&gt;

&lt;p&gt;No policy in that system says the model may not change the cart total. Nobody wrote that sentence, and nobody has to. The model receives a schema of the places it may put things, and no address in that schema reaches the total. It isn't forbidden. There's nowhere to put the instruction.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Hook Is Not a Jig
&lt;/h2&gt;

&lt;p&gt;Here is where my own filing was wrong, and it took someone else pointing at the paragraph to see it.&lt;/p&gt;

&lt;p&gt;I have two hooks on this laptop that I'd been calling jigs. One enforces a rule that parallel agent sessions work in separate git worktrees, because sessions sharing one checkout switch each other's branches underneath each other. It's a &lt;code&gt;PreToolUse&lt;/code&gt; hook matched against &lt;code&gt;Bash&lt;/code&gt;, &lt;code&gt;Write&lt;/code&gt;, &lt;code&gt;Edit&lt;/code&gt;, and &lt;code&gt;MultiEdit&lt;/code&gt;. It reads a lock directory, checks whether another live session holds the repo, and returns &lt;code&gt;permissionDecision: "deny"&lt;/code&gt; with a paste-ready command for making the worktree instead.&lt;/p&gt;

&lt;p&gt;The second guards reads. Images over 1400 pixels on the long edge get denied — it downscales a copy to 1000px, caches it, hands back the new path. Re-reading a file you already read inside a ten-minute window gets denied too, with a note to cite from context.&lt;/p&gt;

&lt;p&gt;Those aren't jigs. They're safety valves.&lt;/p&gt;

&lt;p&gt;A jig is shape. Nothing about the zone catalog detects a violation, because a violation has no representation — there is no cart-total address to attempt. A valve is the opposite: it senses a condition and interrupts. It needs the bad thing to be attemptable in order to catch it.&lt;/p&gt;

&lt;p&gt;The tell is a feature I'd written off as a footnote. Both hooks let the immediate retry through. In the read guard that's an explicit latch — deny once, set &lt;code&gt;pending_retry: True&lt;/code&gt;, and clear it on the next call so the same read succeeds. Its own docstring says "fail-open by design" and calls itself "friction for the reflexive re-read, not a wall." There's an off switch: &lt;code&gt;touch ~/.claude/cache/read-guard/.guard-off&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Every one of those is valve behavior. A fixture has no reset, no fail-open, and no off switch, because there is nothing to switch off. You cannot retry your way past a shape.&lt;/p&gt;

&lt;p&gt;So there are three things, not two, and the ladder is: a rule the agent can decline, a valve that stops it and can be reset, and a surface with nowhere to put the bad instruction.&lt;/p&gt;

&lt;p&gt;The valves are the cheap ones. Five hundred fifty lines of Python for the worktree hook, 293 for the read guard, a few lines of JSON in &lt;code&gt;settings.json&lt;/code&gt;. Anyone running a coding agent can add one this afternoon. Sort your own instructions file into the three columns sometime — mine has two valves, one jig at client scale, and everything else is labels.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Working Jig Erases Its Own Evidence
&lt;/h2&gt;

&lt;p&gt;Here's what took me longest to see, and it's the reason the third column is harder than it looks.&lt;/p&gt;

&lt;p&gt;A valve announces itself. Every time one of my hooks trips, a denial message goes to the agent in-band, with a reason. The trip &lt;em&gt;is&lt;/em&gt; the record. If I put the threshold in the wrong place — say 1400 pixels was too aggressive — I find out, because I watch the agent get stopped from doing something reasonable.&lt;/p&gt;

&lt;p&gt;A jig produces nothing. That's the point of it, and it's also the problem.&lt;/p&gt;

&lt;p&gt;Go back to the storefront resolver. It's 116 lines. When it's handed a zone ID that doesn't exist in the catalog, it throws:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`resolveZone: unknown zone instance "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zoneId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Loud, immediate, unmissable. Now here's the line that enforces the actual constraint, twelve lines further down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;engineRaw&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;engineComposable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the engine produced content for a zone it isn't allowed to write, that condition is false. Execution falls to the next block, then to the static fallback. The page renders. Nothing throws, nothing warns, and the merchant sees a completely normal page with default content in it.&lt;/p&gt;

&lt;p&gt;So the resolver is loud about the harmless failure and silent about the real one.&lt;/p&gt;

&lt;p&gt;I went looking for where the silent case gets recorded. There's a retrieval log next to it, and its entry type has fields for surface, seed entities, session, brand, and the products that got placed in each zone. Every field describes something that succeeded. There is no field for a discarded write, no source, no reason.&lt;/p&gt;

&lt;p&gt;Then I grepped for &lt;code&gt;engineComposable&lt;/code&gt; across the entire codebase. It appears in three places: the catalog that declares it, a test file, and line 71 of the resolver. The one line that enforces the constraint is the same line that swallows the evidence, and nothing else in the system ever reads the flag.&lt;/p&gt;

&lt;p&gt;That's the second grade of invisibility. The third is worse, and it's the one that should actually worry me: a zone I never declared at all. The engine can't attempt it, so there's no branch to instrument, no discard to log, no line to grep for. The model simply never composes the thing I forgot to make a place for.&lt;/p&gt;

&lt;p&gt;How would I ever see that page? Not from an error, not from the log, not from the diff. The output that should have existed and doesn't leaves no trace anywhere in the system that excluded it.&lt;/p&gt;

&lt;p&gt;That's the asymmetry that makes jigs genuinely hard rather than just underrated. A fence in the wrong place and a fence in the right place produce identical telemetry: clean.&lt;/p&gt;

&lt;p&gt;The fix isn't cleverer geometry. It's putting a valve next to the jig — one &lt;code&gt;else&lt;/code&gt; branch at line 71 that records the discard, so the thing the fixture ate leaves a mark on the way down. The catalog stays geometry. The valve makes it observable. That's four lines, and it isn't written.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build the Jig When You'll Make the Cut Twice
&lt;/h2&gt;

&lt;p&gt;The old post buried the rule in a warning box. You built a jig only when the task was worth the setup. Agents dropping the cost of building one to near zero is what killed that discipline.&lt;/p&gt;

&lt;p&gt;The rule survives intact. Nobody builds a jig for one cut. For one cut you clamp carefully, measure twice, go slow.&lt;/p&gt;

&lt;p&gt;The one I lean on hardest is ten shell commands that drive a real Chrome profile. Navigate, evaluate JavaScript in the page, screenshot, scrape to markdown, crawl, manage tabs. That's it. &lt;a href="https://github.com/nino-chavez/browse-tool" rel="noopener noreferrer"&gt;The whole thing is public.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I didn't build it for a project, and that's the part that matters. It's installed permanently, on &lt;code&gt;PATH&lt;/code&gt; in every shell. Because it's already there, I start every integration reaching for a real interface — a CLI, an API — and driving a human interface stays the fallback it should be. That ordering only works if the fallback exists before I need it. Built per project, it doesn't. It's a detour I don't have time for at the moment I hit a system with no API, so I either skip the work or design the whole thing around mimicry from the start.&lt;/p&gt;

&lt;p&gt;Which raises the obvious question: why not use the MCP servers that already do this?&lt;/p&gt;

&lt;p&gt;My own config says to prefer the shell commands because of the token footprint. It doesn't say by how much, and the README for my own tool claims thirteen to eighteen thousand tokens with no method attached. So I measured: started each server over stdio, completed the handshake, called &lt;code&gt;tools/list&lt;/code&gt;, and ran the result through a real tokenizer instead of dividing by four.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Server&lt;/th&gt;
&lt;th&gt;Tools&lt;/th&gt;
&lt;th&gt;Bytes of tool schema&lt;/th&gt;
&lt;th&gt;Tokens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;chrome-devtools-mcp&lt;/td&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;23,244&lt;/td&gt;
&lt;td&gt;4,968&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@playwright/mcp&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;18,502&lt;/td&gt;
&lt;td&gt;3,928&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;My own README is off by roughly three and a half times, in the direction that flatters my tool. It reads like a measurement and it was an assumption about characters per token — the real ratio here is 4.7, and somebody, probably me, used something near 1.3.&lt;/p&gt;

&lt;p&gt;So the honest number is smaller than I'd been telling people, and the size isn't the argument anyway. The argument is &lt;em&gt;when you pay&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Those bytes load at connection, in every session where the server is configured, whether or not the agent ever opens a page. The shell commands cost one sentence in my instructions file — a pointer to a README. Sessions that browse spend about 4,000 tokens reading it. Sessions that don't spend nothing.&lt;/p&gt;

&lt;p&gt;I have 3,711 session transcripts on this machine. Two hundred fifty of them made a real &lt;code&gt;browse-*&lt;/code&gt; call. Sixty-eight made a real call to one of those MCP servers. Whatever the right denominator is, the shape is the same: a browser is a thing I need occasionally and pay for constantly.&lt;/p&gt;

&lt;p&gt;There's a second cost that doesn't show up in bytes. The agent already knows how to write JavaScript and read a DOM. A command that hands it a page and gets out of the way lets it use what it arrived with. A bespoke tool schema wrapping the same operations makes it learn a private vocabulary first, and that vocabulary is a fixture somebody else built for a cut I may not be making.&lt;/p&gt;

&lt;p&gt;None of which means don't use them. If you'll genuinely make the cut once, buy the assembled thing. That isn't a compromise; that's the rule working.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Valve I Left on a Branch
&lt;/h2&gt;

&lt;p&gt;Here's the part that undercuts everything above.&lt;/p&gt;

&lt;p&gt;The operator card I load into every session cites one of my own scripts as a reference implementation — a mechanical check that verifies a short-form caption against the long-form post it was derived from, so a claim can't quietly change owners between the source and the summary. I wrote it because I'd watched exactly that failure happen and decided a rule wasn't enough.&lt;/p&gt;

&lt;p&gt;It lives on a branch called &lt;code&gt;caption-edits-0803&lt;/code&gt;. Five commits of gate work, none of them on &lt;code&gt;main&lt;/code&gt;. The &lt;code&gt;syndication/&lt;/code&gt; directory on &lt;code&gt;main&lt;/code&gt; has no gate script in it at all.&lt;/p&gt;

&lt;p&gt;So the file that tells agents "this rule is enforced mechanically, here's the implementation" points at a check that has never run against anything I've published.&lt;/p&gt;

&lt;p&gt;That's the same failure as &lt;code&gt;tags.ts&lt;/code&gt;, one level up. The first wrote a rule and never built the mechanism. This one built the mechanism and never installed it. Both read as enforcement from inside the instructions file, and both are labels.&lt;/p&gt;

&lt;p&gt;An uninstalled valve is indistinguishable from an installed one until the day it should have tripped. Which is the same silence as before, arriving by a different route.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nothing Here Demos
&lt;/h2&gt;

&lt;p&gt;I ran through a vendor capability questionnaire last week. It has a row for no-code agent builders, and two words after the row: &lt;em&gt;if available&lt;/em&gt;. The next row down asks how you use AI to speed up your own development — writing code, configuring, testing, deploying.&lt;/p&gt;

&lt;p&gt;Two rows, opposite bets. One expects a finished product a buyer can score. The other only makes sense if the surface underneath is clean enough that a general-purpose agent can work it without a human translating.&lt;/p&gt;

&lt;p&gt;The form isn't badly designed. A rubric compares things that come out the same in every hand, and turnkey is the only category that does. A valve at least demos — you can trip it on a stage and watch it stop something. But there's no cell for &lt;em&gt;we made a class of mistake structurally impossible in this surface&lt;/em&gt;, because that isn't a feature. It's an absence, and the better it works the less there is to see.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Still Don't Have
&lt;/h2&gt;

&lt;p&gt;I don't have an instrument for the third column. Nothing in that storefront can tell me what the engine tried to compose and wasn't allowed to, and nothing at all can tell me about the zone I never declared. That's the gap that matters, and it's four lines of &lt;code&gt;else&lt;/code&gt; branch away from being half-closed.&lt;/p&gt;

&lt;p&gt;I also don't have a validator on the tag list. Read the canonical keys, refine the Zod schema from &lt;code&gt;z.string()&lt;/code&gt; to an enum built from them, let the build fail. Small the entire time the file has been claiming it already exists.&lt;/p&gt;

&lt;p&gt;The drawer of snowflakes I warned about in March is still real. But that one's the cheerful failure — you trip over the clutter and clean it up. The other kind doesn't accumulate anywhere you can trip over it.&lt;/p&gt;

&lt;p&gt;The fallback rendered. The page looked right. Nothing asked what was missing.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Measure Your Own Token Waste in Four Exercises</title>
      <dc:creator>Nino Chavez</dc:creator>
      <pubDate>Tue, 04 Aug 2026 12:31:56 +0000</pubDate>
      <link>https://dev.to/ninochavez/measure-your-own-token-waste-in-four-exercises-al6</link>
      <guid>https://dev.to/ninochavez/measure-your-own-token-waste-in-four-exercises-al6</guid>
      <description>&lt;h1&gt;
  
  
  Your Intuition About Where Tokens Go Is Probably Wrong
&lt;/h1&gt;

&lt;p&gt;In &lt;a href="https://ninochavez.co/blog/nothing-broke-it-just-wasnt-there" rel="noopener noreferrer"&gt;Nothing Broke. It Just Wasn't There.&lt;/a&gt;, an audit of a personal AI coding setup found the token-waste problem already solved — not by reasoning about which habits felt expensive, but by measuring a real 60-day corpus and finding that three of four starting hypotheses were wrong.&lt;/p&gt;

&lt;p&gt;This workshop is the hands-on half of that measurement. If you've done the &lt;a href="https://ninochavez.co/blog/tutorials/audit-your-ai-coding-harness" rel="noopener noreferrer"&gt;companion &lt;code&gt;/doctor&lt;/code&gt; workshop&lt;/a&gt;, this covers the other clock: not the standing harness, but what accumulates inside every conversation you have with the model.&lt;/p&gt;

&lt;p&gt;One idea worth having straight before you start: the agent API is stateless. Every single tool call resends your entire conversation so far, from the top. Nothing is free just because you already said it once. A token that lands early in a long session gets paid for again on every turn that follows it — which is why session length, not any one expensive-feeling action, tends to be the real driver.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 1: Install the mechanical half
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;5 min&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Two of the four levers here don't need you to think about them at all once they're installed — a hook that blocks specific wastes automatically, and a statusline that shows you context usage without you having to ask. Get these in place first; they start paying off immediately, before you've measured anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  The structure
&lt;/h2&gt;

&lt;p&gt;Both live in the same public repo as &lt;code&gt;/doctor&lt;/code&gt;: &lt;a href="https://github.com/nino-chavez/agentic-ways-of-working" rel="noopener noreferrer"&gt;&lt;code&gt;github.com/nino-chavez/agentic-ways-of-working&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;hooks/read-guard.py&lt;/code&gt;&lt;/strong&gt; — a PreToolUse hook on file reads. It denies two specific patterns once, with a fix handed back in the same response: an oversized image read (over 1400px on the long edge gets a 1000px copy instead), and a re-read of a file that hasn't changed in the last 10 minutes (you get a reminder to cite what's already in context instead). The immediate retry always succeeds — this is friction for the reflexive case, not a wall.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;statusline.py&lt;/code&gt;&lt;/strong&gt; — shows &lt;code&gt;model | context tokens (color-coded at 50%/80%) | cwd&lt;/code&gt; in your terminal, so a session fattening past a sane point is something you see, not something you discover three tool calls later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your turn
&lt;/h2&gt;

&lt;p&gt;If you already cloned the repo for the &lt;code&gt;/doctor&lt;/code&gt; workshop, you have everything — just run the installer to wire the rest:&lt;/p&gt;

&lt;h3&gt;
  
  
  Full install
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Wires hooks, statusline, and commands in one pass — safe to re-run&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/agentic-ways-of-working   &lt;span class="c"&gt;# or wherever you cloned it&lt;/span&gt;
./install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Starting fresh instead:&lt;/p&gt;

&lt;h3&gt;
  
  
  Fresh clone + install
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;One command, everything wired&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/nino-chavez/agentic-ways-of-working.git ~/agentic-ways-of-working
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/agentic-ways-of-working
./install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The installer is idempotent — it backs up your &lt;code&gt;settings.json&lt;/code&gt; first, only adds hook registrations that aren't already present, and never overwrites a statusline you've already configured.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checkpoint
&lt;/h3&gt;

&lt;p&gt;Restart your Claude Code session. You should see the statusline appear at the bottom of your terminal showing your model, current context usage, and working directory. Re-read a file you haven't touched in the last few minutes, then immediately re-read the exact same file again without it changing — the second read should get bounced once with a reminder, and the retry right after should go through clean. That's the hook working as designed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 2: Measure, don't guess
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;5 min&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Intuitions about which tool call is expensive are routinely wrong — that's not a hedge, it's the actual finding from running this against a real 2,335-file, 529-session corpus. Three of four starting hypotheses were wrong there. Your setup is different from that one. The only way to know what's actually happening in yours is to run the measurement, not to reason from what feels heavy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The structure
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;tools/token-audit.py&lt;/code&gt; reads every session log under &lt;code&gt;~/.claude/projects/**/*.jsonl&lt;/code&gt;, streams through them (a multi-gigabyte corpus finishes in a minute or two), and reports where your tokens actually went — not where you'd guess.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;python3 tools/token-audit.py [--days 60] [--projects-dir ~/.claude/projects] [--top 20]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--days&lt;/code&gt; controls the lookback window (default 60 — use less if you're newer to the tool), &lt;code&gt;--projects-dir&lt;/code&gt; lets you point it somewhere else if your Claude Code data isn't in the default location, &lt;code&gt;--top&lt;/code&gt; controls how many top offenders it lists per category.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your turn
&lt;/h2&gt;

&lt;p&gt;Run it against your own history:&lt;/p&gt;

&lt;h3&gt;
  
  
  Run the audit
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;No dependencies beyond Python 3&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/agentic-ways-of-working
python3 tools/token-audit.py &lt;span class="nt"&gt;--days&lt;/span&gt; 60
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're new to Claude Code and don't have 60 days of history yet, shrink the window: &lt;code&gt;--days 14&lt;/code&gt; or whatever you actually have. A thin window still tells you something; it just won't be as stable a picture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checkpoint
&lt;/h3&gt;

&lt;p&gt;You should see a report with a handful of named metrics and numbers specific to your own sessions — not the reference numbers from the tool's own documentation. If the report comes back essentially empty, check that &lt;code&gt;--projects-dir&lt;/code&gt; is pointing at where your Claude Code session logs actually live (&lt;code&gt;~/.claude/projects&lt;/code&gt; by default).&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 3: Read the five numbers
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;6 min&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;The report isn't useful until you know what each number is telling you to do. Five metrics carry the whole story.&lt;/p&gt;

&lt;h2&gt;
  
  
  The structure
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Replay multiplier&lt;/strong&gt; — cache reads ÷ tokens written. This is the big one: because the API is stateless, a payload's true cost is its size times every API call that follows it in the session, which makes session cost roughly quadratic in turn count. On the reference corpus this measured 41×. If yours is high, the fix is almost never trimming what you send — it's shorter sessions and delegating exploration to subagents whose context dies with them instead of accumulating in yours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redundant re-read rate&lt;/strong&gt; — same file, same session, unchanged content, read more than once. A high rate is usually a symptom of long sessions: compaction drops tool results, the agent re-reads what it lost, context grows, compaction fires again. The &lt;code&gt;read-guard&lt;/code&gt; hook you installed in Exercise 1 is the backstop; shortening sessions is the actual fix.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Image reads&lt;/strong&gt; — billed by pixel dimensions, not file size. A full-resolution screenshot can cost several times what a cropped, resized copy of the same content costs. On the reference corpus, images were 78% of all read bytes, mostly from full-page captures re-read dozens of times in design-loop sessions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cache-write ratio&lt;/strong&gt; — cache writes ÷ fresh input. Writes cost roughly 1.25× the input price and happen on cache-TTL expiry (about 5 idle minutes) and on every subagent spawn. A high ratio usually means a fat session getting resumed after sitting idle — each casual resume rewrites the whole context at the premium rate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-model spread&lt;/strong&gt; — caches are per-model. Switching models mid-session starts a cold cache for whichever model you switched to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your turn
&lt;/h2&gt;

&lt;p&gt;Go back to your own report. Find your replay multiplier first — it's usually the biggest single number and the best place to start. Then check redundant-read rate and image reads; those two are the ones a hook can partially catch, so seeing them stay high after Exercise 1 tells you something specific (older history, before the hook was installed, versus a pattern still happening now).&lt;/p&gt;

&lt;h3&gt;
  
  
  Checkpoint
&lt;/h3&gt;

&lt;p&gt;Name your own replay multiplier and your own redundant-read rate, specifically — not the reference numbers from this page. If either number surprises you compared to what you expected before running the tool, that's the actual point of measuring instead of guessing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 4: Turn one number into one change
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;4 min&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;A measurement that doesn't change a single habit was a research exercise, not an audit. The point isn't the report — it's what you do differently in your next session.&lt;/p&gt;

&lt;h2&gt;
  
  
  The structure
&lt;/h2&gt;

&lt;p&gt;Match what you found to what actually fixes it:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;If your report shows&lt;/th&gt;
&lt;th&gt;The fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;High replay multiplier&lt;/td&gt;
&lt;td&gt;Shorter sessions — &lt;code&gt;/clear&lt;/code&gt; between unrelated tasks instead of one long thread. Delegate multi-file exploration to a subagent when only the conclusion matters to the main task.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High redundant-read rate&lt;/td&gt;
&lt;td&gt;Same root cause as above — session length. The hook from Exercise 1 is already backstopping this; shortening sessions addresses the cause instead of the symptom.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oversized image reads&lt;/td&gt;
&lt;td&gt;Already covered — the hook downsizes these automatically now. If your report reflects mostly older history, that's expected; check again in a few weeks.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High cache-write ratio&lt;/td&gt;
&lt;td&gt;Stop casually resuming sessions that have been idle a while. Finish sessions instead of leaving them open in the background.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One tool dominating the report&lt;/td&gt;
&lt;td&gt;Add a digest step at the source — pull the 20 fields you actually need out of a large raw artifact instead of re-reading the whole thing each time.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Your turn
&lt;/h2&gt;

&lt;p&gt;Pick the ONE row that matches your biggest number from Exercise 3. Not all five — one. Write down, in a sentence, the specific habit you're changing starting with your next session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checkpoint
&lt;/h3&gt;

&lt;p&gt;State your one change out loud or in writing: what you'll do differently, starting when. Run the audit again in a few weeks and check whether that specific number moved. If it didn't, the fix didn't match the actual cause — go back to Exercise 3 and re-read the number more carefully.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You Measured
&lt;/h2&gt;

&lt;p&gt;Four exercises, each covering a different half of the same mechanism:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Exercise&lt;/th&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;What it protects against&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Install the mechanical half&lt;/td&gt;
&lt;td&gt;Are the two automatic fixes actually running?&lt;/td&gt;
&lt;td&gt;Waste you'd otherwise never notice, turn after turn&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Measure, don't guess&lt;/td&gt;
&lt;td&gt;What does your own history actually show?&lt;/td&gt;
&lt;td&gt;Building a fix for a problem you don't have&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read the five numbers&lt;/td&gt;
&lt;td&gt;What does each metric mean for what you do next?&lt;/td&gt;
&lt;td&gt;A report nobody acts on because nobody understood it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Turn one number into one change&lt;/td&gt;
&lt;td&gt;Did anything actually change?&lt;/td&gt;
&lt;td&gt;Measurement as theater instead of practice&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Where This Is Heading
&lt;/h2&gt;

&lt;p&gt;The statusline is the only piece of this that's live — it tells you about the session you're in right now. Everything else here is a look backward: &lt;code&gt;token-audit.py&lt;/code&gt; tells you what already happened, not what's happening this minute.&lt;/p&gt;

&lt;p&gt;Run it again in a few weeks, the same way the &lt;code&gt;/doctor&lt;/code&gt; workshop suggests re-running that command. A single measurement is a snapshot. What actually changes your token bill is whether the habit from Exercise 4 is still true the second time you check.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Grade an Agent Tool Before You Install It</title>
      <dc:creator>Nino Chavez</dc:creator>
      <pubDate>Mon, 03 Aug 2026 17:25:25 +0000</pubDate>
      <link>https://dev.to/ninochavez/grade-an-agent-tool-before-you-install-it-164d</link>
      <guid>https://dev.to/ninochavez/grade-an-agent-tool-before-you-install-it-164d</guid>
      <description>&lt;h1&gt;
  
  
  A Feature List Is Half a Subtraction
&lt;/h1&gt;

&lt;p&gt;In &lt;a href="https://ninochavez.co/blog/one-component-i-didnt-already-have" rel="noopener noreferrer"&gt;One Component I Didn't Already Have&lt;/a&gt;, a plugin advertising eleven agents and fifty-four hooks came out, measured against an existing setup, at a delta of one component.&lt;/p&gt;

&lt;p&gt;Nothing in that result was about the plugin's quality. It was about the other half of the subtraction — and that half lives on your machine, not on the project's page.&lt;/p&gt;

&lt;p&gt;This workshop runs the four checks against whatever tool is currently in your inbox. None of them requires installing it.&lt;/p&gt;

&lt;p&gt;A few terms, defined once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Baseline&lt;/strong&gt; — everything already wrapped around your model: instructions, skills, commands, hooks, memory files, tool connections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delta&lt;/strong&gt; — what the tool would add &lt;em&gt;after&lt;/em&gt; subtracting your baseline. The only number that answers "should I install this."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Issue tracker&lt;/strong&gt; — the part of a project's repository the maintainer cannot curate without the gap being visible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reversibility&lt;/strong&gt; — whether the uninstall actually removes what the install added. Frequently assumed, rarely checked.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Exercise 1: Enumerate your baseline
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;10 min&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;You cannot measure an addition without knowing the starting number. This is the check people skip, and skipping it is what makes every feature list look impressive — a list of fifty-four things is fifty-four gains only against zero.&lt;/p&gt;

&lt;p&gt;It is also the check that pays off permanently. You do it once, and every future tool evaluation becomes a reading exercise.&lt;/p&gt;

&lt;h2&gt;
  
  
  The structure
&lt;/h2&gt;

&lt;p&gt;Whatever your agent loads at startup, get it into one readable list: instruction files, skills, commands, hooks, tool connections, and any helper binaries on your path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ~/.claude/skills/ ~/.claude/commands/ ~/.claude/hooks/ 2&amp;gt;/dev/null
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; ~/.local/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you followed &lt;a href="https://ninochavez.co/blog/tutorials/audit-your-ai-coding-harness" rel="noopener noreferrer"&gt;Audit Your AI Coding Harness&lt;/a&gt;, its report is your baseline and you can skip ahead.&lt;/p&gt;

&lt;p&gt;The durable version of this is a repository rather than a command. Mine is public, which is the only reason the evaluation in the companion post took twenty minutes instead of an afternoon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your turn
&lt;/h2&gt;

&lt;p&gt;Produce your list. Then answer one question about each entry: what does this do, in a sentence, without looking it up?&lt;/p&gt;

&lt;h3&gt;
  
  
  Checkpoint
&lt;/h3&gt;

&lt;p&gt;You should have a list where you can name the function of every item. Anything you can't explain is a finding on its own — it's loaded into every session and you don't know why.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 2: Subtract the baseline from the tool
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;12 min&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;The delta is the decision. Everything else in this workshop refines it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The structure
&lt;/h2&gt;

&lt;p&gt;Pull the tool's component list from its reference documentation rather than its README — the first enumerates, the second sells. Many projects publish something like &lt;code&gt;docs/reference/features.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/&amp;lt;owner&amp;gt;/&amp;lt;repo&amp;gt;/&amp;lt;branch&amp;gt;/docs/reference/features.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then walk it and mark each item one of three ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  The three buckets
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Every component lands in exactly one&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bucket&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;What it does to the decision&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Native&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Your setup or your agent already does this&lt;/td&gt;
&lt;td&gt;Removes it from the gain column entirely&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;New&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Genuinely absent from your baseline&lt;/td&gt;
&lt;td&gt;This is the delta. The only column that argues for installing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Blocked&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;New, but unusable for a reason unrelated to quality&lt;/td&gt;
&lt;td&gt;Wrong platform, broken upstream, needs a subscription you don't hold, requires patching something you don't control&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Blocked&lt;/strong&gt; is the bucket people collapse into the other two, and it distorts the answer in both directions. A component that is excellent and unusable is not a gain, and it is also not a criticism of the tool.&lt;/p&gt;

&lt;p&gt;Then run it backwards: what does your baseline do that the tool's list never mentions? That column is real and nobody publishes it for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your turn
&lt;/h2&gt;

&lt;p&gt;Produce the three-way split, then the reverse column. Count the &lt;strong&gt;New&lt;/strong&gt; bucket.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checkpoint
&lt;/h3&gt;

&lt;p&gt;You should be able to name your covering item for every &lt;strong&gt;Native&lt;/strong&gt; row. "I think I have something like that" doesn't count — if you can't name it, it belongs in &lt;strong&gt;New&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If &lt;strong&gt;New&lt;/strong&gt; is large, the tool is a genuine addition and the rest of this workshop is about risk. If &lt;strong&gt;New&lt;/strong&gt; is one or two items, ask whether those items are available on their own before you adopt everything attached to them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 3: Query the issue tracker
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;10 min&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;A project's documentation describes what it does when it works. Its issue tracker describes what it does on other people's machines. The second is written by users, and unlike testimonials it can't be curated without the absence being obvious.&lt;/p&gt;

&lt;p&gt;This is also the fastest read of a project's health that exists, and it's entirely mechanical.&lt;/p&gt;

&lt;h2&gt;
  
  
  The structure
&lt;/h2&gt;

&lt;p&gt;Three queries. Volume, recency, and your own failure modes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# how much is open, and how fast is it arriving&lt;/span&gt;
gh api &lt;span class="s2"&gt;"search/issues?q=repo:&amp;lt;owner&amp;gt;/&amp;lt;repo&amp;gt;+is:issue+is:open&amp;amp;per_page=1"&lt;/span&gt; &lt;span class="nt"&gt;--jq&lt;/span&gt; &lt;span class="s1"&gt;'.total_count'&lt;/span&gt;
gh api &lt;span class="s2"&gt;"search/issues?q=repo:&amp;lt;owner&amp;gt;/&amp;lt;repo&amp;gt;+is:issue+created:&amp;gt;=&amp;lt;30-days-ago&amp;gt;&amp;amp;per_page=1"&lt;/span&gt; &lt;span class="nt"&gt;--jq&lt;/span&gt; &lt;span class="s1"&gt;'.total_count'&lt;/span&gt;

&lt;span class="c"&gt;# what users argue about most&lt;/span&gt;
gh api &lt;span class="s2"&gt;"search/issues?q=repo:&amp;lt;owner&amp;gt;/&amp;lt;repo&amp;gt;+is:issue&amp;amp;sort=comments&amp;amp;order=desc&amp;amp;per_page=25"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--jq&lt;/span&gt; &lt;span class="s1"&gt;'.items[] | "\(.comments)c \(.state) #\(.number) \(.title)"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then search the tracker for the things that would specifically hurt &lt;em&gt;you&lt;/em&gt; — your platform, your host tool's version, your cost sensitivity, your workflow.&lt;/p&gt;

&lt;p&gt;Read for patterns rather than counts. A high open count on a popular project mostly means it's popular. What matters is shape:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does it break when its host releases a new version? Search the host's version numbers.&lt;/li&gt;
&lt;li&gt;Do its own updates break things? Search &lt;code&gt;auto-update&lt;/code&gt; and &lt;code&gt;after updating&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Are the most-discussed threads features or the same bug recurring?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Your turn
&lt;/h2&gt;

&lt;p&gt;Run the three queries, then two searches specific to your situation. Write down the pattern in one sentence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checkpoint
&lt;/h3&gt;

&lt;p&gt;You should have one sentence of the form: &lt;em&gt;"The recurring failure mode is _&lt;strong&gt;&lt;em&gt;, and it would/wouldn't hit me because _&lt;/em&gt;&lt;/strong&gt;."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If your searches return nothing, say that plainly rather than treating silence as a clean bill of health. A young project has a quiet tracker for reasons that have nothing to do with quality.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 4: Confirm the exit before the entrance
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;8 min&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;"It's cheap to try" is a claim about uninstalling, not installing. Every installer is one command. The exit is the part nobody tests, and it's the part that decides whether trying costs you an afternoon or a weekend.&lt;/p&gt;

&lt;h2&gt;
  
  
  The structure
&lt;/h2&gt;

&lt;p&gt;Read the install guide's own account of what lands on disk, and check each location against your machine &lt;em&gt;before&lt;/em&gt; running anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; ~/.local/bin                       &lt;span class="c"&gt;# names it might shadow&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-nE&lt;/span&gt; &lt;span class="s1"&gt;'^\['&lt;/span&gt; &amp;lt;the-config-file-it-edits&amp;gt;  &lt;span class="c"&gt;# sections it might rewrite&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prefixed names and new named sections are additive and reversible. Bare generic names and rewrites of sections you already use are not.&lt;/p&gt;

&lt;p&gt;Then do the thing almost nobody does: &lt;strong&gt;search the issue tracker for the uninstall itself.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh api &lt;span class="s2"&gt;"search/issues?q=repo:&amp;lt;owner&amp;gt;/&amp;lt;repo&amp;gt;+is:issue+uninstall+OR+cleanup+OR+remove"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--jq&lt;/span&gt; &lt;span class="s1"&gt;'.items[] | "\(.state) \(.created_at[0:10]) #\(.number) \(.title)"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open reports that removal leaves things behind are worth more than the entire installation guide. They tell you the true cost of being wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your turn
&lt;/h2&gt;

&lt;p&gt;Write a one-line verdict for each: name collisions, config writes, and whether uninstall is reported to work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checkpoint
&lt;/h3&gt;

&lt;p&gt;You should be able to say, without having installed anything: which files it creates, which existing file it modifies, whether any name shadows one of yours, and whether other people have successfully removed it.&lt;/p&gt;

&lt;p&gt;If the install guide won't tell you enough to answer those, that absence is your finding. Installers that won't say what they write are the ones most worth not running.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You Ran
&lt;/h2&gt;

&lt;p&gt;Four checks, none of which required installing the thing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A baseline you can read, which turns every future evaluation into a lookup&lt;/li&gt;
&lt;li&gt;A three-bucket subtraction — native, new, blocked — run in both directions&lt;/li&gt;
&lt;li&gt;Three mechanical queries against the writing the vendor doesn't control&lt;/li&gt;
&lt;li&gt;An exit check, before the entrance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output is a number: how many components this tool would actually add to &lt;em&gt;your&lt;/em&gt; setup. That number is the decision, and it is different for every person who asks you whether the tool is good.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where This Is Heading
&lt;/h2&gt;

&lt;p&gt;Exercise 1 is the one that hurts, and not because it's difficult.&lt;/p&gt;

&lt;p&gt;Most people cannot list what their agent loads at startup. The list has grown by accretion — a hook added during one bad afternoon, a rule added after one bad review, three skills installed and never invoked since. Every one of them still loads.&lt;/p&gt;

&lt;p&gt;Which means the honest version of "should I install this" usually surfaces a second question underneath it, and it's the less comfortable one: &lt;em&gt;what is already in here that I would not install today?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
