# CI Agent — Competitive Intelligence Monitoring CI Agent monitors companies you choose, collects publicly available information from multiple sources on a schedule, analyzes it with an LLM into an evidence-linked report, detects meaningful changes between runs, and alerts you by email (and optionally SMS) with a severity and confidence score. See [`PLAN.md`](PLAN.md) for the build strategy, [`ARCHITECTURE.md`](ARCHITECTURE.md) for system design, [`SECURITY.md`](SECURITY.md) for the threat model, [`TASKS.md`](TASKS.md) for the live implementation checklist, [`KNOWN_LIMITATIONS.md`](KNOWN_LIMITATIONS.md) for what's stubbed vs. fully live, and [`docs/FIREBASE_MIGRATION.md`](docs/FIREBASE_MIGRATION.md) for a (skeptical) look at what moving to Firebase would take. ## Quick start (Docker) ```bash git clone cd ci-agent cp .env.example .env docker compose up --build ``` Then visit: | Service | URL | |---|---| | Frontend | http://localhost:3000 | | Backend API | http://localhost:8000 | | API docs (Swagger) | http://localhost:8000/docs | The default `.env.example` runs in `AUTH_MODE=local` (no login required, fixed dev user) with `LLM_PROVIDER=mock` and `SEARCH_PROVIDER=mock` — the whole demo workflow works with zero paid API keys. `api`, `worker`, and `beat` build from the same Dockerfile but are separate images — after adding a Python dependency, run `docker compose build api worker beat` (not just `restart`) or they'll crash with `ModuleNotFoundError` on stale images. Similarly, after adding an npm dependency to `apps/web`, a plain rebuild isn't enough either — `web`'s `node_modules` *and* `.next` are both persistent anonymous Docker volumes that survive `docker compose build web` and even a plain `docker compose restart web`. This means a new package can still 404, and — on Windows + Docker Desktop — an edited existing file can keep serving its pre-edit output after a restart, since the on-disk `.next` build cache isn't cleared by a restart. Run `docker compose rm -f -s -v web && docker compose up -d web` to actually pick up new packages or force a clean recompile. ## Running without Docker **Backend:** ```bash cd apps/api python -m venv .venv ./.venv/Scripts/activate # or `source .venv/bin/activate` on macOS/Linux pip install -e ".[dev]" cp ../../.env.example ../../.env # edit DATABASE_URL to the sqlite line if you don't have Postgres running alembic upgrade head uvicorn app.main:app --reload ``` **Frontend:** ```bash cd apps/web npm install npm run dev ``` ## Common commands ```bash # Database migrations cd apps/api && alembic upgrade head cd apps/api && alembic revision --autogenerate -m "description" # Run a Celery worker + beat (only needed outside Docker) cd apps/api && celery -A app.tasks.celery_app worker --loglevel=INFO -Q default,collection,analysis,notifications,maintenance cd apps/api && celery -A app.tasks.celery_app beat --loglevel=INFO # Backend tests / lint / format cd apps/api && pytest cd apps/api && ruff check app tests cd apps/api && black app tests # Frontend tests / lint / format / typecheck cd apps/web && npm test cd apps/web && npm run lint cd apps/web && npm run format cd apps/web && npm run typecheck # End-to-end test (requires `docker compose up -d` already running) cd apps/web && npx playwright install --with-deps chromium # one-time cd apps/web && npm run e2e ``` ## Configuration All configuration is via environment variables — see [`.env.example`](.env.example) for the full list with comments. Highlights: - `AUTH_MODE=local|jwt` — local single-user dev mode vs. real email/password accounts. - `LLM_PROVIDER=mock|anthropic|ollama|gemini` — set `ANTHROPIC_API_KEY`/`ANTHROPIC_MODEL`, `OLLAMA_BASE_URL`/`OLLAMA_MODEL`, or `GEMINI_API_KEY`/`GEMINI_MODEL` to go live. Gemini has a genuine free tier — grab a key at [aistudio.google.com/apikey](https://aistudio.google.com/apikey) — so it's the cheapest provider to actually try against a real model. - `SEARCH_PROVIDER=mock|brave` — set `BRAVE_SEARCH_API_KEY` to go live. - `SMTP_HOST`/`RESEND_API_KEY` — no bundled local mail sink; point SMTP at a real relay or set `RESEND_API_KEY` to actually test email delivery (alerts and security email both use this). - `NOTIFICATION_SMS_ENABLED=false` by default — set to `true` and provide `TWILIO_*` to enable SMS. Every paid/external provider defaults to a mock/console implementation. Automated tests always run against mocks and never call a paid API. ## Known limitations See [`KNOWN_LIMITATIONS.md`](KNOWN_LIMITATIONS.md).