What the agent may run
hush install-skill # this project
hush install-skill --global # every project
Installs a skill telling your agent never to ask for a pasted key, to use
hush_run rather than reading values, and how to pick a set when you name
one. It goes where each agent looks for instructions — the right-hand column
of the table in Connecting your agent. Codex, Gemini CLI and Zed share .agents/skills/ (and
~/.agents/skills/ for --global), so one file serves all three. Without it the tools still work — the tool
descriptions explain themselves — you just have to say so each time.
.hush/policy.json controls what it may run — through the MCP tools and
through the CLI, so an agent that shells out to hush run or hush export
meets the same approval prompt. For the agent's tools, anything that exists to
dump or re-encode the environment is denied outright — shells, env, base64,
curl, and every interpreter, because node -e can write the whole environment
to a file that output redaction never sees. In your terminal the same commands
are not refused: hush node server.js goes to the approval prompt with a
warning line, the way op run asks rather than blocks. allowCommands still
narrows both:
{
"allowCommands": [],
"denyCommands": ["your-own-additions"],
"unsafeAllowCommands": [],
"allowEnvs": ["default", "work-fal"],
"allowHosts": ["api.stripe.com", "*.github.com"],
"denyKeys": ["STRIPE_LIVE_KEY"],
"maxRunMs": 120000,
"approvalScope": "command"
}
denyCommandsis added to the built-in list, never substituted for it — an old config cannot hold you below the current floor.unsafeAllowCommandsis the only way below that floor. Named to be off-putting: allowingnodeorbashlets an agent read every injected secret and write it anywhere.allowEnvsnames the sets an agent may use — by the name you gave them, wherever they live — so["default", "work-fal"]keeps an agent out ofclient-fal.allowHostsbounds wherehush requestandhush_requestmay send a credential. Empty means any host over https. Entries are a bare host (api.stripe.com), a host with a port (localhost:3000), or a subdomain glob (*.example.com, which does not match the apex). It is the one control that decides where a secret goes, which no command or set rule can express: without it, a set allowed forapi.stripe.comis equally allowed for an attacker's collector.allowCommands, if non-empty, is an allowlist — the only command control that actually holds. Prefer it for anything sensitive.requireApprovallists what a human must approve on screen:run,add,reveal, andrequest.--materializeis gated byreveal, notrun, because it writes plaintext to a path the caller chose.approvalScopeis what "Allow 15 min" covers:"command"(the default) means that command with those sets;"sets"means any allowed command with those sets, if you find the prompts too frequent.approvalTtlSecondsis how long an "Allow" lasts (default 900 = 15 minutes), counted inside the process that asked — the MCP server and the app keep it, a one-shothushcommand does not. Change it in the app's Agent section, or withhush secure approval --for 30m, rather than by hand.
Your floor. policy.json is a file in the repo, so an agent with write
access can edit it. ~/.hush/policy.json — same shape, outside every repo —
is your floor: a repo's policy can only tighten relative to it. allowCommands,
allowEnvs and allowHosts can only narrow, requireApproval and denyKeys
can only grow, biometry and approvalScope can only get stricter, and
unsafeAllowCommands only takes effect when your floor lists the same command
— the repo asks, you permit. unmaskKeys is floor-only as well: it is the list
of keys you have allowed to print unmasked, and a repository cannot add to it.
hush doctor shows every place a repo policy tried to go below your floor.
An allow list your floor sets keeps applying even when a repo's policy.json
does not mention it. A repo file that omits allowCommands inherits your floor's
list rather than replacing it with "no restriction"; a repo file that names only
entries outside your floor is ignored as a whole. Both cases are reported by
hush doctor, so a floor that is doing nothing is never silent.