pi-skill-ignore-bypass

Pi extension that loads skills which pi's skill discovery silently drops because of .gitignore, .ignore, or .fdignore rules

Packages

Package details

extension

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

npm version license pi-package

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:

  • #2947feat: Allow for gitignored skills
  • #5145Skills with a .gitignore file in their directory are not discovered (maintainer reply: "this works as per design and is documented")
  • #8748Skill 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. .git is in the default list for that reason; if you remove it, pi will walk .git object 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.md is treated as a skill root and is not recursed into, so my-skill/scripts/node_modules/ is never reached for well-formed skills. skipDirs mainly 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 skills settings -path exclusions for anything it discovers. Extension-provided skill paths do not go through pi's settings override logic. Narrow roots if you need to avoid this.
  • Skills are matched by SKILL.md only (plus loose *.md at pi-mode roots with a non-empty description). Malformed SKILL.md files still produce pi's normal warnings.
  • Directory symlinks are followed, and a symlinked directory without a top-level SKILL.md is recursed into. Point a root at a monorepo and you are subject to its contents, minus skipDirs.
  • ~ 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.ts before 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.

License

MIT