# Every knob ai-crew-sync reads, with its default. Copy to `.env` and change
# what you need — a bare `make up` works with this file absent, because the
# compose file carries the same defaults.
#
# THESE ARE LOCAL DEFAULTS. A production deploy uses the overlay
# Docker/docker-compose.prod.yml, which has no fallbacks: it refuses to render
# until POSTGRES_PASSWORD, BUS_VERSION, BUS_ALLOWED_HOSTS and
# BUS_DASHBOARD_SECRET are set, and `make deploy` additionally rejects the
# example password and a moving `latest` tag.
#
# Docker Swarm does NOT read .env files: export the variables, or use
# `env $(cat .env | xargs) docker stack deploy -c Docker/docker-compose.yml crew`.
# ---------------------------------------------------------------- compose --
# Keeps container and volume names stable regardless of directory layout.
COMPOSE_PROJECT_NAME=ai-crew-sync
# Database password. CHANGE IT for anything reachable from outside this
# machine — it is the only credential in front of your team's traffic.
POSTGRES_PASSWORD=change-me
# Image tags the stack runs. `latest` is fine locally; production must pin an
# immutable release (the preflight rejects `latest`), so a rolling restart
# cannot silently change the running version.
BUS_VERSION=latest
POSTGRES_IMAGE=postgres:18.4-alpine3.24
# Host port the bus is published on. The container always listens on 8787.
BUS_PORT=8787
# Bus replicas. The server is stateless, so this scales horizontally behind
# the Swarm routing mesh; plain compose ignores values above 1.
BUS_REPLICAS=1
# Memory ceilings, applied by the production overlay only
# (Docker/docker-compose.prod.yml). Ignored by a plain `make up`.
BUS_MEMORY_LIMIT=512m
POSTGRES_MEMORY_LIMIT=2g
# ----------------------------------------------------------------- server --
# Read by `ai-crew-sync serve`, and DATABASE_URL by the admin subcommands.
# Where the server finds Postgres. Under compose this is derived from
# POSTGRES_PASSWORD and needs no setting; export it when running the binary
# directly or using the admin CLI from your own shell.
# DATABASE_URL=postgres://bus:change-me@localhost:5432/bus
# Address to bind inside the container/process.
BUS_BIND=0.0.0.0:8787
# Comma-separated hostnames accepted in the Host header (anti DNS-rebinding).
# "*" accepts any host — fine behind a proxy that already validates it; set
# your real hostname when the bus is exposed directly.
BUS_ALLOWED_HOSTS=*
# Comma-separated browser origins accepted by CORS. Empty disables the check
# (the dashboard is same-origin, so it does not need this).
BUS_ALLOWED_ORIGINS=
# Run pending migrations on startup. Turn it off to run them as a separate
# release step (`ai-crew-sync migrate`) instead.
BUS_AUTO_MIGRATE=true
# Largest MCP request body accepted, in bytes. Rejected with 413 before the
# JSON is parsed. The default clears the biggest legitimate request — a 1 MiB
# body plus eight 256 KiB attachments, which base64 inflates to ~2.7 MiB.
BUS_MAX_REQUEST_BYTES=8388608
# Requests per minute per token, enforced in-process (0 disables it). With
# several replicas the ceiling is per replica: use the reverse proxy when you
# need a hard global limit.
BUS_RATE_LIMIT_PER_MINUTE=600
# Signs the dashboard's read-only session cookies. Set the same value on every
# replica so a session works across all of them; when unset, a random key is
# generated at startup and sessions end at restart.
# BUS_DASHBOARD_SECRET=
# Log filter (tracing-subscriber syntax).
RUST_LOG=ai_crew_sync=info
# ------------------------------------------------- console client + plugin --
# Read by `ai-crew-sync client ...` and by the Claude Code plugin hooks.
# MCP endpoint and the personal token of one agent (from `agent add`).
# The plugin's hooks stay silent when these are unset.
# BUS_URL=http://localhost:8787/mcp
# BUS_TOKEN=acs_...
# Plugin only: seconds each hook waits on the bus before giving up, and how
# many hours of team activity the session-start catch-up summarises.
BUS_TIMEOUT=8
BUS_DIGEST_HOURS=8