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

@orpc-agent/cli

v5.0.0

Published

Capability inventory and CI drift gate for oRPC Agent applications. Independent community project, not affiliated with or endorsed by the oRPC maintainers.

Readme

@orpc-agent/cli

Capability inventory and CI drift gate for oRPC Agent applications.

Answers two questions about a repository: what can an agent reach from here, and did that change in this pull request.

pnpm add -D @orpc-agent/cli
npx orpc-agent init

init is interactive: it finds the module that assembles your application, loads it through the same child-process loader every other command uses, shows what it found — capabilities, exposure, and whether runtime-level policies are in scope — and writes the orpcAgent config, the baseline snapshot, and the CI script once you confirm. It writes nothing before the summary.

Found in src/app.ts

  capabilities        2
  exposed             2
  approval-gated      0  declared in meta.approval
  runtime policies    gate-model-writes

Write this to package.json? (Y/n)

Then:

npx orpc-agent inspect
10 capabilities · 10 exposed
risk 6 low · 3 medium · 1 high · declared gates: 1 approval · 4 policy-scoped capabilities · 1 runtime policy

CAPABILITY                     EFFECT    RISK    EXPOSE                    APPROVAL  POLICIES
cases.escalate                 write        medium  aiSdk, direct, test       —         —
customers.get                  read         high    aiSdk, direct, mcp, test  —         —
messages.send                  external     high    aiSdk, direct, test       required  —
orders.refund                  write        high    aiSdk, direct, test       —         runtime:gate-model-writes, refund-limit

Runtime policy scope — evaluated before capability policies when scope matches
POLICY             PHASES      SCOPE                                     MATCHES
gate-model-writes  invocation  effect(destructive|write) · surface(aiSdk)  3

Point --entry at a defineGovernance value — it names the registry and the runtime-level policies, and it is safe at module scope, so it does not matter that the runtimes serving traffic are built inside a factory the CLI will not call:

export const governance = defineGovernance({
  registry: capabilities,
  policies: [gateModelWrites],
});

const runtime = createAgentRuntime({ governance, approvals: { coordinator } });

An AgentRuntime works too — it carries the governance it was built from. A bare registry also works, and names no policies at all; when that is what the entry resolves, the output says so in place of the count:

10 capabilities · 10 exposed
risk 6 low · 3 medium · 1 high · declared gates: 1 approval · 1 policy-scoped capability · runtime policies not observed

The gate

Commit the snapshot, then let CI fail on drift:

npx orpc-agent snapshot        # writes capabilities.snapshot.json
npx orpc-agent check           # exit 1 if the app no longer matches it

The snapshot is deterministic — no timestamps, no tool version, no absolute paths — so a clean run is byte-identical and any diff is a real change. When one shows up, check sorts it by what it means:

Capability drift — 3 changes, 2 widening

WIDENING — the agent gained reach, or a control weakened
  orders.refund  expose    now exposed on mcp
  billing.charge approval  approval no longer required

NEUTRAL — contract changes worth reading
  orders.refund  description  description changed — the model reads this

Two of those classifications are deliberately counter-intuitive:

  • sideEffect changes count as widening in both directions. Declaring less than before (write → read) silently stops every policy keyed on sideEffect from matching. That weakens governance exactly like a new exposure does.
  • idempotent: false → true is widening. It is the flag that lets the runtime retry a write.

Also widening: a lowered risk, a removed policy, removed redaction, a new capability that arrives already exposed, and a procedure that gains meta.agent.

Removing a runtime-level policy is widening too, and it is the reason the snapshot records them at all. Deleting one entry from defineGovernance({ policies: [...] }) can strip a conditional approval gate from every capability at once while leaving every per-capability field byte-identical — the largest possible change to what a model can reach, in one line, with nothing else to see:

WIDENING — the agent gained reach, or a control weakened
  (runtime)  runtime.policies  runtime policy removed: gate-model-writes — any approval,
                               denial or hiding it added within its declared scope is gone

Losing sight of them is widening as well: if a snapshot recorded runtime policies and a later run does not observe any (because --entry was repointed at a bare registry), check fails rather than quietly reverting to a weaker check.

Commands

| | | |---|---| | orpc-agent init | interactive setup: entry, export, baseline, CI script | | orpc-agent inspect | print the inventory (--json for the raw snapshot) | | orpc-agent snapshot | write the snapshot file — also how you update it | | orpc-agent check | compare the app against the snapshot file |

Exit codes are part of the contract: 0 clean · 1 drift · 2 could not run. CI has to tell "the inventory changed" apart from "the tool never loaded the app", because the second one passing silently is how a gate rots.

Useful flags: --verbosity min|normal|detail (min stops at the headline; detail adds descriptions and declared metadata per row, and makes check print the inventory it gated; --detail is the shorthand), --fail-on widening (let narrowing changes through), --format github (annotations) or --format md (PR comment), --export <name> when a module exports several registries, --no-descriptions, --timeout, --import <module>, --plain.

Terminal output

inspect renders a richer view — colour-coded side effects and risk, and the runtime-policy state as a panel rather than a trailing line — when it is attached to a terminal. It falls back to the plain renderer, byte for byte, whenever output is piped or redirected, CI is set, NO_COLOR is set, --plain is passed, or the optional UI dependencies are absent.

check is always plain. Its output is a report that gets pasted into pull requests and read out of CI logs, so it stays stable text with no rendering framework in its path at all.

The interactive layer is Ink, declared in optionalDependencies and loaded with a dynamic import(). An install that skips optional dependencies keeps the gate to this package plus core, and everything except init still works:

pnpm add -D @orpc-agent/cli --no-optional

Defaults can live in package.json, which makes the CI step just orpc-agent check:

{ "orpcAgent": { "entry": "src/app.ts", "export": "governance" } }

GitHub Actions

- run: pnpm build
- run: npx orpc-agent check --format github

How it loads your application

The entry module is imported in a child process, because importing an app runs its top-level code: it may open pools, start servers, or keep the event loop alive forever. Isolating it means the CLI can time out and hard-exit without inheriting any of that. The child gets ORPC_AGENT_INSPECT=1 so an application can guard its own import-time work:

if (process.env.ORPC_AGENT_INSPECT !== "1") await connect();

TypeScript entries load natively on Node ≥ 22.18. On older Node the CLI uses tsx or jiti if the project already has one — neither is a dependency of this package — and otherwise says so instead of guessing. --import <module> overrides the choice; pointing --entry at compiled JavaScript needs nothing at all.

Exports are found by shape: a value from defineGovernance, an AgentRuntime, or a createCapabilityRegistry registry. A module exporting all three is not ambiguous — whichever carries the most governance wins, governance first. Exports resolving to genuinely different registries still ask for --export. A function export is refused rather than called — calling it could connect, migrate, or charge a card. The inventory is read from a value, never produced by invoking your code.

Snapshot versions

Snapshots are written at version 3, which adds runtime-policy scope and resolved candidate capabilities. Version 2 files remain readable and gain neutral scope-observability drift until refreshed. Version 1 files still mean "runtime policies were never observed". Upgrading does not break a committed snapshot or a --fail-on widening gate.

What this does not see

This is a static inventory. It reports what the registry, the metadata and the runtime configuration declare, and deliberately does not pretend to more:

  • It does not evaluate policies, and never will. evaluate needs a real actor, surface, input and context, and may do I/O. The tool reports authoritative scope and current candidate capabilities, never the decision returned for a real invocation. A capability a policy would hide from everyone still appears here, and the APPROVAL column shows only what meta.approval declares.

    This is why the headline says declared gates and runtime candidates carry a runtime: prefix. check is a diff of declarations and applicability, not a proof of runtime verdicts.

  • Runtime policies are only in scope when a runtime is. --entry resolving a bare registry means they were never observed — reported as runtime policies not observed, which is unknown, not none. A snapshot taken that way cannot detect a runtime policy being deleted.

  • Adapter-level toolNaming is invisible. toolNames is derived from metadata; an adapter configured with its own naming function overrides it.

  • Composite capability-scoped policies appear under the composite's name, not their members'. Runtime-level composites are flattened, matching what audit events record.

Guarding against new code that is wrong from the start is a different job from guarding against change — a rules engine, not a snapshot. That is not in this version.

Programmatic use

buildSnapshot, diffSnapshots, loadSnapshot, and the renderers are exported for building your own gate or report.


Docs: CLI reference · a drift gate in CI · repository

MIT · Independent community project, not affiliated with or endorsed by the oRPC maintainers.