# 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)

**别再让 agent 反复输入 150 字符的长路径了。**

pi 把技能包装在 `~/.pi/agent/npm/node_modules/<pkg>/skills/<skill>/scripts/` 这样的深层路径下。脚本本身没问题——问题是 agent 的每次调用都长成下面这张图的左边：

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

左：你 agent 的现状——每条命令都抄一遍完整 `node_modules` 地址，token 逐次燃烧，一旦文档与现实不符就在原地打转。右：安装后——裸文件名直调，同样的活，零头的开销。

## 问题，三行说完

- 脚本就在磁盘上，本来就能跑。
- agent 不知道可以按文件名裸调——于是每次都解析并输入完整 `node_modules` 路径。
- 每个 skill 的 `SKILL.md` 都各自写死了完整路径，"逐个修"等于要动所有包。

## 工作原理

两个通道，一个共同事实源：

**1. 执行通道——会话启动时注册。** 每次 agent 运行前，扩展读取 pi 的已加载技能信息（兜底扫描 `node_modules`），检查每个 skill 的 `scripts/` 目录非空后，**追加**到 `process.env.PATH`。bash 子进程自动继承环境，裸文件名直接可用。只追加、永不前置——系统命令永远优先，即使某个 skill 脚本恰好叫 `git` 或 `node` 也不可能遮蔽它们。

**2. 知识通道——落在最相关的位置。** 当 agent 读取某个 `SKILL.md` 时，扩展在那次工具结果末尾追加：

```
[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 — ...
```

这是 agent 恰好在加载 skill 时读到的提示——语气故意强硬。老 skill 文档里"相对 SKILL.md 解析路径"的说法，输给工具结果里这张新鲜字条。

两个通道调用同一个 `registerScriptsDir()` 函数，所以提示里 "is on PATH" 的宣称**由构造保证为真**。每个目录每个会话只提示一次（会话级去重）。

## 为什么你会留下它

- **节省 token。** 每次调用用裸文件名，不再重复近百字符的 `node_modules` 路径；文档与现实不一致时也少了绕弯调试。
- **缓存友好。** 提示落在工具结果里，**不碰 system prompt**。你的 system prompt 跨会话字节级不变，服务端 prompt 缓存命中率不受影响。
- **零 system prompt 侵入。** 提示配置一切照旧，扩展只在相关位置追加上下文。
- **机制性防遮蔽。** PATH 只追加不前置，skill 脚本不可能劫持系统命令。
- **优雅降级。** 万一某次提示没送达，agent 退回长路径——只是慢一点，永远不会坏。

## 安装

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

就这一条，**无需改任何设置**。下一个会话开始，你的 agent 就会敲 `cdp.mjs list` 而不是完整地址。

## 说明

- 零信任边界变化：这些脚本本来就能被 agent 全路径执行。
- 注册在每次运行时扫描 pi 的已加载技能；`read` 触发的提示是会话内的补充提醒，按目录去重。
- 空的或缺失的 `scripts/` 目录会被跳过。
- 代价：每个 skill 每个会话追加几行；不改 system prompt。
- 支持 scoped 包（`@scope/pkg`）和任何以 `/skills/<skill>/` 结尾的安装位置。

## 许可

[MIT](LICENSE)
