hush

module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 24, 2026 License: MIT

README ΒΆ

🀫  hush

Discord-gated secrets broker for AI agents

One passphrase. No key files. No dotfiles on agent disks.


Release Go Version License


CI / CD Β Β  Build Last Commit Β Β Β Β  Quality Β Β  Go Report Coverage
Security Β Β  Scorecard Security Β Β Β Β  Community Β Β  Contributors Bitcoin


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 (Go 1.26+) and is built CGO_ENABLED=0 β€” a single static binary.

Status: v0.1.0 is a private MVP. Treat the steps below as the documented happy path, not a guarantee.

Prerequisites: a vault host and an agent host on the same Tailscale tailnet, plus a Discord bot you control (https://discord.com/developers/applications) for the approval channel.

Build from source
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:

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):

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.


⚑ Quick Start

Get up and running with these essential commands:


Run a confidence check

One command, fake secret, real Discord approval:

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 then shuts the temporary server down. Clean smoke artifacts safely with hush smoke clean (archives by default).


Bootstrap the vault host
hush init server          # guided / interactive; preflight + prompts
hush secret add OPENAI_API_KEY
hush serve                # binds Tailscale interface, brokers approvals

hush init server is the canonical first-run entry point. It runs a diagnostic-first preflight, prompts for the inputs it actually needs, classifies pre-existing state per-artifact, and never silently overwrites. When it asks for a listen address, use the vault host's Tailscale IPv4 plus a free port (for example, run printf '%s:7743\n' "$(tailscale ip -4)" on the server host). Do not use the laptop/client IP.

During hush init server, set discord_approval_channel_id if you want approvals in a Discord channel instead of owner DMs. On macOS, if the login Keychain is locked or unavailable, choose the env-token fallback and run hush serve with HUSH_DISCORD_BOT_TOKEN exported in that terminal.


Enrol the agent host
hush init client --machine-index 1
HUSH_SERVER="$(hush --config ~/.hush/config.toml server-url)"
hush request \
  --server "$HUSH_SERVER" \
  --machine-index 1 --scope OPENAI_API_KEY \
  --max-uses 1 --ttl 5m --reason "smoke test" \
  --exec printenv -- OPENAI_API_KEY

Approve on Discord; the child process you named in --exec runs with OPENAI_API_KEY in its environment β€” and only there. --exec names a program, not a shell string; pass child arguments after --. Nothing is written to disk on the agent host.


πŸ“– For the full walkthrough β€” Keychain ACL recovery, clock-skew override, --non-interactive mode β€” see docs/OPERATIONS.md. For Keychain vs HUSH_DISCORD_BOT_TOKEN positioning and the threat model, see docs/SECURITY.md Β§2.4. For long-running daemons, see docs/DAEMONS.md and deploy/examples/supervisors/. For server + supervisor TOML schemas, see docs/CONFIG-SCHEMA.md.


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.

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.


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.


Tech stack
  • Go 1.26+ β€” single static binary, CGO_ENABLED=0 exclusively (Constitution Principle IX).
  • decred/dcrd/dcrec/secp256k1/v4 β€” secp256k1 primitives used for ECDSA signing, ES256K JWTs, and ECIES envelope encryption (Constitution Principle III).
  • decred/dcrd/hdkeychain/v3 β€” BIP32 HD key derivation from the operator passphrase (Constitution Principle III); paired with stdlib golang.org/x/crypto/argon2 for the KDF.
  • Tailscale β€” the only network reachable to the vault server. WireGuard underneath; identity-based ACLs above.
  • Discord + discordgo β€” phone-based approval channel; the v0.1.0 reference Approver.
  • golang-jwt/jwt v5 β€” JWT framework; hush registers a custom ES256K signing method.
  • go-toml v2 β€” strict TOML parsing for server and supervisor configs.
  • zalando/go-keyring β€” OS keychain access with ACL support.
  • cobra + pflag β€” CLI subcommand routing and flag parsing.

The SecureBytes mlock pattern is custom-implemented in internal/vault/securebytes/; the design is inspired by sigil but takes no dependency on it.


πŸ“š Documentation

View the comprehensive documentation for hush:

Doc Purpose
docs/OPERATIONS.md Setup, day-to-day modes, --non-interactive, Keychain recovery
docs/ARCHITECTURE.md Component model, trust boundaries, supervisor lifecycle
docs/SECURITY.md Threat model, 7 security layers, residual risks
docs/CONFIG-SCHEMA.md Server + supervisor TOML schemas, defaults, validation
docs/DAEMONS.md Supervisor pattern, refresh tuning, validator authoring
docs/API.md HTTP endpoint reference
docs/LIFECYCLE-SCENARIOS.md 17 supervisor lifecycle scenarios β€” behavioral reference
docs/TAILSCALE-ACLS.md Recommended ACL pattern restricting the vault port
docs/CLEAN-MACHINE.md Agent-machine cleanup checklist
.specify/memory/constitution.md The 11 non-negotiable principles

Goals

The v0.1.0 goal is a working private MVP that proves the threat model in practice: an agent machine with a clean disk, a vault host on a phone-gated Tailscale mesh, and a daily dev workflow that no longer requires plaintext credentials anywhere on the agent.

Post-v0.1.0 / future scope (any of these may become a future release; none is on the v0.1.0 critical path):

  • Multi-owner approvals
  • Slack / Telegram / PagerDuty Approver backends (the interface is already pluggable)
  • Shamir passphrase splitting (sigil's SSS) for vault recovery
  • Web dashboard
  • Proxy mode (vault proxying provider API calls instead of injecting tokens)
  • Agent-side credential proxy (per-provider HTTP proxy on the agent host)
  • TLS within Tailscale (defence-in-depth on top of WireGuard)
  • TOTP second factor on Discord approval
  • Custom validator authoring SDK

πŸ” 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:

  • Private MVP: v0.1.0 is an unproven private MVP β€” not production-grade, and the end-to-end round-trip has not been independently verified.
  • 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. For security issues, see our Security Policy or contact: hush@mrz1818.com.


Additional Documentation & Repository Management
Development Setup (Getting Started)

Install MAGE-X build tool for development:

# 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:

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 for streamlined binary deployment to GitHub. To get started, install it via:

brew install goreleaser

The release process is defined in the .goreleaser.yml configuration file. Then create and push a new Git tag using:

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/.

Updating Dependencies

To update all dependencies (Go modules, linters, and related tools), run:

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. View the configuration file.

Run all tests (fast):

magex test

Run all tests with race detector (slower):

magex test:race
Test Coverage

View coverage report:

magex test:coverage

Coverage reports are automatically uploaded to Codecov on every commit.


πŸ› οΈ Code Standards

Read more about this Go project's code standards.


πŸ€– AI Usage & Assistant Guidelines

Read the AI Usage & Assistant Guidelines for details on how AI is used in this project and how to interact with AI assistants.


πŸ‘₯ Maintainers

MrZ
MrZ

🀝 Contributing

View the contributing guidelines and please follow the code of conduct.

How can I help?

All kinds of contributions are welcome πŸ™Œ! The most basic way to show your support is to star 🌟 the project, or to raise issues πŸ’¬. You can also support this project by becoming a sponsor on GitHub πŸ‘ or by making a bitcoin donation to ensure this journey continues indefinitely! πŸš€

Stars


πŸ“ License

License

This project is licensed under the terms of the LICENSE file at the repo root.

Directories ΒΆ

Path Synopsis
cmd
hush command
Package main is the hush binary entry point.
Package main is the hush binary entry point.
internal
audit
Package audit owns the hush server's tamper-evident audit log (Constitution III Layer 6).
Package audit owns the hush server's tamper-evident audit log (Constitution III Layer 6).
cli
Package cli is the operator-facing command-line surface of the hush binary.
Package cli is the operator-facing command-line surface of the hush binary.
cli/setup
Package setup hosts the diagnostic-first foundations the guided `hush init server` flow depends on: a structured error taxonomy (errors.go), a preflight check registry (preflight.go), and an existing-state classifier (state.go) that labels pre-existing config / vault / state-dir / Keychain artifacts as safe-to-reuse, repairable, or collision.
Package setup hosts the diagnostic-first foundations the guided `hush init server` flow depends on: a structured error taxonomy (errors.go), a preflight check registry (preflight.go), and an existing-state classifier (state.go) that labels pre-existing config / vault / state-dir / Keychain artifacts as safe-to-reuse, repairable, or collision.
config
Package config owns the server-side TOML configuration file: schema, defaults, validation, and path-safety checks.
Package config owns the server-side TOML configuration file: schema, defaults, validation, and path-safety checks.
discord
Package discord owns the Discord-backed approval surface.
Package discord owns the Discord-backed approval surface.
discord/alerts
Package alerts is the operator-facing Discord alert surface for hush.
Package alerts is the operator-facing Discord alert surface for hush.
keychain
Package keychain wraps the platform-native OS keychain operations behind a single Keychain interface.
Package keychain wraps the platform-native OS keychain operations behind a single Keychain interface.
keys
Package keys derives every cryptographic key used by hush at runtime from a single passphrase, with no key material ever written to disk.
Package keys derives every cryptographic key used by hush at runtime from a single passphrase, with no key material ever written to disk.
logging
Package logging provides the project's single slog.Logger constructor and the credential-redaction primitives every log call passes through.
Package logging provides the project's single slog.Logger constructor and the credential-redaction primitives every log call passes through.
server
Package server: POST /claim handler.
Package server: POST /claim handler.
supervise
Supervised child process layer.
Supervised child process layer.
supervise/config
Package config owns the per-supervisor TOML configuration file: schema, defaults, validation, and path-safety checks.
Package config owns the per-supervisor TOML configuration file: schema, defaults, validation, and path-safety checks.
supervise/validators
Package validators provides the pre-flight credential Validator interface plus five built-in implementations (anthropic, anthropic-oauth, openai, google-ai, github).
Package validators provides the pre-flight credential Validator interface plus five built-in implementations (anthropic, anthropic-oauth, openai, google-ai, github).
supervise/watchdog
Package watchdog implements an alert-only log-pattern watchdog for hush supervisor child processes.
Package watchdog implements an alert-only log-pattern watchdog for hush supervisor child processes.
testutil
Package testutil is the project's shared, test-only harness package.
Package testutil is the project's shared, test-only harness package.
token
Package token implements the Layer-2 session-authority for hush: ES256K JWT issuance, validation, in-memory revocation/use-count store, and the cleanup loop that reclaims expired live records.
Package token implements the Layer-2 session-authority for hush: ES256K JWT issuance, validation, in-memory revocation/use-count store, and the cleanup loop that reclaims expired live records.
transport/ecies
Package ecies implements the Layer-3 wire-level secret-response encryption for hush: BIE1 ECIES over secp256k1 (4-byte magic, 33-byte compressed ephemeral public key, AES-256-CBC ciphertext, 32-byte HMAC-SHA256 tag).
Package ecies implements the Layer-3 wire-level secret-response encryption for hush: BIE1 ECIES over secp256k1 (4-byte magic, 33-byte compressed ephemeral public key, AES-256-CBC ciphertext, 32-byte HMAC-SHA256 tag).
transport/sign
Package sign implements the Layer-4 request-signing protocol for hush: canonical-JSON encoding, ECDSA sign/verify over SHA-256(canonical), and nonce + timestamp replay protection.
Package sign implements the Layer-4 request-signing protocol for hush: canonical-JSON encoding, ECDSA sign/verify over SHA-256(canonical), and nonce + timestamp replay protection.
upgrade
Package upgrade implements the hush self-upgrade pattern: resolve a GitHub release for the requested channel, download the platform- specific tarball, verify its SHA256 against the published checksums file, extract it with Zip-Slip / zip-bomb defenses, and atomically replace the running binary via a copy-and-rename dance that is safe against the SIGBUS class of in-place binary mutation bugs.
Package upgrade implements the hush self-upgrade pattern: resolve a GitHub release for the requested channel, download the platform- specific tarball, verify its SHA256 against the published checksums file, extract it with Zip-Slip / zip-bomb defenses, and atomically replace the running binary via a copy-and-rename dance that is safe against the SIGBUS class of in-place binary mutation bugs.
vault
Package vault is the on-disk secret store: an AES-256-GCM-encrypted file containing JSON-encoded name β†’ SecureBytes mappings, written via temp- file + fsync + atomic rename, with strict permission enforcement at both open and save paths.
Package vault is the on-disk secret store: an AES-256-GCM-encrypted file containing JSON-encoded name β†’ SecureBytes mappings, written via temp- file + fsync + atomic rename, with strict permission enforcement at both open and save paths.
vault/securebytes
Package securebytes provides the SecureBytes container β€” an opaque, pointer-only secret holder that pins its payload in non-swappable memory, zeroes the payload on explicit Destroy AND on garbage collection (via a runtime finalizer), and renders as the literal string "[redacted]" through every standard log/format/JSON path.
Package securebytes provides the SecureBytes container β€” an opaque, pointer-only secret holder that pins its payload in non-swappable memory, zeroes the payload on explicit Destroy AND on garbage collection (via a runtime finalizer), and renders as the literal string "[redacted]" through every standard log/format/JSON path.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL