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

@skill-router/runtime

v0.1.14

Published

SkillRouter runtime — command registry, local daemon (127.0.0.1:19825) and browser bridge for sr-* CLI adapters. Fork of the published @jackwener/opencli 1.8.6 npm artifact (Apache-2.0, see NOTICE); wire-compatible with additive SkillRouter handoff and co

Readme

@skill-router/runtime (sr-runtime)

SkillRouter's local runtime: command registry, executor, plugin system, local daemon (127.0.0.1:19825) and browser bridge. Forked from the published @jackwener/opencli 1.8.6 npm artifact with selected 1.8.7/main framework changes ported (Apache-2.0, see NOTICE). It ships the bare runtime only, without the upstream site adapters; SkillRouter adapters are installed separately as plugins. Basic commands stay wire-compatible with the upstream protocol.

It is normally installed and upgraded together with @skill-router/cli by sr update; no separate steps are needed.

sr-runtime plugin install file:///abs/path/sr-arxiv   # install an adapter
sr-runtime sr-arxiv paper 1706.03762                  # run an adapter command directly
sr-runtime plugin migrate                             # adopt existing plugins from ~/.opencli/plugins
sr-runtime plugin verify [name]                       # check installed plugins against their content hashes
sr-runtime plugin lint /abs/path/sr-x                 # static pre-release checks for an adapter
sr-runtime sitedata sr-x --show                        # show the source and version of a site's calibration data
sr-runtime sitedata sr-x --refresh                     # refresh a site's calibration data now
sr-runtime verify sr-x                                 # run the whole-site fixtures (write commands stop at prepare)
sr-runtime doctor                                      # check daemon and Bridge connectivity

plugin verify exits non-zero for tampered, missing and unverified plugins.

Site calibration data (sitedata)

Every plugin ships a sitedata.json that is data only: URLs, selectors, labels, mappings, wait limits, fixtures and pace. After a command finishes, the runtime spawns at most one detached background process every 15 seconds to check for updates by ETag; the command itself never waits on the network. Selection order: a fresh cache under 24 hours old → a valid cache under 30 days old → the copy bundled with the plugin; a change in the bundled version discards the old cache. Remote documents must pass schema, regular-expression safety and plugin domain allowlist validation; a failure never replaces the last-known-good copy, and a document older than the bundled version is never accepted. SR_NO_SITEDATA_REFRESH=1 disables the background refresh; SR_SITEDATA_REFRESH_INTERVAL_MS adjusts the check interval (5 seconds to 24 hours).

Sites that declare pace keep persistent accounting in ~/.skillrouter/state/pace/<site>.json; when that state cannot be written, the command is refused rather than released. verify checks row counts, columns and pattern/notEmpty for read commands, and for write commands strips the submit arguments and checks only prepare_assert. plugin lint checks command/fixture alignment, literal sleeps, disabled automation surfaces and out-of-domain URLs.

Browser sessions

Browser commands reuse a persistent site session by default; precedence is --site-session > SR_SITE_SESSION > the command's declaration > the default. A read command first makes one non-waiting local lease attempt: when idle it reuses site:<site>, when busy it switches to an isolated tab and prints [sr] site:<site> busy → isolated tab (SR_QUIET=1 silences the notice). A read that loses its lease mid-command discards its result and reruns once in full on an isolated tab; if that fails too, it exits 65 with the original error. A write command returns SESSION_BUSY (exit 75) immediately when the session is busy and is never rerun automatically. After a process crash the lease is reclaimed by TTL within about 45 seconds. Read commands must therefore be idempotent.

After a persistent command succeeds, the runtime sends control-release: the final page and the site-to-tab mapping are kept, but debugger control is detached at once and the extension icon goes from LIVE to IDLE. Only an explicit tabs close really closes the tab.

The browser subcommand picks its window default by host: a person in an interactive terminal gets the foreground; when driven by an agent, MCP or a pipe it runs in the background and never steals focus. --window, --show and login-wall takeover are unaffected; pick and blocking record are always foreground.

Failure handoff and login walls

When an adapter command fails hard, the runtime writes a handoff bundle to ~/.skillrouter/handoff/<timestamp>-p<PID>-<UUID>.json and refreshes latest.json (mode 0600, kept seven days, never uploaded). When takeover is safe the bundle carries the adapter lease, the page target, a screenshot and candidate elements; inspect the scene with sr-runtime browser <session> --surface adapter state --tab <target>. Before taking over a write command, confirm whether the first attempt partially succeeded; never blindly replay it. Login and CAPTCHA go to a human; rate limits and risk-control decisions are never taken over.

On a login wall the runtime brings the tab to the foreground, shows a card asking a human to log in, and reruns the command once after the login lands. SR_REQUEST_HELP=off disables this.

sr report-fix --pick lets you pick the repair target on the live page at the breakpoint and uploads the chosen selector and its structural fingerprint to the SkillRouter repair service. Apart from the optional run signal below, it is the only command in this runtime that sends data out on its own.

Before browser <session> network --detail <key> writes to its cache or output, sensitive headers such as authorization, cookie, token, password, secret and session id, and credential-shaped values, are replaced with <redacted>; URL query parameters are redacted the same way.

Optional anonymous run signal

Off by default. After sr signal on, the runtime asynchronously sends a fixed five-field record {site, cmd, sitedata_version, ok, code} when a command completes; it carries no arguments, URLs, page content, output or credentials, and a failed send never affects the command. SR_SIGNAL=1|0 switches it explicitly. Details: https://skillrouter.org/us/privacy .

Action overlay, recording and exploration audit

SR_SHOW_ACTIONS=1 or --show displays a synthetic cursor, target highlight and action labels (decoration only, not audit evidence).

sr-runtime browser work pick --prompt "click the publish button"   # returns ref + selector (300 s, Esc cancels)
sr-runtime browser work record --purpose "demo a search"           # writes trace.json + states/ after Finish
sr-runtime browser work record --values                            # record typed values (never passwords, OTP, card numbers, SSN)
sr-runtime browser work explore start                              # local black box: command names and redacted arguments only
sr-runtime browser work explore stop
sr-runtime browser audit <record-dir> --json                       # verdict: read_pure / write_actions / violations

audit exits 1 on a violations verdict. network, analyze and wait xhr read the network capture buffer and cannot leave complete network evidence, so an explore session that uses them is always judged violations.

Recordings are written with mode 0600 to ~/.skillrouter/records/<timestamp>-<host>/, kept seven days, capped at 500 steps or 5 MiB. URLs keep origin, path and parameter names; sensitive parameter values are redacted. trace.json is untrusted data supplied by the web page; states/*.txt are full-page text snapshots that may contain personal information from the page and should not be uploaded. Google/Microsoft sign-in, password managers, Alipay/Taobao login, PayPal, Stripe and any host containing bank refuse recording by default; SR_RECORD_BLOCK_HOST=host,*.suffix extends the blocklist, and SR_RECORD_ALLOW_HOST=a,b is an explicit risk acceptance that takes precedence over it. The bank substring rule has a clear ceiling: bank sites whose domain lacks the word and punycode domains not on the list are not recognised automatically. Recordings and exploration files stay on this machine, are never uploaded and must not be placed in the four-field feedback body; they leave the machine only when the owner explicitly submits a candidate later.

Domain allowlist and plugin integrity

Every adapter command runs inside a domain allowlist: the plugin manifest domains ∪ the sitedata.json domains. Navigations and requests the runtime itself initiates outside the allowlist are refused (exit 68, handoff takeover_policy.mode = stop); navigations the page performs on its own are only recorded as landing URLs. A plugin that declares no domains gets a single warning; SR_STRICT_DOMAINS=1 turns that into a refusal and installs a page-side fetch/XHR observer (count only, never blocking). about:, data:, blob: and chrome-extension: pass; javascript: and chrome: do not. A manifest whose domains contain illegal entries (a scheme, path or port, loopback or private addresses, a public-suffix wildcard) is refused by plugin install/update; already-installed plugins are enforced on their valid subset. Matching is exact: a full hostname matches only that host, and *.example.com matches subdomains only.

plugin install/update records a content hash of the plugin directory in ~/.sr/plugins.lock.json (excluding node_modules, .git and *.log); plugin verify compares against it, the executor warns once per process about a mismatching plugin, and under SR_STRICT_INTEGRITY=1 only verified plugins run. A local-path install is a symlink hashed through its real directory; after editing its code, run plugin update <name> to re-record it. Threat model: the domain guard catches hijacked pages, poisoned sitedata and honest adapter mistakes; adapter code runs inside the runtime process, so this is not a sandbox against a malicious plugin author, which is what plugin lint and the integrity hash are for. The lock file lives in the user's home directory and only detects one-sided tampering.

Directories and environment variables

The runtime's own state lives under ~/.sr/ (plugins, plugins.lock.json, monorepos, the update-check cache); logins and configuration shared with upstream opencli stay under ~/.opencli/, so both can coexist. SR_DAEMON_TOKEN optionally enables a daemon handshake token (off by default).