Skip to content

nerve-ink/nerve-cli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nerve-cli

Website Go Reference

Website · Start · App Store · Google Play · Run agent

Encrypted CI/CD, cron, webhook and server alerts to iPhone and Android.

Sender secrets can only send. Relay sees ciphertext. Actions are optional.

echo "deploy failed" | nerve send

Start with signals

  1. Create a pipe in the Nerve mobile app.
  2. Open Pipe Setup and choose Send signals.
  3. Copy the sender DSN.
  4. Install nerve.
  5. Send your first encrypted alert:
curl -fsSL https://nerve.ink/install.sh | sh
export NERVE_DSN="nerve://TOKEN:SENDER_KEY@api.nerve.ink"
echo "deploy failed" | nerve send --title "Nerve test"

Expected output:

sent

The phone receives an encrypted signal. The relay routes ciphertext; decryption happens locally on the device that owns the pipe.

NerveOps is available on the App Store and Google Play.

nerve send is the safe first Nerve integration. It reads plaintext from stdin, encrypts it locally with the sender key from NERVE_DSN, and posts only ciphertext to the Nerve relay.

The sender DSN can send signals into one pipe. It cannot read history, decrypt old messages, connect as an agent, or execute commands.

Why this is not just a webhook

Boundary What happens
CI secret leaks A sender DSN can create alert noise in one pipe. It cannot read history, decrypt content, connect as an agent, or execute commands.
Relay receives traffic The relay routes encrypted records and delivery metadata. Signal content is encrypted before it reaches the relay.
Phone receives push APNs/FCM wake or notify the device. Clients sync the encrypted record and decrypt locally.
Agent is needed Use nerve-agent only when you want signed actions on a machine you control.

Copy-paste Examples

Install

Recommended:

curl -fsSL https://nerve.ink/install.sh | sh

Go fallback / developer install:

go install github.com/nerve-ink/nerve-cli/cmd/nerve@latest
export PATH="$PATH:$(go env GOPATH)/bin"
nerve --help

Docker

Use the Docker image when you want nerve send in CI, cron, or a host where you do not want to install Go or a local binary.

echo "deploy failed" | docker run -i --rm \
  -e NERVE_DSN="nerve://TOKEN:SENDER_KEY@api.nerve.ink" \
  p1xel32/nerve-cli:latest send

GitHub Container Registry mirror:

echo "deploy failed" | docker run -i --rm \
  -e NERVE_DSN="nerve://TOKEN:SENDER_KEY@api.nerve.ink" \
  ghcr.io/nerve-ink/nerve-cli:latest send

The image is send-only. It does not run an agent and cannot execute commands. For signed actions on a trusted host, use nerve-agent.

Flags

echo "deploy failed" | nerve send \
  --severity critical \
  --title "Deploy failed"

Common flags:

Flag Default Purpose
--dsn NERVE_DSN Sender DSN. Prefer an env var or CI secret.
--severity standard Signal severity, for example standard, alert, critical.
--title empty Optional short title shown by clients.
--kind alert Signal kind metadata.
--timeout 10s HTTP request timeout.

GitHub Actions

Store the sender DSN as a repository or organization secret named NERVE_DSN.

name: Notify Nerve

on:
  workflow_run:
    workflows: ["Backend Deploy"]
    types: [completed]

jobs:
  notify:
    runs-on: ubuntu-latest
    steps:
      - name: Install nerve
        run: curl -fsSL https://nerve.ink/install.sh | sh
      - name: Send encrypted deploy signal
        env:
          NERVE_DSN: ${{ secrets.NERVE_DSN }}
        run: |
          printf 'deploy %s\nrun: %s\n' \
            "${{ github.event.workflow_run.conclusion }}" \
            "${{ github.event.workflow_run.html_url }}" \
            | nerve send --title "Backend Deploy"

For a regular job, send only on failure:

- name: Install nerve
  run: curl -fsSL https://nerve.ink/install.sh | sh
- name: Notify Nerve on failure
  if: failure()
  env:
    NERVE_DSN: ${{ secrets.NERVE_DSN }}
  run: |
    printf 'FAILED: %s\nbranch: %s\nrun: %s\n' \
      "${{ github.repository }}" \
      "${{ github.ref_name }}" \
      "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
      | nerve send --severity critical --title "CI failed"

Keep the signal short: repository, branch/environment, status, commit SHA, and run URL. Do not pipe full logs or secrets into phone alerts.

Example message:
deploy success
sha: b62b038
run: https://github.com/nerve-ink/nerve-ops/actions/runs/26969431142

Cron

#!/usr/bin/env bash
set -euo pipefail

export NERVE_DSN="nerve://TOKEN:SENDER_KEY@api.nerve.ink"

if ! /opt/jobs/backup.sh; then
  echo "backup failed on $(hostname)" | nerve send --severity alert
  exit 1
fi

Crontab:

15 3 * * * /opt/jobs/backup-with-nerve.sh

Bash / Smoke Tests

if ./smoke.sh; then
  echo "smoke passed: api-prod" | nerve send
else
  echo "smoke failed: api-prod" | nerve send --severity critical
fi

Security Model

A sender DSN contains:

  • a sender token
  • a sender encryption key
  • the relay host

If it leaks, an attacker can send fake signals into that one pipe until the credential is rotated.

They cannot:

  • read history
  • decrypt old messages
  • connect as an agent
  • execute commands

Do not put secrets, tokens, private keys, or full environment dumps into signal text. Send short operational context: service, environment, status, commit SHA, and a run URL.

Rotate a Sender DSN

  1. Open pipe setup in the mobile app.
  2. Create a new Send signals credential.
  3. Update your CI secret or server env var.
  4. Delete the old sender credential.

Troubleshooting

go: command not found

Use the recommended installer instead of the Go fallback:

curl -fsSL https://nerve.ink/install.sh | sh

The Go path is only for local development or environments that intentionally build from source.

415 Unsupported Media Type

You are probably calling the old nerve shell function or a generic webhook instead of the Go CLI. Check:

type nerve
which nerve
nerve --help

The current CLI prints sent on success and sends Content-Type: application/json automatically.

go install cannot read the repository

Use the public module path exactly:

go install github.com/nerve-ink/nerve-cli/cmd/nerve@latest

If Go reports that GitHub needs credentials, verify that your environment is not rewriting GitHub URLs to a private mirror or stale local fork.

nerve: NERVE_DSN or --dsn is required

Export the DSN copied from pipe setup:

export NERVE_DSN="nerve://TOKEN:SENDER_KEY@api.nerve.ink"

Or pass it directly:

echo "deploy failed" | nerve send --dsn "nerve://TOKEN:SENDER_KEY@api.nerve.ink"

Signal says sent, but I do not see it

Check that:

  • the phone is signed into the same Nerve account
  • notifications are allowed
  • the sender DSN belongs to the pipe you are watching
  • the app can decrypt the pipe keys

Agent

Need signed actions from a machine you control? Use nerve-agent.

The agent is the advanced path. Start with send-only signals unless you explicitly need remote actions.

About

Docker and CLI phone alerts for failed deploys, CI, cron, backups, and smoke tests with a send-only encrypted NerveOps secret.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors