Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ lower is better. See [Benchmarks](#benchmarks).</sub>
curl -fsSL https://pi-bolt.opensec.in/install.sh | sh
```

The same command installs Pi-Bolt on Linux x86-64 and ARM64, on macOS, and on Android in Termux.
The same command installs Pi-Bolt on Linux x86-64 and ARM64, on macOS, and on Android in Termux. On Arch Linux there is also
a community package in the AUR, [`pi-bolt-avx2-bin-release-git`](https://aur.archlinux.org/packages/pi-bolt-avx2-bin-release-git)
(the x86-64 AVX2 build, signature checked): `paru -S pi-bolt-avx2-bin-release-git`.

On Windows, in PowerShell:

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.9.0
0.9.1
111 changes: 111 additions & 0 deletions docs/releases/0.9.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
Pi-Bolt 0.9.1 adds `pi-bolt compile`, `pi-bolt update --rollback` and a beta channel, built-in `grep` and `find`, `pi-bolt
doctor`, Pi as an MCP server (`pi-bolt --mcp`), more of the Agent Client Protocol for editors, Pi's package list shared with Pi,
Comment thread
Kushalkhemka marked this conversation as resolved.
and Linux executables linked with RELRO. Everything else is [0.9.0](0.9.0.md).

### `pi-bolt compile`

Compiles the extensions installed on this machine into the installed Pi-Bolt, on Linux and macOS, with no checkout or tools: a
new release asset per platform, `pi-bolt-kit-<platform>.tar.gz` (about 7 MB), holds what the release build read, and is checked
against the signed `SHA256SUMS` like the runtime. `pi-bolt update` compiles the same extensions into each new release. A
compiled-in extension loads in under a millisecond instead of 10-90 ms; one changed since loads from its files, with a warning.

### Updates

- `pi-bolt update --rollback` puts back the build the last update replaced, without downloading anything; again goes forward.
- `pi-bolt update --channel beta` also takes pre-releases (`--channel stable` goes back). Signatures are checked as before.

### `grep` and `find` built in

Pi-Bolt's `grep` and `find` tools search in-process, with the same parameters and output and nothing to install or start: no
ripgrep or fd. They follow ripgrep's and fd's rules as Pi runs them (`.gitignore`, `.ignore`, global excludes, hidden and binary
files, `--glob`). With `opensec-pi-fff` or `@ff-labs/pi-fff` loaded, its search tools are used instead.

### `pi-bolt doctor`

- **A report to paste into an issue.** It covers:
- the build: version, Pi version, platform, JIT on or off, the runtime it was built with, and whether its compiled code is used;
- how and where Pi-Bolt is installed, and every `pi-bolt` on `PATH`;
- whether the release's signature verifies, and the latest version;
- extensions: compiled in, run at run time, or failing to load, and which use `bun:ffi`;
- how Pi's `packages` and Pi-Bolt's `piBolt.packages` differ;
- the Herdr and editor (ACP) setup, and the problems it finds, such as another `pi-bolt` earlier on `PATH`.

It prints no keys or tokens, and shows the home folder as `~`. `--offline` leaves out the signature and version checks.
- **Extensions that need the JIT say so.** On the default build, "bun:ffi requires the JIT" now names the extension and gives the
command that installs the JIT build, for the installer or npm:
`pi-foo needs Pi-Bolt's JIT build (bun:ffi); switch with: curl -fsSL https://pi-bolt.opensec.in/install.sh | PIBOLT_VARIANT=arm64-jit sh`.
The extension is named when it fails to load, when one of its handlers fails, and in a notice it shows itself.

### Pi as an MCP server

`pi-bolt --mcp` serves Pi to other agents and MCP clients (Claude Code, Codex, Cursor, ...) over stdio:

- `prompt` runs a prompt in a Pi session (with `cwd`, `sessionId`, `model`, `thinking`) and returns Pi's answer and the session's
id; a later call continues the session, in the same process or a later one. `list_sessions` lists them.
- Progress while Pi works: each tool, the first line of each message, a running command's latest line, and a heartbeat.
- Cancelling stops the turn. Up to eight sessions stay open; prompts to one session run in order, different sessions at once.
- Extension dialogs reach the client as elicitation forms when it offers them.

[docs/MCP.md](https://github.com/opensec-git/Pi-Bolt/blob/pi-bolt/docs/MCP.md) has the setup for each client.

### Editors (ACP)

- **Modes:** Default and Read-only (the model gets only `read`, `grep`, `find` and `ls`), as modes and as a config option.
- **Sessions:** delete and fork; compactions shown live and in a loaded session's history.
- **Commands** that need no terminal: `/model`, `/thinking`, `/session`, `/export`, `/reload`, besides `/compact` and `/name`.

### Packages shared with Pi

Pi-Bolt uses Pi's `packages` list: `pi-bolt install` and `pi-bolt remove` change it, as `pi install` does, and Pi and Pi-Bolt load
the same extensions. `--pi-bolt` changes `piBolt.packages` instead, which adds to Pi's list, replaces an entry of it, or leaves
one out (`-<source>`) for Pi-Bolt only. A copied list from an earlier Pi-Bolt is turned into that once, so what Pi-Bolt loaded
stays the same. (Thanks to @boonlai, #30.)

### Linux

- **RELRO:** the Linux executables are linked with `-z relro -z now`, so the loader's tables are read-only once it is done. They
stay at a fixed address, which the prebuilt heap needs.
- **Arch Linux:** the community package `pi-bolt-avx2-bin-release-git` in the AUR, in the README.

### npm on Windows

The Windows builds are published to npm as `@kushalkhemka/pi-bolt-win32-x64` and `-jit`, where `npm install -g pi-bolt` on Windows
now gets them; it used to fall back to GitHub.

### Engine

All four runtimes are new, built by the `runtime` workflow on GitHub's runners: the Linux link flags above, and the runtime's
stamp next to it, which `pi-bolt doctor` reports.

### Install

```bash
curl -fsSL https://pi-bolt.opensec.in/install.sh | sh
```

```powershell
irm https://pi-bolt.opensec.in/install.ps1 | iex
```

```bat
powershell -c "irm https://pi-bolt.opensec.in/install.ps1 | iex"
```

or `pi-bolt update`, or `npm install -g --allow-scripts=pi-bolt pi-bolt`, or `bun add -g --trust pi-bolt`.

| Asset | For |
|---|---|
| `pi-bolt-linux-x64.tar.xz` / `.tar.gz` | **Recommended on Linux x86-64.** CPUs with AVX2 (Intel Haswell 2013+, AMD Zen+). |
| `pi-bolt-linux-x64-baseline.tar.xz` / `.tar.gz` | Any x86-64 CPU with SSE4.2. |
| `pi-bolt-linux-x64-jit.tar.xz` / `.tar.gz` | JIT also on, for plugins loaded at run time. |
| `pi-bolt-linux-arm64.tar.xz` / `.tar.gz` | **Linux on ARM64**, any 64-bit ARM CPU; Android in Termux, with the installer. |
| `pi-bolt-linux-arm64-jit.tar.xz` / `.tar.gz` | Linux on ARM64, JIT also on. |
| `pi-bolt-darwin-arm64.tar.xz` / `.tar.gz` | **macOS.** Macs with Apple silicon, macOS 13 or later. |
| `pi-bolt-darwin-arm64-jit.tar.xz` / `.tar.gz` | macOS, JIT also on. |
| `pi-bolt-win32-x64.zip` | **Windows.** Windows 10 (1809) or 11 on x64; compiled code on AVX2 CPUs, bytecode on others. |
| `pi-bolt-win32-x64-jit.zip` | Windows, JIT also on. |
| `pi-bolt-runtime-linux-x64.tar.gz`, `pi-bolt-runtime-linux-arm64.tar.gz`, `pi-bolt-runtime-darwin-arm64.tar.gz`, `pi-bolt-runtime-win32-x64.zip` | The Pi-Bolt Bun runtime, for compiling plugins in. |
| `pi-bolt-kit-linux-x64.tar.gz`, `pi-bolt-kit-linux-arm64.tar.gz`, `pi-bolt-kit-darwin-arm64.tar.gz` | What `pi-bolt compile` builds with, besides the runtime. |

Linux x86-64 or ARM64 with glibc 2.17 or later; Android 7 or later on 64-bit ARM, in Termux; macOS 13 or later on Apple silicon;
Windows 10 1809 or later, or Windows 11, on x64.
2 changes: 1 addition & 1 deletion npm/bin/pi-bolt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# replaces this script with the native executable (exec), so the launcher costs no startup time.
set -eu

VERSION=0.9.0
VERSION=0.9.1
HOME_DIR="${PIBOLT_HOME:-$HOME/.pi-bolt}"

if [ "$(uname -s)" = Darwin ]; then PLATFORM=darwin; else PLATFORM=linux; fi
Expand Down
2 changes: 1 addition & 1 deletion npm/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pi-bolt",
"version": "0.9.0",
"version": "0.9.1",
"description": "Pi, the coding agent, compiled ahead of time to native code: one executable for Linux x86-64 and ARM64 (Android too, in Termux), macOS on Apple silicon and Windows x64, starts 2-3x sooner than Pi on Bun and uses about a third of its CPU over a session",
"keywords": [
"pi",
Expand Down
49 changes: 39 additions & 10 deletions patches/bun.patch
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ stale and rewrote in turn.
.../libuv/win-thread-stack-reservation.patch | 19 +
.../page-commit-on-demand-default.patch | 22 +
scripts/build/CLAUDE.md | 2 +-
scripts/build/binary-expectations.ts | 32 +-
scripts/build/binary-expectations.ts | 41 +-
scripts/build/bun.ts | 18 +-
scripts/build/deps/libuv.ts | 7 +-
scripts/build/deps/mimalloc.ts | 11 +-
scripts/build/deps/webkit.ts | 56 +-
scripts/build/download.ts | 28 +-
scripts/build/fetch-cli.ts | 39 +-
scripts/build/flags.ts | 47 +-
scripts/build/flags.ts | 53 +-
scripts/build/ninja.ts | 1 +
scripts/build/rust.ts | 3 +
scripts/build/source.ts | 10 +
Expand Down Expand Up @@ -177,7 +177,7 @@ stale and rewrote in turn.
test/napi/napi-app/binding.gyp | 10 +
...eue_async_work_in_finalizer_experimental.c | 87 ++
test/napi/napi.test.ts | 81 ++
131 files changed, 6513 insertions(+), 915 deletions(-)
131 files changed, 6521 insertions(+), 922 deletions(-)
create mode 100644 patches/libuv/win-thread-stack-reservation.patch
create mode 100644 patches/mimalloc/page-commit-on-demand-default.patch
create mode 100644 test/js/node/process/fd-nonblock-fixture.js
Expand Down Expand Up @@ -359,7 +359,7 @@ index 4d067e9044..41c47fee81 100644
**`isExecutable` must check `isFile()`.** `X_OK` on a directory means traversable — a `cmake/` dir in PATH would shadow the real cmake binary.

diff --git a/scripts/build/binary-expectations.ts b/scripts/build/binary-expectations.ts
index f18a60b06b..0ba5981b7f 100644
index f18a60b06b..fabdf34910 100644
--- a/scripts/build/binary-expectations.ts
+++ b/scripts/build/binary-expectations.ts
@@ -7,9 +7,9 @@
Expand Down Expand Up @@ -470,7 +470,26 @@ index f18a60b06b..0ba5981b7f 100644
const localWebKitLibs =
cfg.webkit === "local" && cfg.linux && cfg.abi !== "android"
? ["libicudata.so.*", "libicui18n.so.*", "libicuuc.so.*"]
@@ -523,7 +523,7 @@ export function binaryExpectations(cfg: Config): BinaryExpectations {
@@ -425,14 +425,13 @@ export function binaryExpectations(cfg: Config): BinaryExpectations {
...(staticInitializers && { staticInitializers }),
elf: {
// Android requires PIE; everywhere else bun is a fixed-address
- // executable (-fno-pic, see flags.ts). No RELRO / BIND_NOW anywhere:
- // flags.ts links `-z norelro -z lazy` (a startup-time choice from
- // the CMake era, kept as is); recorded so a change is deliberate.
+ // executable (-fno-pic, see flags.ts). Pi-Bolt links Linux with
+ // `-z relro -z now` (flags.ts); FreeBSD keeps `-z norelro -z lazy`.
type: android ? "DYN" : "EXEC",
execStack: false,
rwxLoad: false,
- relro: false,
- bindNow: false,
+ relro: cfg.linux,
+ bindNow: cfg.linux,
tlsSegment: !android,
},
debugInfo: { symtab: true, debugSections: true, compressed: true },
@@ -523,7 +522,7 @@ export function binaryExpectations(cfg: Config): BinaryExpectations {
forbiddenImports: forbiddenImports(cfg),
// No initializer audit: PE has no symbol table to name .CRT$XCU entries by.
pe: {
Expand Down Expand Up @@ -803,7 +822,7 @@ index eebc97cc79..e8abff8093 100644
// github-archive dep fetch: download tarball, extract, patch, stamp
// ───────────────────────────────────────────────────────────────────────────
diff --git a/scripts/build/flags.ts b/scripts/build/flags.ts
index 3d40f647a4..bbbc26ad1e 100644
index 3d40f647a4..59befe77c9 100644
--- a/scripts/build/flags.ts
+++ b/scripts/build/flags.ts
@@ -499,6 +499,13 @@ export const globalFlags: Flag[] = [
Expand Down Expand Up @@ -854,20 +873,20 @@ index 3d40f647a4..bbbc26ad1e 100644
+ // .pblay is where the region's arenas are (bmalloc::StaticRegionLayout): read-only, since that decides where the engine
+ // reads and writes.
+ flag: ["/SECTION:.pbreg,R", "/SECTION:.pblay,R", "/guard:cf"],
when: c => c.windows,
- desc: "18MB stack reserve (JSC uses deep recursion), no error limit",
+ when: c => c.windows,
+ desc: "The static region's section is read-only until used; its layout is read-only; Control Flow Guard's table (/guard:cf)",
+ },
+ {
+ // The DLLs the executable imports are system DLLs: from System32 only (LOAD_LIBRARY_SEARCH_SYSTEM32), not from the folder
+ // the executable was unzipped to. The delay-loaded ones go there too (c-bindings.cpp, __pfnDliNotifyHook2).
+ flag: "/DEPENDENTLOADFLAG:0x800",
+ when: c => c.windows,
when: c => c.windows,
- desc: "18MB stack reserve (JSC uses deep recursion), no error limit",
+ desc: "Imported DLLs from System32 only",
},
{
flag: "/DEBUG:FULL",
@@ -1333,6 +1368,14 @@ export const linkerFlags: Flag[] = [
@@ -1333,12 +1368,22 @@ export const linkerFlags: Flag[] = [
when: c => c.abi === "android",
desc: "Android: bionic loader requires PIE",
},
Expand All @@ -882,6 +901,16 @@ index 3d40f647a4..bbbc26ad1e 100644
{
flag: [
"-Wl,--as-needed",
"-Wl,-z,stack-size=12800000",
- "-Wl,-z,lazy",
- "-Wl,-z,norelro",
+ // Pi-Bolt: RELRO with immediate binding (the GOT read-only after startup), at the cost of resolving the few hundred
+ // imports at startup instead of on first call.
+ "-Wl,-z,relro",
+ "-Wl,-z,now",
// (no --pack-dyn-relocs=relr: DT_RELR needs glibc ≥ 2.36 to load,
// and we wrap symbols for portability down to 2.17. With -no-pie
// there are <500 R_*_RELATIVE entries anyway — not worth the compat
diff --git a/scripts/build/ninja.ts b/scripts/build/ninja.ts
index e6a4479f14..b7c38f8aa3 100644
--- a/scripts/build/ninja.ts
Expand Down
Loading