{"id":51201149,"url":"https://github.com/shuakami/hush","last_synced_at":"2026-06-28T00:30:47.035Z","repository":{"id":355870414,"uuid":"1229887374","full_name":"shuakami/hush","owner":"shuakami","description":"Zero-trust credential \u0026 access broker for humans, scripts, and AI agents.","archived":false,"fork":false,"pushed_at":"2026-05-05T16:53:38.000Z","size":395,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-05T17:31:30.846Z","etag":null,"topics":["ai-agents","broker","cli","credentials","devops","paramiko","secrets","ssh","vault","zero-trust"],"latest_commit_sha":null,"homepage":"https://shuakami.github.io/hush/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shuakami.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-05T13:29:16.000Z","updated_at":"2026-05-05T16:53:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/shuakami/hush","commit_stats":null,"previous_names":["shuakami/hush"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/shuakami/hush","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuakami%2Fhush","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuakami%2Fhush/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuakami%2Fhush/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuakami%2Fhush/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shuakami","download_url":"https://codeload.github.com/shuakami/hush/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuakami%2Fhush/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34873663,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","broker","cli","credentials","devops","paramiko","secrets","ssh","vault","zero-trust"],"created_at":"2026-06-28T00:30:46.978Z","updated_at":"2026-06-28T00:30:47.026Z","avatar_url":"https://github.com/shuakami.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./.github/assets/banner.png\" alt=\"Hush\" width=\"100%\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/shuakami/hush/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/shuakami/hush/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/shuakami/hush/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/shuakami/hush?label=release\u0026style=flat\u0026color=111111\" alt=\"Release\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/shuakami/hush/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/shuakami/hush?style=flat\u0026color=111111\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://goreportcard.com/report/github.com/shuakami/hush\"\u003e\u003cimg src=\"https://goreportcard.com/badge/github.com/shuakami/hush\" alt=\"Go Report\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/shuakami/hush/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/shuakami/hush?style=flat\u0026color=111111\" alt=\"Stars\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#install\"\u003eInstall\u003c/a\u003e ·\n  \u003ca href=\"#getting-started\"\u003eGetting started\u003c/a\u003e ·\n  \u003ca href=\"#how-it-works\"\u003eHow it works\u003c/a\u003e ·\n  \u003ca href=\"#cli-reference\"\u003eCLI\u003c/a\u003e ·\n  \u003ca href=\"#python-sdk\"\u003eSDK\u003c/a\u003e ·\n  \u003ca href=\"./skills/hush/SKILL.md\"\u003eAgent skill\u003c/a\u003e\n\u003c/p\u003e\n\nHush is a credential broker. It stores secrets in an encrypted vault and runs commands on remote hosts on the caller's behalf, so Python scripts, CI jobs, AI agents, and humans on the CLI never need to handle raw passwords or keys themselves.\n\nIt ships as a single Go binary with no external dependencies. Existing `paramiko`-based scripts can adopt Hush by changing one import; the CLI is shaped after `ssh` and `scp` so muscle memory carries over. Every read, exec, put, and get is appended to a hash-chained audit log that `hush audit verify` can validate end-to-end.\n\n```python\n# before\nssh = paramiko.SSHClient()\nssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())\nssh.connect(\"hk1.example.com\", port=22, username=\"root\",\n            password=\"super-secret-root-password\")\n\n# after\nimport hush.paramiko_compat as paramiko\nssh = paramiko.SSHClient()\nssh.connect(\"hk1\")\n```\n\nThe credential lives in the vault; the shim resolves the host name to a transport + auth pair at `connect` time. No other call-site changes are required.\n\n## Install\n\n```bash\n# macOS / Linux — one-line installer\ncurl -fsSL https://github.com/shuakami/hush/releases/latest/download/install.sh | sh\n```\n\n```powershell\n# Windows\niwr https://github.com/shuakami/hush/releases/latest/download/install.ps1 -useb | iex\n```\n\n```bash\n# Or grab a pre-built binary directly\ncurl -L https://github.com/shuakami/hush/releases/latest/download/hush_linux_amd64.tar.gz | tar xz\n```\n\n```bash\n# Or with Go\ngo install github.com/shuakami/hush/cmd/hush@latest\n```\n\n```bash\n# Or Docker\ndocker run --rm -p 7777:7777 -v hush-data:/data ghcr.io/shuakami/hush:latest\n```\n\n```bash\n# Python SDK\npip install git+https://github.com/shuakami/hush.git#subdirectory=sdk/python\n```\n\n## Getting started\n\nThe first run takes about a minute: pick a master key, start the broker, register a host, run a command. After that, everything is `hush exec`, `hush cp`, or one import line in your Python.\n\n### 1. Pick a master key\n\nHush encrypts the vault with a key-encryption-key (KEK) that **never** lives in the database. By default the KEK comes from the environment variable `HUSH_MASTER_KEY`. Generate one and put it somewhere your shell will read on every login (`~/.zshrc`, `/etc/hush/env`, your secret manager, your `docker run -e`, …).\n\n```bash\nexport HUSH_MASTER_KEY=$(openssl rand -base64 32)\n```\n\nIf you prefer a file on disk, set `HUSH_KEK_KIND=file` and `HUSH_KEK_FILE=/etc/hush/master.key` instead. Lose this value and the vault becomes unreadable; back it up the same way you back up an SSH private key.\n\n### 2. Start the broker\n\n```bash\nhush bootstrap        # mints admin api key + writes ~/.hush/config\nhush server           # daemonise this (systemd, docker, tmux — your call)\n```\n\n`bootstrap` mints an admin API key and writes both the local endpoint (`http://127.0.0.1:8443`) and the key into `~/.hush/config` at mode `0600`. The CLI on this machine is now ready — there is no separate \"log in\" step, and no cloud account anywhere.\n\nTo bootstrap a server whose CLI lives on a different machine, pass `--no-save`; the key is printed to stdout and you can copy it across with `hush login --endpoint … --api-key …`. If `hush server` starts on a fresh data directory and finds no API keys, it self-bootstraps with the same config-writing logic. When local config save succeeds, it does not print the raw key.\n\n### 3. Register a host\n\n```bash\necho 'super-secret-root-password' | hush secret set hk1-root-password --stdin\n\nhush host add hk1 \\\n  --transport ssh \\\n  --address 10.0.0.10 --port 22 --user root \\\n  --auth-kind password --auth-secret hk1-root-password \\\n  --tag prod\n```\n\n`hk1` is now a name. The address, the port, and the credential pointer live in the inventory; the credential value lives in the vault. Anyone with an API key that has `host:exec` scope can reach `hk1` by name without ever seeing the password.\n\nFor a key-based host swap `--auth-kind password --auth-secret …` for `--auth-kind key --auth-secret hk2-private-key`, where `hk2-private-key` is a vault secret containing the PEM blob.\n\n### 4. Use it\n\n```bash\nhush exec hk1 -- \"systemctl status nginx\"           # one host, one command\nhush exec --tag prod -- \"uptime\"                    # every prod host, in parallel\nhush cp ./build.tar.gz hk1:/opt/app/build.tar.gz    # upload\nhush doctor --host hk1                               # config + auth + host connectivity\nhush ssh hk1                                        # interactive shell, for humans\nhush audit verify                                   # confirm the audit chain is intact\n```\n\nThat is the entire daily-driver loop.\n\n### 5. Wire it into a Python script\n\nPick the form that fits the script:\n\n```python\n# minimal change to existing paramiko code\nimport hush.paramiko_compat as paramiko\nssh = paramiko.SSHClient()\nssh.connect(\"hk1\")\nstdin, stdout, stderr = ssh.exec_command(\"systemctl status nginx\")\n```\n\n```python\n# or use the higher-level helper\nfrom hush import remote\nresult = remote.exec(\"hk1\", \"systemctl status nginx\")\nprint(result.exit_code, result.stdout)\n```\n\nThe SDK reads the same `~/.hush/config` the CLI does, so once `hush bootstrap` has written that file the script needs no further configuration.\n\n### 6. Wire it into an AI agent\n\nThe repo ships with an [Agent Skill](./skills/hush/SKILL.md) — a single directory the agent's runtime can load to learn when and how to call Hush. For Claude Code:\n\n```bash\nmkdir -p .claude/skills\ncp -r skills/hush .claude/skills/hush\n```\n\nOther runtimes that support the open Agent Skill standard (Claude Desktop, Cursor, Aider, Devin via `AGENTS.md`) load the same file. Once installed, the agent will reach for `hush exec` instead of asking the user for SSH credentials.\n\n## How it works\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./.github/assets/architecture.png\" alt=\"Hush architecture\" width=\"100%\"\u003e\n\u003c/p\u003e\n\nCallers (operators, Python scripts, CI jobs, AI agents) talk to a single HTTP API on the broker. The exec engine resolves the named host through the inventory, fetches the credential from the vault, dispatches through the matching transport, and appends the result to the audit chain.\n\n- **Vault** — AES-256-GCM with envelope encryption. Each secret has its own DEK, wrapped by a KEK sourced from env, file, or KMS (roadmap).\n- **Inventory** — maps a name (`hk1`) to a transport, an auth method, and a set of tags. The same name resolves the same way for every caller.\n- **Audit** — append-only, hash-chained log. `hush audit verify` walks the chain and refuses to validate if any record has been mutated.\n- **Transports** — SSH password, SSH key, SSH through one or more jump hosts, and `sdjz-relay` (a curl-based temporary tunnel format). The caller never picks the transport; the inventory does.\n\n## Why Hush\n\nExisting tools each cover part of the problem:\n\n| Category                | Examples                          | What they don't do                                                                  |\n| ----------------------- | --------------------------------- | ----------------------------------------------------------------------------------- |\n| Password manager        | 1Password · Bitwarden · sops      | Don't run the work for you — your script still receives the raw password           |\n| Enterprise vault        | HashiCorp Vault · AWS Secrets Mgr | Heavy: cluster + sidecar + IAM tuning before you can deploy                         |\n| Bastion / jump host     | Teleport · Boundary               | Audit SSH, but ignore the API keys baked into your `.py` files                      |\n| Short-lived credentials | OIDC · SSH CA · smallstep         | Require infra changes; existing paramiko code doesn't benefit                       |\n\nHush packs the useful parts into one ~50 MB binary:\n\n1. **Single binary, broker mode.** No cluster, no sidecar, no IAM. `hush exec` runs SSH for you; agents never see the password.\n2. **Drop-in `paramiko` shim.** Change one import line and existing hardcoded paramiko calls go through Hush.\n3. **Named hosts, multi-transport.** `hk1` is a name; the underlying transport can be password SSH, key SSH, jump-host chain, or your own relay tunnel — same call site.\n4. **Code-level migration tool.** `hush migrate scan ./scripts/` walks your repo with Python AST, finds `PASSWORD = \"...\"`, embedded PEM keys, and `paramiko.connect()` kwargs, then generates a diff that pushes secrets into the vault and rewrites the source.\n5. **Hash-chained audit.** `hush audit verify` detects log tampering — same primitive Sigstore Rekor uses for supply-chain proofs.\n6. **CLI-first surface.** `hush exec hk1 -- cmd` is shaped like `ssh user@host cmd`. Anything an agent already knows about ssh transfers.\n\n## CLI reference\n\n```\nhush bootstrap                         init server (KEK + admin token)\nhush server                            run the broker daemon\nhush login                             save endpoint + token to ~/.hush\nhush doctor [--host NAME]              check config, server, auth, inventory, and host\n\nhush get NAME                          read a secret value\nhush secret  set | get | ls | rm       vault management\nhush host    add | ls | show | rm      inventory management\n\nhush exec  HOST  -- CMD                run command on host\nhush exec  --tag TAG -- CMD            run on every host with tag, in parallel\nhush ssh   HOST                        interactive PTY\nhush cp    SRC HOST:/dst               copy file (sftp under the hood)\n\nhush audit  tail | verify              read / verify the audit chain\nhush apikey mint | ls                  scoped API keys for agents\n\nhush migrate scan PATH                 find hardcoded credentials\nhush migrate apply PATH                push to vault + rewrite source\n\nhush completion bash|zsh|fish|powershell\nhush mcp                               start MCP server (Claude Desktop, Devin, etc.)\n```\n\n## Python SDK\n\n```python\nfrom hush import remote\n\n# Single host\nresult = remote.exec(\"hk1\", \"uname -a\")\nprint(result.stdout, result.exit_code)\n\n# Many hosts in parallel by tag\nfor r in remote.exec_many(tag=\"prod\", cmd=\"systemctl is-active nginx\"):\n    print(r.host, r.exit_code)\n\n# Or a paramiko drop-in:\nimport hush.paramiko_compat as paramiko\nssh = paramiko.SSHClient()\nssh.connect(\"hk1\")\nsftp = ssh.open_sftp()\nsftp.put(\"./build.tar.gz\", \"/opt/app/build.tar.gz\")\n```\n\n## Migration\n\n```bash\n$ hush migrate scan ./scripts/ssh/\nfound 11 potential credential(s) across 10 file(s):\n\n  ./scripts/ssh/ssh_hk.py\n    line   16  [literal_assign]  PASSWORD = \"...\"\n           hint: variable=PASSWORD  → suggested secret name: ssh_hk-password\n\n  ./scripts/ssh/ssh_panel_tunnel.py\n    line   31  [embedded_pem]    ED25519_KEY = \"\"\"-----BEGIN OPENSSH PRIVATE KEY-----...\"\"\"\n           hint: variable=ED25519_KEY → suggested secret name: ssh_panel_tunnel-ed25519_key\n  ...\n```\n\n`hush migrate apply` will:\n1. Push every literal value into the vault under its suggested secret name.\n2. Rewrite the source file to call `hush.get(\"...\")` (or replace `import paramiko` with `import hush.paramiko_compat as paramiko`).\n3. Open a PR with the diff for review.\n\n## Security posture\n\n- Server defaults to `127.0.0.1`; expose via mTLS or nginx + client certs only.\n- API keys are scoped: `secret:read` · `secret:write` · `host:list` · `host:exec` · `host:put` · `host:get` · `audit:read` · `apikey:write` · `*`.\n- Vault SQLite file is `0600`. Run server under an unprivileged user.\n- KEK source is pluggable (env / file / KMS); rotate by re-wrapping every DEK.\n- Approval webhooks for high-risk operations (Lark / Slack / Discord) — roadmap.\n\n## Roadmap\n\n**v0.1 — shipped**\n- Vault (AES-256-GCM + envelope, env/file KEK)\n- Host inventory + tags\n- Transports: ssh password / ssh key / jump chain / sdjz-relay\n- Exec broker (single + parallel) + put/get\n- Append-only hash-chained audit log\n- HTTP API + scoped API keys\n- Python SDK + paramiko shim + migration scanner\n- MCP server (stdio)\n- Docker / docker-compose / GitHub Actions CI\n\n**v0.2 — next**\n- OpenSSH `ProxyCommand` integration (let `ssh hk1`, `ansible`, `fab` flow through Hush)\n- SSH CA + short-lived certificates\n- Policy engine (YAML / OPA-style)\n- Approval webhooks for high-risk operations\n- AWS / GCP / Aliyun KMS as KEK source\n- OIDC / WebAuthn for human login\n- GitHub Actions OIDC → token (no persistent secrets in CI)\n- Postgres backend\n- Web UI (embedded SvelteKit, single-binary delivery)\n- `migrate apply` (auto-push to vault + rewrite source + open PR)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshuakami%2Fhush","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshuakami%2Fhush","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshuakami%2Fhush/lists"}