https://github.com/mrz1836/hush
π€« Discord-gated secrets broker for AI agents β encrypted vault, JWT sessions, Tailscale-only
https://github.com/mrz1836/hush
bip32 bitcoin crypto discord go jwt secrets security tailscale
Last synced: about 1 month ago
JSON representation
π€« Discord-gated secrets broker for AI agents β encrypted vault, JWT sessions, Tailscale-only
- Host: GitHub
- URL: https://github.com/mrz1836/hush
- Owner: mrz1836
- License: mit
- Created: 2026-04-26T15:47:48.000Z (2 months ago)
- Default Branch: master
- Last Pushed: 2026-05-20T19:44:39.000Z (about 1 month ago)
- Last Synced: 2026-05-20T19:47:35.125Z (about 1 month ago)
- Topics: bip32, bitcoin, crypto, discord, go, jwt, secrets, security, tailscale
- Language: Go
- Homepage:
- Size: 4.31 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
- Security: .github/SECURITY.md
- Support: .github/SUPPORT.md
- Agents: .github/AGENTS.md
Awesome Lists containing this project
README
# π€«Β Β hush
**Discord-gated secrets broker for AI agents**
One passphrase. No key files. No dotfiles on agent disks.
### Project Navigation
πΒ Installation
β‘Β QuickΒ Start
πΒ Documentation
πΒ Security
π οΈΒ CodeΒ Standards
π§ͺΒ ExamplesΒ &Β Tests
π€Β AIΒ Usage
βοΈΒ License
π€Β Contributing
π₯Β Maintainers
**hush is a single Go binary that keeps every API key, OAuth token, and
service credential encrypted on a single trusted host. Agents request
short-lived, scoped sessions over Tailscale; the request is approved on
your phone via Discord; approved secrets are delivered ECIES-encrypted
end-to-end and injected into the agent process's environment β never
written to disk on the agent machine.**
If your dev workflow runs untrusted code (npm/pip packages, LLM-generated
scripts, AI-agent tools that execute shell commands) and your secrets
currently live in shell rc files or cloud-provider credential files, hush
is for you. Vault, 1Password CLI, and dotfile-based env vars all leave
files on disk that commodity malware grep for first. hush makes those
files not exist.
```
TAILSCALE MESH
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β ββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββ β
β β AGENT MACHINE β β VAULT HOST β β
β β (untrusted, clean disk) β β (mlocked memory; offline) β β
β β β β β β
β β interactive client / β β vault server β β
β β supervisor β β β β
β β β β β β² β β
β β β ECDSA-signed βββββββΌβββββββΊβ verify signature β β
β β β claim β β β check Tailscale IP β β
β β β β β βΌ β β
β β β β β Discord DM ββββββΊ phone β β
β β β β β β [Approve] β β
β β β ES256K JWT βββββββΌββββββββ€ issue scoped JWT β β
β β β β β βΌ β β
β β β secret fetch βββββββΌβββββββΊβ ECIES-encrypt to β β
β β β (ECIES bytes) β β β ephemeral pubkey β β
β β βΌ β β β β β
β β decrypt β env var β β ββββββββββββββββββββββ β β
β β inject into child β β [no key files anywhere] β β
β ββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
## π Installation
**hush** requires a [supported release of Go](https://golang.org/doc/devel/release.html#policy)
(Go 1.26+) and is built `CGO_ENABLED=0` β a single static binary.
> **Status:** this is still `ALPHA` and PR's are welcome to improve the project.
Prerequisites: a vault host and an agent host on the same Tailscale
tailnet, plus a Discord bot you control
() for the approval channel.
### Build from source
```bash
git clone https://github.com/mrz1836/hush.git && cd hush
magex build && sudo install -m 0755 cmd/hush/hush /usr/local/bin/hush
```
### Upgrade
Once `hush` is on your `PATH`, the binary can upgrade itself in place
from the [GitHub releases](https://github.com/mrz1836/hush/releases):
```bash
hush upgrade # download the latest release tarball, verify SHA-256, install in place
hush upgrade --check # report the latest available version without installing
hush upgrade --force # reinstall the latest release even when already current
```
Channel selection is controlled by the `UPDATE_CHANNEL` environment
variable (case-insensitive; default `stable`):
```bash
UPDATE_CHANNEL=stable hush upgrade # latest non-prerelease (default)
UPDATE_CHANNEL=beta hush upgrade # latest prerelease, falls back to stable when none
UPDATE_CHANNEL=edge hush upgrade # most recent release of any kind (excludes drafts)
# Or override the env per-invocation with --channel:
hush upgrade --channel beta
```
The install target is the resolved path of the running binary
(`os.Executable()` with symlinks evaluated β typically `$(which hush)`).
`hush upgrade` requires write access to that directory; when the
directory is not writable the command exits with a clear error naming
the directory rather than silently installing elsewhere. Re-run the
command under `sudo` (or copy the new binary into place manually) when
that happens.
After a successful upgrade `hush upgrade` prints a `Restart any
running 'hush serve' to pick up the new version` reminder β the
upgrade does not touch any supervised process.
## πΊοΈ Command palette
Every hush subcommand at a glance β every entry below is real today.
| Command | Purpose |
|---------|---------|
| `hush smoke` | Guided end-to-end test with a fake secret β start here |
| `hush init server` / `hush init client` | Bootstrap a vault host / enroll an agent host |
| `hush serve` | Run the vault server (Tailscale-only) |
| `hush secret add` / `list` / `remove` / `rotate` | Manage vault entries (rotate re-encrypts and hot-reloads) |
| `hush vault rekey` | Change the vault passphrase β rotates the root of trust (TTY-only) |
| `hush request --exec β¦` | One-shot interactive fetch + child exec |
| `hush supervise ` | Long-running daemon with grace cache + validators |
| `hush health` / `server-url` / `version` | Daily-driver helpers |
| `hush revoke --jti β¦` | Kill an active session token |
| `hush upgrade` | Self-upgrade from a GitHub release (stable / beta / edge) |
Global flags β `--config `, `--verbose`, `--quiet`, `--no-color` β work on every command.
## β‘ Quick Start
Four flows, in the order you'll use them.
### Try it in 60 seconds
**One command, fake secret, real Discord approval:**
```bash
hush smoke --state-dir ~/.hush-smoke --reset
```
`hush smoke` walks the setup prompts, creates an isolated test vault, adds
`HUSH_SMOKE_TEST=hello-from-hush`, starts a temporary Tailscale-only server,
enrolls a client, asks you to approve in Discord, verifies the fake secret,
and shuts the temporary server down.
> π§Ή **Cleanup:** `hush smoke clean` archives smoke artifacts by default.
> Add `--destroy --confirm 'destroy smoke'` to permanently delete them.
### Bootstrap the vault host
Three commands, run on the host you trust with your secrets.
```bash
hush init server # interactive preflight + prompts
hush secret add ANTHROPIC_API_KEY # then OPENAI_API_KEY, GEMINI_API_KEY, β¦
hush serve # binds Tailscale, brokers approvals
```
> π°οΈ **Listen on the vault host's Tailscale IPv4 β not your laptop IP.**
> When `hush init server` asks for a listen address, run
> `printf '%s:7743\n' "$(tailscale ip -4)"` on the **server** host and paste
> the result. Set `discord_approval_channel_id` to route approvals to a
> channel; leave it empty to DM the owner directly.
> π **macOS Keychain locked?** Choose the env-token fallback during init
> and run `hush serve` with `HUSH_DISCORD_BOT_TOKEN` exported in that
> terminal. Full recovery flow in [`docs/SECURITY.md`](docs/SECURITY.md) Β§2.4.
### Enroll the agent host
Enroll a per-machine client key, then fetch secrets straight into a child
process. Nothing lands on disk.
```bash
hush init client --machine-index 1
HUSH_SERVER="$(hush --config ~/.hush/config.toml server-url)"
hush request \
--server "$HUSH_SERVER" \
--machine-index 1 \
--scope ANTHROPIC_API_KEY --scope OPENAI_API_KEY --scope GEMINI_API_KEY \
--max-uses 3 --ttl 10m \
--reason "claude-code session" \
--exec zsh
```
Approve on Discord; the shell you launched inherits all three keys in its
environment β and **only there**. They are zeroed the moment the shell exits.
> βοΈ **`--scope` is repeatable and comma-separated.** Either
> `--scope A --scope B` or `--scope A,B` works. `--max-uses` must be β₯ the
> number of scopes (one fetch per scope per session). `--exec` names a
> program, not a shell string β pass child arguments after `--`.
### Run a long-running daemon
For agents that run overnight, swap `hush request` for `hush supervise`.
One approval per refresh window keeps a 24/7 child alive across crashes;
the grace cache silently restarts a child that dies inside
`cache_grace_ttl`, so a 3am OOM doesn't page you.
Save the snippet below to `~/.hush/supervisors/hermes.toml` β the full
schema lives in
[`deploy/examples/supervisors/example-daemon.toml`](deploy/examples/supervisors/example-daemon.toml):
```toml
name = "hermes"
reason = "Hermes AI gateway"
server_url = "http://100.64.0.1:7743/h/example"
client_machine_index = 1
session_type = "supervisor"
requested_ttl = "20h"
refresh_window = "09:00-10:00"
cache_secrets_for_restart = true
cache_grace_ttl = "60m"
status_socket = "/tmp/hush/supervise-hermes.sock"
pid_file = "/tmp/hush/supervise-hermes.pid"
scope = ["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GEMINI_API_KEY"]
[child]
command = ["/usr/local/bin/hermes", "gateway", "start"]
[validators]
ANTHROPIC_API_KEY = "anthropic"
OPENAI_API_KEY = "openai"
GEMINI_API_KEY = "google-ai"
```
Then:
```bash
hush supervise ~/.hush/supervisors/hermes.toml --dry-run # validate the config
hush supervise ~/.hush/supervisors/hermes.toml # run for real
```
Built-in validators (`anthropic`, `anthropic-oauth`, `openai`, `google-ai`,
`github`) hit each provider before the child starts β stale credentials
fail loudly instead of breaking your daemon at 3am. Full guide in
[`docs/DAEMONS.md`](docs/DAEMONS.md).
> π **More?** [`docs/OPERATIONS.md`](docs/OPERATIONS.md) covers Keychain
> ACL recovery, clock-skew overrides, and `--non-interactive` mode for
> Terraform/Ansible provisioning. [`docs/CONFIG-SCHEMA.md`](docs/CONFIG-SCHEMA.md)
> has the full server + supervisor TOML schemas, and
> [`deploy/examples/supervisors/`](deploy/examples/supervisors/) holds
> production templates ready to copy.
## At a glance
**What hush does:**
- Keeps every secret encrypted in a single AES-256-GCM + Argon2id (256MB) vault file on one trusted host.
- Requires phone approval (Discord DM with interactive buttons) for every fresh session.
- Delivers secrets ECIES-encrypted end-to-end into agent process memory only β no disk writes on the agent.
**What hush explicitly does NOT do (v0.1.0):**
- No multi-owner approvals (a single configured operator approves; multi-owner is post-v0.1.0 future scope).
- No cloud KMS / SaaS dependency. The vault is self-hosted and offline-capable.
- No public network exposure. The vault server is bound to a Tailscale interface and refuses to start otherwise.
**Daily-driver helpers:**
- `hush health --server "$(hush server-url)"` β one-shot reachability + clock-skew check.
- `hush secret list` β enumerate vault entries (TTY: `NAME β description`; pipe-friendly).
- `hush secret rotate` β re-encrypt the vault and hot-reload `hush serve` (SIGHUP, no downtime).
- `hush vault rekey` β change the vault passphrase itself; snapshots the old vault and prints a restart-required reminder. See [`docs/VAULT-REKEY.md`](docs/VAULT-REKEY.md).
- `hush server-url` β print the canonical server URL from your TOML config, perfect for `$(β¦)` substitution.
- `hush revoke --jti ` β kill an active JWT before its TTL expires.
## π Operating modes
Two ways to consume secrets; pick by **how often you can answer your phone**.
| Mode | Best for | Approval cadence |
|------|----------|------------------|
| `hush request --exec` | Interactive shells, one-shot scripts, CI jobs | Once per invocation |
| `hush supervise` | 24/7 daemons, AI gateways, long-running agents | Once per refresh window (e.g. 09:00β10:00 daily) |
Pick `request` for ad-hoc work; pick `supervise` when a phone buzz per
restart would page you at 3am.
### Why hush exists
When untrusted code lands on a developer machine β via npm/pip
supply-chain attacks, LLM-generated scripts, or trojans masquerading as
tools β the very first thing it does is enumerate known credential
patterns in known files: shell rc files, cloud-provider credential
files, `.env` files, signing keys, and PEM files.
**hush exists to make this enumeration return nothing.** Secrets stay
encrypted on a single trusted host. Agents fetch them only after a human
approves the request from a phone. Approved secrets are delivered into
process memory and zeroed when the process exits. Nothing on disk.
For the full threat model, see [`docs/SECURITY.md`](docs/SECURITY.md).
### Architecture summary
hush is a single Go binary playing three roles:
- **Vault server** β holds the encrypted vault file in mlocked memory;
issues ES256K-signed JWTs after Discord approval; ECIES-encrypts
secret responses to the client's per-session ephemeral public key;
exposes a tiny HTTP API over Tailscale only.
- **Interactive client** β ECDSA-signs a claim with a per-machine
BIP32-derived key; receives a JWT after approval; fetches and
decrypts secrets; injects them into a child process's environment.
- **Supervisor** β long-lived per-daemon process that holds the JWT and
ephemeral ECIES key in mlocked memory across child crashes/restarts
within the session TTL; runs validators before child start; exposes a
Unix status socket for agent-visible freshness queries.
**Seven security layers** stack independently β compromise of any single
layer does not enable secret extraction:
1. **BIP32 HD key hierarchy** β all keys derived at runtime from a
single passphrase. **Zero key files on disk.**
2. **ES256K asymmetric JWT signing** β only the server can sign;
leaking the public key does not enable forgery.
3. **ECIES end-to-end secret transport** β secrets are encrypted to a
per-session ephemeral pubkey; captured HTTP traffic shows binary
blobs.
4. **ECDSA-signed client requests** β every claim and revocation is
signed with a registered per-machine client key.
5. **mlocked secure memory** β `SecureBytes` containers; secrets never
stored as Go `string`; explicit zeroing on shutdown.
6. **Signed hash-chained audit log** β every event ECDSA-signed; chain
breaks on modification.
7. **Obscurity** β random API path prefix, custom vault file format,
non-obvious binary name. Additive only β never load-bearing.
The network perimeter is **Tailscale-only** (Constitution Principle VI).
Tailscale is the v0.1.0 mesh-VPN choice; the architecture does not depend
on it specifically β the requirement is "no public reachability" and
Tailscale satisfies it cleanly. The `Approver` interface is also
pluggable; **Discord is the v0.1.0 reference implementation** and the
only one that ships, but future Slack / Telegram / PagerDuty backends can
be wired without changing the rest of the system.
For the full architecture treatment, see [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
### Programmatic integration
AI agents that consume hush β Claude Code, Codex, custom Go daemons β
can integrate in-process via the
[`github.com/mrz1836/hush/pkg/client`](pkg/client/) SDK instead of
exec'ing the CLI. The SDK gives agents typed access to two surfaces:
**1. Supervisor freshness β `SupervisorStatus`** (read what the local
supervisor knows; no Discord roundtrip):
```go
import "github.com/mrz1836/hush/pkg/client"
sup := client.NewSupervisorStatus(os.Getenv("HUSH_STATUS_SOCKET"))
status, err := sup.Snapshot(ctx)
if len(status.ScopeStale) > 0 {
log.Fatal("refusing to run β stale scopes:", status.ScopeStale)
}
fmt.Println("session expires at:", status.SessionExpiresAt)
```
**2. Capability discovery β `Me()`** (ask the vault server *what
scopes exist* and *what does my current session look like*, signed
with the agent's enrolled client key, without burning a Discord
approval):
```go
resp, err := client.Me(ctx, client.MeRequest{
ServerURL: "http://100.64.0.1:7743/h/abcd1234",
ClientKey: myEnrolledPrivKey, // *ecdsa.PrivateKey
MachineName: "claude-code-laptop",
BearerJWT: os.Getenv("HUSH_BEARER"), // optional
})
if err != nil {
log.Fatal(err)
}
fmt.Println("scopes available:", resp.ScopesAvailable)
if resp.CurrentSession != nil {
fmt.Println("current jti:", resp.CurrentSession.JTI,
"expires:", resp.CurrentSession.ExpiresAt)
}
```
Together these let an agent plan: "do I already hold a fresh session
for this scope? when does it expire? what *could* I request if I need
more?" β all without touching the operator's phone.
See [`pkg/client/README.md`](pkg/client/README.md) for the full v1
surface. The SDK ships typed errors (`ErrSocketUnavailable`,
`ErrInvalidResponse`, `ErrRefreshDenied`, `ErrUnauthenticated`) so
callers can switch on them with `errors.Is`.
**3. Lifecycle events β `Watch()`** (reactive notification so an
agent can wind down BEFORE its credentials expire, instead of being
killed mid-task):
```go
events, _ := sup.Watch(ctx, client.WatchOptions{
PollInterval: 30 * time.Second,
ExpiryThresholds: []time.Duration{15 * time.Minute, 5 * time.Minute, 1 * time.Minute},
})
for ev := range events {
switch ev.Type {
case client.EventExpiresSoon:
if ev.Threshold <= time.Minute {
checkpoint(); shutdownCleanly()
}
case client.EventStateChange:
log.Info("supervisor state β", ev.Status.State)
case client.EventSessionRenewed:
log.Info("fresh JTI", ev.Status.SessionJTI)
}
}
```
`Watch()` emits `EventInitial`, `EventStateChange`,
`EventScopeHealthChange`, `EventSessionRenewed`, `EventExpiresSoon`
(once per configured threshold per session), and `EventError` for
transient poll failures. The channel closes on context cancel.
**Worked example**: a runnable program demonstrating all three SDK
calls (Snapshot, Me, Watch) plus the agent-context flags on `/claim`
lives at [`examples/agent/`](examples/agent/). See
[`docs/AGENT-INTEGRATION.md`](docs/AGENT-INTEGRATION.md) for the
complete agent integration guide.
### Tech stack
- **[Go 1.26+](https://go.dev/)** β single static binary, `CGO_ENABLED=0`
exclusively (Constitution Principle IX).
- **[decred/dcrd/dcrec/secp256k1/v4](https://github.com/decred/dcrd)** β
secp256k1 primitives used for ECDSA signing, ES256K JWTs, and ECIES
envelope encryption (Constitution Principle III).
- **[decred/dcrd/hdkeychain/v3](https://github.com/decred/dcrd)** β BIP32
HD key derivation from the operator passphrase (Constitution Principle
III); paired with stdlib `golang.org/x/crypto/argon2` for the KDF.
- **[Tailscale](https://tailscale.com/)** β the only network reachable to
the vault server. WireGuard underneath; identity-based ACLs above.
- **[Discord](https://discord.com/)** + **[discordgo](https://github.com/bwmarrin/discordgo)**
β phone-based approval channel; the v0.1.0 reference Approver.
- **[golang-jwt/jwt v5](https://github.com/golang-jwt/jwt)** β JWT framework;
hush registers a custom `ES256K` signing method.
- **[go-toml v2](https://github.com/pelletier/go-toml)** β strict TOML
parsing for server and supervisor configs.
- **[zalando/go-keyring](https://github.com/zalando/go-keyring)** β OS
keychain access with ACL support.
- **[cobra](https://github.com/spf13/cobra)** + **[pflag](https://github.com/spf13/pflag)** β
CLI subcommand routing and flag parsing.
The `SecureBytes` mlock pattern is custom-implemented in
`internal/vault/securebytes/`; the design is inspired by
[sigil](https://github.com/mrz1836/sigil) but takes no dependency on it.
## π Documentation
View the comprehensive documentation for hush:
| Doc | Purpose |
|-----|---------|
| [`docs/OPERATIONS.md`](docs/OPERATIONS.md) | Setup, day-to-day modes, `--non-interactive`, Keychain recovery |
| [`docs/VAULT-REKEY.md`](docs/VAULT-REKEY.md) | Vault passphrase rotation runbook: `secret rotate` vs `vault rekey`, Keychain follow-up, snapshot/rollback |
| [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) | Component model, trust boundaries, supervisor lifecycle |
| [`docs/SECURITY.md`](docs/SECURITY.md) | Threat model, 7 security layers, residual risks |
| [`docs/AGENT-INTEGRATION.md`](docs/AGENT-INTEGRATION.md) | SDK guide for AI agents: `pkg/client` Snapshot / Me / Watch + agent-context flags on `/claim` |
| [`docs/CONFIG-SCHEMA.md`](docs/CONFIG-SCHEMA.md) | Server + supervisor TOML schemas, defaults, validation |
| [`docs/DAEMONS.md`](docs/DAEMONS.md) | Supervisor pattern, refresh tuning, validator authoring |
| [`docs/API.md`](docs/API.md) | HTTP endpoint reference |
| [`docs/LIFECYCLE-SCENARIOS.md`](docs/LIFECYCLE-SCENARIOS.md) | 17 supervisor lifecycle scenarios β behavioral reference |
| [`docs/TAILSCALE-ACLS.md`](docs/TAILSCALE-ACLS.md) | Recommended ACL pattern restricting the vault port |
| [`docs/CLEAN-MACHINE.md`](docs/CLEAN-MACHINE.md) | Agent-machine cleanup checklist |
| [`.specify/memory/constitution.md`](.specify/memory/constitution.md) | The 11 non-negotiable principles |
## π Security
### Important Disclaimer
> β οΈ **Experimental Software β Use at Your Own Risk**
>
> hush is experimental, open-source software provided "AS-IS" without
> warranty. By running it, you acknowledge:
>
> - **Status:** ALPHA quality; expect bugs, edge cases, and breaking changes.
> - **No formal audit:** hush has not been professionally audited or
> penetration-tested.
> - **You own the host:** the trusted vault host, your Tailscale config, and
> your Discord bot are yours to secure β hush only does its part.
> - **No liability:** the authors accept no responsibility for compromised
> secrets, downtime, or damages.
>
> **Don't trust hush with a secret you can't afford to rotate.** If it breaks,
> you get to keep both pieces.
For the full threat model and the 7 security layers, see
[`docs/SECURITY.md`](docs/SECURITY.md). For security issues, see our
[Security Policy](.github/SECURITY.md) or contact: [hush@mrz1818.com](mailto:hush@mrz1818.com).
### Additional Documentation & Repository Management
Development Setup (Getting Started)
Install [MAGE-X](https://github.com/mrz1836/go-mage) build tool for development:
```bash
# Install MAGE-X for development and building
go install github.com/magefile/mage@latest
go install github.com/mrz1836/go-mage/magex@latest
magex update:install
```
Build Commands
View all build commands:
```bash
magex help
```
Common commands:
- `magex build` β Build the binary
- `magex test` β Run test suite
- `magex lint` β Run all linters
- `magex deps:update` β Update dependencies
Binary Deployment
This project uses [goreleaser](https://github.com/goreleaser/goreleaser) for
streamlined binary deployment to GitHub. To get started, install it via:
```bash
brew install goreleaser
```
The release process is defined in the [.goreleaser.yml](.goreleaser.yml)
configuration file. Then create and push a new Git tag using:
```bash
magex version:bump bump=patch push=true branch=master
```
This process ensures consistent, repeatable releases with properly versioned
artifacts.
GitHub Workflows
hush uses the **Fortress** workflow system for comprehensive CI/CD:
- **fortress-test-suite.yml** β Complete test suite across multiple Go versions
- **fortress-code-quality.yml** β Code quality checks (gofmt, golangci-lint, staticcheck)
- **fortress-security-scans.yml** β Security vulnerability scanning
- **fortress-coverage.yml** β Code coverage reporting to Codecov
- **fortress-release.yml** β Automated binary releases via GoReleaser
See all workflows in [`.github/workflows/`](.github/workflows/).
Updating Dependencies
To update all dependencies (Go modules, linters, and related tools), run:
```bash
magex deps:update
```
This command ensures all dependencies are brought up to date in a single step,
including Go modules and any managed tools. It is the recommended way to keep
your development environment and CI in sync with the latest versions.
## π§ͺ Examples & Tests
All unit tests run via [GitHub Actions](https://github.com/mrz1836/hush/actions).
View the [configuration file](.github/workflows/fortress.yml).
Run all tests (fast):
```bash
magex test
```
Run all tests with race detector (slower):
```bash
magex test:race
```
### Test Coverage
View coverage report:
```bash
magex test:coverage
```
Coverage reports are automatically uploaded to [Codecov](https://codecov.io/gh/mrz1836/hush)
on every commit.
### Benchmarks
Baseline performance numbers for the hot crypto paths. Re-measure after any
refactor that touches the request path, vault loader, or transport encryption β
regressions land here before they land in production.
Run the suite:
```bash
magex bench:default time=2s
```
Capture a baseline file for diffs across branches:
```bash
magex bench:save time=2s out=bench.txt
```
Compare two runs:
```bash
magex bench:compare old=before.txt new=after.txt
```
**Latest baseline** β Apple M1 Max Β· darwin/arm64 Β· Go 1.26 Β· `benchtime=2s`:
| Benchmark | ns/op | B/op | allocs/op | Path covered |
| ------------------------------------------------ | ------: | -----: | --------: | ----------------------------------------------------- |
| `BenchmarkValidate` (`internal/token`) | 192,871 | 5,739 | 105 | JWT parse + ES256K verify + store lookup (supervisor) |
| `BenchmarkEncrypt` (`internal/transport/ecies`) | 173,705 | 3,345 | 40 | Ephemeral keygen + ECDH + AES-CBC + HMAC envelope |
| `BenchmarkDecrypt` (`internal/transport/ecies`) | 151,457 | 2,528 | 29 | Pubkey parse + ECDH + KDF + HMAC verify + AES-CBC |
| `BenchmarkLoad` (`internal/vault`) | 51,813 | 16,528 | 113 | Encrypted-vault read (16 secrets, ~64 B each) |
> Numbers are local-machine baselines, not SLOs. Use them to spot
> β₯10% regressions on the same hardware after a code change. The CI
> machine numbers will differ; track relative deltas, not absolutes.
>
> Last measured: 2026-05-24
## π οΈ Code Standards
Read more about this Go project's [code standards](.github/CODE_STANDARDS.md).
## π€ AI Usage & Assistant Guidelines
Read the [AI Usage & Assistant Guidelines](.github/CLAUDE.md) for details on
how AI is used in this project and how to interact with AI assistants.
## π₯ Maintainers
| [
](https://github.com/mrz1836) |
|:------------------------------------------------------------------------------------------------:|
| [MrZ](https://github.com/mrz1836) |
## π€ Contributing
View the [contributing guidelines](.github/CONTRIBUTING.md) and please follow
the [code of conduct](.github/CODE_OF_CONDUCT.md).
### How can I help?
All kinds of contributions are welcome :raised_hands:!
The most basic way to show your support is to star :star2: the project, or to
raise issues :speech_balloon:.
You can also support this project by [becoming a sponsor on GitHub](https://github.com/sponsors/mrz1836) :clap:
or by making a [**bitcoin donation**](https://mrz1818.com/?tab=tips&utm_source=github&utm_medium=sponsor-link&utm_campaign=hush&utm_term=hush&utm_content=hush)
to ensure this journey continues indefinitely! :rocket:
[](https://github.com/mrz1836/hush/stargazers)
## π License
[](LICENSE)
This project is licensed under the terms of the [`LICENSE`](LICENSE) file at
the repo root.