back

My AI Coding Harness Setup

How I structure AI-assisted development with specialized agents, specifications, worktrees, documentation, and deliberate context management.

Oct 11, 2026
workflow
aicoding-agentsdeveloper-workflowclaude-codeopenspeccontext-management

AI coding agents are getting pretty good at writing code.

We all know that generating code isn’t really the difficult part anymore.

The difficult part is organizing the work around them.

How do you run several agents without creating chaos? How do you keep architectural decisions somewhere outside of a chat history? How do you prevent an agent from jumping straight into implementation before the problem is properly understood? And how do you keep context from slowly filling with logs, command output, and irrelevant details?

Over time, I’ve ended up with a development setup that tries to solve these problems.

It’s still evolving, and I change parts of it regularly, but this is roughly how I work today.

The basic setup

My everyday environment is relatively simple:

  • Ghostty as the terminal
  • Herdr for managing terminal workspaces and multiple agent sessions
  • Zed as my main editor
  • Claude Code as the primary coding agent

I still spend a lot of time in the editor.

AI writes more code now, but I don’t want the editor to disappear from the workflow. I use Zed mostly for reading code, reviewing changes, understanding how things fit together, and making manual edits when that’s faster than explaining the change to an agent.

Herdr is particularly useful once several things are happening at the same time.

I can have an agent implementing one feature, another session investigating something, a dev server running somewhere else, and logs in another pane. It also tracks basic agent states like working, blocked, done, and idle, which makes it easier to see what actually needs my attention.

Both Zed and Herdr also work nicely with git worktrees.

That became important once I started running multiple development tasks in parallel. Instead of constantly switching branches in one working directory, each feature or agent can work in its own worktree.

Claude Code is not the whole workflow

I don’t run Claude Code completely on its own.

On top of it I use oh-my-claudecode-slim as an orchestration layer.

The main thing I like about this approach is specialization.

Instead of one giant agent context trying to plan, implement, debug, and review everything, work can be routed through different roles: planner, executor, reviewer, debugger, and so on.

It also provides reusable skills for common operations such as planning, reviewing, and verification.

There are some lightweight memory helpers as well, including a notepad and project memory. I prefer this to continuously pushing more information into the main conversation.

I specifically use the “slim” version because I don’t want a huge collection of instructions loaded into every request.

Most capabilities are loaded when they’re actually needed.

This becomes surprisingly important once you start caring about context usage.

Specs before code

For feature development I use OpenSpec.

The basic flow looks like this:

  1. Propose the change.
  2. Create the design, specification, and task list.
  3. Review the spec.
  4. Implement against the tasks.
  5. Review the implementation against the spec.
  6. Archive the change.

OpenSpec stores active changes under:

openspec/changes/<change-name>/

After a change is completed, its delta specification is merged into openspec/specs/, which becomes the current version of the system specification.

I like this separation because git history and specification history answer slightly different questions.

Git tells me what changed.

The specification should tell me why the system works this way.

That difference becomes more valuable when AI agents are doing a significant part of the implementation.

Without a specification, it’s very easy to end up with code that technically works but implements an assumption nobody actually agreed on.

I don’t use the same process everywhere

One mistake I’ve tried to avoid is applying the maximum amount of process to every change.

Not everything needs an elaborate agent pipeline.

For backend work, however, I’m deliberately more conservative.

My backend workflow roughly looks like this:

worktree → prepare → explore → spec → spec review → implement → simplify → verify → code review → archive → PR

There are two important human review points.

The first is before implementation, when I review the specification.

The second is after implementation, when I review the resulting code.

I also route different steps to different models. Implementation can use a faster model, while important review steps can use a stronger one.

This adds overhead, but backend mistakes tend to have a larger blast radius.

A bad frontend change is often visible immediately and relatively easy to revert.

A bad migration, authentication decision, or API contract can be much more expensive.

So for backend code, especially changes involving database migrations, authentication, or public API shapes, I think the additional friction is worth it.

For frontend work, scripts, documentation, and smaller changes, I usually use a much lighter workflow:

plan → review the approach → implement

That’s usually enough.

The workflow should be proportional to the cost of being wrong.

Documentation becomes part of the harness

Another thing I’ve standardized is the repository documentation structure.

Most of my recent projects have something similar to:

docs/
  adr/
  specs/
  temp/
  workflows/
  glossary.md

Each directory has a specific purpose.

adr/

Architecture Decision Records.

When an architectural decision is important enough to survive the current task, it gets an ADR.

I don’t rewrite old decisions after they’ve landed. If the decision changes, a new ADR supersedes the old one.

This preserves the reasoning instead of pretending the project always looked the way it does today.

specs/

This points to the current OpenSpec specifications.

These describe what the system currently expects to do.

temp/

Temporary investigation notes, implementation briefs, experiments, and other task-specific documents.

The important rule is that this directory isn’t supposed to become permanent storage.

If something turns into a durable architectural decision, it gets promoted to an ADR.

Otherwise it eventually gets deleted.

workflows/

Repeatable engineering processes.

For example, my API development workflow lives here.

I like keeping these workflows inside the repository rather than only inside a global AI configuration because the process then evolves together with the project.

The repository becomes part of the agent harness.

glossary.md

Domain terminology.

This is one of those files that looks unnecessary until several developers—or several AI agents—start using slightly different names for the same concept.

Having explicit product terminology helps keep code, specs, APIs, and conversations aligned.

Context is a resource

Once you use coding agents heavily, context management becomes another engineering problem.

A lot of context gets wasted on things that humans don’t really want to read either:

  • huge test outputs
  • git command output
  • logs
  • API responses
  • large files
  • repetitive tool output

I’m currently using two tools to reduce this.

The first is rtk (Rust Token Killer).

It acts as a CLI proxy and rewrites common development command output into a more token-efficient form.

The useful part is that it’s transparent. Commands can still be invoked normally while the agent receives a more compact representation.

The second is context-mode.

Instead of dumping a large tool result directly into the conversation, context-mode puts it into a sandboxed indexed store.

The agent can then execute operations against the data or search it and bring only the relevant result back into the main context.

Conceptually, I prefer this model a lot.

The main agent context should contain reasoning, decisions, requirements, and relevant code—not 5,000 lines of test output.

Automatic context compaction

I also use /autocompact to keep long-running sessions from becoming unnecessarily bloated.

Instead of manually watching context usage and deciding when to compact, the session can periodically reduce older context while preserving the information that still matters.

For me, this fits the general goal of the setup: keep the active context focused on current decisions, requirements, and code rather than carrying the entire history of the session forever.

The bigger idea

I’m increasingly thinking about AI-assisted development less in terms of “which coding agent is best?” and more in terms of the environment around the agent.

The model obviously matters.

But so do:

  • specifications
  • repository structure
  • worktrees
  • specialized agent roles
  • review gates
  • project memory
  • documentation
  • context management
  • repeatable workflows

Together, these things form the harness around the model.

And I suspect that harness will matter more over time.

Models will continue getting better at implementation. The interesting engineering problem becomes how we give them the right constraints, the right context, and the right feedback loops without turning development into either uncontrolled automation or an enormous bureaucratic process.

I’m still experimenting with this setup.

Some parts will probably disappear. Others will become more automated.

For now, though, this gives me a useful balance: agents can do a significant amount of work independently, while specifications, review gates, and repository-level documentation keep me in control of what actually gets built.