# pi-skill-path-hint

[![npm](https://img.shields.io/npm/v/pi-skill-path-hint)](https://www.npmjs.com/package/pi-skill-path-hint)
[![license](https://img.shields.io/npm/l/pi-skill-path-hint)](LICENSE)

[English](README.md) | [中文](README.zh-CN.md)

**Stop making your agent retype 150-character paths.**

pi installs skill packages under `~/.pi/agent/npm/node_modules/<pkg>/skills/<skill>/scripts/`. The scripts are fine where they are — the problem is that every call your agent makes looks like the left side of this picture:

![Before / After comparison](https://raw.githubusercontent.com/heykb/pi-skill-path-hint/main/assets/before-after.png)

Left: your agent today — copying the full `node_modules` address into every command, burning tokens call after call, and spinning in place the moment a doc and reality disagree. Right: after install — bare filenames, same work, a fraction of the tokens.

## The problem, in three lines

- The skill's scripts are on disk and they work.
- Your agent doesn't know it can call them by bare filename — so it resolves and types the full `node_modules` path every single time.
- Every skill's `SKILL.md` documents its own full path, so "fixing this per-skill" means touching every package.

## How it works

Two channels, one shared source of truth:

**1. Execution — registered at session startup.** On every agent run, the extension reads pi's loaded-skills info (with a `node_modules` scan as fallback), checks each skill for a non-empty `scripts/` directory, and appends it to `process.env.PATH`. Bash child processes inherit the environment, so bare filenames just work. Appending — never prepending — means system commands always win: a skill script that happens to share a name with `git` or `node` can never shadow them.

**2. Knowledge — dropped exactly where it lands.** When the agent reads a `SKILL.md`, the extension appends a notice to that tool result:

```
[skill-path-hint] MANDATORY — the following script directories are on PATH:
- <scripts-dir>
You MUST invoke their scripts by bare filename (e.g. `cdp.mjs list`).
NEVER type node_modules paths for these scripts — ...
```

It's the note your agent reads at the exact moment it loads the skill — and yes, it's worded firmly on purpose. Old skill docs that say "resolve the path relative to SKILL.md" lose to a fresh note sitting in the tool result.

Both channels call the same `registerScriptsDir()` function, so the notice's "is on PATH" claim is true by construction. Announcements are deduplicated per session: one notice per directory per conversation.

## Why you'll keep it

- **Token-efficient.** Bare filenames instead of ~100 characters of `node_modules` path on every invocation; fewer debugging detours when docs and reality diverge.
- **Prompt-cache friendly.** The hint lands in a tool result, never in your system prompt. Your system prompt stays byte-identical across sessions, so provider-side prompt caching keeps hitting.
- **Zero system-prompt modification.** Nothing about your prompt setup changes; the extension only appends contextual notices where they are relevant.
- **Shadow-proof.** PATH entries are appended, never prepended — skill scripts can't hijack system commands.
- **Graceful degradation.** If the notice is ever missed, the agent falls back to long paths — slower, never broken.

## Install

```bash
pi install npm:pi-skill-path-hint
```

That's it — no settings changes. From the next session on, your agent calls `cdp.mjs list` instead of the whole address.

## Notes

- Zero trust-boundary change: registered scripts were always executable via their full path.
- Registration scans pi's loaded skills each run; the `read`-based notice is a per-session refresher, deduplicated per directory.
- Empty or missing `scripts/` directories are skipped.
- Cost: a few lines appended once per skill per session; no system-prompt changes.
- Works with scoped packages (`@scope/pkg`) and any install location ending in `/skills/<skill>/`.

## License

[MIT](LICENSE)
