CLAUDE.md — Company Atlas (repo guide)
Product: Company Atlas — The Live Atlas of Global Companies. A distributed public-web sensor network attached to companies:
observations → snapshots → changes → structured events → metrics → intelligence. The accumulated history is the product.
Full product specification (200 sections, non-negotiable principles): docs/PRODUCT-SPEC.md. Read it before changing behaviour.
Domains: canonical https://www.company-atlas.co today (DNS A → MacLustr Tunnel 51.161.112.61). www.company-atlas.com is the
spec's primary hostname but its nameservers are at Vercel, not GoDaddy — once its A records point to the gateway, add it as a tunnel
route/redirect and flip CA_SITE_URL. Apex → www 308.
Stack
- Python 3.12
src/companyatlas(FastAPI, SQLAlchemy Core + asyncpg, Alembic SQL forward-only, httpx, selectolax, feedparser, zstd), CLIcatlas(commands auto-discovered fromcompanyatlas/commands/*.py). - Postgres 17 only (no Redis): queue =
queue_jobswithSKIP LOCKED; caches in-process (api/common.TTLCache). - Objects: content-addressed zstd store
CA_DATA_DIR/objects/ab/cd/<sha256>.zst(archive.py). - Web:
apps/webNext 16 + React 19 + Tailwind v4 (Geist), SSR, rewrites/api/v1/*→ FastAPI loopback. Ports: prod web 8360 / api 8361; dev web 8370 / api 8371 (see.env.example). - LLM enrichment: OpenAI-compatible
CA_LLM_BASE_URL(MacLustr llm-api.io, key "company-atlas" indeploy/.llm-key, git-ignored). Optional; deterministic first.
Layout
src/companyatlas/ config.py taxonomy.py ids.py urls.py fetch.py archive.py db/ logging.py cli.py
sdk/ (models, normalize, diff, connector) connectors/ services/ (discovery, pipeline, scheduler, events, llm, metrics…)
api/ (main, common, routers/*) commands/ (CLI groups) registry/ (seed loader)
migrations/versions/0001_initial.py registry/ (companies ndjson, industries.yaml, countries.csv) prompts/ fixtures/ tests/
apps/web/ docs/ (PRODUCT-SPEC, ARCHITECTURE, API, DATA-MODEL, CONNECTORS, SCORING, DEPLOY, OPERATIONS) deploy/ (mld manifest, scripts)Architecture, ownership map and boundaries: docs/ARCHITECTURE.md. API contract: docs/API.md.
Operating rules (spec §182)
- Inspect existing architecture first; preserve working functionality; avoid rewrites; reuse the SDK.
- Never fabricate data. No inference presented as fact: careful language (detected, no longer listed, signal), confidence labels.
- Historical-first: never overwrite or delete history; new versions,
statuscolumns, forward-only migrations. - Raw vs interpreted stay separate (objects ↔ snapshots ↔ changes ↔ events). Reprocessing must never require re-fetching.
- LLMs are enrichment, not the crawler: deterministic fetch → normalize → hash → diff → significance → LLM only if useful, budgeted.
- Only
fetch.Fetchertalks to the network: SSRF guard, robots, per-domain rate/concurrency, size and redirect caps. Never bypass authentication or challenges; never collect private data. - No magic numbers: tunables in
config.Settings/taxonomy.py; bump formula/prompt/connector versions when behaviour changes. - Mobile is first-class; dark and light both designed; dense, readable, terminal-grade UI.
- Tests use fixtures (
fixtures/), never the live web (-m liveopt-in). Run.venv/bin/pytest -q,.venv/bin/ruff check src tests,pnpm typecheckafter meaningful changes. - Secrets only in env / git-ignored files (
deploy/.admin-token,deploy/.llm-key); the rendered manifest lives on M1M32.
Dev quickstart
uv venv --python 3.12 .venv && uv pip install --python .venv/bin/python -e '.[dev]'
createdb -O companyatlas companyatlas # role companyatlas/companyatlas, extensions pg_trgm + uuid-ossp
cp .env.example .env && .venv/bin/catlas migrate && .venv/bin/catlas seed
.venv/bin/catlas onboard --limit 50 # discovery + sensors for the first companies
.venv/bin/catlas schedule # scheduler + workers (Ctrl-C to stop)
.venv/bin/catlas api # http://127.0.0.1:8371/api/v1/docs
pnpm install && pnpm dev:web # http://localhost:8370Deploy (see docs/DEPLOY.md)
Since 2026-09-14: OVH server BHS128b (ssh BHS128b, Ubuntu 24.04), outside mld — dir ~/apps/company-atlas (uv Python 3.12 venv),
data ~/company-atlas-data, Postgres 17 native (companyatlas), PM2 under systemd (~/apps/pm2.company-atlas.config.cjs, generated from
the mld manifest kept in ~/apps/.manifests/): company-atlas-api / company-atlas-scheduler / company-atlas-web. Route
https://www.company-atlas.co → wg1 10.67.0.62:8360. Release = rsync + uv pip install -e . + catlas migrate + web build + pm2 restart
(exact command in docs/DEPLOY.md). Former home: M2U64 via mld (deploy/render-manifest.sh --push → mld stage → mld deploy), cold copy kept.