Nostr CLI for Cobot agents - keygen, DMs, identity management
  • Python 99.6%
  • Shell 0.4%
Find a file
nazim 9f61a9e8c0
All checks were successful
CI / test (3.11) (push) Successful in 7s
CI / test (3.12) (push) Successful in 8s
CI / lint (push) Successful in 6s
CI / test (3.13) (push) Successful in 8s
refactor: replace NIP-04 + custom crypto with nostr-sdk + NIP-44 (#1)
## What

Replaces all custom cryptography and NIP-04 encryption with `nostr-sdk` (rust-nostr Python bindings) and NIP-44.

## Why

- **NIP-04 is deprecated** — known vulnerabilities (no padding, IV reuse risks, metadata leaks)
- **NIP-44** is the replacement (XChaCha20-Poly1305, HMAC-SHA256 key derivation, proper padding)
- **4 dependencies → 1** — `websockets` + `cryptography` + `secp256k1` + `bech32` all replaced by `nostr-sdk`
- `nostr-sdk` handles key management, event signing, relay connections, and encryption — no reason to reimplement any of it

## Changes

### Encryption
- **Outgoing DMs:** NIP-44 V2 (was NIP-04)
- **Incoming DMs:** NIP-44 first, NIP-04 fallback (backwards compatible)

### Dependencies
- **Before:** `websockets`, `cryptography`, `secp256k1`, `bech32`
- **After:** `nostr-sdk` (single dependency, Rust-backed)

### Key management
- `generate_keypair()` → `Keys.generate()`
- `load_identity()` → `Keys.parse()` (handles nsec, hex automatically)
- No more manual bech32 ↔ hex conversion

### Relay communication
- Custom websocket code → `nostr-sdk.Client` (connection pooling, auto-reconnect)
- Event signing via `EventBuilder.sign_with_keys()`

### Unchanged
- Injection shield (regex + local DeBERTa)
- Wake mechanism
- CLI interface and all commands

## Tests

28/28 passing — updated for nostr-sdk API, added NIP-44 roundtrip, NIP-04 backwards compat, and wrong-key-fails tests.

Co-authored-by: Nazim <nazim@al-munazzim.github.io>
Co-authored-by: Nazim <nazim@openclaw.ai>
Reviewed-on: #1
Co-authored-by: nazim <nazim@olymp.local>
Co-committed-by: nazim <nazim@olymp.local>
2026-02-23 07:38:38 +00:00
.github/workflows refactor: replace NIP-04 + custom crypto with nostr-sdk + NIP-44 (#1) 2026-02-23 07:38:38 +00:00
bin Initial commit: Nostr CLI for Cobot agents 2026-02-19 20:06:45 +00:00
.gitignore feat: add timestamped logging for DM receipt and wake calls 2026-02-22 19:38:51 +00:00
nostr_cli.py refactor: replace NIP-04 + custom crypto with nostr-sdk + NIP-44 (#1) 2026-02-23 07:38:38 +00:00
README.md Integrate local DeBERTa prompt-guard service 2026-02-20 08:28:54 +00:00
requirements.txt refactor: replace NIP-04 + custom crypto with nostr-sdk + NIP-44 (#1) 2026-02-23 07:38:38 +00:00
test_e2e.py refactor: replace NIP-04 + custom crypto with nostr-sdk + NIP-44 (#1) 2026-02-23 07:38:38 +00:00
test_nostr_cli.py refactor: replace NIP-04 + custom crypto with nostr-sdk + NIP-44 (#1) 2026-02-23 07:38:38 +00:00

Nostr CLI

Command-line tool for Nostr identity management and encrypted DMs (NIP-04).

Features:

  • 🔑 Key generation (nsec/npub)
  • 📨 Send & receive encrypted DMs
  • 🛡️ Prompt injection shield (blocks malicious messages)
  • Wake mechanism (alert agents on new DMs)

Installation

# Create venv and install deps
python3 -m venv venv
./venv/bin/pip install -r requirements.txt

# Make CLI executable
chmod +x bin/nostr

# Add to PATH (optional)
export PATH="$PATH:$(pwd)/bin"

Commands

Generate Keypair

nostr keygen

Show Identity

export NOSTR_NSEC="nsec1..."
nostr whoami

Listen for DMs

nostr listen

With wake notifications:

nostr listen --wake-url http://localhost:18793/hooks/wake --wake-token filedrop-wake-olymp

Disable injection shield (not recommended):

nostr listen --no-shield

Send DM

nostr send npub1abc... "Hello!"

Test Wake

nostr wake --url http://localhost:18793/hooks/wake "Test message"

Environment Variables

Variable Description
NOSTR_NSEC Private key (nsec1... or hex)
NOSTR_WAKE_URL Wake endpoint URL
NOSTR_WAKE_TOKEN Wake auth token
NOSTR_AGENT_NAME Agent name (for registry lookup)
NOSTR_REGISTRY Path to agents.json

Security Features

Injection Shield (Two Layers)

Incoming DMs are scanned for prompt injection:

Layer 1: Regex (fast, ~80%)

  • Instruction override attempts
  • System prompt injection
  • Roleplay jailbreaks
  • Credential extraction
  • Tool abuse attempts

Layer 2: Local DeBERTa Model (~99%, multilingual)

  • Uses protectai/deberta-v3-base-prompt-injection-v2
  • Runs on olymp at http://localhost:8080
  • Catches obfuscated attacks, language switching, etc.

Disable local model with --no-local-shield (regex only). Disable entirely with --no-shield.

Wake Mechanism

When a DM arrives, the CLI can notify an agent via webhook:

POST /hooks/wake
Authorization: Bearer <token>
{"text": "Nostr DM from npub1...: message preview", "mode": "now"}

Compatible with OpenClaw hooks and filedrop wake system.

Integration with agents.json

The CLI can read wake config from /olymp/agents.json:

{
  "agents": {
    "Hermes": {
      "wake": {
        "method": "hooks",
        "url": "http://localhost:18793/hooks/wake",
        "token": "filedrop-wake-olymp"
      }
    }
  }
}

Set NOSTR_AGENT_NAME=Hermes to use this config.

Credits

  • Original listener script by noopsec
  • Refactored with shield + wake by Hermes 🪽