Example

Give a skill files and a check script it can run

Bundle references and a POSIX shell script beside SKILL.md; the script must fail loudly, and a bundled file reaches context only when read.

The review guard’s checklist is forty items; inlining it in SKILL.md would load all forty every time the skill fires. Bundle it as a file the body names instead. A bundled file is a file on disk — it reaches the context only when the model reads it with its own tool. The bundled script in this example needs a POSIX shell, so on Windows run it under Git Bash.

The layout

review-guard/
├── SKILL.md
├── scripts/
│   └── run-checks.sh
└── references/
    └── checklist.md

SKILL.md names the files by path relative to the skill directory, because Pi tells the model where the skill lives so it can resolve them:

---
name: review-guard
description: Reviews changed code against this repository's conventions and runs its own checks. Use when reviewing a diff.
---

# Review guard

1. Run `scripts/run-checks.sh` and read its output before reviewing anything.
2. Read `references/checklist.md`.

The three directory names are a convention, not an enforced layout. What matters is when each kind loads: a reference is read after the skill decides the task is relevant, a script runs when told to, and an asset is used at the point of output.

The check script

#!/usr/bin/env bash
# scripts/run-checks.sh - run the target repository's own verification.
set -euo pipefail

root="${PI_REVIEW_GUARD_ROOT:-$(git rev-parse --show-toplevel)}"
cd "$root"

echo "== repository: $root =="
echo "== typecheck =="
pnpm typecheck

The script never derives the repository from its own path: dirname "$0" is the skill’s scripts/ directory, and how many parents separate that from the repository depends on where the skill was installed. It asks Git for the top level of the working directory Pi was launched in, which is inherited by the bash tool, not the skill’s. set -euo pipefail is the difference between a script that fails and one that exits zero while skipping everything.

Expected outcome

The backing test runs the script under a POSIX shell (skipped when none is available) with a stand-in pnpm on PATH, and drives a session for the context claims:

  • a project skill at repo/.pi/skills/review-guard/scripts/ runs pnpm in the repository root — three levels up, so a parent count would have picked wrong;
  • a shared or packaged skill outside the repository resolves the same target;
  • PI_REVIEW_GUARD_ROOT overrides discovery; frontmatter naming that variable has no effect, because nothing in Pi writes frontmatter into the environment;
  • a bundled guard.conf beside the script is found relative to the script;
  • the same failing line exits non-zero with set -euo pipefail and zero without it, and without it the script still printed its final line;
  • the SKILL.md path is in the prompt, but a marker in references/checklist.md is absent until the model reads it with its own read tool call.

Mechanism and limitations

Documented: docs/skills.md says to use relative paths from the skill directory, that Pi tells the model where the skill lives, and to keep environment setup inside the skill. Observed: skill-files.test.ts executes the script (POSIX shell required) and inspects the prompt and tool result of a scripted session. Proposed: the size rule of thumb — body for steps, references for detail needed after deciding, inline anything needed on every run.

git rev-parse discovery is a convention, not a boundary: a model told to run a script has a path into your machine, and the working directory is whatever Pi was launched in. Frontmatter does not become environment variables. A bundled file is not magically in context. On Windows this example needs Git Bash; the tests skip without a POSIX shell.

Full source and test .

Understand this example

Copy this prompt into your AI tool. No code runs here.

Apply this example

Copy this prompt into your AI tool. No code runs here.