# ============================================================================= # Sprout Backend — Local Development Environment # ============================================================================= # Copy this file to .env and adjust as needed: # cp .env.example .env # # All defaults here work with `docker compose up` out of the box. # # Service ports (defaults): # Postgres → localhost:5432 # Redis → localhost:6379 # Typesense → localhost:8108 # Adminer → localhost:8082 (DB browser UI) # # Note: If port 8082 conflicts, change the adminer port in docker-compose.yml # ============================================================================= # ----------------------------------------------------------------------------- # Database (Postgres 17) # ----------------------------------------------------------------------------- DATABASE_URL=postgres://sprout:sprout_dev@localhost:5432/sprout PGHOST=localhost PGPORT=5432 PGUSER=sprout PGPASSWORD=sprout_dev PGDATABASE=sprout # ----------------------------------------------------------------------------- # Redis 7 # ----------------------------------------------------------------------------- REDIS_URL=redis://localhost:6379 # ----------------------------------------------------------------------------- # Typesense (search) # ----------------------------------------------------------------------------- TYPESENSE_API_KEY=sprout_dev_key TYPESENSE_URL=http://localhost:8108 # ----------------------------------------------------------------------------- # Relay (WebSocket server) # ----------------------------------------------------------------------------- # Bind address for the relay (host:port) SPROUT_BIND_ADDR=0.0.0.0:3000 # Public WebSocket URL — used in NIP-42 auth challenges RELAY_URL=ws://localhost:3000 # Stable relay signing key. Set this in dev if you want REST-created forum posts # to keep resolving to the original author across relay restarts. # SPROUT_RELAY_PRIVATE_KEY=<32-byte hex private key> # Set to true in production to require bearer token authentication SPROUT_REQUIRE_AUTH_TOKEN=false # ----------------------------------------------------------------------------- # Auth # ----------------------------------------------------------------------------- # Set to false for dev (accepts NIP-42 without JWT, allows X-Pubkey header). # Set to true in production to require bearer token authentication. SPROUT_REQUIRE_AUTH_TOKEN=false # JWKS endpoint for verifying JWT access tokens. # Claim that carries the user's Nostr public key (hex, 32 bytes). OKTA_PUBKEY_CLAIM=nostr_pubkey # ── Keycloak (local OAuth testing — stands in for Okta in prod) ────────────── # Keycloak is NOT a production dependency. It lets you test the full OAuth # flow locally without needing an Okta tenant. Run `docker compose up -d` # then `./scripts/setup-keycloak.sh` to create the realm, client, and users. # # Admin UI: http://localhost:8180 (admin / admin) # Get a token: # curl -s -X POST http://localhost:8180/realms/sprout/protocol/openid-connect/token \ # -d 'client_id=sprout-desktop&grant_type=password&username=tyler&password=password123' \ # | jq -r .access_token OKTA_JWKS_URI=http://localhost:8180/realms/sprout/protocol/openid-connect/certs OKTA_ISSUER=http://localhost:8180/realms/sprout OKTA_AUDIENCE=sprout-desktop # ── Okta (production / staging) ────────────────────────────────────────────── # Uncomment and fill in when deploying against a real Okta tenant. # OKTA_JWKS_URI=https://dev-example.okta.com/oauth2/default/v1/keys # OKTA_ISSUER=https://dev-example.okta.com/oauth2/default # OKTA_AUDIENCE=sprout-api # OKTA_PUBKEY_CLAIM=nostr_pubkey # ----------------------------------------------------------------------------- # Logging / Tracing # ----------------------------------------------------------------------------- RUST_LOG=sprout_relay=debug,sprout_db=debug,sprout_auth=debug,sprout_pubsub=debug,tower_http=debug # OTLP tracing endpoint (optional — leave unset to disable) # OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 # ----------------------------------------------------------------------------- # Huddle (LiveKit integration) # ----------------------------------------------------------------------------- # LIVEKIT_API_KEY=devkey # LIVEKIT_API_SECRET=devsecret # LIVEKIT_URL=ws://localhost:7880 # ----------------------------------------------------------------------------- # ACP (Agent Communication Protocol — sprout-acp harness) # ----------------------------------------------------------------------------- # The ACP harness bridges Sprout events to AI agents. Each env var below maps # to a CLI flag of the same name (lowercase, hyphens → underscores). All values # are optional unless noted; defaults are shown in comments. # # Quick start: # SPROUT_PRIVATE_KEY= SPROUT_RELAY_URL=ws://localhost:3000 sprout-acp # ── Identity & auth ────────────────────────────────────────────────────────── # Nostr private key (hex or bech32). REQUIRED — identifies the agent on the relay. # SPROUT_PRIVATE_KEY=<32-byte hex or nsec1… private key> # Bearer token for relay authentication (when SPROUT_REQUIRE_AUTH_TOKEN=true). # SPROUT_API_TOKEN= # Relay WebSocket URL the harness connects to. # Note: the relay itself uses RELAY_URL (above); this is the ACP harness's # connection target — they happen to point at the same place in local dev. # SPROUT_RELAY_URL=ws://localhost:3000 # ── Agent subprocess ───────────────────────────────────────────────────────── # Binary to spawn as the AI agent (e.g. "goose", "codex-acp", "claude-code"). # SPROUT_ACP_AGENT_COMMAND=goose # Comma-separated arguments passed to the agent binary. # Goose default: "acp". Codex/Claude default: "" (empty). # SPROUT_ACP_AGENT_ARGS=acp # Binary for the Sprout MCP server sidecar (provides channel tools to the agent). # SPROUT_ACP_MCP_COMMAND=sprout-mcp-server # Number of parallel agent subprocesses (1–32). # SPROUT_ACP_AGENTS=1 # Desired LLM model ID. Applied to every new ACP session. # Use `sprout-acp models` to discover available model IDs. # SPROUT_ACP_MODEL= # ── Timeouts & sessions ────────────────────────────────────────────────────── # Max seconds per agent turn before timeout (default 320 = ~5 min). # SPROUT_ACP_TURN_TIMEOUT=320 # Max turns per session before proactive rotation. 0 = disabled (rotate only # on MaxTokens / MaxTurnRequests). Recommended: 50 for long-running agents. # SPROUT_ACP_MAX_TURNS_PER_SESSION=0 # ── Prompts ────────────────────────────────────────────────────────────────── # System prompt injected into every agent session (inline text). # SPROUT_ACP_SYSTEM_PROMPT= # Path to a file containing the system prompt (mutually exclusive with above). # SPROUT_ACP_SYSTEM_PROMPT_FILE= # Message sent to the agent immediately after session creation. # SPROUT_ACP_INITIAL_MESSAGE= # ── Heartbeat ──────────────────────────────────────────────────────────────── # Seconds between heartbeat prompts. 0 = disabled. Must be 0 or ≥10. # Recommended: 60 for long-running agents to prevent idle session timeouts. # SPROUT_ACP_HEARTBEAT_INTERVAL=0 # Heartbeat prompt text (inline). Mutually exclusive with file variant. # SPROUT_ACP_HEARTBEAT_PROMPT= # Path to a file containing the heartbeat prompt. # SPROUT_ACP_HEARTBEAT_PROMPT_FILE= # ── Subscription & filtering ───────────────────────────────────────────────── # Subscribe mode: "mentions" (default), "all", or "config" (rule-based). # SPROUT_ACP_SUBSCRIBE=mentions # Comma-separated event kind numbers to subscribe to (overrides mode defaults). # SPROUT_ACP_KINDS= # Comma-separated channel UUIDs to limit subscription scope. # SPROUT_ACP_CHANNELS= # Set to true to disable the @-mention filter in mentions mode. # SPROUT_ACP_NO_MENTION_FILTER=false # Path to TOML config file for rule-based subscriptions (config mode). # SPROUT_ACP_CONFIG=./sprout-acp.toml # ── Dedup & self-ignore ────────────────────────────────────────────────────── # How to handle duplicate events: "queue" (default) or "drop". # SPROUT_ACP_DEDUP=queue # Set to true to process the agent's own messages (default: ignore self). # SPROUT_ACP_NO_IGNORE_SELF=false # ── Context ────────────────────────────────────────────────────────────────── # Max context messages fetched for thread replies and DMs (0–100). 0 = disabled. # SPROUT_ACP_CONTEXT_MESSAGE_LIMIT=12 # ── Presence & typing ──────────────────────────────────────────────────────── # Set to true to disable automatic online/offline presence status. # SPROUT_ACP_NO_PRESENCE=false # Set to true to disable typing indicators while the agent is processing. # SPROUT_ACP_NO_TYPING=false # ── Advanced tuning ────────────────────────────────────────────────────────── # Event channel buffer capacity (WebSocket → harness). Increase for # high-throughput agents. Minimum 1. # SPROUT_ACP_EVENT_BUFFER=256 # ── Legacy aliases ─────────────────────────────────────────────────────────── # These are accepted for backward compatibility but the canonical names above # are preferred: # SPROUT_ACP_PRIVATE_KEY → SPROUT_PRIVATE_KEY # SPROUT_ACP_API_TOKEN → SPROUT_API_TOKEN