27 min read

My Agentic Coding Workflow: Claude Code, Codex, and Pi

It’s been nearly 12 months since I wrote Claude Code Workflow: My Complete Development Setup, and the models have moved fast since then. Opus 4.5 marked a real turning point for agentic workflows. Fable 5 had a rocky launch that briefly took it offline, but once it was back it raised the ceiling again and became one of the models I trust to orchestrate my largest pieces of work. Not long after, OpenAI shipped the GPT-5.6 family: Luna, Terra, and Sol. My agentic coding workflow has changed a lot along with them. In this post I want to share what’s changed, what’s stayed the same, and what I’ve learned along the way.

Context Is Still King

In my original post I said that “Context is King.” That’s still true, and it’s the reason I keep a close eye on the context window. The difference is that back then I relied entirely on Claude Code. Since then I’ve spent a lot of time in Codex with OpenAI’s models, and I’ve even found myself reaching for Pi. Each one has earned a place in my workflow, and I pick between them based on the job in front of me.

My Agent Stack

As I mentioned, I find myself switching between Claude Code, Codex, and Pi throughout my day. Each one has a specific slot in my toolbox. I have to admit that the time I spend in each tool also tends to shift over time. For example, I had a few-month period where I was solely using Codex as opposed to Claude Code. Then I found myself using Pi with my Codex subscription. Over the past few weeks, as of this writing, I’ve found myself back to using Claude Code for quite a bit of my work. So where do these all fit?

My Switch to Codex

Around May of 2026 I hit my weekly limit on my Claude Code Max plan, and that’s what pushed me to give Codex a real shot. What I found was an excellent coding harness, one that I felt was better than Claude Code at the time. The desktop and mobile apps made picking up work from my phone feel far more natural than Claude Code’s remote control and dispatch. When the GPT-5.6 family came out, I found Sol much more efficient than Opus 4.6. Add Codex’s built-in browser and its native way to delegate and orchestrate multiple agents, and the whole ecosystem felt like a step change in my development workflow. This is where multi-agent orchestration really started to click for me. Dispatching agents to new threads in worktrees was a breeze.

I stuck with Codex for the next several months, only going back to Claude Code occasionally for specific workflows, which I’ll cover shortly. Around the same time I started to dabble with Pi. I’d heard a lot about it but couldn’t really justify using it before the move to Codex, because I couldn’t reliably use my Claude Max subscription with it. That was another point of frustration that pushed me toward OpenAI, which is much friendlier about letting you use your subscription outside of its own ecosystem.

Pi

If you’re unfamiliar, Pi is a minimal, open source agent harness. Its philosophy is “primitives, not features.” It deliberately leaves out things like sub-agents, plan mode, and permission prompts, and lets you add them through extensions and packages. You can connect it to a wide range of models and providers, so if you enjoy tweaking your setup it’s a great tool. The package catalog gives you a good sense of how far people have taken it. I first started using it while I was at August Health, as an easy way to connect to our Amazon Bedrock models. I leaned into it more once I started using herdr (more on that below) to manage my coding agents in the terminal. For some reason there still appears to be a bug where Codex doesn’t reliably launch or manage herdr panes and agents, so Pi filled that gap.

Claude Code

Despite all the time I’ve spent in Codex and Pi, Claude Code has kept a special place in my stack. As much as OpenAI’s models have improved, I still think Anthropic has the edge in a few areas, especially design. Claude Design works exceptionally well, and Fable and Opus feel much stronger at building frontend experiences. The recent GPT-6 Astra and GPT-6 Sol releases have closed some of that gap, but in my experience Claude’s artifacts and design systems still reign supreme.

It’s not just design, though. Over the past few weeks I’ve been drawn back to the Claude Code experience itself. Its multi-agent tooling has gotten really good, especially ultracode. Add ultracode to a prompt, or turn it on for the whole session with /effort ultracode, and Claude writes its plan as a workflow script, then fans the work out across a team of agents in the background while my session stays responsive. /advisor pairs my main model with a stronger one that Claude consults at key moments, like before committing to an approach or declaring a task done. Even the built-in plugins lean on extra agents. You Should Know runs one alongside longer sessions to flag things Claude or I might have missed.

Managing Multiple Agents with herdr

You might be asking how I manage all these different ecosystems. That’s where herdr comes in, one of my favorite new tools. herdr is a terminal multiplexer built specifically for agents, and I walked through setting it up in a video a couple of months ago. What I like most about it is how easily it coordinates between different types of agents. For example, I might orchestrate work with an Opus 5.5 agent in Claude Code, which then hands pieces off to agents in Pi or Codex. Often that’s a qwen3.8-flash-next agent in Pi running on my DGX Spark, which lets me offload a significant portion of my work to a local model.

What makes that possible is that herdr gives agents the same controls I have. With its agent skill installed, an agent can create a worktree, start another agent inside it, and send that agent a prompt, all through the herdr CLI. Every agent shows up in one panel with its status, whether it’s working, blocked, or idle, and herdr notifies me when one needs my attention. It also runs as a background server, so closing my terminal doesn’t lose anything. I can also connect to those sessions remotely over SSH, which I find myself doing frequently from my phone.

DHH put it well recently:

DHH on X: Every developer needs an AI shed: An always-on machine running on their tailscale network where the majority of their herdr agents are running.

That’s close to how I work. My shed is a MacBook Pro that sits on my desk with sleep turned off, connected to my Tailscale network. When I’m away from my desk I open Termius on my phone, a Galaxy Z Fold 8, connect over Tailscale, and pick up the same herdr sessions I left running. And with the DGX Spark running local models alongside it, I like to think I’m most of the way to what DHH calls a “baller shed”.

Damian on the couch holding an unfolded Galaxy Z Fold 8, with a terminal agent session open in Termius
Checking in on an agent session from the couch, over Termius on my Galaxy Z Fold 8.

Giving My Agents Context

Earlier I said context is still king. The tools I connect my agents to are how they get that context, and context is one of the four levers I check whenever an agent goes wrong.

The first source of context is the codebase itself. Lauren Tan, whose pstack skills I’ll get to later, describes the codebase as the best form of memory an agent has in a talk on shipping 2,500 PRs in a month, because agents extend whatever patterns they already see. If the code is full of workarounds, agents will copy them. Lauren’s advice is to push each correction as close to the code as you can: make the mistake impossible through the architecture first, catch it with static analysis next, and only then fall back to rules and skills. If you’re not sure where your codebase stands, Codebase Readiness scores a repo for agent readiness and gives you a prioritized roadmap, and Agent Ready scaffolds the docs agents need to understand it.

A lot of what an agent needs to know lives outside the codebase, though, in tickets, production errors, meeting notes, and docs. Here’s what I have set up.

Linear MCP

Linear is my go-to tool for organizing software projects, and giving my agents access to read and write tickets is incredibly important. I connect them through the Linear MCP. If you use a different tool, check whether it has an MCP server or a CLI your agent can use (I wrote about when to choose MCPs versus agent skills). Jira, GitHub Issues, and Asana all have at least one. Whenever I’m working on an issue, I feed my agent the issue ID and it gathers the context it needs from there. It works just as well in the other direction, for storing context. When an agent writes its progress back to Linear (I covered that pattern in more depth), a future agent can pick up the work and understand where things stand and how to proceed.

Implement PRX-66

Sentry CLI

Next up is the Sentry CLI, which is incredibly powerful for investigating production issues as they come up. The agent can fetch everything Sentry has on an issue, including the stack trace. Pair that with logs from your environment and your agent has deep insight into what went wrong, which helps you triage and resolve issues quickly. Sentry also offers an MCP if you’d rather go that route. I prefer the CLI when possible, though. It’s lightweight and works the same across every agent I use. If your errors and logs live somewhere else, the same idea applies. Datadog, for example, has an official MCP server that covers APM, logs, and monitors.

Investigate sentry error PRAXIS-FACTORY-2F

Integrating a note taker

As a developer you likely spend a fair amount of time in meetings, discussing features and work with product, design, stakeholders, or other engineers. A note taker is table stakes for a modern workflow these days. It lets you stay focused on the conversation instead of splitting your attention to take notes. That doesn’t mean I never write notes by hand. I still do, because writing something down helps me remember it. Where the recordings really pay off, though, is when I connect my agent to them. If I have a meeting about a feature, I might jot down the details that stand out to me. When I go to work on that issue later, I can point my agent at the relevant calls to gather the full context of what was discussed. Pair that with the Linear issue and the agent has what it needs to unpack the problem. My note taker of choice these days is Fireflies, since I like having the video recordings alongside the notes. I’ve also had great success with Granola in the past, which is more lightweight. Both have official MCP servers, which is how I connect Fireflies to my agents. (The Fireflies and Granola links are referral links.)

Pull up PRX-587 and my call today with Fred where we discussed the implementation of the Software Factory

Notion + Obsidian

Rounding out my knowledge tools are Notion and Obsidian. Notion is our company’s second brain, where we share knowledge across the team, and Obsidian is my personal vault for anything that’s just mine. You can connect Notion through the Notion MCP to give your agent access to all the pages and databases your team has. If your team is on Confluence instead, Atlassian’s MCP server covers it. Obsidian lives locally, so I add a line to my global instructions file telling the agent where to find the vault. Each agent looks in a different place:

  • Codex: ~/.codex/AGENTS.md
  • Claude Code: ~/.claude/CLAUDE.md
  • Pi: ~/.pi/agent/AGENTS.md

Some agents also support ~/.agents/AGENTS.md. A single line in each file is enough:

My Obsidian vault is located in ~/vault

The Loop

With the context in place, here’s how the work actually flows. I think of my workflow as a loop with four stages, and each stage has its own set of skills:

  • Shape the work into well-defined issues
  • Build each issue with an agent
  • Review what the agent produced
  • Ship it, then loop back to shape the next problem
the problem issues changes approved next problem shape work build review ship
One trip around the loop is one piece of work, from shaping it into issues to shipping them.

Shape: Get the Work Ready for an Agent

These days a good portion of my work goes into shaping, which means making sure the work is ready for an agent to pick up. That starts with a strong understanding of the problem we’re trying to solve, then a solid spec, then breaking the work into pieces an agent can work through iteratively. Shaping is different from plan mode. Plan mode helps an agent figure out how to implement a solution, while shaping makes sure we understand the problem well before anyone gets to the how. When the work is well shaped, I rarely reach for plan mode anymore.

My favorite skills for shaping are by Matt Pocock:

  • grill-me interviews you relentlessly about a plan or design. I use it for non-coding problems.
  • grill-with-docs runs the same interview but also writes docs as you go, recording decisions as ADRs and terms in a glossary. That makes it the better fit for coding work.
  • domain-modeling builds and sharpens a project’s domain model, the vocabulary and decisions behind the code.
  • codebase-design gives the agent a shared vocabulary for designing deep modules: clean interfaces, well-placed seams, and code that’s easy to test.

Both grilling skills build on a parent skill called grilling, and grill-with-docs pulls in domain-modeling as well. You can install all of them with npx skills add mattpocock/skills. I install them globally so they’re available across all my projects.

These skills make sure you and your agent agree on what you’re building before any code gets written. grill-me and grill-with-docs both work through a series of questions to unpack the problem, and you make decisions along the way. With grill-with-docs, those decisions and the terms you define get written down, so future agents have that context too. From the README:

Get relentlessly interviewed about a plan or design until every branch of the design tree is resolved.

Here’s an excerpt from a recent grilling session, where I was shaping an artifacts feature for Praxis:

Round 1. These are the root decisions. Everything else hangs off them.

❓ Q1 - Who views artifacts in v1: Is v1 for you alone, viewed through the private admin gallery over Tailscale, with client-facing sharing deferred to a later phase? The alternative is building share links and a public origin from the start, which pulls in the Cloudflare repo and a token model on day one.

➡️ Yes. You only, admin gallery, Tailscale. Client sharing is a later phase.

---

❓ Q2 - Vocabulary: Shall we fix these terms now? An Artifact is a stable identity with a title, kind, scope, and tags. A Version is an immutable published snapshot of an artifact's files. The Head is the current version. A Design System is an artifact of a specific kind that other artifacts copy files from at publish time. Scope is where an artifact belongs, internal or a client, optionally narrowed to an engagement. Do you use any of these words differently today, especially "project"?

➡️ Yes, with "project" meaning engagement everywhere, and no separate project concept.

---

❓ Q3 - Scope model: Is scope exactly internal or client(id) with an optional engagement, reusing the catalog tables, and nothing else? The thing I want to probe is your content business. A blog post mockup or a YouTube thumbnail concept is neither a client nor internal ops. Does that fall under internal with a content tag, or does it deserve its own scope?

➡️ Yes. Internal plus tags covers content work. Tags like content, youtube, blog. No third scope.

---

❓ Q4 - Kinds in v1: Only html and design-system in v1? No markdown rendering, no React build step, no slides type. An HTML artifact can be a single file or a directory of files with an entry page.

➡️ Yes. Two kinds. Markdown waits until something needs it.

---

❓ Q5 - Where it lives: Build this inside PraxisAgent as a src/artifacts module, a Drizzle-owned app schema addition, an /admin/artifacts page, a Mastra tool, and an MCP route, rather than a separate service or repo?

➡️ Yes, inside Praxis. It already has the catalog, the auth, the database, and the agent.

---

Once the grilling is done, I turn that shared understanding into a spec and a set of issues an agent can pick up for implementation. I use a couple of internal skills for this, spec-writer and issue-writer, inspired by Matt’s to-spec and to-tickets. spec-writer synthesizes what the grilling session already settled into a short spec, without interviewing you again: the problem, the solution, numbered rules, decisions, open questions, how it will be tested, and what’s out of scope. It saves the spec as a Linear document in the right project through the same Linear MCP connection I use for issues. issue-writer then splits the spec into small, vertical slices with blocking relations between them. Each ticket says what to build, how to know it’s done, and what not to touch, and it links back to the spec’s rules by ID instead of copying them, so each rule only lives in one place.

Here’s a trimmed example from a recent spec for a code review agent I’m building:

## Problem

Temporary provider failures cause reviews to fail permanently after one
immediate retry. Users have to intervene even when waiting briefly would
likely resolve the problem.

## Solution

Automatically reschedule eligible review jobs with bounded exponential
backoff, using the existing Postgres-backed queue. Show **Retry scheduled**,
the next attempt time, and the underlying reason.

## Rules

**R1 — Retry only recognized transient provider failures.** Overload,
temporary rate limits, retryable server responses, and network interruptions.

**R2 — Keep permanent and ambiguous failures terminal.** Authentication
failures, exhausted quota, invalid responses, cancellation, and unclassified
errors are never retried automatically.

**R3 — Use bounded exponential backoff.** Retry after 30 seconds, 2 minutes,
and 8 minutes, with ±20% jitter. Three automatic retries, four attempts total.

**R4 — Preserve one logical job.** Retries keep the same job ID and target
commit. Duplicate webhook deliveries neither create a new job nor reset the
retry budget.

…

## Decisions

- Extend the existing Postgres queue rather than adding a queue service.
  Postgres already owns job identity, leases, and cleanup; a second store adds
  coordination without solving the problem.
- Retry the whole review rather than checkpointing individual steps.

## Testing

Integration flow with real Postgres and a controlled provider: overload →
persisted retry → worker restart → successful fresh attempt → exactly one
published review.

## Out of scope

- Manual retry controls.
- Provider or model fallback.

Build: Parallel Agents with pstack

Once the work is shaped, it’s time to implement. I usually hand this off to a fresh agent rather than continuing in the shaping session, so implementation starts with a clean context window. Using herdr, I’ll create a new worktree and start whichever agent fits the work:

  • Codex for a fairly simple, one-off piece of work.
  • Pi for multi-step work I want to delegate or spread out.
  • Claude Code for frontend and visual work, or for complex work I want an agent to orchestrate.

Whichever agent I pick, I run the build with pstack, a set of engineering skills by Lauren, aka poteto. Lauren describes it like this:

pstack gives you fearless parallelism. when you can go deep on one agent and trust it to write good, verifiable code, you can truly parallelize with confidence. start multiple agents up with poteto-mode and trust that they’ll apply rigorous engineering principles to their work.

I’m usually skeptical of big skill packs that promise to fix your whole coding workflow. Most of them add more process than they’re worth. pstack has been the exception.

pstack is open sourced in Cursor’s plugins repo and built for Cursor first. It also installs in Claude Code from the same marketplace, and there are ports available for other coding agents, like Michael Denyer’s pstack-claude, which keeps pace with Lauren’s changes and covers Claude Code, Codex, Pi, and a handful of other harnesses. Since I move between Claude Code, Codex, and Pi throughout the day, that port is the one I use.

Whichever version you install, pstack is organized the same way, in three layers.

/poteto-mode is the entry point. You start a task with it and describe what you want. It matches the task to one of its 23 playbooks, things like bug fix, feature, refactoring, prototype, perf, and shipping, and copies that playbook’s steps into a todo list before it starts. The bug fix playbook, for example, has the agent reproduce the defect and find the root cause before it touches a fix. For most tasks, that’s the only command you need.

Situational skills sit underneath it. /how walks through how a subsystem works. /why digs through git history, PR comments, and your issue tracker to explain why it was built that way. /architect settles the types and call sites before implementation starts, and /interrogate has different models try to break a diff. /poteto-mode calls most of these on its own when a playbook step needs them, so you only reach for them directly when you want one specifically.

The principles tie it together. pstack ships 24 short principle skills, one rule each, grouped into core, architecture, verification, delegation, and meta. /poteto-mode reads an index of them at the start of every task. A few that capture the spirit of it:

  • Laziness protocol: bias toward deletion and the smallest change that solves the problem.
  • Subtract before you add: remove dead code and redundant checks first, then build on the simpler base.
  • Build the lever: build the codemod, script, or generator that does the work instead of doing it by hand, so a reviewer can rerun it.
  • Fix root causes: trace a symptom back to the first place the system went wrong and fix it there.
  • Prove it works: verify against the real thing by running the feature and reading the actual value, not “it compiles” or the agent’s own report.
  • Never block on the human: make the reversible call, keep going, and let the human course-correct afterwards.

pstack also intentionally doesn’t ship a planning skill. The README puts it bluntly: “personally, i don’t believe in planning. the best spec is code.” Design questions get settled with throwaway prototypes and /architect sketches rather than long abstract plans. That pairs well with shaping. Shaping settles what we’re building and why, and pstack works out the how in code.

Verification is the foundation of all of this. The first post in Lauren’s Complete Guide to pstack series is titled “Verification is all you need.” Running /create-verification-skill generates a project-local skill with a small CLI for driving your app and a feature map of what’s in it and how to reach each feature. With that in place the agent can prove its own changes work, instead of you being the one who checks. It’s also what makes orchestration possible, since an orchestrator can only hand off work safely when each agent can prove its own changes.

How I run pstack depends on the size of the work. For a single issue, I start an agent with /poteto-mode and point it at the issue. For an epic, I hand the whole thing to an orchestration agent running /poteto-mode. I explicitly ask it to act as the orchestrator, work through every issue in the epic, and delegate the implementation to a team of agents, stacking the work with GitHub’s stacked PRs. This pairs well with my stacked-prs skill.

That orchestration usually takes one of three shapes:

  • All Claude Code. Depending on the complexity of the epic, Fable 5.1 or Opus 5.5 acts as the orchestrator and fans the implementation out to Sonnet or Haiku agents.
  • Claude Code plus a local model. Lately I’ve been having an Opus 5.5 agent in Claude Code orchestrate qwen3.8-flash-next agents in Pi through herdr. This has worked quite well.
  • All Pi. Pi runs GPT-6.1 Sol or GPT-6 Astra as the orchestrator, delegating to other GPT agents in Pi or to qwen3.8-flash-next running locally.

Review: Specialist Agents, Verified Findings

Once the work is built, the next step is code review. /poteto-mode usually includes a review as part of its routine, but I’ve also built my own review skills. My team-code-review skill hands the changes to six specialist agents, each with its own lens:

  • Architecture and code quality: are responsibilities and abstractions coherent, or is behavior duplicated or misplaced?
  • Readability: naming, control flow, and whether the intent is easy to follow.
  • Testing: does each changed behavior have meaningful coverage, including failure paths and edge cases?
  • Maintainability: coupling, the cost of extending the code later, and likely future failure modes.
  • Security: trust boundaries, authorization, validation, and how secrets and sensitive data are handled.
  • Documentation: public interfaces, setup, migrations, and runbooks affected by the change.

What makes it work is the verification step. The main agent independently checks every finding before reporting it by opening the cited code, looking at callers and tests, and reproducing the issue where it can. Anything speculative or unverified gets dropped, so what comes back is a short list of evidence-backed issues.

A variant on this is herdr-code-review, which wraps team-code-review but runs the review in a fresh agent session through herdr. That way the reviewers start with a clean context window instead of inheriting the implementation session’s. Any findings go back to the implementation team to resolve, followed by another review, and that loop continues until the work is ready for a pull request.

When I’m reviewing someone else’s pull request, the same skill can draft the review for me with my conventional-comments skill, but only after I’ve seen the verified findings and agreed to it.

Ship: Clean Commits and Stacked Pull Requests

Once the work passes review, it’s time to open a pull request. Two skills help here, and both live in my agent-skills library, which I recently consolidated into one library for every coding agent. The first is conventional-commits, which keeps every commit following the Conventional Commits specification:

The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of. This convention dovetails with SemVer, by describing the features, fixes, and breaking changes made in commit messages.

Consistent commit messages make the history easier for me to scan, and I find they help agents too when they look back through history to understand past changes.

The second is stacked-prs. When the work is part of a larger orchestration, like an epic broken into many issues, my agents use it to ship the changes as GitHub stacked pull requests through the gh stack CLI extension. Each pull request holds one focused change and builds on the one below it, which keeps related work queued up in small, reviewable pieces and avoids giant pull requests. Stacked pull requests are still in public preview on GitHub, so you may need to enable them for your repository first.

issues changes approved next problem shape work build review ship grill-me grill-with-docs domain-modeling codebase-design spec-writer issue-writer pstack (poteto-mode) tdd team-code-review herdr-code-review conventional-comments conventional-commits stacked-prs
The full loop, with the skills I reach for at each stage.

What Carries Over Between Tools

A year ago this post was about one tool. Now it’s about three, plus herdr to hold them together, and I expect the list to look different again a year from now. What hasn’t changed is the shape of the work.

Agents still do their best work with good context, so the tools that feed them context carry over no matter which harness I’m in. Shaping still comes first, because a well-understood problem is what lets an agent work on its own. And verification is what lets me hand off more of the loop, whether that’s an agent proving its own changes, a team of reviewers whose findings get checked before they reach me, or a stack of small pull requests a human can actually read.

If you’re building out your own workflow, I’d start with the loop rather than the tools. Pick the stage that’s weakest for you today, which is usually shaping or verification, and invest there first. The rest of the loop gets easier once the problem is well understood and the agent can prove its work.


If you want help with AI-native engineering on your team, from shaping work for agents to the review loops and conventions that make them reliable in production, that’s the kind of engagement I take on. See how I help teams adopt AI-native engineering.

Further Reading