<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tameem Bin Haider</title>
    <description>The latest articles on DEV Community by Tameem Bin Haider (@zangetsu101).</description>
    <link>https://dev.to/zangetsu101</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4046913%2Fa543b9d5-6275-4141-827b-8143a608ff93.jpg</url>
      <title>DEV Community: Tameem Bin Haider</title>
      <link>https://dev.to/zangetsu101</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zangetsu101"/>
    <language>en</language>
    <item>
      <title>The Coding Agent I Could Shape Around My Workflow</title>
      <dc:creator>Tameem Bin Haider</dc:creator>
      <pubDate>Sat, 25 Jul 2026 13:52:51 +0000</pubDate>
      <link>https://dev.to/zangetsu101/the-coding-agent-i-could-shape-around-my-workflow-3c38</link>
      <guid>https://dev.to/zangetsu101/the-coding-agent-i-could-shape-around-my-workflow-3c38</guid>
      <description>&lt;p&gt;Claude Code is my daily driver at work. Its defaults are very good, and most things just work. But for a while, I had been hearing plenty of praise for how extensible &lt;a href="https://github.com/earendil-works/pi" rel="noopener noreferrer"&gt;Pi&lt;/a&gt; was.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pi is a small, extensible coding-agent harness that runs in the terminal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That caught my attention because I am a hardcore Neovim user. I have stayed with Neovim not because it arrives perfectly suited to me, but because I can keep shaping it around the way I work. Start with a small core, add what is missing, change the awkward parts, and eventually the editor feels like yours.&lt;/p&gt;

&lt;p&gt;Pi seemed to promise something similar for coding agents.&lt;/p&gt;

&lt;p&gt;Pi does not officially support using an Anthropic subscription, so I got an OpenAI subscription and ran Pi with Codex.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting small
&lt;/h2&gt;

&lt;p&gt;One of the first things I asked Pi was whether it could show my OpenAI usage limits in its status line. It replied that it should be possible with the &lt;a href="https://github.com/openai/codex" rel="noopener noreferrer"&gt;Codex CLI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So after I installed the Codex CLI, Pi built an extension that displayed both rate-limit windows—the five-hour and seven-day windows—in the footer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Codex used 5h:32% (resets 8:00 PM) 7d:14%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It launches Codex's app server, requests the current rate limits, and updates the status after turns. I could ask Pi to modify the extension, run &lt;code&gt;/reload&lt;/code&gt;, and see the result without restarting the CLI.&lt;/p&gt;

&lt;p&gt;It was useful, but it was not yet my “wow” moment. Usage information is hardly unique to Pi.&lt;/p&gt;

&lt;p&gt;I kept using it on side projects. It felt lighter than my usual setup and gave me more control over the agent. I installed an existing RTK integration, added a few keybindings, and made small changes as annoyances appeared.&lt;/p&gt;

&lt;p&gt;These were good customizations, but they were mostly things I knew I wanted before I started.&lt;/p&gt;

&lt;h2&gt;
  
  
  The monitor that blocked the conversation
&lt;/h2&gt;

&lt;p&gt;My real moment with Pi came while working on CI.&lt;/p&gt;

&lt;p&gt;I had asked it to open a pull request and monitor the checks until they turned green. I left it running, came back later, and tried to ask something else. The monitor was still running in the foreground, so my messages were queued behind it.&lt;/p&gt;

&lt;p&gt;I stopped the command and asked whether Pi could monitor the PR in the background instead.&lt;/p&gt;

&lt;p&gt;It could use shell tricks to launch the process, redirect its output, and save its PID. But the command could finish in the background, yet the agent had no reliable way to wake itself and react.&lt;/p&gt;

&lt;p&gt;So I asked Pi to build that.&lt;/p&gt;

&lt;p&gt;The resulting extension registered a &lt;a href="https://github.com/Zangetsu101/dotfiles/blob/main/pi/agent/extensions/background-monitor.ts" rel="noopener noreferrer"&gt;&lt;code&gt;background_monitor&lt;/code&gt;&lt;/a&gt; tool. It runs a long-lived command asynchronously, captures a bounded tail of its output, and returns immediately so the conversation remains usable.&lt;/p&gt;

&lt;p&gt;When the process exits, the extension notifies Pi and triggers a follow-up turn. The agent can inspect the exit code and output, report success, or react to failure.&lt;/p&gt;

&lt;p&gt;This was the first extension that changed how the harness itself worked for me rather than merely adding information to its interface.&lt;/p&gt;

&lt;p&gt;It also taught me something related: adding a tool does not guarantee that the model will use it. We had something along the lines of this on our first iteration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run background commands whose completion the agent must react to
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the next CI session, Pi reached for another blocking Bash watcher. The new tool was registered properly but Pi was not selecting it. After a few iterations, the routing rule became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run slow, finite shell commands asynchronously and wake on completion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That small instruction made the new mechanism part of the agent's normal behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  “You have background agents?”
&lt;/h2&gt;

&lt;p&gt;Shortly afterward, I asked Pi to research asynchronous alternatives to a few blocking Vim Fugitive operations.&lt;/p&gt;

&lt;p&gt;Pi told me the research was running in a background agent.&lt;/p&gt;

&lt;p&gt;That was news to me.&lt;/p&gt;

&lt;p&gt;I had recently installed Matt Pocock's &lt;a href="https://github.com/mattpocock/skills" rel="noopener noreferrer"&gt;&lt;code&gt;research&lt;/code&gt; skill&lt;/a&gt;, which explicitly asks the parent agent to delegate the reading. Pi could always launch another &lt;code&gt;pi&lt;/code&gt; process through Bash; there was no hidden swarm or built-in multi-agent framework. But before &lt;code&gt;background_monitor&lt;/code&gt;, doing so would either block the parent or leave it with an unmanaged detached process.&lt;/p&gt;

&lt;p&gt;The monitor supplied the missing lifecycle: launch the child, keep working, capture its result, and wake the parent when it finished.&lt;/p&gt;

&lt;p&gt;One extension had accidentally paved the way for another capability.&lt;/p&gt;

&lt;p&gt;The first version was crude, though. The delegated Pi ran in non-interactive print mode, and its output was hidden inside the monitor. I could not see what it was doing or steer it while it worked.&lt;/p&gt;

&lt;p&gt;That was not the kind of background agent I wanted. If an agent is working on my behalf, I should be able to look at it whenever I want.&lt;/p&gt;

&lt;h2&gt;
  
  
  From hidden subprocesses to inspectable agents
&lt;/h2&gt;

&lt;p&gt;We built a separate &lt;a href="https://github.com/Zangetsu101/dotfiles/blob/main/pi/agent/extensions/background-agent.ts" rel="noopener noreferrer"&gt;&lt;code&gt;background_agent&lt;/code&gt;&lt;/a&gt; extension.&lt;/p&gt;

&lt;p&gt;Each delegated agent runs as an interactive Pi session inside tmux. The tool call returns immediately to the parent conversation, while the child gets a fresh conversation with the parent's model, thinking level, and working directory. I can list the agents, attach to one, inspect or steer it, and return to the parent. While researching this post, the task list looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Background tasks
  running  agent  Mine old conversations
  running  agent  Inspect extension code and Git history
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tmux also gives these agents a useful durability property: they survive &lt;code&gt;/reload&lt;/code&gt;. The extension can rebuild its watchers from metadata stored with the tmux sessions, while completed children leave records waiting to be consumed.&lt;/p&gt;

&lt;p&gt;Then we had to decide what “finished” meant.&lt;/p&gt;

&lt;p&gt;Waiting for the child process to exit would be wrong because I wanted the interactive session to remain available. Instead, the extension watched Pi's &lt;code&gt;agent_settled&lt;/code&gt; event, reporting when the initial task had settled while keeping the tmux session alive for inspection.&lt;/p&gt;

&lt;p&gt;That seemed like the right boundary—until I used the agents to research this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  “Settled” is not always “done”
&lt;/h2&gt;

&lt;p&gt;I asked Pi to gather context for this post. It launched two background agents: one to mine old conversations and another to inspect the extension code and Git history.&lt;/p&gt;

&lt;p&gt;Each child loaded the same research skill as its parent. That skill told it to delegate the reading, but children deliberately do not have the &lt;code&gt;background_agent&lt;/code&gt; tool. So they improvised: each launched another Pi process through &lt;code&gt;background_monitor&lt;/code&gt;, then replied that research was underway.&lt;/p&gt;

&lt;p&gt;The parent immediately told me both children had finished and went looking for reports that did not exist yet.&lt;/p&gt;

&lt;p&gt;At first glance, this might look like a race in the tmux machinery, but Pi had correctly emitted &lt;code&gt;agent_settled&lt;/code&gt;: each child's own loop had no tool call, retry, or queued follow-up left at that instant. But each child still owned asynchronous work outside the loop.&lt;/p&gt;

&lt;p&gt;“Settled” was local. “Done” was transitive.&lt;/p&gt;

&lt;p&gt;The fix was to let the extensions coordinate. &lt;code&gt;background_monitor&lt;/code&gt; now announces when asynchronous activity starts and finishes. A child agent tracks the activity it owns and refuses to report completion while any remains active. Only after the monitors finish, their follow-up turns run, and the child settles again does the parent receive the result.&lt;/p&gt;

&lt;p&gt;A regression test with two concurrent monitors locks down the behavior: neither initial settlement nor the first monitor finishing is enough. Completion happens only after both jobs and the final turn are done.&lt;/p&gt;

&lt;p&gt;The protocol does not pretend to discover every process on the machine. Background work has to declare itself. But its definition now matches what I mean much more closely:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Done means the agent is settled and no asynchronous work it owns is still running.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There was also a simpler problem underneath all this. The children should not have delegated their own research in the first place. By loading the same skill, the workers were following an instruction written for a coordinator.&lt;/p&gt;

&lt;p&gt;The extension now adds one worker-scoped instruction to every delegated task:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Delegated task: Complete all work—including skill delegation steps—in this session.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The two fixes solve different problems. Activity tracking makes completion correct when a child legitimately owns asynchronous work. The worker prompt prevents orchestration instructions from recursively creating that work.&lt;/p&gt;

&lt;p&gt;The satisfying part is how we found both: by using the extension for real work, watching it fail, and asking Pi to diagnose and extend itself again.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Neovim feeling
&lt;/h2&gt;

&lt;p&gt;This is what finally made Pi click for me.&lt;/p&gt;

&lt;p&gt;I did not install a predetermined “background agent system” and adapt my workflow to it. A foreground watcher blocked the conversation. Shell backgrounding removed the block but lost completion notification. A monitor connected process completion back to the agent. Running Pi through that monitor made delegation possible. Hidden delegation created a need for inspectability. Dogfooding then exposed that an agent could settle before its asynchronous work was done.&lt;/p&gt;

&lt;p&gt;Each solution revealed the next problem.&lt;/p&gt;

&lt;p&gt;That feels similar to what attracted me to Neovim, with one important difference. Much of my Neovim setup consists of extensions other people built, plus smaller customizations of my own. AI makes writing the missing pieces yourself dramatically more approachable.&lt;/p&gt;

&lt;p&gt;Pi has an ecosystem too. I use existing packages where they fit: &lt;a href="https://github.com/lajarre/pi-vim" rel="noopener noreferrer"&gt;&lt;code&gt;pi-vim&lt;/code&gt;&lt;/a&gt; for Vim mode, &lt;a href="https://github.com/rtk-ai/rtk" rel="noopener noreferrer"&gt;RTK&lt;/a&gt; integration for token-efficient shell commands, and &lt;a href="https://github.com/mattpocock/skills" rel="noopener noreferrer"&gt;skills&lt;/a&gt; for workflows such as research and code review. But when something feels wrong, I can ask Pi how it works, change it, reload, and keep going in the same conversation. If that becomes an extension-building detour, &lt;code&gt;/tree&lt;/code&gt; lets me return to the original conversation branch as though the divergence never happened.&lt;/p&gt;

&lt;p&gt;There are costs. &lt;a href="https://github.com/Zangetsu101/dotfiles/tree/main/pi/agent" rel="noopener noreferrer"&gt;My extension directory&lt;/a&gt; eventually became a real TypeScript project with pinned types, strict compiler settings, dependency scripts, and regression tests. Tmux-backed agents create lifecycle and cleanup questions that hidden subprocesses avoid.&lt;/p&gt;

&lt;p&gt;But those costs are visible and understandable. Pi is small enough that I can inspect what it produced and test the exact failure that motivated a change.&lt;/p&gt;

&lt;p&gt;That sense of control matters more to me than having every feature built in.&lt;/p&gt;

&lt;p&gt;The best part, though, is simpler: this is fun.&lt;/p&gt;

&lt;p&gt;Pi feels less like a fixed coding product and more like a tool I am gradually shaping around my own requirements. Its gaps are not always shortcomings to work around. Sometimes they are invitations to teach the harness a new trick—and Pi is remarkably good at helping build the trick itself.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
