paubox-cli
v0.3.0
Published
Official CLI for the Paubox encrypted email API
Downloads
875
Readme
paubox-cli
Official CLI for the Paubox encrypted email API. Send HIPAA-compliant email, check delivery status, and manage your credentials from the terminal.
Installation
npm (all platforms)
npm install -g paubox-cliHomebrew (macOS)
brew tap paubox/paubox
brew install paubox-cliWindows
winget install Paubox.CLIOr via npm:
npm install -g paubox-cliKeytar (optional): The CLI uses the Windows Credential Vault for secure credential storage via the
keytarnative module. Ifkeytarfails to build during install, credentials fall back to a config file automatically — no action required. To enable native keychain support, install Visual C++ Build Tools before runningnpm install -g paubox-cli.
Requirements
- Node.js ≥ 20.12.0
- On Linux:
libsecret-1-devis required for OS keychain support
Without it, credentials fall back to a local config file automatically (sudo apt-get install libsecret-1-dev~/.config/paubox/config.jsonon Linux/macOS,%APPDATA%\paubox\config.jsonon Windows).
Quick Start
# Authenticate with your Paubox API credentials
paubox auth login
# Send an email
paubox send --to [email protected] --from [email protected] --subject "Hello" --text "Hi there!"
# Check delivery status
paubox status <trackingId>Commands
paubox auth
Manage Paubox API credentials.
paubox auth login # Prompt for API username and key; validate and store
paubox auth logout # Remove stored credentials
paubox auth status # Show current authentication stateCredentials are stored in the OS keychain (macOS Keychain, Windows Credential Vault, Linux Secret Service) when available. If the keychain is unavailable, they fall back to a local config file (~/.config/paubox/config.json on Linux/macOS, %APPDATA%\paubox\config.json on Windows).
paubox send
Send a secure email.
paubox send \
--to [email protected] \
--from [email protected] \
--subject "Your subject" \
--text "Plain text body" \
--html "<p>HTML body</p>" \
--attachment /path/to/file.pdf| Flag | Required | Description |
|------|----------|-------------|
| --to <email...> | Yes | Recipient(s). Repeat for multiple: --to [email protected] --to [email protected] |
| --from <email> | No* | Sender address. Defaults to defaultFrom config value |
| --subject <text> | Yes | Email subject |
| --text <body> | No† | Plain text body |
| --html <body> | No† | HTML body |
| --attachment <file...> | No | File path(s) to attach |
† At least one of --text or --html is required.
On success, prints the source tracking ID:
✓ Email sent. Tracking ID: abc123-def456paubox status
Check the delivery status of a sent email.
paubox status <trackingId>Outputs a table of recipients with delivery status and timestamps:
recipient status delivered at opened opened at
--------------------- --------- ------------------------ ------ ---------
[email protected] delivered 2026-01-01T12:00:00Z opened 2026-01-01T13:00:00Zpaubox forms
Retrieve form metadata and submit responses to Paubox forms. These commands do not require authentication.
forms get <formId>
paubox forms get <formId>
paubox --json forms get <formId>Prints the form's title, description, active status, submission count, and timestamps. With --json, returns the raw API response object.
forms submit <formId>
# Inline key=value pairs (repeatable)
paubox forms submit <formId> \
--data "first_name=Jane" \
--data "last_name=Doe" \
--data "[email protected]"
# Read form fields from a JSON file
paubox forms submit <formId> --data-file ./fields.json
# Mix file and inline overrides (--data wins on matching keys)
paubox forms submit <formId> \
--data-file ./base.json \
--data "field=override"
# Attach a file with the submission
paubox forms submit <formId> \
--data "name=Jane" \
--attach /path/to/signed-consent.pdf| Flag | Description |
|------|-------------|
| --data <key=value> | Form field as a key=value pair. Repeatable. Values may contain =. |
| --data-file <path> | Path to a JSON file whose top-level string values are used as form_data. Merged with --data; --data takes precedence on matching keys. |
| --attach <file> | File to include as an attachment. Repeatable. Total request size must not exceed 250 MB. |
On success:
✓ Form submitted successfully.With --json:
{ "status": "ok", "formId": "<formId>" }paubox config
Manage CLI configuration stored in ~/.config/paubox/config.json (Linux/macOS) or %APPDATA%\paubox\config.json (Windows).
paubox config set defaultFrom [email protected]
paubox config get defaultFrom
paubox config list
paubox config reset| Key | Description |
|-----|-------------|
| defaultFrom | Default sender address used when --from is omitted |
Global Options
These flags work with any command:
| Flag | Description |
|------|-------------|
| --json | Output result as JSON (useful for scripting) |
| -q, --quiet | Suppress non-essential output |
| -v, --version | Print version |
| --help | Show help |
JSON output example
paubox --json send --to [email protected] --from [email protected] --subject Hi --text Hello
# {"sourceTrackingId":"abc123-def456"}Homebrew Tap Setup
After publishing to npm, create the Homebrew tap in a separate repository named homebrew-paubox:
homebrew-paubox/
└── Formula/
└── paubox-cli.rbclass PauboxCli < Formula
desc "Official CLI for the Paubox encrypted email API"
homepage "https://github.com/Paubox/paubox-cli"
url "https://registry.npmjs.org/paubox-cli/-/paubox-cli-0.1.0.tgz"
sha256 "<sha256 of the npm tarball>"
license "Apache-2.0"
depends_on "node"
def install
system "npm", "install", *std_npm_args
bin.install_symlink libexec/"bin/paubox"
end
test do
assert_match "paubox", shell_output("#{bin}/paubox --version")
end
endTo get the SHA256: curl -s https://registry.npmjs.org/paubox-cli/0.1.0 | jq -r .dist.shasum
Development
git clone https://github.com/Paubox/paubox-cli.git
cd paubox-cli
npm install
npm test # Run tests
npm run lint # Lint
npm run build # Compile TypeScript
npm run dev -- auth status # Run without buildingProject structure
src/
commands/ auth, send, status, config, forms command handlers
lib/ api client, forms API client, credential storage, config store, output helpers
index.ts Library entry — exports createProgram() and run()
cli.ts Runtime entry — invokes run() (used by bin/ and `npm run dev`)
bin/
paubox.js Shebang wrapper (ships in npm package)
test/ Jest unit tests mirroring src/ structureReleasing
Releases are fully automated through Release Please and npm Trusted Publishers. No local commands, no tokens, no manual tagging.
Flow
- Land changes on
masterusing Conventional Commits:fix: ...→ patch bump (e.g. 0.1.0 → 0.1.1)feat: ...→ minor bump (e.g. 0.1.0 → 0.2.0)feat!: ...orBREAKING CHANGE:in the body → minor bump pre-1.0, major bump after 1.0chore: ...,docs: ...,refactor: ...,test: ...→ no version bump
- The release-please workflow opens (or updates) a PR titled
chore(master): release <next-version>with a generatedCHANGELOG.mdentry and the version bump inpackage.jsonand.release-please-manifest.json. - When that PR is merged, the same workflow creates the
paubox-cli-v<version>git tag + GitHub Release, then immediately runs a dependentpublishjob that validates the build and publishes to npm with provenance via OIDC.
Release-please and the publish job live in the same workflow file (release-please.yml) on purpose: a separate workflow listening for tag pushes would never fire, because tags created by GITHUB_TOKEN deliberately don't trigger downstream workflows. Chaining the jobs via needs: keeps the entire release in one run, no PAT required.
If the publish job ever fails for a transient reason (registry hiccup, OIDC rotation, etc.), recover by re-running just the failed job from the Actions UI — the release-please job already created the tag and Release, so re-running the publish job picks them up unchanged.
Setup requirements (one-time)
- Repository setting: Settings → Actions → General → Workflow permissions → Allow GitHub Actions to create and approve pull requests (so release-please can open the release PR).
- npm package setting: a trusted publisher must be configured at
npmjs.com/package/paubox-cli/access, pointing at this repo andrelease-please.yml.
License
Apache 2.0 — see LICENSE
