AI
-
When I Use a Subagent and When I Don't
Give a good harness access to subagents and everything starts looking like a team project.
You’ve got one agent working with the database layer. Another can research the API. Another can write the tests. Another can check the work. Another can manage moving the data. As work starts happening in parallel, colored dots appear, and the whole thing starts looking like an org chart.
That sounds like fun to me, but it can also be a mess.
Having more agents doesn’t automatically produce better results.
Sometimes they duplicate work. Sometimes they edit files at the same time, producing unexpected changes or behavior.
I mean, I still use subagents constantly. They are definitely the default.
Sometimes we need, like, a subagent arena. Two agents enter. One survives.
The Subagent Context Boundary
I started using subagents as a way to protect the main context window. I wrote about that back in March: the delegated agent can read files, inspect logs, and grind through intermediate reasoning in its own context.
It’s still one of the best reasons to delegate. When finding the right answer means searching through 20 files, reading five of them, tracing a configuration value, and checking the tests, that sounds like a subagent task to me.
The search is noisy, and the output needs to be compact.
Using subagents keeps the main context window free for the larger task.
I Delegate Bounded, Independent Work
The tasks I delegate have one thing in common: I can define the output before the work begins.
Here are some areas where a subagent makes sense:
- Repository research.
- A separate implementation surface.
- Specialist review.
- Independent verification.
- Real parallel work.
Don’t Delegate an Unclear Problem
Delegation is not a substitute for deciding what the work is.
If a request is vague, spawning more agents isn’t going to help with the vagueness. It’s just more output with no clear direction. The parent still needs to choose the requirement and figure out what we’re building.
Before I delegate, I want to handle the following in the parent context:
- what question the subagent is answering,
- which files or systems it owns,
- whether it may edit anything,
- what constraints it must preserve,
- what evidence it should return,
- when it should stop and ask instead of guessing.
If we can’t figure out answers to those, the next step should be planning, not delegation.
Don’t Split Tightly Coupled Work
Avoid having two agents edit code in neighboring areas. The code may share an interface, a fixture, or a schema, and if you start changing things in multiple places without coordination, you’re going to have problems.
Each agent has its own context window. When it reads a file, block of code, or dependency into that window, the context is only current at that moment. If another agent changes the same thing, how does the first agent know its context needs to be updated?
It’s a complicated problem, for sure.
So your best bet is to avoid parallel edits where agents are working in the same or similar areas of the code. The agent work areas need to be distinct.
If humans can have coordination problems, agents can too.
I Don’t Delegate Five Minutes of Work
Delegation has a cost. The parent needs to describe the task and load enough context for the subagent to do the work and summarize it. Then the parent needs to verify the result. All of that burns a bunch of tokens. Obviously, for one-line changes or small amounts of text, this handoff should never happen in the first place. To decide whether to pass the work to a subagent, ask: will using a subagent substantially improve the output?
Sometimes the answer is just to do it in the parent context window, even if that means you have to compact sooner.
A good subagent task looks a lot like a good software interface. It has a narrow purpose, explicit inputs, clear permissions, and predictable output.
Compare these two assignments:
Look into the tests and fix anything missing.Review the unchanged-record tests for Book. Identify provider-owned fields that are not covered. Add focused tests only in tests/test_books_client.py. Do not change production code. Run the focused test file and report the result.The first transfers uncertainty. The second transfers work.
The difference does matter.
The Parent Still Owns the Result
Subagents report completion. They don’t make completion true.
The parent still has to inspect the changes, reconcile conflicting findings, run the combined quality gate, and decide whether the original requirement was satisfied. If three agents each report that their piece passes, you have three pieces of evidence. You don’t yet know whether the assembled system works.
Delegation changes who gathers the evidence. It doesn’t remove the need to judge it.
The goal isn’t keeping every agent busy. The goal is finishing the work without turning yourself into middle management for robots.
Oh God, I think that’s my job title.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
-
Where Should This Agent Knowledge Live?
Every agent has a junk drawer.
It usually starts with project instructions. Then I added build commands, personal preferences, database warnings, old architecture decisions, and things to fix later.
The agent could see everything if I wanted it to, but then it would have to read a small novel before touching the code, recurring workflows were buried between random facts, and completed work kept hanging around like it was still relevant. I had given the agent more context and somehow made it less informed.
The problem was not missing knowledge. The problem was putting every kind of knowledge in the same place. An instruction, a skill, a memory, and an issue can all be written in Markdown.
They do four completely different jobs.
Four Places, Four Jobs
A clean version looks like this:
What the agent needs Where it belongs A rule that must apply during every relevant session Instructions A reusable procedure for a particular kind of work Skill A durable fact that may become relevant later Memory A commitment that remains open until completed Issue tracker In practice, this is messier than a table… That’s where the engineering and attention to detail really matter.
So the useful questions are Does the agent need to know about this? and What bucket does this knowledge belong in?
Instructions Are Guaranteed and Expensive
Project instruction files are the things your agent loads automatically. Depending on the tool, that might be
AGENTS.md,CLAUDE.md, or another repository-level file.This is your guaranteed layer. The agent (or harness) doesn’t have to remember to search for it. If a session starts in the project, the rules are sitting in context.
Use that guarantee for knowledge that must shape nearly every relevant action:
- the preferred package manager and command runner,
- where the main source and tests live,
- dangerous commands that require explicit approval,
- the authoritative source for important data,
- mandatory validation before work counts as complete,
- a pointer telling the agent when to load a skill or recall a memory.
The guarantees come with a cost. Every line added to the context is loaded on every session, even when all you really need is a lightweight session where that context doesn’t matter.
Be diligent about cleaning up and maintaining your guaranteed context window, especially if you don’t have a memory layer in place.
Skills Are Procedures With Judgment
A skill answers a different question: how should the agent perform this kind of work?
Publishing a blog post, reviewing a pull request, applying a database migration, preparing a release, updating dependencies. Those are workflows. They have an entry condition, a sequence, safety rules, and a way to verify the result. That’s more than a fact. It’s operational judgment packaged for reuse.
Before we had skills, we had playbooks. Now we can make playbooks out of anything.
A good skill tells the agent when the workflow applies, what to inspect before acting, which steps and tools are appropriate, what must never happen silently, and what evidence proves the work succeeded.
Maybe the deployment instructions can now stay short; when doing a deployment, load the deployment skill.
Instructions are guaranteed. Skills are conditional.
Memory Is Context, Not Policy
Memory is where durable facts live without being injected into every session.
I prefer pnpm for JavaScript and most TypeScript projects. I prefer uv, and sometimes Poetry, for Python. These are facts that shouldn’t have to be repeated.
What about that time you had to troubleshoot an integration and observed some strange behavior? What about when you changed the database design and it broke the support layer? None of this deserves to be injected into every prompt, but it deserves a place where the details can be accessed later.
A semantic memory system can store and retrieve the relevant durable facts and give them to the agent when it asks. I described this earlier.
Memory can be large, and it can be flexible. But it’s also not guaranteed. The agent might not use the right keyword. You might have a problem with the vendor. A critical dependency could go down and take the memory system offline.
Don’t put safety-critical policies in memory. It’s good to have backups. If preferences get lost, they can be recreated, but absolutes like never print secret values belong in several places. If it has anything to do with security, cover your ass.
Memory is best for facts, preferences, relationships, explanations, and past decisions.
Issues Are Promises, Not Storage
An issue tracker tells the agent what needs to be done.
Issues have always been little documentation vaults. We write the history of the bug as it travels through the system. We link back to the issue as it maintains relevance.
An issue should preserve the context for a decision. It should act as a durable property of the project, recording the circumstances around a decision point.
Don’t make it a container for everything the agent did along the way, but I think it’s totally fine if you use it to publish an implementation plan.
Just, you know, you gotta read it.
Our job now is reading about software. The issue trackers are our corpus.
Route the Knowledge With Four Questions
When I don’t know where something belongs, these four questions can help.
1. Must the agent know this before it acts?
Instruction
2. Is this about performing a recurring kind of work?
Skill
3. Is this a durable fact that may help later?
Memory
4. Is this unfinished work or a commitment?
Issue
Sometimes the answer can be more than one place. But don’t copy the content blindly between locations.
All the files may be Markdown, but maintaining the architecture now means knowing where to put the information.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
-
Not Every Agent Task Needs an Issue
I’ve written before that your AI agent needs a task manager, and I stand by it. Chat history is not project state. Context windows compact. Sessions end. If the work matters tomorrow, it needs to live somewhere tomorrow’s agent can find it.
The part I didn’t mention: not every task matters tomorrow.
Some work should disappear with the session. Turning all of it into durable project state doesn’t make your agent more organized. It gives the next session a bigger pile of bookkeeping to misunderstand.
Tasks Have Different Lifetimes
When we say “task,” we’re lumping together several different things.
“Add filtering to the search API” is a project commitment. It might take several sessions, affect other work, and need a record of why the behavior changed.
“Inspect the existing query code” is not a project commitment. It’s one step the agent needs to finish the larger task.
“Run the focused tests” is even shorter-lived. Once they pass and the result has informed the work, that checklist item has done its whole job.
These all deserve attention. They don’t all deserve permanent storage. I think about them in two buckets:
- Session tasks help the current agent organize execution. They live in a plan or checklist, then disappear when the work is complete.
- Durable issues preserve commitments, decisions, dependencies, and unfinished work across sessions.
The distinction isn’t importance. A database backup check can be a critical session task. The distinction is whether the information needs to outlive the work happening right now.
If it doesn’t, let it die.
Ephemeral Does Not Mean Sloppy
There’s a temptation to treat ephemeral tasks as unstructured work. Just tell the agent,
plz fixand see what happens.A session still benefits from a clear plan. The agent should inspect before editing, break a change into steps, mark progress, run focused tests, run the full quality gate, and verify the result. A visible checklist makes long work easier to supervise, and it reduces the chance the agent quietly skips the boring last step.
The checklist just doesn’t need to become part of the project’s permanent record. Picture something like this:
- inspect the repository method - find every caller - update the shared comparison helper - add focused tests - run the full suiteThose are excellent session tasks. They tell the agent how to move through one change. After the implementation lands, keeping all five around adds nothing. The commit and tests preserve the result. The issue, if one exists, preserves the reason.
An Issue Should Earn Its Permanence
A durable issue is more expensive than it looks. Someone has to write it clearly, connect dependencies, update its state, close it, and eventually decide whether it’s stale. An agent also has to read it. Every open issue becomes part of the project’s apparent reality.
That cost is worth paying when the issue preserves something important. I create one when at least one of these is true:
- The work will survive the current session. If we’re likely to stop before it’s done, the next session needs a reliable handoff.
- Other work depends on it. A dependency belongs in a system that can represent blocked and ready work, not in a paragraph buried in chat history.
- It represents a real commitment. A user-reported bug, an accepted feature, or a promised follow-up shouldn’t vanish because a terminal closed.
- The decision needs a record. If future maintainers will ask why the system behaves this way, the issue preserves context a diff can’t.
- The work crosses boundaries. Changes spanning repos, services, migrations, or people need coordination beyond one agent’s checklist.
- We found valid work but aren’t doing it now. That’s exactly what a backlog is for.
If none of those apply, a session task is probably enough.
Promote Work When It Changes Shape
You don’t have to pick the perfect tracking level before the agent starts.
Begin with a session plan. During inspection, the agent may discover that the “small fix” requires a migration, depends on another repository, or exposes a separate bug. If the work changes shape. Promote it.
Agents are very good at expanding scope. They inspect one path, notice three adjacent problems, and offer to fix everything while the files are open. Sometimes that’s useful…
Your Backlog Is an Agent Prompt
Humans are pretty good at looking at an old issue and thinking, “yeah, we don’t care about that anymore.”
Agents are more literal. If the tracker says the issue is open and ready, the agent has a strong reason to treat it as authorized work. A stale backlog can send a perfectly capable agent down an obsolete implementation plan just as it easily as it can with a valid one.
No issue hygiene needs to be a part of your process. An open issue tells the agent this work is still wanted, this description is still accurate, these constraints still apply, and finishing it would improve the project.
If any of that is false, the issue isn’t harmless clutter. It’s a bad prompt waiting to be executed.
Use the Smallest State That Survives Long Enough
After six months with git-native issue tracking, my workflow has gotten a lot more varied.
I use a session plan when the current agent only needs help organizing the work in front of it. I use an issue tracker when the project needs to remember something after that agent is gone. For local projects i’m very rarely reaching for Beads. For team work it’s always GitHub or GitLab.
Too little tracking and the project forgets real commitments. Too much and it accumulates stale instructions, duplicate tasks, and chores whose only purpose is maintaining the tracker.
Start small. Let the agent make a checklist. Promote the work when it makes sense. Close it when the feature is satisfied. Delete old tasks like you are pulling weeds to make space for the flowers to bloom.
Your agent needs a task manager. It does not need a permanent record of every box it checked along the way.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
-
Tests Are Evidence, Not a Definition of Done
I’ve watched thousands of tests run over the years.
When they pass it has felt good. A huge screen of green checks in the terminal is incredibly rewarding as a software developer.
But the work is never finished.
The tests are always valuable. They are evidence, but they were never the definition of done.
Tests Prove the Claims We Give Them
I’ve written before that testing is how we show our work, and I still believe it. If software is meant to run more than once, test it. No excuses, just testing.
The mistake is treating a passing suite as proof of more than it covers.
A test makes one specific claim about a system:
given this setup when this action happens then I expect this resultRun enough of those claims and you build confidence. You know the parser handles a missing field. You know the repository preserves an identifier. You know the command returns a failure code when authentication breaks.
What you do not know is whether you wrote the right claims.
If the requirement was misunderstood, the implementation and its tests can agree perfectly. If your fixture contains a field the real API never sends, every parser test can pass while production fails. If your mock accepts a request the provider rejects, you’ve proven compatibility with the mock.
That’s useful, but let’s not get carried away.
The Agent Can Test Its Own Misunderstanding
Coding agents make this distinction more important, because they generate code and tests together.
You ask for a feature. The agent interprets the request, implements that interpretation, then writes tests asserting the implementation behaves exactly as it wrote it. Everything passes.
Sometimes that’s a clean, efficient workflow. Sometimes it’s one misunderstanding with excellent test coverage.
Picture asking an agent to add a
published_atfield from an external service. It sees another timestamp calledcreated_at, assumes they mean roughly the same thing, and uses one as a fallback for the other. Then it writes tests proving the fallback works.The suite is green. The code is wrong.
The issue isn’t that an agent wrote the tests. Humans have spent decades writing tests around their own bad assumptions. The difference is speed. An agent can turn a vague requirement into a thoroughly tested wrong answer before you notice the semantic choice it made.
More tests don’t rescue a bad premise. They preserve it.
Mocks Prove You Understand the Mock
Mocks are one of the best tools we have for keeping tests fast and deterministic. I use them a lot. I don’t want every local run hitting a real provider, burning rate limits, changing remote data, or failing because somebody’s service is having a bad Tuesday.
Still, a mocked integration is a model of reality, not reality.
Your fixture may be stale. The provider may omit fields you marked required. Auth may use a header you never modeled. Pagination may stop differently than the docs imply. Error responses may arrive as HTML because a proxy had opinions.
Unit tests prove your code handles the world you described. A live, read-only check tells you whether the world still resembles that description.
That doesn’t mean turning the whole suite into live integration tests. It means picking a small amount of extra evidence proportional to the risk:
- Fetch one real response and inspect the fields you depend on.
- Exercise authentication without modifying remote state.
- Run a dry run through the production code path.
- Validate a migration against a realistic database copy.
- Confirm the deployed service reports the expected version.
Tests stay fast. Reality gets a vote.
Passing Is Not the Same as Shipped
There’s another gap between tested and done that has nothing to do with correctness.
Code can pass every check and still exist only in a working tree. A migration can be valid but unapplied. A config change can be committed but missing from the deployment environment. A feature can reach production without the logs you’d need to understand its first failure.
This sounds operational because it is. Software isn’t finished when the implementation works in the place where it was written. It’s finished when the intended system has the change, and you can tell whether that change is healthy.
For a small personal script, that might mean committing it and running it once with real input. For a web service, deployment, a health check, logs, metrics, and a rollback path. For a database change, verifying both the schema and the application behavior after migration.
The evidence changes with the risk. The principle doesn’t.
pytestcannot tell you whether you forgot to push the commit.
Done Is a Decision Built From Evidence
A definition of done should answer a broader question than “did the tests pass?” It should answer: what evidence would make us comfortable owning this change?
For most work, I look in a few categories:
- Intent: The behavior matches the actual requirement, not the first interpretation of it.
- Implementation: Automated tests cover the important paths and failure cases.
- Quality: Static analysis, formatting, types, and review caught what they’re designed to catch.
- Integration: Real boundaries behave the way our fixtures and mocks claim.
- Operations: The change is delivered, observable, and recoverable in proportion to its risk.
- Durability: Code, migration, docs, and task state are saved where the next person or agent can find them.
Not every change needs all of them. Fixing a typo doesn’t require a rollback drill. Changing how customer data is stored deserves more than one unit test and a thumbs-up from the agent that wrote it.
Good engineering is choosing the right amount of evidence, not applying the largest checklist to everything.
Green means the evidence looks good. Done means you have enough of it.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
DevOps AI Testing Software development Engineering practices
-
Every Feature Opens a Maintenance Account
Coding agents have developed a dangerous little habit. You ask for one change, and somewhere near the end they offer to add three more.
Would you like a configuration flag? A JSON output mode? A retry option? Maybe a dashboard while we’re here?
The agent can build it. The tests and relevant files are already in the context. So why not?
Just one more feature, one more prompt. You know what I’m talking about.
Then six months later the flag is still there. Somebody relies on the JSON shape. The retry behavior conflicts with a new timeout. The dashboard has a dependency that needs a security update. The agent that offered to build all of it has moved on with its life, mostly because it never had one.
You still own the feature.
That’s the part we need to consider. Every feature is another record in a maintenance ledger.
A Feature Is a Standing Promise
We tend to think of a feature as the code that implements it. Add the function, connect the interface, write the tests, merge the change. Feature complete.
That’s the construction phase. The feature itself is a promise that begins after the merge.
If you add a CLI flag, you’re promising that scripts can keep using it. If you expose a JSON response, you’re promising something about its shape. If you store a new piece of data, you’re promising to preserve, migrate, export, and eventually delete it correctly. If you connect another service, you’re promising to notice when its API changes.
The code might be thirty lines. The promise has no line count.
This is why tiny features get expensive. The implementation fits in one file, but the behavior crosses documentation, tests, support, deployment, security, and every future change near that boundary. Agents are very good at showing us the thirty lines. They’re much less likely to show us the next three years.
The Opening Balance Looks Great
Before coding agents, implementation cost acted as a filter. Not always a good one, but a filter.
Someone had to estimate the work, find time in a sprint, write the code, and get it reviewed. A small convenience feature might lose simply because nobody wanted to spend two days on it. Frustrating, sure, but it forced the question: is this worth building?
Now the estimate is twenty minutes. The agent has already inspected the codebase. It can update the model, add the command, generate the tests, and fix the type errors without needing another meeting. The old cost-benefit calculation collapses, because almost everything looks worth building when you only count the first implementation.
So we say yes more often.
That’s not automatically bad. Plenty of useful software never existed because construction cost too much. Cheaper implementation lets small teams solve problems that used to require a real budget. Good for us, but the maintenance math didn’t collapse along with it.
The feature still adds another path through the system. It still creates behavior that can regress. It still has users, even if the only user is you on a Sunday afternoon six months from now.
The opening balance is cheap. The account stays open.
What Accumulates
Maintenance is easy to wave away because no single piece sounds overwhelming. It’s just one more test. One more paragraph in the docs. One more migration. Then the interest starts adding up:
- Compatibility: Existing callers depend on behavior you considered an implementation detail.
- Testing: Every supported path needs coverage, fixtures, and updates when neighboring code changes.
- Documentation: The feature needs to be discoverable, accurate, and removed from the docs if it goes away.
- Dependencies: A tiny feature can introduce a library that now participates in every upgrade and security review.
- Operations: New jobs, tables, queues, or API calls need logs, failure handling, and a recovery story.
- Support: Someone has to answer why it behaved differently on another machine.
- Removal: Deleting it later means finding its users, migrating their data, and deciding how long compatibility lasts.
None of these costs are unique to generated code. We’ve always paid them. The difference is volume. Agents let us open maintenance accounts much faster than we close them.
A Ten-Minute Flag Is Still an Interface
Let me give you an example.
You have a command that prints a human-readable table. An agent offers to add
--json. That sounds great. It probably is great. The code serializes the existing records, the tests compare a sample payload, and the whole change lands before lunch.Then someone pipes that output into another script.
Now field names matter. Null behavior matters. Ordering might matter even though you never promised it. A renamed internal property breaks an external workflow. Adding a timestamp creates noisy diffs. Removing a field requires a compatibility decision.
The flag didn’t add another display format. It created an API.
Would you still build it? Probably. I like useful CLI tools, and machine-readable output is usually worth supporting. The point isn’t to reject the feature. The point is to recognize the account you’re opening. Once you see it as an interface instead of a ten-minute patch, you define the schema deliberately, document what’s stable, avoid exposing fields that should stay internal, and decide whether versioning matters before somebody’s automation answers that question for you.
Same code. Better ownership.
Backlogs Hide the Statements
One reason maintenance gets away from us is that backlogs are organized around changes, not promises.
The issue says “add export support.” It rarely says:
Maintain this export format for as long as anyone depends on it, update it whenever the underlying model changes, keep its documentation accurate, and provide a safe way to retire it later.
That would look ridiculous in an issue title. It’s still what the issue means.
Agents make backlogs disappear quickly, which feels fantastic. I’ve watched them knock out work that would have sat around for months. But a closed issue can become an open obligation. A project with fifty completed features isn’t necessarily healthier than one with twenty. It might just have thirty more things that can break.
Price the Account Before You Open It
I don’t want a meeting for every CLI flag. The whole advantage of these tools is that we can move fast.
We can still take thirty seconds to ask better questions before accepting the extra code:
- Who will depend on this? A person clicking a button creates a different promise than a script parsing output.
- What new state or interface does it introduce? Stored data and public schemas are much harder to remove than local calculations.
- What has to stay compatible? Name the stable boundary instead of letting users guess.
- How will we know it broke? Tests help, but logs, validation, and recovery may matter more.
- What ongoing work does it create? Dependencies, docs, migrations, provider changes.
- What would cause us to close the account? Decide now whether it’s experimental, permanent, or removable.
If the answers are cheap too, build it. If the feature creates a permanent public contract for a minor convenience, nope, not going in.
Cheap Construction Needs Better Restraint
I’m not interested in making software expensive again. Faster implementation is good. More people turning an idea into a working tool is good. Small teams getting leverage that used to belong to large companies is very good.
We just need to stop treating features as free.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
AI Programming Software-development Coding-agents Maintenance
-
Code Is Cheap Now. Decisions Aren't
I’ve spent a lot of time working on software backlogs with coding agents. Pick an issue, inspect the code, make the change, run the tests, close it, move to the next one.
The strange part is how often writing the code is no longer the hard part.
An agent can add a field to a model, update the database, wire it through a client, and write a pile of tests before I check on it again. That would have been hours or days of time before. Now it happens in one focused session.
Great.
But the feature still needs someone to decide what the field means. Is it nullable? Which system owns it? Can it be inferred from another value? What happens when the provider stops sending it? Does an older local value survive, or should it be cleared?
The typing got cheaper. The decisions did not.
The Keyboard Was Never the Whole Job
We’ve spent decades measuring software work by its visible output. Lines of code, commits, pull requests, story points, features shipped. Code was expensive to produce, so counting the artifacts at least felt related to the effort.
That relationship is falling apart.
You can ask an agent for three implementations of the same feature and get all three before lunch. You can generate a REST API, a migration, a test suite, and a deployment manifest in one sitting. If you don’t like the architecture, ask for another one.
Now you have four implementations and a new problem: which one should exist?
Software development was never just converting requirements into syntax. It was deciding which requirements were real, where the boundaries belonged, what failure looked like, and which tradeoffs you were willing to own. Code generation doesn’t remove that work. It removes the part that used to hide it.
One Small Change, Twelve Real Questions
Let me give you an example.
Say an external API adds an optional date. Adding it to your application sounds trivial. Nullable column, property on the model, parse the response, write a migration, done.
Except the provider already has another date with a similar name. One is when the item was published. The other is when the user interacted with it. They’re both dates. They are not interchangeable.
So now the real questions start:
- Do we store only the explicit value, or infer it when it’s missing?
- Is a missing field the same as a field containing
null? - If the remote value disappears, do we delete the local value?
- Does this field participate in unchanged-record detection?
- Will a dry run exercise the same comparison path as a real sync?
- Can older installations run safely before the migration is applied?
- What happens when a second provider represents the same idea differently?
None of those are unique to any language. The agent can explain the options and implement whichever answer you pick, but it can’t discover your intended data contract from the shape of a JSON response.
If you skip those decisions, you still get code. You just get code that quietly invents policy for you.
Cheap Code Creates Expensive Options
This is the part that you might underestimate.
When implementation was slow, the cost naturally limited how many ideas made it into a codebase. You might sketch three approaches, but you probably built one. The friction forced a little restraint.
Agents remove that friction. A feature that would have been rejected as “not worth a week” now looks attractive because the first version only takes an hour. A speculative abstraction feels harmless because the agent can generate it in minutes. A new internal tool seems reasonable because the prototype already works.
It worked. But “it works” and “it’s a good idea” are two very different things.
The generated code still has to be reviewed. Its dependencies still need updates. Its behavior still needs tests. Someone still has to understand it when the surrounding system changes. If it handles credentials or customer data, somebody owns that risk too.
The implementation cost may be close to zero. The ownership cost is not.
This is how you end up with a backlog full of individually reasonable features that collectively make the project worse. Each one was cheap enough to add. Nobody stopped to price the maintenance costs associated with each successive feature.
Decision Debt
We already have a name for shortcuts in implementation: technical debt. You move quickly today and accept that the code will cost more to change later.
Agentic development creates another kind. Call it decision debt.
Decision debt is what happens when code gets produced faster than anyone can answer why it exists, what promise it makes, and who is responsible for it. The implementation is complete, but the boundaries are fuzzy. The tests prove what the code currently does, but nobody has decided whether that’s what it should do.
You can see it in questions like these:
- Are we supporting this behavior or merely tolerating it?
- Is this data authoritative, derived, or cached?
- Is this workflow meant for one person or every user?
- Is this abstraction solving a repeated problem or predicting one?
- What would make us remove this feature?
An agent can help you reason through every one of those. That’s one of the best uses of the technology. Ask it to inspect the repository, find conflicting assumptions, model failure cases, and challenge the proposed design.
Just don’t confuse receiving an answer with making a decision.
The Human Work Moves Upstream
If agents keep getting better at implementation, the valuable human work moves toward choosing and framing the work.
That means writing a clear definition of done before generating code. Deciding which system is the source of truth. Recognizing when two similar concepts need separate names. Looking at a working implementation and saying, “No, this does not belong here.”
It also means treating restraint as engineering work.
Closing a stale issue without implementing it can be more valuable than shipping the feature. Reusing an existing boundary can beat introducing a cleaner new abstraction. Deleting a half-maintained tool can improve a system more than generating its replacement.
None of those choices produce an impressive diff. That’s fine. The diff was never the product.
What Good Looks Like Now
I don’t think the answer is to slow agents down, or to pretend generated code is somehow less legitimate than code typed by hand. The code doesn’t care who wrote it. If it’s correct, understandable, tested, and worth owning, ship it.
The change is in where we spend our attention.
Spend less time admiring how quickly the implementation appeared. Spend more time checking the assumptions it smuggled in. Ask what new state the system owns, what promise the interface makes, what can fail, and whether the feature deserves to survive its prototype.
Agents make it possible to build almost anything you can describe. Our job is deciding what should still exist six months later.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
AI Software-development Engineering Agentic-coding Technical-debt
-
Pi and Hermes Are Trying to Solve Different Problems
I went looking for a talk from Mario Zechner, the creator of Pi, because I wanted to understand why someone would build another coding agent when we already have a pile of them. I found: a talk called “Building pi in a World of Slop.”
Zechner described Pi as a minimal, extensible coding agent that should fit your workflows instead of forcing you into its workflow. He also made a point that should be printed on the box of every AI coding tool: code is not free. The model can produce it quickly, sure. You still own the review, the maintenance, the weird edge cases, and the next person trying to understand it six months later.
That framing explains Pi better than any feature list does.
I’ve also been reading about Hermes Agent, from Nous Research. Hermes is a useful comparison because it’s also an open, provider-flexible agent harness. But it isn’t trying to be Pi with a few extra switches turned on.
Pi and Hermes are trying to solve different problems.
Pi Gives You a Small Place to Start
Pi is a terminal coding harness with a deliberately small default: read files, write files, edit files, run shell commands. Underneath that CLI is a set of TypeScript packages for model access, the agent loop, sessions, and the terminal UI. You can use the CLI, run it through JSON/RPC, or embed the SDK in something else.
That last part is the point.
Pi deliberately leaves out things a lot of agent products treat as table stakes: MCP in the core, subagents, plan mode, permission popups, to-do lists, background shell work. This can look like a missing-feature list if you evaluate it like Claude Code or another finished product.
I don’t think that’s the right test.
Those omissions are Pi’s design. It’s saying: a harness should give you a stable loop, a tool boundary, sessions, and enough extension points to build the workflow you actually need. Then it should get out of the way.
Want MCP? Add it. Want a planning workflow? Make one. Want agents that coordinate over a message bus, work in separate git worktrees, or run in a weird internal deployment? You own the composition. Pi has extensions and packages for that, and now an explicitly experimental orchestration package, but none of it is presented as the one true way to work.
That’s a compelling idea if you’re building a specialized system. It’s also work. Both things can be true.
Hermes Starts With the System
Hermes starts from almost the opposite direction. It’s an integrated autonomous-agent platform with persistent memory, learned skills, built-in delegation, MCP support, scheduling, multiple execution environments, and surfaces that extend beyond the terminal into messaging and desktop interfaces.
Hermes is asking a larger question: what does an agent need to keep working over time, across channels, with memory of what it has already learned?
That’s not just a bigger Pi configuration.
When Hermes includes persistent memory and skill creation, it’s making those things part of the product contract. When it includes subagents and scheduling, it’s giving you an operating model for delegation and recurring work. You get more out of the box, and you inherit more of the system’s assumptions.
For a lot of people, that’s exactly right. If you want an agent to run continuously, show up in Slack or Telegram, remember prior work, and execute recurring workflows, building all of that from Pi primitives would be a very committed hobby.
Good for you, but I think most teams shouldn’t volunteer for that job unless the control model is part of what they’re building.
The Comparison That Matters
Here’s the version I keep coming back to:
Pi Hermes Default posture Minimal programmable harness Integrated autonomous-agent platform Core workflow You compose the pieces The product ships an opinionated system Multi-agent work Extensions, packages, or your own topology Built-in delegation and parallel work Memory Session primitives and JSONL history Persistent memory and skill-learning features Best fit A workflow or control plane you need to own A capable agent system you want to operate This isn’t a scorecard. Hermes isn’t “better” because it has more rows filled in, and Pi isn’t “purer” because it has fewer.
The question is where you want the complexity to live.
With Pi, much of it lives in the system you build around the harness. You have to decide how agents coordinate, what gets remembered, which tools are safe, and how approval works. In exchange, the result can fit your environment instead of being a very configurable version of someone else’s environment.
With Hermes, more of that complexity is already in the platform. You spend less time assembling basic capabilities, but you should understand its memory model, delegation model, security posture, and operational boundaries before you give it real work.
Neither choice removes responsibility. It just changes the shape of it.
Don’t Build a Harness Because It Sounds Fun
Agent harnesses are one of those things that sound like a great weekend project. You wire up a model, give it a few tools, add memory, spawn a couple subagents, and suddenly you have a tiny digital organization running in your terminal.
Then Monday happens.
The agent needs a permission model. It needs observability. It needs a way to recover from bad state. It needs sensible defaults for credentials and logs. It needs evaluation. It needs someone to own the changes when a provider API shifts or an extension becomes a security problem.
That’s why I like the Pi and Hermes comparison. It makes the tradeoff visible.
Use Hermes when you want an agent platform. It already has an opinion about the features an always-on, multi-surface agent needs.
Use Pi when the workflow itself is the product, or when the product assumptions are exactly what you need to escape. Pi’s small core is valuable because it leaves room for a different control plane.
And if all you need is a better code-review prompt or a way to query one internal system, build that inside the harness you already use. A skill, extension, or MCP server is usually a better answer than inventing an agent platform because you wanted one new capability.
This is the same point I landed on in a recent post: you think you want to build your own harness, but what you usually want is a wrapper around the one you already have.
Code is not free. Neither is a harness.
Sources & References
- “Building pi in a World of Slop” — Mario Zechner (talk) — Pi’s design philosophy, workflow fit, and the cost of generated code.
- Pi documentation — current product scope, installation, extensions, and operating modes.
- Pi usage documentation — default tool surface and deliberate core omissions.
- Pi monorepo — TypeScript package architecture and experimental orchestrator package.
- Hermes Agent documentation — persistent memory, skills, delegation, MCP, execution environments, and surfaces.
- Hermes Agent repository — open-source project and implementation reference.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
-
Don't Build a Full Agentic Harness. Wrap One Instead.
I keep seeing people talk about building an “Agentic OS”. A personal system where agents get tools, memory, sub-agents, long-running tasks, permissions, and maybe a little dashboard with colored dots so you know the robots are thinking.
I get it. It sounds fun. It is fun. I like building things too.
So first, a distinction, because the word gets thrown around loosely. Wrapping an existing harness is fine. A little script that shells out to Claude Code or Codex to do one job is a wrapper, and most people should build those. Plenty of people build one by accident and never call it a harness. I’ve got three small ones driving the pipeline that publishes this blog, each just handing a task to Claude Code and getting out of the way. That’s not the trap.
The trap is starting from a raw model API and trying to rebuild the whole thing, replicating Codex or Claude Code or OpenCode from scratch because you want a better way to work with agents. Do that and chances are you’re about to spend several weekends building a worse version of the tool you already have.
No-thX.
So the useful question isn’t “should I build a harness?” It’s how much of the harness do I need to own?
You’re Choosing an Ownership Level
A harness is all the stuff around the model: the agent loop, tool execution, sessions, permissions, memory, context management, orchestration. The model is the part you rent. The harness is the part you choose to own.
And that choice is a slider, not a binary.
What you do What you own What you inherit Extend a full harness Skills, sub-agents, MCP servers, conventions The loop, permissions, sessions, tool execution Run an open harness Deployment, provider, config Most core agent machinery Start from primitives The loop, workflow-specific behavior A small SDK and a few tools Build an agent app Everything that makes it a product Framework primitives, maybe Most people should start at the top and work down only when they hit a real reason to.
Start by Composing What Already Works
If you already use Claude Code, Codex, Gemini CLI, or another complete coding harness, you have more leverage than you think.
You can add specialized agents. You can write skills for recurring work. You can connect MCP servers for memory, documents, databases, browser tooling, whatever you need. You can set project conventions so the agent doesn’t rediscover the same rules every time.
That’s not “just configuration.” Configuration is how you shape a system without becoming responsible for every moving part inside it. The host already knows how to run the model loop, ask permission before risky actions, manage sessions and context, stream tool output, handle files and diffs, and coordinate sub-agents.
I’ve got a vault full of agent instructions, task-specific skills, persistent memory, and a few specialized agents. None of it required me to write a scheduler, a context-compaction system, or an approval UI from scratch. Good. I have other things to do.
The DIY Tax Is Real
A basic agent loop looks almost insultingly simple:
send prompt → receive tool call → run tool → send result → repeatYou can get that running in an afternoon.
What happens when a tool hangs? When the user cancels halfway through a long task? Where do sessions live, and how do you resume them? How do you show the user what changed? How do you stop an agent from reading the wrong file, deleting the wrong directory, or spending five dollars retrying the same broken command?
Then you need permissions. Sandboxing. Tool schemas. Retries. Logging. Secret handling. Context limits. Model fallbacks. Observability. A way to update all of it without turning your harness into the largest unmaintained project in your life.
It works. But “it works” and “it’s a good idea” are two very different things.
When You Should Go Lower
There are good reasons to own more of the stack. Maybe you need provider independence, routing cheap models to bulk work and expensive ones to the hard problems. Maybe you need an agent running persistently on your own infrastructure. Maybe the agent has to live inside another product, not a coding CLI. Maybe your workflow is weird: several specialized agents passing structured work between each other, a custom approval model, durable state that’s part of the thing you’re selling.
Those are all real reasons to move down the slider.
The trap is that people move down the slider because they’re curious, not because they hit a constraint. Curiosity is a great reason to build a prototype. It is not automatically a great reason to make yourself responsible for a runtime.
The Path That Doesn’t Make You Miserable
- Extend the harness you already use. Add a few good skills, focused sub-agents, the tools and memory you need. Do this first, because it shows you which parts of the workflow are painful before you replace anything.
- Add a model-agnostic harness for the jobs that hurt. When billing, deployment, or long-running automation become a real problem, reach for an open, self-hostable harness like Goose, OpenHands, Hermes Agent, or Pi. You still inherit the hard machinery but get control over providers and hosting. (This is also the layer where a model gateway like OpenRouter or LiteLLM slots in underneath, so you’re not locked to one vendor.)
- Drop to primitives for one narrow workflow. Skip the harness entirely and write the loop yourself on a thin SDK, the Vercel AI SDK or Anthropic’s Claude Agent SDK, when you need an embedded agent or a topology existing tools can’t represent cleanly. Build the smallest thing that proves the point. Don’t start by recreating a general-purpose coding agent.
- Reach for a framework when you’re shipping an agent product. If the harness itself is the product, then yes, you probably need graphs, durable state, domain models, and all the rest. This is where something like LangGraph or CrewAI earns its weight. That’s a different project from improving your own workflow.
One tool blurs steps 1 through 3 on purpose, and it’s worth calling out: Pi (pi.dev). It’s a coding-agent CLI you can use today and a TypeScript SDK you build your own harness on top of, provider-agnostic, with a “primitives, not features” core. If you already know you’ll want to customize, Pi lets you start by using it and grow into owning the loop, one extension at a time, without ever switching tools. Hermes Agent sits in similar territory for the self-hosted, model-agnostic case. Either one is a saner on-ramp than a from-scratch build on day one.
Own the Part That Makes You Different
The more of the harness you own, the more control you have. You also own more bugs, more security decisions, more context problems, and more ways for an agent to fail that are hard to explain.
So my strategy is boring in the good way. Start with a full harness. Compose it around your work. Add a lower-level tool only when you can name the limitation it solves. Build the loop yourself only when owning the loop is the point.
You don’t need an Agentic OS to get serious value out of agents. You need a workflow that helps you finish work without becoming one more system you have to maintain.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
-
Your Coding Agent Should Not Own Your Editor
Every coding agent wants to become the place where you work. It starts life as a command-line tool. Then it grows a chat interface, a diff viewer, a permission system, a terminal, a model picker, and eventually an editor integration. Meanwhile, every editor has to build a separate adapter for every agent its users might want. Ten editors, ten agents, and suddenly you’re staring at a hundred bespoke pairings nobody wants to maintain.
We’ve seen before, it’s called a shared boundary.
That’s what the Agent Client Protocol (ACP) is. An agent implements ACP once. An editor implements ACP once. Now you can run the agent inside the editor without either product having to swallow the other whole. It sounds like plumbing because it is plumbing. Plumbing is also the thing that makes ecosystems possible.
ACP in One Sentence
ACP is an open protocol for communication between an AI coding agent and the application presenting that agent to you.
Let’s be specific:
- The client is usually the editor or IDE. It owns the interface, your local environment, and the interaction with you.
- The agent is the coding-agent process. It owns the model loop, the conversation state, and the tool-use logic.
That word agent carries a lot of baggage, so it’s worth nailing down. In everyday AI talk it can mean the raw model, a harness like Claude Code or Opencode that wraps a model, or a subagent that a larger agent spawns to handle a subtask. ACP means the narrow one: the coding-agent process, the harness itself. You’re almost never talking to the model directly in this picture. You talk to the harness, and it drives the model on the other side. An ACP agent also isn’t a subagent. Subagents are an internal detail of whatever the harness does behind its own loop, invisible to the protocol. ACP draws its boundary one level up, between the editor and the whole coding-agent process, not between an agent and its helpers.
In the common local setup, the editor launches the agent as a subprocess and they trade newline-delimited JSON-RPC messages over stdin and stdout.
flowchart LR U[Developer] <--> C[ACP client<br/>Editor or IDE] C <-->|JSON-RPC over stdio| A[ACP agent<br/>Coding-agent process] A <--> M[Model provider] A <--> T[MCP servers and tools] C <--> W[Workspace, buffers, terminals]The whole design is in that picture: the editor and the agent stay separate programs. The agent doesn’t rebuild a serious code-review UI. The editor doesn’t reimplement the reasoning loop. Each side keeps the part it already understands.
The LSP Analogy Only Gets You Halfway
The usual pitch borrows from the Language Server Protocol, and the economics do rhyme. Before LSP, editors built language support one language at a time. After, one language server worked across many editors. ACP applies the same trick to agents: agents stop maintaining an integration per editor, editors stop maintaining one per agent, and you can swap agents without changing where you review code.
But don’t take the analogy too literally. A language server answers bounded questions. Where is this symbol defined? What completions apply here? A coding agent is a long-running, stateful thing. It streams text, announces plans, calls tools, asks permission, edits files, starts processes, and sometimes needs to be interrupted mid-turn. So ACP has to standardize more than request-and-answer. It standardizes enough of the experience of supervising an agent for the client to render it well.
What Happens in a Session
A connection opens with
initialize, where both sides negotiate a version and advertise capabilities. This is deliberately not all-or-nothing. Both programs are expected to cope with optional features being absent.Then the client opens a conversation with
session/newand gets a session ID back. One connection can carry several independent sessions. The client sends your message withsession/prompt, and while the agent works it streamssession/updatenotifications: assistant chunks, thoughts and progress, a plan and edits to that plan, tool calls and their status, mode changes. If a tool call needs a sign-off, the agent sendssession/request_permissionand the editor shows you the choice. Cancel a turn and the client firessession/cancel.That bidirectional flow is the whole difference between ACP and a thin chat API. The agent isn’t just handing back text. It’s exposing a structured account of what it’s doing so the editor can turn that into something you can watch and steer.
The Editor Stops Being a Chat Window
An agent in a plain terminal sees the files on disk. An editor knows more than disk. It has unsaved buffers, syntax highlighting, diagnostics, symbol navigation, a diff UI, and a model of what you’re reviewing right now. ACP’s filesystem methods let the agent ask the client to read or write text including editor state that hasn’t hit disk yet. Its terminal methods let the agent request a command, get a handle, read bounded output, wait for exit, or kill it, while the editor keeps ownership of the process and shows output in its own native terminal.
That split is a lot healthier than every agent inventing its own janky approximation of an IDE. The agent brings intent and execution. The editor brings visibility and control.
ACP and MCP Are Not the Same Thing
People mix these up because both use JSON-RPC and both show up in agent tooling. They sit on different boundaries.
- MCP answers: what can the agent use? Databases, issue trackers, browsers, internal APIs.
- ACP answers: where and how do you work with the agent?
They’re complementary. During
session/new, the ACP client can hand MCP server config to the agent, which then connects to those servers itself. Tools arrive through MCP. Agent work arrives through ACP. Clean.The Interface Is Becoming Its Own Layer
Strip away the JSON-RPC and the method names and the idea is simple: the coding agent and the interface you use to supervise it are different products. Improve the editor without waiting on every agent vendor. Stay in the environment where your code, terminal, and review workflow already live.
We should want coding agents to get better. We should also want the things we use to control them to get better. Those two will move faster if they’re allowed to move apart. That’s the actual promise of ACP. Not one universal agent, but a boundary that stops any single agent from owning the entire way we work.
Sources & References
- Agent Client Protocol introduction and architecture — overview, subprocess model, sessions, permissions, and the relationship to LSP and MCP.
- ACP v1 overview, session setup, and prompt turn — methods, streaming updates, cancellation, and MCP handoff.
- ACP filesystem and terminal methods — unsaved editor state, tracked writes, and process control.
- The ACP Registry is Live — distribution for compatible agents and clients.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
-
Graphify Turns Your Repos Into a Map You Can Query
Navigating code dependencies inside a single repository is already hard enough. But if you’re on a microservice setup, or a split frontend and backend, tracking what depends on what across multiple repos is a special kind of misery. A backend API route changes. Which frontend components just broke? Good luck. You’re grepping three workspaces and hoping you didn’t miss one.
So when I ran across Graphify, an open-source project from Graphify Labs (YC S26), it caught my attention. It maps your code directories into queryable knowledge graphs. Not fuzzy text search. Not an expensive vector RAG lookup that burns tokens every time you ask it a question. A deterministic index of your codebase.
Let me walk through how it works, why it’s useful for AI coding agents, and the part I wanted to figure out: how to stitch multiple repos into one unified map.
What Graphify Does
Instead of guessing at relationships, Graphify parses your source and builds a real graph out of it. Three pieces make it tick:
- Deterministic AST parsing. It uses
tree-sittergrammars locally to parse roughly 40 languages, pulling out classes, functions, calls, and imports. No LLM tokens, no API rate limits. Just parsing. - Explicit vs. inferred edges. Every relationship gets a confidence tag.
EXTRACTEDmeans it’s right there in the syntax, like an import or a direct function call.INFERREDmeans it deduced the connection from context. You always know how much to trust an edge. - Leiden community clustering. It automatically segments your code into logical domain boundaries, which makes it easy to spot the “god nodes”, the files with way too many dependencies hanging off them. Those are usually the first thing you want to refactor.
Merging Multiple Repos Into One Graph
This is the part I cared about. Graphify supports it natively through the CLI, and here’s the flow straight from the docs (I haven’t run it on my own repos yet). Say you’ve got a frontend repo and a backend repo. Three steps.
Step 1: Scan each repo on its own. Run the scan inside each folder. Results land in a
graphify-out/directory.# In your frontend repo cd ~/Work/frontend graphify . # In your backend repo cd ~/Work/backend graphify .Step 2: Merge the graphs. The
merge-graphssubcommand joins the JSON outputs into one combined map of nodes and relationships.graphify merge-graphs \ ~/Work/frontend/graphify-out/graph.json \ ~/Work/backend/graphify-out/graph.json \ --out ~/Work/combined_graph.jsonStep 3: Traverse it, or hand it to your agent. Now you can trace a call path straight across the service boundary, or serve the combined graph to a coding agent over MCP.
# Trace a path across the frontend/backend boundary graphify path "login_component.ts" "auth_controller.py" --graph ~/Work/combined_graph.json # Or expose the combined graph to your coding agent over MCP python -m graphify.serve --graph ~/Work/combined_graph.jsonThat
pathcommand is the whole pitch, honestly. You point it at a frontend file and a backend file and it tells you how they’re connected. No manual grep archaeology.Why This Matters for AI Coding Agents
If you use Claude Code, Cursor, or Antigravity, you already know the problem. Feed the agent raw files and you torch the context window in about four prompts. Point it at Graphify’s output instead, the
GRAPH_REPORT.mdor thegraph.jsonover MCP, and the agent can do a few things it otherwise can’t:- Figure out exactly which files a refactor will touch before it edits anything.
- Trace dependency lineage across code boundaries deterministically, not by vibes.
- Describe your architecture based on the actual shape of the code, not a hallucinated version of it.
That last one is underrated. Half of “the AI got confused” moments happen because the AI never saw the whole picture.
Two Gotchas Before You Install
A couple of things will trip you up, so here they are up front.
The package name has a typo built in.
graphifywas already taken on PyPI, so the official package is registered asgraphifyy. Two y’s. You install it like this:pip install graphifyyWatch your Python version. The Leiden community detection library has C-extension limits, so Graphify currently runs best on Python under 3.13. Worth checking or switching to a compatible version (like 3.12) using mise.
The honest appeal here isn’t the visualization, pretty as the HTML map is. It’s that cross-repo dependency tracing has been a manual, error-prone chore for as long as I’ve worked on split codebases, and this makes it a single command.
Sources
- Graphify Labs on GitHub: setup requirements, supported parsers, and CLI options.
- Auriga IT’s Graphify introduction: explains the three-pass architecture and Leiden clustering optimization.
- Graphify on PyPI: package installation details and version compatibility.
- Aider’s Repository Map: on using tree-sitter to parse AST-based codebase maps for token-efficient coding context.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
- Deterministic AST parsing. It uses