Skip to content

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.

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
Terminal window
cd brutor-gateway-control
docker compose up -d
  1. 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-control
    pip install -e .
    python main.py # http://localhost:5050

    Set JWT_SECRET, ENCRYPTION_KEY and DATABASE_URL in 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 # apply
    alembic downgrade -1 # roll back one revision
    alembic current # show applied revision
  2. Core Proxy (Rust/Axum, :8100) — must see the same database, JWT_SECRET and ENCRYPTION_KEY as the control plane.

    Terminal window
    cd brutor-gateway-core
    cargo run # http://localhost:8100
    cargo test # unit tests

    The 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.

  3. Admin Console (React, :3002) — talks to the control plane.

    Terminal window
    cd brutor-gateway-admin
    npm install
    npm run dev # http://localhost:3002
    brutor-gateway-admin/.env
    VITE_GATEWAY_URL=http://localhost:5050

    Lint before committing: npm run lint (zero warnings allowed).

  4. User Portal (React, :3001) — talks to the core proxy, not the control plane.

    Terminal window
    cd brutor-gateway-portal
    npm install
    npm run dev # http://localhost:3001
    brutor-gateway-portal/.env
    VITE_GATEWAY_URL=http://localhost:8100
    VITE_TENANT_ID=default

    Also available: npm run type-check (TypeScript) and npm run format (Prettier).

With all four running:

Terminal window
curl http://localhost:5050/health # control plane
curl 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.