pi-skill-ignore-bypass
Pi extension that loads skills which pi's skill discovery silently drops because of .gitignore, .ignore, or .fdignore rules
Package details
Install pi-skill-ignore-bypass from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-skill-ignore-bypass- Package
pi-skill-ignore-bypass- Version
0.1.0- Published
- Sep 12, 2026
- Downloads
- 150/mo · 150/wk
- Author
- xyenon
- License
- MIT
- Types
- extension
- Size
- 20.7 KB
- Dependencies
- 0 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-skill-ignore-bypass
A pi extension that makes pi load skills which its
skill discovery silently drops because of .gitignore / .ignore / .fdignore rules.
Install
pi install npm:pi-skill-ignore-bypass
To try it without touching your settings, run pi with the package loaded temporarily:
pi -e npm:pi-skill-ignore-bypass
Then /reload (or restart pi) if you installed it while pi was running. Remove it with
pi remove npm:pi-skill-ignore-bypass.
If you prefer not to use a package, index.ts is a self-contained extension file — drop it
into ~/.pi/agent/extensions/ (or any auto-discovered extension location) and it works the
same way.
The problem
When pi scans a skills directory it reads the ignore files inside that tree and skips any
SKILL.md they match:
// packages/coding-agent/src/core/skills.ts
if (!isFile || ig.ignores(relPath)) continue;
That is intentional (it was added to stop pi from recursing into .venv, __pycache__,
dist, etc. — see #1072), but it has a
nasty side effect: if your skills tree lives in a dotfiles repo that keeps it clean with a
whitelist .gitignore:
*
!.gitignore
!/kitty
!/kitty/**
…then every skill that is not whitelisted silently disappears. No warning, no diagnostic, nothing. Claude Code loading the same tree is unaffected, so the gap is easy to miss for months.
Reported upstream, all closed without a fix:
- #2947 — feat: Allow for gitignored skills
- #5145 — Skills with a
.gitignorefile in their directory are not discovered (maintainer reply: "this works as per design and is documented") - #8748 — Skill discovery honors .gitignore in skills dirs; excluded skills vanish with no diagnostic
There is no upstream toggle to disable this behavior, and docs/skills.md does not mention it.
How it works
pi's loader treats directory and file skill paths differently:
skillPath passed to pi |
Behavior |
|---|---|
| directory | recursive scan, ignore files are applied, matched SKILL.md files are skipped |
.md file |
loadSkillFromFile is called directly — no ignore check at all |
So this extension re-scans the configured skill roots itself, never consulting any ignore
file, and hands pi the resulting SKILL.md files as extra skill paths:
pi.on("resources_discover", () => {
// own no-ignore traversal of the roots
return { skillPaths: ["/path/to/skill/SKILL.md", ...] };
});
Extension-provided paths are merged into pi's skill path list, and pi deduplicates by
realpathSync, so skills that pi already discovered normally are not loaded twice and keep
their original source metadata.
Because it works on file paths, it also handles the case where the ignore rule is
inside the skill directory itself (a * gitignore used to keep generated files out of
version control) — #5145.
Default scan roots
Used when includeDefaults is not false:
Project-level — only when the current project is trusted, walked from cwd up to the git
repo root (or the filesystem root when not inside a repo):
<cwd>/.agents/skills
<cwd>/../.agents/skills
... up to <git-root>/.agents/skills
<home>/.agents/skills is filtered out of this list because the user-level root below already
covers it. pi's own project .agents/skills scanning is trust-gated, and this extension does
not bypass that: untrusted projects never contribute skills.
User-level:
| Directory | mode |
|---|---|
$PI_CODING_AGENT_DIR/skills (default ~/.pi/agent/skills) |
pi |
~/.agents/skills |
agents |
$XDG_CONFIG_HOME/agents/skills (default ~/.config/agents/skills) |
agents |
mode only affects one rule: whether loose *.md files directly inside the root are treated
as skills (pi) or ignored (agents). This mirrors pi's own behavior for its two directory
conventions.
Configuration
Optional file: $PI_CODING_AGENT_DIR/skills-bypass.json (default ~/.pi/agent/skills-bypass.json).
A missing file, or invalid JSON, means all defaults.
{
// Turn the whole extension off without removing it. Read at startup / reload time.
"disabled": false,
// Enable the default roots listed above. Default: true.
// Set to false to use only "roots" below.
"includeDefaults": true,
// Extra roots, APPENDED after the default roots.
// String form is shorthand for { "dir": "...", "mode": "pi" }.
// "~/" is expanded; leading "~user" is not. Missing directories are skipped silently.
"roots": [
"~/work/shared-skills",
{ "dir": "~/another/tree", "mode": "agents" }
],
// Directory names to skip while recursing (exact match, any depth).
// Omitted => the built-in dependency list (see below). Empty array => skip nothing.
"skipDirs": ["node_modules", ".git"],
// Log the forced skill files to stderr on every discovery (startup and /reload).
"verbose": false
}
Every field is optional. The config is read once when the extension is instantiated, so
changes require /reload.
skipDirs
Exact directory-name matching at any depth. Defaults to common dependency directories — deliberately not build/output artifact directories:
.git .hg .svn
node_modules bower_components jspm_packages .pnpm-store .yarn
.venv venv virtualenv site-packages __pypackages__ .tox .nox
vendor .bundle
.cargo
.gradle .m2
deps
Pods
.stack-work
.terraform
dist, build, target, out, _build, obj, bin, DerivedData, __pycache__,
.cache, .next and friends are intentionally absent.
Notes:
- There is no implicit "skip dot-directories" rule.
.gitis in the default list for that reason; if you remove it, pi will walk.gitobject databases. - Conversely, a skill placed inside a hidden directory (e.g.
.hidden/my-skill/SKILL.md) is now found, which pi itself cannot do. - A directory containing
SKILL.mdis treated as a skill root and is not recursed into, somy-skill/scripts/node_modules/is never reached for well-formed skills.skipDirsmainly matters for the non-skill branches of the tree, and for symlinks pointing at repositories.
Caveats
- It re-adds skills you may have deliberately ignored. That is the whole point, but it also means ignore rules can no longer be used to hide a skill from pi.
- It overrides pi's
skillssettings-pathexclusions for anything it discovers. Extension-provided skill paths do not go through pi's settings override logic. Narrowrootsif you need to avoid this. - Skills are matched by
SKILL.mdonly (plus loose*.mdatpi-mode roots with a non-emptydescription). MalformedSKILL.mdfiles still produce pi's normal warnings. - Directory symlinks are followed, and a symlinked directory without a top-level
SKILL.mdis recursed into. Point a root at a monorepo and you are subject to its contents, minusskipDirs. ~expansion only handles a leading~/or~\.- Extensions run with full system access. This one only reads the filesystem and never executes
anything, but review
index.tsbefore installing any extension.
Verifying it works
A model-free way to inspect which skills pi actually loaded is RPC mode plus get_commands:
printf '{"type":"get_commands"}\n' | pi --mode rpc --no-session --offline \
| jq -r 'select(.command=="get_commands") | .data.commands[] | select(.source=="skill") | .name'
With the extension disabled ("disabled": true) the ignored skills are missing; with it
enabled they are present. Set "verbose": true to also see exactly which files were forced:
[skill-ignore-bypass] forced 6 skill file(s): /home/you/.config/agents/skills/agent-browser/SKILL.md, ...
Development
npm install
npm run typecheck
The extension ships as TypeScript source and is loaded by pi's own TypeScript loader, so there
is no build step. @earendil-works/pi-coding-agent is a peerDependency because pi bundles it
at runtime; it is only installed as a dev dependency for type checking.