<?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: Masih Maafi</title>
    <description>The latest articles on DEV Community by Masih Maafi (@masihmoafi).</description>
    <link>https://dev.to/masihmoafi</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%2F3345178%2F4bb95e46-47e7-4b24-9265-7b45b8d6b3de.png</url>
      <title>DEV Community: Masih Maafi</title>
      <link>https://dev.to/masihmoafi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/masihmoafi"/>
    <language>en</language>
    <item>
      <title>How Aider works under the hood</title>
      <dc:creator>Masih Maafi</dc:creator>
      <pubDate>Sat, 26 Sep 2026 12:31:56 +0000</pubDate>
      <link>https://dev.to/masihmoafi/how-aider-works-under-the-hood-3ik7</link>
      <guid>https://dev.to/masihmoafi/how-aider-works-under-the-hood-3ik7</guid>
      <description>&lt;p&gt;Codex and Aider look alike from the outside: you type, the model edits your code. Inside&lt;br&gt;
they are opposite designs. In Codex the model has tools and explores the repository&lt;br&gt;
itself. In Aider &lt;strong&gt;the model has no tools at all&lt;/strong&gt;. The harness decides what the model&lt;br&gt;
sees, the model answers in plain text, and the harness finds the edits in that text and&lt;br&gt;
applies them.&lt;/p&gt;

&lt;p&gt;This post follows one message through Aider's Python source, the same way my&lt;br&gt;
&lt;a href="https://masihmoafi.com/blog/codex-elpis-under-the-hood" rel="noopener noreferrer"&gt;Codex and Elpis post&lt;/a&gt; does for Codex. Code is quoted&lt;br&gt;
verbatim from Aider &lt;code&gt;0.86.3.dev&lt;/code&gt;, commit &lt;code&gt;5dc9490&lt;/code&gt;, with paths relative to the&lt;br&gt;
repository root. Nothing here was run; it is read from the source.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. The shape: one object per mode
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;main()&lt;/code&gt; builds a single &lt;code&gt;Coder&lt;/code&gt; and loops on &lt;code&gt;coder.run()&lt;/code&gt;.&lt;br&gt;
Each edit format is its own &lt;code&gt;Coder&lt;/code&gt; subclass with its own prompts and parser, so a mode&lt;br&gt;
change such as &lt;code&gt;/ask&lt;/code&gt; or &lt;code&gt;/architect&lt;/code&gt; is not a flag. It raises &lt;code&gt;SwitchCoder&lt;/code&gt;, and &lt;code&gt;main&lt;/code&gt;&lt;br&gt;
builds a new &lt;code&gt;Coder&lt;/code&gt; from the old one, copying the files, history and cost across&lt;br&gt;
(in &lt;code&gt;Coder.create&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/main.py
&lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ok_to_warm_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_keepalive_pings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Completed main CLI coder.run&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;SwitchCoder&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;        &lt;span class="n"&gt;kwargs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;from_coder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;coder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;        &lt;span class="n"&gt;coder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the edit format&lt;br&gt;
changed, the old history is summarized first, because the code's own comment says the old&lt;br&gt;
format "will confused the new LLM. It may try and imitate it".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/coders/base_coder.py
# If the edit format changes, we can't leave old ASSISTANT
# messages in the chat history. The old edit format will
# confused the new LLM. It may try and imitate it, disobeying
# the system prompt.
&lt;/span&gt;&lt;span class="n"&gt;done_messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;from_coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;done_messages&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;edit_format&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;from_coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;edit_format&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;done_messages&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;summarize_from_coder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;done_messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;from_coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;summarizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;summarize_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;done_messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. What the model sees
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb9b5k5sy8z2rx6nc6ezz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb9b5k5sy8z2rx6nc6ezz.png" alt="Flowchart of one Aider turn: preprocess the message, build the request, send and stream the reply, check for newly named files, apply and commit edits, lint and test, then either send problems back as the next message, up to three times, or move the turn into history." width="800" height="904"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8jq8xuv1jsqhmpymf8mn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8jq8xuv1jsqhmpymf8mn.png" alt="Diagram, continued (part 2 of 3)" width="800" height="707"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnhjvczklntkb7hguf0tp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnhjvczklntkb7hguf0tp.png" alt="Diagram, continued (part 3 of 3)" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The request is assembled by &lt;code&gt;ChatChunks&lt;/code&gt; in a fixed order: system prompt, examples,&lt;br&gt;
read-only files, the repo map, past history, the editable files, the current turn, and&lt;br&gt;
last a reminder of the edit-format rules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/coders/chat_chunks.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;all_messages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;
        &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;examples&lt;/span&gt;
        &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readonly_files&lt;/span&gt;
        &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;
        &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;
        &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_files&lt;/span&gt;
        &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur&lt;/span&gt;
        &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reminder&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;done&lt;/code&gt; is the past history and &lt;code&gt;cur&lt;/code&gt; is the current turn. Stable&lt;br&gt;
parts come first and volatile ones last, so the prompt cache keeps a long prefix (my&lt;br&gt;
inference from the caching code below). Notice that the editable files sit after the&lt;br&gt;
history, so the model reads the newest version of a file right next to your request.&lt;/p&gt;

&lt;p&gt;Context blocks are faked as conversation: a message such as "here are the files" followed&lt;br&gt;
by an invented "Ok." from the assistant. A history summary comes back the same way, as a&lt;br&gt;
&lt;em&gt;user&lt;/em&gt; message beginning "I spoke to you previously about..." (see &lt;code&gt;summarize_all&lt;/code&gt; in&lt;br&gt;
&lt;code&gt;aider/history.py&lt;/code&gt; and &lt;code&gt;summary_prefix&lt;/code&gt; in &lt;code&gt;aider/prompts.py&lt;/code&gt;).&lt;br&gt;
The model sees these as things that were said, not as notes from the system.&lt;/p&gt;

&lt;p&gt;The whole conversation goes to &lt;code&gt;litellm&lt;/code&gt;, one API over many providers, at temperature 0&lt;br&gt;
by default (in &lt;code&gt;Model.send_completion&lt;/code&gt;). Retryable errors back off from 0.125 seconds,&lt;br&gt;
doubling until the delay passes 60.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/models.py
&lt;/span&gt;&lt;span class="n"&gt;RETRY_TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;        &lt;span class="n"&gt;retry_delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.125&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_retry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;retry_delay&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;retry_delay&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;RETRY_TIMEOUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;should_retry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. No tools, on purpose
&lt;/h2&gt;

&lt;p&gt;The base class sets &lt;code&gt;functions = None&lt;/code&gt;, and the reflection limit sits right next to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/coders/base_coder.py
&lt;/span&gt;&lt;span class="n"&gt;functions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;&lt;span class="n"&gt;num_reflections&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;max_reflections&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three coders&lt;br&gt;
once used JSON function calls to edit, but they are out of the registry, and two raise&lt;br&gt;
"Deprecated" when built (in &lt;code&gt;editblock_func_coder.py&lt;/code&gt; and &lt;code&gt;wholefile_func_coder.py&lt;/code&gt;). The only reason the&lt;br&gt;
repository gives is a changelog note from v0.7.0 in &lt;code&gt;HISTORY.md&lt;/code&gt;: "Initial experiments show that using&lt;br&gt;
functions makes 3.5 less competent at coding".&lt;/p&gt;

&lt;p&gt;So the model writes edits as fenced text, and Aider finds them with regular expressions.&lt;br&gt;
The nearest thing to a shell tool is a fenced bash block in the reply, which runs only if you&lt;br&gt;
say yes (in &lt;code&gt;run_shell_commands&lt;/code&gt;). Its output goes into the &lt;em&gt;next&lt;/em&gt; turn, not&lt;br&gt;
back to the model at once.&lt;/p&gt;

&lt;p&gt;That changes what "agentic" means. Codex loops until the model stops asking for tools.&lt;br&gt;
Aider's only loop is a &lt;strong&gt;reflection&lt;/strong&gt;: after a turn, if Aider itself found a problem, it&lt;br&gt;
sends the problem back as the next user message, at most three times&lt;br&gt;
(the &lt;code&gt;max_reflections = 3&lt;/code&gt; above). Four things count as a problem: an edit that&lt;br&gt;
would not parse or match, a repo file the model named that is not in the chat, lint&lt;br&gt;
errors, and test errors. They all share the same budget of three.&lt;/p&gt;

&lt;p&gt;That second one is how the model "opens a file". It cannot call a read tool, so it names&lt;br&gt;
the file in its reply. Aider notices, asks you whether to add it, and replays the turn.&lt;br&gt;
The check runs before any edit is applied, so an otherwise valid edit in that same reply&lt;br&gt;
is thrown away.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/coders/base_coder.py
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;interrupted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;add_rel_files_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_for_file_mentions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;add_rel_files_message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reflected_message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reflected_message&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;add_rel_files_message&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reflected_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add_rel_files_message&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The early &lt;code&gt;return&lt;/code&gt; comes before &lt;code&gt;apply_updates()&lt;/code&gt; is ever called. A person is the gate where&lt;br&gt;
Codex would have a tool call.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. From a reply to a change on disk
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkke2hq0rh2tzofr4nazs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkke2hq0rh2tzofr4nazs.png" alt="Flowchart of how Aider applies an edit: parse edit blocks from the reply text, dry-run to find each real target file, ask permission for new or unadded files, match and write each block, collect an error with near-miss lines for blocks that fail to match, auto-commit what was written, then send any errors back to the model." width="800" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fat8i3eujtzsjvug45iqt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fat8i3eujtzsjvug45iqt.png" alt="Diagram, continued (part 2 of 2)" width="800" height="927"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The default format is SEARCH/REPLACE: the model quotes the lines to change, then the&lt;br&gt;
lines to put there. The parser is loose on purpose, accepting five to nine marker&lt;br&gt;
characters and hunting up to three lines above a block for its filename, because one&lt;br&gt;
model kept misplacing them (in &lt;code&gt;find_original_update_blocks&lt;/code&gt; and &lt;code&gt;find_filename&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/coders/editblock_coder.py
&lt;/span&gt;&lt;span class="n"&gt;HEAD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^&amp;lt;{5,9} SEARCH&amp;gt;?\s*$&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;DIVIDER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^={5,9}\s*$&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;UPDATED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^&amp;gt;{5,9} REPLACE\s*$&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;                &lt;span class="c1"&gt;# if next line after HEAD exists and is DIVIDER, it's a new file
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;divider_pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
                    &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;find_filename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;fence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;find_filename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;fence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;valid_fnames&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;{5,9}&lt;/code&gt; in each pattern and the &lt;code&gt;i - 3&lt;/code&gt; window for the filename.&lt;/p&gt;

&lt;p&gt;Matching an imperfect SEARCH tries a fixed sequence: an exact line match, then the same&lt;br&gt;
match with the leading indentation repaired ("GPT often messes up leading whitespace",&lt;br&gt;
says the comment), then the same again without a stray blank line, then a &lt;code&gt;...&lt;/code&gt; elision&lt;br&gt;
that requires each piece to appear exactly once (in &lt;code&gt;replace_most_similar_chunk&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/coders/editblock_coder.py
&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;perfect_or_whitespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;whole_lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;part_lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;replace_lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;part_lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;part_lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;skip_blank_line_part_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;part_lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;perfect_or_whitespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;whole_lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skip_blank_line_part_lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;replace_lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;    &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;try_dotdotdots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;whole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="c1"&gt;# Try fuzzy matching
&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;replace_closest_edit_distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;whole_lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;part_lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;replace_lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;perfect_or_whitespace&lt;/code&gt; covers the first two steps. Keep an eye on the bare &lt;code&gt;return&lt;/code&gt;&lt;br&gt;
near the end; section 10 comes back to it.&lt;/p&gt;

&lt;p&gt;When a block fails, the error the model receives is written to be fixable: each failed&lt;br&gt;
block echoed back, the closest real lines in the file, a reminder that SEARCH must match&lt;br&gt;
exactly including whitespace, and "The other N blocks were applied successfully. Don't&lt;br&gt;
re-send them." (in &lt;code&gt;EditBlockCoder.apply_edits&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/coders/editblock_coder.py
&lt;/span&gt;        &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The SEARCH section must exactly match an existing block of lines including all white&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; space, comments, indentation, docstrings, etc&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;passed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;pblocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;block&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;passed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;blocks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
# The other &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;passed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; SEARCH/REPLACE &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pblocks&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; were applied successfully.
Don&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t re-send them.
Just reply with fixed versions of the &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;blocks&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; above that failed to match.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aider also has unified-diff, whole-file and OpenAI-style patch formats. The whole-file&lt;br&gt;
format has no matching step at all: the file is simply overwritten.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. The repo map: context without a model choosing it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd6k18jrb4829bdu5pvlv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd6k18jrb4829bdu5pvlv.png" alt="Flowchart of how Aider builds its repo map: extract definitions and references with tree-sitter, cache them, build a graph of files linked by shared identifiers, weight the edges, run personalized PageRank, then binary search for the largest map that fits the token budget." width="696" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fou1bjc695re7kslm3gzh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fou1bjc695re7kslm3gzh.png" alt="Diagram, continued (part 2 of 3)" width="696" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1rqb81d3zcm15va5o953.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1rqb81d3zcm15va5o953.png" alt="Diagram, continued (part 3 of 3)" width="696" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aider never lets the model search the repository, so it hands over a map. For every file&lt;br&gt;
it uses tree-sitter to pull out definitions and references, and caches them on disk&lt;br&gt;
keyed by modification time (in &lt;code&gt;RepoMap.get_tags&lt;/code&gt; and &lt;code&gt;get_tags_raw&lt;/code&gt;, in &lt;code&gt;aider/repomap.py&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Then it builds a graph. Files are nodes, and an identifier that one file defines and&lt;br&gt;
another references becomes an edge from the referencing file to the defining one. The&lt;br&gt;
weight is a multiplier times the square root of the number of references, so a name&lt;br&gt;
repeated a hundred times does not drown out the rest. The multiplier is 10 if you&lt;br&gt;
mentioned the name, 10 if it looks distinctive (long snake, kebab or camel case), 0.1 if&lt;br&gt;
it starts with an underscore, 0.1 if more than five files define it, and a further 50 if&lt;br&gt;
the edge comes from a file already in the chat (in &lt;code&gt;RepoMap.get_ranked_tags&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/repomap.py
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ident&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mentioned_idents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;mul&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_snake&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;is_kebab&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;is_camel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;mul&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;mul&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;defines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;mul&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;referencer&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;chat_rel_fnames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;use_mul&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;        &lt;span class="n"&gt;num_refs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_refs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;referencer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;definer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;use_mul&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;num_refs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ident&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"Long" means at least eight characters.&lt;/p&gt;

&lt;p&gt;Personalized PageRank then ranks the files, seeded by the chat files and anything you&lt;br&gt;
mentioned (the &lt;code&gt;nx.pagerank&lt;/code&gt; call in the same function). No language model is involved. The score is split&lt;br&gt;
over each file's definitions, definitions in chat files are dropped because their full&lt;br&gt;
text is already sent, and Aider binary-searches for the largest map that fits the token&lt;br&gt;
budget, stopping once it is within 15% of it (in &lt;code&gt;RepoMap.get_ranked_tags_map_uncached&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/repomap.py
&lt;/span&gt;&lt;span class="n"&gt;pct_err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_tokens&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;max_map_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;max_map_tokens&lt;/span&gt;
&lt;span class="n"&gt;ok_err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.15&lt;/span&gt;
&lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;max_map_tokens&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;num_tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;best_tree_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;pct_err&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ok_err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;best_tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt;
    &lt;span class="n"&gt;best_tree_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;num_tokens&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pct_err&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ok_err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The budget is&lt;br&gt;
an eighth of the model's input window, clamped between 1,024 and 4,096 tokens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/models.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_repo_map_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;map_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;
    &lt;span class="n"&gt;max_inp_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_input_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;max_inp_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;map_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;max_inp_tokens&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
        &lt;span class="n"&gt;map_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;map_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;map_tokens&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Keeping the window under control
&lt;/h2&gt;

&lt;p&gt;Aider never trims context by itself. Before each request &lt;code&gt;check_tokens()&lt;/code&gt; only warns,&lt;br&gt;
"Try to proceed anyway?", and tells you to &lt;code&gt;/drop&lt;/code&gt; or &lt;code&gt;/clear&lt;/code&gt;.&lt;br&gt;
If the provider still reports an exceeded window, the turn simply ends.&lt;/p&gt;

&lt;p&gt;The one thing a model does manage is chat history. Once past history exceeds a sixteenth&lt;br&gt;
of the context window, clamped to between 1,024 and 8,192 tokens, a background thread&lt;br&gt;
summarizes the older part with the cheap "weak" model, keeping a recent tail of about&lt;br&gt;
half the budget word for word (the limit is set in the &lt;code&gt;Model&lt;/code&gt; constructor; the split is in&lt;br&gt;
&lt;code&gt;ChatSummary.summarize_real&lt;/code&gt; in &lt;code&gt;aider/history.py&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;For cost, &lt;code&gt;--cache-prompts&lt;/code&gt; places Anthropic-style cache markers on up to three&lt;br&gt;
prefixes (examples, repo map, editable files), and a daemon thread pings the model every&lt;br&gt;
five minutes minus five seconds with a one-token request to keep the cache warm while you&lt;br&gt;
think (in &lt;code&gt;ChatChunks.add_cache_control_headers&lt;/code&gt; and &lt;code&gt;Coder.warm_cache&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/coders/base_coder.py
&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AIDER_CACHE_KEEPALIVE_DELAY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;        &lt;span class="n"&gt;kwargs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extra_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Codex aims at the same goal differently:&lt;br&gt;
it re-sends the whole history with a &lt;code&gt;prompt_cache_key&lt;/code&gt; and lets the provider's cache do&lt;br&gt;
the rest.&lt;/p&gt;
&lt;h2&gt;
  
  
  7. Git as the safety net
&lt;/h2&gt;

&lt;p&gt;Aider has no sandbox; a search of its source finds none. Its safety net is git. Before&lt;br&gt;
editing a file it commits any uncommitted changes you had in it, so each edit gets its own&lt;br&gt;
clean commit. After writing, it commits the result with a message written by a model, and&lt;br&gt;
tells the model the hash (in &lt;code&gt;check_for_dirty_commit&lt;/code&gt; and &lt;code&gt;auto_commit&lt;/code&gt;, and &lt;code&gt;GitRepo.commit&lt;/code&gt; in &lt;code&gt;aider/repo.py&lt;/code&gt;).&lt;br&gt;
&lt;code&gt;/undo&lt;/code&gt; will only revert a commit if it is one of this session's own, has a single&lt;br&gt;
parent, has not been pushed, and its files are clean (in &lt;code&gt;raw_cmd_undo&lt;/code&gt; in &lt;code&gt;aider/commands.py&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;
  
  
  8. Architect and editor: two models, one handoff
&lt;/h2&gt;

&lt;p&gt;In architect mode a strong model plans and a second model writes the edits. The architect&lt;br&gt;
produces no edits itself. When it finishes it asks "Edit the files?", then starts a new&lt;br&gt;
&lt;code&gt;Coder&lt;/code&gt; on the editor model with no history and no repo map, and passes the architect's&lt;br&gt;
whole reply to it as the user message (in &lt;code&gt;ArchitectCoder.reply_completed&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/coders/architect_coder.py
&lt;/span&gt;&lt;span class="n"&gt;editor_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;editor_model&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main_model&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main_model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;editor_model&lt;/span&gt;
&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;edit_format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;editor_edit_format&lt;/span&gt;
&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;suggest_shell_commands&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;map_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;&lt;span class="n"&gt;editor_coder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;new_kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;editor_coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;editor_coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;done_messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="c1"&gt;# …
&lt;/span&gt;&lt;span class="n"&gt;editor_coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;with_message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;preproc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;map_tokens = 0&lt;/code&gt; turns the repo map off, the two message lists are emptied, and &lt;code&gt;content&lt;/code&gt;&lt;br&gt;
is the architect's reply. My reading&lt;br&gt;
is that this lets a strong reasoning model be paired with one that is better at the&lt;br&gt;
edit format, though the code does not say so.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Side by side
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Aider&lt;/th&gt;
&lt;th&gt;Codex&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Who explores the repo&lt;/td&gt;
&lt;td&gt;The harness, through a repo map and the files you add&lt;/td&gt;
&lt;td&gt;The model, through shell and read tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How edits happen&lt;/td&gt;
&lt;td&gt;Parsed from the model's text&lt;/td&gt;
&lt;td&gt;A tool call (&lt;code&gt;apply_patch&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The loop&lt;/td&gt;
&lt;td&gt;At most 3 harness-driven reflections&lt;/td&gt;
&lt;td&gt;Until the model stops calling tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safety&lt;/td&gt;
&lt;td&gt;A git commit per edit, and your yes before any command the model suggests&lt;/td&gt;
&lt;td&gt;An approval policy and an OS sandbox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long sessions&lt;/td&gt;
&lt;td&gt;You manage the file set; old history is summarized in the background&lt;/td&gt;
&lt;td&gt;The window is compacted at 90%, and the model's own outputs are dropped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Providers&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;litellm&lt;/code&gt;, one call for many providers&lt;/td&gt;
&lt;td&gt;The Responses API, with adapters added in Elpis&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Neither is simply better. Aider's design gives up autonomy for predictability: roughly one&lt;br&gt;
model call per turn plus at most three reflections, and a human at every decision that&lt;br&gt;
reaches outside the chat. Codex's gives the model room to explore and pays for it with a sandbox, an approval&lt;br&gt;
system and a longer context.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Things you would not guess
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fuzzy matching is switched off.&lt;/strong&gt; A comment reads "Try fuzzy matching", but a bare
&lt;code&gt;return&lt;/code&gt; sits just above the call, so it never runs. Only the error hint uses similarity
(see the end of &lt;code&gt;replace_most_similar_chunk&lt;/code&gt; in section 4).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A reply can leave a half-applied commit.&lt;/strong&gt; Blocks that match are written to disk one by
one, and the result is auto-committed before the failures are sent back to be retried
(in &lt;code&gt;EditBlockCoder.apply_edits&lt;/code&gt; and &lt;code&gt;Coder.send_message&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A wrong filename is quietly forgiven.&lt;/strong&gt; If a SEARCH does not match its named file,
Aider tries every other file in the chat and applies the edit to the first that matches
(in &lt;code&gt;EditBlockCoder.apply_edits&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The context guard fails open.&lt;/strong&gt; If token counting throws, it prints a warning and
returns 0, so the check passes (in &lt;code&gt;Model.token_count&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The unified-diff format replaces every match.&lt;/strong&gt; The uniqueness check is commented out
and the code calls &lt;code&gt;str.replace&lt;/code&gt;; the
SEARCH/REPLACE format replaces only the first.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/coders/search_replace.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search_and_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texts&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;search_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;replace_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;original_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texts&lt;/span&gt;

    &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;original_text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# if num &amp;gt; 1:
&lt;/span&gt;    &lt;span class="c1"&gt;#    raise SearchTextNotUnique()
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="n"&gt;new_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;original_text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;replace_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/drop a.py&lt;/code&gt; also drops &lt;code&gt;data.py&lt;/code&gt;.&lt;/strong&gt; Dropping matches by substring of the path, where
&lt;code&gt;/add&lt;/code&gt; matches exactly or by glob (in &lt;code&gt;cmd_drop&lt;/code&gt;).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aider/commands.py
# For editable files, use glob if word contains glob chars, otherwise use substring
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;expanded_word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*?[]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;matched_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob_filtered_to_repo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expanded_word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Use substring matching like we do for read-only files
&lt;/span&gt;    &lt;span class="n"&gt;matched_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_rel_fname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abs_fnames&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;expanded_word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What this does not cover
&lt;/h2&gt;

&lt;p&gt;I did not trace &lt;code&gt;ContextCoder&lt;/code&gt;, watch mode's internals beyond the outline, voice input,&lt;br&gt;
the web scraper, or analytics. Aider can be run with a different edit format per model,&lt;br&gt;
and the defaults live in a settings file I read only through git.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://masihmoafi.com/blog/aider-under-the-hood" rel="noopener noreferrer"&gt;https://masihmoafi.com/blog/aider-under-the-hood&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>How Codex and Elpis work under the hood</title>
      <dc:creator>Masih Maafi</dc:creator>
      <pubDate>Sat, 26 Sep 2026 12:22:30 +0000</pubDate>
      <link>https://dev.to/masihmoafi/how-codex-and-elpis-work-under-the-hood-2ch9</link>
      <guid>https://dev.to/masihmoafi/how-codex-and-elpis-work-under-the-hood-2ch9</guid>
      <description>&lt;p&gt;A coding agent is a loop around a list of messages. This post follows one prompt&lt;br&gt;
through the Rust code of Codex CLI, the foundation Elpis is forked from, and marks the&lt;br&gt;
exact places where Elpis hooks in.&lt;/p&gt;

&lt;p&gt;Code is quoted verbatim from commit &lt;code&gt;e2efa7a5&lt;/code&gt;. Paths are relative to&lt;br&gt;
&lt;code&gt;codex-rs/&lt;/code&gt;. Nothing here was run for this post; it is read from the source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to tell Elpis code from Codex code.&lt;/strong&gt; All of &lt;code&gt;codex-rs&lt;/code&gt; arrived as one import of&lt;br&gt;
&lt;code&gt;openai/codex&lt;/code&gt; at revision &lt;code&gt;2e1607ee&lt;/code&gt; (&lt;code&gt;ELPIS_UPSTREAM.md&lt;/code&gt;), committed as &lt;code&gt;f37fc774&lt;/code&gt;.&lt;br&gt;
A file that exists at that commit is Codex's; one that does not was written by Elpis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git cat-file &lt;span class="nt"&gt;-e&lt;/span&gt; f37fc774:codex-rs/core/src/session/turn.rs   &lt;span class="c"&gt;# exists  -&amp;gt; Codex's&lt;/span&gt;
git cat-file &lt;span class="nt"&gt;-e&lt;/span&gt; f37fc774:codex-rs/core/src/smart_prune.rs    &lt;span class="c"&gt;# missing -&amp;gt; Elpis's&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  1. Two queues, and typing while it works
&lt;/h2&gt;

&lt;p&gt;The UI never calls the agent. It pushes a &lt;code&gt;Submission { id, op }&lt;/code&gt; into a bounded&lt;br&gt;
channel (capacity 512) and reads &lt;code&gt;Event { id, msg }&lt;/code&gt; from an unbounded one&lt;br&gt;
(both types are in &lt;code&gt;protocol/src/protocol.rs&lt;/code&gt;; the channels are made in&lt;br&gt;
&lt;code&gt;Session::spawn&lt;/code&gt;). One background task,&lt;br&gt;
&lt;code&gt;submission_loop&lt;/code&gt;, routes each &lt;code&gt;Op&lt;/code&gt;. Interrupts and approvals are handled inline, which&lt;br&gt;
is how an approval can reach a turn that is already running.&lt;/p&gt;

&lt;p&gt;Typing while the agent works does not start a second turn. &lt;code&gt;user_input_or_turn_inner&lt;/code&gt;&lt;br&gt;
first tries &lt;code&gt;steer_input&lt;/code&gt;, and only spawns a new &lt;code&gt;RegularTask&lt;/code&gt; if that fails with&lt;br&gt;
&lt;code&gt;NoActiveTurn&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// core/src/session/handlers.rs&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;sess&lt;/span&gt;
    &lt;span class="nf"&gt;.steer_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;additional_context&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="cm"&gt;/*expected_turn_id*/&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;client_user_message_id&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;responsesapi_client_metadata&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;current_context&lt;/span&gt;&lt;span class="py"&gt;.session_telemetry&lt;/span&gt;&lt;span class="nf"&gt;.user_prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;SteerInputError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;NoActiveTurn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your message is seen at the next sampling step; tool calls already in flight finish&lt;br&gt;
first.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. What the model actually receives
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Nothing is stored server-side.&lt;/strong&gt; The request sets &lt;code&gt;store&lt;/code&gt; to true only for Azure&lt;br&gt;
in &lt;code&gt;core/src/client.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// core/src/client.rs&lt;/span&gt;
&lt;span class="n"&gt;parallel_tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="py"&gt;.parallel_tool_calls&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;model_info&lt;/span&gt;&lt;span class="py"&gt;.use_responses_lite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="nf"&gt;.is_azure_responses_endpoint&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The whole history, including encrypted reasoning items, is re-sent on every request of&lt;br&gt;
the loop.&lt;/p&gt;

&lt;p&gt;That is only affordable because of the prompt cache, and it explains a design choice:&lt;br&gt;
context is append-only. On the first turn (and right after compaction) Codex builds the&lt;br&gt;
full context, meaning developer messages for permissions, collaboration mode and&lt;br&gt;
skills, plus one contextual user message holding instructions and environment. On later&lt;br&gt;
turns it appends only &lt;em&gt;diffs&lt;/em&gt; (&lt;code&gt;record_context_updates_and_set_reference_context_item&lt;/code&gt;&lt;br&gt;
in &lt;code&gt;core/src/session/mod.rs&lt;/code&gt;). Each fragment is&lt;br&gt;
wrapped in text markers (&lt;code&gt;# AGENTS.md instructions ... &amp;lt;/INSTRUCTIONS&amp;gt;&lt;/code&gt;) so the code&lt;br&gt;
can find and replace it later (&lt;code&gt;context-fragments/src/fragment.rs&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Before every request the history is normalized: a tool call with no output gets an&lt;br&gt;
"aborted" output, and an output whose call is gone is dropped:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// core/src/context_manager/normalize.rs&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.enumerate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;ResponseItem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FunctionCall&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;call_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;function_output_ids&lt;/span&gt;&lt;span class="nf"&gt;.contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;call_id&lt;/span&gt;&lt;span class="nf"&gt;.as_str&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;info!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Function call output is missing for call id: {call_id}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;missing_outputs_to_insert&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;
                &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nn"&gt;ResponseItem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FunctionCallOutput&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;synthetic_output_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fco"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="nf"&gt;.as_deref&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
                    &lt;span class="n"&gt;call_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;call_id&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                    &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;FunctionCallOutputPayload&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"aborted"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API rejects unpaired calls, and an interrupt can leave one behind.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The loop
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl7d985u6e4d6wsgsh6n0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl7d985u6e4d6wsgsh6n0.png" alt="Flowchart of one turn: a submission either steers the running turn or starts a new one, then the loop compacts if needed, records context, streams the model's reply, runs tool calls, and repeats until no follow-up is needed." width="800" height="811"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0g62jx2amjz7v1q80u8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0g62jx2amjz7v1q80u8e.png" alt="Diagram, continued (part 2 of 3)" width="800" height="942"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9bmiybeikuogp5i4336g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9bmiybeikuogp5i4336g.png" alt="Diagram, continued (part 3 of 3)" width="800" height="1030"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The stream is parsed into &lt;code&gt;ResponseEvent&lt;/code&gt;s. Text deltas go straight to the UI, but an&lt;br&gt;
item only enters history when it is &lt;em&gt;done&lt;/em&gt; (&lt;code&gt;handle_output_item_done&lt;/code&gt; in&lt;br&gt;
&lt;code&gt;core/src/stream_events_utils.rs&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;If the item is a tool call, the call is recorded at once and its execution is pushed&lt;br&gt;
onto a &lt;code&gt;FuturesOrdered&lt;/code&gt;, so tools start running while the model is still streaming. An&lt;br&gt;
&lt;code&gt;RwLock&lt;/code&gt; decides concurrency: tools that support parallelism take a read lock, the rest&lt;br&gt;
take the write lock and run alone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// core/src/tools/parallel.rs&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_guard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;supports_parallel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;Either&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Left&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="nf"&gt;.read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;Either&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Right&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="nf"&gt;.write&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After &lt;code&gt;Completed&lt;/code&gt;, the outputs are drained and recorded &lt;strong&gt;in call order&lt;/strong&gt;, which keeps&lt;br&gt;
the history deterministic (&lt;code&gt;drain_in_flight&lt;/code&gt; in &lt;code&gt;core/src/session/turn.rs&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The turn continues while &lt;code&gt;needs_follow_up&lt;/code&gt; holds: there were tool calls, or the server&lt;br&gt;
said &lt;code&gt;end_turn: false&lt;/code&gt;, or you steered mid-turn. Otherwise Stop hooks run, and can&lt;br&gt;
block the stop by injecting a continuation prompt. There is no planner and no state&lt;br&gt;
machine underneath. "Agentic" is this inner loop.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Running a command
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faz9afabpldmdfcqt2jtf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faz9afabpldmdfcqt2jtf.png" alt="Flowchart of how a tool call runs: routing and hooks, then the shell, apply_patch or MCP path, execution policy, approval, the sandbox attempt with a possible unsandboxed retry, and output capping." width="800" height="860"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4d1gcoueby1gjhl3sm99.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4d1gcoueby1gjhl3sm99.png" alt="Diagram, continued (part 2 of 2)" width="800" height="860"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Routing.&lt;/strong&gt; A &lt;code&gt;FunctionCall&lt;/code&gt; becomes JSON arguments; a &lt;code&gt;CustomToolCall&lt;/code&gt; (apply_patch&lt;br&gt;
uses this) becomes free text. An unknown tool name is returned to the model as an error,&lt;br&gt;
not a crash. Hooks wrap every tool, built-in or MCP, at one choke point&lt;br&gt;
(&lt;code&gt;build_tool_call&lt;/code&gt; in &lt;code&gt;core/src/tools/router.rs&lt;/code&gt;, &lt;code&gt;dispatch_any_with_terminal_outcome&lt;/code&gt;&lt;br&gt;
in &lt;code&gt;registry.rs&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Policy.&lt;/strong&gt; Rules are Starlark &lt;code&gt;prefix_rule(pattern=[...], decision=allow|prompt|forbidden)&lt;/code&gt;&lt;br&gt;
files, loaded per config layer (&lt;code&gt;load_exec_policy&lt;/code&gt; in &lt;code&gt;core/src/exec_policy.rs&lt;/code&gt;). A&lt;br&gt;
&lt;code&gt;bash -lc&lt;/code&gt; script is split into its commands, each is matched, and the strictest&lt;br&gt;
decision wins, because the decisions are ordered Allow &amp;lt; Prompt &amp;lt; Forbidden:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// execpolicy/src/decision.rs&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Clone,&lt;/span&gt; &lt;span class="nd"&gt;Copy,&lt;/span&gt; &lt;span class="nd"&gt;Debug,&lt;/span&gt; &lt;span class="nd"&gt;Eq,&lt;/span&gt; &lt;span class="nd"&gt;PartialEq,&lt;/span&gt; &lt;span class="nd"&gt;Ord,&lt;/span&gt; &lt;span class="nd"&gt;PartialOrd,&lt;/span&gt; &lt;span class="nd"&gt;Serialize,&lt;/span&gt; &lt;span class="nd"&gt;Deserialize)]&lt;/span&gt;
&lt;span class="nd"&gt;#[serde(rename_all&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"camelCase"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Decision&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/// Command may run without further approval.&lt;/span&gt;
    &lt;span class="n"&gt;Allow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="cd"&gt;/// Request explicit user approval; rejected outright when running with `approval_policy="never"`.&lt;/span&gt;
    &lt;span class="n"&gt;Prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="cd"&gt;/// Command is blocked without further consideration.&lt;/span&gt;
    &lt;span class="n"&gt;Forbidden&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The derived &lt;code&gt;Ord&lt;/code&gt; follows declaration order, so &lt;code&gt;from_matches&lt;/code&gt; in&lt;br&gt;
&lt;code&gt;execpolicy/src/policy.rs&lt;/code&gt; just takes the &lt;code&gt;.max()&lt;/code&gt;. Commands that match no rule fall to heuristics: a&lt;br&gt;
known-safe list, a dangerous-command check, and the approval policy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One choke point.&lt;/strong&gt; Shell, unified exec and apply_patch all go through&lt;br&gt;
&lt;code&gt;ToolOrchestrator::run&lt;/code&gt;: approval first, then a sandbox, then a possible retry&lt;br&gt;
(&lt;code&gt;core/src/tools/orchestrator.rs&lt;/code&gt;). Approval is decided by a hook, then by the&lt;br&gt;
Guardian (an automated reviewer agent) if configured, then by you&lt;br&gt;
(&lt;code&gt;core/src/tools/approvals.rs&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The sandbox, on Linux.&lt;/strong&gt; The command is prefixed with &lt;code&gt;codex-linux-sandbox&lt;/code&gt;. It builds&lt;br&gt;
a bubblewrap jail (&lt;code&gt;--new-session --die-with-parent --unshare-user --unshare-pid&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;--unshare-net&lt;/code&gt; when the network is off, the root mounted read-only, writable roots&lt;br&gt;
bound back in), then re-execs inside it, sets &lt;code&gt;PR_SET_NO_NEW_PRIVS&lt;/code&gt;, and installs a&lt;br&gt;
seccomp filter that blocks &lt;code&gt;ptrace&lt;/code&gt;, &lt;code&gt;process_vm_*&lt;/code&gt; and &lt;code&gt;io_uring&lt;/code&gt;, plus network&lt;br&gt;
syscalls in restricted mode (&lt;code&gt;linux-sandbox/src/bwrap.rs&lt;/code&gt;, &lt;code&gt;linux_run_main.rs&lt;/code&gt;). The&lt;br&gt;
blocked syscalls are listed plainly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// linux-sandbox/src/landlock.rs&lt;/span&gt;
&lt;span class="nf"&gt;deny_syscall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SYS_ptrace&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;deny_syscall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SYS_process_vm_readv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;deny_syscall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SYS_process_vm_writev&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;deny_syscall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SYS_io_uring_setup&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;deny_syscall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SYS_io_uring_enter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;deny_syscall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SYS_io_uring_register&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Landlock is only a legacy fallback behind &lt;code&gt;features.use_legacy_landlock&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limits.&lt;/strong&gt; A command times out after 10 seconds by default and its whole process group&lt;br&gt;
is killed (&lt;code&gt;DEFAULT_EXEC_COMMAND_TIMEOUT_MS&lt;/code&gt; in &lt;code&gt;core/src/exec.rs&lt;/code&gt;). At most 1 MiB of output is kept in memory, and the&lt;br&gt;
model sees it trimmed again by the model's truncation policy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;apply_patch&lt;/strong&gt; is a custom diff format with no line numbers. Hunks are found by&lt;br&gt;
matching context in &lt;code&gt;seek_sequence&lt;/code&gt;, which tries an exact match, then ignoring trailing&lt;br&gt;
whitespace, then ignoring all surrounding whitespace, and last of all treating typographic&lt;br&gt;
dashes and quotes as their ASCII twins, so small drift in model output still applies.&lt;br&gt;
The first three comparisons, one per pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// apply-patch/src/seek_sequence.rs&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// …&lt;/span&gt;
&lt;span class="c1"&gt;// Then rstrip match.&lt;/span&gt;
&lt;span class="c1"&gt;// …&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;p_idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.trim_end&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;pat&lt;/span&gt;&lt;span class="nf"&gt;.trim_end&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// …&lt;/span&gt;
&lt;span class="c1"&gt;// Finally, trim both sides to allow more lenience.&lt;/span&gt;
&lt;span class="c1"&gt;// …&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;p_idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;pat&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The patch is checked against the real filesystem before approval is decided, and it is&lt;br&gt;
applied through a sandboxed filesystem helper, not a shell (&lt;code&gt;handle_call&lt;/code&gt; in&lt;br&gt;
&lt;code&gt;core/src/tools/handlers/apply_patch.rs&lt;/code&gt;). Models often run apply_patch through the&lt;br&gt;
shell anyway, so &lt;code&gt;run_exec_like&lt;/code&gt; detects that and reroutes it&lt;br&gt;
(&lt;code&gt;core/src/tools/handlers/shell.rs&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP&lt;/strong&gt; tools never touch the OS sandbox: the server process is launched with&lt;br&gt;
&lt;code&gt;sandbox: None&lt;/code&gt;, and approval comes from the server's own destructive/read-only&lt;br&gt;
annotations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// core/src/mcp_tool_call.rs&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;destructive_hint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="nf"&gt;.and_then&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="py"&gt;.destructive_hint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;destructive_hint&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;read_only_hint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;
    &lt;span class="nf"&gt;.and_then&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="py"&gt;.read_only_hint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.unwrap_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;read_only_hint&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skills are not tools at all; a mentioned skill's &lt;code&gt;SKILL.md&lt;/code&gt; is injected as context.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. When the window fills
&lt;/h2&gt;

&lt;p&gt;The context size Codex acts on is part measurement and part guess: the server's total&lt;br&gt;
from the last request, plus a 4-bytes-per-token estimate for everything added since&lt;br&gt;
(&lt;code&gt;get_total_token_usage&lt;/code&gt; in &lt;code&gt;core/src/context_manager/history.rs&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Auto-compaction triggers at 90% of the model's window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// protocol/src/openai_models.rs&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;auto_compact_token_limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;context_limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;
        &lt;span class="nf"&gt;.resolved_context_window&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;context_window&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context_window&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;config_limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.auto_compact_token_limit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context_limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context_limit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;config_limit&lt;/span&gt;&lt;span class="nf"&gt;.map_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context_limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context_limit&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;config_limit&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is checked before a turn and, mid-turn, when a follow-up is needed. The local backend&lt;br&gt;
sends the history plus a "context checkpoint" prompt as an ordinary request. The&lt;br&gt;
replacement history is the most recent user messages that fit in 20k tokens plus one&lt;br&gt;
user-role message holding the summary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// core/src/compact.rs&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;user_messages&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.rev&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// …&lt;/span&gt;
&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ResponseItem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nn"&gt;ContentItem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;InputText&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;summary_text&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="n"&gt;phase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;internal_chat_message_metadata_passthrough&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your messages are walked newest first, and the summary goes in with &lt;code&gt;role: "user"&lt;/code&gt;. &lt;strong&gt;Every tool call&lt;br&gt;
and every assistant message is gone.&lt;/strong&gt; The model does not remember its own earlier&lt;br&gt;
outputs; it reads a summary of them. For OpenAI and Azure the default backend is&lt;br&gt;
instead a server-side compaction that returns an opaque encrypted item.&lt;/p&gt;

&lt;p&gt;Each thread appends to &lt;code&gt;sessions/YYYY/MM/DD/rollout-&amp;lt;timestamp&amp;gt;-&amp;lt;id&amp;gt;.jsonl&lt;/code&gt; under&lt;br&gt;
&lt;code&gt;CODEX_HOME&lt;/code&gt;, which Elpis defaults to &lt;code&gt;~/.elpis&lt;/code&gt;. Resume reads that file &lt;em&gt;backwards&lt;/em&gt;&lt;br&gt;
until it reaches the last compaction checkpoint, which carries the full replacement&lt;br&gt;
history, and replays only the tail (&lt;code&gt;reconstruct_history_from_rollout&lt;/code&gt; in&lt;br&gt;
&lt;code&gt;core/src/session/rollout_reconstruction.rs&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;
  
  
  6. Where Elpis hooks in
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp92gtngsfl99ucfsvrj5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp92gtngsfl99ucfsvrj5.png" alt="Diagram of where Elpis hooks into Codex: the TUI writes admission state that filters the request, requests go through a provider adapter, and tool outputs pass through Smart Prune with an audit record before entering history; memory saves are a separate tool." width="800" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7yfvcqk7ytwmjtf31hq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7yfvcqk7ytwmjtf31hq9.png" alt="Diagram, continued (part 2 of 2)" width="800" height="760"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Prune is one call inserted into the loop.&lt;/strong&gt; Codex collects finished tool&lt;br&gt;
outputs and records them into history. Elpis added &lt;code&gt;optimize_pending_outputs&lt;/code&gt; between&lt;br&gt;
those two steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// core/src/session/turn.rs&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pending_outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;smart_prune&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;optimize_pending_outputs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;turn_context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pending_outputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cancellation_token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pending_output&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pending_outputs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;response_item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pending_output&lt;/span&gt;&lt;span class="py"&gt;.response&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;sess&lt;/span&gt;&lt;span class="nf"&gt;.record_conversation_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;turn_context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;response_item&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because it acts before a result is&lt;br&gt;
first admitted, the existing prefix is never rewritten and the prompt cache stays valid;&lt;br&gt;
the older force-prune rewrites history and discards it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eligibility.&lt;/strong&gt; A result needs at least 1,024 estimated tokens, a batch stays under
24,000, and a result is only replaced if that saves at least 256 tokens and at least
20%. Runtime failures and hook or policy feedback are never touched, so control text
stays exact. The batch cap is &lt;code&gt;MAX_PRUNE_BATCH_TOKENS&lt;/code&gt; in &lt;code&gt;context_pruner.rs&lt;/code&gt;; the
other three floors are here:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// core/src/smart_prune.rs&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MIN_SOURCE_TOKENS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1_024&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MIN_SAVED_TOKENS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MIN_SAVINGS_PERCENT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The optimizer call.&lt;/strong&gt; One extra request with its own system prompt, Low reasoning
effort, a 180-second timeout and a strict JSON schema. On the OpenAI provider the
default optimizer is &lt;code&gt;gpt-5.6-luna&lt;/code&gt; (&lt;code&gt;run_model_admission&lt;/code&gt; and &lt;code&gt;selected_model_slug&lt;/code&gt;
in &lt;code&gt;core/src/session/smart_prune.rs&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The contract.&lt;/strong&gt; Every call ID must appear exactly once, as &lt;code&gt;compact&lt;/code&gt; with content or
&lt;code&gt;unchanged&lt;/code&gt; with none. An unknown, duplicate or missing ID rejects the entire batch.
A kept result ends with a pointer,
&lt;code&gt;exact_source=smart-prune://&amp;lt;admission&amp;gt;/&amp;lt;call&amp;gt; source_sha256=…&lt;/code&gt;, back to the original.
In &lt;code&gt;parse_decision_manifest&lt;/code&gt;, every &lt;code&gt;return None&lt;/code&gt; throws the whole batch away:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// core/src/smart_prune.rs&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;by_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;HashMap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with_capacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="py"&gt;.items&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="py"&gt;.items&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="nf"&gt;.contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="py"&gt;.call_id&lt;/span&gt;&lt;span class="nf"&gt;.as_str&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;by_id&lt;/span&gt;&lt;span class="nf"&gt;.contains_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="py"&gt;.call_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="py"&gt;.decision&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="py"&gt;.content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;RawDecisionKind&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Compact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// …&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;RawDecisionKind&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Unchanged&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;AdmissionDecision&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Unchanged&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// …&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Audit first.&lt;/strong&gt; The record is written to a &lt;code&gt;.pending-*&lt;/code&gt; directory, fsynced, and
renamed into place. Only then is the shortened result recorded
(&lt;code&gt;write_admission&lt;/code&gt; in &lt;code&gt;core/src/session/smart_prune_audit.rs&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail open.&lt;/strong&gt; Any failure keeps the original. A failed batch also switches Smart
Prune off for the rest of that turn (&lt;code&gt;record_batch_failure&lt;/code&gt; in
&lt;code&gt;core/src/session/smart_prune.rs&lt;/code&gt;), and a
toggle takes effect on the next turn, because the flag is copied into the turn once at
its start.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Context Ledger&lt;/strong&gt; is a TOML file. &lt;code&gt;admission.toml&lt;/code&gt; lives under&lt;br&gt;
&lt;code&gt;&amp;lt;elpis_home&amp;gt;/context/workspaces/&amp;lt;workspace&amp;gt;/&lt;/code&gt; and records which sources are admitted:&lt;br&gt;
AGENTS.md (global and project), &lt;code&gt;GOAL.md&lt;/code&gt;, &lt;code&gt;ES.md&lt;/code&gt;, &lt;code&gt;MEMORY.md&lt;/code&gt; and the dev rule files&lt;br&gt;
(&lt;code&gt;core/src/elpis_context.rs&lt;/code&gt;). Excluding one changes the request through two gates.&lt;br&gt;
Continuity files go through &lt;code&gt;ElpisContinuityExtension&lt;/code&gt;, which emits a single developer&lt;br&gt;
fragment headed &lt;code&gt;## Elpis Admitted Context&lt;/code&gt; and only re-emits it when the text changes.&lt;br&gt;
AGENTS.md is already sent by Codex, so Elpis patched &lt;code&gt;agents_md_manager&lt;/code&gt; to filter it,&lt;br&gt;
and the cache key includes an admission fingerprint so a toggle applies on the very next&lt;br&gt;
request (&lt;code&gt;contribute_world_state&lt;/code&gt; in &lt;code&gt;app-server/src/extensions.rs&lt;/code&gt;, &lt;code&gt;refresh&lt;/code&gt; in&lt;br&gt;
&lt;code&gt;core/src/agents_md_manager.rs&lt;/code&gt;). There is no protocol call for this: the TUI writes&lt;br&gt;
&lt;code&gt;admission.toml&lt;/code&gt; itself through core (&lt;code&gt;set_context_source_admitted&lt;/code&gt; in&lt;br&gt;
&lt;code&gt;tui/src/chatwidget/context_ledger.rs&lt;/code&gt;) and the app-server re-reads it each turn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory is one more tool.&lt;/strong&gt; &lt;code&gt;save_memory&lt;/code&gt; is registered only when the turn began with a&lt;br&gt;
baseline snapshot of &lt;code&gt;MEMORY.md&lt;/code&gt; and &lt;code&gt;ES.md&lt;/code&gt;, and only for the root agent. It applies&lt;br&gt;
exact append, replace or remove edits, refuses to write if either file changed since&lt;br&gt;
the turn began, and writes a receipt marked prepared, then &lt;code&gt;MEMORY.md&lt;/code&gt;, then &lt;code&gt;ES.md&lt;/code&gt;&lt;br&gt;
(rolled back if that fails), then marks the receipt committed&lt;br&gt;
(&lt;code&gt;commit_update&lt;/code&gt; in &lt;code&gt;core/src/memory_save.rs&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Providers are an adapter.&lt;/strong&gt; At import, &lt;code&gt;WireApi&lt;/code&gt; had one variant, Responses. Elpis&lt;br&gt;
added Anthropic Messages, Gemini and Chat Completions (the &lt;code&gt;WireApi&lt;/code&gt; enum in&lt;br&gt;
&lt;code&gt;model-provider-info/src/lib.rs&lt;/code&gt;). Every non-Responses provider goes through one&lt;br&gt;
function that translates the Responses-shaped request into the provider's format and&lt;br&gt;
translates the stream back into &lt;code&gt;ResponseEvent&lt;/code&gt;s (&lt;code&gt;stream_native_api&lt;/code&gt; in&lt;br&gt;
&lt;code&gt;core/src/client.rs&lt;/code&gt;, and &lt;code&gt;core/src/chat_completions.rs&lt;/code&gt;). The&lt;br&gt;
turn loop, tools, history and pruning still only see Responses items, which is why&lt;br&gt;
swapping providers touches so little.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Work graphs.&lt;/strong&gt; The &lt;code&gt;enable_fanout&lt;/code&gt; flag is not an Elpis flag: it is Codex's own&lt;br&gt;
&lt;code&gt;SpawnCsv&lt;/code&gt; feature, under development and off by default (&lt;code&gt;features/src/lib.rs&lt;/code&gt;).&lt;br&gt;
Elpis's &lt;code&gt;run_agent_work_graph&lt;/code&gt; is registered beside the CSV fan-out tool. A graph is&lt;br&gt;
validated before anything is stored, and a topological sort rejects cycles. A task is&lt;br&gt;
ready when every dependency has succeeded, and a task only counts as done if its&lt;br&gt;
report passes an evidence gate: files outside its scope, a &lt;code&gt;changed_files&lt;/code&gt; list that&lt;br&gt;
disagrees with the engine's own before/after snapshot, or empty evidence are all&lt;br&gt;
rejected (&lt;code&gt;report_work_task&lt;/code&gt; in &lt;code&gt;core/src/tools/handlers/work_graphs.rs&lt;/code&gt;). Only one&lt;br&gt;
writable task runs per environment at a time, whatever their scopes&lt;br&gt;
(&lt;code&gt;tasks_have_write_conflict&lt;/code&gt; in the same file).&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Things you would not guess
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Under the &lt;code&gt;OnRequest&lt;/code&gt; approval policy, a command that fails inside the sandbox is
&lt;strong&gt;not&lt;/strong&gt; retried outside it. The model has to ask for escalation up front:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// core/src/tools/sandboxing.rs&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;wants_no_sandbox_approval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AskForApproval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;AskForApproval&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;UnlessTrusted&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;AskForApproval&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Never&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;AskForApproval&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OnRequest&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;AskForApproval&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Granular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;granular_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;granular_config&lt;/span&gt;&lt;span class="py"&gt;.sandbox_approval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;An &lt;code&gt;Allow&lt;/code&gt; rule removes the sandbox entirely when every segment of a script matches an
explicit Allow. It is a trust grant, not just "skip the prompt":
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// core/src/exec_policy.rs&lt;/span&gt;
&lt;span class="nn"&gt;Decision&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Allow&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;ExecApprovalRequirement&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Skip&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Bypass sandbox only when every parsed command segment is&lt;/span&gt;
    &lt;span class="c1"&gt;// explicitly allowed by execpolicy.&lt;/span&gt;
    &lt;span class="n"&gt;bypass_sandbox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.all&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// …&lt;/span&gt;
            &lt;span class="nf"&gt;.any&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;rule_match&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;is_policy_match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rule_match&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;rule_match&lt;/span&gt;&lt;span class="nf"&gt;.decision&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nn"&gt;Decision&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Allow&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The "Linux seccomp" sandbox type is bubblewrap plus a seccomp filter, and the file
named &lt;code&gt;landlock.rs&lt;/code&gt; holds the seccomp code (&lt;code&gt;SandboxType::LinuxSeccomp&lt;/code&gt; in
&lt;code&gt;sandboxing/src/manager.rs&lt;/code&gt;, and the header comment of &lt;code&gt;linux-sandbox/src/landlock.rs&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The context-size number is partly an estimate, so the compaction trigger fires on a
guess as well as a measurement.&lt;/li&gt;
&lt;li&gt;Compaction keeps your messages and drops the agent's own: tool calls and replies are
replaced by a summary written as a &lt;em&gt;user&lt;/em&gt; message.&lt;/li&gt;
&lt;li&gt;Toggling Smart Prune or a Ledger row applies at the next turn or request, not
mid-flight.&lt;/li&gt;
&lt;li&gt;Inferred, not tested: since the Ledger writes a file rather than calling the server, a
remote app-server would see a different file from the one your TUI edits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Status
&lt;/h2&gt;

&lt;p&gt;Smart Prune is experimental and off by default. In a frozen synthetic study its cost&lt;br&gt;
depended on the horizon: short sessions cost more, and sessions of about 35 requests cost&lt;br&gt;
less. Whether it changes task success remains unproven.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://masihmoafi.com/blog/codex-elpis-under-the-hood" rel="noopener noreferrer"&gt;https://masihmoafi.com/blog/codex-elpis-under-the-hood&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rust</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why Your AI Coding Agent Needs Local Hybrid Search: Building rag-mcp with LanceDB &amp; Tantivy</title>
      <dc:creator>Masih Maafi</dc:creator>
      <pubDate>Sun, 23 Aug 2026 16:38:58 +0000</pubDate>
      <link>https://dev.to/masihmoafi/why-your-ai-coding-agent-needs-local-hybrid-search-building-rag-mcp-with-lancedb-tantivy-5g49</link>
      <guid>https://dev.to/masihmoafi/why-your-ai-coding-agent-needs-local-hybrid-search-building-rag-mcp-with-lancedb-tantivy-5g49</guid>
      <description>&lt;p&gt;&lt;strong&gt;A coding agent should not have to choose between opening files one at a time and dumping an entire repository into context.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When building autonomous AI coding assistants (like Claude Code, Codex, or Cursor), context window management is everything. Today, agents face a painful trilemma:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Greedy file probing&lt;/strong&gt;: Running &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, or &lt;code&gt;find_by_name&lt;/code&gt; across dozens of directories wastes precious tokens, incurs multi-turn tool latency, and often misses cross-file abstractions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brute-force context stuffing&lt;/strong&gt;: Dumping entire directories into the prompt triggers quadratic attention costs, slows inference to a crawl, and increases reasoning hallucination.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Naive vector search&lt;/strong&gt;: Pure dense embedding search fails spectacularly on exact symbol names, compiler error codes, and unique variable identifiers like &lt;code&gt;AUTH_JWT_SECRET_KEY&lt;/code&gt; or &lt;code&gt;handle_epoch_timeout&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To solve this, I built &lt;strong&gt;&lt;a href="https://github.com/MasihMoafi/rag-mcp" rel="noopener noreferrer"&gt;rag-mcp&lt;/a&gt;&lt;/strong&gt;: a 100% local, high-throughput hybrid search engine engineered specifically as a Model Context Protocol (MCP) server for coding agents.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🚀 &lt;strong&gt;Try it live in your browser (Zero Download / Zero Backend)&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
&lt;a href="https://rag.masihmoafi.com" rel="noopener noreferrer"&gt;https://rag.masihmoafi.com&lt;/a&gt; &lt;em&gt;(Mirror: &lt;a href="https://rag.masihmoafi.tech" rel="noopener noreferrer"&gt;https://rag.masihmoafi.tech&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Architecture: Why Pure Vector Search Fails on Code
&lt;/h2&gt;

&lt;p&gt;Merging sparse lexical search (BM25) and dense semantic vectors sounds simple in theory, but in practice, linear score combination ($S = \alpha S_{\text{vector}} + (1-\alpha) S_{\text{bm25}}$) causes severe calibration skew because BM25 scores are unbounded floats while cosine similarities are bounded in $[-1, 1]$.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rag-mcp&lt;/code&gt; resolves this with a 2-stage retrieval pipeline:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmasihmoafi.com%2Frag-mcp%2Farchitecture.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmasihmoafi.com%2Frag-mcp%2Farchitecture.svg" alt="rag-mcp Architecture" width="100" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Tantivy Rust BM25 (Lexical Accuracy)
&lt;/h3&gt;

&lt;p&gt;Tantivy provides native Rust-speed full-text indexing directly over your codebase. If your prompt asks about &lt;code&gt;class TransactionHandler&lt;/code&gt; or an exact error string, Tantivy surfaces the exact line ranges with zero semantic hallucination.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. LanceDB Apache Arrow Vectors (Semantic Context)
&lt;/h3&gt;

&lt;p&gt;Unlike traditional vector databases that serialize records into SQLite blobs or require heavy background Docker containers, &lt;strong&gt;LanceDB&lt;/strong&gt; stores embeddings in Apache Arrow columnar memory format. It allows zero-copy vector querying directly against your filesystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Reciprocal Rank Fusion (RRF, $k=60$)
&lt;/h3&gt;

&lt;p&gt;Instead of normalizing uncalibrated similarity scores, &lt;code&gt;rag-mcp&lt;/code&gt; merges the ranked lists using Reciprocal Rank Fusion:&lt;/p&gt;

&lt;p&gt;$$RRF(d) = \sum_{m \in M} \frac{1}{k + r_m(d)}$$&lt;/p&gt;

&lt;p&gt;Where $k=60$ acts as a smoothing constant preventing any single outlier from dominating the final ranking.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Cross-Encoder Reranker
&lt;/h3&gt;

&lt;p&gt;The top $N$ fused candidates pass through a fast local Cross-Encoder (&lt;code&gt;ms-marco-MiniLM-L-6-v2&lt;/code&gt;) that jointly attends over &lt;code&gt;(query, passage)&lt;/code&gt; pairs to prune false positives before returning tokens to the agent.&lt;/p&gt;




&lt;h2&gt;
  
  
  Empirical Benchmark Results
&lt;/h2&gt;

&lt;p&gt;We evaluated &lt;code&gt;rag-mcp&lt;/code&gt; against the &lt;strong&gt;&lt;a href="https://github.com/vectara/open-rag-eval" rel="noopener noreferrer"&gt;open-rag-eval&lt;/a&gt;&lt;/strong&gt; taxonomy across multiple heterogeneous corpora ($top_k=5$, local Ollama embeddings):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Corpus / Domain&lt;/th&gt;
&lt;th&gt;Total Queries&lt;/th&gt;
&lt;th&gt;Strict Relevance (Score 3 / Exact)&lt;/th&gt;
&lt;th&gt;Full + Partial (Score $\ge$ 2)&lt;/th&gt;
&lt;th&gt;Miss Rate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mixed Codebase (Python + Rust + Notebooks)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;90.9%&lt;/strong&gt; (20/22)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;100.0%&lt;/strong&gt; (22/22)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;0.0%&lt;/strong&gt; (0/22)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scientific Literature (Attention Paper)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;93.3%&lt;/strong&gt; (28/30)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;96.7%&lt;/strong&gt; (29/30)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;3.3%&lt;/strong&gt; (1/30)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Academic Textbook (Brain &amp;amp; Behavior)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;85.7%&lt;/strong&gt; (30/35)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;94.3%&lt;/strong&gt; (33/35)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;5.7%&lt;/strong&gt; (2/35)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Historical Biography (Napoleon)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;88.6%&lt;/strong&gt; (31/35)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;97.1%&lt;/strong&gt; (34/35)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;2.9%&lt;/strong&gt; (1/35)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On real-world software codebases, combining breadcrumb AST chunking with RRF achieved &lt;strong&gt;100% at-least-partial evidence capture and 0% total retrieval failure&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try the In-Browser WASM Demo (Zero Setup)
&lt;/h2&gt;

&lt;p&gt;Before configuring your local CLI, you can test the full pipeline in an air-gapped WebAssembly environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔗 &lt;strong&gt;Live Demo&lt;/strong&gt;: &lt;a href="https://rag.masihmoafi.com" rel="noopener noreferrer"&gt;https://rag.masihmoafi.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔒 &lt;strong&gt;100% Private&lt;/strong&gt;: Runs quantized ONNX models (&lt;code&gt;all-MiniLM-L6-v2&lt;/code&gt;) via Transformers.js in a dedicated Web Worker.&lt;/li&gt;
&lt;li&gt;💾 &lt;strong&gt;Local IndexedDB Persistence&lt;/strong&gt;: All documents, chunks, and vector tables persist locally in your browser with &lt;strong&gt;zero backend server requests&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick Start &amp;amp; Installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Install via &lt;code&gt;uv&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/MasihMoafi/rag-mcp
&lt;span class="nb"&gt;cd &lt;/span&gt;rag-mcp
uv &lt;span class="nb"&gt;sync&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the automated test suite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;.venv/bin/python &lt;span class="nt"&gt;-m&lt;/span&gt; pytest tests/ &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Connect to Your Coding Agent
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Claude Code (&lt;code&gt;~/.claude.json&lt;/code&gt;):
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/absolute/path/to/rag-mcp/.venv/bin/python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/absolute/path/to/rag-mcp/server.py"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Codex CLI (&lt;code&gt;~/.codex/config.toml&lt;/code&gt;):
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[mcp_servers.rag]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/absolute/path/to/rag-mcp/.venv/bin/python"&lt;/span&gt;
&lt;span class="py"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"/absolute/path/to/rag-mcp/server.py"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Cursor (&lt;code&gt;Settings &amp;gt; Features &amp;gt; MCP&lt;/code&gt;):
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name&lt;/strong&gt;: &lt;code&gt;rag&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type&lt;/strong&gt;: &lt;code&gt;command&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command&lt;/strong&gt;: &lt;code&gt;/absolute/path/to/rag-mcp/.venv/bin/python /absolute/path/to/rag-mcp/server.py&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Links &amp;amp; Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;⭐️ &lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/MasihMoafi/rag-mcp" rel="noopener noreferrer"&gt;github.com/MasihMoafi/rag-mcp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Live WASM Demo&lt;/strong&gt;: &lt;a href="https://rag.masihmoafi.com" rel="noopener noreferrer"&gt;rag.masihmoafi.com&lt;/a&gt; | &lt;a href="https://rag.masihmoafi.tech" rel="noopener noreferrer"&gt;rag.masihmoafi.tech&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📖 &lt;strong&gt;Deep-Dive Technical Report&lt;/strong&gt;: &lt;a href="https://masihmoafi.com/projects/rag-mcp" rel="noopener noreferrer"&gt;masihmoafi.com/projects/rag-mcp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👤 &lt;strong&gt;Author&lt;/strong&gt;: &lt;a href="https://masihmoafi.com" rel="noopener noreferrer"&gt;Masih Moafi&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to star the repo, test the WASM demo with your own files, or contribute optimizations!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>python</category>
      <category>rust</category>
    </item>
    <item>
      <title>How I Saved My Laptop CPU After a Bad Thermal Paste Job (Windows + Linux)</title>
      <dc:creator>Masih Maafi</dc:creator>
      <pubDate>Wed, 29 Jul 2026 16:44:38 +0000</pubDate>
      <link>https://dev.to/masihmoafi/how-i-saved-my-laptop-cpu-after-a-bad-thermal-paste-job-windows-linux-23ab</link>
      <guid>https://dev.to/masihmoafi/how-i-saved-my-laptop-cpu-after-a-bad-thermal-paste-job-windows-linux-23ab</guid>
      <description>&lt;h2&gt;
  
  
  The Problem: A "Fixed" Laptop That Got Worse
&lt;/h2&gt;

&lt;p&gt;About three years of heavy use in, I took my laptop in for a routine cleaning. Fan vents clogged, running hot — the usual. The technician cleaned it up and replaced the thermal paste. Standard stuff.&lt;/p&gt;

&lt;p&gt;Except it wasn't. After getting it back, something was wrong.&lt;/p&gt;

&lt;p&gt;In games like &lt;strong&gt;Elden Ring&lt;/strong&gt; and &lt;strong&gt;Sekiro: Shadows Die Twice&lt;/strong&gt; — demanding but not unusually so — my CPU used to top out around &lt;strong&gt;75°C&lt;/strong&gt;. Warm, manageable, stable. After the service? It was sitting &lt;strong&gt;above 90°C consistently&lt;/strong&gt;. Throttling. Spiking. Never coming down.&lt;/p&gt;

&lt;p&gt;The thermal paste had been applied badly. Too much, wrong type, poor spread — I'll never know exactly, but the result was clear: my laptop was now thermally worse than before it was serviced.&lt;/p&gt;

&lt;h2&gt;
  
  
  No Warranty, No Local Expert
&lt;/h2&gt;

&lt;p&gt;Here's where it got frustrating: I hadn't bought this laptop in my home country. The local warranty system doesn't cover that. Refused, end of story.&lt;/p&gt;

&lt;p&gt;And finding a technician I could actually trust with a disassembly? That's harder than it sounds. I've seen what bad service jobs do — I was living with one. So I decided to handle it myself. Not the thermal paste (yet) — but the temperatures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Windows — 99% CPU Cap (Surprisingly Effective)
&lt;/h2&gt;

&lt;p&gt;The quickest win was on Windows. In &lt;strong&gt;Power Options → Advanced → Processor power management&lt;/strong&gt;, I set the &lt;strong&gt;Maximum processor state to 99%&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's it. One percent less.&lt;/p&gt;

&lt;p&gt;This disables Intel's Turbo Boost — a feature that temporarily spikes the CPU far above its base clock for short bursts. It sounds drastic, but in practice: &lt;strong&gt;zero noticeable quality loss in Elden Ring or Sekiro&lt;/strong&gt;, and temperatures dropped back below &lt;strong&gt;70°C&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The CPU still runs at full base clock. Turbo is a headroom feature, not a sustained performance feature. For gaming at 1080p, you don't need it.&lt;/p&gt;

&lt;p&gt;This bought me stability on Windows. But I spend most of my time on Linux — and there, I wanted something more robust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Linux — A 3-Tier Thermal Manager
&lt;/h2&gt;

&lt;p&gt;On Linux, the equivalent of "disable turbo" is one line (&lt;code&gt;echo 1 &amp;gt; /sys/devices/system/cpu/intel_pstate/no_turbo&lt;/code&gt;), but I wanted something smarter: automatic, tiered, and running before I even log in.&lt;/p&gt;

&lt;p&gt;I discovered the &lt;strong&gt;&lt;code&gt;msi-ec&lt;/code&gt;&lt;/strong&gt; kernel module — a DKMS driver that exposes the MSI laptop's Embedded Controller, including a &lt;code&gt;cooler_boost&lt;/code&gt; sysfs node that does exactly what &lt;code&gt;Fn+F8&lt;/code&gt; does: forces the fans to maximum.&lt;/p&gt;

&lt;p&gt;With that, I built a 3-tier system:&lt;/p&gt;

&lt;h3&gt;
  
  
  Tier 1 — Fan Boost at 70°C (System Service, Pre-Login)
&lt;/h3&gt;

&lt;p&gt;A root-level &lt;code&gt;systemd&lt;/code&gt; service monitors CPU temperature every 2 seconds. When it hits &lt;strong&gt;70°C&lt;/strong&gt;, it writes &lt;code&gt;on&lt;/code&gt; to &lt;code&gt;/sys/devices/platform/msi-ec/cooler_boost&lt;/code&gt;. When temp drops back below &lt;strong&gt;68°C&lt;/strong&gt; (hysteresis to avoid flutter), it writes &lt;code&gt;off&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This runs before any user logs in — at the system level.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# /usr/local/sbin/msi-cooler-boost (excerpt)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-ge&lt;/span&gt; 70 &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$boosting&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;on &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /sys/devices/platform/msi-ec/cooler_boost
    &lt;span class="nv"&gt;boosting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
    logger &lt;span class="nt"&gt;-t&lt;/span&gt; msi-cooler-boost &lt;span class="s2"&gt;"ON at &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;temp&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;°C"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tier 2 — CPU Frequency Throttle at 75°C (thermald)
&lt;/h3&gt;

&lt;p&gt;Intel's &lt;code&gt;thermald&lt;/code&gt; daemon runs in adaptive mode by default, using the platform's own DPTF tables. I supplemented it with a custom XML config that adds a &lt;strong&gt;passive CPU frequency trip point at 75°C&lt;/strong&gt; — so if the fans alone aren't enough, &lt;code&gt;thermald&lt;/code&gt; starts walking down the CPU's frequency states.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;TripPoint&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;SensorType&amp;gt;&lt;/span&gt;x86_pkg_temp&lt;span class="nt"&gt;&amp;lt;/SensorType&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Temperature&amp;gt;&lt;/span&gt;75000&lt;span class="nt"&gt;&amp;lt;/Temperature&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;type&amp;gt;&lt;/span&gt;passive&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;CoolingDevice&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;type&amp;gt;&lt;/span&gt;cpufreq&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;influence&amp;gt;&lt;/span&gt;100&lt;span class="nt"&gt;&amp;lt;/influence&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/CoolingDevice&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/TripPoint&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps the existing adaptive DPTF policy intact — the custom config is additive, not replacing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tier 3 — Kill &amp;amp; Notify at 81°C (User Service)
&lt;/h3&gt;

&lt;p&gt;A user-level &lt;code&gt;systemd&lt;/code&gt; service (runs after login) monitors the same temp sensor. If things still reach &lt;strong&gt;81°C&lt;/strong&gt;, it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Finds the top CPU-consuming user process&lt;/li&gt;
&lt;li&gt;Sends &lt;code&gt;SIGTERM&lt;/code&gt;, waits 2s, then &lt;code&gt;SIGKILL&lt;/code&gt; if needed&lt;/li&gt;
&lt;li&gt;Fires a desktop notification so you know what was terminated
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Graceful kill with fallback to SIGKILL&lt;/span&gt;
&lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-15&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pid&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;sleep &lt;/span&gt;2
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-0&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pid&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-9&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pid&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi
&lt;/span&gt;notify-send &lt;span class="nt"&gt;-u&lt;/span&gt; critical &lt;span class="s2"&gt;"CPU Temp Spike: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;temp&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;°C"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;"Terminated '&lt;/span&gt;&lt;span class="nv"&gt;$comm&lt;/span&gt;&lt;span class="s2"&gt;' to prevent overheating."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Full Picture
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Trigger&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Runs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;≥ 70°C&lt;/td&gt;
&lt;td&gt;Cooler boost ON (fans max)&lt;/td&gt;
&lt;td&gt;Before login&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;≥ 75°C&lt;/td&gt;
&lt;td&gt;CPU freq throttle&lt;/td&gt;
&lt;td&gt;Always&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;≥ 81°C&lt;/td&gt;
&lt;td&gt;Kill process + notify&lt;/td&gt;
&lt;td&gt;After login&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Everything is automatic and persistent across reboots:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;msi-ec&lt;/code&gt; loads via &lt;code&gt;/etc/modules-load.d/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;udev rule makes the &lt;code&gt;cooler_boost&lt;/code&gt; node group-writable on load&lt;/li&gt;
&lt;li&gt;System service is enabled in &lt;code&gt;multi-user.target&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;User service is enabled via &lt;code&gt;systemctl --user enable&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install It Yourself
&lt;/h2&gt;

&lt;p&gt;Everything — scripts, service files, thermald config, and a one-shot &lt;code&gt;install.sh&lt;/code&gt; — is in the GitHub repo:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/MasihMoafi/msi-linux-thermal" rel="noopener noreferrer"&gt;github.com/MasihMoafi/msi-linux-thermal&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The install script handles msi-ec DKMS build, udev rules, group setup, and service registration in one run. Tested on Ubuntu 24.04 with kernel 7.x.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Check the &lt;a href="https://github.com/BeardOverflow/msi-ec" rel="noopener noreferrer"&gt;msi-ec supported device list&lt;/a&gt; before installing. Your MSI model needs to be on it for the cooler boost tier to work. The thermald and kill tiers work on any Intel laptop.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Sometimes the right fix isn't opening the chassis — it's writing a better daemon.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>hardware</category>
      <category>tutorial</category>
      <category>gaming</category>
    </item>
    <item>
      <title>Elpis: a terminal environment that keeps AI coding agent's context window free</title>
      <dc:creator>Masih Maafi</dc:creator>
      <pubDate>Sun, 26 Jul 2026 04:50:46 +0000</pubDate>
      <link>https://dev.to/masihmoafi/elpis-a-terminal-environment-that-keeps-ai-coding-agents-context-window-free-2g5l</link>
      <guid>https://dev.to/masihmoafi/elpis-a-terminal-environment-that-keeps-ai-coding-agents-context-window-free-2g5l</guid>
      <description>&lt;p&gt;I build &lt;a href="https://github.com/MasihMoafi/Elpis" rel="noopener noreferrer"&gt;Elpis&lt;/a&gt; — a terminal environment for coding agents forked from OpenAI's Codex CLI.&lt;/p&gt;

&lt;p&gt;One problem I keep running into with long agent sessions: the context window fills up with the &lt;em&gt;history of how the agent got to the answer&lt;/em&gt;, not the answer itself. Transcripts, file reads, searches, command output, dead ends — all of it accumulates, and every new request pays for all of it.&lt;/p&gt;

&lt;p&gt;Elpis exists to fix that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Elpis
&lt;/h2&gt;

&lt;p&gt;Elpis is a terminal environment for coding agents. You put an agent into Elpis, and it becomes Elpis.&lt;/p&gt;

&lt;p&gt;The agent runs the model loop. Elpis owns the environment around it: &lt;strong&gt;context, continuity, memory, permissions, evidence, and explicit provider choice.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Elpises
&lt;/h3&gt;

&lt;p&gt;Elpis is the shared environment, not any one agent. Put an agent inside it and the agent inherits the same context, memory, permissions, evidence, and control.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6y8w5dd3b0kz9e5265so.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6y8w5dd3b0kz9e5265so.png" alt="Elpises working on different paths of one shared Elpis environment" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Multiple Elpises working from those shared roots is a direction for the project — not a claim that multi-agent control ships in &lt;code&gt;v0.1.1&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Elpis
&lt;/h2&gt;

&lt;p&gt;Long agent sessions accumulate transcripts, file reads, searches, command output, and dead ends. The useful state gets buried in the history of how the agent reached it, while every request pays for more context.&lt;/p&gt;

&lt;p&gt;Elpis separates working context from durable evidence. The next request receives a small, inspectable working set; the exact record stays on disk and is retrieved only when needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One controlled comparison — same task, same prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Free context at end&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Elpis&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;93%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Codex&lt;/td&gt;
&lt;td&gt;73%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Screenshots from that comparison&lt;/p&gt;

&lt;p&gt;Start:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwvmubah0un88mhjn3hsm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwvmubah0un88mhjn3hsm.png" alt="Starting Elpis" width="799" height="116"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkjmthzg6pcu2lew7lx48.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkjmthzg6pcu2lew7lx48.png" alt="Starting Codex with the same prompt" width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;End — Elpis, 93% free:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnvntpry0o2nk652rmiwd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnvntpry0o2nk652rmiwd.png" alt="Elpis end state" width="799" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;End — Codex, 73% free:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnld85p8igcn22vfgd1ey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnld85p8igcn22vfgd1ey.png" alt="Codex end state" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is one recorded workflow, not a claim that every task reduces the same amount.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Managed context&lt;/strong&gt; — Ace performs meaning-aware post-turn pruning while Codex's inherited safety cap bounds exceptionally large tool output. Inspect pruning with &lt;code&gt;/prune&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portable continuity&lt;/strong&gt; — goal and checkpoint state survive compaction and restarts, so work resumes without replaying the full transcript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visible context&lt;/strong&gt; — the Context Ledger shows exactly which files are in the working set, with ctrl+clickable paths for inspection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Durable evidence and bounded memory&lt;/strong&gt; — exact conversations, terminal events, and artifacts remain on disk; reusable memory stays selective, size-capped, and attributable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit provider choice&lt;/strong&gt; — use OpenAI, Anthropic, Gemini, or OpenRouter without silently routing one provider through another.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visible safety controls&lt;/strong&gt; — Read Only, Default, and Full Access modes keep file changes, commands, approvals, and results inspectable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No analytics by default&lt;/strong&gt; — Elpis does not upload usage analytics, and all OpenTelemetry exporters default to off. Telemetry is sent only if you explicitly configure an OTEL exporter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local read-only RAG&lt;/strong&gt; — from a source checkout, &lt;code&gt;scripts/setup-rag.sh&lt;/code&gt; adds semantic search over local knowledge without granting write access.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Evidence — full context-management session
&lt;/h2&gt;

&lt;p&gt;The clip above is a 25-second highlight. This one is the full uncut session: you can watch the context loop run — post-turn pruning, the Context Ledger updating, goal and checkpoint state surviving compaction — and see the 93 vs 73% numbers appear in real time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quickstart
&lt;/h2&gt;

&lt;p&gt;Linux x86_64:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/MasihMoafi/Elpis/main/scripts/install-elpis.sh | bash
elpis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On first launch, choose a provider and sign in or enter its API key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current state
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;v0.1.1&lt;/code&gt;, Linux x86_64. Not in this release: macOS, Windows, &lt;code&gt;/auto&lt;/code&gt; routing, multi-agent control, voice input, LSP integration.&lt;/p&gt;

&lt;p&gt;The execution foundation — terminal UI, patches, permissions, sandboxing, sessions — derives from OpenAI's Apache-2.0 Codex CLI. Elpis adds the context, continuity, memory, retrieval, and provider-control layer around it.&lt;/p&gt;




&lt;p&gt;GitHub: &lt;strong&gt;&lt;a href="https://github.com/MasihMoafi/Elpis" rel="noopener noreferrer"&gt;https://github.com/MasihMoafi/Elpis&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Docs: &lt;strong&gt;&lt;a href="https://masihmoafi.github.io/Elpis/" rel="noopener noreferrer"&gt;https://masihmoafi.github.io/Elpis/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>productivity</category>
      <category>rust</category>
    </item>
    <item>
      <title>My AI coding agent reverted a core feature in one buried line — and its commit messages lied about it</title>
      <dc:creator>Masih Maafi</dc:creator>
      <pubDate>Fri, 24 Jul 2026 07:51:04 +0000</pubDate>
      <link>https://dev.to/masihmoafi/my-ai-coding-agent-reverted-a-core-feature-in-one-buried-line-and-its-commit-messages-lied-about-dcn</link>
      <guid>https://dev.to/masihmoafi/my-ai-coding-agent-reverted-a-core-feature-in-one-buried-line-and-its-commit-messages-lied-about-dcn</guid>
      <description>&lt;p&gt;&lt;em&gt;2026-07-23 — Masih Moafi&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I build &lt;a href="https://github.com/MasihMoafi/Elpis" rel="noopener noreferrer"&gt;Elpis&lt;/a&gt;, a terminal coding agent forked&lt;br&gt;
from Codex-rs, focused on one thing: keeping your context window empty. Its whole&lt;br&gt;
value is aggressive, meaning-aware context reduction — in side-by-side runs on the&lt;br&gt;
same task it finishes with ~93% of the context window free where stock Codex ends&lt;br&gt;
at ~73%.&lt;/p&gt;

&lt;p&gt;I build it &lt;em&gt;with&lt;/em&gt; AI agents. This week I audited their work. What I found changed&lt;br&gt;
how I treat every AI-generated commit, and I have the diffs to prove all of it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Act 1: every fresh install was broken, and nobody knew
&lt;/h2&gt;

&lt;p&gt;The v0.1.0 release published a binary plus a sha256 checksum file. The CI step that&lt;br&gt;
generated it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;sha256sum dist/elpis-linux-x86_64 &amp;gt; dist/elpis-linux-x86_64.sha256&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sha256sum&lt;/code&gt; records the path you give it. So the published checksum file said&lt;br&gt;
&lt;code&gt;dist/elpis-linux-x86_64&lt;/code&gt; — but the installer downloads assets flat into a temp dir&lt;br&gt;
and runs &lt;code&gt;sha256sum --check&lt;/code&gt; there. No &lt;code&gt;dist/&lt;/code&gt; exists. &lt;strong&gt;Every single fresh install&lt;br&gt;
failed checksum verification.&lt;/strong&gt; The fix is a &lt;code&gt;cd&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;(cd dist &amp;amp;&amp;amp; sha256sum elpis-linux-x86_64 &amp;gt; elpis-linux-x86_64.sha256)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Annoying, but honest — a normal bug. The next two were not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Act 2: features that existed, hidden on purpose
&lt;/h2&gt;

&lt;p&gt;Users (me) noticed &lt;code&gt;/goal&lt;/code&gt; and &lt;code&gt;/fork&lt;/code&gt; — both fully implemented — didn't exist in&lt;br&gt;
the app. Git said otherwise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3584023 fix(tui): hide /fork from the visible command list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An agent had implemented the commands, then &lt;em&gt;hidden them from the command popup&lt;/em&gt;,&lt;br&gt;
then &lt;strong&gt;written a test that asserted they must stay hidden&lt;/strong&gt; — a test literally&lt;br&gt;
named &lt;code&gt;removed_commands_are_not_visible_or_parseable&lt;/code&gt;, listing &lt;code&gt;"fork"&lt;/code&gt; and&lt;br&gt;
&lt;code&gt;"goal"&lt;/code&gt; as removed. Nothing was removed. The features sat there, invisible,&lt;br&gt;
guarded by a test enforcing the lie.&lt;/p&gt;
&lt;h2&gt;
  
  
  Act 3: the one-line revert buried in a merge
&lt;/h2&gt;

&lt;p&gt;This is the one that matters. Elpis compacts old tool outputs out of live context.&lt;br&gt;
One commit tightened the threshold, with a clear message and a test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;9637b19 fix(core): enable instant history compaction for all completed tool outputs &amp;gt;400 chars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MAX_INLINE_TOOL_OUTPUT_CHARS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then came a merge commit titled &lt;code&gt;feat: merge /context command updates from&lt;br&gt;
agent/context-command&lt;/code&gt; (&lt;code&gt;3c6d19e&lt;/code&gt;). Its entire change to this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-const MAX_INLINE_TOOL_OUTPUT_CHARS: usize = 400;
&lt;/span&gt;&lt;span class="gi"&gt;+const MAX_INLINE_TOOL_OUTPUT_CHARS: usize = 1200;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One line. Not mentioned in the commit message. It reverted the core&lt;br&gt;
context-saving behavior the previous commit shipped — the thing my project exists&lt;br&gt;
to do — while the message talked about &lt;code&gt;/context&lt;/code&gt; command updates. The test from&lt;br&gt;
&lt;code&gt;9637b19&lt;/code&gt; failed from that moment on, permanently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Act 4: why CI never caught it — the tag was moved to a commit that never passed
&lt;/h2&gt;

&lt;p&gt;"But the release was green!" It was — for a different commit. The passing release&lt;br&gt;
run (&lt;code&gt;29534784054&lt;/code&gt;) ran at commit &lt;code&gt;e841704&lt;/code&gt;. The &lt;code&gt;v0.1.0&lt;/code&gt; tag pointed at&lt;br&gt;
&lt;code&gt;7dce07c&lt;/code&gt;, several commits later. No passing run ever existed for the tagged&lt;br&gt;
commit. The project docs, meanwhile, claimed the tag was at yet a &lt;em&gt;third&lt;/em&gt; commit&lt;br&gt;
(&lt;code&gt;eba95a0&lt;/code&gt;). Three different answers to "what did we ship?" — all written down&lt;br&gt;
with confidence, at most one of them true. On top of that, the curated CI suite&lt;br&gt;
ran only the binary-target tests; the library tests — where the failing test and&lt;br&gt;
a long-stale UI snapshot lived — never executed in CI at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I changed
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Commit messages are claims, not evidence.&lt;/strong&gt; I now verify agent commits against
the diff, not the description. The description is marketing written by the thing
being audited.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merges get read line-by-line.&lt;/strong&gt; A merge diff is the best place to hide a
payload; "merge X updates" reviewed nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tags are created by CI-gated flows only&lt;/strong&gt;, and docs never pin "we shipped at
hash X" — the tag itself is the record.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests are tripwires — keep them honest and run all of them.&lt;/strong&gt; The failing
threshold test is what exposed the revert. It sat failing, unexecuted by CI,
for days. A test suite you don't run is a story you tell yourself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A human owns functional verification.&lt;/strong&gt; My agents now build, install, and hand
me a plain checklist. They are forbidden from claiming "verified" — that word is
mine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standing rules live in files, not chat.&lt;/strong&gt; Every instruction I gave an agent in
conversation died with that session. The rules that stuck are the ones in
version-controlled &lt;code&gt;AGENTS.md&lt;/code&gt; files the next agent is forced to read.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Elpis v0.1.0 is re-tagged, re-released, and installs clean on a bare machine. The&lt;br&gt;
history is rewritten to say only true things. If a terminal agent that treats your&lt;br&gt;
context window as sacred sounds useful, it's here:&lt;br&gt;
&lt;strong&gt;&lt;a href="https://github.com/MasihMoafi/Elpis" rel="noopener noreferrer"&gt;https://github.com/MasihMoafi/Elpis&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Draft Show HN title:&lt;/em&gt; &lt;strong&gt;Show HN: Elpis — a Codex fork that keeps 90%+ of your&lt;br&gt;
context window free&lt;/strong&gt; — first comment: the story above, linked.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>rust</category>
      <category>codereview</category>
    </item>
    <item>
      <title>RoPE: How 2D Rotations Solved Transformer Long-Context</title>
      <dc:creator>Masih Maafi</dc:creator>
      <pubDate>Wed, 22 Jul 2026 19:13:19 +0000</pubDate>
      <link>https://dev.to/masihmoafi/rope-or-how-2d-rotations-solved-transformer-long-context-2aia</link>
      <guid>https://dev.to/masihmoafi/rope-or-how-2d-rotations-solved-transformer-long-context-2aia</guid>
      <description>&lt;h1&gt;
  
  
  Why 2D Rotations Solved Transformer Long-Context: A Mechanics-First Look at RoPE
&lt;/h1&gt;

&lt;p&gt;Attention requires two things from positional encodings:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Relative Distance Sensitivity:&lt;/strong&gt; Token 

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 attending to Token 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 should care primarily about how far apart they are (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
), not where they sit globally in the context window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature Preservation:&lt;/strong&gt; Injecting position information must not destroy or mangle the semantic embedding features learned by the model.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Original absolute positional encodings added static sine/cosine waves directly to input embeddings:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathbf"&gt;x&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathbf"&gt;e&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathbf"&gt;p&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;This forced the model to burn parameter capacity un-mixing semantic meaning (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
) from positional location (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathbf"&gt;p&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
). Worse, if a model was trained on sequence lengths up to 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;N&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2048&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, position 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2049&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 presented an unseen vector 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;p&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2049&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, causing immediate generation collapse.&lt;/p&gt;

&lt;p&gt;Subsequent approaches tried adding relative bias terms 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 directly into the attention matrix 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;Q&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;K&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. While functionally effective, modifying the 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;N&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 matrix broke kernel-level GPU fusions like FlashAttention and introduced huge memory overheads.&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;Rotary Position Embedding (RoPE)&lt;/strong&gt; (Su et al., 2021). Instead of &lt;em&gt;adding&lt;/em&gt; positional vectors or &lt;em&gt;patching&lt;/em&gt; the attention matrix, RoPE &lt;strong&gt;rotates&lt;/strong&gt; the Query and Key vectors in 2D sub-planes before computing attention.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Geometry: Inner Products Under Rotation
&lt;/h2&gt;

&lt;p&gt;To make attention relative, we want an encoding function 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathbf"&gt;x&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 applied to a vector 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 at position 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 such that the dot product between Query at position 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and Key at position 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 depends &lt;strong&gt;only on the relative offset (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
)&lt;/strong&gt;:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;⟨&lt;/span&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathbf"&gt;q&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathbf"&gt;k&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)⟩&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;g&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathbf"&gt;q&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;k&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;How do you preserve vector norms while encoding an angle shift? &lt;strong&gt;Complex space rotations.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a 2D plane, rotating a vector 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;x&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;[&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;&lt;span class="mclose"&gt;]&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 by an angle 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is represented by the orthogonal rotation matrix:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;Θ&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size1"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size1"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;When you compute the dot product between a rotated Query at position 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and a rotated Key at position 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size1"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;Θ&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;q&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size1"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size1"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;Θ&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;k&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size1"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathbf"&gt;q&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size1"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;Θ&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size1"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;Θ&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;k&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathbf"&gt;q&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;Θ&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;n&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Because 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, &lt;strong&gt;the absolute positions 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 cancel out completely.&lt;/strong&gt; The resulting attention weight is strictly a function of the distance (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
).&lt;/p&gt;

&lt;p&gt;For a 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
-dimensional vector, RoPE splits the channels into 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mord"&gt;/2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 pairs of 2D planes, applying a different rotation frequency 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 to each pair:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;Θ&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1000&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;span class="mord mtight"&gt;/&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;∈&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;[&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="minner"&gt;…&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mord"&gt;/2&lt;/span&gt;&lt;span class="mclose"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  High-Performance Vectorized PyTorch Implementation
&lt;/h2&gt;

&lt;p&gt;In practice, explicitly constructing full block-diagonal rotation matrices for every head and token is slow. We can implement RoPE efficiently using the complex number representation or the real-valued slice trick:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;Θ&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;x&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;x&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⊙&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord"&gt;Θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;~&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⊙&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord"&gt;Θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;where 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;~&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;[&lt;/span&gt;&lt;span class="mord"&gt;−&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;−&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="minner"&gt;…&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mclose"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;/p&gt;

&lt;p&gt;Here is a clean, production-ready PyTorch implementation:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
python
import torch
import torch.nn as nn

class RotaryPositionalEmbedding(nn.Module):
    """
    Rotary Position Embedding (RoPE) for multi-head attention.
    Applies 2D plane rotations across d_model / 2 feature pairs.
    """
    def __init__(self, dim: int, max_seq_len: int = 8192, base: float = 10000.0):
        super().__init__()
        self.dim = dim
        self.base = base

        # Compute frequency bands theta_i = 10000^(-2(i-1)/d)
        inv_freq = 1.0 / (self.base ** (torch.arange(0, dim, 2).float() / dim))
        self.register_buffer("inv_freq", inv_freq, persistent=False)

        # Precompute cosine and sine cache for max_seq_len
        self._build_cache(max_seq_len)

    def _build_cache(self, max_seq_len: int):
        t = torch.arange(max_seq_len, dtype=self.inv_freq.dtype)
        # Outer product: [seq_len, dim / 2]
        freqs = torch.outer(t, self.inv_freq)

        # Duplicate frequencies to match feature dimensions: [seq_len, dim]
        emb = torch.cat((freqs, freqs), dim=-1)

        self.register_buffer("cos_cached", emb.cos(), persistent=False)
        self.register_buffer("sin_cached", emb.sin(), persistent=False)

    def _rotate_half(self, x: torch.Tensor) -&amp;gt; torch.Tensor:
        """Splits vector in half and negates/swaps halves: [-x2, x1]"""
        x1 = x[..., : self.dim // 2]
        x2 = x[..., self.dim // 2 :]
        return torch.cat((-x2, x1), dim=-1)

    def forward(self, x: torch.Tensor, seq_len: int) -&amp;gt; torch.Tensor:
        """
        Args:
            x: Tensor of shape [batch_size, num_heads, seq_len, head_dim]
            seq_len: Current sequence length
        Returns:
            Tensor with RoPE applied to Query or Key
        """
        cos = self.cos_cached[:seq_len, :].unsqueeze(0).unsqueeze(1) # [1, 1, seq_len, dim]
        sin = self.sin_cached[:seq_len, :].unsqueeze(0).unsqueeze(1) # [1, 1, seq_len, dim]

        # Apply elementwise rotation formula
        return (x * cos) + (self._rotate_half(x) * sin)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>python</category>
      <category>machinelearning</category>
      <category>ai</category>
      <category>pytorch</category>
    </item>
    <item>
      <title>Financial Market Analysis (Double-Tower Transformer)</title>
      <dc:creator>Masih Maafi</dc:creator>
      <pubDate>Fri, 10 Jul 2026 12:09:00 +0000</pubDate>
      <link>https://dev.to/masihmoafi/financial-market-analysis-double-tower-transformer-2nih</link>
      <guid>https://dev.to/masihmoafi/financial-market-analysis-double-tower-transformer-2nih</guid>
      <description>&lt;h2&gt;
  
  
  Content
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Intro - What is it? Briefly
&lt;/h3&gt;

&lt;p&gt;A predictive machine learning system explicitly designed to generate profitable trading signals from high-frequency (1-minute) EUR/USD forex data. The flagship focus of this repository is a custom Double-Tower Gated Transformer Network (GTN) built to predict Take Profit / Stop Loss (TP/SL) strikes.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Does it Work? Technical Spec.
&lt;/h3&gt;

&lt;p&gt;The data pipeline processes 1-minute OHLC bars to map out realistic TP/SL bounds over a 24-hour lookahead rather than using fixed time horizons. &lt;br&gt;
The core model, the &lt;strong&gt;Gated Transformer Network (GTN)&lt;/strong&gt;, utilizes a dual-tower architecture that separates feature interactions from temporal sequences. It replaces traditional sinusoidal encodings with learned time embeddings to capture market regime shifts and session overlaps (London, NY, Tokyo). &lt;br&gt;
To combat severe class imbalance (the model's tendency to constantly predict "keep/hold"), the network optimizes against a custom cost matrix and weighted cross-entropy loss.&lt;br&gt;
![[Pasted image 20260710145647.png]]&lt;/p&gt;

&lt;h3&gt;
  
  
  What Sets This Project Apart?
&lt;/h3&gt;

&lt;p&gt;Instead of optimizing for standard classification accuracy, the pipeline tackles raw profitability. The intent is for models to learn the structural mechanics of price action, balancing Risk/Reward ratios (e.g., 1:2) against real-world MetaTrader 5 execution constraints (enforcing next-candle open entries and proper UTF-16-LE signal formatting).&lt;/p&gt;

&lt;h3&gt;
  
  
  Evals and test Series
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primary Metric&lt;/strong&gt;: Composite Score = &lt;code&gt;(buy_precision + sell_precision)/2 - 0.25 * |buy_precision - sell_precision|&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best GTN Score&lt;/strong&gt;: 0.36 Composite&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Baseline (LightGBM)&lt;/strong&gt;: 0.37 Composite (prone to overfitting the 'keep' class).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status&lt;/strong&gt;: The dual-tower architecture maps the feature-space better than tree-based models, but converting high composite scores to live P&amp;amp;L in MT5 remains the primary hurdle.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Future Dev
&lt;/h3&gt;

&lt;p&gt;find out why despite everything we underfitted? &lt;br&gt;
I did manage to overfit on a single batch of data; however, based on the scaling laws paper, I tried to do 1 epoch with proportionate maximum parameters that I can efficiently fit into the 80GB VRAM of an A100 GPU or 2*40GB VRAM of A100 depending of availability. &lt;/p&gt;

&lt;p&gt;reference paper: &lt;a href="https://arxiv.org/pdf/2103.14438" rel="noopener noreferrer"&gt;https://arxiv.org/pdf/2103.14438&lt;/a&gt;&lt;br&gt;
Gated Transformer Networks for Multivariate Time Series Classification&lt;/p&gt;

</description>
      <category>ai</category>
      <category>deeplearning</category>
      <category>fintech</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Transformers From Scratch In Code</title>
      <dc:creator>Masih Maafi</dc:creator>
      <pubDate>Fri, 10 Jul 2026 12:08:58 +0000</pubDate>
      <link>https://dev.to/masihmoafi/transformers-from-scratch-in-code-4o6g</link>
      <guid>https://dev.to/masihmoafi/transformers-from-scratch-in-code-4o6g</guid>
      <description>&lt;p&gt;map:&lt;br&gt;
1) hyperparams block&lt;br&gt;
2) data block&lt;br&gt;
    loss tracking function&lt;br&gt;
3) Single Attention Head Class (head_size)&lt;br&gt;
    at first B, T, C = shape&lt;br&gt;
4) head_size = n_embd // num_head&lt;br&gt;
    wei = attention scores matrix&lt;/p&gt;

&lt;h3&gt;
  
  
  Qs for recall:
&lt;/h3&gt;

&lt;p&gt;what's d_head's formula? &lt;br&gt;
what's wei and its formula? &lt;/p&gt;

&lt;p&gt;![[transformers.png]]&lt;/p&gt;

&lt;h3&gt;
  
  
  The Big Tensor Shape Correction ($B, T, C$)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;**B = how many independent sequences will we process in parallel?&lt;/li&gt;
&lt;li&gt;**T = block_size = 256 # what is the maximum context length for predictions? (num_tokens_needed_to_predict_the_next)&lt;/li&gt;
&lt;li&gt;**C = channels = block-size = num_features = n_embd&lt;/li&gt;
&lt;li&gt;n_embd = &lt;/li&gt;
&lt;li&gt;n_head = &lt;/li&gt;
&lt;li&gt;n_layer = 
When the input $X$ enters &lt;code&gt;Head.forward(x)&lt;/code&gt;, its shape is $(B, T, C)$ where $C = \text{n_embd}$.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you pass it through your $Q, K, V$ linear layers, you project it to a &lt;strong&gt;new channel dimension&lt;/strong&gt;, let's call it $D$ ($\text{head_size}$).&lt;/p&gt;

&lt;p&gt;$$\large\text{head_size} = \frac{\text{n_embd}}{\text{n_head}}$$&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;$Q(X) \rightarrow (B, T, D)$&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;$K(X) \rightarrow (B, T, D)$&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;$V(X) \rightarrow (B, T, D)$&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your attention score matrix (&lt;code&gt;wei&lt;/code&gt;) is the dot product of $Q$ and $K^T$. To do this &lt;strong&gt;across batches&lt;/strong&gt;, you transpose only the last two dimensions of $K$:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;$$\large\text{wei} = Q \cdot K^T \rightarrow (B, T, D) \times (B, D, T) = (B, T, T)$$&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;wei&lt;/code&gt; is $(B, T, T)$. This represents how much every token in the sequence cares about every other token. This is where you apply &lt;code&gt;torch.tril&lt;/code&gt; and &lt;code&gt;softmax&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, you multiply &lt;code&gt;wei&lt;/code&gt; by $V$:&lt;/p&gt;

&lt;p&gt;$$\large\text{out} = \text{wei} \cdot V \rightarrow (B, T, T) \times (B, T, D) = (B, T, D)$$&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;__init__(self, head_size)&lt;/code&gt;&lt;/strong&gt;: This is called &lt;em&gt;once&lt;/em&gt; when you create the layer. It defines &lt;strong&gt;what structural components live inside the head&lt;/strong&gt; (the weights, matrices, and configuration). It only needs &lt;code&gt;head_size&lt;/code&gt; because it's just setting up the architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;forward(self, x)&lt;/code&gt;&lt;/strong&gt;: This is called &lt;em&gt;every single time you pass data&lt;/em&gt; through the layer during training or inference. &lt;strong&gt;&lt;code&gt;x&lt;/code&gt; is the actual tensor of data moving through the network.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1. Instantiation (uses &lt;strong&gt;init&lt;/strong&gt;)
&lt;/h3&gt;

&lt;h3&gt;
  
  
  2. Execution (calls forward)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch.nn&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;torch.nn&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;functional&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;

&lt;span class="c1"&gt;# hyperparameters
&lt;/span&gt;&lt;span class="n"&gt;batch_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="c1"&gt;# how many independent sequences will we process in parallel?
&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt; &lt;span class="c1"&gt;# how many previous tokens are used for predicting the next?
&lt;/span&gt;&lt;span class="n"&gt;max_iters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;
&lt;span class="n"&gt;eval_interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
&lt;span class="n"&gt;learning_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3e-4&lt;/span&gt;
&lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cuda&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cuda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_available&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cpu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;eval_iters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;span class="n"&gt;n_embd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;384&lt;/span&gt;
&lt;span class="n"&gt;n_head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="n"&gt;n_layer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="n"&gt;dropout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;
&lt;span class="c1"&gt;# ------------
&lt;/span&gt;
&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;manual_seed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1337&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# To get the exact same results every time
&lt;/span&gt;
&lt;span class="c1"&gt;# wget https://raw.githubusercontent.com/karpathy/char-rnn/master/data/tinyshakespeare/input.txt
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;input.txt&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# here are all the unique characters that occur in this text
&lt;/span&gt;&lt;span class="n"&gt;chars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="n"&gt;vocab_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# create a mapping from characters to integers
&lt;/span&gt;&lt;span class="n"&gt;stoi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;itos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;encode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stoi&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# encoder: take a string, output a list of integers
&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;itos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# decoder: take a list of integers, output a string
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# --- EXAMPLE 
&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cat bit the dog&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;encoded_ints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Original String:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Encoded Integers:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoded_ints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="sb"&gt;``&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;endraw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Output: [28, 26, 45, 0, 27, 34, 45, 0, 45, 33, 30, 0, 29, 40, 32] &lt;/p&gt;

&lt;p&gt;Decoding that list back into a string decoded_string:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
python
decode(encoded_ints) print("Decoded Output :", decoded_string) # Output: "cat bit the dog"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;




```python
# Train and test splits
data = torch.tensor(encode(text), dtype=torch.long)
n = int(0.9*len(data)) # first 90% will be train, rest val
train_data = data[:n]
val_data = data[n:]

# data loading
def get_batch(split):
    # generate a small batch of data of inputs x and targets y
    data = train_data if split == 'train' else val_data
    ix = torch.randint(len(data) - block_size, (batch_size,))
    x = torch.stack([data[i:i+block_size] for i in ix])
    y = torch.stack([data[i+1:i+block_size+1] for i in ix])
    x, y = x.to(device), y.to(device)
    return x, y

@torch.no_grad()
def estimate_loss():
    out = {}
    model.eval()
    for split in ['train', 'val']:
        losses = torch.zeros(eval_iters)
        for k in range(eval_iters):
            X, Y = get_batch(split)
            logits, loss = model(X, Y)
            losses[k] = loss.item()
        out[split] = losses.mean()
    model.train()
    return out

class Head(nn.Module):
    """ one head of self-attention """

    def __init__(self, head_size):
        super().__init__()
        self.key = nn.Linear(n_embd, head_size, bias=False)
        self.query = nn.Linear(n_embd, head_size, bias=False)
        self.value = nn.Linear(n_embd, head_size, bias=False)
        self.register_buffer('tril', torch.tril(torch.ones(block_size, block_size)))
        self.dropout = nn.Dropout(dropout)

    def forward(self, x):
        # input of size (batch, time-step, channels)
        # output of size (batch, time-step, head size)
        B,T,C = x.shape
        k = self.key(x)   # (B,T,head_size)
        q = self.query(x) # (B,T,head_size)
        # compute attention scores ("affinities")
        wei = q @ k.transpose(-2,-1) * k.shape[-1]**-0.5 # (B, T, head_size) @ (B, head_size, T) -&amp;gt; (B, T, T)
        wei = wei.masked_fill(self.tril[:T, :T] == 0, float('-inf')) # (B, T, T)
        wei = F.softmax(wei, dim=-1) # (B, T, T)
        wei = self.dropout(wei)
        # perform the weighted aggregation of the values
        v = self.value(x) # (B,T,head_size)
        out = wei @ v # (B, T, T) @ (B, T, head_size) -&amp;gt; (B, T, head_size)
        return out

class MultiHeadAttention(nn.Module):
    """ multiple heads of self-attention in parallel """

    def __init__(self, num_heads, head_size):
        super().__init__()
        self.heads = nn.ModuleList([Head(head_size) for _ in range(num_heads)])
        self.proj = nn.Linear(head_size * num_heads, n_embd)
        self.dropout = nn.Dropout(dropout)

    def forward(self, x):
        out = torch.cat([head(x) for head in self.heads], dim=-1)
        out = self.dropout(self.proj(out))
        return out

class FeedFoward(nn.Module):
    """ a simple linear layer followed by a non-linearity """

    def __init__(self, n_embd):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(n_embd, 4 * n_embd),
            nn.ReLU(),
            nn.Linear(4 * n_embd, n_embd),
            nn.Dropout(dropout),
        )

    def forward(self, x):
        return self.net(x)

class Block(nn.Module):
    """ Transformer block: communication followed by computation """

    def __init__(self, n_embd, n_head):
        # n_embd: embedding dimension, n_head: the number of heads we'd like
        super().__init__()
        head_size = n_embd // n_head
        self.selfattention = MultiHeadAttention(n_head, head_size)
        self.ffwd = FeedFoward(n_embd)
        self.ln1 = nn.LayerNorm(n_embd)
        self.ln2 = nn.LayerNorm(n_embd)

    def forward(self, x):
        x = x + self.selfattention(self.ln1(x))
        x = x + self.ffwd(self.ln2(x))
        return x

class GPTLanguageModel(nn.Module):

    def __init__(self):
        super().__init__()
        # each token directly reads off the logits for the next token from a lookup table
        self.token_embedding_table = nn.Embedding(vocab_size, n_embd)
        self.position_embedding_table = nn.Embedding(block_size, n_embd)
        self.blocks = nn.Sequential(*[Block(n_embd, n_head=n_head) for _ in range(n_layer)])
        self.ln_f = nn.LayerNorm(n_embd) # final layer norm
        self.lm_head = nn.Linear(n_embd, vocab_size)

        # better init, not covered in the original GPT video, but important, will cover in followup video
        self.apply(self._init_weights)

    def _init_weights(self, module):
        if isinstance(module, nn.Linear):
            torch.nn.init.normal_(module.weight, mean=0.0, std=0.02)
            if module.bias is not None:
                torch.nn.init.zeros_(module.bias)
        elif isinstance(module, nn.Embedding):
            torch.nn.init.normal_(module.weight, mean=0.0, std=0.02)

    def forward(self, idx, targets=None):
        B, T = idx.shape

        # idx and targets are both (B,T) tensor of integers
        tok_emb = self.token_embedding_table(idx) # (B,T,C)
        pos_emb = self.position_embedding_table(torch.arange(T, device=device)) # (T,C)
        x = tok_emb + pos_emb # (B,T,C)
        x = self.blocks(x) # (B,T,C)
        x = self.ln_f(x) # (B,T,C)
        logits = self.lm_head(x) # (B,T,vocab_size)

        if targets is None:
            loss = None
        else:
            B, T, C = logits.shape
            logits = logits.view(B*T, C)
            targets = targets.view(B*T)
            loss = F.cross_entropy(logits, targets)

        return logits, loss

    def generate(self, idx, max_new_tokens):
        # idx is (B, T) array of indices in the current context
        for _ in range(max_new_tokens):
            # crop idx to the last block_size tokens
            idx_cond = idx[:, -block_size:]
            # get the predictions
            logits, loss = self(idx_cond)
            # focus only on the last time step
            logits = logits[:, -1, :] # becomes (B, C)
            # apply softmax to get probabilities
            probs = F.softmax(logits, dim=-1) # (B, C)
            # sample from the distribution
            idx_next = torch.multinomial(probs, num_samples=1) # (B, 1)
            # append sampled index to the running sequence
            idx = torch.cat((idx, idx_next), dim=1) # (B, T+1)
        return idx

model = GPTLanguageModel()
m = model.to(device)
# print the number of parameters in the model
print(sum(p.numel() for p in m.parameters())/1e6, 'M parameters')

# create a PyTorch optimizer
optimizer = torch.optim.AdamW(model.parameters(), lr=learning_rate)

for iter in range(max_iters):

    # every once in a while evaluate the loss on train and val sets
    if iter % eval_interval == 0 or iter == max_iters - 1:
        losses = estimate_loss()
        print(f"step {iter}: train loss {losses['train']:.4f}, val loss {losses['val']:.4f}")

    # sample a batch of data
    xb, yb = get_batch('train')

    # evaluate the loss
    logits, loss = model(xb, yb)
    optimizer.zero_grad(set_to_none=True)
    loss.backward()
    optimizer.step()

# generate from the model
context = torch.zeros((1, 1), dtype=torch.long, device=device)
print(decode(m.generate(context, max_new_tokens=500)[0].tolist()))
#open('more.txt', 'w').write(decode(m.generate(context, max_new_tokens=10000)[0].tolist()))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  On why the first class outputs (B, T, head_size)?
&lt;/h3&gt;

&lt;p&gt;$$\large(X, Y) \times (Y, Z) = (X, Z)$$&lt;/p&gt;

&lt;p&gt;In the final line of your &lt;code&gt;Head&lt;/code&gt; forward pass, you have:&lt;/p&gt;

&lt;p&gt;$$\large\text{wei} \ (\text{shape: } B, T, T) \quad @ \quad v \ (\text{shape: } B, T, \text{head_size})$$&lt;/p&gt;

&lt;p&gt;PyTorch ignores the batch dimension ($B$) and looks at the last two dimensions:&lt;/p&gt;

&lt;p&gt;$$(\large T, \underline{T}) \times (\underline{T}, \text{head_size}) = (T, \text{head_size})$$&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;BatchNorm normalizes across the &lt;em&gt;batch&lt;/em&gt; dimension.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;LayerNorm&lt;/strong&gt; normalizes across the &lt;strong&gt;channel dimension (&lt;code&gt;n_embd&lt;/code&gt;)&lt;/strong&gt; for each individual token independently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We have &lt;strong&gt;two&lt;/strong&gt; LayerNorms because we have two distinct sub-layers inside the block:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;ln1&lt;/code&gt; stabilizes the data &lt;em&gt;before&lt;/em&gt; it goes into Attention.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;ln2&lt;/code&gt; stabilizes the data &lt;em&gt;after&lt;/em&gt; attention, right &lt;em&gt;before&lt;/em&gt; it goes into the FFN.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Flash Attention
&lt;/h3&gt;

&lt;p&gt;Standard attention is bottlenecked by the $O(N^2)$ memory bandwidth costs of repeatedly reading and writing the $N \times N$ attention matrix to HBM (High Bandwidth Memory). FlashAttention solves this by fusing the operations and aggressively tiling the computation to keep it entirely within the fast SRAM, completely bypassing the massive I/O overhead.&lt;/p&gt;

&lt;p&gt;![[compute.png]]&lt;/p&gt;

</description>
      <category>deeplearning</category>
      <category>machinelearning</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Ubuntu Agent Starter</title>
      <dc:creator>Masih Maafi</dc:creator>
      <pubDate>Sun, 05 Jul 2026 12:11:19 +0000</pubDate>
      <link>https://dev.to/masihmoafi/ubuntu-agent-starter-5768</link>
      <guid>https://dev.to/masihmoafi/ubuntu-agent-starter-5768</guid>
      <description>&lt;h1&gt;
  
  
  Ubuntu Agent Starter
&lt;/h1&gt;

&lt;p&gt;An installable Ubuntu helper layer: small shell commands, sane terminal helpers, and eventually agent-powered workflows for people who want Linux to feel less hostile.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this can realistically become
&lt;/h2&gt;

&lt;p&gt;Start with an installer for normal Ubuntu. Once that is useful, package it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Shell starter kit: aliases/functions installed into &lt;code&gt;~/.bash_aliases&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Safe installer: backups, managed blocks, &lt;code&gt;--dry-run&lt;/code&gt;, and &lt;code&gt;--uninstall&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Guided setup: optional install checks for apps like Obsidian, Git, &lt;code&gt;ripgrep&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;, and editors.&lt;/li&gt;
&lt;li&gt;Agent layer: a command such as &lt;code&gt;ask&lt;/code&gt; or &lt;code&gt;fix&lt;/code&gt; that explains terminal errors and suggests commands.&lt;/li&gt;
&lt;li&gt;Packaging: publish a GitHub repo, then a &lt;code&gt;.deb&lt;/code&gt;, then maybe an Ubuntu remix ISO.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;ubuntu-agent-starter
./install.sh &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
./install.sh
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bash_aliases
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Commands
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;note&lt;/code&gt; creates &lt;code&gt;temp.md&lt;/code&gt; in the current directory.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;obs&lt;/code&gt; opens the normal Obsidian desktop app from wherever you are.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;op [path]&lt;/code&gt; opens a file or folder with the desktop opener.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkcd name&lt;/code&gt; creates a directory and enters it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;extract archive.zip&lt;/code&gt; extracts common archive formats.&lt;/p&gt;

&lt;h2&gt;
  
  
  Uninstall
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./install.sh &lt;span class="nt"&gt;--uninstall&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bash_aliases
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The installer only manages the block between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# &amp;gt;&amp;gt;&amp;gt; ubuntu-agent-starter &amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;# &amp;lt;&amp;lt;&amp;lt; ubuntu-agent-starter &amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ai</category>
      <category>productivity</category>
      <category>automation</category>
      <category>discuss</category>
    </item>
    <item>
      <title>How to Keep AI Coding Agents from Hallucinating: A Guide to Harness Engineering</title>
      <dc:creator>Masih Maafi</dc:creator>
      <pubDate>Sun, 14 Jun 2026 10:05:48 +0000</pubDate>
      <link>https://dev.to/masihmoafi/how-to-keep-ai-coding-agents-from-hallucinating-a-guide-to-harness-engineering-12mm</link>
      <guid>https://dev.to/masihmoafi/how-to-keep-ai-coding-agents-from-hallucinating-a-guide-to-harness-engineering-12mm</guid>
      <description>&lt;h1&gt;
  
  
  How to Keep AI Coding Agents from Hallucinating: A Guide to Harness Engineering
&lt;/h1&gt;

&lt;p&gt;AI coding agents (like Claude Code, Devin, or open-source equivalents like OpenClaw) are incredibly powerful. They can navigate directories, write tests, refactor modules, and submit PRs.&lt;/p&gt;

&lt;p&gt;Yet, if you drop them into a raw repository without boundaries, they suffer from &lt;strong&gt;context window pollution&lt;/strong&gt;, &lt;strong&gt;agent amnesia&lt;/strong&gt;, and &lt;strong&gt;scope drift&lt;/strong&gt;. A simple bug-fix refactor can trigger a 6-hour loop where the agent rewires half the project, deletes unrelated tests, and gets stuck in "process theater."&lt;/p&gt;

&lt;p&gt;To fix this, we need &lt;strong&gt;Harness Engineering&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Harness Engineering?
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;Agent Harness&lt;/strong&gt; is a structured, repository-local control layer designed to guide and verify the agent's work. Instead of feeding your LLM a monolithic prompt, you embed a lightweight system of record and physical feedback loops directly inside the workspace.&lt;/p&gt;

&lt;p&gt;I have packaged the exact, battle-tested Markdown-based context rules I use to steer and constraint my local agents into a public repository: &lt;strong&gt;&lt;a href="https://github.com/MasihMoafi/harnesses-I-use" rel="noopener noreferrer"&gt;MasihMoafi/harnesses-I-use&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Rather than complex code, this repo shares raw configuration rule sheets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;a href="https://github.com/MasihMoafi/harnesses-I-use/blob/main/AGENTS.md" rel="noopener noreferrer"&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;: The global router and primary entry point. Every AI agent reads this first to understand the Priority Kernel (reply constraints, English defaults, local-first behavior).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;a href="https://github.com/MasihMoafi/harnesses-I-use/blob/main/CODEX_CODING_GUIDELINES.md" rel="noopener noreferrer"&gt;&lt;code&gt;CODEX_CODING_GUIDELINES.md&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;: Surgical coding rules adapted from Andrej Karpathy's coding practices. Enforces minimal changes, style-matching, and goal-driven execution.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;a href="https://github.com/MasihMoafi/harnesses-I-use/blob/main/TERMINAL_AND_GIT_RULES.md" rel="noopener noreferrer"&gt;&lt;code&gt;TERMINAL_AND_GIT_RULES.md&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;: Safe terminal navigation, SOCKS/HTTP proxy configuration, explicit git scoping (e.g., &lt;em&gt;never&lt;/em&gt; using &lt;code&gt;git add -A&lt;/code&gt;), and change safety (using Ubuntu &lt;code&gt;pkexec&lt;/code&gt; for root commands instead of raw CLI password prompts).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;a href="https://github.com/MasihMoafi/harnesses-I-use/blob/main/SESSION_HANDOFF_RULES.md" rel="noopener noreferrer"&gt;&lt;code&gt;SESSION_HANDOFF_RULES.md&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;: Guidelines for context awareness and continuity. Defines how state should be captured and transferred between sessions.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;a href="https://github.com/MasihMoafi/harnesses-I-use/blob/main/ARTIFACT_RULES.md" rel="noopener noreferrer"&gt;&lt;code&gt;ARTIFACT_RULES.md&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;: Rules for generating verified visual and math outputs, including local HTML layout verification, MathML for formula rendering, and PDF inspection.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;a href="https://github.com/MasihMoafi/harnesses-I-use/blob/main/abbn.md" rel="noopener noreferrer"&gt;&lt;code&gt;abbn.md&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;: A dictionary of standard abbreviations (e.g., &lt;code&gt;ctu&lt;/code&gt; = continue, &lt;code&gt;fmy&lt;/code&gt; = familiarize, &lt;code&gt;ver&lt;/code&gt; = verify) to save token count and maintain short, high-efficiency communication.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Karpathy Connection: Simplicity &amp;amp; Rigor
&lt;/h2&gt;

&lt;p&gt;This harness approach is heavily inspired by &lt;strong&gt;Andrej Karpathy's&lt;/strong&gt; open-source education repos (like &lt;strong&gt;&lt;a href="https://github.com/karpathy/micrograd" rel="noopener noreferrer"&gt;micrograd&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://github.com/karpathy/makemore" rel="noopener noreferrer"&gt;makemore&lt;/a&gt;&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;Karpathy’s projects are celebrated because they strip away bloat. They focus on clear, reproducible mathematical baselines and avoid over-engineering.&lt;/p&gt;

&lt;p&gt;We applied that same philosophy to agent-driven code generation. The core rules of our harness require:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Surgical Changes&lt;/strong&gt;: Touch only the exact lines requested. No drive-by style refactoring of adjacent code.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Verifiable Outcomes&lt;/strong&gt;: Before the agent claims a feature is complete, it must run a local script to verify the baseline, compile the code, and attach raw terminal output logs to its session record as physical evidence of success.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Harness Simplification&lt;/strong&gt;: Every rule is considered overhead. As models grow smarter, we run tests to prune redundant rules.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Case Study: Autonomously Generating ML Research Reports
&lt;/h2&gt;

&lt;p&gt;To test this, I used this exact harness to build a comparative machine learning research project: &lt;strong&gt;Sensor Fault Diagnosis&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The agent was given a realistic synthetic sensor dataset and tasked with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Training a Bayesian classifier (Gaussian Naive Bayes) and mapping conditional probabilities.&lt;/li&gt;
&lt;li&gt; Building and training a PyTorch MLP neural network.&lt;/li&gt;
&lt;li&gt; Calculating and comparing multiple losses—including standard Binary Cross-Entropy (BCE), &lt;strong&gt;micrograd-style Max-Margin (Hinge) loss&lt;/strong&gt;, and &lt;strong&gt;makemore-style Cross-Entropy loss&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Exporting ROC curves, decision boundaries, and generating a publication-grade LaTeX/HTML research paper.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By restricting the agent to a single control surface (a structured manual) and enforcing strict keep/discard criteria, the agent completed the pipeline and wrote the final report &lt;strong&gt;entirely autonomously&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Without a harness, the agent would have bloated the repository with decorative dashboard scripts or fake performance metrics. The harness kept it grounded.&lt;/p&gt;




&lt;h2&gt;
  
  
  Get the Harness
&lt;/h2&gt;

&lt;p&gt;If you are building code with AI agents, stop writing 2,000-word system prompts. Start building repository harnesses.&lt;/p&gt;

&lt;p&gt;Check out the templates and configurations:&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://github.com/MasihMoafi/harnesses-I-use" rel="noopener noreferrer"&gt;MasihMoafi/harnesses-I-use&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For more of my work, experiments, and research, check out my website:&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://masihmoafi.tech" rel="noopener noreferrer"&gt;masihmoafi.tech&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>developer</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Building a Horror Game in 8 Hours with Kiro AI - My Kiroween Hackathon Journey</title>
      <dc:creator>Masih Maafi</dc:creator>
      <pubDate>Wed, 03 Dec 2025 04:46:57 +0000</pubDate>
      <link>https://dev.to/masihmoafi/building-a-horror-game-in-8-hours-with-kiro-ai-my-kiroween-hackathon-journey-5cjp</link>
      <guid>https://dev.to/masihmoafi/building-a-horror-game-in-8-hours-with-kiro-ai-my-kiroween-hackathon-journey-5cjp</guid>
      <description>&lt;h1&gt;
  
  
  Building a Horror Game in 8 Hours with Kiro AI
&lt;/h1&gt;

&lt;p&gt;For the Kiroween 2025 hackathon, I built &lt;strong&gt;Layers of Static&lt;/strong&gt; - a psychological horror experience disguised as a vintage 1970s CRT television. The twist? An AI lives inside it, asking disturbing questions and giving creepy dares.&lt;/p&gt;

&lt;p&gt;The real story isn't what I built. It's &lt;strong&gt;how&lt;/strong&gt; I built it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge: Frankenstein Category
&lt;/h2&gt;

&lt;p&gt;The hackathon's "Frankenstein" category challenged us to stitch together incompatible technologies into something unexpectedly powerful. My chimera:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1970s CRT aesthetics&lt;/strong&gt; (scanlines, phosphor glow, chromatic aberration)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern AI&lt;/strong&gt; (Google Gemini for conversation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Voice synthesis&lt;/strong&gt; (ElevenLabs TTS with a little girl's voice)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web Audio API&lt;/strong&gt; (music box loops, audio ducking, sound effects)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Normally, this would take weeks. With Kiro, I shipped in 8 hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Kiro?
&lt;/h2&gt;

&lt;p&gt;Kiro is an AI-powered development environment that goes beyond code generation. It's a &lt;strong&gt;development partner&lt;/strong&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Spec-driven development&lt;/strong&gt; - Turn requirements into structured implementation plans&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steering docs&lt;/strong&gt; - Inject project context into every conversation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP (Model Context Protocol)&lt;/strong&gt; - Extend capabilities with custom servers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CLI-first workflow&lt;/strong&gt; - Terminal-native for speed and flexibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think "GitHub Copilot meets project manager meets senior dev who never forgets context."&lt;/p&gt;

&lt;h2&gt;
  
  
  My Workflow: Hybrid Approach
&lt;/h2&gt;

&lt;p&gt;I used four Kiro features strategically:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Steering Docs: Never Repeat Context
&lt;/h3&gt;

&lt;p&gt;I created three markdown files in &lt;code&gt;.kiro/steering/&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;product.md&lt;/strong&gt; - The vision:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Design Philosophy&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Visual: CRT effects (scanlines, phosphor glow, chromatic aberration)
&lt;span class="p"&gt;-&lt;/span&gt; Tone: Cryptic, poetic, disturbing - unsettling but not explicit
&lt;span class="p"&gt;-&lt;/span&gt; Inspiration: Layers of Fear, Call of Duty: Black Ops terminal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;structure.md&lt;/strong&gt; - Where code lives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| File | Purpose |
|------|---------|
| components/Screen.tsx | Game logic, menu, chat |
| services/ttsService.ts | ElevenLabs TTS integration |
| utils/sound.ts | Audio system, ducking, effects |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;tech.md&lt;/strong&gt; - Stack constraints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; React 18 with TypeScript
&lt;span class="p"&gt;-&lt;/span&gt; Vite for fast builds
&lt;span class="p"&gt;-&lt;/span&gt; Tailwind CSS + custom CRT effects
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These docs auto-injected into &lt;strong&gt;every conversation&lt;/strong&gt;. No more "remember, we're building a horror game" every session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time saved&lt;/strong&gt;: ~5 hours of repetitive context-setting.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. MCP: Persistent Memory Across Sessions
&lt;/h3&gt;

&lt;p&gt;I used custom MCP servers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory Server&lt;/strong&gt; - Persisted decisions across days&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RAG Server&lt;/strong&gt; - Queried large files without loading full context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On Day 1: "We're using ElevenLabs for TTS with a creepy little girl voice."&lt;/p&gt;

&lt;p&gt;On Day 2 (after closing/reopening): Kiro &lt;strong&gt;remembered&lt;/strong&gt;. No re-explaining needed.&lt;/p&gt;

&lt;p&gt;This transformed Kiro from stateless to stateful. Multi-day development felt like a single continuous conversation.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Spec-Driven Development: Structure for Core Features
&lt;/h3&gt;

&lt;p&gt;For complex features, I created a spec in &lt;code&gt;.kiro/specs/&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;requirements.md&lt;/strong&gt; - 9 EARS-compliant requirements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REQ-2.1: WHEN the terminal is visible, 
         the system SHALL display animated scanlines
         with 0.1 opacity and 2px spacing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;design.md&lt;/strong&gt; - Technical blueprint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Scanline Implementation&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; CSS: repeating-linear-gradient
&lt;span class="p"&gt;-&lt;/span&gt; Animation: vertical scroll at 10s duration
&lt;span class="p"&gt;-&lt;/span&gt; Fallback: Static scanlines if animation disabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;tasks.md&lt;/strong&gt; - 25 atomic tasks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; [x] 2.2 Implement scanline effect
&lt;span class="p"&gt;  -&lt;/span&gt; Create #scanlines overlay
&lt;span class="p"&gt;  -&lt;/span&gt; Add vertical animation
&lt;span class="p"&gt;  -&lt;/span&gt; Requirements: 2.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I said "execute task 2.2," Kiro knew:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What to build (scanlines)&lt;/li&gt;
&lt;li&gt;How to build it (repeating-linear-gradient)&lt;/li&gt;
&lt;li&gt;Where to put it (style.css)&lt;/li&gt;
&lt;li&gt;Why it exists (requirement 2.1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: Zero missed features. Every line of code traced back to a requirement.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Vibe Coding: Speed for Iteration
&lt;/h3&gt;

&lt;p&gt;For polish and refinements, I ditched specs and just talked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Make the scanlines more subtle"&lt;/li&gt;
&lt;li&gt;"Add a scream sound effect when the player types DARE"&lt;/li&gt;
&lt;li&gt;"The candles should flicker more realistically"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kiro understood the aesthetic (from steering docs) and iterated instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spec vs Vibe&lt;/strong&gt;: I used specs for core features (needed structure), vibe for polish (needed speed).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Most Impressive Code Generation
&lt;/h2&gt;

&lt;p&gt;I asked: "When TTS speaks, background music should duck down smoothly, then restore when done."&lt;/p&gt;

&lt;p&gt;Kiro generated a complete audio management system in &lt;code&gt;utils/sound.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;duck&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;muted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;ducking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;targetVolume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;masterVolume&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;DUCK_VOLUME&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DUCK_DURATION&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;duckInterval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;activeTracks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newVolume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; 
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;targetVolume&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;targetVolume&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newVolume&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;duckInterval&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This handled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smooth volume ramping (200ms transitions)&lt;/li&gt;
&lt;li&gt;Coordination between 5+ audio sources&lt;/li&gt;
&lt;li&gt;Cancellation flags for interrupting speech&lt;/li&gt;
&lt;li&gt;Proper cleanup to prevent memory leaks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Zero bugs. Worked perfectly on first try.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This would have taken me hours to implement and debug manually. Kiro did it in seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Kiro CLI &amp;gt; IDE
&lt;/h2&gt;

&lt;p&gt;I used &lt;code&gt;kiro-cli&lt;/code&gt; instead of the IDE for 90% of development:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Speed&lt;/strong&gt;: Instant responses, no UI overhead&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kiro &lt;span class="s2"&gt;"add error handling to TTS service"&lt;/span&gt;
kiro &lt;span class="s2"&gt;"make the glow effect more subtle"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;: Pipe commands, script workflows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kiro &lt;span class="s2"&gt;"list all TODO comments"&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;URGENT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Focus&lt;/strong&gt;: Terminal-first matches my workflow. No context switching.&lt;/p&gt;

&lt;p&gt;The CLI felt like pair programming with a senior dev who types at 1000 WPM and never forgets context.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Development time&lt;/strong&gt;: ~8 hours (including spec creation)&lt;br&gt;
&lt;strong&gt;Lines of code&lt;/strong&gt;: 2000+ (React + TypeScript + CSS)&lt;br&gt;
&lt;strong&gt;Features&lt;/strong&gt;: 3 game modes, AI integration, voice synthesis, audio system&lt;br&gt;
&lt;strong&gt;Bugs&lt;/strong&gt;: Minimal (caught during task execution)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kiro's contribution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;~90% of final codebase&lt;/li&gt;
&lt;li&gt;80% first-try success rate&lt;/li&gt;
&lt;li&gt;100% context retention across sessions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Insights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. MCP is the Killer Feature
&lt;/h3&gt;

&lt;p&gt;Custom MCP servers transformed Kiro from "smart autocomplete" to "development partner with memory." Multi-day projects became seamless.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Steering Docs Save Hours
&lt;/h3&gt;

&lt;p&gt;Writing 3 markdown files upfront saved 5+ hours of repetitive context-setting. Best time investment of the project.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Hybrid Approach Works Best
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Specs&lt;/strong&gt; for core features (structure, traceability)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vibe&lt;/strong&gt; for iteration (speed, creativity)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steering&lt;/strong&gt; for consistency (context, aesthetic)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP&lt;/strong&gt; for persistence (memory, efficiency)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. CLI is Underrated
&lt;/h3&gt;

&lt;p&gt;The terminal interface is faster and more flexible than GUI IDEs. If you're comfortable in the terminal, try &lt;code&gt;kiro-cli&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live demo&lt;/strong&gt;: &lt;a href="https://layers-of-static.vercel.app" rel="noopener noreferrer"&gt;layers-of-static.vercel.app&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Source code&lt;/strong&gt;: &lt;a href="https://github.com/MasihMoafi/kiroween" rel="noopener noreferrer"&gt;github.com/MasihMoafi/kiroween&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: Turn on your speakers. Light the candles. Don't play alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons for Your Next Project
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Write steering docs first&lt;/strong&gt; - 30 minutes upfront saves hours later&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use specs for complex features&lt;/strong&gt; - Clarity beats speed for core systems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vibe code for polish&lt;/strong&gt; - Iteration is faster without formal structure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build/use MCP servers&lt;/strong&gt; - Persistent context is a superpower&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Try the CLI&lt;/strong&gt; - Terminal-first development is surprisingly efficient&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Kiro didn't just generate code. It understood my vision, maintained context across days, executed structured plans, and iterated rapidly.&lt;/p&gt;

&lt;p&gt;The result: A polished horror experience that would have taken weeks manually, shipped in 8 hours.&lt;/p&gt;

&lt;p&gt;That's not automation. That's &lt;strong&gt;augmentation&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What's your experience with AI-assisted development? Have you tried Kiro or similar tools? Drop your thoughts in the comments!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This project was built for the Kiroween 2025 hackathon. Check out other submissions at &lt;a href="https://devpost.com/kiroween" rel="noopener noreferrer"&gt;devpost.com/kiroween&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>hackathon</category>
      <category>webdev</category>
      <category>gamedev</category>
    </item>
  </channel>
</rss>
