> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pendpost.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Nostr

> Set up Nostr posting with a keypair you mint yourself and a list of relays.

The Nostr lane publishes notes to a set of relays. It publishes only once a Nostr credential is present in your `.env`; until then the lane is live-but-unauthenticated and waits for you to connect it (set `PENDPOST_MODE=mock` to exercise it through the mock driver).

Nostr has no accounts and no central service, only a keypair you hold. You are responsible for how you use it. pendpost drafts and schedules, but a human approves before anything goes live.

> [!NOTE]
>
> **Text only.** The Nostr protocol has no media hosting, so a media post publishes its caption and logs a warning. Deletion is a request (NIP-09) that relays may ignore.

> [!NOTE]
>
> **Node 22+.** The Nostr lane needs the global WebSocket client, so it requires Node 22 or newer. The other lanes also require Node 22 or newer.

## Setup ceremony

The private key (`nsec`) is the account: anyone holding it can post as you, so treat it like a password.

1. **Mint or import a keypair.** Run the keygen CLI below to mint a fresh `nsec`/`npub` pair, or reuse an existing `nsec` from any Nostr client.

   ```bash theme={null}
   node scripts/nostr-social.mjs keygen --save
   ```

2. **Choose relays.** Posts are published to every relay in a comma-separated list, and one acceptance counts as published. Public defaults such as `wss://relay.damus.io,wss://nos.lol` work; a private relay works too.

Then validate. It derives your `npub` and proves at least one relay is reachable:

```bash theme={null}
node scripts/nostr-social.mjs auth
```

## Environment variables

| Variable | Purpose |
| - | - |
| `NOSTR_PRIVATE_KEY` | Your `nsec` private key. It is the account; treat it like a password. |
| `NOSTR_RELAYS` | A comma-separated list of relay URLs (`ws://` or `wss://`). |

> [!NOTE]
>
> A lane publishes only once its credential is present. If the Nostr variables are blank, the Nostr lane is live-but-unauthenticated and waits for you to connect it. Set `PENDPOST_MODE=mock` to exercise it through the mock driver.

## Validate the lane

A present credential is not the same as a working one. After setup, validate the Nostr lane in the **Setup** tab, or run a live probe with the `health_recheck` tool, to confirm the credential is live and not just configured. The lane is ready when it reports live.

> [!NOTE]
>
> **Over MCP.** Setup and rotation are an interactive human ceremony; secrets are never written through MCP. An agent can still check status (`account_status`), run a live liveness probe (`health_recheck`), and read non-secret config (`config_get`) over MCP without touching credentials.

## Common failures

| Symptom | Cause | Fix |
| - | - | - |
| auth reports no reachable relay. | The relay URLs are wrong (must be `ws://` or `wss://`), or the relay is down or blocking writes. | Test with a known-good public relay (`wss://relay.damus.io`) and re-run auth. |
| The engine refuses to start with a WebSocket error. | Node is older than 22, so the global WebSocket client is missing. | Upgrade Node to 22+ for the Nostr lane. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.