pi-rust
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Fail
- rm -rf — Recursive force deletion command in .github/workflows/ci.yml
- rm -rf — Recursive force deletion command in .github/workflows/release.yml
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Rust-only port of the pi coding agent harness
pi-rust
pi-rust is a Rust port of the pi coding agent harness. It has these parts:
- A streaming API for large language models (LLMs) from many providers.
- An agent loop that calls tools.
- The
picoding agent, which has a command-line interface (CLI).
pi-rust does not need Node.js or a different JavaScript runtime. In this file, "upstream pi" is the original pi, which is written in TypeScript.
Install
Linux and macOS:
curl -fsSL https://raw.githubusercontent.com/yannelli/pi-rust/main/install.sh | sh
Windows (PowerShell):
irm https://raw.githubusercontent.com/yannelli/pi-rust/main/install.ps1 | iex
The script downloads the latest release, compares it with SHA256SUMS, and installs pi. For script options, manual install, and build from source, see Install.
Quick start
export ANTHROPIC_API_KEY=... # or OPENAI_API_KEY, GEMINI_API_KEY, ...; or run /login
pi # interactive session in the current directory
pi -p "Summarize src/main.rs" # print mode: run once, print the answer
pi --mode json -p "List the TODOs" # one JSON event per line
pi --mode rpc # JSON-RPC over stdio for other programs
pi -c # continue the latest session here
pi -r # pick a session to resume
pi --model openai/gpt-5.5 --thinking high
pi @notes.md @screenshot.png "What changed?"
cat error.log | pi -p "Explain this error"
pi install npm:<package> # install a pi package (extensions, skills, themes)
Run pi --help to see all options. In interactive mode, type / to see the commands.
Documentation
| Page | Contents |
|---|---|
| Install | Script options, manual install, provenance check, update, and build from source |
| Interactive commands | /diff, /context, /export, /init, /review, /undo, /retry, and prompt history |
| CLI commands and flags | pi completion, pi doctor, pi sessions, pi stats, run limits, structured output, and pi extensions |
| Extension marketplace | Find, install, update, and remove native Rust extensions |
| Providers | Wire protocols, logins, Cursor, Google Antigravity, disabledProviders, OpenRouter, and account model lists |
| Status line | The marketplace:statusline extension and the move from the built-in status line |
| Terminal | Themes, notifications, and the marketplace:iterm2 extension |
| ACP mode | pi --mode acp for Zed and other editors |
| ACP agents | Kiro CLI, Amp, and ACP registry agents as providers, /acp, and the acpAgents setting |
| Docs index | Agent playbooks, parity, and the protocol notes of the subscription providers |
Configuration
pi-rust reads the same files as upstream pi, so the two can use one setup. To use a different folder in place of ~/.pi/agent, set PI_CODING_AGENT_DIR.
| Path | Contents |
|---|---|
~/.pi/agent/auth.json |
API keys and OAuth logins from /login or pi auth |
~/.pi/agent/settings.json |
Settings. In a trusted project, <project>/.pi/settings.json overrides them. |
~/.pi/agent/models.json |
Custom providers and models |
~/.pi/agent/keybindings.json |
Key bindings |
~/.pi/agent/mcp.json, <project>/.pi/mcp.json |
MCP servers |
~/.pi/agent/{extensions,skills,prompts,themes}/ |
Extensions, skills, prompt templates, and themes. .pi/ in a project and ~/.agents/skills also work. |
AGENTS.md, CLAUDE.md, SYSTEM.md, APPEND_SYSTEM.md |
Context files and system prompt overrides |
~/.pi/agent/sessions/ |
Sessions as JSONL trees in the pi format |
~/.pi/agent/prompt-history.jsonl |
The prompts that you sent, for Up, Down, and Ctrl+R (pi-rust only) |
When pi-rust starts for the first time, it moves files from older pi layouts, as upstream pi does. For example, it moves oauth.json into auth.json.
Differences from upstream pi
pi-rust ports the upstream pi CLI and its libraries. This section lists the differences and SDK limits.
Runtime
New Kimi Code OAuth logins use the global
.aiendpoints. To sign in to mainland China, setKIMI_CODE_OAUTH_HOST=https://auth.kimi.com. The login stores its OAuth and API endpoints for later refreshes; older logins without this metadata retain their mainland endpoints. ExplicitKIMI_CODE_OAUTH_HOSTandKIMI_CODE_BASE_URLvalues override saved endpoints. A custom modelbaseUrlinmodels.jsonstays in effect. Kimi and Moonshot tool requests infer omitted types from enums, constants, and unambiguous schema structure.Extensions run on an embedded QuickJS engine, so pi-rust does not need Node.js. All Node built-in modules load. These include:
zlibwith gzip, brotli, and zstd.async_hookswithAsyncLocalStorage, andv8serialization.- The network modules
net,tls,dgram,dns,http,https, andhttp2. vmcontexts with timeouts,worker_threads, andcluster. They can send socket and server handles over inter-process communication (IPC).node:sqliteon the bundled SQLite,node:testwith TAP and spec output, andreplover any streams.- In-process
inspectorsessions, andwasiwith aWebAssemblyglobal on the wasmi interpreter.
The APIs that do not work throw
ERR_PI_UNSUPPORTED. Examples arecrypto.subtleother thandigest, and rarecryptociphers such as Camellia.crates/pi-js/src/unsupported.rslists all of them. Native npm addons cannot load on QuickJS.To run extensions on Node 22 or later, set
extensionRuntimeto"node"or"auto", or use--extension-runtimeorPI_EXTENSION_RUNTIME. On Node, native addons,child_process.fork, and V8-only modules work. If Node is missing, pi uses QuickJS. See Node backend.IPC handle retries use a pi-js-specific wrapper. Internal handle listeners receive an object with only
close(), and cluster connections queued to a disconnected worker are not reclaimed. See Extension runtime.On non-Linux Unix, a concurrent child spawn can inherit an IPC socket before QuickJS marks it close-on-exec. Node closes inherited descriptors in its macOS
posix_spawnpath. See Platform.The extension SDK still has gaps in child sessions, resource loading, and model runtimes. A
DefaultResourceLoaderwith extensions serves one child session for eachreload(), and its factories run in the extension host of the caller.SettingsManagersupports custom storage and queued writes, with limits on JSON values and live object references. See Extension module exports for the remaining differences.The providers that extensions get from
@earendil-works/pi-ai/providers/allstream, classify, generate images, and resolve auth in Rust. Their API key login asks for one key, also for Amazon Bedrock, Google Vertex AI, and Cloudflare. See Extension module exports.When you quit the interactive mode, pi waits at most 3 seconds for the running turn and the
session_shutdownhandlers, then exits. Upstream pi waits until they finish.grepandfinduse the Rustignorecrate, so pi-rust does not downloadrgorfd.The version check and
pi update --selfuse the releases of this repository.Word movement in Chinese, Japanese, Korean (CJK), and Thai text uses ICU4X dictionaries. Thus some word boundaries are different from
Intl.Segmenterin Node.pi-envlooks for remote daemons in api-env-daemonsfolder next to thepiprogram. Each release has api-env-daemons-<tag>.tar.gzarchive with the daemons for Linux, Android (Termux), macOS, and Windows on x86-64 and arm64. Extract this archive in the folder that containspi.pi experimentaland its commandsserver,client,durable, andvacationneedPI_EXPERIMENTAL=1, as in upstream pi.serverandclientuse Unix sockets. On Windows, they show a message that they need Unix. Upstream pi also has no Windows transport.When a local shell command exits, pi-durable still stops waiting for output 100 ms after the exit or the last chunk after it, as upstream does. It then delivers queued chunks and any chunk the readers finish reading before they observe the stop signal. On Unix it also takes at most 64 KiB more per stream if readable without waiting. On Windows it starts no further read. See Platform.
Extension and login
selectmenus show at most 10 options and fewer in short terminals, with a(n/total)counter, so the selected option stays visible. Upstream pi shows all options.
Additions
| Addition | Upstream pi | Docs |
|---|---|---|
The slash commands /diff, /init, /review, /context, /undo, and /retry |
Has none of them. Shows context use only in the footer. | Interactive commands |
Markdown export: /export notes.md and pi --export session.jsonl notes.md |
Exports only HTML and JSONL | Export |
Prompt history across sessions, with the Ctrl+R search and the promptHistory settings |
Keeps prompt history only while the process runs | Prompt history |
| Esc clears the input draft when the agent is idle, and undo restores the draft. Submitted slash commands join prompts and shell commands in the Up and Down history. | ||
pi completion and pi doctor |
Has neither command | CLI |
pi sessions and pi stats |
Lists and deletes sessions only in its session picker (pi -r and /resume). Shows usage only for the current session (/session). |
Sessions |
pi extensions lists, installs, removes, enables, and disables extensions through the package and resource settings |
Extensions | |
marketplace: package sources and pi extensions search and info use signed indexes and checksummed native binaries |
Has no Rust extension marketplace | Marketplace |
The /extensions browser searches, installs, updates, removes, enables, and disables extensions, then offers a reload |
Has no /extensions command |
/extensions |
Run limits (--max-turns, --max-cost) and structured output (--output-schema, --output-retries) |
Run limits | |
pi --mode acp. Permission modes are separate from thinking levels and control tool execution. The stdio MCP servers the client sends connect for that session. |
Needs the separate pi-acp adapter | ACP mode |
| Account model lists for OpenAI Codex, Anthropic, GitHub Copilot, OpenAI, xAI, Google, and Cursor | Limits only OpenRouter | Account model lists |
/usage, pi usage, and the native extension method usage.get show the subscription limits of the Claude, ChatGPT (Codex), Cursor, SuperGrok (xai, with Grok Build), and Google Antigravity logins: the 5-hour and weekly windows, the used percentage, and the reset time |
Has no usage report | Subscription usage limits |
Fast mode for models that have one: /fast, --fast, the fastMode setting, the ACP Speed option, and RPC set_fast_mode |
Has no fast mode | Fast mode |
The providers cursor and google-antigravity. Antigravity supports /acp mode, /model, and /thinking before a prompt, with the agent confirming selections before pi saves them. |
Has none of them | Subscription providers |
ACP agents as providers: Kiro CLI (V3), Amp, and the agents of the ACP registry run over stdio with their own tools. /acp installs them from the registry in the global or project settings, logs in, enables, disables, moves, and sets the default. The acpAgents setting stores them. They get pi's MCP servers, their slash commands complete in the editor, and /undo covers their file changes. |
Has no ACP client | ACP agents |
The global disabledProviders setting hides providers from model selection and keeps their credentials. The TUI /settings menu has a Disabled providers list. |
Disable providers | |
/settings items for the retry.* and retry.provider.* values |
Sets these values only in settings.json |
Retry settings |
| A terminal notification when a run takes 10 seconds or more | Has this only as the example extension notify.ts |
Notifications |
The status line and /statusline are the marketplace:statusline extension (pi install marketplace:statusline). It reads the legacy statusLine setting. Interactive mode offers to install it when statusLine is set. |
Changes the footer only through extensions | Status line |
| More harness themes | Themes | |
The iTerm2 integration and /terminal-setup are the marketplace:iterm2 extension (pi install marketplace:iterm2). It reads the legacy terminal.iterm2 setting. Interactive mode offers to install it when terminal.iterm2 is on. |
iTerm2 integration | |
Extension UI calls: ctx.ui.writeTerminal(data, { tmuxPassthrough }) writes raw bytes to the terminal. Footer data of ctx.ui.setFooter also has getSessionStats() (input, output, cacheRead, cacheWrite, cost, contextTokens, contextWindow, contextPercent) and getRunState() (idle, working, blocked, done, or error). |
Has none of them | |
Native extensions: a package lists programs in package.json pi.native, and pi runs each one as an extension over a JSON-RPC protocol on stdio |
Loads only TypeScript and JavaScript extensions | Native extension protocol |
Extensions call a tool of an MCP server of the session outside of a tool call, for example for a hook: pi.callMcpTool(server, tool, args) and the native method mcp.callTool |
Has no MCP tool calls for extensions | mcp.callTool |
Extension events for hook runners: instructions_loaded, prompt_expansion (can block a skill or template prompt or add context), notification, tool_call_blocked, and cwd_changed. session_start handlers can call ctx.switchSession(). |
Has none of these events. Only command contexts have switchSession. |
pi-rust events |
Native extensions draw the rows of tools without renderers, such as the built-in tools (toolRenderers), animate a spinner inside drawn rows, refresh rows on a timer, read the TUI theme (ui.getTheme, theme.changed), and set the working indicator. ctx.ui.setChatStyle (ui.setChatStyle) puts prefixes before user and assistant messages, collapses finished thinking, and rounds the editor |
Renderers | |
Native extensions write their own top-level settings key in the global or a trusted project settings.json with settings.set. pi refuses its own setting keys. |
Extensions have no settings write | settings.set |
pi.registerProvider takes oauth: { builtin: "<provider id>", name? }: the provider logs in and refreshes with a login flow of pi, and stores the credential under its own id |
Reuses a flow only through an imported OAuth object | provider.register |
Extension widgets above and below the editor share a budget of a third of the terminal rows. Over the budget, each widget shows its first line. Alt+W (app.widgets.toggle) and /widgets collapse, expand, or auto change this, and /widgets shows all widgets in full in the chat. |
Caps only text widgets, at 10 lines each | /widgets |
MCP elicitation: servers can ask the user for form data or to open a URL. The extension events mcp_elicitation and mcp_elicitation_result can answer a request or change the answer of the user. |
Has no MCP elicitation | MCP elicitation events |
The extension event message_display replaces the text of an assistant message on the screen in the TUI. The session and the model context keep the original text. JavaScript and native extensions can listen to it. |
Has no display-only event. registerMarkdownTransformer changes the Markdown at each render. |
Events |
A choice of extension engine: the extensionRuntime setting, --extension-runtime, and PI_EXTENSION_RUNTIME (quickjs, node, or auto) |
Always runs extensions on Node | Extension runtime |
Bug fixes that are open upstream
The numbers are upstream issue numbers.
- If you remove a tool from the first tool list, later Anthropic requests do not fail (upstream issue 11376).
- On Bedrock,
strict: "prefer"tools change to non-strict when the strict tools have more than 16 optional parameters (11416). modelOverridesinmodels.jsonalso apply to classifier and image models:name,input,inputLimits, andcost. For classifiers,contextWindowandcompatalso apply (11223).- The editor removes escape sequences from pasted text. If the end marker of a paste does not arrive, the paste ends after 10 seconds without input or at 16 MiB. Then Ctrl+C works again (11383).
- MCP HTTP replies that are plain JSON obey
maxMessageBytes(11335). - A code mode script can declare its own top-level
toolsorconsole(11226). - Branch summaries from
/treeuse the selected thinking level (11444). If you resume a session after/tree, pi restores the thinking level that you used last (11451). - pi removes mouse reports and other escape sequences with private parameters, such as
ESC[<35;59;1M, from tool output (11377). - In
pi -p, a prompt that an extension command sends withsendUserMessageruns before pi exits (11238). - An unpinned
-e npm:package updates when npm has a newer version (11375). pi.execkeeps a maximum of 16 MiB of output from a command. It stops the command when the output gets to that limit (11360).pi-envwatches a directory again after the kernel drops the watch and the directory keeps its inode (11342).
Crates
| Crate | Contents |
|---|---|
pi-ai |
Message types (JSON-compatible with pi), streaming events, providers, OAuth, the model registry, and catalogs |
pi-agent |
The agent loop, tool argument validation, and the stateful Agent |
pi-tui |
The terminal UI library: differential rendering, editor, markdown, images, and components |
pi-mcp |
The MCP client (stdio and HTTP, OAuth) and server manager |
pi-codemode |
Codemode: a sandboxed JavaScript runtime in which the model writes scripts that call tools |
pi-js |
Embedded QuickJS with Node-style modules and TypeScript, for pi extensions |
pi-coding-agent |
Tools, sessions, compaction, resources, extensions, the interactive TUI, the print, JSON, RPC, and ACP modes, and the pi CLI |
pi-chord |
Chord: an application composition runtime for services, replicated state, RPC, and plugins |
pi-telemetry |
Vendor-neutral telemetry contracts and typed schema utilities |
pi-schema |
TypeBox-compatible JSON Schema checks, defaults, and value cleanup, for pi-ai and pi-chord |
pi-embedded |
In-process pi sessions for native and Rust applications, with a C ABI (include/pi_embedded.h) |
pi-protocol, pi-client, pi-server |
The CBOR wire protocol, its client, and its server over Unix sockets |
pi-durable |
Pi Durable: durable sessions on memory, SQLite, or JSONL storage, the harness, and its coding tools |
pi-env, pi-env-daemon |
Remote execution environments for Pi Durable over SSH, and the pi-env daemon that runs on the remote machine |
pi-evals |
Behavioral evals for the coding agent: host evals and a documentation-lift comparison in Docker (not published) |
Development
cargo fmt --all
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
The tests use the faux provider and local mock HTTP servers. They do not need API keys or network access.
Releases
Versions obey Semantic Versioning. The commit messages set the next version, as in Conventional Commits:
| Commit | Release |
|---|---|
fix:, perf:, revert: |
patch |
feat: |
minor (patch before 1.0) |
feat!:, fix!:, or a BREAKING CHANGE: footer |
major (minor before 1.0) |
docs:, chore:, ci:, test:, refactor:, style:, build: |
none |
After continuous integration (CI) passes on main, the Release workflow runs cargo xtask plan. If a release is necessary, the workflow does these steps:
- It increases the workspace version.
- It adds the new section at the top of
CHANGELOG.md. - It commits
chore(release): vX.Y.Zand adds the tagvX.Y.Z. - It builds all targets.
- It publishes the GitHub release with checksums.
Other ways to start the workflow:
- Push a
vX.Y.Ztag that matchesCargo.toml. The workflow releases that version. - Push a
vX.Y.Z-rc.1tag. The workflow publishes a pre-release. - Run the workflow manually with
dry_run. The workflow builds all targets and does not release. - Run the workflow manually with
bumpset topatch,minor, ormajor, and withdry_runoff. The workflow releases when the commits do not need a release.
cargo xtask plan # next version and release decision
cargo xtask prepare 0.2.0 # set the version and update CHANGELOG.md
cargo xtask notes 0.2.0 # print release notes
License
MIT. pi-rust is based on pi by Mario Zechner. See LICENSE.
These parts come from other projects. Each release archive includes their license notices.
| Part | Source | License file |
|---|---|---|
| ACP mode | pi-acp by Sergii Kozak | LICENSE-pi-acp |
| Some JavaScript modules of the extension runtime | Node.js | LICENSE-node |
| JSON syntax diagnostics in the extension runtime | V8 | LICENSE-v8 |
| MCP OAuth code, ported from upstream pi | MCP TypeScript SDK | LICENSE-mcp-typescript-sdk |
Warning colors of loadProjectContextFiles in the extension SDK |
chalk 6.0.0 by Sindre Sorhus | LICENSE-chalk |
| Settings JSON error messages | V8, BSD 3-Clause | LICENSE-v8-settings |
File locks and exit cleanup for ProjectTrustStore |
proper-lockfile 4.1.2 and signal-exit 3.0.7 | LICENSE-proper-lockfile, LICENSE-signal-exit |
The release archives also include THIRD-PARTY-LICENSES.md with the licenses of the third-party Rust crates in the binaries. The Release workflow writes it with cargo-about from about.toml and about.hbs.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found