Manage your Mailhub relay addresses from the terminal.
mailhub is the command-line client for Mailhub. Authenticate a
device through the browser, then manage relay email aliases and API keys without leaving your
terminal.
Early release: the current CLI version is
0.1.2. The supported release targets are macOS Apple Silicon (arm64) and Intel (amd64).
This CLI uses the device-authorization and API-key contract in Mailhub's
backend PR #67, with browser approval from
frontend PR #4. The matching CLI change is in
cli PR #4. When the poll-proof requirement from
backend PR #67 is deployed, CLI version 0.1.1 or newer will be required. This version sends a
poll-secret hash when it starts device authorization and proves possession of that secret on every
token poll. The current 0.1.2 release also treats omitted HTTP and HTTPS ports as their default
ports when following same-origin redirects. After this PR is merged, Homebrew users can run
brew update && brew upgrade mailhub to install the current release. End-to-end login also requires
the frontend approval page from PR #4 to be deployed.
Use those commands only with a Mailhub server that implements the contract above and accepts its API
keys for the relay endpoints. mailhub version, mailhub completion, and local help work without a
server.
- What you can do
- Server compatibility
- Requirements
- Install
- Quick start
- Command reference
- Configuration
- Credentials and security
- Exit codes
- Development
- Contributing
- License
- Sign in with a compatible Mailhub server's browser-based device authorization flow.
- List, create, enable, disable, and label relay email aliases on a compatible server.
- List and revoke API keys on a compatible server.
- Use
--jsonoutput for scripts and automation where supported. - Generate shell completions for Zsh, Bash, and Fish.
- macOS with Apple Silicon or Intel, including a working macOS Keychain.
- Go 1.27 or newer when building from source.
- A compatible Mailhub server and account. See Server compatibility.
Homebrew builds the CLI from the tagged Go source for your Mac:
brew tap private-mailhub/cli https://github.com/private-mailhub/cli.git
brew install private-mailhub/cli/mailhub
mailhub versionThe formula lives in Formula/mailhub.rb in this repository. The explicit tap
URL is required because this repository is named cli, without Homebrew's usual
homebrew- prefix. Homebrew updates the tap with brew update.
If you installed mailhub from the former private-mailhub/tap repository, switch to this tap:
brew uninstall private-mailhub/tap/mailhub
brew untap private-mailhub/tap
brew tap private-mailhub/cli https://github.com/private-mailhub/cli.git
brew install private-mailhub/cli/mailhubUninstalling the formula does not remove the CLI's Keychain credential or configuration file.
Clone the repository and build the binary:
git clone https://github.com/private-mailhub/cli.git
cd cli
go build -trimpath -o mailhub ./cmd/mailhub
./mailhub versionPlace mailhub somewhere on your PATH when you are ready to use it without the ./ prefix.
If your Go bin directory is already on PATH, you can install the command directly:
go install github.com/private-mailhub/mailhub-cli/cmd/mailhub@main
mailhub versionThe Go module keeps its original mailhub-cli path for compatibility after the repository rename.
Prebuilt binaries are not published. Homebrew builds from source; you can also build or install the CLI with Go directly.
Once mailhub is available on your PATH and you have a compatible server:
The default flow opens the Mailhub approval page in your browser:
mailhub auth loginTo avoid launching a browser, such as from a remote shell, run the same login flow with:
mailhub auth login --no-browser--no-browser suppresses browser launch; the CLI still prints the approval URL and one-time code.
You can give the device a recognizable name:
mailhub auth login --device-name "Work Mac"Open the printed URL, sign in to Mailhub, approve the request, and return to the terminal. The CLI waits for approval and stores the resulting API key automatically. For each login, it creates a fresh random poll proof, sends only its SHA-256 hash with the device request, and presents the proof on each token poll. The proof stays in memory and is not printed.
mailhub auth status# List aliases
mailhub alias list
# Create an alias with an optional label
mailhub alias create --label newsletter
# Disable or enable an alias by ID or exact relay email
mailhub alias off 12
mailhub alias on 12
# Change or clear its label
mailhub alias label 12 shopping
mailhub alias label 12 --clearWith a Keychain credential, logout revokes the current API key on the server and removes the
local credential. With MAILHUB_TOKEN, it revokes that environment-supplied key but leaves any
saved Keychain credential unchanged:
mailhub auth logoutRun mailhub <command> --help for the authoritative help text and flags. All authentication,
API-key, and alias commands below require a compatible server; see
Server compatibility.
| Command | Description |
|---|---|
mailhub auth login |
Authenticate the current device. |
mailhub auth login --no-browser |
Suppress browser launch while still printing the approval URL and one-time code. |
mailhub auth login --device-name <name> |
Set the name shown on the approval page. |
mailhub auth status |
Show the current key ID and expiry; with MAILHUB_TOKEN, report environment-based authentication only. |
mailhub auth logout |
Revoke the current key; clear the Keychain credential only when it is the active credential. |
mailhub auth keys list |
List API keys. |
mailhub auth keys list --json |
List API keys as JSON. |
mailhub auth keys revoke <key-id> |
Revoke one API key by ID. |
Login creates a fresh random poll proof for each device authorization. The start request contains only the proof's SHA-256 hash; each token poll contains the same proof. The protocol is implemented by backend PR #67 and the corresponding CLI PR #4, which must be merged and deployed together. The browser approval page is provided by frontend PR #4.
| Command | Description |
|---|---|
mailhub alias list |
List relay aliases in a human-readable table. |
mailhub alias list --json |
List relay aliases as JSON. |
mailhub alias create |
Create a random relay alias. |
mailhub alias create --label <label> |
Create an alias with a label. |
mailhub alias create --json |
Create an alias and print the response as JSON. |
mailhub alias on <id-or-email> |
Enable an alias. |
mailhub alias off <id-or-email> |
Disable an alias. |
mailhub alias label <id-or-email> <label> |
Set an alias label. |
mailhub alias label <id-or-email> --clear |
Clear an alias label. |
Alias identifiers can be the numeric alias ID or the exact relay email address shown by
mailhub alias list. Labels are limited to 100 characters.
# Generate completion scripts
mailhub completion zsh
mailhub completion bash
mailhub completion fish
# Print the CLI version
mailhub versionFor example, load Zsh completions for the current shell with:
eval "$(mailhub completion zsh)"The default API origin is https://private-mailhub.com. For a login flow or a command using
MAILHUB_TOKEN, select an alternate origin with the global --api-url flag or MAILHUB_API_URL:
mailhub --api-url https://staging.example.com alias list
MAILHUB_API_URL=https://staging.example.com mailhub alias listThe flag takes precedence over MAILHUB_API_URL, which takes precedence over the default origin.
The value must be an absolute origin. Do not append /api, a path, a query string, or a fragment;
HTTPS is required except for loopback development URLs such as http://localhost:8080.
After auth login, the Keychain credential is bound to the origin used for that login. Supplying a
different --api-url or MAILHUB_API_URL with that saved credential is rejected; log in again at
the new origin. A MAILHUB_TOKEN environment credential can be used with an explicit origin.
| Variable | Purpose |
|---|---|
MAILHUB_API_URL |
Selects the origin for login and MAILHUB_TOKEN flows; it cannot replace the origin bound to a saved Keychain credential. |
MAILHUB_TOKEN |
Uses a compatible server's API key from the environment instead of the macOS Keychain. |
MAILHUB_CONFIG_DIR |
Overrides the directory used for non-secret CLI metadata. |
MAILHUB_TOKEN is useful for CI and automation. Prefer a secret manager or the CI platform's
secret store, and never put the token in a command argument or committed script.
- The API key is stored in the macOS Keychain under service
private-mailhub.mailhub-cliand accountdefault. - The CLI stores only non-secret metadata in
mailhub/config.jsonbelow the platform user configuration directory. On macOS, this is normally~/Library/Application Support/mailhub/config.json. - The metadata directory is created with
0700permissions and the config file with0600permissions. - When a compatible server returns a raw API key during login, the CLI saves it in the Keychain and never prints or writes it to logs.
- Key expiry is a server policy. The CLI warns when saved expiry metadata indicates seven days or less remaining.
- On a compatible server,
auth logoutrevokes the server-side key before deleting the local Keychain credential. When usingMAILHUB_TOKEN, it cannot remove the environment variable for you; unset it after logout.
| Code | Meaning |
|---|---|
0 |
Command completed successfully. |
1 |
API, network, or server error. |
2 |
Invalid command, flag, or argument. |
3 |
Authentication is missing, expired, or revoked. |
Errors are written to stderr; JSON and normal command output are written to stdout.
| Path | Responsibility |
|---|---|
cmd/mailhub |
Binary entrypoint. |
internal/api |
Mailhub HTTP client and response contracts. |
internal/cli |
Cobra commands, validation, output, and exit codes. |
internal/credentials |
Keychain access and local metadata. |
internal/platform |
Browser-launch and platform helpers. |
# Format check
test -z "$(gofmt -l .)"
# Static analysis and tests
go vet ./...
go test ./...
go test -race ./...
# Build the CLI
go build -trimpath -o mailhub ./cmd/mailhubThe same checks run in GitHub Actions. CI builds macOS binaries for both Apple Silicon (darwin/arm64)
and Intel (darwin/amd64), and audits, builds, and tests the Homebrew formula.
After tagging and publishing a CLI release, update the source tag and SHA-256 checksum in
Formula/mailhub.rb. Calculate the checksum from the release's GitHub source archive. Audit and
build the formula from source before merging the update:
brew audit --strict private-mailhub/cli/mailhub
brew install --build-from-source private-mailhub/cli/mailhub
brew test private-mailhub/cli/mailhubThe formula version comes from the tag in its source URL.
Issues and pull requests are welcome. Before opening a pull request:
- Keep changes focused and explain the user-visible behavior.
- Add or update tests for command, API, credential, or security behavior.
- Run
gofmt,go vet ./...,go test ./..., andgo test -race ./.... - Never include API keys, personal email addresses, or real user data in code, tests, logs, or screenshots.
Mailhub CLI is licensed under the GNU Affero General Public License v3.0.
