Skip to content

About

The Nervly local CLI — environment detection, secret management (SOPS/age) and webhook forwarding for developers.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

@nervly/cli — the Nervly local CLI

A local CLI with environment detection, secret management and webhook forwarding. It talks to the same gateway API the SDK does; there is no second send surface (there is deliberately no nervly send).

nervly doctor                 # environment detection diagnostics
nervly env                    # print the resolved environment (--json)
nervly secrets …              # local, SOPS-compatible secret store
nervly forward webhooks …     # relay delivery webhooks to a local receiver
nervly login / logout         # console-session auth for management commands
nervly config show/set        # inspect/override the active profile

Install

npm install -g @nervly/cli     # prebuilt platform binary
cargo install nervly-cli       # from source
brew install igmrrf/taps/nervly # Homebrew

Prebuilt binaries for aarch64/x86_64 × darwin/linux and x86_64 windows are published on GitHub Releases with signed checksums; shell completions and a man page ship inside every artifact.

Environment detection

Before every command the CLI resolves which environment it points at. First hit wins, and conflicts are loud, never silent:

Step Environment
1 --env live|test|local
2 NERVLY_ENV
3 the API key's mode segment (nervly_sk_test_… ⇒ test)
4 the base-URL shape (localhost/127.0.0.1 ⇒ local)
5 the active profile, then an interactive prompt

Base URL: --base-url → the profile override → the environment default (local ⇒ http://localhost:8080, live ⇒ https://api.nervly.io, test ⇒ https://sandbox-api.nervly.io). A test resolution never falls back to the production base — if the sandbox base is unreachable the command fails loudly.

Credentials: --api-key → NERVLY_API_KEY → a .env file that defines NERVLY_API_KEY → none. A key whose mode disagrees with the resolved environment fails the command unless --force is given.

Secrets

nervly secrets manages your local secrets in .nervly/secrets.enc.yaml — a bit-for-bit SOPS-compatible age-encrypted YAML file. Nervly never sees them. The real sops binary decrypts what the CLI writes, and the CLI decrypts what sops -e writes.

nervly secrets set DB_PASSWORD          # value read from stdin, never argv
nervly secrets get DB_PASSWORD          # redacted; --reveal to print
nervly secrets list
nervly secrets remove DB_PASSWORD
nervly secrets import secrets/prod.enc.yaml
nervly secrets encrypt plain.yaml       # → plain.enc.yaml
nervly secrets decrypt secrets/prod.enc.yaml
nervly secrets run -- your-command      # store decrypted into the child env

Values are never printed unredacted, never logged, never emitted in --json, and the store is 0600 after every write. The age identity is found the same way sops finds it (SOPS_AGE_KEY, SOPS_AGE_KEY_FILE, or ~/.config/sops/age/keys.txt).

Webhook forwarding

nervly forward webhooks --to http://localhost:3000/webhooks/nervly

The CLI dials out to the Nervly relay (GET /v1/relay/tunnel), receives real recorded delivery events down the SSE tunnel, re-signs each body locally with HMAC-SHA256 (x-nervly-signature, verified by the SDK's nervly.webhooks.verifySignature) using a secret drawn from the CLI store, and posts it to your receiver. It never synthesizes a delivery: if the relay is unreachable it delivers nothing and exits non-zero. The tunnel is workspace-scoped and at-least-once.

Console sessions

nervly login runs the device-code flow, shows a code and a browser URL, and stores the resulting session token in the OS keychain (never the profile file, never the secret store). Management commands (e.g. nervly config show) accept the session; data-plane calls never do — a console session cannot authorize the relay tunnel or any /v1 call.

Development

make dev            # cargo build + macOS dev-sign + run (ARGS=... to pass flags)
make dev-sign       # sign target/debug/nervly with the stable macOS identity
cargo test          # unit + integration; requires `sops` and `age-keygen`
cargo clippy --all-targets -- -D warnings

The integration suites drive the built binary and a real sops/age interop — no simulated crypto. The contract-drift test reads the sibling nervly-docs OpenAPI spec and the nervly-gate key parser.

On macOS, cargo build ad-hoc signs the binary, so its code identity changes on every rebuild and the OS re-prompts for the keychain session nervly login stored. make dev / make dev-sign signs the debug binary with one persistent self-signed nervly-dev identity instead (created on first use in its own ~/Library/Keychains/nervly-dev keychain, via scripts/dev-sign.sh; the first run asks macOS once to trust the certificate), so rebuilds read the session silently. The identity is local-only and is never used for release artifacts.

About

The Nervly local CLI — environment detection, secret management (SOPS/age) and webhook forwarding for developers.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages