This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.
DeepFry is a modular backend stack for Humble Horse that surrounds a stock (unmodified) StrFry Nostr relay with sidecar services for discovery, trust scoring, and search. The core principle: never fork StrFry — extend via its JSON plugin interface and external services.
Data separation rule: canonical events live only in StrFry's LMDB. Dgraph stores ID-only graphs (pubkey relationships). No event payloads outside StrFry.
Upstream Relays → Event Forwarder → StrFry Relay (LMDB, port 7777)
├── Whitelist Plugin → Dgraph (accept/reject writes)
└── Search Plugin (planned) → Semantic Search (planned)
Web of Trust Crawler → subscribes kind 3 from StrFry → writes pubkey graph to Dgraph
Production-ready subsystems: event-forwarder, whitelist-plugin, web-of-trust, quarantine-rescuer Placeholder subsystems: search-plugin, semantic-search, embeddings-generator, profile-builder, thread-inference
Each subsystem is an independent Go module with its own Makefile. Always cd into the subsystem first.
make build # Compile to bin/
make test # Unit tests (-short)
make lint # golangci-lint (warns, doesn't fail)
make lint-fix # Auto-fix lint issues
make fmt # go fmt
make vet # go vet
make tidy # go mod tidy
make clean # Remove bin/make build-alpine # Static binary for Alpine (CGO_ENABLED=0)
make docker-build # Docker image with version injection
make test-integration # Integration testsmake build-crawler # Build crawler binary
make build-pubkeys # Build pubkeys exportermake bench # Run benchmarks
make build-alpine # Static Alpine binaryOne-shot CLI that pulls events for newly-whitelisted pubkeys from the
quarantine LMDB back into the main StrFry instance. Reads ~/deepfry/whitelist.yaml
for the whitelist server URL (same config the live plugin uses). Runs on the
strfry host; calls docker exec against the quarantine container.
make build # ./bin/quarantine-rescue
./bin/quarantine-rescue --dry-run # preview only# Start Dgraph + Ratel UI + Whitelist Server
docker-compose -f docker-compose.dgraph.yml up -d
# Start StrFry
docker-compose -f docker-compose.strfry.yml up -d
# Start event forwarders (requires .env with keys)
docker-compose -f docker-compose.evtfwd.yml up -d- StrFry:
ws://localhost:7777 - Dgraph HTTP/GraphQL:
http://localhost:8080 - Dgraph gRPC:
localhost:9080 - Dgraph Ratel UI:
http://localhost:8000
Secrets go in .env (see .env.example). Keys: STRFRY_PRIVATE_KEY, NOSTR_SYNC_SECKEY_LIVE, NOSTR_SYNC_SECKEY_HISTORY.
All DeepFry config files live in ~/deepfry/. Never delete, overwrite, or rm files in this directory. When testing config loading, use a temporary directory instead.
~/deepfry/web-of-trust.yaml— web-of-trust crawler config~/deepfry/whitelist.yaml— whitelist plugin config
- StrFry must stay unmodified — extend only via its stdin/stdout JSON plugin protocol
- Use standard Nostr WebSocket (NIP-01) for all relay communication
- Sync progress events must be kind 30078 with tags:
d,from,to - One forwarder instance per source relay to avoid race conditions
- Secrets via env vars, never logged raw
- Go 1.24.1+
github.com/nbd-wtf/go-nostr— Nostr protocol librarygithub.com/dgraph-io/dgo/v210— Dgraph gRPC client (web-of-trust)github.com/spf13/viper— YAML config (web-of-trust)- golangci-lint (optional, for linting)
The Profile type in config/dgraph/schema.graphql has: pubkey (@id), follows, followers, kind3CreatedAt, last_db_update. The whitelist plugin queries this to determine which pubkeys may write events.