108 lines
8.2 KiB
Markdown
108 lines
8.2 KiB
Markdown
---
|
|
name: nixos-workflow
|
|
description: STRICT workflow for managing Pi assets via Gitea on NixOS
|
|
version: 1.2.0
|
|
---
|
|
|
|
# NixOS Gitea Asset Manager (STRICT)
|
|
|
|
You are an expert at managing Pi Agent assets on a NixOS system using a Gitea-centric workflow.
|
|
|
|
## ⛔ CRITICAL PROHIBITIONS
|
|
- **NEVER** suggest or perform edits to `home.nix` to add individual extensions or skills.
|
|
- **NEVER** use `pi install` or `npm install -g` (Nix store is read-only).
|
|
## 🗄 PER-MACHINE REPOS
|
|
Each machine has its OWN `~/.agents` git repo — its own clone of the shared Gitea `pi-config` repo (Gitea itself runs as Docker on `.35`, web `.35:3001`, SSH `.35:2222`). **A push from `.27` does NOT auto-update `.13`/`.51`** — update each machine's clone individually (`git -C ~/.agents pull`). `/config-add` discovery reads the local `~/.agents/extensions|skills` dirs, so a machine must pull before a new asset can be activated there. (.51 had no repo until 2026-08-05 — cloned then.)
|
|
|
|
## 🛠 THE SOURCE OF TRUTH
|
|
All assets MUST be managed in the local Git-controlled directory:
|
|
- **Local Path**: `/home/sam/.agents`
|
|
- **Remote URL**: `https://gitea.lab.audasmedia.com.au/sam/pi-config`
|
|
|
|
## 🏗 ASSET DEPLOYMENT WORKFLOW
|
|
When the user asks for a new tool or skill, you MUST follow these steps exactly:
|
|
|
|
1. **Local Authoring** — the asset MUST be a directory under `~/.agents/`:
|
|
- Skills: `skills/<name>/SKILL.md` (+ optional supporting files).
|
|
- Extensions: `extensions/<name>/index.ts` (or `index.js`), or a `package.json` with a `"pi": { "extensions": ["./index.ts"] }` manifest.
|
|
- **Vendoring an external npm package**: copy the published package into `extensions/<name>/` (e.g. `npm pack <pkg>` then extract). If cloning a git repo instead, immediately `rm -rf .git` inside that folder (prevents submodule issues) and remove `.gitignore` if present.
|
|
2. **Local Dependency Check + Security**:
|
|
- If an extension, run `npm install` inside that specific subfolder. `node_modules/` is gitignored (see `.gitignore`) — pi runs `npm install` automatically after pulling from Gitea, so deps are never committed.
|
|
- Run `vet scan -D .` (npm-security skill) and follow the vet → npq → socket workflow for any installs.
|
|
3. **Gitea Synchronization**:
|
|
- `cd /home/sam/.agents`
|
|
- `git add .`
|
|
- `git commit -m "Add [asset name]"`
|
|
- `git push origin main`
|
|
4. **Project Activation — via `/config-add`, NEVER by hand**:
|
|
- The user activates per project with `/config-add skill <name>` or `/config-add ext <name>`, then `/reload`.
|
|
- **Do NOT hand-edit any `.pi/settings.json`**, and do NOT add bare `"npm:..."` package entries to settings. `/config-add`/`/config-remove`/`/config-show`/`/config-list` (pi-config extension) are the ONLY sanctioned interface to project settings.
|
|
|
|
## 🔍 DISCOVERY & ACTIVATION (pi-config commands)
|
|
|
|
`/config-add`, `/config-remove`, `/config-show`, `/config-list` are provided by the **pi-config** extension (`~/.agents/extensions/pi-config/index.ts`). Mechanics that matter:
|
|
|
|
- **Discovery is directory-based.** The commands list subdirectory names under `~/.agents/skills/` and `~/.agents/extensions/`. If an asset is not a directory there, it is invisible to `/config-list`/`/config-show` and `/config-add` will refuse it ("not found in ~/.agents/...").
|
|
- `/config-add` resolves the entry point (`skills/<name>`, `extensions/<name>/index.ts`, or the `pi.extensions` list from the folder's `package.json`) and appends it to the project's `~/.agents` package entry in `.pi/settings.json`, then asks for `/reload`.
|
|
- Project settings **replace** (not merge) global settings — each folder loads only what it needs, keeping the LLM context lean. This is the point of the whole workflow: no clutter.
|
|
- **Global-only packages** (e.g. pi-memctx, @tintinweb/*) are NOT per-project assets — they live in the home-manager-managed global `~/.pi/agent/settings.json` (`/etc/nixos/home/sam/home.nix`) and are out of scope for `/config-add`.
|
|
|
|
## ✅ WORKED EXAMPLE — adding `pi-langfuse` (2026-08-03)
|
|
|
|
External npm extension (Langfuse LLM observability for pi) vendored + activated:
|
|
|
|
1. `npm pack pi-langfuse@1.5.8` → extracted into `~/.agents/extensions/pi-langfuse/` (contains `package.json` with `pi.extensions: ["./index.ts"]`)
|
|
2. `npm install` inside the folder (deps gitignored; pi reinstalls on pull)
|
|
3. `vet scan -D .` → clean (242 packages)
|
|
4. `git add . && git commit && git push` → Gitea `pi-config` (commit `bc91a15`)
|
|
5. Project activation: `/config-add ext pi-langfuse` → writes `"extensions/pi-langfuse/index.ts"` to the project's `.pi/settings.json`, then `/reload`
|
|
|
|
The extension's own config lives at `~/.pi/agent/pi-langfuse/config.json` (`publicKey`/`secretKey`/`host` → `http://192.168.20.13:3001`). Commands: `/langfuse-setup`, `/langfuse-status`. Full documentation: `/home/sam/obsidian/300 areas/350 AI/Pi Agent Extensions & Skills.md` (section "pi-langfuse — LLM Observability for Pi").
|
|
|
|
## ⚠️ VENDORING PITFALL — vscode-languageserver-protocol subpath
|
|
`pi-lsp-extension` (and possibly other extensions) imports `vscode-languageserver-protocol/node.js`. npm resolves `^3.17.5` to 3.18.x whose `exports` map exposes `./node` but **not** `./node.js` — the import throws at load and the ENTIRE extension silently fails (no `/lsp` commands appear, while other extensions still load — confusing). Fix: change the import to `vscode-languageserver-protocol/node` (no `.js`); re-apply whenever re-vendoring from npm (our fix = commit `57c5cd2`).
|
|
|
|
**Load-verify any vendored extension** by bundling it the way pi's loader does:
|
|
```bash
|
|
npx esbuild src/index.ts --bundle --platform=node --format=esm \
|
|
--external:@earendil-works/* --external:vscode-languageserver-protocol \
|
|
--external:web-tree-sitter --external:tree-sitter-wasms --outfile=/tmp/x.mjs
|
|
# then import /tmp/x.mjs with a stub ExtensionAPI (registerTool/registerCommand/on/events)
|
|
```
|
|
|
|
## ❄ NIXOS INTEGRATION
|
|
The ONLY time you reference Nix is for the **Global Settings**. Confirm the user's `home.nix` contains a `settings.json` that points to the Gitea source:
|
|
`"source": "git:https://gitea.lab.audasmedia.com.au/sam/pi-config"`
|
|
|
|
## 🖥 PI INSTALLATION CONTEXT
|
|
On all three machines (`.27`/`.13`/`.51`) `pi` is **Nix-managed** — the nixpkgs package **`pi-coding-agent`** (v0.82.1) in `home.packages`. There is NO npx wrapper and NO npm-global install anymore (both removed 2026-08-05).
|
|
- **`pi update --self` / `pi update --extensions`**: not applicable — the binary is Nix. Updating pi = bump the nixpkgs flake input (`nix flake update nixpkgs`) + `sudo nixos-rebuild switch --flake .#<host>`.
|
|
- **Never `npm install -g @earendil-works/pi-coding-agent`** — npm-global/bin precedes `/etc/profiles/per-user/sam/bin` in PATH, so it shadows the Nix pi (caused a real bug once).
|
|
- **After a Nix pi switch: fully CLOSE running pi sessions.** A `/reload` in a session started from the old binary fails — the loader re-resolves every extension import against the old runtime dir, which no longer exists. Fresh sessions only.
|
|
- **Vendored extensions** (`pi-tool-display` global, `pi-lsp-extension` per-project) live in `~/.agents`; see the Obsidian doc `350 AI → Pi Agent Extensions & Skills.md`.
|
|
|
|
## ⌨ KEYBOARD TROUBLESHOOTING (Corne/QMK)
|
|
|
|
The user has a Corne-like QMK keyboard. These are critical things to remember:
|
|
|
|
### Caps lock stuck ON
|
|
If all letters output uppercase and Shift inverts to lowercase, the Lower/Raise layer keys may be reversed in the keymap. **Do NOT suggest hardware resets or firmware flashing.**
|
|
|
|
**Fix**: Use VIA Web at https://usevia.app — it works immediately in Chrome via WebHID (no install needed). The user can identify and remap misconfigured keys there.
|
|
|
|
### udev setup for VIA/Vial Web
|
|
Required in `configuration.nix`:
|
|
```nix
|
|
services.udev.extraRules = ''
|
|
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", GROUP="input", MODE="0660"
|
|
'';
|
|
users.users.sam.extraGroups = [ "input" ];
|
|
```
|
|
After rebuild, unplug/replug the keyboard for permissions to take effect.
|
|
|
|
### Vial desktop app — DO NOT recommend
|
|
- The nixpkgs `vial` package wraps an AppImage with no Qt5 Wayland support
|
|
- It fails with `Could not connect to any X display`
|
|
- VIA Web (usevia.app) provides identical functionality without native dependencies
|
|
- Only suggest the desktop app if the nixpkgs package has been proven to work on Wayland
|