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. v1 supports two backends:
- anthropic (x-api-key injection on api.anthropic.com)
- openai (Bearer injection on api.openai.com)
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 anthropic/openai credential providers (Pi honors HTTP_PROXY, verified). Pi's own ConfigureProxy/ContainerEnv are no-ops. The backend grant provider sets a placeholder API-key env var that Pi reads; the real key is injected by the proxy at the network layer and never touches the container filesystem.
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
- func DefaultDependencies() []string
- func NetworkHosts() []string
- type Provider
- func (p *Provider) Cleanup(cleanupPath string)
- func (p *Provider) ConfigureProxy(proxy provider.ProxyConfigurer, cred *provider.Credential)
- func (p *Provider) ContainerEnv(cred *provider.Credential) []string
- func (p *Provider) ContainerMounts(cred *provider.Credential, containerHome string) ([]provider.MountConfig, string, error)
- func (p *Provider) Grant(ctx context.Context) (*provider.Credential, error)
- func (p *Provider) ImpliedDependencies() []string
- func (p *Provider) Name() string
- func (p *Provider) PrepareContainer(ctx context.Context, opts provider.PrepareOpts) (*provider.ContainerConfig, error)
- func (p *Provider) RegisterCLI(root *cobra.Command)
- type SnippetResult
Constants ¶
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).
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 NetworkHosts ¶
func NetworkHosts() []string
NetworkHosts lists the LLM API hosts Pi may need under a strict network policy. Both backends are allowed so a run works regardless of the resolved provider.
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 or openai 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) Cleanup ¶
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 anthropic/openai credential providers for 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 ¶
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 ¶
ImpliedDependencies returns none.
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 anthropic/openai grant provider.
func (*Provider) RegisterCLI ¶
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.