<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>LLM on Redowan&#39;s Reflections</title>
    <link>https://rednafi.com/tags/llm/</link>
    <description>Recent content in LLM on Redowan&#39;s Reflections</description>
    <image>
      <title>Redowan&#39;s Reflections</title>
      <url>https://blob.rednafi.com/home/cover-39e2ac8de020.png</url>
      <link>https://rednafi.com/</link>
    </image>
    <generator>Hugo -- 0.165.0</generator>
    <language>en</language>
    <dc:creator>Redowan Delowar</dc:creator>
    <lastBuildDate>Sun, 06 Sep 2026 01:20:27 +0000</lastBuildDate>
    <atom:link href="https://rednafi.com/tags/llm/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>The irrational effectiveness of the Pi harness</title>
      <link>https://rednafi.com/misc/pi-harness/</link>
      <pubDate>Sat, 05 Sep 2026 00:00:00 +0200</pubDate>
      <guid>https://rednafi.com/misc/pi-harness/</guid>
      <dc:creator>Redowan Delowar</dc:creator>
      <description>A month of coding with Pi, its small agent loop, and the skills and extensions I&amp;#39;ve added to it.</description>
      <content:encoded>&lt;p&gt;&lt;img src=&#34;https://blob.rednafi.com/misc/pi-harness/cover-62823da84914.png&#34; alt=&#34;Pi running in Ghostty with a read tool call&#34; width=&#34;2480&#34; height=&#34;1600&#34; referrerpolicy=&#34;no-referrer&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;
&lt;/p&gt;
&lt;p&gt;A few months back, Pi&amp;rsquo;s creator Mario Zechner gave a talk on &lt;a href=&#34;https://www.youtube.com/watch?v=RjfbvDXpFls&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;developing Pi and slowing
things down (opens in new tab)&#34;&gt;developing Pi and slowing
things down&lt;/a&gt;. It resonated with me so much that I wanted to try out the harness. I&amp;rsquo;m also
getting increasingly wary of how bloated Claude Code and Codex have gotten over time.&lt;/p&gt;
&lt;p&gt;I have no idea what these harnesses are putting into the system prompt or how that&amp;rsquo;s
affecting the models&amp;rsquo; responses. I also have no clue about how their tool calling works or
what search engine they&amp;rsquo;re using while searching for something. This opaque nature, along
with the sweeping changes they make to their system instructions every now and then, makes
it difficult to build a reliable workflow. Models are non-deterministic enough. I really
don&amp;rsquo;t want my harness to add to it.&lt;/p&gt;
&lt;p&gt;Pi is a tiny coding harness written in TypeScript. By default, it gives the model four
tools: &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;write&lt;/code&gt;, &lt;code&gt;edit&lt;/code&gt;, and &lt;code&gt;bash&lt;/code&gt;. Ostensibly, that&amp;rsquo;s all you need for most coding
work. The core is small enough that you can read the important parts in one sitting. The
repo has more packages than this, but these are the four salient ones, and they&amp;rsquo;re quite
pleasant to read:&lt;/p&gt;
&lt;div class=&#34;codeblock&#34; translate=&#34;no&#34; data-lang=&#34;txt&#34;&gt;
  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;packages/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;|-- ai/           # model APIs, streaming, and token usage
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;|-- agent/        # agent loop and tool execution
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;|-- tui/          # terminal rendering and keyboard input
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;`-- coding-agent/ # CLI, sessions, and extensions&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Its &lt;a href=&#34;https://github.com/earendil-works/pi/blob/main/packages/agent/src/agent-loop.ts&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;agentic loop (opens in new tab)&#34;&gt;agentic loop&lt;/a&gt; boils down to this:&lt;/p&gt;
&lt;div class=&#34;codeblock&#34; translate=&#34;no&#34; data-lang=&#34;ts&#34; data-copyable&gt;
  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;callModel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;messages&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;tools&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;messages&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stopReason&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stopReason&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aborted&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;calls&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;toolCall&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;calls&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;results&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;executeTools&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;calls&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;messages&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;results&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The model requests tool calls and Pi runs them. The results go back into the conversation.
This repeats until the model replies without requesting another tool. The actual loop also
handles queued user messages and emits events for the UI. The above sketch leaves those out,
along with tool validation and error handling.&lt;/p&gt;
&lt;p&gt;Pi&amp;rsquo;s &lt;a href=&#34;https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/system-prompt.ts&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;system prompt (opens in new tab)&#34;&gt;system prompt&lt;/a&gt; and &lt;a href=&#34;https://github.com/earendil-works/pi/tree/main/packages/coding-agent/src/core/tools&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;tool definitions (opens in new tab)&#34;&gt;tool definitions&lt;/a&gt; together come in at around 1,000 tokens. In
contrast, the &lt;a href=&#34;https://github.com/openai/codex/blob/main/codex-rs/models-manager/prompt.md&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;Codex system prompt (opens in new tab)&#34;&gt;Codex system prompt&lt;/a&gt; that ships with the CLI is about 4,400 tokens before you
count its tool definitions. Claude Code isn&amp;rsquo;t open source, but people have &lt;a href=&#34;https://github.com/Piebald-AI/claude-code-system-prompts&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;reconstructed
its prompts (opens in new tab)&#34;&gt;reconstructed
its prompts&lt;/a&gt;, and the built-in tool descriptions alone add up to several thousand tokens.
There is no benchmark that proves these huge system prompts make the output measurably
better. But they make the sessions costlier from the get-go for sure.&lt;/p&gt;
&lt;p&gt;Pi doesn&amp;rsquo;t bundle extra skills, subagents, or MCP support. If you need them, you can ask Pi
to write an extension or install someone else&amp;rsquo;s. Pi knows its internals, and writing an
extension is such a pleasant experience. You can literally one-shot most of the simple
extensions with any capable model.&lt;/p&gt;
&lt;p&gt;I really like this opt-in approach. Don&amp;rsquo;t add garbage you think I need that I actually
don&amp;rsquo;t. Let me pick my own.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m also skeptical of installing random skills and extensions from the internet. My local
setup has a few I&amp;rsquo;ve written or adapted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rednafi/dotfiles/tree/main/dot_agents/skills/whip&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;skill:whip (opens in new tab)&#34;&gt;skill:whip&lt;/a&gt;: tames the insufferable text that LLMs generate. I copied the content of
&lt;a href=&#34;https://tropes.fyi&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;tropes.fyi (opens in new tab)&#34;&gt;tropes.fyi&lt;/a&gt; into a skill and regularly use it to fix PR descriptions at work.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rednafi/dotfiles/blob/main/dot_pi/agent/extensions/web.ts&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;extension:web.ts (opens in new tab)&#34;&gt;extension:web.ts&lt;/a&gt;: lets Pi search DuckDuckGo and open the results as plain text. It tells
the model to read the pages before answering factual questions.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rednafi/dotfiles/tree/main/dot_pi/agent/extensions/subagent&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;extension:subagent (opens in new tab)&#34;&gt;extension:subagent&lt;/a&gt;: delegates a task to a separate Pi process with its own context. I
copied the code from Pi&amp;rsquo;s &lt;a href=&#34;https://github.com/earendil-works/pi/tree/main/packages/coding-agent/examples/extensions/subagent&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;extension example (opens in new tab)&#34;&gt;extension example&lt;/a&gt;. I can run agents in parallel or pass one
agent&amp;rsquo;s findings to the next.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rednafi/dotfiles/blob/main/dot_pi/agent/extensions/welcome-logo.ts&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;extension:welcome-logo.ts (opens in new tab)&#34;&gt;extension:welcome-logo.ts&lt;/a&gt;: draws the block-letter Pi logo in the screenshot above. This
is the first Pi extension I wrote. It replaces the startup header and uses the current
theme&amp;rsquo;s accent color.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I don&amp;rsquo;t use &lt;code&gt;/goal&lt;/code&gt; or &lt;code&gt;/plan&lt;/code&gt; mode. I still babysit agents and read every line of their
output, so I haven&amp;rsquo;t found the way &lt;code&gt;/goal&lt;/code&gt; works particularly useful for my workflow. As for
planning, I just ask the model to dump the plan in a &lt;code&gt;plan.md&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;Apart from these, I also installed &lt;a href=&#34;https://github.com/nicobailon/pi-mcp-adapter&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;pi-mcp-adapter (opens in new tab)&#34;&gt;pi-mcp-adapter&lt;/a&gt; for MCP access. Its bundled
&lt;code&gt;mcp-scripting&lt;/code&gt; skill lets Pi combine MCP calls in JavaScript. That&amp;rsquo;s the only third-party
extension I&amp;rsquo;m currently using. At some point, I&amp;rsquo;d like to dig into its implementation and
write my own MCP extension too.&lt;/p&gt;
&lt;p&gt;My &lt;a href=&#34;https://github.com/rednafi/dotfiles/tree/main/dot_pi/agent&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;Pi configuration (opens in new tab)&#34;&gt;Pi configuration&lt;/a&gt; is in my dotfiles repo.&lt;/p&gt;
&lt;p&gt;I thought Pi&amp;rsquo;s bare-bones defaults would slow me down. But almost irrationally, I&amp;rsquo;ve used it
every day for the last 30 days and haven&amp;rsquo;t felt the need to return to a more feature-packed
harness. It feels good to use a tool whose core I can keep in my head without flailing. The
TUI has been rock solid too. It hasn&amp;rsquo;t crashed or frozen on me once. I haven&amp;rsquo;t seen it
flicker while I&amp;rsquo;m working. Maybe that&amp;rsquo;s because it&amp;rsquo;s a frikkin TUI and &lt;a href=&#34;https://x.com/trq212/status/2014051501786931427&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34; aria-label=&#34;not a game engine! (opens in new tab)&#34;&gt;not a game engine!&lt;/a&gt;&lt;/p&gt;
&lt;!-- references --&gt;
&lt;!-- prettier-ignore-start --&gt;
&lt;!-- pi running in ghostty --&gt;
&lt;!-- prettier-ignore-end --&gt;
</content:encoded>
      <category>LLM</category>
      <category>CLI</category>
    </item>
  </channel>
</rss>

