Repository navigation
PiG 0.7.0
PiG 0.7.0 is a fix, SDK and Pi-catch-up release. It follows Pi v1.5.0 and carries two commits from Pi's main branch that are ahead of that release (D231 and D233). It follows PiG 0.5.3. There was no 0.6.0 release, so the work that was planned for it ships here. Install it with go install github.com/MichaelKinsy/PiG/cmd/pig@latest or npm i -g @pi-in-go/pig.
PiG is a Go implementation of Pi, the reference. Pi's behavior is the contract, and every place PiG differs is a numbered divergence. PiG is not an official Pi project, and Pi's maintainers have not endorsed it. It was created by Michael Kinsy and originally developed at Hewlett Packard Enterprise.
This is a minor release because it adds a large part of the extension SDK surface (Common Lisp extensions, Pi's Type, createProvider, the extension runner and session runtime), moves the Bedrock provider to its own Go package, changes the Durable watch API and bumps stored formats. Read "Upgrading" before you update Go code or share a Durable store with an older build.
Thanks
This release has fixes that came straight from your reports and patches 🐷
- @mblarsen reported #374, where a Node extension kept reading
ctx.isIdle()as false after a run settled, which held back pi-intercom messages. Their fix is the one that landed, with their authorship. - @dorokuma asked for #384, a way for a subprocess extension to remove the blank rows a hidden thinking run leaves, found a second trigger path, and tested the result against their compact-ui port before the release. They are also credited on the fix for the crash a markdown transformer could cause while an answer streams.
- @jihongwei reported #385, the embedded
reflect.Typethat made binaries about 6 MB larger when a reflection-heavy package such as protobuf was linked too, and sent #301 (MCP reconnect after a cancelled client cleanup) and #302 (extension entry append for embedding hosts). - @NicoSenerman reported #389, where
pig installrecorded a package path that startup could not resolve and the package's tools disappeared without a visible error. - @semiherdogan reported #395, where subagents of pi-open-agents failed to start, and traced it to the missing
dist/cli.js. - @ShoichiTect reported #396 and #397, the session that stopped again after
bgand theinterrupted system callafterfg, each with a paired Pi result. - @bharatvaj reported #402, where Option+Up did not remove a message from the steering queue in macOS Terminal.
- @runningman84 reported #380, the
llama.cpp returned HTTP 404from/llamaagainst llama-swap. - @balcsida reported #321 and #322 (SDK helpers and the edit override) sent #378, which scopes
BuildModel's catalog lookup to the requested provider, and sent herdr-app #299, which makes PiG a known agent in the herdr desktop app with its own icon, name and agent menu entry (in herdr 0.1.12 and later). - @rafiksalama is credited on the fix that stops a Session whose
Eventsnobody reads from blockingSend. - @SkrOYC asked for #308 and sent the Nix flake (#368).
- @xoviat asked for #315, the OpenRouter
:nitroand:floorvariants. - @nyxiereal sent #388, which resolved the landing blockers of the parity snapshot cleanup that keeps only the snapshots of the active Pi pin.
- @yxd-ym reported #299 and sent #300, so
pig statusno longer reports a shared extension name as an unhealthy duplicate. - @Neiko2002 reported #394, which made the bug report form require only "What happened".
Fixes for reported issues
- #374. The Node runtime answered
ctx.isIdle()from a cached value that changed only on events, while Pi reads it live. It now asks the host on each call, and tests in every SDK read it outside any event. Background callbacks such as pi-intercom's see a finished run as idle. - #380.
/llamaagainst llama-swap used to end in a barellama.cpp returned HTTP 404on load or unload, because llama-swap has no load or unload endpoint and loads a model when a request names it. PiG now recognises llama-swap and says to add it tomodels.jsonas anopenai-completionsprovider and pick models with/model. A 404 from a real llama.cpp router keeps Pi's text (D212). The llama.cpp docs page has a llama-swap section. - #384. An extension can call
pi.ownThinkingRuns(enabled)(OwnThinkingRunsin Go,own_thinking_runsin Rust and Python,own-thinking-runsin Lisp). While any extension owns thinking runs, a hidden run, or one that a Markdown transformer rewrote to empty text, leaves no stub row and no blank rows around it. It handles spacing only, so pair it with a transformer to hide the text. Without such an extension the message draws as Pi does (D214). - #385. The field metadata in
durable/internal/orderedembeddedreflect.Typeanonymously, which made the linker keep every exported method of every reachable type. The field is named now, and a test fails if an anonymous one returns. A program that links protobuf next to PiG is about 6 MB smaller. - #389.
pig install /abs/pathrecords the path as you typed it. Before, it stored a path relative to the agent directory, which resolved to nothing whenPIG_HOMEwas reached through another spelling (D215). A configured local Package whose directory is missing is a startup warning that names thepig removecommand, andpig install --validate-onlywith no source checks every local-path entry and exits 1 when one is missing (D216). Entries written by an earlier version stay relative, so runpig install <absolute path>again for those. - #395. PiG pointed
@earendil-works/pi-coding-agentat a shim file instead of a package root, sopi-open-agentslooked for adist/cli.jsthat was not there. The package now resolves to a root laid out like Pi's, withdist/index.jsand adist/cli.jsthat starts PiG.pi-agent-core,pi-tuiandpi-aigot the same layout. A test now compares every Pi package PiG serves against Pi's layout. - #396. A suspended session that gets SIGCONT while its process group does not own the terminal (
bg) no longer re-enters raw mode and draws into the shell. It stops again and waits forfg. Pi does the same as PiG did here, so this is a numbered divergence (D227). - #397. After Ctrl+Z,
bgandfg, the session returns instead of ending withError: interrupted system call, because raw-mode entry and exit retry an interrupted ioctl as Node's libuv does. A write to a terminal that went away now ends the session with exit 129 as Pi does, and any other terminal write error restores the terminal, records a crash and exits 1. Real-terminal stop,bgandfgtests now run on macOS. - #402. Terminal.app sends Option+Up as plain Up in its default profile, so PiG recalled history while the queued message stayed queued and still went out. In Terminal.app, plain Up with an empty editor and a queued message now restores the queued messages to the editor and clears the queue, and the hint under the queue names Up. In tmux, ssh and other terminals PiG shows one dim line, once per run, when Up recalls a copy of a queued message. Mapping Option+Up to
\033[1;3Ain Terminal's keyboard settings also works. Pi 1.5.0 behaves as PiG did before (D228).
Pi catch-up
- Pi v1.5.0, including Pi 1.5.0's schema validation of tool arguments as plain JSON Schema.
Type.Refinecallbacks are no longer run on a tool's arguments, so check such constraints in the tool'sexecute()(D226). - D231. RPC mode acts on an extension's
ctx.shutdown()while idle, for example from a timer, instead of waiting for the next command (Pi main 1708b4788, ahead of the pin). - D233. An MCP Streamable HTTP
application/jsonreply overmaxMessageBytes(default 16 MiB) is rejected withMCP JSON response exceeds N bytes, and an HTTP error body is read only up to its first 8 KiB (Pi main 4a8b60bc3, ahead of the pin). - Package changelogs. After a package update PiG shows the package's changelog entries under "Extension Updates", and a manifest may name its file with
pi.changelogPath. pi.exec()takesmaxBufferand reportstruncatedin every SDK, andkeyText()andkeyHint()format the user's keybindings in extension renderers.- Images are decoded and encoded the way Pi's Photon does, pixel for pixel on the oracle corpus, for PNG, JPEG, WebP, GIF, BMP and TIFF.
- The Durable core follows Pi's continue submissions,
maxTurns,afterRunhooks, deferred commits and telemetry spans.
Extension SDKs
- Common Lisp extensions.
pig extension init --lang lispscaffolds an ASDF system, and PiG builds it into a cached SBCL image that runs isolated or packed beside other Lisp extensions. The Lisp SDK serves the extension API the Go, Rust and Python SDKs serve. - The Go, Rust and Python SDKs export Pi's
Type(TypeBox 1.3.27),createProvider,createExtensionRuntimeandExtensionRunner,createAgentSessionRuntime,createAgentSessionServices,buildSessionContext, andTuiAltScreen. - The Go SDK has
sdk.FindCutPoint,sdk.SessionEntryToContextMessagesandsdk.EstimateTokens, and an edit-tool override keeps the model's legacy edit shapes. examples/headlessis a complete small embed with the session API, MCP servers and one provider. The Go SDK page lists thepig_strip_*build tags and what each saves.
Chord, Durable and Piglets
- Chord v2 (
chord/next, experimental) as in Pi: host, store, documents, links, plugins and HTTP components, pluschord.Watch. - Durable has continue submissions,
WhenIdleReject,SubmitIn,MaxTurns,AfterRunhooks,BeforeProviderRequest,pi.live.runFailureand a windowedConversationView. - A Piglet's tool scope bounds the Session tool registry (see Security), a Piglet Binary accepts overlay Piglets, and
build.closed: truemakes a Binary refuse--piglet,PIG_PIGLET_PATH,PIG_PIGLET_NAMEand--system-prompt. - A Nix flake builds PiG from source (
nix run github:MichaelKinsy/PiG), with a CI check on its vendor hash. - OpenRouter
:nitroand:floorvariants are listed beside every OpenRouter model and resolve by name (D199). pig updatecan run a wrapper or another package manager throughPI_SELF_UPDATE_COMMANDor theselfUpdateCommandsetting.
Size and speed
Sizes and counts are from the release regression runs against the 0.6.0 release-branch build. Memory figures are the ones recorded in the changelog fragments, each from its own measurement.
- The
pigbinary is 0.41% to 0.47% larger on the six release targets (linux/amd64 68,792,480 to 69,103,776 bytes, +0.45%). - The first interactive frame makes about 22% fewer allocations (30,354 to 23,668).
- Extension conformance passes 5185 sub-tests with 0 failures and 29 skipped, and the 116 parity-perf cases all pass.
- Resuming a 365 MB session peaked at 2 GB at startup and now peaks at about 130 MB.
/forkand/cloneof a 427 MB session peaked at 4.8 to 5.1 GB and now peak at about 280 MB. A 375 MB session resumed from inside PiG held 2.2 GB until exit and now holds about 100 MB. - A program that embeds PiG and links no Bedrock package is smaller (39.9 MB to 36.7 MB for
examples/headlesson linux/amd64, and 18.3 MB to 15.0 MB for a program that only importsai).
Upgrading
Breaking changes for Go code and the SDKs (each has a before and after in the CHANGELOG).
ai: the Bedrock provider moved toai/providers/bedrock(bedrock.NewBedrockProviderand the rest). Importingaialone no longer links the AWS SDK.chord,durable/session: the watch handle moved from Durable to Chord. Usechord.Watchwithchord.NewWatch.durable/harness:Conversation.WatchandHarness.ObserveConversationtake a*ConversationWindow(passnilfor the defaults),WatchEvents,AgentEventStreamand the agent event types are removed, andHarness.RetryTaskis removed. A task cut offrestartLimittimes in a row now ends visibly.- Stored formats.
pi.liveis version 3,pi.toolis version 3 andpi.generationis version 2, and submission records may becontinue. Older stores open through a migration, but a build that expects the older versions cannot read a store this version wrote. - Programs that embed the extension host call
subprocess.EnableTuiAltScreens()andsubprocess.EnableEditorViews(), and importcoding/extension/host/lispcellfor Lisp extensions. Thepigcommand does all three. - Go SDK:
HostHelpers.HighlightCodeloses itsmarkdownparameter. Type.Refinecallbacks no longer run (D226).pig extension upgraderewrites what has one safe form and lists the rest.
Security
PiG 0.4.0 through 0.5.3 applied a Piglet's tools lists to the model's active set only. A tool exposed as codemode or deferred stayed callable from codemode scripts, and tool_search could find and load it, although the Piglet did not list it. This release enforces the scope in the Session tool registry. A tool outside the scope is not registered, so it is not listed, active, callable from codemode or findable by tool_search, and no later setActiveTools call, registration or reload brings it back. A Piglet Binary or a run with pig --piglet gets the fix when you upgrade PiG and rebuild the Binary.
Full changelog
See CHANGELOG.md (0.7.0 section).