nixpi
nixpi declaratively configures the Pi coding agent with Nix. It provides one typed programs.pi module for standalone packages, Home Manager, NixOS, and nix-darwin.
Start here
Run the default agent without creating a configuration:
nix run github:mateusdcc/nixpi
For a project or personal configuration, start from a template, then read the usage guide. The complete option reference is generated from the live Nix module schema during every documentation build, so it includes every programs.pi option, type, default, and description.
What is documented
- Every public flake output and library function, with callable examples.
- Every
programs.pioption, generated from the evaluated module. - Bundled profiles, extensions, skills, and providers.
- Home Manager, NixOS, nix-darwin, standalone, devShell, and direnv usage.
- Templates, secrets, mutable state, updating, tests, migration guidance, and troubleshooting.
The site is built by nix build .#docs. Its static files are in result/share/doc/nixpi/html and GitHub Actions publishes that same directory to GitHub Pages.
Getting started
Run the default package
nix run github:mateusdcc/nixpi
The default package includes a declarative configuration with safe defaults. Pin the input in a flake for repeatable installations.
Home Manager
Add the input and import the module:
{
inputs.nixpi.url = "github:mateusdcc/nixpi";
outputs = { home-manager, nixpkgs, nixpi, ... }: {
homeConfigurations.me = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.aarch64-darwin;
modules = [
nixpi.homeModules.default
{
home = {
username = "me";
homeDirectory = "/Users/me";
stateVersion = "26.05";
};
programs.pi = {
enable = true;
settings.defaultProvider = "openai";
extensions.ripgrep-search.enable = true;
skills.commit-style.enable = true;
environment.required = [ "OPENAI_API_KEY" ];
};
}
];
};
};
}
Use nixpi.nixosModules.default in NixOS and nixpi.nixDarwinModules.default in nix-darwin. The programs.pi options are shared by every integration.
Secrets
Do not put secret values in Nix expressions. Declare only their names with programs.pi.environment.required, then provide values through the runtime environment. The wrapper reports missing names before Pi starts.
Updating safely
Commit flake.lock, review deprecation warnings, and run nix flake check before switching a system. Existing 1.x output names remain available with warnings throughout the 1.x release line.
Everyday usage
Choose an integration
Use the same programs.pi options in every integration. The difference is where the evaluated package is installed.
| Situation | Entry point | Run it |
|---|---|---|
| One-off trial | packages.<system>.default | nix run github:mateusdcc/nixpi |
| Project-owned agent | lib.nixpi.makePi | nix run .# |
| User environment | homeModules.default | activate Home Manager |
| NixOS host | nixosModules.default | rebuild NixOS |
| macOS host | nixDarwinModules.default | rebuild nix-darwin |
Standalone package
This is the smallest persistent configuration. Put it in a project flake.nix, replace the system value when needed, and keep flake.lock committed.
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-26.05";
nixpi.url = "github:mateusdcc/nixpi";
};
outputs = { nixpkgs, nixpi, ... }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
in {
packages.${system}.default = nixpi.lib.nixpi.makePi {
inherit pkgs;
modules = [{
programs.pi = {
enable = true;
settings = {
defaultProvider = "openai";
defaultModel = "gpt-4o";
};
extensions.ripgrep-search.enable = true;
skills.commit-style.enable = true;
environment.required = [ "OPENAI_API_KEY" ];
};
}];
};
};
}
Run it with nix run .#. environment.required checks that a name exists at launch time. It does not put secret values in the Nix store.
Home Manager
Import nixpi.homeModules.default, then configure the same module namespace:
{
imports = [ inputs.nixpi.homeModules.default ];
programs.pi = {
enable = true;
settings.defaultProvider = "anthropic";
extensions.plan-mode = {
enable = true;
mode = "balanced";
};
environment.required = [ "ANTHROPIC_API_KEY" ];
};
}
The integration installs the evaluated package and links the generated immutable settings.json and, when configured, models.json under ~/.pi/agent.
NixOS and nix-darwin
Import inputs.nixpi.nixosModules.default in NixOS or inputs.nixpi.nixDarwinModules.default in nix-darwin. Configure programs.pi exactly as above. The option schema and generated package are shared across all three host integrations.
Secrets and state
Put only non-secret values in environment.variables. Export API keys from your shell, your secret manager, or your host configuration before starting Pi. auth.json and sessions/ remain mutable runtime state.
programs.pi.environment = {
variables.PI_OFFLINE = "1";
required = [ "OPENAI_API_KEY" ];
};
Do not write API key values into a Nix expression. Nix derivations and their logs can be world-readable to users of the same store.
direnv
direnv is a convenient way to give a repository a reproducible Pi command and expose secret names only while you are in that repository.
Project flake
Start with the devshell template or add this output to an existing flake:
devShells.${system}.default = pkgs.mkShell {
packages = [
(nixpi.lib.nixpi.makePi {
inherit pkgs;
modules = [{
programs.pi = {
enable = true;
settings.defaultProvider = "openai";
extensions.ripgrep-search.enable = true;
environment.required = [ "OPENAI_API_KEY" ];
};
}];
})
];
};
.envrc
Keep secrets outside Git. One simple pattern is a local .envrc that reads a separately ignored file and enters the flake development shell:
dotenv_if_exists .env.local
use flake
Put the real value in .env.local, which must be ignored:
export OPENAI_API_KEY='replace-with-your-secret-manager-output'
Then allow the project once:
direnv allow
pi
Why this works
use flake adds the configured Pi package to PATH. nixpi evaluates the required variable names into the launcher but does not evaluate their values. The launcher verifies that OPENAI_API_KEY is present only when you start Pi.
For shared or production credentials, have .envrc call your existing secret manager instead of storing a value in .env.local.
Templates
Initialize a new directory with the template that matches how Pi will be used:
nix flake init --template github:mateusdcc/nixpi#standalone
| Template | Command suffix | Use it for |
|---|---|---|
| Standalone | #standalone | A configured nix run .# agent package. |
| Home Manager | #home-manager | A home.nix fragment for a user installation. |
| devShell | #devshell | A repository development environment, especially with direnv. |
| learning | #learning | Legacy compatibility only. Use deep-comprehension-engine for new learning environments. |
Standalone
After initializing, set the target system and provider in flake.nix, export the required key, and run:
nix run .#
Home Manager
The template supplies a home.nix module. Add it to your Home Manager module list after importing nixpi.homeModules.default:
modules = [
inputs.nixpi.homeModules.default
./home.nix
];
devShell
Use this for a repository-specific agent and pair it with the direnv guide. Enter it manually with:
nix develop
The template makes Pi, Git, and ripgrep available in the shell. Change programs.pi in the template rather than maintaining a separate imperative setup script.
Configuration
All configuration lives under programs.pi. This page provides a map; use All options for the generated, exhaustive reference.
programs.pi = {
enable = true;
settings = {
defaultProvider = "openai";
defaultModel = "gpt-4o";
defaultThinkingLevel = "medium";
theme = "dark";
};
extensions = {
echo.enable = true;
ripgrep-search.enable = true;
plan-mode.enable = true;
};
skills.commit-style.enable = true;
providers.local = {
baseUrl = "http://localhost:11434/v1";
models = [{ id = "local-model"; }];
};
runtimePackages = with pkgs; [ git jq ];
environment.required = [ "OPENAI_API_KEY" ];
};
Main sections
| Section | Purpose |
|---|---|
settings | Pi settings serialized into the generated settings file. |
providers | Provider endpoints, package support, models, and credentials references. |
extensions | Enable packaged extensions and provide extension-specific settings. |
skills | Enable skill packages that Pi can discover. |
prompts and themes | Add prompt and theme resources. |
runtimePackages | Commands available to Pi and extensions at runtime. |
environment | Non-secret variables and required environment variable names. |
resources and extraPackages | Compose custom resource and package inputs. |
Add a local provider
programs.pi.providers.local = {
baseUrl = "http://localhost:11434/v1";
api = "openai-completions";
models = [
{
id = "qwen2.5-coder";
name = "Qwen 2.5 Coder";
}
];
};
Add runtime tools
An extension that invokes git, rg, or a language runtime needs those executables in runtimePackages:
programs.pi.runtimePackages = with pkgs; [
git
ripgrep
jq
nodejs
];
The generated option reference documents the exact option type and default for each item.
Flake outputs
| Output | Purpose |
|---|---|
packages.<system>.default | Configured Pi executable |
packages.<system>.legal-research | Legal research profile |
packages.<system>.docs | Generated option and project documentation |
packages.<linux-system>.docker-* | Tested minimal, features, and provider CI images |
piModules.default | Complete standalone module |
piModules.base | Reusable core without bundled features |
piModules.profiles.* | Curated configurations |
piModules.extensions.* | Individual extension modules |
piModules.skills.* | Individual skill modules |
piModules.providers.* | Individual provider modules |
homeModules.default | Home Manager integration |
nixosModules.default | NixOS integration |
nixDarwinModules.default | nix-darwin integration |
lib.nixpi | Canonical library namespace |
overlays.default | Adds packages under pkgs.nixpi |
templates.* | Starter flakes |
Compatibility aliases such as homeManagerModules, piModules.core, and moved learning resources remain available during 1.x. Evaluation emits a warning that identifies the replacement.
The complete generated option reference is available from:
nix build .#docs
Open result/share/doc/nixpi/options.md after the build.
Library API
The public library is nixpi.lib.nixpi. Builder functions accept pkgs either as an argument in their input set or through the extensible library used by nixpi itself.
Evaluate and build
evalPi
evalPi { pkgs, modules ? [], extraSpecialArgs ? {} } evaluates the complete Pi module system and returns the normal Nix module evaluation result, including config and options.
let
evaluated = nixpi.lib.nixpi.evalPi {
inherit pkgs;
modules = [{ programs.pi.enable = true; }];
};
in evaluated.config.programs.pi.finalPackage
makePi
makePi { pkgs, modules ? [], extraSpecialArgs ? {} } returns the configured Pi package. Its passthru exposes config, options, unwrapped, and extend.
let
pi = nixpi.lib.nixpi.makePi {
inherit pkgs;
modules = [{ programs.pi.enable = true; }];
};
in pi.extend {
programs.pi.skills.commit-style.enable = true;
}
Package resources
mkPiExtension
mkPiExtension { pname, src, version ? "0.1.0", runtimePackages ? [], runtimeEnvironment ? {}, piManifest ? {}, meta ? {}, ... } packages an extension directory. It writes a default Pi manifest if src does not provide package.json.
myExtension = nixpi.lib.nixpi.mkPiExtension {
inherit pkgs;
pname = "hello";
src = pkgs.writeTextDir "extensions/index.js" ''
export default pi => pi.registerCommand("hello", { handler: () => console.log("hello") });
'';
};
mkPiSkill
mkPiSkill { name, description ? "", content ? "", src ? null, runtimePackages ? [], passthru ? {}, meta ? {} } creates a skill package. With src, it returns that source unchanged.
nixpi.lib.nixpi.mkPiSkill {
inherit pkgs;
name = "release-check";
description = "Check a release before publishing.";
content = "Run nix flake check before a release.";
}
mkPiPrompt
mkPiPrompt { name, description ? "", argumentHint ? null, content } creates a prompt Markdown resource, adding front matter when requested.
nixpi.lib.nixpi.mkPiPrompt {
inherit pkgs;
name = "review";
argumentHint = "[path]";
content = "Review the requested path for correctness and maintainability.";
}
mkPiTheme
mkPiTheme { name, colors } creates a JSON theme resource. name is added to the supplied color attribute set.
nixpi.lib.nixpi.mkPiTheme {
inherit pkgs;
name = "night";
colors.background = "#111827";
}
mkPiProvider
mkPiProvider { name, src ? null, package ? null, version ? "0.1.0", baseUrl ? null, api ? null, apiKey ? null, models ? {}, runtimePackages ? [], environment ? {}, piManifest ? {}, meta ? {}, ... } returns a normalized provider object. models may be a list or attribute set. A src is packaged as an extension when no package is supplied.
nixpi.lib.nixpi.mkPiProvider {
inherit pkgs;
name = "local";
baseUrl = "http://localhost:11434/v1";
models = [{ id = "qwen2.5-coder"; }];
}
Module factories
mkPiExtensionModule
Creates a complete programs.pi.extensions.<name> module. It accepts name, optional description, package or defaultPackage, runtimePackages, extraPackages, settingsOptions, settingsExample, settingsDescription, defaultText, extraOptions, and extraConfig.
nixpi.lib.nixpi.mkPiExtensionModule {
name = "hello";
defaultPackage = myExtension;
runtimePackages = [ pkgs.git ];
}
mkPiSkillModule
Creates a complete programs.pi.skills.<name> module. It accepts name, optional description, package or defaultPackage, runtimePackages, extraPackages, defaultText, extraOptions, and extraConfig.
nixpi.lib.nixpi.mkPiSkillModule {
name = "release-check";
defaultPackage = mySkill;
}
mkPiProviderModule
Creates a complete programs.pi.providers.<name> module. It accepts name, optional description, package or defaultPackage, baseUrl, api, apiKey, models, runtimePackages, extraPackages, and extraConfig.
nixpi.lib.nixpi.mkPiProviderModule {
name = "local";
baseUrl = "http://localhost:11434/v1";
models = [{ id = "qwen2.5-coder"; }];
}
deprecation.warn
deprecation.warn { old, replacement, supportedThrough ? "1.x" } value returns value while emitting a Nix evaluation warning. It is used for compatibility aliases.
nixpi.lib.nixpi.deprecation.warn {
old = "oldOutput";
replacement = "newOutput";
} value
Bundled modules
Import the complete module with nixpi.piModules.default, or import a focused module from the output names below. The generated option reference is authoritative for every option exposed by these modules.
Core and profiles
| Output | Purpose |
|---|---|
piModules.base | Core options without bundled features. |
piModules.default | Core plus the bundled feature modules. |
piModules.profiles.minimal | Minimal Pi configuration. |
piModules.profiles.research | Research-oriented configuration. |
piModules.profiles.legalResearch | Legal research configuration. |
piModules.profiles.learning remains a deprecated compatibility alias for deep-comprehension-engine.
Extensions
| Output | Enable with | Use |
|---|---|---|
piModules.extensions.echo | extensions.echo.enable = true; | Simple command extension and package example. |
piModules.extensions.ripgrep-search | extensions.ripgrep-search.enable = true; | Repository search using ripgrep. |
piModules.extensions.plan-mode | extensions.plan-mode.enable = true; | Planning workflow controls. |
piModules.extensions.pi-gpt-search | extensions.pi-gpt-search.enable = true; | GPT-powered search integration. |
piModules.extensions.researchTools | extensions.research-tools.enable = true; | Research tools and MCP bridges. |
piModules.extensions.obsidian is a deprecated compatibility alias. Configure the replacement from deep-comprehension-engine for new work.
Skills
Enable a bundled skill through programs.pi.skills:
programs.pi.skills = {
commit-style.enable = true;
legal-pain-discovery.enable = true;
voice-of-customer-mining.enable = true;
evidence-deduplication.enable = true;
legal-market-segmentation.enable = true;
competitor-gap-analysis.enable = true;
brazil-localization-test.enable = true;
opportunity-scoring.enable = true;
product-opportunity-report.enable = true;
};
The corresponding public module outputs are commit-style, legalPainDiscovery, voiceOfCustomerMining, evidenceDeduplication, legalMarketSegmentation, competitorGapAnalysis, brazilLocalizationTest, opportunityScoring, and productOpportunityReport under piModules.skills.
The former learning skills under piModules.skills are compatibility aliases that warn and point to deep-comprehension-engine.
Providers
piModules.providers.antigravity adds the Antigravity provider module. It can be enabled through the normal programs.pi.providers.antigravity option tree. Use the provider’s generated options for models, endpoint, package, and credential requirements.
Host modules
| Output | Alias | Use |
|---|---|---|
homeModules.default | homeModules.pi, homeManagerModules | Home Manager. |
nixosModules.default | nixosModules.pi | NixOS. |
nixDarwinModules.default | nixDarwinModules.pi | nix-darwin. |
All options
programs.pi.enable
Whether to enable Pi coding agent.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.package
The base Pi coding agent package to use.
Type: package
Default:
pkgs.pi-coding-agent
Declared by:
programs.pi.packages
List of Pi packages (derivations or directory paths) to load.
Type: list of (package or absolute path or string)
Default:
[ ]
Declared by:
programs.pi.assertions
List of assertions to check during evaluation.
Type: list of unspecified value
Default:
[ ]
Declared by:
programs.pi.builtinProviders
List of built-in LLM providers.
Type: list of string (read only)
Default:
[
"antigravity"
"openai"
"anthropic"
"google"
"ollama"
"openrouter"
"groq"
"deepseek"
"mistral"
"bedrock"
"xai"
"github-models"
"copilot"
"azure-openai"
"cerebras"
"together"
"fireworks"
"cohere"
]
Declared by:
programs.pi.environment.optional
List of optional environment variable names supported by the configuration.
Type: list of string
Default:
[ ]
Declared by:
programs.pi.environment.required
List of environment variable names required by enabled extensions or providers. These are checked or documented as runtime requirements.
Type: list of string
Default:
[ ]
Declared by:
programs.pi.environment.variables
Non-secret environment variables to export for Pi. DO NOT put secret API keys here as they will be written into the Nix store.
Type: attribute set of (null or string or signed integer or boolean or absolute path)
Default:
{ }
Declared by:
programs.pi.extensions.echo.enable
Whether to enable Pi echo extension.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.extensions.echo.package
Package providing the echo extension.
Type: package
Default:
pkgs.piExtensions.echo
Declared by:
programs.pi.extensions.pi-gpt-search.enable
Whether to enable Pi GPT search extension (OpenAI Codex search engine).
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.extensions.pi-gpt-search.package
Package providing the pi-gpt-search extension.
Type: package
Default:
pkgs.piExtensions.pi-gpt-search
Declared by:
programs.pi.extensions.pi-gpt-search.debug
Enable debug logging for web search operations.
Type: boolean
Default:
false
Declared by:
programs.pi.extensions.plan-mode.enable
Whether to enable Pi plan-mode extension.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.extensions.plan-mode.package
Package providing the plan-mode extension.
Type: package
Default:
pkgs.piExtensions.plan-mode
Declared by:
programs.pi.extensions.plan-mode.autoApprove
Whether to automatically approve plan steps.
Type: boolean
Default:
false
Declared by:
programs.pi.extensions.plan-mode.maxSteps
Maximum number of steps in plan execution.
Type: signed integer
Default:
10
Declared by:
programs.pi.extensions.plan-mode.mode
Planning execution mode.
Type: one of “fast”, “balanced”, “thorough”
Default:
"balanced"
Declared by:
programs.pi.extensions.research-tools.enable
Whether to enable Pi legal tech research tools & MCP bridge extension.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.extensions.research-tools.enableGptResearcher
Enable GPT Researcher synthesis fallback tool (conditional, disabled by default).
Type: boolean
Default:
false
Declared by:
programs.pi.extensions.research-tools.enableWorldMonitor
Enable World Monitor macro context tool (conditional, disabled by default).
Type: boolean
Default:
false
Declared by:
programs.pi.extensions.research-tools.enableXhs
Enable XHS / RedNote Chinese market research tool (conditional, disabled by default).
Type: boolean
Default:
false
Declared by:
programs.pi.extensions.research-tools.package
Package providing the research-tools extension.
Type: package
Default:
pkgs.piExtensions.research-tools
Declared by:
programs.pi.extensions.ripgrep-search.enable
Whether to enable Pi ripgrep-search extension.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.extensions.ripgrep-search.package
Package providing the ripgrep-search extension.
Type: package
Default:
pkgs.piExtensions.ripgrep-search
Declared by:
programs.pi.extraExtensions
Extra standalone extension file paths or derivations to load.
Type: list of (package or absolute path or string)
Default:
[ ]
Declared by:
programs.pi.extraPackages
Extra CLI packages to make available in PATH for Pi (alias/escape hatch for runtimePackages).
Type: list of package
Default:
[ ]
Declared by:
programs.pi.extraSkills
Extra standalone skill directory paths or derivations to load.
Type: list of (package or absolute path or string)
Default:
[ ]
Declared by:
programs.pi.finalPackage
The fully configured and wrapped Pi coding agent package.
Type: package (read only)
Declared by:
programs.pi.finalRuntimePackages
Combined list of all runtime packages from core, extensions, and derivations.
Type: list of package (read only)
Default:
[ ]
Declared by:
programs.pi.generatedModelsFile
Generated immutable models.json derivation (null if no providers defined).
Type: null or package (read only)
Default:
null
Declared by:
programs.pi.generatedSettingsFile
Generated immutable settings.json derivation.
Type: package (read only)
Declared by:
programs.pi.prompts
List of prompt template files or derivations to load.
Type: list of (package or absolute path or string)
Default:
[ ]
Declared by:
programs.pi.providers
Declared LLM providers with options and model definitions.
Type: attribute set of (open submodule of attribute set of anything)
Default:
{ }
Declared by:
programs.pi.providers.<name>.enable
Whether this provider is enabled.
Type: boolean
Default:
true
Declared by:
programs.pi.providers.<name>.package
Optional package/extension derivation implementing this provider.
Type: null or package
Default:
null
Declared by:
programs.pi.providers.<name>.packages
Additional packages implementing this provider.
Type: list of package
Default:
[ ]
Declared by:
programs.pi.providers.<name>.api
API protocol type (e.g. openai-completions, anthropic-messages).
Type: null or string
Default:
null
Declared by:
programs.pi.providers.<name>.apiKey
API key or placeholder.
Type: null or string
Default:
null
Declared by:
programs.pi.providers.<name>.baseUrl
Base URL for the provider API endpoint.
Type: null or string
Default:
null
Declared by:
programs.pi.providers.<name>.environment
Environment variables and secret requirements for this provider.
Type: submodule
Default:
{ }
Declared by:
programs.pi.providers.<name>.environment.optional
Optional environment variable names.
Type: list of string
Default:
[ ]
Declared by:
programs.pi.providers.<name>.environment.required
Required environment variable names.
Type: list of string
Default:
[ ]
Declared by:
programs.pi.providers.<name>.environment.variables
Environment variables exported for this provider.
Type: attribute set of anything
Default:
{ }
Declared by:
programs.pi.providers.<name>.models
Models offered by this provider.
Type: (attribute set of (open submodule of attribute set of anything)) or (list of anything) convertible to it
Default:
{ }
Declared by:
programs.pi.providers.<name>.models.<name>.contextWindow
Maximum context window size in tokens.
Type: null or signed integer
Default:
null
Declared by:
programs.pi.providers.<name>.models.<name>.id
Unique model identifier.
Type: string
Default:
"‹name›"
Declared by:
programs.pi.providers.<name>.models.<name>.maxTokens
Maximum output tokens.
Type: null or signed integer
Default:
null
Declared by:
programs.pi.providers.<name>.models.<name>.name
Human-readable display name for the model.
Type: null or string
Default:
null
Declared by:
programs.pi.providers.<name>.models.<name>.reasoning
Whether the model supports extended reasoning/thinking.
Type: null or boolean
Default:
null
Declared by:
programs.pi.providers.<name>.name
Provider identifier.
Type: string
Default:
"‹name›"
Declared by:
programs.pi.providers.<name>.runtimePackages
Runtime dependencies added to PATH for this provider.
Type: list of package
Default:
[ ]
Declared by:
programs.pi.rawExtensions
List of standalone extension file paths or derivations to load.
Type: list of (package or absolute path or string)
Default:
[ ]
Declared by:
programs.pi.rawSkills
List of standalone skill directory paths or derivations to load.
Type: list of (package or absolute path or string)
Default:
[ ]
Declared by:
programs.pi.runtimePackages
List of CLI packages to make available in PATH for Pi and its extensions.
Type: list of package
Default:
[ ]
Declared by:
programs.pi.settings
Pi settings configuration (generated as settings.json).
Type: open submodule of attribute set of anything
Default:
{ }
Declared by:
programs.pi.settings.enableSkillCommands
Register skills as /skill:name commands.
Type: boolean
Default:
true
Declared by:
programs.pi.settings.enabledModels
Model patterns for Ctrl+P cycling.
Type: list of string
Default:
[ ]
Declared by:
programs.pi.settings.compaction
Conversation compaction settings.
Type: null or (submodule)
Default:
null
Declared by:
programs.pi.settings.compaction.enabled
Enable auto-compaction.
Type: null or boolean
Default:
null
Declared by:
programs.pi.settings.compaction.keepRecentTokens
Recent tokens to keep without summarization.
Type: null or signed integer
Default:
null
Declared by:
programs.pi.settings.compaction.reserveTokens
Tokens reserved for LLM response.
Type: null or signed integer
Default:
null
Declared by:
programs.pi.settings.defaultModel
Default model ID to use (string ID or model object).
Type: (null or string) or (string or (attribute set)) convertible to it
Default:
null
Declared by:
programs.pi.settings.defaultProvider
Default LLM provider to use (string name or provider object).
Type: (null or string) or (string or (attribute set)) convertible to it
Default:
null
Declared by:
programs.pi.settings.defaultThinkingLevel
Default reasoning/thinking level.
Type: null or one of “off”, “minimal”, “low”, “medium”, “high”, “xhigh”, “max”
Default:
null
Declared by:
programs.pi.settings.npmCommand
Command argv used for npm package operations.
Type: null or (list of string)
Default:
null
Declared by:
programs.pi.settings.retry
Agent and provider retry settings.
Type: null or (submodule)
Default:
null
Declared by:
programs.pi.settings.retry.enabled
Enable automatic agent-level retry.
Type: null or boolean
Default:
null
Declared by:
programs.pi.settings.retry.baseDelayMs
Base delay for exponential backoff.
Type: null or signed integer
Default:
null
Declared by:
programs.pi.settings.retry.maxRetries
Maximum agent-level retry attempts.
Type: null or signed integer
Default:
null
Declared by:
programs.pi.settings.retry.provider
Provider-level retry configuration.
Type: null or (submodule)
Default:
null
Declared by:
programs.pi.settings.retry.provider.maxRetries
Provider/SDK retry attempts.
Type: null or signed integer
Default:
null
Declared by:
programs.pi.settings.retry.provider.maxRetryDelayMs
Max server-requested delay before failing.
Type: null or signed integer
Default:
null
Declared by:
programs.pi.settings.retry.provider.timeoutMs
Provider timeout in milliseconds.
Type: null or signed integer
Default:
null
Declared by:
programs.pi.settings.sessionDir
Directory for session storage and lookup.
Type: null or string
Default:
null
Declared by:
programs.pi.settings.theme
Name of the active theme.
Type: null or string
Default:
null
Declared by:
programs.pi.skills.brazil-localization-test.enable
Whether to enable Pi Brazil localization test skill.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.skills.brazil-localization-test.package
Package providing the brazil-localization-test skill.
Type: null or package
Default:
<derivation pi-skill-brazil-localization-test-0.1.0>
Declared by:
programs.pi.skills.brazil-localization-test.runtimePackages
Additional runtime packages required by the brazil-localization-test skill.
Type: list of package
Default:
[ ]
Declared by:
programs.pi.skills.commit-style.enable
Whether to enable Pi commit-style skill (Conventional Commits v1.0.0).
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.skills.commit-style.package
Package providing the commit-style skill.
Type: package
Default:
pkgs.piSkills.commit-style
Declared by:
programs.pi.skills.commit-style.customGuidelines
Additional guidelines or rules for writing commit messages.
Type: list of string
Default:
[ ]
Declared by:
programs.pi.skills.commit-style.examples
Additional repository-specific commit examples.
Type: list of (string or (submodule))
Default:
[ ]
Declared by:
programs.pi.skills.commit-style.scopes
List of recommended or repository-specific scopes.
Type: list of string
Default:
[ ]
Declared by:
programs.pi.skills.commit-style.types
List of allowed commit types with descriptions.
Type: list of (string or (submodule))
Default:
[
{
description = "A new feature for the user or library (correlates with SemVer MINOR)";
name = "feat";
}
{
description = "A bug fix for the user or library (correlates with SemVer PATCH)";
name = "fix";
}
{
description = "Documentation changes only";
name = "docs";
}
{
description = "Code style/formatting changes that do not affect code logic or semantics";
name = "style";
}
{
description = "Refactoring production code (neither fixes a bug nor adds a feature)";
name = "refactor";
}
{
description = "A code change that improves performance";
name = "perf";
}
{
description = "Adding missing tests, refactoring tests, or correcting test fixtures";
name = "test";
}
{
description = "Changes that affect the build system or external dependencies (e.g. Nix, npm, Cargo)";
name = "build";
}
{
description = "Changes to CI/CD configuration files, scripts, and workflows (e.g. GitHub Actions)";
name = "ci";
}
{
description = "Routine maintenance tasks, tool configs, or auxiliary changes";
name = "chore";
}
{
description = "Reverts a previous commit";
name = "revert";
}
]
Declared by:
programs.pi.skills.competitor-gap-analysis.enable
Whether to enable Pi competitor gap analysis skill.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.skills.competitor-gap-analysis.package
Package providing the competitor-gap-analysis skill.
Type: null or package
Default:
<derivation pi-skill-competitor-gap-analysis-0.1.0>
Declared by:
programs.pi.skills.competitor-gap-analysis.runtimePackages
Additional runtime packages required by the competitor-gap-analysis skill.
Type: list of package
Default:
[ ]
Declared by:
programs.pi.skills.evidence-deduplication.enable
Whether to enable Pi evidence deduplication skill.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.skills.evidence-deduplication.package
Package providing the evidence-deduplication skill.
Type: null or package
Default:
<derivation pi-skill-evidence-deduplication-0.1.0>
Declared by:
programs.pi.skills.evidence-deduplication.runtimePackages
Additional runtime packages required by the evidence-deduplication skill.
Type: list of package
Default:
[ ]
Declared by:
programs.pi.skills.legal-market-segmentation.enable
Whether to enable Pi legal market segmentation skill.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.skills.legal-market-segmentation.package
Package providing the legal-market-segmentation skill.
Type: null or package
Default:
<derivation pi-skill-legal-market-segmentation-0.1.0>
Declared by:
programs.pi.skills.legal-market-segmentation.runtimePackages
Additional runtime packages required by the legal-market-segmentation skill.
Type: list of package
Default:
[ ]
Declared by:
programs.pi.skills.legal-pain-discovery.enable
Whether to enable Pi legal pain discovery research skill.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.skills.legal-pain-discovery.package
Package providing the legal-pain-discovery skill.
Type: null or package
Default:
<derivation pi-skill-legal-pain-discovery-0.1.0>
Declared by:
programs.pi.skills.legal-pain-discovery.runtimePackages
Additional runtime packages required by the legal-pain-discovery skill.
Type: list of package
Default:
[ ]
Declared by:
programs.pi.skills.opportunity-scoring.enable
Whether to enable Pi opportunity scoring skill.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.skills.opportunity-scoring.package
Package providing the opportunity-scoring skill.
Type: null or package
Default:
<derivation pi-skill-opportunity-scoring-0.1.0>
Declared by:
programs.pi.skills.opportunity-scoring.runtimePackages
Additional runtime packages required by the opportunity-scoring skill.
Type: list of package
Default:
[ ]
Declared by:
programs.pi.skills.product-opportunity-report.enable
Whether to enable Pi product opportunity report skill.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.skills.product-opportunity-report.package
Package providing the product-opportunity-report skill.
Type: null or package
Default:
<derivation pi-skill-product-opportunity-report-0.1.0>
Declared by:
programs.pi.skills.product-opportunity-report.runtimePackages
Additional runtime packages required by the product-opportunity-report skill.
Type: list of package
Default:
[ ]
Declared by:
programs.pi.skills.voice-of-customer-mining.enable
Whether to enable Pi voice of customer mining skill.
Type: boolean
Default:
false
Example:
true
Declared by:
programs.pi.skills.voice-of-customer-mining.package
Package providing the voice-of-customer-mining skill.
Type: null or package
Default:
<derivation pi-skill-voice-of-customer-mining-0.1.0>
Declared by:
programs.pi.skills.voice-of-customer-mining.runtimePackages
Additional runtime packages required by the voice-of-customer-mining skill.
Type: list of package
Default:
[ ]
Declared by:
programs.pi.themes
List of theme JSON files or derivations to load.
Type: list of (package or absolute path or string)
Default:
[ ]
Declared by:
FAQ
Why are there files in both ~/.pi/agent and $XDG_DATA_HOME/nixpi/agent?
This is the concern raised in issue #3. It is not a configuration split. Home Manager links generated settings.json and models.json under ~/.pi/agent. The generated launcher sets PI_CODING_AGENT_DIR to its XDG runtime directory and links the same immutable generated configuration there before Pi starts.
Pi reads the directory selected by the launcher. The Home Manager links are useful as a conventional, inspectable location, but they are not a competing configuration source. auth.json and sessions/ remain writable runtime state.
Where should API keys go?
Outside Nix expressions. Export them from your shell, direnv, a secret manager, or host secret integration, then list only the variable names in programs.pi.environment.required. See direnv.
Why does nix build not show my new secret or session?
Those values are intentionally not build inputs. nixpi produces immutable configuration and a launcher. Credentials and session state are runtime data, so they are neither copied into the Nix store nor changed by rebuilds.
Which branch should I pin?
Pin main for the stable release channel or track specific version tags like v1.0.0. Pin the input deliberately in your flake.nix, commit flake.lock, and read warnings when updating. Use the versioned compatibility policy in the README and migration guide when moving older configurations.
How do I see every available option?
Open All options on this site. It is generated with nixosOptionsDoc from the evaluated programs.pi schema. Locally, run nix build .#docs and open result/share/doc/nixpi/options.md.
Can I use nixpi without Home Manager, NixOS, or nix-darwin?
Yes. Use lib.nixpi.makePi in a standalone flake, or initialize the standalone template. Run the resulting package with nix run .#.
How do I add an extension or skill that nixpi does not package?
Package it with mkPiExtension or mkPiSkill, then compose an option module with mkPiExtensionModule or mkPiSkillModule. The Library API includes each function signature and example.
Why did I get a deprecation warning?
The output or option is a supported 1.x compatibility alias. The warning names its replacement. Update to that replacement before the next major version, then run nix flake check to validate the migrated configuration.
Migrating to the edge architecture
The edge release reorganizes internals while preserving the 1.x public contract.
Recommended names
- Use
lib.nixpifor library helpers. - Use
piModules.basefor the complete reusable core. - Use
homeModules.default,nixosModules.default, ornixDarwinModules.defaultfor host integration. - Import learning and Obsidian resources directly from
deep-comprehension-enginein new configurations.
Compatibility aliases
The previous helper names, piModules.core, homeManagerModules, learning profile, Obsidian extension, and moved learning skill packages remain available throughout 1.x. They emit evaluation warnings but preserve behavior.
Rollout checklist
- Update the nixpi input on a feature branch.
- Run
nix flake checkin the consuming configuration. - Replace warned names with their documented replacements.
- Build the target Home Manager, NixOS, or nix-darwin configuration without activating it.
- Commit the updated lock file before activation.
Runtime secrets stay outside the Nix store. If environment.required is used, make sure those variables exist in the activation environment before starting Pi.
Security policy
Reporting a vulnerability
Use GitHub private vulnerability reporting for the repository. Do not open a public issue for suspected credential exposure, arbitrary code execution, unsafe generated shell, or a dependency vulnerability with a known exploit.
Include the affected revision, configuration, reproduction steps, impact, and any known mitigation. Maintainers should acknowledge a complete report within three business days and coordinate disclosure after a fix is available.
Supported versions
The latest stable release and the current edge release candidate receive security fixes. Older revisions may receive a backport when upgrading immediately would create a larger operational risk.
Security boundaries
nixpi generates packages, configuration files, and a runtime wrapper. Secret values must be supplied at runtime and must not be committed to Nix expressions, lock files, build logs, or store paths. Report any behavior that serializes secret values into the Nix store.
Architecture
nixpi separates stable contracts from implementation details.
Layers
lib/evaluates modules, builds packages, defines resource constructors, and owns deprecation helpers.modules/core/defines the reusableprograms.pischema and package assembly.modules/extensions/,modules/skills/, andmodules/providers/add one capability each.modules/profiles/composes capabilities into opinionated configurations.integrations/maps the shared module into Home Manager, NixOS, and nix-darwin.flake/publishes modules, packages, templates, checks, and legacy builders.
The root flake.nix only composes these output families. This keeps public contracts visible while preventing one file from owning unrelated concerns.
Dependency direction
Feature modules may depend on core options. Profiles may depend on feature modules. Integrations may depend on the complete module. Core modules must not depend on profiles or integrations.
Compatibility
Renames use helpers from lib/deprecation.nix. A deprecated output must continue to evaluate, identify its replacement, and have contract coverage. Breaking removals are reserved for a major release.
Verification
Unit-style evaluation tests cover option behavior. End-to-end tests execute the wrapped binary. Integration tests evaluate the project inside the real Home Manager, NixOS, and nix-darwin module systems. CI evaluates every supported system and builds on each platform family.
Container tests
nixpi builds its CI images directly with Nix. No imperative Dockerfile installation is involved, so the Pi package and scenario configuration use the same locked inputs as every other output.
Scenarios
| Scenario | Coverage |
|---|---|
minimal | Pi startup with no optional extensions or skills |
features | Echo, ripgrep search, plan mode, and commit-style skill |
provider | Custom OpenAI-compatible provider and required runtime secret |
Each scenario has two checks:
- A flake check executes Pi and validates generated JSON with
jq. - Docker CI builds the image, loads it into Docker, verifies its scenario label, and runs the same test inside the container as an unprivileged user.
Docker CI runs every scenario on x86_64 Linux and ARM Linux.
Run locally on Linux
nix build .#docker-features
docker load < result
docker run --rm nixpi-ci-features:edge
Run only the configuration-level check with:
nix build .#checks.$(nix eval --impure --raw --expr builtins.currentSystem).container-features-tests
Contributing
Thank you for improving nixpi.
Before opening a change
- Check existing issues and pull requests for overlapping work.
- Discuss public API changes before implementation.
- Keep each change focused on one behavior or architectural concern.
Local checks
Use a recent Nix installation with flakes enabled:
nix fmt
nix flake check -L
nix flake check --all-systems --no-build -L
Add evaluation coverage for option changes, end-to-end coverage for runtime behavior, and real host integration coverage when Home Manager, NixOS, or nix-darwin behavior changes.
Design rules
- Keep the public
programs.pischema shared across integrations. - Put reusable behavior in
modules/core, one capability per feature module, and composition in profiles. - Preserve 1.x APIs with a deprecation warning and a tested compatibility alias.
- Keep secrets out of Nix expressions and generated store paths.
- Prefer direct Nix module composition over custom framework machinery.
Commits and pull requests
Use Conventional Commits such as fix(runtime): ... or docs: .... Each commit must be independently buildable and should contain one logical change. Pull requests should explain behavior, compatibility impact, and verification performed.
Maintainer guide
Release channels
mainis the stable channel.edgeis the release candidate for upcoming changes.- Version tags use Semantic Versioning and the form
vMAJOR.MINOR.PATCH.
The unified architecture was promoted to main as v1.0.0 on August 30, 2026.
Compatibility policy
Public flake outputs, module options, and library functions introduced in 1.x remain usable throughout 1.x. Renames and moves require:
- A compatibility alias with an evaluation warning.
- A direct replacement in the warning and migration guide.
- Contract coverage for the old and new names.
- Removal only in the next major release.
Security fixes may override this policy when preserving behavior would leave users exposed. Document the exception in the release notes.
Release process
- Confirm
edgepasses every required CI job. - Review deprecation warnings and the migration guide.
- Build generated documentation with
nix build .#docs. - Merge the tested edge release into
mainwithout unrelated changes. - Create an annotated version tag on the stable commit.
- Push the tag. The release workflow validates the commit and publishes generated release notes.
- Verify a fresh consumer can evaluate each supported host integration.
Do not edit generated release notes or generated option documentation in source. Fix their inputs instead.
Supported systems
CI evaluates all declared systems and builds on x86_64 Linux, ARM Linux, Intel macOS, and Apple Silicon macOS. A system is supported only when its native CI job is required and passing.
Intel macOS uses the Nixpkgs 26.05 Darwin branch, which receives security fixes through the end of 2026. Reassess its support plan before that maintenance window closes.
1. Mutable vs. Immutable State Separation
Date: 2026-08-15
Status
Accepted
Context
Pi Coding Agent manages both declarative resources (settings, packages, extensions, skills, prompt templates, themes, custom model definitions) and mutable runtime state:
- Session history (
sessions/orPI_CODING_AGENT_SESSION_DIR) - Authentication credentials and tokens (
auth.json) - Runtime lock files
- Debug log files (
pi-debug.log)
When PI_CODING_AGENT_DIR is pointed directly to a read-only path in /nix/store, Pi attempts to call writeFileSync to ensure auth.json exists on startup and fails with EACCES: permission denied.
Decision
- Store declarative files (
settings.json,models.json, packaged extensions, skills, themes, prompts) immutably in the Nix store. - In Home Manager mode, link
settings.jsonandmodels.jsoninto the user’s mutable agent directory (~/.pi/agent/or$XDG_CONFIG_HOME/pi/agent/), leavingauth.jsonandsessions/writable by Pi. - In standalone and devShell wrapper mode, default mutable state to the user’s standard home directory (
~/.pi/agent) while instructing the wrapper to read declarative configuration from the generated store paths, and allow configuringsessionDir/PI_CODING_AGENT_SESSION_DIR. - Ensure no secret tokens or keys are written to
/nix/store. Passwords and API keys remain external environment variables or are managed viaauth.json/ secret managers.
Consequences
- Pi runs smoothly without permission errors.
- Declarative settings and extensions are 100% reproducible via Nix.
- Sessions and auth state persist normally without polluting the Nix store.
2. Adoption of Nixvim Architectural Patterns and Composability
Date: 2026-08-26
Status
Accepted
Context
As nixpi evolved into a declarative framework for configuring the Pi coding agent, it became necessary to benchmark its architecture against mature, large-scale Nix configuration frameworks. Neovim’s premier Nix framework, nixvim (with 450+ plugins, multi-platform integrations, and high composability), offers battle-tested design patterns for configuration management, module scaling, package distribution, and testing.
Key architectural gaps in early nixpi versions included:
- Lack of package composition: Evaluating a Pi package via
makePireturned an opaque derivation. Users could not easily inspect the evaluatedconfig/optionsor extend an already-configured instance (pkg.extend { ... }). - Boilerplate in module definitions: Extensions and skills required repetitive option definitions (
enable,package,settings,runtimePackages). - Platform wrapper fragmentation: Only Home Manager was integrated, with no native NixOS or nix-darwin system module wrappers.
- Flake output rigidity: Flake exports were tied to specific naming conventions without standardized aliases or unified builder endpoints.
Decision
We adopt the following architectural patterns from Nixvim into nixpi:
1. Package Distribution Strategy
- Nixpi separates declarative module abstractions from package definitions.
- Modules accept a
packageoption defaulting to either the internal package or an upstream package, allowing users to override the underlying derivation cleanly. - Direct escape hatches (
programs.pi.extraPackages,programs.pi.extraExtensions,programs.pi.extraSkills) allow injecting arbitrary derivations without needing dedicated modules.
2. Standalone Package Composability (passthru.extend)
makePinow wraps the resulting derivation withpassthru = { config, options, extend, unwrapped }.- Calling
pkg.extend { programs.pi.skills.commitStyle.enable = true; }evaluates a new Pi package by appending the additional modules to the base configuration, mirroring Nixvim’smakeNixvimcomposability.
3. Standardized Module Factories (lib.mkPiExtensionModule & lib.mkPiSkillModule)
- Introduce helper generators in
lib/module-factories.nixthat generate standardized module schemas:programs.pi.extensions.<name>.enableprograms.pi.extensions.<name>.packageprograms.pi.extensions.<name>.settingsprograms.pi.extensions.<name>.runtimePackages
- Reduces code duplication across extension and skill definitions by ~70%.
4. Multi-Platform Module Unification (integrations/)
- Establish a shared evaluation engine (
integrations/shared.nix) providing consistent options across:- Standalone:
lib.makePi/legacyPackages.${system}.makePiWithModule - Home Manager:
homeModules.default(withhomeManagerModulespreserved as a backwards-compatible alias) - NixOS:
nixosModules.defaultandnixosModules.pi - Nix-Darwin:
nixDarwinModules.defaultandnixDarwinModules.pi
- Standalone:
5. Strict Backwards Compatibility & Graceful Deprecations
- All existing flake outputs (
piModules,homeManagerModules,packages.*,lib.*) remain 100% functional. - Any naming modernizations (e.g.
homeModulesoverhomeManagerModules) provide transparent compatibility layers and non-breaking warnings.
Consequences
- Pre-configured Pi environments can be dynamically extended in devshells and downstream flakes using
.extend { ... }. - System-level configuration is now supported natively across Linux (NixOS) and macOS (nix-darwin).
- Authoring new extensions and skills requires significantly less boilerplate.
- Existing user configurations and test suites continue to work without any breaking changes.