Skip to content

hq-secrets

hq-secrets is a capability of the hq CLI, not a standalone repo. It operates against the encrypted vault provided by hq-pro.

hq-secrets is how HQ handles credentials safely. Secrets live in AWS SSM Parameter Store behind the HQ vault, and the CLI injects them into your commands as environment variables — it never prints the values. Access is Cognito-authenticated and governed by per-secret ACLs.

When to use it

  • Repos with a committed .env.schema → use hq run (the recommended path).
  • One-off or scripted invocations without a schema → use hq secrets exec.
  • A credential the agent should never see (vendor keys, personal tokens) → use hq secrets generate-link to collect it from a human.

Schema-driven workflow: hq run

For repos that commit a .env.schema, hq run discovers the schema by walking up to the repo root, batch-fetches every hq()-declared secret in a single request, and spawns your command with them injected as env vars — no --only list to maintain, and values are never printed.

# .env.schema (committed)
# @hqCompany("indigo")
NODE_ENV=development # non-sensitive, passed straight through
# @required
DATABASE_URL=hq() # var name == secret name
# @required
DB_URL=hq("INDIGO_NX/DB_URL") # explicit secret-name override
# @optional
SENTRY_DSN=hq() # skipped if missing / no ACL access
Terminal window
hq run -- npm run dev
hq run --check # resolve + report without spawning a child
hq run --company indigo -- node script.js

A gitignored .env.local overrides any schema value locally.

One-off injection: hq secrets exec

Terminal window
hq secrets exec --only DATABASE_URL,API_KEY -- npm run migrate
hq secrets exec --only AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY -- aws s3 ls

Values are fetched server-side, injected into the child process, and never written to stdout/stderr. The --only flag is required — there is no “inject all” mode. Results cache locally (encrypted, 5-minute TTL).

Never-print-secrets discipline

The defining rule of this capability: the safe path is the easy path.

  • hq run / hq secrets exec inject secrets into a child process; the CLI itself prints nothing.
  • hq secrets get <PATH> redacts the value by default; --reveal is a deliberate human-in-the-loop escape hatch, not for automation.
  • hq secrets env (sourcing into a shell) has a TTY guard — it prints [REDACTED] when stdout is a terminal, emitting real values only into a pipe / process substitution.
  • Do not capture exec output, and do not run value-printing commands (env, printenv, echo $SECRET) inside it.

These are prompt-level guidelines reinforced by CLI design, not absolute technical enforcement — a child process deliberately built to print its environment can still expose values. The contract is: don’t.

Scoping and ACLs

ScopeFlagSharing
Company (shared)default / --company <slug>per-secret ACLs + groups
Personal--personalowner-only, no sharing surface

Each company secret has an ACL with read / write / admin permissions. The creator is implicitly admin (non-revocable). New secrets are restricted by default (creator-only); an open flag grants company-wide read. Grants can target an individual or a group (group membership changes adjust access without touching the ACL).

Terminal window
hq secrets acl PROD/DB_PASSWORD # who has access
hq secrets share PROD/DB_PASSWORD --with alice@example.com --permission read
hq secrets unshare PROD/DB_PASSWORD --from alice@example.com
hq groups create grp_backend --name "Backend team"
hq secrets share PROD/DB_PASSWORD --with grp_backend --permission read

You need admin on a secret to share / unshare it. Widening to admin or setting open is a privilege escalation — confirm with a human first.

Collecting human-supplied credentials

When a secret should reach the vault without the agent ever seeing it, generate a single-use submission link:

Terminal window
hq secrets generate-link VENDOR_API_KEY --expires 1h

The human opens the URL and enters the value, which goes straight to SSM. The resulting URL is a single-use capability — surface it only as a Markdown inline link (label free of the token), never as bare text, and never echo it again in any later turn or persisted artifact. Use the redacted form https://hq.{co}.com/secrets-input/<TOKEN_REDACTED> everywhere after minting.

  • hq-cli — the CLI that ships this capability
  • hq-pro — the vault and identity it operates against
  • hq-share — single-use vault share-session links