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-opa-net

v0.1.0

Published

OPA-backed bash command guard for the pi ecosystem — structured decision-output.v1 JSON, fail-open default, Claude Code hook protocol compatible. Agent-agnostic engine + CLI.

Readme

pi-opa-net

npm version CI License: MIT

OPA-backed bash command guard for the Pi ecosystem. Structured --json output (decision-output.v1 schema), fail-open default, exit-code compatible with the Claude Code hook protocol.

An agent-agnostic engine + CLI that evaluates shell commands against an OPA/Rego policy and emits a strict, auditable decision record. Designed as the decision backend for pi extensions, Claude Code hooks, scripts, and any agent that needs a uniform bash-guard contract.

Why

Three limitations of today's asymmetric, agent-specific guard output that this fixes:

| # | Limitation | Fix | |---|------------|-----| | 1 | Asymmetric — allow is silent, deny emits a string | Both allow AND deny emit the full schema | | 2 | No provenance — only a human message | reasons[].rule_id traces decision → rule → source line | | 3 | Agent-specific — tied to one hook protocol | Agent-agnostic wrapper; adapters become thin views |

Status

  • Stable: v0.1.0 — schema v1.0, 37-rule catalog, full TDD coverage
  • Engine: OPA 1.x (lazy-loaded on every dev box)
  • Scope: bash command guarding only (see docs/locked-decisions.yaml LD3)
  • Pi extension: the thin tool_call adapter lives in a separate future repo (pi-opa-net-ext, per OT5) — this package is the engine + library

Installation

Prerequisites

OPA 1.x on PATH (recommended via mise):

mise install opa@latest
mise use -g opa@latest

Install

# as a library (pi extension / script consumer)
npm install pi-opa-net
# or
bun add pi-opa-net

# run the CLI directly via bun
bunx pi-opa-net eval "git stash pop"

Usage

CLI

# claude-code mode (default): suppress stdout on allow, JSON on deny
pi-opa-net eval "git stash pop"             # exit 2 + JSON on stdout
pi-opa-net eval "git stash list"            # exit 0, empty stdout

# --json: always emit the full decision-output.v1 schema
pi-opa-net eval "git stash pop" --json

# stdin
echo "docker stop foo" | pi-opa-net eval

Exit codes: 0 = allow, 2 = deny (Claude Code hook protocol compatible).

Programmatic API

import { configFromEnv, CommandParserCoordinator, OpaCliEngine, DecisionBuilder, OutputFormatter, RULES, RuleRegistry } from 'pi-opa-net';

const config = configFromEnv('/path/to/safety.rego');
const parser = new CommandParserCoordinator();
const engine = new OpaCliEngine(config);
const builder = new DecisionBuilder({
  config,
  registry: new RuleRegistry(RULES),
  digest: engine.rulebookDigest(),
});

const parsed = parser.parse('git stash pop');
const engineDecision = await engine.evaluate(parsed);
const output = builder.build(parsed, engineDecision);

console.log(output.decision);  // 'deny'
console.log(output.reasons[0].rule_id);  // 'block-git-stash-mutations'

Output schema

See schemas/decision-output.v1.json — JSON Schema draft 2020-12, strict (additionalProperties: false throughout). Every emitted record is validated against it before leaving the process.

{
  "schema_version": "1.0",
  "decision": "deny",            // allow | deny
  "action": "block",             // allow | block | prompt_user(v2) | log_only(v2)
  "source": "opa",               // opa | fail-open | fail-closed | cached
  "reasons": [                   // every fired deny rule → one entry
    { "rule_id": "block-git-stash-mutations",
      "message": "Do not mutate stashes in shared work...",
      "family": "git", "severity": "block" }
  ],
  "input": { "raw": "git stash pop", "program": "git",
             "subcommand": "stash", "args": ["pop"],
             "parse_confidence": "full" },   // full | partial | regex-only | failed
  "summary": "BLOCKED: git stash pop (rule: block-git-stash-mutations)",
  "suggestions": ["git stash list", "git stash show"],
  "metadata": { "engine": "opa", "opa_version": "1.18.1",
                "rulebook_digest": "dee3746bf7b5", "policy_path": "...",
                "hostname": "box", "session_id": "" },
  "evaluated_at": "2026-07-01T14:23:45.123Z",
  "decision_id": "7f3a9c2e-1b4d-4e8f-9a2c-5d6e7f8a9b01",
  "duration_ms": 4.2
}

Architecture

Two halves (per the design findings):

| Half | Responsibility | Module | |------|----------------|--------| | Parse | raw "git stash list"{program, subcommand, args, parse_confidence} | src/parser/ | | Decide | structured input → allow/deny + reasons | policy/safety.rego + src/engine/ |

src/
├── parser/     CommandParserCoordinator (hybrid: ShellQuote AST primary, regex fallback)
├── engine/     OpaCliEngine (subprocess `opa eval` + fail-mode)
├── rules/      RuleRegistry + catalog (message → rule_id + family provenance)
├── output/     DecisionBuilder (schema assembly) + OutputFormatter (stdout/exit-code)
├── config/     EngineConfig (fail-mode, OPA binary discovery)
├── cli/        run.ts (wires the pipeline)
└── util/       sha256Prefix (rulebook drift detection)

Design principles

  • OOPDecisionEngine and CommandParser interfaces; fakes injectable for tests.
  • DRYRuleRegistry is the single source of truth for rule provenance; the catalog mirrors policy/safety.rego message-for-message (a parity test fails on drift).
  • Observable — the source field makes fail-mode (open/closed) auditable per-decision; parse_confidence surfaces parser fidelity.

Fail-mode

When OPA is unreachable (cold-start, binary missing, timeout):

| Mode | Behavior | source field | |------|----------|----------------| | open (default) | allow the command through | fail-open | | closed | block the command | fail-closed |

PI_OPA_FAIL_MODE=closed pi-opa-net eval "git stash pop"

The default open matches the pi-safety-net fork's "never brick the shell" guarantee.

Configuration (env)

| Var | Default | Purpose | |-----|---------|---------| | PI_OPA_BINARY | auto (PATH → mise) | OPA binary path | | PI_OPA_FAIL_MODE | open | fail-mode | | PI_OPA_TIMEOUT_MS | 250 | OPA eval timeout | | PI_OPA_HOSTNAME | os.hostname() | metadata.hostname | | PI_OPA_SESSION_ID | "" | metadata.session_id |

Develop

bun install
bun test                 # all tests (106)
bun test --coverage      # coverage (line > 98%)
bun run typecheck        # tsc --noEmit
bun run lint             # biome
bun run smoke            # one-shot CLI check

E2E tests run the live CLI against real OPA + the real policy, covering ≥40% of the 37-rule catalog.

Decisions & open threads

Project health

Related

  • pi-safety-net — the fail-open fork of cc-safety-net (Path A: non-pi agents). pi-opa-net is Path B (OPA-backed, structured output).
  • cc-safety-net — upstream Claude Code safety net.

License

MIT © buihongduc132