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

cloakport

v0.1.0

Published

Reversible, deterministic, local-first PII redaction for LLM traffic: cloak sensitive values before they reach a model, restore them in the response.

Readme

cloakport

CI License: MIT Node deps

Reversible, deterministic, local-first PII redaction for LLM traffic. cloakport replaces sensitive values with placeholder tokens before text reaches a model, and restores the originals in the response — so the model works with [EMAIL_1] while you keep working with real data.

Status: early. Detection is a strong first pass, not a guarantee. Review the output before trusting it with regulated or high-risk data.

Why

Sending prompts to a hosted LLM often means shipping emails, phone numbers, keys, and account numbers to a third party. Most existing tools redact destructively (you lose the original) or depend on a cloud NER service (more data egress). cloakport is different:

  • Reversible — a vault maps each token back to its original value, so you can restore a model's response to real, usable text.
  • Deterministic & local — detection is plain regex plus checksum validators (Luhn for cards, ISO mod-97 for IBANs). No network, no model download, fully auditable.
  • Composable — a small engine with a CLI and a drop-in OpenAI-compatible proxy built on top of it. Zero runtime dependencies.

Install

git clone <this-repo> && cd cloakport
npm install && npm run build
npm link            # exposes `cloakport` on your PATH

Requires Node.js >= 20.

Usage

Redact / restore (CLI)

# Cloak PII; the vault records how to undo it (keep it private!)
cloakport redact notes.txt --map vault.json --out notes.redacted.txt

# ... send notes.redacted.txt to a model, get a reply that mentions tokens ...

# Restore the originals in the reply
cloakport restore reply.txt --map vault.json

# See what would be redacted, without changing anything
cloakport scan notes.txt --counts
cat notes.txt | cloakport scan --json

Drop-in proxy

Point any OpenAI-compatible client's base URL at cloakport; it redacts request bodies, forwards upstream, and restores the response:

cloakport proxy --upstream https://api.openai.com --port 8787
# then set your client's baseURL to http://127.0.0.1:8787

The per-request vault lives only in memory and is never logged or written to disk. The proxy fails closed: JSON bodies are redacted field-by-field, any other text body is redacted as plaintext, and a binary body is rejected rather than forwarded raw. Streaming (text/event-stream) responses are restored on line boundaries. Request bodies above a configurable cap (default 25 MB) are rejected with 413.

See examples/proxy-demo.mjs for a self-contained, runnable demo (npm run build && node examples/proxy-demo.mjs) that shows the model receiving only tokens while the client gets real values back.

What it detects

| Type | Method | |---|---| | EMAIL, IPV4, IPV6, URL | pattern | | CREDIT_CARD | pattern + Luhn checksum | | IBAN | pattern + ISO 7064 mod-97 checksum | | SSN (US), PHONE | pattern (+ digit-count check for phone) | | JWT, AWS_ACCESS_KEY, API_KEY | pattern (common prefixes) |

Detection favors precision where a checksum exists and recall elsewhere. Limit or widen it with --include / --exclude (e.g. --include EMAIL,PHONE).

How reversibility works

redact emits tokens like [EMAIL_1] and a vault:

{
  "version": 1,
  "createdAt": "2026-01-01T00:00:00.000Z",
  "nonce": "9f3a2b7c",
  "entries": [
    { "token": "[EMAIL_1_9f3a2b7c]", "type": "EMAIL", "value": "[email protected]" }
  ]
}

The same original value always maps to the same token (pass a vault back into redact to keep tokens stable across calls). Each vault carries a random nonce that is embedded in every token (e.g. [EMAIL_1_9f3a2b7c]) so a placeholder can never collide with token-shaped text that already exists in your input. restore replaces tokens with their values, longest-token-first so names never collide as substrings.

The vault contains your original secrets. Treat it as sensitive: store it separately from the redacted text and never send it to a model.

Limitations

  • Heuristic detection: unusual PII formats, names, and addresses without a structured pattern are not caught. This is a filter, not a guarantee.
  • The proxy inspects request/response bodies; it does not redact values placed in the URL/query string (the request path is forwarded upstream as-is).
  • Body redaction walks string values; PII sent as a bare JSON number is not redacted.
  • Detection runs on text; binary request bodies (e.g. audio/multipart uploads) are rejected with 415 rather than forwarded unredacted.
  • Tokens are stable within a shared vault (reuse a vault for cross-call stability); independent runs use a fresh random nonce, so tokens differ between runs by design.

Development

npm run build      # tsc -> dist/
npm test           # build + vitest
npm run test:watch

License

MIT