@bstakes/pi-references
Find and open file and web references mentioned in your pi session.
Package details
Install @bstakes/pi-references from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@bstakes/pi-references- Package
@bstakes/pi-references- Version
0.1.1- Published
- Oct 21, 2026
- Downloads
- 474/mo · 6/wk
- Author
- bstakes
- License
- MIT
- Types
- extension
- Size
- 51.7 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./src/extension.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi references
Fuzzy-find files and web links the assistant references in your pi session. Plans, playbooks, images, source code, and /tmp outputs stay where they are. This extension keeps references, not copies.
Built-in cmux support needs no configuration. Inside a cmux workspace, Enter opens files with cmux open. In other terminals, it uses your operating system's default app. You can also configure custom openers, including terminal editors in cmux splits.
Install
Requires pi 1.3.0 or later and Node.js 22.19 or later.
Install from npm:
pi install npm:@bstakes/pi-references
This adds the package to your personal pi settings for future launches. Resume an existing session to browse its earlier references too.
To try it for one launch without changing settings:
pi -e npm:@bstakes/pi-references
You can also install from GitHub with pi install git:github.com/bstakes/pi-references.
From a local checkout, use pi -e ./src/extension.ts to try it, or pi install /absolute/path/to/pi-references to keep it installed.
Use it
Run /refs, or /refs playbook to start with a search. The References picker filters and ranks matches as you type. Ordinary queries search project-relative paths, external filenames, anchors, web URLs, and Markdown link titles, without matching the shared project root or temporary-directory prefixes. Include a slash in the query to search full file paths. Recent mentions appear first when the query is empty.
- Type to filter, then use Up/Down and Enter to open a file or web link.
- Click a hyperlink using your terminal's usual modifier, such as Ctrl+click or Cmd+click.
- Press Ctrl+Y to paste the selected reference into the pi prompt, quoted as a JSON string. Anchored file references use a
file://URI to retain the heading; source locations retain their line and column. Web links retain their query strings and fragments. This does not modify the system clipboard. - Press Escape to close the list.
A dim References N · /refs status appears when the session has matching references. It updates after each agent run. Set "showStatus": false in your personal configuration to hide it without disabling /refs. N counts distinct targets, so two anchors in one file count separately. Existing custom pi selection keybindings work in the picker.
What gets indexed
The default is files referenced in the assistant's visible text, not every file written during a run. It recognizes local Markdown links, reference-style links, inline-code paths, plain paths, and file:// links. References can point outside the project, including /tmp. Heading fragments such as README.md#optional-personal-configuration remain attached to the reference while discovery checks the underlying file. Encode a literal # in a filename as %23. Source locations such as src/main.ts:42:3 and src/main.ts#L42-L50 retain their starting line and column.
HTTP and HTTPS links are also indexed by default, including Markdown links, reference-style links, autolinks, inline-code URLs, and plain URLs. They appear alongside files with a web marker. Search by link title, hostname, or any part of the URL. Query strings and fragments distinguish targets. Links are never fetched or checked for reachability. Other URL schemes are not indexed, except local file:// links as described above.
Relative paths resolve against the session working directory. References with spaces work as Markdown destinations, encoded URLs, or inline-code paths. Different anchors and source locations have separate picker entries. Repeated mentions of the same target merge and retain the latest available reply excerpt and link title. The selected entry shows that excerpt below its full path and anchor. The picker never reads file contents, copies attachments, or rewrites the assistant's reply.
The index is derived from the active session branch. Resume, reload, fork, and tree navigation use that branch's transcript. Compaction does not require a second index file. Thinking blocks and user prompts are not indexed. Missing or unreadable files are hidden by default, and file paths are checked again whenever you open the list.
How opening works
Enter and hyperlink clicks use different opening mechanisms.
- Enter uses the extension's opener. For files, it detects cmux as described below. Outside cmux, it uses the OS file association through macOS
open, Linuxxdg-open, or Windows PowerShell. Web links always use the OS default browser, bypassing cmux and custom file opener rules. - Hyperlink clicks follow standard OSC 8 links to
file://,http://, orhttps://URLs. Your terminal and operating system control what happens. The extension does not intercept Ctrl+click or install a URL handler. Opener settings affect Enter for files, not web links or hyperlink clicks.
For files, the default Enter opener passes references with fragments as anchored file URIs and other files as absolute paths. The extension checks that the underlying file is readable before launching an opener. The viewer must honor URI fragments to scroll to a heading. The extension does not render Markdown or inject scrolling scripts.
Built-in cmux support
When CMUX_WORKSPACE_ID is present, the default opener uses cmux open. The cmux executable must be on pi's PATH. If that command fails, the extension falls back to the OS opener with the same target. Set defaultOpener to "system" to skip cmux detection.
This integration handles Enter without custom rules or scripts. Hyperlink clicks still follow cmux's own link handling and do not guarantee a new pane. To launch a specific editor or control split placement, see Custom cmux openers.
Heading navigation has a known limitation in cmux 0.65.2, commit 9d01f956c. cmux open converts file URIs to bare paths and discards their fragments before opening Markdown previews. Its native Markdown CLI/socket API has no heading-target parameter. cmux browser open retains the fragment but displays raw Markdown, so it is not a heading-navigation workaround. See cmux's file-URL conversion.
Optional personal configuration
No settings file is needed. To customize behavior, create ~/.pi/agent/references.json. If you use a custom pi agent directory, put it there instead. The extension reads this file on session start and each /refs invocation. It does not load project-local executable settings.
For example, open JavaScript and TypeScript in VS Code while leaving other files on the built-in automatic opener:
{
"openers": [
{ "extensions": [".js", ".jsx", ".ts", ".tsx"], "command": ["code", "{path}"] }
]
}
Filtering and sources
To keep the picker file-only, set includeWebLinks to false in ~/.pi/agent/references.json:
{
"includeWebLinks": false
}
Web links are enabled by default. The existing source settings apply to both files and links. File extension filters and showMissing apply only to files.
To limit file entries to documents and images:
{
"includeExtensions": [".md", ".pdf", ".html", ".svg", ".png", ".jpg"]
}
To include paths mentioned in tool results and files written without an assistant reference:
{
"sources": {
"assistant": true,
"toolOutput": true,
"writes": true
},
"excludeExtensions": [".lock", ".map"],
"showMissing": false
}
Settings reference
| Setting | Default | Behavior |
|---|---|---|
sources.assistant |
true |
File paths and web links in the assistant's text blocks. |
sources.toolOutput |
false |
File paths and web links in tool-result text, including failed results. Can be noisy. |
sources.writes |
false |
Successful direct calls to write, edit, readSeek_write_file, and readSeek_edit_text. Includes modifications to existing files. |
includeWebLinks |
true |
Include HTTP and HTTPS links from enabled text sources. Links open in the default browser without file checks or extension filtering. |
includeExtensions |
Unset | Allow all suffixes. An explicit array limits them; [] includes none. |
excludeExtensions |
[] |
Exclude matching suffixes, even if included above. |
showMissing |
false |
Show unresolved or unreadable references with a warning. Opening still requires a readable regular file. |
showStatus |
true |
Show the dim reference-count status in Pi's footer. Set to false to hide it; /refs still works. |
defaultOpener |
"auto" |
"auto" detects cmux, otherwise uses the OS opener. "system" always uses the OS opener. A command array sets a custom default. |
openers |
[] |
Rules with extensions and command arrays. Longest suffix wins, case-insensitively. "*" is the fallback. |
Custom opener commands
Each opener rule shares one command across its extensions. Matching uses the filename, not parent directories. A matching suffix wins over "*", then defaultOpener handles unmatched files. Rule order does not change priority. Duplicate suffixes, including case variants or multiple wildcards, are configuration errors. Extension arrays must be nonempty. There are no built-in file groups or content-based detection.
Commands are executable-and-argument arrays, not shell strings. If a command contains no placeholders, the extension appends the absolute file path.
Use {uri} to pass a heading fragment to a viewer, or {fragment} if your launcher handles headings itself. Commands using only {path} open without an anchor. Use {line} and {column} for source locations.
| Placeholder | Value |
|---|---|
{path} |
Absolute file path without a location suffix. |
{uri} |
File URI including the selected fragment, if present. Colon-style line locations do not invent a URI fragment. |
{fragment} |
Original fragment without #, retaining percent escapes; empty when absent. |
{line} |
Starting line number; empty when absent. |
{column} |
Starting column number; empty when absent, even if a line is present. |
An explicit :1 produces "1"; a bare file produces "". Empty arguments are preserved, not removed. Launchers should check {line} first for a source location, otherwise {fragment} for a heading, otherwise open the plain file. A source fragment such as #L42 supplies both fragment "L42" and line "42". Heading names are not converted to line numbers. Apply viewer-specific defaults in your launcher rather than in the configuration template.
Use a launcher that opens a separate viewer and exits. Child processes have no interactive terminal input or output; a terminal editor such as vim is not suitable as a direct opener. A custom opener can execute code, so only add commands you trust. The extension does not run commands automatically when it sees a reference.
To use a browser, configure its launcher, for example { "extensions": [".html"], "command": ["open", "-a", "Firefox", "{uri}"] } as an opener rule on macOS. There is no HTTP server. Files that depend on HTTP, module loading, or a web app runtime may need your own development server instead.
Custom cmux openers
The built-in cmux integration uses cmux open. The following setup is optional and replaces that behavior for selected file types with a Neovim split and an explicit Markdown viewer command.
Opening source files in a cmux split
Use the bundled scripts/cmux-nvim wrapper for terminal editors. It opens a new right split for each reference, starts Neovim directly without an interactive shell or an echoed launch command, and focuses the editor. Quitting Neovim successfully closes that split; a failed editor stays visible for diagnostics.
Install it from this checkout on macOS:
sudo install -m 755 scripts/cmux-nvim /usr/local/bin/cmux-nvim
cmux, nvim, and node must be on pi's PATH. The wrapper uses cmux's surface.split socket API with initial_command, verified on cmux 0.65.2. In that version, new-split --command instead supplies terminal input to an interactive shell, which shows the command before the editor launches and waits for shell startup. The wrapper deliberately does not use that route or fall back to it.
It jumps only when a line is present, using column 1 if none is supplied. Named headings open at the editor's normal position. Arguments are quoted with Bash's printf '%q', encoded as JSON using Node.js, and executed with noninteractive Bash without loading its profile or rc files.
Configure ~/.pi/agent/references.json:
{
"defaultOpener": "auto",
"openers": [
{
"extensions": [".ts", ".rs", ".cs", ".py"],
"command": ["/usr/local/bin/cmux-nvim", "{path}", "{line}", "{column}"]
},
{
"extensions": [".md"],
"command": ["cmux", "markdown", "--focus", "true", "{path}"]
}
]
}
Only the listed source extensions use Neovim. Markdown opens directly in cmux's formatted viewer; this command does not navigate to headings or source locations. Other files retain automatic opening. To use Neovim for every unmatched file instead, set defaultOpener to ["/usr/local/bin/cmux-nvim", "{path}", "{line}", "{column}"].
Limits
Discovery is text-based, not a complete Markdown parser. Unusual escaping, deeply nested link destinations, and paths embedded in arbitrary code or structured tool data may be missed. Remote file shares and URL schemes other than HTTP, HTTPS, and local file:// links are not indexed. This extension does not monitor the filesystem, infer shell redirection targets, discover unreferenced build outputs, or preserve deleted temporary files. Optional write tracking does not reconstruct tools nested inside another tool.
Under SSH, file paths refer to the machine running pi. The local terminal may not be able to open those paths. Use your terminal's remote-file handling or configure an appropriate opener.
The interactive picker requires pi's terminal UI. It does not open dialogs or launch files in print, JSON, or RPC modes.
Development
npm install --ignore-scripts
npm test
npm run typecheck
npm pack --dry-run
Tests cover reference discovery, active-branch reconstruction, missing files, filters, fuzzy searching, terminal links, narrow rendering, custom selection bindings, opener selection, and safe argument passing. Tests do not launch desktop applications.
For a manual check, load the extension, ask pi to reference an existing Markdown file and a /tmp file, then run /refs. Check both Enter and your terminal's link-click gesture. Repeat after resuming the session. Native cmux click behavior and desktop application opening require this manual check.