Local Development
For working on Brutor (rather than just running it), the pattern is infrastructure in Docker, services native: PostgreSQL, Redis, Qdrant and friends run as containers, while the control plane, core proxy and both UIs run from source with hot reload and native debuggers.
Infrastructure containers
Section titled “Infrastructure containers”The brutor-gateway-control repository ships a dev compose file with just the infrastructure:
| Service | Host port | Notes |
|---|---|---|
PostgreSQL 16 (brutor-postgres-dev) |
5432 | Shared DB for both planes |
Redis 7.4 (brutor-redis-dev) |
6379 | Counters, cache |
Qdrant 1.18 (brutor-qdrant-dev) |
6333 (REST) / 6334 (gRPC) | Semantic cache + KB vectors |
mcp-app-map (brutor-mcp-app-map) |
3010 → container 3001 | Demo MCP server to test against |
Skill Runner (brutor-skill-runner-dev) |
8210 | Sandboxed skill execution (exposed in dev, internal-only in the trial bundle) |
LocalStack + Vault (profile kms) |
4566 / 8200 | Only when testing the aws_kms / vault key providers |
cd brutor-gateway-controldocker compose up -dRun the services
Section titled “Run the services”-
Control Plane (Python/FastAPI, :5050) — owns the schema and runs Alembic migrations on startup, so start it first on a fresh database.
Terminal window cd brutor-gateway-controlpip install -e .python main.py # http://localhost:5050Set
JWT_SECRET,ENCRYPTION_KEYandDATABASE_URLin your environment (or the repo’s.env) before starting — they’re required. Migration commands, when you’re changing the schema:Terminal window alembic revision -m "describe change" # new migration under alembic/versions/alembic upgrade head # applyalembic downgrade -1 # roll back one revisionalembic current # show applied revision -
Core Proxy (Rust/Axum, :8100) — must see the same database,
JWT_SECRETandENCRYPTION_KEYas the control plane.Terminal window cd brutor-gateway-corecargo run # http://localhost:8100cargo test # unit testsThe core repo has its own compose file with an OTel/Prometheus/Loki/Grafana stack (Grafana on :3010) if you want tracing while you develop — see the observability tour.
-
Admin Console (React, :3002) — talks to the control plane.
Terminal window cd brutor-gateway-adminnpm installnpm run dev # http://localhost:3002brutor-gateway-admin/.env VITE_GATEWAY_URL=http://localhost:5050Lint before committing:
npm run lint(zero warnings allowed). -
User Portal (React, :3001) — talks to the core proxy, not the control plane.
Terminal window cd brutor-gateway-portalnpm installnpm run dev # http://localhost:3001brutor-gateway-portal/.env VITE_GATEWAY_URL=http://localhost:8100VITE_TENANT_ID=defaultAlso available:
npm run type-check(TypeScript) andnpm run format(Prettier).
Sanity check
Section titled “Sanity check”With all four running:
curl http://localhost:5050/health # control planecurl http://localhost:8100/health # core proxy — "components": {"database": "up", ...}Then log into the Admin Console at http://localhost:3002 and the portal at http://localhost:3001, and send a request through :8100 — see your first LLM call.
