pi

package
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package pi implements the Pi coding agent provider.

Pi (https://github.com/earendil-works/pi) is a model-agnostic, BYOK terminal coding agent. Moat runs it in an isolated container with transparent credential injection.

No credential of its own

Unlike the claude/codex/gemini providers, Pi has no dedicated credential. It runs against whichever backend the user's grant provides. Three backends are supported:

  • anthropic (x-api-key injection on api.anthropic.com)
  • openai (Bearer injection on api.openai.com)
  • lunaroute (Bearer on gw.lunaroute.com, LUNAROUTE-API-KEY on mcp.lunaroute.com; see lunaroute.go)

Every other Pi backend fails hard as future work. The backend is chosen by resolvePiProvider: pi.provider / --provider override, otherwise inferred from the single configured grant; ambiguous or missing configurations are hard errors.

Credential injection

Injection is delegated entirely to the backend's credential provider (Pi honors HTTP_PROXY, verified). Pi's own ConfigureProxy/ContainerEnv are no-ops. The backend grant provider supplies a placeholder key Pi reads (an env var for anthropic/openai, ~/.pi/agent/auth.json for lunaroute); the real key is injected by the proxy at the network layer and never touches the container filesystem.

LunaRoute

The lunaroute backend depends on LunaRoute's Pi extension, which registers the provider and loads models from the gateway. `moat pi` adds it to pi.packages and the run omits PI_OFFLINE so the extension can load models.

Runtime context

The Moat runtime-context markdown is injected via Pi's --append-system-prompt flag pointing at a staged file, so it augments Pi's system prompt without clobbering the user's own AGENTS.md / CLAUDE.md.

Index

Constants

View Source
const ContextFileName = "moat-context.md"

ContextFileName is the staged runtime-context file. It is injected into Pi's system prompt via --append-system-prompt (so it never clobbers a user's own AGENTS.md / CLAUDE.md).

View Source
const LunaRouteExtensionPackage = "npm:@lunaroute/pi-extension"

LunaRouteExtensionPackage is LunaRoute's Pi extension. It registers the "lunaroute" provider and syncs the model catalog from the gateway; without it Pi has no LunaRoute models to offer.

View Source
const PiInitMountPath = "/moat/pi-init"

PiInitMountPath is where the Pi staging directory is mounted in containers.

Variables

This section is empty.

Functions

func DefaultDependencies

func DefaultDependencies() []string

DefaultDependencies returns the default dependencies for running Pi.

func HasLunaRouteExtension added in v0.8.0

func HasLunaRouteExtension(pkgs []string) bool

HasLunaRouteExtension reports whether pkgs installs the LunaRoute extension, either unpinned or pinned to a version (npm:@lunaroute/pi-extension@x.y.z).

func NetworkHosts

func NetworkHosts() []string

NetworkHosts lists the LLM API hosts Pi may need under a strict network policy. Both built-in backends are allowed so a run works regardless of the resolved provider. LunaRoute's hosts are added only for that backend (see configurePiBackend): it is a gateway to arbitrary models, so a strict run on another backend should not be able to reach it.

Types

type Provider

type Provider struct{}

Provider implements provider.AgentProvider for the Pi coding agent.

Pi has no credential of its own: it runs against whichever backend the user's anthropic, openai, or lunaroute grant provides, so credential injection is handled by those credential providers, not here. This provider is purely the runtime — installing the CLI, staging the runtime context, and resolving which backend to launch.

func (*Provider) AgentOnly added in v0.8.0

func (p *Provider) AgentOnly()

AgentOnly marks Pi as having no credential of its own: it runs on the anthropic, openai, or lunaroute grant, so credential listings exclude it.

func (*Provider) Cleanup

func (p *Provider) Cleanup(cleanupPath string)

Cleanup is a no-op — staging-directory cleanup is handled by the Cleanup closure returned from PrepareContainer.

func (*Provider) ConfigureProxy

func (p *Provider) ConfigureProxy(proxy provider.ProxyConfigurer, cred *provider.Credential)

ConfigureProxy is a no-op: credential injection is delegated to the credential provider of the resolved backend.

func (*Provider) ContainerEnv

func (p *Provider) ContainerEnv(cred *provider.Credential) []string

ContainerEnv is a no-op: the backend grant provider sets the placeholder API-key env var (ANTHROPIC_API_KEY / OPENAI_API_KEY) that Pi reads.

func (*Provider) ContainerMounts

func (p *Provider) ContainerMounts(cred *provider.Credential, containerHome string) ([]provider.MountConfig, string, error)

ContainerMounts returns none — Pi uses the staging-directory approach (see PrepareContainer).

func (*Provider) Grant

func (p *Provider) Grant(ctx context.Context) (*provider.Credential, error)

Grant always errors: Pi has no credential of its own. Users grant a model backend with `moat grant anthropic` or `moat grant openai` instead.

func (*Provider) ImpliedDependencies

func (p *Provider) ImpliedDependencies() []string

ImpliedDependencies returns none.

func (*Provider) Name

func (p *Provider) Name() string

Name returns the provider identifier.

func (*Provider) PrepareContainer

func (p *Provider) PrepareContainer(ctx context.Context, opts provider.PrepareOpts) (*provider.ContainerConfig, error)

PrepareContainer stages the Pi runtime-context file and returns the mount + env needed to inject it.

The context is injected into Pi's system prompt at launch via --append-system-prompt (see cli.go), so it augments rather than replaces the user's own AGENTS.md / CLAUDE.md. No credential is staged here: the real API key is injected by the proxy via the backend's grant provider.

func (*Provider) RegisterCLI

func (p *Provider) RegisterCLI(root *cobra.Command)

RegisterCLI registers the `moat pi` command.

type SnippetResult

type SnippetResult struct {
	// DockerfileSnippet is Dockerfile text to append (USER/WORKDIR/COPY/RUN).
	DockerfileSnippet string
	// ScriptName is the build-context filename for ScriptContent.
	ScriptName string
	// ScriptContent is the generated shell script.
	ScriptContent []byte
}

SnippetResult holds a Dockerfile snippet and the generated script it runs.

func GenerateDockerfileSnippet

func GenerateDockerfileSnippet(packages []string, containerUser string) SnippetResult

GenerateDockerfileSnippet builds the Dockerfile snippet + script that installs the declared Pi packages and bakes Moat's safe global settings into ~/.pi/agent/settings.json, as containerUser at image build time.

Commands are written to a separate script (a build-context file) rather than inline RUN steps — mirroring claude.GenerateDockerfileSnippet — to stay under the Apple containers builder's ~16KB Dockerfile gRPC limit.

containerUser is inserted directly into the Dockerfile; callers must pass a safe, validated value (the hardcoded containerUser constant). Package sources are validated by config.validatePiPackages and are additionally single-quoted.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL