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

hushenv

v0.4.0

Published

Local secret manager for the agent era - encrypted vault, {hushenv.X} refs in .env, plaintext only at runtime.

Downloads

948

Readme

hushenv

npm version CI OpenSSF Scorecard license node provenance

Keeps your secrets hush-hush 🤫 — a local secret manager for the agent era, starting with your .env.

Your .env files hold references, not secrets:

NEXTAUTH_URL=http://localhost:3000
DATABASE_URL=postgres://app:{hushenv.DB_PASSWORD}@localhost:5432/app
RESEND_KEY={hushenv.RESEND_KEY}

Real values live AES-256-GCM-encrypted in ~/.hushenv/vault.json, with the master key in your OS keychain (macOS Keychain / Windows Credential Manager). Plaintext exists in exactly one place: the child process environment, in memory, at hushenv run time. The .env file is safe to commit and safe for AI agents to read.

Quickstart

npm i -g hushenv

hushenv init                       # master key -> OS keychain, empty vault
hushenv set DB_PASSWORD            # hidden prompt
hushenv set RESEND_KEY --stdin     # or pipe it in
hushenv run -- pnpm dev            # resolves refs from ./.env, injects, runs
hushenv run -f .env.local -- pnpm dev

Migrating an existing .env

Already have a populated .env? import moves the real values into the vault and rewrites the file to refs, in one step:

hushenv import --dry-run            # preview: what gets vaulted vs left literal
hushenv import                      # interactive: pick which values to vault
hushenv import --all                # non-interactive: take the heuristics

It vaults values that look like secrets and leaves config (e.g. NEXTAUTH_URL=http://localhost:3000) literal — review the picks in the interactive prompt or with --dry-run. Re-running is a safe no-op (refs are skipped). Two things to know:

  • It vaults whole values. A secret embedded in a larger string (e.g. the password inside a DATABASE_URL) is vaulted whole or skipped — split those by hand into their own {hushenv.X} ref.
  • If the .env was ever committed, the old plaintext is in your git history — rotate those secrets after importing.

Commands

| Command | What it does | |---|---| | hushenv init | Create the master key (keychain) and an empty vault | | hushenv set <name> [value] | Store a secret. Hidden prompt by default; --stdin to pipe. Positional value is discouraged (shell history). | | hushenv get <name> | Reveal a value. Requires an interactive TTY + confirmation; --force to bypass (use sparingly). | | hushenv ls | List names and update dates. Never values. | | hushenv rm <name> | Delete a secret | | hushenv mv <old> <new> | Rename a secret (alias: rename). Re-encrypted under the new name; --force to overwrite. | | hushenv import [-f file] | Migrate plaintext values from an .env into the vault, rewriting them to refs. --dry-run, --all, --force/--skip-existing, --prefix. | | hushenv run [-f file]... -- <cmd> | Resolve refs and run the command with secrets injected | | hushenv log [--verify] | Show the append-only audit log (names/metadata, never values); --verify checks the tamper-evident chain. --tail <n>, --json. |

Reference syntax: {hushenv.NAME} — whole-value or embedded inside a larger string. {mysm.NAME} and {mysmtool.NAME} are accepted as legacy aliases.

Use with your stack

hushenv run injects resolved secrets into the environment of any child process — your app's language doesn't matter:

hushenv run -- <your dev command>

Per-stack recipes with the framework-specific details:

| Stack | Guide | |---|---| | Next.js | docs/nextjs.md | | NestJS | docs/nestjs.md | | Express / plain Node | docs/express.md | | Vite | docs/vite.md | | Python (FastAPI / Django / Flask) | docs/python.md | | Go | docs/go.md | | PHP / Laravel | docs/php-laravel.md | | Ruby / Rails | docs/ruby-rails.md | | Rust | docs/rust.md |

They all work for the same reason: every mainstream dotenv loader (Node dotenv, python-dotenv, godotenv, phpdotenv, dotenv-rails, dotenvy) refuses to overwrite environment variables that already exist — and hushenv sets the real values before your app starts. Your framework keeps its .env loading; the ref strings in the file are simply never used.

Semantics

  • Multiple -f files: loaded in order, the first occurrence of a key wins.
  • Existing process.env variables are not overridden by file values (dotenv convention).
  • Missing refs fail fast before your app starts, with the exact hushenv set commands to fix it. Exit code 2.
  • Exit codes: 0 ok · 1 error · 2 missing secret.

How it compares

| | Plaintext on disk | .env safe to commit | Agent-safe .env | Works offline | Price | |---|---|---|---|---|---| | plain .env + dotenv | yes 😬 | no | no | yes | free | | hushenv | no — AES-256-GCM vault, key in OS keychain | yes — refs only | yes | yes | free | | dotenvx | no — ciphertext in .env | yes — ciphertext | partly — private key sits in .env.keys | yes | free core, paid sync | | 1Password op run | no | yes — op:// refs | yes | mostly | subscription | | cloud secret managers | no | n/a | yes | no | usage-based |

Honest take: if your team needs shared secrets today, dotenvx sync or a cloud manager solves that and hushenv doesn't yet — team sync is what hushenv Cloud (closed-source, paid) will add on top of this free core.

No keychain? (CI, containers)

Set the master key via the environment instead:

export HUSHENV_MASTER_KEY="<32 bytes, base64>"

hushenv init prints exactly this fallback if no OS keychain is reachable.

Security model — honest version

What this protects against:

  • Agents or tools reading secrets from .env files (they only see refs)
  • Secrets leaking into git history
  • Vault file theft without the OS keychain (ciphertext only)
  • Ciphertext swapping between entries (AES-GCM AAD binds value to name)

What it does not protect against:

  • hushenv run -- env prints that project's resolved secrets — scoping arrives with per-project grants in v1
  • hushenv get --force from a non-interactive shell — pair it with an agent deny rule, e.g. Bash(hushenv get*) in Claude Code settings
  • Malware running as your user with an unlocked keychain — same limit as any local secret manager
  • Deletion or truncation of the audit log by anything with filesystem access — see below

Audit log

Every action (init/set/get/rm/mv/import/run) is appended to ~/.hushenv/audit.lognames and metadata only, never secret values.

hushenv log                # recent activity (never values)
hushenv log --verify       # check the tamper-evident chain

Each entry is chained to the previous one with an HMAC-SHA256 keyed by your master key, so entries can't be forged or edited without the key (which lives in your OS keychain). Honest limit: the chain proves contents weren't altered, but it can't stop something with filesystem access from deleting or truncating the log — the same "malware running as you" boundary above. Real deletion-resistance needs an off-box anchor (a trusted external timestamp or remote append-only collection); that belongs to hushenv Cloud, not the offline core.

Repo layout

packages/vault-core   engine: crypto, keychain, vault storage (name-agnostic)
apps/cli              the hushenv CLI: ref resolution, run, prompts

vault-core never imports anything env-file- or CLI-specific. Future surfaces (tray UI, MCP broker) sit on the same engine.

Contributing

PRs welcome — it's a small, readable codebase. Setup, tests, and how releases work are in CONTRIBUTING.md. Contributions are licensed under Apache-2.0.

Roadmap

v1: per-project grants with strict mode (import and the append-only audit log have shipped). v2: secret versions, rotation warnings, tray UI.