@bacnh85/pi-selfskills
v0.4.0
Published
Pi extension for skill self-improvement — one skill_manage tool (list/read/patch/create/write/delete/restore) to patch gaps in loaded skills and create new ones, with a writable-root allowlist, SDK validation, and content-addressed backups.
Maintainers
Readme
@bacnh85/pi-selfskills
Pi extension for skill self-improvement: one skill_manage tool that lets
the agent patch gaps in its own loaded skills and create new skills for
recurring procedures — with a writable-root allowlist, real SDK validation,
atomic writes, and content-addressed backups. Ships a selfskills doc-skill
(long-form patch/create discipline) and injects a compact standing-rules block
each turn (patch-by-exception default: most tasks end with no skill write).
Why
Skills rot the first time reality disagrees with them. Without tooling the
agent either silently works around a stale skill or rewrites the whole file by
hand. pi-selfskills makes the fix a first-class, guarded action: targeted
patch in the same turn the gap surfaces, validated against the same loader pi
uses at startup, with an automatic backup and a one-step restore.
Tool: skill_manage
| Action | Params | What it does |
|---|---|---|
| list | skill? (filter) | Discovered skills: name — description (first 100 chars) — path — patchable yes/no |
| read | skill | path, file? | SKILL.md (default) or a bundled file; truncated at 30k chars; records THAT file as read — reading a bundled file does not unlock patch/write/delete (those gate on the SKILL.md read state). Scoped to discovered skill dirs — no arbitrary-file reads |
| patch | skill|path, old_string, new_string | Targeted replacement; backup first; refuses non-unique matches and invalid results |
| create | name, description, body | New skill <skillsDir>/<name>/SKILL.md, SDK-validated |
| write | skill|path, file, content | Create/overwrite a bundled file (references/*.md, scripts/…); SKILL.md is patch-only; overwrites backed up |
| delete | skill|path, file? | Delete a bundled file — or the whole skill (omit file): full snapshot first, always restorable |
| restore | skill|path, file?, backup? | Revert SKILL.md or a bundled file to latest/named backup; recreate a deleted skill from its deletion snapshot; current content backed up first |
| operations | [{action: patch\|write\|delete, …}] | All-or-nothing batch: planned on an in-memory overlay, fully validated, committed together — any PLANNING failure writes NOTHING. A commit-time filesystem failure (hash re-check against a file changed on disk mid-flight, unreadable target) may partially apply and is reported with what landed |
skill_manage { "action": "list" }
skill_manage { "action": "read", "skill": "my-skill" }
skill_manage { "action": "patch", "skill": "my-skill",
"old_string": "Run npm build.", "new_string": "Run npm run build." }
skill_manage { "action": "create", "name": "deploy-checks",
"description": "Use when deploying. Verifies health after rollout.",
"body": "1. ...\n2. ..." }
skill_manage { "action": "restore", "skill": "my-skill" }Patch gates, in order: non-empty old_string ≠ new_string → file was read
this session → file unchanged since read (hash precondition — re-read and
retry on mismatch) → path inside a writable root → old_string occurs exactly
once → patched result passes real SDK skill validation → backup → atomic write
under the shared file-mutation queue.
Writable roots (everything else is refused):
<agentDir>/skills(i.e.$PI_CODING_AGENT_DIR/skillsor~/.pi/agent/skills)<cwd>/.pi/skills— only when the project is trusted (isProjectTrusted())- project
.agents/skills(cwd + ancestors up to the git root) — trusted projects, unlesspatchProjectAgents: false - local package skill dirs from settings
packages— unlesspatchPackages: false - the
selfskills.skillsDiroverride
Read-only by policy: user-level ~/.agents/skills, npm:/node_modules
package skills, skills from settings skill arrays / --skill flags, anything in
untrusted projects (including their declared packages — never scanned), and
anything outside the roots above.
Command
/selfskills — status: enabled, inject, skills dir, discovered skills, backup count.
Configuration (settings.json, key selfskills)
| Key | Default | Meaning |
|---|---|---|
| enabled | true | Master switch; false disables the tool and injection |
| inject | true | Prepend the standing-rules block to the system prompt each turn |
| skillsDir | ~/.pi/agent/skills | Create target dir (tilde-expanded); also a writable root |
| backupCap | 10 | Backups kept per skill (oldest pruned) |
| patchPackages | true | Patch skills in LOCAL packages from settings packages (monorepo source; git + backups make it safe). npm:/node_modules package skills are always read-only. |
| patchProjectAgents | true | Patch project .agents/skills in trusted projects, within the git boundary (the project dir itself when not git-tracked). User-level ~/.agents/skills stays read-only. |
Settings resolve <cwd>/.pi/settings.json (trusted projects only — mirrors
Pi's own trust gating, so an untrusted repo cannot steer this extension)
→ <agentDir>/settings.json where <agentDir> is $PI_CODING_AGENT_DIR
or ~/.pi/agent; first found wins.
npm-installed package skills and skills from settings skill arrays / --skill
flags may be absent from list (read-only regardless). LOCAL package skills
(monorepo checkouts) are listed and patchable unless patchPackages: false.
Backups
Content-addressed snapshots live under
~/.pi/agent/selfskills/backups/<skill>/<relpath>/<yyyyMMdd-HHmmss.mmm>-<sha256[:10]>.md
where <relpath> mirrors the file inside the skill dir (SKILL.md for the
skill file; v0.1 flat SKILL.md backups remain restorable). Whole-skill
deletions snapshot to <skill>/__deleted__/<stamp>/…. Manual restore is just
a copy:
cp ~/.pi/agent/selfskills/backups/my-skill/SKILL.md/<yyyyMMdd-HHmmss.mmm>-<hash>.md \
~/.pi/agent/skills/my-skill/SKILL.mdInstall
pi install @bacnh85/pi-selfskillsTest
npm ci && npm test # mocha + tsx, tmpdir-isolated