refactor(home/pi): consolidate pi package wiring

Reorganize Pi configuration around local resources and external package modules:
- load local extensions, skills, and prompts from the main Pi module
- move external packages behind packages/default.nix
- use buildPiPackage terminology throughout
- refresh the pi-extension-authoring workflow skill

Assisted-by: pi (gpt-5.5)
This commit is contained in:
Gabriel Fontes
2026-06-29 04:25:10 -03:00
parent 3d8d365b45
commit 85892ad024
22 changed files with 92 additions and 125 deletions
+42 -10
View File
@@ -1,21 +1,27 @@
{pkgs, ...}: {
{
pkgs,
osConfig,
lib,
...
}: let
customExtensions = pkgs.buildPiPackage {
pname = "extensions";
version = "unstable";
src = ./extensions;
npmDeps = pkgs.importNpmLock {npmRoot = ./extensions;};
npmConfigHook = pkgs.importNpmLock.npmConfigHook;
};
in {
imports = [
./theme.nix
./extensions
./prompts
./skills
./packages/pi-claude-bridge.nix
./packages/pi-codex-image-gen.nix
./packages/pi-llama-cpp.nix
./packages
];
programs.pi-coding-agent = {
enable = true;
# Used by the web-fetch skill to extract fetched HTML as Markdown.
extraPackages = [pkgs.python3Packages.trafilatura];
extraPackages = [pkgs.python3Packages.trafilatura]; # Used by the web-fetch skill
context = ./context.md;
settings = {
llamaServerUrl = "http://llm.m7.rs";
compaction = {
enabled = true;
keepRecentTokens = 20000;
@@ -28,6 +34,32 @@
"qwen3.6"
"gemma-4"
];
skills = [./skills];
prompts = [./prompts];
extensions = [customExtensions];
webSearch = {
braveApiKeyFile = osConfig.sops.secrets.brave_api_key.path;
kagiSessionTokenFile = osConfig.sops.secrets.kagi_session_token.path;
};
gondolin = {
qemuPath = lib.getExe pkgs.qemu;
httpProxy = {
allowedHosts = ["api.github.com" "firefly.m7.rs"];
secrets = {
GITHUB_TOKEN = {
hosts = ["api.github.com"];
cmd = "gh auth token";
};
FIREFLY_TOKEN = {
hosts = ["firefly.m7.rs"];
cmd = "pass firefly.m7.rs/pi-pat";
};
};
};
};
};
keybindings = {
"app.editor.external" = ["alt+e"];
@@ -1,42 +0,0 @@
{
pkgs,
lib,
osConfig,
...
}: let
gabsExtensions = pkgs.buildPiExtension {
pname = "pi-extensions";
version = "unstable";
src = ./gabs-extensions;
npmDeps = pkgs.importNpmLock {npmRoot = ./gabs-extensions;};
npmConfigHook = pkgs.importNpmLock.npmConfigHook;
};
in {
programs.pi-coding-agent = {
settings = {
extensions = [
gabsExtensions
];
webSearch = {
braveApiKeyFile = osConfig.sops.secrets.brave_api_key.path;
kagiSessionTokenFile = osConfig.sops.secrets.kagi_session_token.path;
};
gondolin = {
qemuPath = lib.getExe pkgs.qemu;
httpProxy = {
allowedHosts = ["api.github.com" "firefly.m7.rs"];
secrets = {
GITHUB_TOKEN = {
hosts = ["api.github.com"];
cmd = "gh auth token";
};
FIREFLY_TOKEN = {
hosts = ["firefly.m7.rs"];
cmd = "pass firefly.m7.rs/pi-pat";
};
};
};
};
};
};
}
@@ -0,0 +1,7 @@
{
imports = [
./pi-claude-bridge.nix
./pi-codex-image-gen.nix
./pi-llama-cpp.nix
];
}
@@ -1,4 +1,4 @@
{pkgs, ...}: let
{pkgs, lib, ...}: let
piClaudeBridge = pkgs.buildPiPackage {
pname = "pi-claude-bridge";
version = "unstable";
@@ -11,5 +11,8 @@
dontNpmInstall = true;
};
in {
programs.pi-coding-agent.settings.packages = [piLlamaCpp];
programs.pi-coding-agent.settings = {
llamaServerUrl = "http://llm.m7.rs";
packages = [piLlamaCpp];
};
}
@@ -1,5 +0,0 @@
{
programs.pi-coding-agent.settings.prompts = [
./.
];
}
@@ -1,5 +0,0 @@
{
programs.pi-coding-agent.settings.skills = [
./.
];
}
@@ -1,83 +1,62 @@
---
name: pi-extension-authoring
description: Workflow for creating or wiring Pi extensions and skills. Use when adding, changing, packaging, or persisting global Pi extensions/skills for Gabs; not for per-project extensions/skills. Always load this when you consider writing/editing `~/.pi/agent` in any way.
description: Workflow guidelines for durable Pi package, extension, skill, prompt, and theme changes in Gabs's Nix-managed Pi config. Use before editing ~/.pi/agent or home/gabriel/features/pi.
---
# Pi Extending for Gabs's NixConfig
# Pi Authoring for Gabs's NixConfig
This skill is the local persistence map and workflow, not a replacement for Pi docs. If API details are needed, read the relevant Pi docs/examples first, then apply the repo-specific rules here.
This is a workflow guardrail, not a duplicate map of the code. Inspect the existing Nix files and follow their current shape.
The config usually lives at `~/Projects/NixConfig` and at `https://github.com/misterio77/nix-config`.
## First principles
This only applies to "global" (i.e. `~/.pi/agent`) pi configs.
- Read the current Pi docs before relying on API/package behavior: packages, extensions, skills, themes, and TUI docs as relevant.
- Do not edit `~/.pi/agent/*` for durable changes. It is Home Manager output. Temporary experiments are fine, but upstream working changes into Nix before calling them done.
- Prefer Pi packages for third-party/external resources. If a package provides metadata or conventional resource directories, wire it as a package and let Pi discover what it contains.
- Do not split a single external package into separate extension/skill paths unless package discovery genuinely cannot represent it.
- Use `pkgs.buildPiPackage` for package wiring.
## Persistence model
## Local vs external
Do not edit `~/.pi/agent/*` directly for durable changes. It is Home Manager output.
- Gabs-owned code belongs in the local Pi resource areas already wired by the module.
- Third-party code belongs under the external package module pattern already present in the repo.
- When unsure, copy the nearest existing example and adjust minimally. The repo is the source of truth; this skill is just the goblin with a clipboard.
Durable Pi config lives under:
## Change process
- `home/gabriel/features/pi/default.nix` — core Pi settings, context, keybindings
- `home/gabriel/features/pi/extensions/default.nix` — extension packages and `settings.extensions`
- `home/gabriel/features/pi/extensions/gabs-extensions/` — Gabs's packaged TypeScript extensions
- `home/gabriel/features/pi/skills/default.nix` — skill list exported to Pi settings
- `home/gabriel/features/pi/skills/*/SKILL.md` — repo-managed skills
1. Inspect current files before editing.
2. For external packages, review the source first. Pi packages can execute code; skills can instruct the agent to do anything.
3. Keep package derivations single-source: if one package contains both extension and skill resources, build/fetch it once.
4. Update package imports/aggregation in the same style as the existing modules.
5. Format touched Nix files only.
6. Evaluate the relevant `programs.pi-coding-agent.settings` values to confirm paths/types are what Pi will receive.
7. If package discovery matters, inspect the built output for `package.json` / conventional resource directories.
## Configuring Pi
## Local extension process
Edit the relevant `.nix` files.
When changing Gabs-owned TypeScript extensions:
## Tweaking global context
1. Keep runtime dependencies in `package.json`; update the lockfile when dependencies change.
2. Run the package's typecheck and formatter/check scripts from the extension package directory.
3. Then format touched Nix files and evaluate the Pi settings/package output.
Edit the `context.md` file.
## Skill content guidelines
## Adding or changing a local extension
Use `home/gabriel/features/pi/extensions/gabs-extensions/` for Gabs-owned extensions.
Checklist:
1. Add or edit a `*.ts` file there.
2. Keep dependencies in `package.json`; update `package-lock.json` if dependencies change.
3. Run from that directory:
- `npm run typecheck`
- `npm run format` if TypeScript files changed
4. From repo root, format touched Nix files with `nix fmt <file>`.
5. Build/evaluate enough to catch packaging mistakes. For this repo, the extension package is wired by `pkgs.buildPiExtension` in `home/gabriel/features/pi/extensions/default.nix`.
Avoid one-off extension paths in `~/.pi/agent/settings.json`; use the Nix module so the store path is regenerated by Home Manager.
## Adding or changing a skill
Use `home/gabriel/features/pi/skills/<name>/SKILL.md`, then add the directory to `home/gabriel/features/pi/skills/default.nix`.
Skill content should be Gabs/repo-specific. Do not paste generic Pi docs into skills; instead point the model to read Pi docs when API specifics matter.
Skills in this repo should stay Gabs/repo-specific. Do not paste generic Pi docs into skills; point the agent to read the docs when API details matter.
Good skill material:
- local file paths and ownership
- build/test commands for this repo
- Pi-authoring-specific workflow ordering
- gotchas discovered while dogfooding this Nix-managed Pi setup
- workflow ordering
- local gotchas
- repo-specific verification commands
- decisions that are not obvious from copying nearby Nix
Bad skill material:
- copied ExtensionAPI reference
- copied TUI component docs
- generic TypeScript tutorials
- copied API reference
- copied TUI docs
- generic TypeScript/Nix tutorials
- directory maps that duplicate what the Nix files already show
## Avoid duplicating global rules
## Reloading
Do not restate rules from `home/gabriel/features/pi/context.md` or other skills here. For VCS work, load `jujutsu`; for harness identity, commit trailers, and push policy, follow the context file.
This skill should only carry Pi-authoring-specific local knowledge: where persistent files live, how Gabs packages extensions, and what to verify before calling the wiring done.
## Rebuilding
See repo's `AGENTS.md` for testing/building/deployment info.
## Reloading and testing
After NixOS/home-manager applies the config, Pi sees extension and skill paths from generated settings. During active Pi sessions, use `/reload` to reload extensions, skills, prompts, and themes after the underlying files are available.
For quick local API experiments, writing to `~/.pi/agent` is fine, but convert successful experiments into the Nix-managed `gabs-extensions` package before calling them done.
After Home Manager applies config, active Pi sessions may need `/reload` to pick up changed extensions, skills, prompts, or themes.
-2
View File
@@ -118,8 +118,6 @@ in {
});
});
buildPiExtension = final.buildPiPackage;
buildPiPackage = let
inherit (final) lib buildNpmPackage jq stdenvNoCC;
fakeSha512 = lib.convertHash {