Files
timmy-home/nostr/COMMS_MIGRATION.md

4.4 KiB

Nostr Comms Pipeline — Integration Guide

Status

  • Nostr relay: RUNNING on relay.alexanderwhitestone.com:2929 (relay29/khatru29, NIP-29)
  • Agent keys: EXISTING for timmy, claude, gemini, groq, grok, hermes, alexander
  • Bridge: RUNNING nostr-bridge on Allegro VPS
  • Group: NOT YET CREATED (khatru29 requires NIP-42 auth for writes)

Architecture

Timmy Hermes Gateway → Nostr Client → Relay:2929 ← Alexander Phone (Damus)
                                       ↑
                              Other Wizards ← nostr_client.py

What Works Right Now

  1. Nostr relay is live and serving WebSocket connections on port 2929
  2. Event signing via coincurve schnorr works (raw Python)
  3. pynostr Event class can create and sign events
  4. websockets library can connect to relay (ws://127.0.0.1:2929 on VPS)
  5. Relay requires NIP-42 AUTH handshake for writes (khatru29 default)

What's Blocked

  • NIP-42 auth event signing: the relay returns ["AUTH", challenge] but our signed 22242 events are rejected with "signature is invalid"
  • The nostr-sdk Python bindings (v0.44.2) have incompatible API vs what the code expects
  • pynostr's Event.sign() doesn't exist (uses pk.sign_event() instead)
  • coincurve.sign_schnorr() works but the auth event format might not match what khatru29 expects

How to Fix NIP-42 Auth (Next Session)

Option 1: Disable AUTH requirement on the relay (quick but insecure)

On 167.99.126.228, add to relay29 options:

relay.RequireNIP07Auth = false
// or
state.AllowEvent = func(context.Context, nostr.Event, string) (bool, string) {
    return true, "" // allow all
}

Option 2: Fix the auth event properly

The auth event (kind 22242) needs:

Python code that should work:

from nostr.key import PrivateKey
pk = PrivateKey.from_nsec(nsec)

# Create auth event with challenge as CONTENT
evt = Event(
    public_key=pk.hex(),
    created_at=int(time.time()),
    kind=22242,
    content=challenge,  # <-- this is the key
    tags=[["relay", "relay.alexanderwhitestone.com:2929"]]
)
pk.sign_event(evt)

# Send as AUTH event (full event object, not just ID)
await ws.send(json.dumps(["AUTH", {
    "id": evt.id,
    "pubkey": evt.public_key,
    "created_at": evt.created_at,
    "kind": evt.kind,
    "tags": evt.tags,
    "content": evt.content,
    "sig": evt.signature
}]))

Option 3: Use the relay's admin key to create the group

The relay has an admin private key in the RELAY_PRIVKEY env var. Can create the group via the relay's Go code by adding an admin-only endpoint.

Group Creation (Once Auth Works)

# On the VPS, run this Python script
python3 -c "
import asyncio, json, time
import websockets
from nostr.key import PrivateKey
from nostr.event import Event

pk = PrivateKey.from_nsec('timmy-nsec-here')

async def create_group(code):
    evt = Event(
        public_key=pk.hex(),
        created_at=int(time.time()),
        kind=39000,
        tags=[['d', code], ['name', 'Timmy Time'], ['about', 'The Timmy household']],
        content=''
    )
    pk.sign_event(evt)
    print(f'Group event: {evt.id[:16]}')
    print(f'Group code: {code}')

asyncio.run(create_group('b082d1'))
"

Adding Members to the Group

After the group is created, add members via kind 9 events with "h" tag:

evt = Event(
    public_key=pk.hex(),
    created_at=int(time.time()),
    kind=9,
    tags=[['h', group_code], ['p', member_pubkey_hex]],
    content='Welcome to Timmy Time'
)
pk.sign_event(evt)

Wiring Hermes to Nostr

To replace Telegram sends with Nostr:

  1. Add ~/.timmy/nostr/nostr_sender.py — imports coincurve, websockets
  2. In Hermes tools: replace send_telegram_message() with send_nostr_message()
  3. Morning report cron calls the Nostr sender
  4. Fallback: if Nostr relay unreachable, use Telegram

Current Credentials

Agent npub hex_pub
Timmy npub1qwyndfwvwy4edlwgtg3jlssawg7aj36t78fqyk30ehtyd82j22nqzt5m94 038936a5cc712b96fdc85a232fc21d723dd9474bf1d2025a2fcdd6469d5252a6
Claude npub1s8rew66kl357hj20qth5uympp9yvj5989ye2grw0r9467eafe9ds7s2ju7 81c7976b56fc69ebc94f02ef4e13610948c950a72932a40dcf196baf67a9c95b
Gemini npub1sy4sqms6559arup5lxquadzahevcyy5zu028d8rw9ez4h957j6yq3usedv 812b006e1aa50bd1f034f981ceb45dbe59821282e3d4769c6e2e455b969e9688

Keys file: ~/.timmy/nostr/agent_keys.json