<?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: koenvg</title>
    <description>The latest articles on DEV Community by koenvg (@koenvg).</description>
    <link>https://dev.to/koenvg</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%2F500880%2Fc63109e9-c77f-4e1e-89b0-5a8486fd7578.jpeg</url>
      <title>DEV Community: koenvg</title>
      <link>https://dev.to/koenvg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/koenvg"/>
    <language>en</language>
    <item>
      <title>When worktrees share RAM</title>
      <dc:creator>koenvg</dc:creator>
      <pubDate>Sat, 29 Aug 2026 10:11:18 +0000</pubDate>
      <link>https://dev.to/koenvg/when-worktrees-share-ram-gba</link>
      <guid>https://dev.to/koenvg/when-worktrees-share-ram-gba</guid>
      <description>&lt;p&gt;The symptom is familiar if you have hit it. I have two coding agents running, each in its own Git worktree, each pointed at a different branch. One triggers a type-check. A few minutes later the second does the same. The laptop starts sounding like it is warming up for takeoff, terminal output stalls, and the whole desktop gets sluggish. The agents are not stuck. They are both running. So is the swap partition.&lt;/p&gt;

&lt;p&gt;The setup felt well-organized. Separate worktrees, separate branches, parallel work. What it did not account for is that worktrees do not know anything about memory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdme5z5v7njehafhyfq0b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdme5z5v7njehafhyfq0b.png" alt="Four friendly robot dogs lunging toward the same bone, representing multiple coding agents competing for the same machine's RAM." width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What worktrees actually isolate
&lt;/h2&gt;

&lt;p&gt;A Git worktree gives each agent its own working directory and its own checked-out branch. One &lt;code&gt;.git&lt;/code&gt; object store, multiple working trees. From a version control perspective this is clean: the agents cannot corrupt each other's file state or accidentally work on the same branch.&lt;/p&gt;

&lt;p&gt;The operating system sees something different. It sees processes. Each agent spawns whatever it needs: a TypeScript compiler, a test runner, a linter. Those processes compete for the same physical RAM. The kernel does not know or care that they came from different worktrees.&lt;/p&gt;

&lt;p&gt;TypeScript checkers are not light. &lt;code&gt;tsc&lt;/code&gt; on a mid-sized monorepo can hold several gigabytes of heap while it loads the full type graph. Vitest with a large test suite can do the same. ESLint with TypeScript-aware rules loads the full type checker internally. Node.js does not aggressively cap its own heap. V8's default heap limit on a machine with plenty of RAM sits around four gigabytes. When two agents each trigger one of these processes at once, the memory math can stop working before either finishes.&lt;/p&gt;

&lt;p&gt;The OS handles the overflow by paging to disk. Swap is slower than RAM by several orders of magnitude, and it degrades the whole machine at once. (An unplanned test of your swap throughput is one way to spend an afternoon.) Every interactive application on the desktop stutters. The agents slow down because the OS is paging their data in and out. Neither finishes faster. They finish slower, and they take everything else with them.&lt;/p&gt;

&lt;p&gt;The isolation worktrees provide is real and useful. It just does not extend to this part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remote machines
&lt;/h2&gt;

&lt;p&gt;The most complete answer to this problem is to run agents somewhere else. A remote VM, a cloud dev environment, a dedicated build server: the agent runs there, its processes consume that machine's RAM, and the local machine stays responsive.&lt;/p&gt;

&lt;p&gt;This works well for some people. If you have a cloud account with powerful VMs and a workflow that tolerates network-attached development, remote agents are genuinely good infrastructure. The swap problem becomes some other machine's problem.&lt;/p&gt;

&lt;p&gt;But remote compute carries real costs. There is the monthly cost of the machines themselves. There is the setup time: provisioning, SSH keys, environment parity, secret management, and all the configuration that makes a remote machine feel like the local one. Many teams keep code off external infrastructure by policy. Solo developers and small teams may not want to manage a remote agent fleet on top of everything else.&lt;/p&gt;

&lt;p&gt;There is also data locality. Some projects have licensing constraints, client data, or proprietary tooling that cannot leave the local network. "Run it in the cloud" requires more sign-off than is always available, or carries legal risk that is not worth taking for a quality-of-life improvement.&lt;/p&gt;

&lt;p&gt;Remote machines also drift. They need updates, monitoring, and when something breaks, it is harder to debug than a process running locally. For developers who already work primarily offline or who value low-latency tool feedback, the operational overhead of remote agents can exceed the original problem in friction.&lt;/p&gt;

&lt;p&gt;None of this is an argument against remote compute. It is a recognition that local development has real advantages and that not every team has the budget, the infrastructure access, or the appetite for the trade. The local problem is worth solving on its own terms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serializing the expensive parts
&lt;/h2&gt;

&lt;p&gt;If the problem is concurrent heavy processes sharing memory, one solution is to not run them concurrently. Not all processes. Most agent work is lightweight in parallel: editing files, reading context, writing tests, making API calls. The expensive operations are the validation steps: the full type-check, the test suite, the lint run.&lt;/p&gt;

&lt;p&gt;Serializing just those operations is a tractable trade. If one agent is running &lt;code&gt;tsc&lt;/code&gt; and another wants to start its own &lt;code&gt;tsc&lt;/code&gt;, the second one waits. Each type-check still takes the same amount of time, but they do not overlap. The machine stays responsive. Agents keep working on everything else while they wait.&lt;/p&gt;

&lt;p&gt;The mechanism is a machine-wide lock: a single token that any process can try to acquire before running an expensive command. The lock lives outside any individual worktree, in a shared location like &lt;code&gt;/tmp&lt;/code&gt; or a stable path in &lt;code&gt;$HOME&lt;/code&gt;, so any agent on the machine can reach it. The process that holds the lock runs its command. Everyone else waits.&lt;/p&gt;

&lt;p&gt;This is not a new idea. CI pipelines have used file-based mutual exclusion for a long time. What is slightly different here is applying it across independent AI coding agents that were not designed to coordinate with each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the lock does not do
&lt;/h2&gt;

&lt;p&gt;A lock prevents processes from overlapping. It does nothing else.&lt;/p&gt;

&lt;p&gt;A single process holding the lock can still consume all available RAM if its heap grows unchecked. Adding &lt;code&gt;--max-old-space-size&lt;/code&gt; to the Node.js invocation caps V8's old-space heap, but it does not cap total process RSS or native allocations, and it does not prevent the OS from swapping. When V8 exceeds the heap limit, it raises an out-of-memory error; whether that terminates the process cleanly depends on whether anything catches it. It can still be a useful signal: it removes one obvious source of unbounded heap growth and tends to make overreaching processes fail sooner. Use it as a complement to the lock, not a guarantee.&lt;/p&gt;

&lt;p&gt;The lock also does not coordinate agents automatically. Each agent has to invoke the wrapper script rather than calling &lt;code&gt;tsc&lt;/code&gt; or &lt;code&gt;vitest&lt;/code&gt; directly. Agents that bypass npm scripts and invoke binaries through other paths will not acquire the lock. The approach requires each worktree's scripts to be updated to use the wrapper.&lt;/p&gt;

&lt;p&gt;And it provides no memory isolation beyond serialization. It is not cgroups, not a container, not a memory budget. It is a queue for one category of operation. That is a much smaller guarantee than full resource isolation, but for a local multi-agent setup it is usually the right-sized one.&lt;/p&gt;

&lt;h2&gt;
  
  
  agent-flock
&lt;/h2&gt;

&lt;p&gt;I built &lt;a href="https://github.com/koenvg/agent-flock" rel="noopener noreferrer"&gt;&lt;code&gt;agent-flock&lt;/code&gt;&lt;/a&gt; to handle this. The first version is out and I am testing it in my personal repos.&lt;/p&gt;

&lt;p&gt;It is a small native CLI that uses an OS-managed file lock. Give a command a lock name, and any other command using the same name will wait its turn. The OS releases the lock when the process exits, so there is no daemon to run and no stale-lock timer to worry about. Drop it into any worktree's npm scripts and it coordinates without any agent framework integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real trade
&lt;/h2&gt;

&lt;p&gt;Serializing type-checks does mean total wall-clock time goes up when agents would otherwise overlap. Two concurrent type-checks that each take a few minutes will now run back to back instead of simultaneously.&lt;/p&gt;

&lt;p&gt;The machine stays responsive the whole time. The agents keep working on unblocked tasks. And the type-checks actually finish, rather than thrashing swap while the fans run and the whole desktop crawls.&lt;/p&gt;

&lt;p&gt;That is the bet: that real swap degradation is worse than sequential execution. For most local multi-agent setups, it is.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
      <category>typescript</category>
    </item>
    <item>
      <title>MCP Isn't Dead. It Just Has a Different Job.</title>
      <dc:creator>koenvg</dc:creator>
      <pubDate>Sun, 23 Aug 2026 06:21:41 +0000</pubDate>
      <link>https://dev.to/koenvg/mcp-isnt-dead-it-just-has-a-different-job-38cb</link>
      <guid>https://dev.to/koenvg/mcp-isnt-dead-it-just-has-a-different-job-38cb</guid>
      <description>&lt;p&gt;The argument that MCP is past its prime keeps surfacing in developer circles. It goes something like this: MCP adds context bloat, loads verbose tool definitions into every request, introduces latency, and gets in the way when you want a coding agent to move fast and precisely. For that specific use case, it is a reasonable critique.&lt;/p&gt;

&lt;p&gt;But it is also a narrow one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm7vg2pzwez20fy4yrmlw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm7vg2pzwez20fy4yrmlw.png" alt="Calendar, email, map, and notification tools feeding through a central MCP connector into a chat interface." width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the criticism lands
&lt;/h2&gt;

&lt;p&gt;The concerns about MCP in coding agent contexts are real and worth taking seriously.&lt;/p&gt;

&lt;p&gt;A long coding session already puts pressure on the context window. A complex refactor can fill thousands of tokens before a single tool call happens. Adding dense tool schemas to every interaction compounds the problem. When a developer needs precise control over what an agent sees and does, and when latency between actions adds up over a multi-step task, MCP's abstraction layer can start to feel like friction rather than infrastructure.&lt;/p&gt;

&lt;p&gt;Latency matters too. A developer waiting on a chain of tool calls in the middle of active debugging has different patience than someone asking for a restaurant recommendation on their phone. When the interaction is long and the context is already expensive, every added step costs something real.&lt;/p&gt;

&lt;p&gt;So the developers who raise these concerns are not wrong. MCP has tradeoffs. In contexts where context economy is paramount and where tools need to be hand-selected and narrow, those tradeoffs can tip against it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem MCP was actually built for
&lt;/h2&gt;

&lt;p&gt;But MCP was not designed only for coding agents. It was designed to answer an older and harder question: how does any application expose its capabilities to conversational interfaces without requiring a custom integration to be built and maintained for every possible host?&lt;/p&gt;

&lt;p&gt;Before protocols like MCP, the answer was: one integration at a time. An AI platform wants to let users check their calendar? The AI company builds a calendar connector. Another platform wants the same thing? They build another one. The calendar provider now maintains integrations with a dozen different hosts, each with its own format, auth flow, and update cadence.&lt;/p&gt;

&lt;p&gt;This is not a theoretical inefficiency. It is the current state of most software integrations, and it is expensive. Each integration is a contract between two parties that neither wants to break but both eventually change.&lt;/p&gt;

&lt;p&gt;MCP proposes something different: build to one interface, expose your capabilities once, work anywhere that speaks the protocol. For application developers, that is a meaningful deal. For AI platforms, it is the difference between curating a fixed list of hardcoded integrations and supporting an open, extensible ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The context overhead argument does not generalize
&lt;/h2&gt;

&lt;p&gt;The most common technical criticism of MCP is that the tool schema adds too much to the context. This is worth examining carefully, because the conclusion depends almost entirely on what was already in the context when the tool definition arrived.&lt;/p&gt;

&lt;p&gt;In a long coding session, context fills up fast. An involved refactor can accumulate a great deal before a single tool call is made. Tool schemas that arrive with every interaction, whether relevant or not, compound that pressure. In that environment, persistent overhead has a real cost.&lt;/p&gt;

&lt;p&gt;Ordinary end-user requests are a different situation. A short, focused query does not approach the same context constraints as an extended coding session. The overhead that puts genuine pressure on a long agentic task may be a more acceptable tradeoff when a user is asking a single question that touches a small number of services.&lt;/p&gt;

&lt;p&gt;This is not a defense of verbosity. Protocols should be as lean as they can be while still being useful. But a user may reasonably trade some overhead for the ability to take useful actions across connected apps in a single conversation. The cost-benefit calculation changes depending on the nature of the request. Treating the coding-agent scenario as the universal baseline inflates the cost and understates the benefit for everyone else.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this actually enables for end users
&lt;/h2&gt;

&lt;p&gt;The value of MCP for end users is not a technical property. It is a product property.&lt;/p&gt;

&lt;p&gt;Consider what it looks like when conversational access to software actually works. A user asks their assistant to reschedule a meeting before the end of the day, check whether a flight is delayed, summarize what happened in a Slack thread while they were traveling, and draft a short reply to a client. Each of those actions involves a different service. Each service stores its data differently and exposes its functionality differently.&lt;/p&gt;

&lt;p&gt;Without a standardized way for the assistant to discover and call those capabilities, the assistant either requires each application to have built a bespoke integration specifically for that platform, or it cannot help at all. The user is back to opening four different apps.&lt;/p&gt;

&lt;p&gt;With a protocol like MCP, each connected service describes what it can do in a common format. The assistant discovers the available tools, calls the right one, uses the result, and moves on. The user asked a question and got the outcome they wanted. They did not need to know which service was involved or how the connection worked.&lt;/p&gt;

&lt;p&gt;That gap between what users want to say and what software can hear is the core problem. MCP is a practical attempt to close it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What open and standardized actually buys
&lt;/h2&gt;

&lt;p&gt;There is a version of this future that works without MCP or anything like it. AI companies could build every integration in-house, negotiate every API deal, and maintain every connector themselves. Some of them are doing exactly that for their highest-priority integrations.&lt;/p&gt;

&lt;p&gt;But that version scales poorly and concentrates capability in platforms that can afford the negotiation work. A small productivity app does not have the leverage to get its integration included in the next major AI platform release. A niche professional tool does not make the priority list. Users of those products get a lesser conversational experience or none at all.&lt;/p&gt;

&lt;p&gt;The open-protocol version looks different. If any application can expose its capabilities through a standard interface, and if AI hosts adopt that standard, then the ecosystem grows from both ends simultaneously. The small app ships an MCP server. The AI assistant picks it up. The user gets access without anyone having to broker a deal.&lt;/p&gt;

&lt;p&gt;Whether that plays out depends on adoption, on the quality of the spec, and on whether the major platforms treat it as a genuine open standard or as a compatibility gesture. Those are fair things to watch. The structural argument for open protocols in integration-heavy ecosystems is not new, though. It has worked before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Richer than chat, not a replacement for everything
&lt;/h2&gt;

&lt;p&gt;Plain chat is useful. But "tell me about this" and "do this for me" are different interactions, and most software is built around things worth doing.&lt;/p&gt;

&lt;p&gt;The category of interaction MCP enables for ordinary users is not magic. It is closer to what a capable assistant provides: look something up, book something, check something, return the result, without requiring the user to navigate a different interface for each step. One conversation. Multiple services. A coherent outcome.&lt;/p&gt;

&lt;p&gt;That is richer than a search box and less demanding than learning a new interface for every task. It is also not a replacement for dashboards, forms, visual editors, or any structured interface that does things a conversational layer cannot. MCP does not obsolete those. It adds a layer that did not reliably exist before: structured, discoverable, standardized access to application capabilities through natural language.&lt;/p&gt;

&lt;p&gt;This pattern is probably part of how people interact with software in the future. Not all of it. Not a replacement for every other interface. But a real and useful mode that extends the reach of conversational AI beyond what plain text responses can do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shortcomings worth naming
&lt;/h2&gt;

&lt;p&gt;None of this means MCP is without real problems.&lt;/p&gt;

&lt;p&gt;Tooling is still maturing. Authentication and permission flows for MCP-connected systems are not as standardized as the protocol itself, which means the experience of connecting services can vary significantly from one implementation to the next. Security considerations around what tools can do and what data they can access require careful handling and are not solved by the spec alone.&lt;/p&gt;

&lt;p&gt;Discovery is also an open problem. The value of an open protocol depends on being able to find and trust the implementations that exist. Without good directories, quality signals, or review mechanisms, the theoretical benefit of an open ecosystem can fail to materialize in practice.&lt;/p&gt;

&lt;p&gt;These are genuine limitations. They are the work still to be done, not arguments against the pattern itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the argument actually gets right
&lt;/h2&gt;

&lt;p&gt;The "MCP is dead" argument is right about one thing: for coding agents doing long, context-heavy, tool-intensive work, MCP's tradeoffs can tip against it. That is a real constraint and developers are reasonable to work around it when they need to.&lt;/p&gt;

&lt;p&gt;It is not right that this conclusion generalizes. The end-user case is different in scale, in context cost, in the nature of what is being asked, and in the structural problem it is trying to solve. Writing off the whole protocol based on one edge of its application misses the more interesting argument.&lt;/p&gt;

&lt;p&gt;Something like MCP is probably part of the future of software interaction. Not because it is technically elegant in every scenario, but because the problem it addresses is real: software is useful, people want access to it through the interfaces they already use, and building every connection from scratch is a poor way to get there.&lt;/p&gt;

&lt;p&gt;That is a calm bet, not a grand claim. The protocol has real work left to do. So does everyone building on it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Grilling Before You Build</title>
      <dc:creator>koenvg</dc:creator>
      <pubDate>Mon, 17 Aug 2026 11:35:55 +0000</pubDate>
      <link>https://dev.to/koenvg/grilling-before-you-build-399d</link>
      <guid>https://dev.to/koenvg/grilling-before-you-build-399d</guid>
      <description>&lt;p&gt;Most planning problems are not about not having enough information. They are about not asking the right questions before starting. You think you understand the feature, you open an editor, and two days later you hit an assumption that was wrong from the start.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grill-me&lt;/code&gt; is a skill that tries to prevent this. It interviews you about your plan, one question at a time, and walks down the decision tree until the design is actually resolved rather than vaguely understood. I have been using it for a while now as part of a longer planning sequence, and the combination with &lt;code&gt;to-spec&lt;/code&gt; and &lt;code&gt;to-tickets&lt;/code&gt; has changed how I start any work that is more than a small change.&lt;/p&gt;

&lt;p&gt;This is not a tutorial. It is an account of what works, what does not, and how I shaped these tools to fit the way I actually work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu6a0e8kwjy2341l6as3t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu6a0e8kwjy2341l6as3t.png" alt="A planning conversation in grill-me flowing into a reviewed spec document, with dependent tickets ordered and linked in OpenForge." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the grilling session does
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;grilling&lt;/code&gt; skill is a structured interview. It asks about your plan one branch at a time, waits for your answer, and proposes a recommendation for each question so you are reacting rather than generating from scratch. That last part matters: being asked "should this be stored on the user or the account?" and having a suggested answer in front of you is much faster than being asked the same question with a blank page.&lt;/p&gt;

&lt;p&gt;The value is strongest in business logic. If a feature has multiple parts with non-obvious connections, the session forces you to articulate those connections out loud. You end up with a clear picture of the decision tree, resolved, before anything gets built. Dependencies that would have surprised you mid-implementation become visible early.&lt;/p&gt;

&lt;p&gt;I also use &lt;code&gt;grill-with-docs&lt;/code&gt; when working in a codebase with an existing domain model. That variant checks your language against the project's glossary and updates documentation as decisions are made. When a term gets resolved during the interview, it gets added to &lt;code&gt;CONTEXT.md&lt;/code&gt; in the same session. This keeps the model and the documentation consistent rather than diverging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it falls short
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;grill-with-docs&lt;/code&gt; handles business logic well. UI and interactions are a different story.&lt;/p&gt;

&lt;p&gt;The session works through decisions that have a defensible answer: data dependencies, sequencing, ownership rules, edge cases. What it does not ask about is the other layer: whether a confirmation belongs in a modal or inline, whether the interaction flow makes sense in practice, whether the overall experience feels right once someone is using it. Those decisions simply do not come up.&lt;/p&gt;

&lt;p&gt;The gap shows up after you build. The implementation can be correct by everything the session decided and still feel wrong when you use it. A dialog is missing where the user expects one. The flow works but feels off. Nothing in the grilling session would have flagged this, because the session never went there.&lt;/p&gt;

&lt;p&gt;Visual and interaction decisions need building, looking at, and adjusting. There is no version of reasoning your way to the right interaction pattern.&lt;/p&gt;

&lt;p&gt;This is not a criticism of the skill. The problem is expecting it to cover ground it was never designed for. The tool works well where it works. The mistake is assuming the grilling session has resolved the full picture when it has only resolved the logic.&lt;/p&gt;

&lt;p&gt;Knowing where the tool is useful is part of using it well.&lt;/p&gt;

&lt;h2&gt;
  
  
  The sequence
&lt;/h2&gt;

&lt;p&gt;After the grilling session, I run &lt;code&gt;to-spec&lt;/code&gt; in the same session, without starting a new conversation. The skill reads what was discussed, explores the codebase, and writes a Markdown spec file. No further interview. It synthesises, writes, and stops.&lt;/p&gt;

&lt;p&gt;The spec covers the problem statement, user stories, implementation decisions, testing decisions, and anything flagged as out of scope or unresolved. Having all of that in one reviewable document is considerably easier than scrolling back through a long grilling session looking for what was actually decided.&lt;/p&gt;

&lt;p&gt;The stop is the important part.&lt;/p&gt;

&lt;p&gt;When you are inside a grilling session, it is easy to feel like everything has been resolved. The conversation has momentum. Reading the resulting spec is a different experience. The document makes vague resolutions visible: things that were gestured at rather than actually decided tend to show up as incomplete or contradictory sentences in the spec. Reviewing it takes fifteen minutes, and those fifteen minutes regularly catch something worth fixing.&lt;/p&gt;

&lt;p&gt;Only after reviewing the spec do I run &lt;code&gt;to-tickets&lt;/code&gt;. That skill takes the approved spec and breaks it into work items, each with its blocking edges declared: which other tickets must finish before this one can start.&lt;/p&gt;

&lt;p&gt;The review boundary is not ceremony. It is the point at which you decide whether the plan is good enough to decompose. Fixing a sentence in a Markdown file is fast. Fixing a wrong assumption that has been spread across eight tickets and assigned to an agent is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Linked dependencies in OpenForge
&lt;/h2&gt;

&lt;p&gt;When &lt;code&gt;to-tickets&lt;/code&gt; publishes tickets to OpenForge, the blocking edges become real links rather than notes in a description. Each ticket lists what it depends on, and OpenForge creates structural blocking relationships between them.&lt;/p&gt;

&lt;p&gt;This matters in practice. When an agent picks up work from the queue, only tickets with no unresolved blockers are available. The execution sequence that was reasoned through during grilling is preserved in the tracker. Nothing gets picked up out of order because the order is enforced, not just suggested.&lt;/p&gt;

&lt;p&gt;If ticket three depends on a schema migration in ticket one, that is a link, not a comment. The agent working on ticket three will not start until ticket one is done. The dependency is captured in the place where it can actually do something.&lt;/p&gt;

&lt;p&gt;Dependencies are one of the harder things to communicate across a planning session. Writing them down in a spec is useful but passive. Having them as structural links in the tracker is something an agent can act on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customising the skills
&lt;/h2&gt;

&lt;p&gt;The skills I use are not exactly the originals. There are three changes I made.&lt;/p&gt;

&lt;p&gt;The first is making them work with OpenForge. &lt;code&gt;to-tickets&lt;/code&gt; in its general form handles multiple trackers and output formats. That flexibility adds branching logic that is noise in my setup. I trimmed the skill to target OpenForge specifically and removed the parts that do not apply.&lt;/p&gt;

&lt;p&gt;The second is adjusting the output templates. The ticket format that made sense for the original skill is not the same as what OpenForge expects, and the spec template needed adjustments to fit the projects I work on. These were small changes: a few structural edits to the format blocks in the skill files.&lt;/p&gt;

&lt;p&gt;The third is making the two-skill sequence explicit. &lt;code&gt;grill-me&lt;/code&gt; and &lt;code&gt;to-spec&lt;/code&gt; run in the same session. The &lt;code&gt;to-spec&lt;/code&gt; skill now knows it is synthesising an existing conversation rather than starting fresh. It does not re-interview.&lt;/p&gt;

&lt;p&gt;None of this required understanding how the skills work at a deep level. They are text files with instructions. You read them, find what does not fit, and change it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to modify skills without breaking them
&lt;/h2&gt;

&lt;p&gt;One change at a time. Use the modified version for a day. Then decide whether the output is better or worse.&lt;/p&gt;

&lt;p&gt;This sounds too simple, but the alternative is making five changes at once and not knowing which one produced the new behaviour. Skill files are short and easy to read, which makes it tempting to see ten improvements when you open one and make them all at the same moment.&lt;/p&gt;

&lt;p&gt;The one-change rule gives you a clean comparison. You ran the previous version yesterday. You run this version today. The difference is one variable. If the output improved, keep the change. If it got worse, revert it and try something different.&lt;/p&gt;

&lt;p&gt;Skills change how a model approaches a task. Some changes that look like improvements produce subtly worse output in ways that only show up after a few uses. The only way to catch that is to actually use the thing before moving on to the next change.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual value
&lt;/h2&gt;

&lt;p&gt;Two things make this sequence worth using.&lt;/p&gt;

&lt;p&gt;The first is dependency capture. The grilling session surfaces how parts of the plan connect and what blocks what. Those dependencies end up in the spec and then as structural links in the tickets. The execution order is not an afterthought added during planning: it is the thing planning produces.&lt;/p&gt;

&lt;p&gt;The second is shared understanding. Before any code is written, there is a document that describes what is being built and why. The decisions from the grilling session are recorded rather than existing only in a session that will be lost. If you are picking the work up after a break, or someone else is picking it up at all, the spec is there.&lt;/p&gt;

&lt;p&gt;Neither of these is guaranteed. A careless grilling session produces a weak spec and weak tickets. But the structure makes it easier to produce something useful, which is the most a planning tool can offer. The rest is still your job.&lt;/p&gt;

&lt;p&gt;If you have not tried this sequence before, start with one real feature. Run &lt;code&gt;grill-me&lt;/code&gt;, read the resulting spec, and see whether the dependency graph it surfaces matches what you had in your head. The gap, if there is one, is the thing the session was for.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
      <category>devtools</category>
    </item>
  </channel>
</rss>
