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

@iota-policy/pi-extension

v0.2.0

Published

iota embedded policy engine as a pi coding-agent extension: hash-pinned bless, agents.yaml enforcement for read/write/edit/bash, JSONL decision log

Readme

@iota-policy/pi-extension

A permission system for pi, in one YAML file. pi ships no permission layer by design — your agent runs with your full user account. This extension is that layer: declare what the agent may read, write, run, and it enforces the verdict before anything executes, in-process, ~0.2 ms per decision, zero extra tokens. Part of the iota project — a portable policy format for coding agents.

  • agents.yaml lives in your repo like .gitignore
  • Unknown commands prompt you; in CI they auto-deny — no override exists
  • Repo policies need your hash-pinned approval (bless); edits show you a diff
  • The policy file itself is write-protected from the agent — self-escalation attempts get blocked and logged (we've watched it happen)
  • Every decision goes to .iota/decisions.jsonl for jq debugging

Install

pi install npm:@iota-policy/pi-extension    # global; add -l for project-only

This is the only package you install into pi. Its dependency @iota-policy/core is the policy engine (parser + evaluator) and comes along automatically as a normal npm dependency — it is a library, not a pi extension, and installing it into pi directly will just show as invalid.

Then create a policy (or let your repo's committed one prompt for bless). The simplest path is in-session — launch pi and run the /iota init command:

pi
# inside pi:
/iota init        # scaffolds a starter agents.yaml, then prompts you to bless it

If there's no policy, iota also nudges you toward /iota init on session start. To scaffold from the shell instead (e.g. in CI), use npx -p @iota-policy/pi-extension iota-pi init.

npm install -D @iota-policy/pi-extension
npx iota-pi install     # writes .pi/extensions/iota.ts, gitignores .iota/

Bless: repo policies need your approval

A repo-committed policy arrives with someone else's code, so it governs nothing until you approve it. On first use, iota shows what the policy grants — with every weak best_effort pattern called out — pinned to the file's sha256:

iota: bless repo policy?
Repo policy /path/to/agents.yaml
sha256 3f9c2ab41d…

• fs.read: ** — deny: **/.env*, .git/config
• fs.write: src/**, test/**, *.md
• exec actions: test
• [!] BEST-EFFORT pattern: "git *" → allow (weak matching, evadable — review carefully)
• exec default: ask
• net: registry.npmjs.org (default: deny)

Apply this policy? Any change to the file will require re-approval.

Decisions live in ~/.iota/bless.json (outside every workspace) and are sticky in both directions. Any change to the file invalidates an approval and re-prompts with a line diff against the version you approved — an agent that rewrites its own policy triggers exactly the review it was trying to avoid, and you see precisely what it changed. A rejection also persists until the file changes: a policy you refused stays refused across sessions instead of nagging you every start.

Continuity: while a changed file awaits your decision — or after you reject its new revision — the last version you approved keeps governing. A teammate's edit arriving via git pull can't downgrade you from "governed" to "ungoverned"; you stay protected by the policy you approved until you approve the new one. Only a policy you never approved is treated as absent: it cannot govern you, and it cannot pretend to. In headless runs (pi -p, JSON mode) approvals can't happen — the last approved version (or nothing, on first use) governs; bless interactively once first. Your user-level baseline (~/.config/iota/agents.yaml) needs no bless and can never be widened by a repo policy (tighten-only merging).

Writing a policy

# agents.yaml
version: 0.1

fs:
  read:
    allow: ["**"]                          # globs: * segment, ** any depth, {a,b}
    deny: ["**/.env*", "**/*.pem"]         # deny ALWAYS wins; dotfiles are matched
  write:
    allow: ["src/**", "test/**", "*.md"]   # nothing else is writable
  delete: ask                              # or a full allow/deny mapping

exec:
  actions:                                 # exact program + frozen flags; can't be
    test: "npx vitest run <paths?>"        # pattern-evaded (pipes/$()/sh -c fall
    deps: "npm install <pkg?>"             # through to default)
  patterns:                                # escape hatch — must confess weakness:
    - match: "git *"
      verdict: allow
      best_effort: true                    # surfaced at bless time + in every log line
  default: ask                             # unmapped commands prompt; headless = deny

net:
  allow: ["registry.npmjs.org", "*.github.com"]   # wildcard ≠ apex
  default: deny

Typed slots validate arguments by type, not regex: <paths> accepts only workspace-relative paths (no flags, no absolute, no ..), <pkg> npm-name-shaped tokens, <word> single safe tokens; ? variants may be empty. So npx vitest run src/a.test.ts matches test, but npx vitest run --reporter=evil falls to default.

Built-in guarantees, not configurable: paths outside the workspace are always denied; writes to agents.yaml and harness configs are always denied (self-protection); a repo policy can only narrow your user baseline (~/.config/iota/agents.yaml), never widen it.

Two more ready-made policies (docs-only, read-only investigator) in the project README; full grammar in the spec.

Verdict behavior

| Verdict | Interactive (TUI/RPC) | Non-interactive (-p, JSON) | |---|---|---| | allow | passes through | passes through | | deny | blocked with reason | blocked with reason | | ask | confirm prompt | denied, logged (SPEC §3.1, no override) |

No agents.yaml → not governed, logged as ungoverned (SPEC §3.2). A present-but-invalid agents.yaml fails closed: every governed tool call blocks until it parses. Denial reasons instruct the model not to retry, route around, or lobby you with policy-loosening suggestions.

Decision log

Every evaluation appends one JSON line to .iota/decisions.jsonl (configure via createIotaExtension({ logPath }), disable with null):

{"ts":"2026-07-13T06:22:04.648Z","v":"0.2.0","toolName":"write","toolCallId":"call_7b","operation":{"kind":"fs.write","path":"agents.yaml"},"reason":"'agents.yaml' is a protected policy/harness path…","bestEffort":false,"resolution":"blocked","durationMs":0.086,"verdict":"deny","rule":"baseline.self_protection"}

resolution: allowed | blocked | asked_user_allowed | asked_user_denied | denied_non_interactive | ungoverned.

jq -r 'select(.resolution=="blocked") | .reason' .iota/decisions.jsonl   # what got stopped and why
jq -r 'select(.bestEffort) | .operation.command' .iota/decisions.jsonl   # traffic riding the escape hatch

Honesty notes

  • Intent, not execution. This governs tool calls; a child process spawned by an allowed bash command is not constrained here. Pair with an OS sandbox as the enforcement backstop — the iota compiler will emit one from the same agents.yaml (roadmap).
  • net is not enforceable at this layer in pi: there is no fetch tool to intercept; egress happens inside bash and falls under exec policy.
  • Custom/unknown pi tools are outside the v0.1 vocabulary and pass through, logged as ungoverned.
  • Overhead measured in practice: ~0.1–0.5 ms per decision, in-process, zero extra tokens.