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

@cloakcode/gateway

v1.0.0

Published

Standalone CloakCode gateway — the run-it-yourself hub that serves the PWA and multiplexes phone (operator) + extension (provider) connections. NO vscode import.

Readme

@cloakcode/gateway

The standalone CloakCode gateway — a run-it-yourself hub that serves the CloakCode phone app (PWA) and connects your phone (operator) and your VS Code extensions (providers) over two role-scoped listeners — a loopback operator listener (PWA + phone) and a dedicated provider listener (extensions, wss:// by default). Run it when you want several VS Code windows or machines to share one phone endpoint, or to keep the hub outside the editor.

Pairs with the CloakCode VS Code extension: the extension observes and steers your Copilot sessions; the gateway is the shared hub your phone connects to.

Needs Node ≥ 20. When the gateway is exposed (a wide 0.0.0.0 bind or a live tunnel) it requires operator TOTP by default (secure-by-exposure — see Operator auth and the step-by-step setup); still prefer a private tunnel over a wide bind on an untrusted network (see Security).

Deployment shapes at a glance

Pick a row; each links to the section with the detail.

| Goal | Command | Operator auth (phone) | Provider transport (extensions) | | ------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------ | ----------------------------------------- | | Try it locally, everything on one machine | npx @cloakcode/gateway | Off (pure loopback isn't exposed) | wss://127.0.0.1:3544, self-signed + pin | | Phone access from anywhere | CLOAKCODE_TUNNEL=devtunnel npx @cloakcode/gateway | TOTP (auto — the tunnel exposes it) | unchanged — extensions stay on loopback | | Extensions on other machines | Docker (publishes 3544), or CLOAKCODE_TLS_HOST=0.0.0.0 | as above | wss://<host>:3544 + fingerprint pin | | You already run Tailscale / WireGuard / ssh -L | npx @cloakcode/gateway (keep both listeners on loopback) | CLOAKCODE_MFA=required if you want it | the overlay encrypts; pin still applies | | Trusted LAN, no TLS wanted | CLOAKCODE_PROVIDER_INSECURE=1 npx @cloakcode/gateway | as above | plain ws:// — warned, no pin |

The two listeners are independent: exposing the phone endpoint never exposes the extension one, and vice versa. See Two listeners for the binding and certificate rules, and docs/07 — Deployment for network-level detail (dev containers, WSL, firewall lockdown).

Run it — npx (no install)

npx @cloakcode/gateway

Serves the PWA (phone) on the operator listener at http://127.0.0.1:3543 and accepts extensions on the dedicated provider listener at wss://127.0.0.1:3544 (wss by default), printing separate browser and extension URL lists.

There are no CLI flags — the published bin (cloakcode-gateway) is configured entirely by environment variables set on the command line. The common ones:

# phone access via a private Dev Tunnel (needs the devtunnel CLI, signed in) — prints a phone URL
CLOAKCODE_TUNNEL=devtunnel npx @cloakcode/gateway

# pick a fixed port (default 3543; a fixed value keeps the phone/tunnel URL stable)
CLOAKCODE_GATEWAY_PORT=8080 npx @cloakcode/gateway

# require a provider token and host a phone tunnel — extensions reach the provider
# listener (wss on 3544) directly; the phone reaches the PWA via the tunnel
CLOAKCODE_GATEWAY_TOKEN=<shared-secret> \
CLOAKCODE_TUNNEL=devtunnel \
  npx @cloakcode/gateway

See all options below.

Run it — Docker

# extensions connect to the provider listener (wss) on 3544; the phone reaches the
# PWA via the gateway's own private tunnel (enable it below)
docker run --rm -p 3544:3544 ghcr.io/lsiddiquee/cloakcode-gateway:latest
# pin a version:  ...cloakcode-gateway:v0.1.2

In the image the operator listener (PWA + phone) binds loopback 127.0.0.1:3543 — reach it via the gateway's own private Dev Tunnel (below), or front it with your own ingress by setting -e CLOAKCODE_GATEWAY_HOST=0.0.0.0 and publishing -p 3543:3543. The provider listener binds 0.0.0.0:3544 (wss); publish it with -p 3544:3544 so extensions can connect. Configure with the same environment variables via -e:

docker run --rm -p 3544:3544 \
  -e CLOAKCODE_GATEWAY_TOKEN=<shared-secret> \
  -e CLOAKCODE_TUNNEL=devtunnel \
  -v cloakcode-devtunnel:/home/app/.local/share/DevTunnels \
  ghcr.io/lsiddiquee/cloakcode-gateway:latest

Phone tunnel from the container

The image bundles the devtunnel CLI (inert unless you enable it). To host a private Dev Tunnel straight from the container, enable it and mount a volume for the token so you only sign in once:

docker run -p 3544:3544 \
  -e CLOAKCODE_TUNNEL=devtunnel \
  -v cloakcode-devtunnel:/home/app/.local/share/DevTunnels \
  ghcr.io/lsiddiquee/cloakcode-gateway:latest

On first run it prints a device code + URL to the console (docker logs) — open the URL in any browser and enter the code. The sign-in is device-code, so -it is not needed (it runs fully detached); it blocks until you finish, and if the code expires the container exits — just restart. The token lives in the mounted volume, so later runs sign in silently. Sign-in defaults to GitHub; set -e CLOAKCODE_TUNNEL_PROVIDER=microsoft for a Microsoft account. The container runs as a non-root user (app). Prefer your own ingress instead? Leave the tunnel off and front the published port with Cloudflare Tunnel / Tailscale / a reverse proxy.

Persisting state across container upgrades (volumes)

A container is ephemeral — without volumes, replacing it (an image upgrade, docker rm, a recreate) regenerates the operator TOTP secret (so every paired phone must re-enrol), drops the Dev Tunnel sign-in, and discards the action log. Mount a volume for each piece of state you want to keep — and you can relocate the files with env vars if you'd rather point them at one shared volume:

| State | Default path in the container | Relocate with | Keep it with | | -------------------------------------- | ------------------------------------- | ----------------------------------- | --------------------------------------------------------------------------------------- | | Operator TOTP secret (+ confirmed) | /home/app/.cloakcode/operator-totp.secret | CLOAKCODE_MFA_SECRET_FILE | -v cloakcode-mfa:/home/app/.cloakcode | | Dev Tunnel sign-in token | /home/app/.local/share/DevTunnels | (fixed — mount the path) | -v cloakcode-devtunnel:/home/app/.local/share/DevTunnels | | Action log (JSONL) | /app/cloakcode-gateway.jsonl | CLOAKCODE_GATEWAY_LOG_FILE ("" = off) | point it into a mounted dir (see below) |

All three at once — TOTP secret survives upgrades, tunnel signs in once, and the action log lands on a named volume:

docker run -p 3544:3544 \
  -v cloakcode-mfa:/home/app/.cloakcode \
  -v cloakcode-devtunnel:/home/app/.local/share/DevTunnels \
  -v cloakcode-logs:/data \
  -e CLOAKCODE_GATEWAY_LOG_FILE=/data/gateway.jsonl \
  -e CLOAKCODE_TUNNEL=devtunnel \
  ghcr.io/lsiddiquee/cloakcode-gateway:latest

Prefer one volume for everything? Relocate the secret + log into it and mount it once: -e CLOAKCODE_MFA_SECRET_FILE=/data/totp.secret -e CLOAKCODE_GATEWAY_LOG_FILE=/data/gateway.jsonl -v cloakcode-data:/data (the Dev Tunnel token dir is fixed, so mount it separately if you use the built-in tunnel).

Full setup — exposed gateway with MFA (step by step)

When the gateway is exposed — a live tunnel (the phone path) or a wide 0.0.0.0 operator bind — operator TOTP is on automatically (secure-by-exposure). Here's the whole flow: gateway → phone → extension. Force it on/off with CLOAKCODE_MFA=required / CLOAKCODE_MFA=off.

1. Start the gateway

# The phone reaches the operator via a private tunnel, which EXPOSES it → MFA turns
# on. Mount a volume so the TOTP secret (and the tunnel sign-in) survive container
# replacement. Extensions connect to the provider listener on 3544.
docker run -p 3544:3544 \
  -e CLOAKCODE_TUNNEL=devtunnel \
  -v cloakcode-mfa:/home/app/.cloakcode \
  -v cloakcode-devtunnel:/home/app/.local/share/DevTunnels \
  ghcr.io/lsiddiquee/cloakcode-gateway:latest

On first run the console prints the instance name + the connect URLs and reports that enrolment is required — until you pair an authenticator the hub serves only the pairing screen, no session data. (No tunnel? The operator stays on loopback with MFA off; front it with your own private tunnel / ingress, or set -e CLOAKCODE_GATEWAY_HOST=0.0.0.0 -p 3543:3543 to expose the PWA directly.)

2. Enrol an authenticator (operator — one time)

Open the gateway app — easiest on a desktop browser so you can scan the on-screen QR with your phone's authenticator app:

  • Local / LAN: http://<gateway-host>:<gateway-port>
  • Tunnel: the phone URL printed in the console (docker logs).

The app shows a QR code. Scan it into an authenticator app (Google Authenticator, 1Password, …), then enter the current 6-digit code to confirm. The secret is generated once and stored 0600 (in the mounted volume). Once confirmed, the gateway is active and serves normally.

Desktop vs phone. Opening the page on a desktop lets you scan the QR with your phone's authenticator. If you open it on the phone itself, you can't scan a QR on the same screen — tap/copy the shown secret into your authenticator instead.

Lock it down with strict enrolment. By default (CLOAKCODE_MFA_ENROL=browser) the QR + secret are served to whoever opens the gateway during enrolment — convenient, but it means anyone who reaches the gateway before you've paired could enrol their own authenticator and take over. Set CLOAKCODE_MFA_ENROL=strict so the secret is never sent over the wire — the QR is shown only on an interactive TTY (never the persistent docker logs stream, drift audit S7). Scan it from an attached terminal, then enter a code in the app; a headless run instead points at the 0600 secret file (retrieve it once out-of-band, e.g. docker exec … cat) or use browser enrolment.

Every later phone/browser logs in with the current 6-digit code and gets a session token (12 h, or 30 days with "remember this device"), so reconnects don't re-prompt. Replayed and repeatedly wrong codes are rejected.

3. Connect your VS Code extension (provider)

In each VS Code window point the extension at the gateway:

"cloakcode.gatewayUrl": "ws://<gateway-host>:<gateway-port>"

The extension connects, and because the gateway requires auth it asks the extension to sign in (it does not fall back to an embedded bridge). Click the Sign In prompt, or run CloakCode: Sign in to Gateway from the Command Palette, and enter a current 6-digit code from the same authenticator you enrolled in step 2. The extension stores the issued provider token (per gateway URL) and reconnects. (Set the URL after activation? Run CloakCode: Reconnect or reload the window.)

Headless/automation instead of interactive sign-in? Present a static machine-to-machine secret: CLOAKCODE_GATEWAY_TOKEN on the gateway + cloakcode.gatewayToken on the extension (Provider token).

4. Validate

Refresh the gateway in your browser/phone — the Copilot sessions from that VS Code window now appear. Open one to see the live transcript; a blocked session shows a "Needs your input" card you can answer remotely.

Connect your VS Code extension

In VS Code settings, point the extension at the gateway's provider listener (several windows can share one):

"cloakcode.gatewayUrl": "wss://<gateway-host>:3544"

Also set cloakcode.gatewayCertFingerprint to the pin from the gateway's Connect an extension view (all a self-signed gateway needs). An insecure gateway (CLOAKCODE_PROVIDER_INSECURE=1) uses a plain ws:// URL instead.

If you started the gateway with a token, set the same value on the extension so it can register as a provider — see Provider token below.

If the gateway requires operator TOTP (the default when exposed), the extension connects but the gateway asks it to sign in — it does not fall back to an embedded bridge. Click the Sign In prompt (or run CloakCode: Sign in to Gateway) and enter a current 6-digit code from the authenticator you enrolled on the gateway; the extension stores the issued provider token per URL and reconnects. Full walkthrough: Full setup.

For a gateway on another machine or container, bind the provider listener wide (CLOAKCODE_TLS_HOST=0.0.0.0 — the Docker image already does), then use that host's IP with the provider port in gatewayUrl (e.g. wss://192.168.1.10:3544) plus the cloakcode.gatewayCertFingerprint pin from its Connect an extension view. (The operator/PWA listener stays on loopback — reach the phone via the gateway's tunnel.)

Provider token (shared secret)

The gateway and every extension that connects to it authenticate the provider↔gateway link with one shared secret. When you run the gateway separately, the token must be identical on both sides and configured in both places — otherwise the gateway rejects the extension and its sessions never reach your phone.

Set the same value on the gateway and on every VS Code window that connects:

# gateway (env) — npx
CLOAKCODE_GATEWAY_TOKEN=<shared-secret> npx @cloakcode/gateway
# gateway (env) — Docker
# gateway (env) — Docker (publish the provider listener so extensions can reach it)
docker run --rm -p 3544:3544 -e CLOAKCODE_GATEWAY_TOKEN=<shared-secret> ghcr.io/lsiddiquee/cloakcode-gateway:latest
// VS Code settings — must match the gateway's token exactly
"cloakcode.gatewayToken": "<shared-secret>"
  • Machine-to-machine only. The token is never sent to or shown on the phone (operator auth is separate).
  • Both unset = no auth (fine for loopback dev). If the gateway has a token and the extension doesn't — or they differ — the gateway logs provider.auth_reject and closes the connection.
  • Use any hard-to-guess value; e.g. openssl rand -hex 32. The CLOAKCODE_GATEWAY_TOKEN env var overrides the cloakcode.gatewayToken setting on the extension side.

Two listeners: operator (loopback) + provider (wss)

The gateway binds two role-scoped listeners:

  • the operator listener — the PWA + phone — on CLOAKCODE_GATEWAY_HOST (default 127.0.0.1), fronted by your private Dev Tunnel (which supplies TLS). Operators only.
  • the provider listener — the dedicated endpoint extensions connect to — on CLOAKCODE_TLS_HOST (default 127.0.0.1; the Docker image sets 0.0.0.0) :CLOAKCODE_TLS_PORT (default 3544). Providers only; a provider is never served on the operator bind.

The provider listener is wss:// by default — with no BYO cert the gateway generates and persists a self-signed pair under ~/.cloakcode (key 0600, never logged) and prints its SHA-256 fingerprint — the pin. BYO a real CA / mkcert / corporate cert with CLOAKCODE_TLS_CERT_FILE + CLOAKCODE_TLS_KEY_FILE:

# wss on the default provider port (3544), auto self-signed cert:
npx @cloakcode/gateway
# a fixed provider port + BYO cert/key:
CLOAKCODE_TLS_PORT=7443 CLOAKCODE_TLS_CERT_FILE=./gw.crt CLOAKCODE_TLS_KEY_FILE=./gw.key npx @cloakcode/gateway
# INSECURE plain ws (trusted network only — warned in console + UI):
CLOAKCODE_PROVIDER_INSECURE=1 npx @cloakcode/gateway

An encrypted overlay / reverse proxy (Tailscale, WireGuard, ssh -L, Caddy/nginx) with both listeners on loopback is still the lowest-friction path when you already have one.

Pair an extension from the app: open the PWA (behind your tunnel + TOTP) → Settings → Connect an extension. It shows one pairing URL to paste into the extension's cloakcode.gatewayUrl — the reachable wss:// address with this gateway's fingerprint attached as a #fp=… fragment, so the address and its pin can never drift apart (the fragment is never transmitted; the extension splits it off locally). The extension then fetches the certificate, accepts it only if it matches that pin, and uses it as the trust anchor — failing closed on a mismatch, never downgrading to trust-on-first-use. The bare pin is shown too for anyone who prefers cloakcode.gatewayCertFingerprint as a separate setting. A gateway whose certificate a real authority already vouches for (a public CA, or your org's root deployed to the device) needs no setting beyond the URL. The console printout is the fallback when no tunnel is up. The fingerprint is public (an integrity pin, not a secret); the private key never leaves the gateway.

Operator auth (TOTP)

The phone → gateway boundary is gated by a time-based one-time code (RFC 6238 TOTP) whenever the hub is exposed — a wide bind or a live tunnel. Force it with CLOAKCODE_MFA=required, turn it off with CLOAKCODE_MFA=off; unset means secure-by-exposure (off for pure loopback dev). For the end-to-end walkthrough see Full setup.

Pair once (enrolment). On first run the gateway generates a secret and persists it 0600 to CLOAKCODE_MFA_SECRET_FILE (default ~/.cloakcode/operator-totp.secret). A fresh secret is unconfirmed — the hub runs in enrolment mode, serving only the pairing screen until you verify a code. Default (browser): open the gateway URL and the app shows the QR — scan it into an authenticator app, then enter a code to confirm. Strict (CLOAKCODE_MFA_ENROL=strict): the secret is never sent over the wire — the QR + otpauth URI are printed to the console instead; scan there and verify in the app. Either way the secret is shown once; later runs reuse the file.

Each phone logs in with the current 6-digit code; the gateway returns a signed session token (12h, or 30d with “remember this device”) so reconnects don't re-prompt until it expires. A reused code (replay) and repeated bad codes (lockout) are rejected. The secret is never sent to the phone or written to the action log.

Identifying a gateway (CLOAKCODE_INSTANCE_ID). Each gateway has an instance id used as its authenticator label (the otpauth account — so the app shows CloakCode: <id>), its Dev-Tunnel name seed, and the name shown to the phone (in the app header). It defaults to the machine hostname (the Windows computer/NetBIOS name, or the Unix hostname) — printed at startup as [cloakcode-gateway] instance: <id> — so gateways on different machines are already distinguishable with no configuration.

Running more than one gateway on one machine (e.g. office + home)? Set a distinct CLOAKCODE_INSTANCE_ID on each (office, home, …) so the authenticator entries read CloakCode: office / CloakCode: home and the phone shows which one you're connected to, instead of two identical hostnames. The VS Code extension stores each gateway's issued token separately (per URL), so switching cloakcode.gatewayUrl between them never re-pairs.

In Docker, mount -v cloakcode-mfa:/home/app/.cloakcode so the TOTP secret survives container replacement (the image runs as app, so its home is /home/app), or relocate it with CLOAKCODE_MFA_SECRET_FILE — see Persisting state across container upgrades for all the volumes (secret, tunnel token, action log).

Configuration (environment variables)

| var | default | meaning | | --------------------------- | --------------------------- | ----------------------------------------------------------------------- | | CLOAKCODE_GATEWAY_HOST | 127.0.0.1 | operator listener bind (PWA + phone); keep loopback and front it with a private tunnel | | CLOAKCODE_GATEWAY_PORT | 3543, else a free port | operator port — also the port segment of the Dev Tunnel URL. Unset ⇒ try 3543 and fall back to a free port; 0 ⇒ always ephemeral; a value ⇒ lock it | | CLOAKCODE_TUNNEL | (off) | devtunnel → auto-host a private tunnel and print the phone URL | | CLOAKCODE_TUNNEL_PROVIDER | github | Docker only: github or microsoft for the container's device-code sign-in; defaults to GitHub | | CLOAKCODE_INSTANCE_ID | (machine hostname) | tunnel-name seed and authenticator label (e.g. office/home, so multiple gateways are distinguishable in your app) | | CLOAKCODE_GATEWAY_TOKEN | (off) | provider↔gateway shared secret; extensions must present the same value | | CLOAKCODE_MFA | (secure by exposure) | operator TOTP: required to force it, off to disable; unset ⇒ on when the hub is exposed (wide bind / live tunnel), off for pure loopback | | CLOAKCODE_MFA_SECRET_FILE | ~/.cloakcode/operator-totp.secret | where the base32 TOTP secret persists (0600); mount it as a volume in Docker | | CLOAKCODE_MFA_ENROL | browser | strict never sends the pairing secret over the wire (console QR only) | | CLOAKCODE_MFA_RESET | (off) | 1 regenerates the secret (lockout recovery) and re-enters enrolment | | CLOAKCODE_TLS_HOST | 127.0.0.1 (0.0.0.0 in Docker) | provider listener bind — the dedicated endpoint extensions connect to (separate from the operator listener) | | CLOAKCODE_TLS_PORT | 3544, else a free port | provider listener port (always on); same rule as the operator port (0 = ephemeral, a value locks it). Pair extensions via Connect an extension in the app | | CLOAKCODE_TLS_CERT_FILE | (auto self-signed) | BYO PEM cert for the wss provider listener (with _KEY_FILE); unset ⇒ an auto self-signed pair persisted under ~/.cloakcode | | CLOAKCODE_TLS_KEY_FILE | (auto self-signed) | BYO PEM private key for wss (with _CERT_FILE); a 0600 secret, never logged | | CLOAKCODE_PROVIDER_INSECURE | (off) | 1 ⇒ serve the provider listener as insecure plain ws:// (no cert) — trusted-network only; warned in console + UI | | CLOAKCODE_GATEWAY_LOG_FILE| ./cloakcode-gateway.jsonl | on-disk action log (JSONL); set empty to disable | | CLOAKCODE_WEB_DIR | bundled web/ | PWA directory to serve (defaults to the bundled app) | | CLOAKCODE_LOG_LEVEL | info | trace/debug/info/warn/error (CLOAKCODE_VERBOSE=1 ⇒ debug) | | CLOAKCODE_VERBOSE | (off) | 1 ⇒ shorthand for CLOAKCODE_LOG_LEVEL=debug (per-RPC detail: relay routing, sessions.list) |

The gateway logs provider / operator connect + disconnect by default; raise the level (or CLOAKCODE_VERBOSE=1) for per-RPC detail.

Security

The two trust boundaries are authenticated separately:

  • Operator (phone) → gateway: TOTP (F2a). On by default whenever the hub is exposed (wide bind or a live tunnel); force it with CLOAKCODE_MFA=required, disable with CLOAKCODE_MFA=off. See Operator auth (TOTP) — pair once, then each phone logs in with a 6-digit code and resumes with a 12h/30d session token.
  • Provider (extension) → gateway: shared token. Set CLOAKCODE_GATEWAY_TOKEN so only extensions holding the secret can register (machine-to-machine; never shown to the phone).

Both set together? The two hops authenticate independently — enabling one never disables the other:

  • Phone (operator) → gateway: always TOTP when MFA is on. The static token is never used on this hop.
  • Extension (provider) → gateway: verifyProviderCredential accepts either a TOTP-issued token or the static token — an OR, not a priority or override. With MFA only, the extension must sign in with a code to obtain a token, so TOTP gates this hop too; adding a static token just supplies a second accepted credential (the headless escape hatch). On its side, the extension prefers its stored sign-in token and falls back to the static one.

Still prefer loopback + a private tunnel (default host 127.0.0.1; the Dev Tunnel is private, sign-in required) over a wide 0.0.0.0 bind on an untrusted network — TOTP gates control, but a private tunnel keeps the surface off the open internet.

Build from source

Requires the monorepo checkout (lsiddiquee/CloakCode):

# assemble a copy-ready folder (main.mjs + web/ + run.sh) into dist/gateway/
pnpm --filter @cloakcode/gateway assemble
cd dist/gateway && ./run.sh --tunnel      # run.sh is a flag-driven launcher (--host/--port/--tunnel…)

dist/gateway/ is self-contained — copy it to any host with Node ≥ 20 and run ./run.sh there. run.sh --help lists the flags (each maps to a CLOAKCODE_* env var above).