Skip to content

Sets

Everything in hush is a set: some keys, a name you chose, an optional description, and an optional note on when to use it. dev, prod, Personal fal, Acme Production — all sets. There is no second concept to learn.

A set lives in one of two places:

  • Your library — ~/.hush/vaults/<name>, yours alone, never in any repo. A key you use across projects lives here once, so rotating it is one edit.
  • This project — .hush/vault.json, committed, shared with your team.

A project uses sets. Its own default set is always used, as the floor; everything else layers on top in the order you added it, later wins.

Your library is a catalog, not a floor. Nothing in it reaches a folder until that folder asks: hush use <set>, or tell your agent which ones you want and it adds them. Its default set is your catch-all (hush add K=v --library with no --to lands there); use it in a folder with hush use default --library. Add more from the library any time. .hush/envs.json records only the names — a teammate who clones the repo gets “this project uses a set called acme-production” and supplies their own.

Because that list travels with the repository, it does not reach your library on its own. The first time a project you did not link yourself names one of your library sets, hush asks before using it (on the terminal, or in a dialog), once per project on this machine; until then the set is left out and hush says so. hush use <set> and the app’s “Use here” count as confirming, and hush use --confirm confirms the sets a cloned project already lists. The confirmation is kept in ~/.hush, where no repository can write it.

Terminal window
hush add .env.production --as "Acme Production" --library \
--description "Live Stripe + Convex" --when "deploys only"
hush add DATABASE_URL=postgres://… --to "Acme Production" # one value into a set
hush add fal --as "Personal fal" --library # a known service: asks for FAL_KEY, hidden
hush use acme-production # this project uses it
hush use # what this project uses, in order
hush use --not acme-production

A set you make from inside a project is used by that project automatically (--no-use to opt out), so hush add .env --as Dev followed by hush npm run dev just works.

$ hush ls
YOUR LIBRARY (global)
● Acme Production (acme-production) 12 key(s)
Live Stripe + Convex
when: deploys only
Personal fal (personal-fal) 1 key(s)
THIS PROJECT
● default (default) 2 key(s)
● = used by this project.

hush ls <set> lists one set’s key names — never values.

Everything already in one pile? That is where everyone starts. Make the sets you want and move keys across — the value is re-encrypted under its new name, so it is a real move rather than a relabelling:

Terminal window
hush env move STRIPE_SECRET_KEY DATABASE_URL --to "Acme Production"

Renaming works properly. hush env rename acme-production "Acme Prod EU" re-seals every value under acme-prod-eu and updates any project using the old name. Nothing is left pointing at a name that no longer exists.

Values are cryptographically bound to their set: a staging ciphertext cannot be moved into the prod slot, even by someone editing the JSON by hand.