5.2 KiB
5.2 KiB
AGENTS.md - AI Agent Integration Guide
Project-Specific Information for AI Agents Working with C-Relay
Critical Build Commands
Primary Build Command
./make_and_restart_relay.sh
Never use make directly. The project requires the custom restart script which:
- Handles database preservation/cleanup based on flags
- Manages architecture-specific binary detection (x86/ARM64)
- Performs automatic process cleanup and port management
- Starts relay in background with proper logging
Architecture-Specific Binary Outputs
- x86_64:
./build/c_relay_x86 - ARM64:
./build/c_relay_arm64 - Other:
./build/c_relay_$(ARCH)
Database File Naming Convention
- Format:
<relay_pubkey>.db(NOT.nrdbas shown in docs) - Location: Created in
build/directory during execution - Cleanup: Use
--preserve-databaseflag to retain between builds
Critical Integration Issues
Event-Based Configuration System
- No traditional config files - all configuration stored in config table
- Admin private key shown only once on first startup
- Configuration changes require cryptographically signed events
- Database path determined by generated relay pubkey
First-Time Startup Sequence
- Relay generates admin keypair and relay keypair
- Creates database file with relay pubkey as filename
- Stores default configuration in config table
- CRITICAL: Admin private key displayed once and never stored on disk
Port Management
- Default port 8888 with automatic fallback (8889, 8890, etc.)
- Script performs port availability checking before libwebsockets binding
- Process cleanup includes force-killing processes on port 8888
Database Schema Dependencies
- Uses embedded SQL schema (
sql_schema.h) - Schema version 4 with JSON tag storage
- Critical: Event expiration filtering done at application level, not SQL level
Admin API Event Structure
{
"kind": 23456,
"content": "base64_nip44_encrypted_command_array",
"tags": [
["p", "<relay_pubkey>"]
]
}
Configuration Commands (encrypted in content):
["relay_description", "My Relay"]["max_subscriptions_per_client", "25"]["pow_min_difficulty", "16"]
Auth Rule Commands (encrypted in content):
["blacklist", "pubkey", "hex_pubkey_value"]["whitelist", "pubkey", "hex_pubkey_value"]
Query Commands (encrypted in content):
["auth_query", "all"]["system_command", "system_status"]
Process Management
# Kill existing relay processes
pkill -f "c_relay_"
# Check running processes
ps aux | grep c_relay_
# Force kill port binding
fuser -k 8888/tcp
Cross-Compilation Specifics
- ARM64 requires explicit dependency installation:
make install-arm64-deps - Uses
aarch64-linux-gnu-gccwith specific library paths - PKG_CONFIG_PATH must be set for ARM64:
/usr/lib/aarch64-linux-gnu/pkgconfig
Testing Integration
- Tests expect relay running on default port
- Use
tests/quick_error_tests.shfor validation - Event configuration tests:
tests/event_config_tests.sh
SystemD Integration Considerations
- Service runs as
c-relayuser in/opt/c-relay - Database files created in WorkingDirectory automatically
- No environment variables needed (event-based config)
- Resource limits: 65536 file descriptors, 4096 processes
Development vs Production Differences
- Development:
make_and_restart_relay.sh(default database cleanup) - Production:
make_and_restart_relay.sh --preserve-database - Debug build requires manual gdb attachment to architecture-specific binary
Critical File Dependencies
nostr_core_lib/submodule must be initialized and built first- Version header auto-generated from git tags:
src/version.h - Schema embedded in binary from
src/sql_schema.h
WebSocket Protocol Specifics
- Supports both WebSocket (Nostr protocol) and HTTP (NIP-11)
- NIP-11 requires
Accept: application/nostr+jsonheader - CORS headers automatically added for NIP-11 compliance
Memory Management Notes
- Persistent subscription system with thread-safe global manager
- Per-session subscription limits enforced
- Event filtering done at C level, not SQL level for NIP-40 expiration
Configuration Override Behavior
- CLI port override only affects first-time startup
- After database creation, all config comes from events
- Database path cannot be changed after initialization
Non-Obvious Pitfalls
- Database Lock Issues: Script handles SQLite locking by killing existing processes first
- Port Race Conditions: Pre-check + libwebsockets binding can still fail due to timing
- Key Loss: Admin private key loss requires complete database deletion and restart
- Architecture Detection: Build system auto-detects but cross-compilation requires manual setup
- Event Storage: Ephemeral events (kind 20000-29999) accepted but not stored
- Signature Validation: All events validated with
nostr_verify_event_signature()from nostr_core_lib
Quick Debugging Commands
# Check relay status
ps aux | grep c_relay_ && netstat -tln | grep 8888
# View logs
tail -f relay.log
# Test WebSocket connection
wscat -c ws://localhost:8888
# Test NIP-11 endpoint
curl -H "Accept: application/nostr+json" http://localhost:8888
# Find database files
find . -name "*.db" -type f