saksham 1a4c80958f Initial commit: CI Agent competitive-intelligence monitoring app
FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring,
source collection, LLM-based change analysis, enrichment, and account
security (Turnstile, escalating lockout, email verification).
2026-08-05 10:48:20 -04:00

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 for the build strategy, ARCHITECTURE.md for system design, SECURITY.md for the threat model, TASKS.md for the live implementation checklist, KNOWN_LIMITATIONS.md for what's stubbed vs. fully live, and docs/FIREBASE_MIGRATION.md for a (skeptical) look at what moving to Firebase would take.

Quick start (Docker)

git clone <repository>
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:

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:

cd apps/web
npm install
npm run dev

Common commands

# 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 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 — 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.

S
Description
CI Agent - competitive intelligence monitoring
Readme
924 KiB
Languages
Python 72.3%
TypeScript 27.1%
Shell 0.4%