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

@fetchproxy/cli

v1.6.1

Published

One-shot CLI for the fetchproxy bridge: authenticated fetches and session reads through the user's signed-in browser tab, scoped by per-service profiles.

Readme

@fetchproxy/cli

fpx — a one-shot CLI for the fetchproxy bridge: authenticated fetches and session reads through the user's signed-in browser tab, straight from a shell prompt or a skill.

@fetchproxy/server and @fetchproxy/bootstrap are libraries an MCP server embeds. fpx is the same bridge wrapped as a standalone binary — no Node process to write, no MCP server to run. Point it at a URL, get the response on stdout; point it at a storage bucket, get JSON back. Useful anywhere a skill or shell script needs one authenticated request and doesn't want to carry a whole MCP.

Install

npm install -g @fetchproxy/cli

Or run it without installing:

npx @fetchproxy/cli profile list

Either way, the user also needs the fetchproxy browser extension (Transporter) installed — see the top-level README.

The profile model

fpx scopes every command to a named profile — a small JSON record describing one service: its declared domains, and (optionally) the cookie keys, storage keys, capture-headers, and IndexedDB scopes it's allowed to read. Profiles live at $FETCHPROXY_CLI_HOME/profiles.json, or ~/.fetchproxy/cli/profiles.json if that variable is unset.

fpx profile add opentable --domain opentable.com
fpx profile list
# opentable    opentable.com

Per-service identity

Each profile gets its own long-term identity, keyed by name: profile opentable connects to the bridge as fpx-opentable, with its identity keypair persisted at ~/.fetchproxy/identity/fpx-opentable.json. This mirrors how a real opentable-mcp would identify itself — the extension's trust store, pair history, and capability grants are all keyed off that per-service identity, not off fpx itself. Running fpx against ten services looks, from the extension's point of view, like ten independent MCPs.

Pair-code flow

The first time any verb connects under a given profile, the extension doesn't auto-trust it. fpx prints a 6-digit pair code to stderr:

$ fpx health -p opentable
fetchproxy pair code: 482-913 — approve in the Transporter extension popup

Open the Transporter popup, confirm the code matches, click Approve. Every subsequent command against that profile — from any verb — reuses the same trust record and skips the prompt.

Re-pair on scope change

fpx profile declare widens a profile's scope (more cookie keys, a new capture-header, etc.). Because the extension's trust is keyed to (identity, domains, capabilities), widening the scope changes the hello the next connection sends, and the extension treats that as a diff worth re-confirming:

fpx profile declare opentable --cookie oaid --capture-header [email protected]
# profile "opentable" scope updated — the next connect will ask you to re-pair (scope diff)

The next command against opentable prints a fresh pair code even though the identity is unchanged.

Revocation

fpx profile remove <name> deletes the local profile entry and its identity file:

fpx profile remove opentable
# profile "opentable" removed — also revoke fpx-opentable in the Transporter extension popup

That only cleans up the CLI's side. The extension still holds a trust row for fpx-opentable until the user opens the Transporter popup and revokes it there — removing the profile does not reach into the browser.

Verbs

Every verb takes -p/--profile <name> (except the profile subcommands themselves, which take the name as a positional).

| Command | What it does | Example | |---|---|---| | fpx profile add <name> --domain <apex>… | Create a profile with one or more declared domains. | fpx profile add opentable --domain opentable.com | | fpx profile declare <name> [--cookie k]… [--local-storage k]… [--session-storage k]… [--capture-header name@host[/path]]… [--dom-selector handle=css]… [--allow-download] | Widen a profile's scope. Merges with the existing declaration; forces a re-pair. | fpx profile declare opentable --cookie oaid | | fpx profile list | List all profiles and their domains (tab-separated, one per line). | fpx profile list | | fpx profile show <name> | Print a profile's full JSON record. | fpx profile show opentable | | fpx profile remove <name> | Delete the profile and its identity file. | fpx profile remove opentable | | fpx pair -p <name> [--domain <apex>] | Force a pairing round-trip against one declared domain (defaults to the only one, if there's exactly one). | fpx pair -p opentable | | fpx health -p <name> | Print the bridge's health snapshot (host/peer role, connection state). | fpx health -p opentable | | fpx get <url> -p <name> [--json] [-H 'K: V']… | GET a URL through the profile's tab. | fpx get https://www.opentable.com/ -p opentable | | fpx post-json <url> <body\|@file> -p <name> [--json] [-H 'K: V']… | POST a JSON body (literal or @file); sets Content-Type: application/json unless overridden. | fpx post-json https://www.opentable.com/dapi/fe/gql '{"operationName":"Autocomplete"}' -p opentable | | fpx request <url> -p <name> [-X METHOD] [-H 'K: V']… [-d body\|@file] [--json] | Arbitrary method/headers/body. | fpx request https://www.opentable.com/x -p opentable -X DELETE | | fpx cookies [keys…] -p <name> | Read declared cookies (all declared keys if none given). | fpx cookies -p opentable | | fpx local-storage [keys…] -p <name> | Read declared localStorage keys. | fpx local-storage authToken -p opentable | | fpx session-storage [keys…] -p <name> | Read declared sessionStorage keys. | fpx session-storage csrfToken -p opentable | | fpx indexeddb -p <name> | Read all declared IndexedDB scopes (no key arguments — scopes come from the profile). | fpx indexeddb -p opentable | | fpx session -p <name> [--storage-domain d] [--storage-subdomain s] | Bootstrap-parity one-shot: pair (if needed), read every declared bucket, close, print the combined session JSON. | fpx session -p opentable | | fpx dom <name…> -p <name> [--storage-domain d] [--storage-subdomain s] | Read declared DOM selector values (all declared selectors if no names given). Requires --dom-selector declarations. | fpx dom title -p opentable | | fpx download <url> -p <name> [--filename f] | Download a URL through the browser's own network stack (chrome.downloads — real cookies + TLS fingerprint); prints {path, bytes, mime?, finalUrl?} for the saved local file. Requires --allow-download. | fpx download https://www.opentable.com/f.pdf -p opentable | | fpx --version (or -v) | Print the CLI version to stdout. The version also appears in the fpx / fpx --help header. | fpx --version |

--storage-domain / --storage-subdomain (on the storage-read verbs, session, and dom) select which declared domain to read from when a profile declares more than one — required only in that case, same as the underlying library.

--dom-selector <handle>=<css> (on profile declare) declares a named DOM read: <handle> is the logical name fpx dom references, <css> is the document.querySelector CSS selector the extension reads (first match only, no page-JS execution). --allow-download grants the profile the download capability, letting fpx download save a declared-domain URL through the browser's own network stack.

Output contract

  • stdout carries data only — response bodies, --json envelopes, storage-read JSON, profile list/profile show output.
  • Everything else goes to stderr — pair codes, status lines (profile "x" created …, paired ✓ …), hints, and error messages.

This split means fpx get … | jq . or fpx cookies -p x > cookies.json never picks up incidental noise.

Exit codes

| Code | Meaning | |---|---| | 0 | Success. | | 1 | Usage error — bad flags, unknown command, unknown profile, undeclared scope, malformed body. | | 2 | Bridge unavailable — extension not connected, pairing still pending, or an unexpected bridge-level failure. | | 3 | Bot wall detected in the response (Akamai/Cloudflare-style interstitial). | | 4 | Upstream HTTP error — the request reached the site but got a non-2xx response. |

Exit codes 3 and 4 are emitted only by the fetch verbs (get, post-json, request); the pair, health, session, read verbs (cookies/local-storage/session-storage/indexeddb), dom, and download all return 0 on a successful bridge round-trip regardless of upstream status.

FETCHPROXY_CLI_HOME

Profiles are stored at $FETCHPROXY_CLI_HOME/profiles.json if that environment variable is set, otherwise at ~/.fetchproxy/cli/profiles.json. Set it to isolate fpx state per-shell, per-CI-job, or for a smoke test:

FETCHPROXY_CLI_HOME=$(mktemp -d) fpx profile add scratch --domain example.com

Per-service identity files are unaffected by this variable — they always live at ~/.fetchproxy/identity/fpx-<name>.json.

Capability parity

Every verb — get, post-json, request, cookies, local-storage, session-storage, indexeddb, dom, download, even health and pair — derives its hello frame from the full profile record via the same serverOptsFor() helper, not just the fields that particular verb happens to touch. That's deliberate: the extension's trust is keyed to (identity, domains, capabilities), so if fpx get sent a narrower hello than fpx cookies, alternating between the two verbs on the same profile would look like a capability change and force a re-pair every time. Sending the same hello for every verb means you can freely interleave fpx get, fpx cookies, fpx dom, etc. against one profile and only ever pair once — a re-pair only happens when fpx profile declare actually changes the stored scope.

One exception: fpx session goes through @fetchproxy/bootstrap directly, not serverOptsFor(), and bootstrap has no concept of domSelectors/download — those two fields only exist for fpx's own dom/download verbs. So a profile that declares --dom-selector/--allow-download sends a wider hello on the direct verbs than fpx session does. In practice this costs nothing but a one-time, non-blocking re-pair the first time you alternate between fpx session and fpx dom/fpx download on such a profile — the same self-healing behavior already accepted for the storage-pointer scopes.

Skills

fpx is designed to be the thing a skill shells out to when it needs one authenticated read, without embedding a bridge client. A typical pattern:

# One-time setup (pairs interactively):
fpx profile add opentable --domain opentable.com
fpx pair -p opentable

# From then on, any skill script can do:
fpx get -p opentable 'https://www.opentable.com/dapi/fe/gql?...' --json | jq .body

Or, scoped to a declared cookie for a lightweight auth check:

fpx cookies oaid -p opentable | jq -r .oaid

Because pairing is per-profile and persists across invocations, a skill can call fpx repeatedly across a session — once per tool call, even — without re-triggering the pair prompt after the first approval.