npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pi-better-rules

v0.3.0

Published

Pi extension that surfaces global and project rules per prompt (spec .scratch/rules-extension/spec.md §5; loader manifest: package.json ‘pi.extensions’ -> ./src/index.ts per docs/extensions.md + docs/packages.md).

Readme

pi-better-rules

Pi extension that loads persistent rule memory from markdown files into every prompt — global conventions plus project conventions, with always-on rules and path-scoped activation.

Rule memory (pi-better-rules)

What it does. On session_start the extension scans two rule trees, caches the result in memory, appends unscoped full content to the systemPrompt on every before_agent_start, and appends newly activated scoped rules to the triggering tool_result content same-turn (cumulative inject-once). After loading it reports pi-rules: N rule(s) — U unscoped, S scoped at info level, followed by one detail line per rule and the trigger reason (full scan, checksum refresh, compaction retention); the scan summary also persists as a pi-rules.scan timeline entry, and /rules reprints load state on demand. Unscoped rules live in the system prompt; scoped rules ride tool results — never as user-role text.

Two rule locations. Global rules live under ~/.pi/agent/rules; project rules under <project>/.pi/rules. Both trees are scanned recursively for **/*.md, including subdirectories. Global loads first, project second, concatenated — on conflict project wins: an identical relative path in both trees is a shadow (the project copy replaces the global copy, no merge) and a load-time warning names the shadowed file. Files larger than 4 MiB are hard-skipped.

Scope model. paths: is optional scoping with ** / * / ? / {a,b} / [...] / backslash-escape glob syntax (an invalid pattern matches nothing while siblings keep working). Absent paths: means always-on; present paths: means conditional:

| Scope | Where it renders | When | | --- | --- | --- | | Unscoped (paths: absent) | Full content appended to the system prompt | Every prompt | | Scoped (paths: present) | Full content appended to the triggering tool result (## Rules (scoped — matched for <file>)) | Same-turn, once per rule (inject-once) |

Keep the always-on (unscoped) set minimal — invariants only. Domain rules belong in paths:-scoped rules. Every paths:-scoped rule is compaction-evictable: persistent invariants belong in unscoped rules. Each touched file matches against two bases — its repo-relative path and its bare filename — so bare paths: entries (e.g. pyproject.toml) fire for nested files. Paths come from the tool_result event (read/edit input.path plus details.filePath, write filePath/path), relativized against the session cwd, so absolute tool paths match too. Every injection warns +N scoped rule(s) matched for <file>, matched pattern: <p> with one bare - <rel> bullet per rule. bash carries no path, and error results never inject — documented limitations.

Freshness: snapshot, not live re-read. The filesystem scan happens once per session and lives in module state; the per-prompt handler is cheap string concat. Edits to rule files mid-session do not take effect until a refresh:

  • /reload wipes extension memory, so checksums persist on disk as pi-better-rules-checksums.json — global copy under ~/.pi/agent/cache/, project copy under .pi/.cache/.
  • On session_start with reason === "reload" the extension verifies checksums (list → stat pre-filter → checksum candidates): changed files reload, deleted files drop, and it reports refreshed / added / removed with one ~/+/- line per changed file plus the full rule list — unchanged rules keep byte-identical text. When nothing changed it reports unchanged (checksums verified, no rescan) plus the rule list and skips the rescan entirely. Other reasons (startup | new | resume | fork) always rescan with a full rule list. A session_compact handler notifies retention (cache untouched, no rescan).
  • A corrupt checksum cache is treated as everything-changed (rebuild) with a warning. Rule-load warnings (over-budget globs, corrupt cache, shadowed files) surface via notify(message, "warning"). Scoped injections name the matched file and the activating file.

[!tip] Writing rules? See the rule-authoring guide — filename style, frontmatter examples, the shared-rules-via-symlink pattern, and version-control etiquette.