pi_agent_rust: a Rust-native AI coding agent CLI with capability-gated extensions
High-performance AI coding agent CLI written in Rust with zero unsafe code
At a glance
- What is it?
- pi_agent_rust is a from-scratch Rust port of Pi Agent that ships a single `pi` binary, a structured concurrency runtime, and a two-stage extension execution guard. It is aimed at long-running, extension-heavy sessions, and the README is explicit that it is no longer chasing drop-in parity with the legacy TypeScript Pi.
- Who is it for?
- Adopt pi_agent_rust if you run long, extension-heavy terminal sessions and want a single native binary with an auditable extension trust lifecycle; skip it if you need a stable drop-in replacement for the legacy TypeScript Pi, because the README states that parity is no longer the target.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What pi_agent_rust actually solves, and for whom
The README frames the problem in four complaints about existing terminal assistants: slow startup from managed runtimes, memory overhead from Electron or heavy runtimes, streaming and session corruption, and extension systems that are either closed or complicated. pi_agent_rust answers with a native Rust binary named `pi`, built from a from-scratch port of Pi Agent by Mario Zechner, which the README says was made with his blessing.
The audience is narrower than "anyone who wants an AI in their terminal". The README's own TL;DR is addressed to Pi and OpenClaw users, and the stated design center is large-session, multi-agent, and extension-heavy workloads. If you open a short prompt once a day, the extension machinery described below is weight you will never use. If you run agents that stay alive, load third-party extensions, and execute shell commands on your behalf, that machinery is the reason to look at this project rather than a wrapper around an API.
One thing to read carefully before adopting: the README states that the project is no longer trying to be a strict drop-in replacement for the legacy TypeScript Pi, and that legacy Pi is historical context rather than a compatibility authority. OMP is named as the closer reference for feature surface, workflows, and UI. So the pitch is a Rust-native agent that may intentionally diverge, not a compatible reimplementation.
How the runtime is put together: asupersync, rich_rust, and a bounded hostcall mesh
The port is not a line-by-line translation. It is built on two purpose-built Rust libraries: asupersync, described as a structured concurrency async runtime with built-in HTTP, TLS, and SQLite, and rich_rust, a Rust port of the Rich terminal formatting library. Structured concurrency is the interesting choice here. It gives the runtime a defined cancellation and lifecycle model, which matters when an agent session holds open tool calls, HTTP requests, and extension realms at the same time.
Extension execution runs over what the README calls a deterministic hostcall reactor mesh, with shard affinity, bounded SPSC lanes, backpressure telemetry, and optional NUMA slab tracking. The practical consequence of bounded lanes is that queue pressure becomes observable rather than silent. The README also describes cold owner-isolated JS realms on every reload, paired with a persistent versioned transpile cache on disk, so mutable JavaScript state is not carried across reloads.
Hostcalls are capability-gated across six named lanes: `tool`, `exec`, `http`, `session`, `ui`, and `events`. Enforcement is two-stage for `exec`: the capability gate runs first, then command mediation inspects the command, with DCG and heredoc AST signals used to catch destructive intent hidden inside multiline wrappers. The README lists recursive delete, disk and device writes, and reverse shells as classes blocked by default, with strict or safe policy able to tighten further to high-tier classes. That is a real design position: the guard sits before spawn, not after.
Install pi_agent_rust and run a first session
The README's installation path is a shell script fetched from the repository and piped into bash. The query string with `date +%s` is there to defeat caching, exactly as the README writes it:
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/pi_agent_rust/main/install.sh?$(date +%s)" | bashThe README states that official release archives install the single end-user binary `pi`. There is also an `uninstall.sh` at the repository root if you want to reverse it. Piping a remote script into a shell is a decision you should make deliberately; the alternative the README offers is the release archives.
Once `pi` is on your PATH, the README gives three invocation shapes. A plain prompt starts a session:
pi "Help me refactor this function to use async/await"`--continue` resumes a previous session, and `-p` runs single-shot with no session, which is what you want when you are piping a file in:
pi -p "What does this error mean?" < error.logTool availability is worth knowing before your first run. The README says there are 36 built-in tools, of which 19 are in the default `--tools` list and 14 are always present in the model's schema. The remainder are reachable through the `xdev` dispatcher or by enabling them in settings. If a tool you expect is missing, that split is the first place to look.
The extension trust lifecycle is the part worth studying
Extensions move through four states: `pending`, `acknowledged`, `trusted`, and `killed`. The README describes kill-switch audit logs and explicit operator provenance, meaning the record shows who pulled the switch and why, and restoring access requires re-acknowledgement. For anyone running third-party extensions against a real codebase, this is a more useful primitive than a blanket enable/disable flag.
There are also two hostcall-lane emergency controls, `forced_compat_global_kill_switch` and `forced_compat_extension_kill_switch`. These force compatibility-lane execution either globally or for one extension, without disabling the extension system. The README positions this as containment for fast-path regressions. It is an admission that the fast lane can misbehave, paired with a way to keep working while it does.
The security posture extends to policy, runtime risk, and quota enforcement on the execution path, plus auditable runtime signals and ledgers with redacted alerts for extension behavior. Whether the enforcement matches the description is something you should verify in `src/` and the tests directory rather than take on faith; the README describes the model, and the repository is where the model would be implemented.
Where the evidence stops: benchmarks, licensing, and release tooling
The README has a section titled Benchmark Methodology and Claim Integrity, and the rule it states is strict: release-facing performance numbers are published only when checked-in evidence artifacts are current, have matching run provenance, and show data and a passing result for every declared budget with no data-contract failures. Historical benchmark snapshots are retained in planning and evidence artifacts but are not treated as current README claims until the gate is regenerated cleanly. Read that as the project telling you it has no current headline number to hand you. Any startup or throughput figure you see quoted elsewhere should be traced back to the evidence artifacts before you repeat it.
Licensing is genuinely ambiguous from the surface. The README badge says MIT plus Rider, the Cargo.toml uses `license-file = "LICENSE"` rather than a standard SPDX `license` field, and the repository metadata reports the license as NOASSERTION. The LICENSE file is the authority here. If the terms matter to your organization, read that file rather than the badge.
Build and release flow is also unusual. The README states that all quality checks, builds, and releases run through Doodlestein Self-Releaser (DSR), that contributors must not invoke Cargo or RCH directly, and that GitHub Actions is never an execution or evidence authority for this project. The registered quality recipe is `dsr quality --tool pi_agent_rust`, and the canonical build and release commands are documented in docs/releasing.md. If your team expects a conventional `cargo build` contribution path, this is a real friction point, not a stylistic preference.
The case against: parity, contribution model, and the wrong fit
The clearest limitation is stated by the project itself. If you have scripts, prompts, or extension code written against the legacy TypeScript Pi, the README says the project is no longer targeting strict drop-in replacement, and that legacy Pi is not the compatibility authority. Migration is therefore an open question rather than a supported path. The README does not document rollback, and it does not document a migration procedure from legacy Pi.
The contribution model is the second constraint. Direct Cargo and RCH invocations are disallowed for contributors, and GitHub Actions carries no evidentiary weight. A developer who wants to clone, patch, and run `cargo test` on a hunch is working against the project's stated process. The repository does carry an UPGRADE_LOG.md and a CHANGELOG.md, so upgrade history exists, but the README does not describe a supported upgrade path between releases.
The wrong tool test is simple. If you want a small assistant that answers a question and exits, `pi -p` works but the extension system, trust lifecycle, and hostcall mesh are dead weight. If you need a stable, compatible successor to an existing Pi setup today, this is not it. And if you cannot accept installing through a piped shell script or a release archive with no documented package-manager route, the README offers you no third option.
How pi_agent_rust differs from other terminal coding agents
The natural comparison is the legacy TypeScript Pi this project ports. The difference is architectural rather than cosmetic: legacy Pi runs on a managed JavaScript runtime, while pi_agent_rust is a native binary built on asupersync and rich_rust. The README's stated motivation for that move is startup and runtime overhead. The trade-off is that the two projects have diverged in behavior, and the README says so directly.
The README's own TL;DR also addresses OpenClaw users, positioning the port as keeping the core workflow while changing the engine underneath. That framing is honest about what is preserved and what is replaced.
Against a general-purpose agent framework, the distinction is the capability model. Most terminal agents treat tool execution as a trust decision made once, at install time. pi_agent_rust layers a per-extension trust lifecycle, a two-stage `exec` guard with command mediation, policy and quota enforcement, and lane-level kill switches on top. That is a heavier model, and it only pays off if you actually run extensions you did not write.
Editorial conclusion
Adopt pi_agent_rust if you run long, extension-heavy terminal sessions and want a single native binary with an auditable extension trust lifecycle; skip it if you need a stable drop-in replacement for the legacy TypeScript Pi, because the README states that parity is no longer the target. Before committing, verify three things in the repository: that docs/releasing.md describes a release path you can actually follow, that the performance evidence gate has been regenerated cleanly, and what LICENSE actually grants, since the license file is the authority and the Cargo.toml points at it rather than naming a standard SPDX identifier.
Frequently asked questions
How do I use pi_agent_rust?
The README gives three invocation shapes: a plain prompt such as `pi "Help me refactor this function to use async/await"` starts a session, `--continue` resumes a previous one, and `-p` runs single-shot with no session, which is what you want when piping a file in with `< error.log`.
Is pi agent good?
That depends on your workload. The README targets large-session, multi-agent, and extension-heavy use, and it states plainly that the project no longer aims to be a strict drop-in replacement for the legacy TypeScript Pi, so compatibility with an existing Pi setup is not a reason to pick it.
What can a pi agent do?
The README states there are 36 built-in tools, with 19 in the default `--tools` list and 14 always present in the model's schema; the rest are reachable through the `xdev` dispatcher or by enabling them in settings. It can also load extensions, which run under capability-gated hostcalls across `tool`, `exec`, `http`, `session`, `ui`, and `events` lanes.
Is pi agent better than OpenCode?
The README does not compare pi_agent_rust with OpenCode, so there is no basis for that judgement here. It does name OMP as the closer reference for feature surface, workflows, and UI, and states that Pi Rust may intentionally differ from both legacy Pi and OMP where a Rust-native approach is simpler or safer.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dicklesworthstone-pi-agent-rust)