Pi-ople keep asking what pi-codex-conversion actually adds. GPT models already work in Pi, so why bother?
Fair question.
I don’t even use Codex. Mine is set up pretty much vanilla and eats roughly 20k tokens to say hi.
My complete hard-clanking, fully kitted-out Pi setup starts around 1.8k. That includes 19 available skills, 17 tools, 15 extensions and a 3,127-character personality file. The Clanker still knows what all of it does.
I counted
The Codex number is an observation from opening my mostly untouched Codex desktop setup. It is not a controlled benchmark against Pi, before the benchmark police start getting excited.
The Pi runs were controlled enough for a bloke firing up terminal sessions: same Pi version, same GPT-5.6 Luna model, same 272k context window and the same tiny first turn. Pi rounds the displayed input count, so another decimal place would be cosplay.
| Setup | Startup input |
|---|---|
| Bare Pi, no context files, extensions or skills | ~1.1k |
| Conversion core, previous default prompt handling | ~1.2k |
| Conversion core, first heavy-overwrite run | 913 |
| Conversion core, current heavy-overwrite run | ~1.1k |
| Conversion with custom tools, web search and image generation, previous run | ~1.5k |
| My daily environment, previous run | ~2.9k |
| My daily environment now | ~1.8k |

The bare run was just:
pi --no-context-files --no-extensions --no-skills
I then loaded the conversion checkout, added its toolkit and custom tools, and finally started my full environment.
The original 2.9k run had six skills in the normal inventory and thirteen more behind more_skills. Three tools were ordinary provider-level tools, eleven lived inside exec, and another three were deferred. Fifteen extensions were running around them.
The new skills tool has since replaced both Pi’s native skill inventory and more_skills. One call lists all 19 under Agent, Creative, Operations and SWE, then loads only the one the Clanker needs. My full setup is now down to roughly 1.8k.
I asked the model what it could use. It found shell, patching, search, agents, images, web, interaction and skills without seventeen full schemas being rammed into every request.
At one point the empty conversion setup started around 800 tokens. It crept up to roughly 1.2k as I added realtime voice, dictation, image generation, web search, blind-model vision, native compaction and custom tools. The heavy overwrite got it down to 913 at some point. It is 1.1k now. I don’t even know what changed xD
What gets converted
Pi can already send requests to GPT. The conversion changes what the model sees around that request.
GPT gets shell, patch, image and web operations in the shape Codex models were trained to call. The adapter can run across every provider, with structured tools for models outside the supported GPT-5.6 Code Mode routes. I can point Code Mode somewhere stranger if I am feeling brave enough.
Giving a model tools and call syntax it already knows is probably better than inventing another dialect. Boring argument. I won’t elaborate. If you get it, you get it. If you don’t, you don’t. The RL will only get stronger.
Three schemas
My Code Mode provider receives three normal tool schemas:
exec, freeformwait, JSONask, JSON
The adapter owns exec and wait. I leave ask as a normal Pi tool because it talks to Pi’s UI. Pretending that is a shell command would be daft.
The rest composes locally inside exec:
const status = await tools.exec_command({ cmd: "git status --short" });
text(status);
Shell, patch, image, web and image-generation calls still get their proper Pi rendering. Their complete schemas do not travel to the provider. apply_patch now gets the exact patch grammar accepted by its parser, which should stop malformed patch calls and make the Clanker less wary of using it properly.
exec also spells out the awkward V8 bits: JavaScript source only, no JSON wrapper or fences, no Node, imports or console, and extra care around String.raw when shell text contains backticks or ${...}.
Configured custom tools are now kept separate from the bundled ones. A promoted custom tool adds one compact usage line to the system prompt. A deferred one adds no tool-specific text at startup and can be discovered through ALL_TOOLS later. Neither becomes another provider JSON schema.
ALL_TOOLS contains only the deferred custom tools available at that moment. No bundled tools, no promoted tools, and no stale list after the tool set changes.
The custom-tool docs are for changing the TOML definitions. The Clanker does not have to read them before calling a tool it already has.
Seventeen usable tools. Three provider schemas.
Voice, images and web, whichever Clanker is active
The kit currently covers:
- web search
- image generation and editing
- local image inspection
- realtime voice and push-to-dictate
- usage and reset visibility
- OpenAI compaction
- verbosity and fast service tier
- background and interactive shell sessions
Voice connects through my Codex login and stays attached to the Pi session where I started it. When voice hands off a job, that exact agent receives it. The agent does not have to use an OpenAI model. Dictation is just hold key, yap, receive one final transcript in Pi’s editor.
Images are slightly sillier. A model with vision gets the image normally. For a blind model, view_image can send it straight to a small vision-capable helper. Mine uses Luna. The main Clanker receives Luna’s description as an ordinary tool result and carries on without even needing to know it is blind.
Web search and image generation follow the same basic arrangement. Pi handles the operation and authentication. The model gets a callable thing, not a tour of the pipes.
The commands behind the tools
A custom Code Mode tool can point at a script, a CLI on PATH, or any command that accepts one string through an argument or standard input. This is the bit that makes the whole setup mine.
My spawn_agent command can invoke whichever coding CLI I choose, pick its model behind the scenes, append a Git diff and offer the main Clanker only a few obvious agent types. I do not need to let it choose providers, reasoning levels and sixteen made-up specialist personas.
skills now keeps all 19 skills out of the startup inventory. It can show the category names, list skills from one or several categories, then load one exact skill. That replaced Pi’s native skill dump and my separate more_skills tool in one go.
sites is my bridge to the ChatGPT Sites beta. It can manage sites, versions, deployments, access, environment settings, domains and analytics. sites_documentation loads only the topic or operation schema the Clanker needs before calling it.
Code Mode rediscovers those definitions when it collects the available tools, so I can change a command without rebuilding the conversion extension.
Deferred definitions are particularly cheap because their individual text never enters the system prompt. Promoted definitions do change the small inventory, so changing one can affect the prompt cache. Claiming otherwise would be bollocks.
When custom tools click, they REALLY click.
Token min-maxxing is mostly deleting words
There is no clever compression algorithm hiding in here. I keep comparing Pi’s provider, my provider and Codex, then delete or combine whatever the model does not need.
Well, I finally ate into Pi’s base prompt xD
The new heavy overwrite removes around 40% of it and got one empty conversion launch down from roughly 1.2k to 913 tokens. It is around 1.1k as I write this. The option stays off by default.
It removes Pi’s known default scaffold, documentation and guidelines, then rebuilds the bits the model still needs. Non-default additions from other extensions are left alone. It does not blindly replace the whole prompt and wipe out everybody else’s work.
View image is enough. Arguments can say Cwd, Wait ms and Truncate. The backticks are only here because this is Markdown. I omit them from the text sent to the model, along with decorative formatting, flowery sentences and cosmetic full stops.
The same fussiness applies after a call. Outputs are bounded. Errors retain enough information to recover. Processes that keep emitting output can stay in the original call, while a silent one yields a resumable session. Repeated empty polls back off instead of training the Clanker to ask wait the same question every second.
Finished sessions remain pollable too. If a process exits before the next poll, its completed output is still available and each late poll gets its own output cap. No more Unknown process id while the result is sitting right there.
I also stopped native compaction from trimming GPT-5.6 tool history at 272k. Pi can let the session overrun that nominal window and the compaction endpoint accepts up to 372k, so throwing away tool output early only nuked cache and gave the post-compaction Clanker less evidence. It now keeps the history until the endpoint budget actually requires trimming.
Compaction V2 also reports input, cache read, cache write and output tokens inline. I would rather see what it did than guess.
I nick the useful bits
Pi, Codex and my adapter do not need to agree on everything.
Pi owns local execution, sessions and UI. I port Codex behaviour where Pi has an honest equivalent. Remote execution metadata, telemetry, attestation and tracing belong to OpenAI’s runtime, so I leave them there.
I keep Pi’s answer, nick Codex’s, or ignore both and put together my own version.
The measurements above use the Lite package I run every day. It keeps structured tools for models without Code Mode and adds Code Mode for supported GPT-5.6 routes:
pi install npm:@howaboua/pi-codex-conversion-lite
The original package also retains PATH mode:
pi install npm:@howaboua/pi-codex-conversion
There are a few less glamorous escape hatches now too. Older Linux installations can use replacement Rust binaries. Voice-only mode can keep explicitly selected extra tools. Lite can optionally identify itself to OpenAI as pi-codex-conversion, if you fancy confuzzling OAI :P
That is why I use the conversion: less model-facing crap without taking the toys away.
You should check it out.