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

macvault

v0.1.0

Published

macOS Keychain-backed secrets over a local Vault-like API and CLI.

Readme

MacVault

MacVault is a macOS-only proof of concept that exposes selected Keychain items through a tiny Vault-like API, a remote-friendly CLI, and a local React console. Keychain remains the only source of truth.

Threat Model

MacVault is designed for a single operator with a trusted Mac and a remote VPS connected over Tailscale.

  • Transport security is delegated to Tailscale. Do not expose this service to the public internet.
  • Every /v1/* endpoint requires Authorization: Bearer <KCV_TOKEN>.
  • Bearer token checks compare SHA-256 digests with crypto.timingSafeEqual so unequal-length and unequal-byte cases share the same hash-then-compare path.
  • The server refuses 0.0.0.0 / :: binds and refuses any hostname that resolves outside 127.0.0.1, ::1, the Tailscale CGNAT range 100.64.0.0/10, or fd7a:115c:a1e0::/48. Set KCV_ALLOW_UNSAFE_HOST=1 to override (do not).
  • Incoming requests are rejected if their Host header is not in the allowlist (loopback + the configured bind + any KCV_HOST_ALIASES entries). This kills DNS rebinding attacks against 127.0.0.1.
  • Responses ship strict Content-Security-Policy, X-Frame-Options: DENY, Referrer-Policy: no-referrer, and X-Content-Type-Options: nosniff.
  • Request logs include method, path, status, and duration only. Secret values, bearer tokens, and request bodies are never logged. Secret names in /v1/secrets/:name paths are replaced with a 12-char SHA-256 prefix in logs.
  • The server keeps an internal index (macvault-meta.index Keychain entry) and never calls dump-keychain, so it has no read scope over unrelated Keychain items.
  • macOS Keychain ACLs still gate access by the security process and may prompt on first read.

TLS is intentionally out of scope for this POC because Tailscale is the transport boundary.

Install On The Mac

./scripts/install.sh

The installer builds the React console, compiles the Bun binary, installs a LaunchAgent, generates or reuses a 48-byte bearer token in Keychain, and prints a local curl test.

The LaunchAgent does NOT store the bearer token in its plist. It sets KCV_TOKEN_FROM_KEYCHAIN=1, and the binary loads the token from the macvault-meta.token Keychain entry at startup. The plist is also installed mode 0600. Retrieve the token at any time with:

security find-generic-password -s macvault-meta.token -a default -w

Install With npm

The npm package installs the macvault command and requires Bun on the target Mac because the CLI entrypoint runs TypeScript through Bun.

npm install -g macvault
macvault --help

For a manual local server run:

export KCV_TOKEN="$(openssl rand -base64 48 | tr '+/' '-_' | tr -d '=')"
macvault serve

The npm package includes the built React console under dist/client. Run bun run build:package before packing or publishing so those assets are fresh.

CLI On A VPS

Copy the compiled binary to the VPS:

scp dist/macvault user@vps:/usr/local/bin/macvault

Create ~/.config/macvault/config.toml on the VPS:

url = "http://your-mac.tailnet-name.ts.net:7331"
token = "paste-token-from-installer"

Then use stdin-first writes so secrets do not land in shell history:

echo "sk-..." | macvault set openai_key
macvault get openai_key --raw
macvault list
macvault rm openai_key

CLI config resolution order is flags, then MACVAULT_URL / MACVAULT_TOKEN, then ~/.config/macvault/config.toml.

API

All endpoints except /health require Authorization: Bearer <KCV_TOKEN>.

GET    /health
GET    /v1/secrets
GET    /v1/secrets/:name
PUT    /v1/secrets/:name      { "value": "secret", "account": "optional" }
DELETE /v1/secrets/:name

Bodies are validated with strict Zod schemas, so unknown fields are rejected.

React Console

After install, open:

http://127.0.0.1:7331

By default the console holds the bearer token in memory only — it is lost on reload. Enable "Keep token for this tab only" to persist it in sessionStorage (per-tab, never localStorage); closing the tab purges it.

Binding To Tailscale

Keep the default loopback bind for local-only operation:

KCV_HOST=127.0.0.1 macvault serve

To listen directly on your Tailscale address, set KCV_HOST to that specific interface IP or DNS-resolved address. Never use 0.0.0.0. The server validates that the resolved address falls inside loopback or the Tailscale CGNAT range and refuses to start otherwise.

KCV_HOST=100.x.y.z KCV_TOKEN="..." macvault serve

If you bind to a Tailscale interface, also set KCV_HOST_ALIASES to the additional Host: headers clients will send (typically your tailnet DNS name). Requests with any other Host header are rejected with 403 forbidden_host:

KCV_HOST=100.x.y.z \
KCV_HOST_ALIASES=your-mac.tailnet-name.ts.net \
KCV_TOKEN_FROM_KEYCHAIN=1 \
macvault serve

First-Run Keychain ACL Gotcha

macOS may prompt the first time the launchd-spawned binary reads each Keychain item. Either run macvault serve interactively once and click "Always Allow", or add the installed binary to each item's ACL with the security CLI -T option.

Development

bun install
bun run dev:server
bun run dev
bun test
bun run typecheck
bun run build

Build output:

  • UI: dist/client
  • Binary: dist/macvault

Npm publishing smoke check:

bun test
bun run typecheck
bun run build:package
npm run pack:dry-run