Repository navigation
v0.4.0
PiG 0.4.0 is a Go implementation of Pi 1.0.0. It collects the changes since PiG 0.3.1, which followed Pi 0.87.1: the upstream 0.99 releases (MCP, codemode, virtual models), Pi 1.0.0's leaner codemode, MCP OAuth hardening, fullscreen by default and new sign-in options, and PiG's own header, /sprite with fifteen sprites, and easter eggs. Upgrade with pig update, or npm update -g @pi-in-go/pig for an npm installation; on 0.3.0 installed with npm, use only npm update (see Updating).
Thanks to everyone who reported an issue or sent a change, in this release and in 0.3.1. Details are under Thanks. Extension and SDK authors: this release breaks the Rust SDK and some Go library signatures to match Pi. The Go and Python extension SDKs only gain API. See Breaking changes.
Pi is the reference implementation: earendil-works/pi (documentation). PiG is a separate Go implementation of it, created by Michael Kinsy and originally developed at Hewlett Packard Enterprise. The differences a user can see are recorded, numbered, in the divergence ledger.
Updating
- Installed with the script or a standalone download, on 0.3.0 or 0.3.1: run
pig update. It checks the signedupdate.json, downloads the archive for your platform and verifies its SHA-256 before it replaces the executable. The first start after the update rebuilds source extensions, so it is slower. - Installed with npm, on 0.3.1: run
pig updateornpm update -g @pi-in-go/pig. On 0.3.0, do not usepig updatefor this one step: 0.3.0 reads the wrong package name from the update manifest and runsnpm install -g pig@<version>, which installs an unrelated package. Runnpm update -g @pi-in-go/pig. - On 0.2.0: run the installer again. PiG 0.2.0 cannot update a script installation itself. On macOS and Linux:
curl -fsSL https://pi-in-go.dev/install.sh | sh. On Windows:irm https://pi-in-go.dev/install.ps1 | iex. - On Windows with a standalone
pig.exe:pig updatedoes not replace a runningpig.exein place (D39). Run the PowerShell installer again. - Installed with Go: run
go install github.com/MichaelKinsy/PiG/cmd/pig@v0.4.0again. - Stop running PiG processes before you update.
Added
-
Codemode and tool search. The
codemodetool runs model-written JavaScript in a QuickJS sandbox that calls PiG's tools, andtool_searchfinds tools that were not declared to the model. Both are built-in extensions written in Go; the JavaScript engine is QuickJS compiled to WebAssembly and run by wazero, so codemode needs no Node. Enable codemode withdefaultToolsor--tools, for example"defaultTools": ["+codemode"], and configure it with thecodemode.modeandcodemode.inlineBudgetsettings. Seepig docs show codemode. -
Leaner codemode, as in Pi 1.0.0. The
codemodedescription lists the script globals in one line each and points to the codemode page of the docs bundle for themodelsAPI. Declared tools say in one line how scripts call them and what the call resolves to, instead of repeating their declaration, and the system prompt's codemode guidance and MCP server section are shorter. Errors say how to recover: reading a tool ormodelsmember that does not exist names the close matches (tools.Bashsuggeststools.bash), malformedmodels.classify()andmodels.generateImages()arguments report the expected shape, an unknown model points tomodels.getAvailableOfType(), and an oversizedstore()value explains what the store is for. Scripts that probed for a tool withtypeof tools.namemust use"name" in tools. -
Image generation in codemode. Scripts call
models.generateImages(model, { input }). It runs image models such as OpenRouter's with the session's credentials and returns base64 image blocks thatimage()attaches to the result. Usage counts toward the session cost likemodels.classify(). Extensions callctx.modelRegistry.generateImages()in every SDK. -
Model Context Protocol client, in every mode. PiG has a native MCP client in Go with stdio and streamable HTTP transports and OAuth (discovery, PKCE, dynamic client registration, refresh). The built-in
mcpextension loadsmcp.json(global, or.pig/mcp.jsonin a trusted project) in print, JSON, RPC and interactive mode, registersmcp__<server>__<tool>tools plus resource tools, adds the/mcpcommand, and keeps OAuth credentials inmcp-auth.json.pig mcp add,remove,list,loginandlogoutmanage servers without starting a session. Servers with the defaultcodemodeexposure connect in the background and do not delay the first prompt.pig mcp addtakes--descriptionand--oauth-client-name, and an HTTP server can use"auth": {"provider": "<provider>"}to send a provider's current/logintoken as the bearer token. Disable the extension with--no-extensionsor-builtin:mcp. Seepig docs show mcp. -
MCP OAuth hardening, as in Pi 1.0.0.
oauth.authServerMetadataUrlnames the authorization server metadata document to use instead of discovery, for servers that advertise a wrong authorization server or none (https, orlocalhost,127.0.0.1or[::1]). Sign-in rejects an authorization response whoseissparameter names another authorization server before it exchanges the code (RFC 9207). Credentials are stored per server name and URL, so two servers with one URL can sign in with different accounts, and credentials stored by URL alone move to the first server that uses them. A server that asks for more scope (insufficient_scope) gets a sign-in that keeps the scope granted so far./mcp loginprints the sign-in URL as a terminal link that stays clickable when it wraps. -
Virtual models. An extension registers a virtual model and chooses the physical model and thinking level for each request. The footer shows the routed model, and retries, compaction summaries and restored selections follow the route. See
pig docs show virtual-models. -
pi-durable in Go. Go packages port Pi 1.0.0's
@earendil-works/pi-durablewith its upstream tests:durable(types, IDs, errors, entries, documents, tasks, truncation),durable/storage(memory, JSONL and SQLite storage; SQLite runs on the pure-Gomodernc.org/sqlite, soCGO_ENABLED=0builds keep it),durable/session(the Session kernel: transactions, document trackers, forks, document states and watches),durable/harness(agents, conversations, generation, scheduling, compaction, tasks and tools),durable/tools(read, write, edit and bash over a durable environment) anddurable/env, withchord/delta, the Chord overlay draft tracker. The experimental services run on the durable harness in builds with thepig_experimentaltag; the releasedpigbinary does not include them. -
pi-telemetry in Go. The
telemetrypackage ports Pi 1.0.0's telemetry schema data types,DefineTelemetrySchema,CreateTypedSpanStarterand the in-memory telemetry context, andtelemetry/telemetrytestholds the runner-independent conformance cases for telemetry adapters. -
Typed models, image generation and classifiers.
coding.ModelRuntimelists and resolves chat, image and classifier models, generates images with the provider's key and headers (GenerateImages), and keeps OpenRouter image models apart from chat models. llama.cpp lists a classifier next to each chat model. -
The extension API for tools, MCP and models, in every SDK. Node, Go, Python and Rust extensions can register MCP servers and virtual models, read settings (
getSettings), declare tools withexposure(direct,codemode,deferred,hidden),namespace,annotations,outputSchema,defaultActiveandprepareLoadout, returnstructuredContent, call other tools withctx.toolsandctx.executeTool(), observeprovider_stream_event, and readctx.signal, the signal of the run in progress, as Pi does. Go, Python and Rust extensions also get Pi'spi.eventsbus. The TypeScript declarations are Pi 1.0.0's. -
Sign in with ChatGPT.
/login openaiuses a ChatGPT subscription with the OpenAI provider. GPT-6.1 Sol is in the catalog and is the defaultopenai-codexmodel; Fireworks, Together and OpenCode Go default to Kimi K3. -
Anthropic workload identity federation. PiG authenticates to Anthropic from
ANTHROPIC_FEDERATION_RULE_ID,ANTHROPIC_ORGANIZATION_IDandANTHROPIC_IDENTITY_TOKEN_FILE. -
System theme. PiG's colors come from your terminal's palette by default (the
systemtheme) and follow a light/dark switch. Theme files accept#rgb,oklch()andokhsl()colors. The theme keeps the palette's chroma, so pastel palettes such as Catppuccin Frappe are no longer made more vivid. -
Sign in with Radius.
/loginoffers Radius as the last top-level option, with its status. After a Radius sign-in,/loginoffers to add the Radius MCP server to the globalmcp.jsonwith"auth": {"provider": "radius"}and reloads. -
Anthropic copy code login.
/loginfor Anthropic asks for browser login or copy code login. Copy code login prints a URL to open on any machine and takes the code Anthropic shows, so it works when the browser runs on another machine. -
Fullscreen by default. Interactive mode starts in fullscreen. Set
tuiModeto"regular", or pass--tui-mode regular, to keep the terminal's normal scrollback.quietStartupaccepts"header", which keeps the startup header and hides the loaded-resource listing (truehides both,falseshows both;/settingsoffers the three values). -
The PiG header and
/sprite. The startup header shows the sprite's pixel pig where it showed Pi's logo: seven lines tall, with the version, the key hints and the onboarding line beside it. 256-color terminals and panes too narrow for the head get a one-linePiG.mark, and Apple Terminal gets Pi's Apple Terminal layout with that mark./spritechooses the pig from fifteen sprites (/sprite list,/sprite set <id>, or a picker): the default green pig, eight colors, and the characters Pigrogu, Darth Vader, Kratos, Piglet, Spider-Ham and Sheriff PiG./sprite preview [id]shows a sprite's full art with thePiG.wordmark. The choice is saved in$PIG_HOME/state/pig-standard/login.json./spritecomes from the built-inpig-loginextension, whichpig configlists with the other built-in extensions. Extensions and Piglets add sprites withctx.ui.registerSprite(GoRegisterSprite, Rust and Pythonregister_sprite). An extension can still replace the header withsetHeader. -
Easter eggs. In fullscreen mode, click the pig head in the startup header (or the
PiG.mark): the screen dissolves into braille dust, and the pig head flies to the center, grows and spins, then turns into a big side-view pig, drawn in the same braille dots, that runs in place. Escape or Ctrl+C lands it back on the header (press again to skip). It is PiG's version of Pi 1.0.0's logo animation, in the colors of your/sprite./pigsayhiis a second name for/arminsayshi, which now draws a pig head labeledpigsayhiwith Pi's effects (D87). -
Games over MCP, demonstrated. The 0.4.0 demo is one real terminal take: first-run setup picks the Sheriff sprite, then Jev, the
typesafe/jev-latestclassifier, plays Pig Runner and Angry Pigs live in their terminal overlays through code mode over MCP, onemodels.classifycall per move, and a click on the header shows the braille running pig. It is on the Demos page. -
Built-in extensions in
pig config.pig configlists built-in extensions in a "Built-in" group. Enable or disable one with+builtin:<name>or-builtin:<name>in theextensionssetting, load one for a run with-e builtin:<name>, and disable all of them with--no-extensions. -
/reloadpicks up new default tools. Tools newly added todefaultToolsare enabled on/reload.defaultToolsalso accepts+nameand-name. -
Sessions are saved from the first prompt. The session file is created when the first user message is added, so a crash before the first reply no longer loses the prompt.
-
More settings.
fullscreenWheelScrollLines("auto"or 1 to 100) and a random installationdeviceIdin the global settings, which bug reports leave out. -
Termux on Android (arm64).
curl -fsSL https://pi-in-go.dev/install.sh | shdetects Termux and installs the newandroid-arm64release into$PREFIX/bin;npm install -g @pi-in-go/piginstalls the new@pi-in-go/pig-android-arm64package. The Android binary is a cgo build against Android's libc, started throughlinker64; PiG setsTMPDIRandSSL_CERT_FILEfor Termux when they are unset (#119). -
pig piglet buildwithout a checkout. A release binary fetches the PiG source of exactly its own version through the Go module proxy (checked byGOSUMDB, cached after the first build). A built-incontainerbuilder runs the build in Podman or Docker when Go is missing or for otherlinux/<arch>targets.
Changed
- Sign-in labels.
/loginand/logoutlabel providers without credentials "not configured" instead of "unconfigured". Only subscription-backed OAuth sign-ins say "subscription"; the others, Radius and OpenRouter among them, say "account". Cancelling a sign-in method prompt returns to the menu the login started from. Login dialogs show each flow's own paste prompt. OAuth browser pages show the color logo. --providerneeds--model.--providerwithout--modelfails with an error instead of running the default model of another provider.- Apple Terminal header. The header shows the one-line
PiG.mark and the version on the first line and the key hints below. - Syntax highlighting as in Pi. PiG highlights code with a Go port of highlight.js 10.7.3, the highlighter Pi uses, instead of chroma. Code blocks in messages, tool output and codemode cards get Pi's token colors for every language, and
pigstarts faster. As in Pi, the 20 most common languages highlight at startup and the rest load after the first screen, which then repaints. Tool previews take the language from the text after the last dot of the path, so aMakefileorDockerfileinside a directory is no longer highlighted.
Fixed
- Extension widgets and footers stay visible in fullscreen after a terminal resize and re-render at the new width, and
belowEditorwidgets sit between the editor and the footer in both TUI modes. Thanks @baggiiiie (#121, #122, shipped through #114). - A Piglet whose root
toolsnames an extension tool gets an error that points toextensions[].tools; a package that lists both a directory and its own index file resolves to one extension; extension tools with Pi source info are no longer scoped as built-ins. - On Windows,
pig updatefor an npm installation finds its running executable when PiG was started through an 8.3 short path. - An extension keeps the terminal height after
/reload. A packed Go extension received a height of 0 after a reload until the next resize. The host now delivers width and height changes to each extension that has not seen the value. Thanks @nicholas-recht (#115, #116). - On Windows, publishing a Node extension cell (and any other cached runtime cell) is retried with backoff for up to 10 seconds when the final directory rename fails with
Access is denied, a sharing violation or a lock violation, instead of stopping extension loading. Thanks @worldofgeese (#106, #110). - Fullscreen mode keeps the Kitty keyboard flags on the alternate screen, so
Shift+Enterandctrl+digitextension shortcuts work there, and PiG no longer leaves the flags set in the shell after it exits fullscreen. The bash execution block, the compaction and branch summary label, the editor's thinking-level border and the settings list cursor take their colors from the active theme. Thanks @jkerdreux-imt (#105, #108, #109). - MCP stdio servers started through npm
.cmdshims on Windows run throughcmd.exe, sonpx-style servers start. - On Windows, pasting a Print Screen or other bitmap-only clipboard image with Alt+V inserts the image, a Python extension no longer resolves Python to the Microsoft Store
python.exealias, and thePIG_DEBUGlog is written belowTEMPinstead of the missingC:\tmp. - Parallel MCP tool calls reach the server in the order the model issued them.
- Codemode
image()rejects malformed base64 and unsupported image types instead of persisting an image block that makes every later provider request fail with HTTP 400. - MCP tool and namespace names replace
-with_(mcp__my-server__xbecomesmcp__my_server__x), and colliding tools of one server get a hash suffix, so a script cannot call the wrong tool. See Breaking changes. - A deep
TMPDIRno longer makes the extension host fail to start on macOS and Linux. tool_execution_updateevents reach extensions, RPC and JSON consumers with Pi'spartialResultshape, and a tool's result members keep the order the tool wrote them, in every SDK.- An extension tool's
prepareArgumentsruns before PiG validates the model's arguments, as in Pi, so an extension that spreads Pi'screateEditToolDefinitionaccepts the legacy flat{path, oldText, newText}edit again. - The tool calls of a parallel batch start in the model's order in extension tools, as in Pi.
- Anthropic strict tool use sends a tool non-strict when its schema uses a keyword Anthropic rejects, and context overflow detection recognizes Z.AI CN
Prompt exceeds max lengtherrors. - A
Retry-Afterheader with an unparseable value makes the provider retry with exponential backoff instead of immediately. - Prompt submission no longer slows down with session length.
- RPC mode loads extensions before it resolves
--modeland--models, so a model registered by a-eextension can start an RPC session. - MCP OAuth sign-in no longer fails with
Invalid client_secret,Invalid scopeand similar errors when a token or client registration response sends""ornullfor an optional field, andexpires_in: nullno longer marks the token as expired. An emptyscope=""in aWWW-Authenticatechallenge or an emptyscopes_supportedno longer overrides the next scope source. MCP list pagination ends at anextCursorof""ornullinstead of failing with a duplicate cursor error. - Deferred MCP tools that
tool_searchloaded are active again after/reload, and after resuming a session, once their server reconnects before the next prompt. - OpenAI Responses requests no longer fail with
Expected an ID that begins with 'ctc'when they replay grammar tool calls, such ascodemode, from another provider or a gateway like Radius. - Typing
/after leading spaces offers slash-command completions, and colors no longer bleed past mouse selections and search highlights in fullscreen mode. - Leaving fullscreen with
fullscreenExitOutputset to"transcript"keeps the blank line before the resume hint, and background-colored message rows end at their padding. - Codemode
modelsandctx.modelRegistrywork in interactive mode and after/newor a resume. - Messages that tell the user to run a command say
pig configandpig login, notpi configandpi login, and a start that fails only because an extension did not build prints the-nehint.
The complete list is in CHANGELOG.md.
Breaking changes for extension and SDK authors
PiG has no compatibility shim for these. Each follows the Pi API named in the changelog.
- Go tool progress API.
agent.ToolUpdateCallbackisfunc(partial agent.AgentToolResult), andagent.ToolExecutionUpdateEventcarriesPartialResult agent.AgentToolResultinstead ofContent stringandDetails any. - Go
aimodel API.CreateProviderOptions.ModelsandFetchModelsuse[]ai.AnyModel(convert withai.AnyModels(models)).ImagesModelisImageModel,ImagesAPIisImageAPI, andImagesCostand theImagesModelscollection are removed (useModels.GenerateImages).CreateProviderpanics when it gets no chat, image or classifier implementation, as Pi'screateProviderthrows. - Go extension host API.
extension.EventBusisEmit(channel, data)andOn(channel, handler), returning the unsubscribe function.extension.APIgainsGetSettings, the MCP and virtual-model registration methods andOnProviderStreamEvent.coding.ProviderConfigInput.Modelsand the valueRefreshModelsreturns are[]ai.AnyModel.Session.SteerandSession.FollowUpreturn(QueuedInputDisposition, error), andPromptOptions.PreflightResultisfunc(PromptDisposition), called only for an accepted prompt. - Settings.
Settings.DefaultToolsholds the rawdefaultToolslist; read the selection throughSettingsManager.GetDefaultTools(). - Built-in paths. The
sourceInfo.pathof a built-in tool isbuiltin:<name>, and the llama.cpp extension isbuiltin:llama.cppwith sourcebuiltin. - Rust SDK.
ToolDefinitionandToolInfogain Pi's tool fields (exposure,namespace,annotationsand, onToolDefinition,output_schema,default_activeandprepare_loadout); build aToolDefinitionwithToolDefinition::new. TheProviderstruct gainsgenerate_imagesandclassify. - Go MCP OAuth library.
McpOAuthCredentialStore.ForServer,TokensandRemovetake the server name before the server URL, as in Pi 1.0.0.mcp/oauth.OAuthIssuerMismatchError.Receivedis a*string, nil when an authorization response lacks theissits server promised.mcp/oauthgainsStepUpScope, theIssandAuthorizationServerMetadataURLflow options andDiscoveryOptions.AuthorizationServerMetadataURL.Session.ReapplyActiveToolsapplies a selection again after a mode rebuilds the agent's tools. - Codemode scripts. Reading a tool or global-namespace member that does not exist throws instead of returning
undefined. Replacetypeof tools.namewith"name" in tools. npmCommandsetting. AnnpmCommandthat wraps more than one supported package manager without a--to choose one (for example["corepack", "npm", "pnpm"]) is an error (Ambiguous npmCommand package managers: npm, pnpm), as in Pi. Git package dependencies install with the arguments of the detected package manager.- MCP tool names.
-in an MCP server or tool name becomes_. Update--tools,defaultTools,-xtand Piglet tool-scope entries that name an MCP tool with a hyphenated server. Two server names that differ only in-and_are now rejected. - Default models. The defaults of
openai-codex,fireworks,togetherandopencode-gochange as listed above.
Windows
Windows remains a preview. The release workflow smoke-tests the windows-amd64 zip; the windows-arm64 zip and npm package are published without a native smoke test, and a standalone pig.exe does not update itself (D39). See the Windows setup page for what is not yet covered.
Known issues
- RPC: a command sent immediately after
agent_endcan be answered beforeagent_settledis emitted, and an extension command's prompt response can be lost when stdin closes at once. Both are ordering races found under CPU load on a two-core machine; they affect only clients that send a command onagent_endor close stdin right after a command. quietStartup: "header"hides the resource listing but PiG does not print Pi'sModel scope:startup line in any mode, so the setting differs from Pi only by that missing line.- A start that loads PiG Standard's own
pigloginextension, or any extension that registers/sprite, replaces the built-inpig-loginand prints Pi's replaced-built-in warning. The warning is correct; the replacement is intended. - Under heavy CPU load,
/cloneright after the first answer can report "This session has not been saved yet" and draw the error above that turn's message. Run/cloneagain. - One Pi test file,
2860-replaced-session-context.test.ts, is only partly ported, because no extension SDK exposeswithSession. Seedocs/parity/KNOWN-GAPS-0.3.x.md.
Verification
PiG 0.4.0 was checked against Pi 1.0.0 with the parity scenarios and upstream tests listed in the repository. The release workflow smoke-tests the linux/amd64, darwin/arm64 and windows/amd64 archives on native runners; linux/arm64, darwin/amd64, windows/arm64 and android/arm64 are cross-built and published without a native smoke test. The release evidence (checksums, SBOMs, inventory validation, vulnerability reports and provenance attestations) is attached to this release.
Thanks
New in this release:
- @nicholas-recht: reported packed Go extensions losing the terminal height after
/reload(#115) and contributed the first fix (#116). A follow-up in this release covers the remaining cases. - @worldofgeese: reported the intermittent Windows Node extension cell publication failure (
Access is deniedon rename) (#106). The fix is in #110. - @jkerdreux-imt: contributed the fullscreen Kitty keyboard fix (#105) and the theme color fix (#108), landed together in #109 after 0.3.1.
Carried over from 0.3.1, which this release builds on:
- @nguyen-tran-100x: reported
--exclude-toolsbeing ignored in RPC mode (#101). - @sj0n: reported a Node extension command crashing its extension (#103).
- @nickdeighton: reported the startup panic when an extension footer is wider than the terminal (#104).
- @ShoichiTect: reported transport errors saying
fetch failedwhere Pi saysConnection error.orRequest timed out.(#86). - @baggiiiie: reported
pig confignot closing on Escape (#89) and contributed the fix that keeps the shell prompt below the selector after it exits (#90); reported extension widgets and footers disappearing after a fullscreen resize (#121) and contributed the fix (#122), which shipped inside #114. - @SamarthBoranna: reported
pig piglet show --effectiverejecting local paths (#98) and contributed the fix (#99).