{"slug": "show-hn-velocity-a-keyless-3d-globe-that-fuses-15-live-intel-feeds", "title": "Show HN: Velocity – a keyless 3D globe that fuses 15 live Intel feeds", "summary": "A developer released Velocity, a keyless 3D globe that aggregates 15 live open intelligence feeds including aircraft, ships, satellites, GPS jamming, dark vessels, earthquakes, internet outages, conflict events, and news, correlating them server-side. The tool runs as an MCP server, allowing AI agents to query live data, and requires no API keys for core feeds, though it is a single-analyst tool with state stored in memory.", "body_md": "A 3D globe that pulls a stack of open intelligence feeds into one place: live aircraft, ships, satellites, GPS jamming, dark vessels, earthquakes, internet outages, conflict events and news. It correlates them on the server instead of leaving you to eyeball six tabs. It also runs as an MCP server, so an AI agent can ask it for live data instead of guessing from its training cut-off.\n\n** Live demo** ·\n\n[Quick start](#quick-start)·\n\n[Take the tour](#take-the-tour)·\n\n[Query it from an AI agent](#mcp-server-query-the-live-console-from-an-ai-agent)\n\nBefore you get excited:it's a single-analyst tool, state lives in memory (restart = gone), AIS is densest over Northern Europe (global coverage is sparser and terrestrial-biased), and the 3D satellite mode is a VRAM hog. Full caveats in[Scope and limits].\n\nHonestly, not much. There are two ways to run it, pick whichever you're set up for:\n\n**The easy way, with Docker.** If you have Docker (24 or newer, with the`compose`\n\nplugin that ships with Docker Desktop), that's the whole list. One command and you're up.**Running the pieces yourself.** If you'd rather not use Docker, you'll need Node 20+, pnpm 9 (`corepack enable`\n\npicks the right version for you), Python 3.12 for the backend, and`uv`\n\nto pull its dependencies. A plain venv works too if you don't have`uv`\n\n.\n\nEither way, you need a browser that can do WebGL2, so any recent Chrome, Edge or Firefox. The globe leans on your GPU, so on a laptop with switchable graphics do yourself a favour and push it onto the discrete card before you judge the frame rate.\n\nAnd no keys. The core feeds (planes, ships, quakes, satellites, the basemap) all\nrun without a single API key. Keys only ever add reach; see\n[What it pulls in](#what-it-pulls-in) for what each one buys you.\n\nDocker is the short road. It brings up the API, the web app and nginx together:\n\n```\ngit clone https://github.com/AndrewCTF/osint-geospatial-console.git\ncd osint-geospatial-console\ncp .env.example .env       # optional, leave it empty and it still works\ndocker compose up          # api + web + nginx on :8080\n```\n\nNow open [http://localhost:8080](http://localhost:8080). It comes up live, planes moving, ships,\nquakes, the lot, with nothing to configure in between. The first time in, a\nshort tour points out where things live; you can pull it back up whenever from\n**⚙ Settings**.\n\n**Local dev without Docker**\n\n```\nmake install                                      # pnpm install + api venv\ncd apps/api && .venv/bin/uvicorn app.main:app     # backend on :8000\npnpm dev                                          # vite on :5173, proxies /api to localhost:8000\n```\n\nSet `VITE_API_URL`\n\nif the backend isn't on `http://localhost:8000`\n\n. If you set\n`API_KEY`\n\non the backend, build the web app with a matching `VITE_API_KEY`\n\n; it\nrides along as `X-API-Key`\n\non every call.\n\n**1. The whole planet, live.** Thousands of aircraft plus vessels, satellites,\nquakes and more on one Cesium globe. Every aircraft and ship renders as its\ncategory icon, coloured and rotated to its heading.\n\n**2. Zoom anywhere.** Drag into a region and traffic, labels and coastlines\nfill in. Here's Europe and the Med: a few thousand aircraft at a glance, plus\nthe layer rail on the left (toggle aircraft, vessels, jamming, quakes, …) and\nthe timeline along the bottom.\n\n**3. Click anything.** Select an aircraft or vessel and the panel on the right\nfills with its dossier: position, a track-history sparkline, GPS integrity, and\nthe raw fields, while a magenta line traces its recent track on the globe. Click\nempty space and it clears.\n\n**4. Bring your own data — the Foundry tab.** Upload a CSV/JSON/NDJSON, shape it\nthrough a governed pipeline (13 transform steps: filter, derive, join, aggregate,\nwindow, pivot, dedup, cast, regex…), gate every version with data-health checks\n(freshness SLAs, schema-drift, uniqueness…), and bind it into the same ontology\ngraph as the live feeds. Lineage, immutable versions with rollback, and a\ndead-letter for rows that fail a transform all come along.\n\nThe point is fusion. Plenty of sites already do one feed well: Flightradar24 for\nplanes, MarineTraffic for ships, [GPSJam](https://gpsjam.org) for jamming.\nVelocity goes after the seam between them: AIS plus radar imagery flags a ship\nthat's switched its transponder off; a cluster of aircraft reporting bad GPS\nintegrity becomes a jamming hotspot; when two or more of those line up in the\nsame place and time, they get promoted to a single incident with a written,\ncited summary.\n\nA few things worth knowing up front, because I'd rather you read them here than be annoyed later:\n\n- It's built for one analyst. One optional API key, no accounts or roles.\n- Most state lives in memory. Restart the backend and the incident and AOI history is gone — but the position-track replay buffer survives: it's a 7-day SQLite store on disk. Durable storage for the rest (Postgres + PostGIS + TimescaleDB) is Phase 2.\n- AIS runs keyless and global (~33k vessels, MMSI-deduped across ShipXplorer, MyShipTracking, Digitraffic and Kystverket), but coverage is densest over Northern Europe and the Baltic and thins out elsewhere; an AISStream key fills in the gaps. Sparse regions still lean on the radar (SAR) layer.\n- The 3D satellite view will eat your VRAM. The default 2D dark map runs on a\nlaptop; check\n[System requirements](#system-requirements)before switching the heavy mode on.\n\nNone of it needs an API key to start. Keys only add reach.\n\nRough live numbers off a running backend; they move around through the day:\n\n| Feed | Typical live count | Where it comes from |\n|---|---|---|\n| Aircraft (ADS-B) | 9–13k (~11k typical) | OpenSky + airplanes.live |\n| Military aircraft | ~140 | adsb.lol |\n| Vessels (AIS) | ~33k, global | ShipXplorer + MyShipTracking + Digitraffic + Kystverket |\n| GPS jamming | ~200 flagged 1° cells | ADS-B NACp/NIC, the GPSJam method |\n| Dark vessels | radar change-detection | Sentinel-1 SAR |\n| Fused incidents | correlation-driven | the correlation engine |\n| Satellites | ~16k | CelesTrak |\n| Earthquakes | ~250/day | USGS + EMSC |\n| News + fact-check | ~370 articles | publisher RSS |\n| Internet outages | country level | IODA, Cloudflare |\n| Submarine cables | 715 | TeleGeography |\n| Conflict events | ~1.5k live | GDELT, EONET, ACLED |\n| Wildfires | VIIRS hotspots | NASA FIRMS (needs a key) |\n| 3D war damage, imagery, webcams | varies | Sentinel, GIBS, OSM |\n\nOptional keys, if you want more reach: AISStream for global AIS, an OpenSky\nlogin for a bigger ADS-B budget, `FIRMS_MAP_KEY`\n\nfor fires, an ACLED key for\nconflict events, `CLOUDFLARE_TOKEN`\n\nfor outages. `GET /api/intel/sources`\n\nreports what's actually live versus what's still waiting on a key.\n\nThe part I think is genuinely new: the backend doubles as a **Model Context\nProtocol** server, so an AI agent can interrogate the same warm feeds the globe\nrenders without scraping a dozen sites or flooding its own context. Ask \"where\nis GPS being jammed right now?\" and it answers from the live feed. Full\narchitecture + `/api/intel/*`\n\nHTTP reference: [ docs/mcp-server.md](/AndrewCTF/osint-geospatial-console/blob/master/docs/mcp-server.md).\nIt exposes 22 tools over\n\n`app.mcp_server`\n\n(a representative slice below; run\n`--list-tools`\n\nfor the full set):| Tool | What it returns |\n|---|---|\n`get_situation` |\nGlobal summary: aircraft by category, GNSS-degraded count, emergencies, worst jamming cells, vessel/alert counts. The cheap first call. |\n`focus_area(lat,lon,radius_nm)` |\nLoads a region PRIMARY (dedicated fresh `/v2/point` fetch + ongoing priority refresh, independent of global rate limits) and returns a full bundle: aircraft + density + GPS jamming + vessels + fused anomalies. |\n`aircraft_density` |\nGrid of cells (count, by category, GNSS-degraded) for an area. |\n`gps_jamming` |\nGPSJam-method assessment (ADS-B NACp<8 / NIC<7, 1° bins): flagged cells, severity, affected aircraft. Global or scoped. |\n`query_aircraft` |\nFiltered query (bbox/centre, category, squawk, callsign, altitude band, emergency / gnss_degraded / on_ground). |\n`lookup_aircraft(ident)` |\nOne aircraft by ICAO24 or callsign + integrity/threat assessment. |\n`query_vessels` |\nAIS vessels in an area, classified; `dark_only` for dark-vessel candidates. |\n`anomalies` |\nFused report: emergencies, jamming hotspots, dark vessels, alerts + a triage threat level. |\n`list_focus_areas` / `data_sources` |\nActive priority AOIs / feed health. |\n`deep_analyze(question, lat?, lon?)` |\nGathers the relevant intel JSON and has a reasoning model reason over it (DeepSeek when configured, else a local Ollama model), so heavy analysis stays off the agent's context and only the conclusion returns. |\n\nEvery tool returns compact, bounded JSON (counts, grids, ≤50-item samples), so\nan agent can sweep the planet for a few hundred tokens instead of pulling 15k\nfeatures. Heavy tools also take ** detail='short'** (the default digest — top-N\nof each list plus a\n\n`<field>_total`\n\n) or **(the full bundle), so an agent sweeps in**\n\n`detail='long'`\n\n`short`\n\nand drills in `long`\n\n. Area-primary loading means the\nagent's region of interest stays fresh and dense even while the global firehose is\nbeing rate-limited; the rest of the world keeps streaming from the sticky snapshot.The repo is also a Claude Code **plugin marketplace**. One install wires the MCP\nserver *plus* an analyst skill (`osint-intel`\n\n), slash commands (`/osint-brief`\n\n,\n`/osint-watch`\n\n, `/osint-jamming`\n\n), and a `osint-watch-officer`\n\nagent. Start the\nbackend (`bash scripts/run-api.sh`\n\n), then in Claude Code:\n\n```\n/plugin marketplace add /path/to/OSINT\n/plugin install osint-geoint@osint-velocity\n```\n\nSet **repo_dir** and **python** (the repo's venv interpreter) when prompted; the\nplugin runs that Python directly, so it works on Windows, macOS, and Linux. The\ninstaller prints the exact commands for your OS: `bash plugin/osint-geoint/install.sh`\n\n(Linux/macOS, `-y`\n\nto register the MCP server) or\n`plugin\\osint-geoint\\install.ps1`\n\n(Windows, `-Run`\n\nto register).\n\nOn the hosted platform the MCP server is mounted into the backend at `/mcp`\n\n(streamable-HTTP), so there's nothing to install or run. Register it with any\nMCP client using your Velocity access token:\n\n```\nclaude mcp add --transport http osint-geoint \\\n  https://projectvelocity.org/mcp \\\n  --header \"Authorization: Bearer $VELOCITY_TOKEN\"\n```\n\n`$VELOCITY_TOKEN`\n\nis your signed-in Velocity (Supabase) access token; the\ngateway Worker verifies it and the backend re-checks it, so the endpoint is\ngated to your session.\n\n```\n# 1. backend must be running (provides the warm feeds)\nuv run --project apps/api uvicorn app.main:app --port 8000\n\n# 2a. MCP server over stdio (Claude Code / Desktop / Agent SDK), cross-platform\nuv run --project apps/api python -m app.mcp_server\n# 2b. or streamable-HTTP\nuv run --project apps/api python -m app.mcp_server --http --port 8765\n# introspect (no backend needed)\nuv run --project apps/api python -m app.mcp_server --list-tools\n```\n\nTo register the local stdio server with Claude Code, run from the repo root:\n\n```\nclaude mcp add osint-geoint -- uv run --project apps/api python -m app.mcp_server\n```\n\n`uv run`\n\nresolves the right interpreter on Linux, macOS, and Windows without\nhardcoding a venv path. No `uv`\n\n? Point it at the venv Python directly:\n`apps/api/.venv/bin/python -m app.mcp_server`\n\n(Linux/macOS) or\n`apps\\api\\.venv\\Scripts\\python.exe -m app.mcp_server`\n\n(Windows), run from\n`apps/api`\n\n.\n\nConfig (env or `apps/api/.env`\n\n): `API_BASE`\n\n, `API_KEY`\n\n, `OLLAMA_HOST`\n\n,\n`OLLAMA_MODEL`\n\n(empty picks the smallest installed model; `deep_analyze`\n\ndegrades to returning raw JSON if Ollama is absent). The MCP server never\ncrashes a tool call: backend down returns a structured `backend_unreachable`\n\nerror; Ollama down falls back to raw intel JSON.\n\n`GET /api/export?fmt=geojson|csv|kml&kinds=aircraft,vessels&bbox=min_lon,min_lat,max_lon,max_lat&limit=N`\n\ndownloads the current live picture (the same snapshot the globe renders) as\n**GeoJSON** (QGIS / kepler.gl / Leaflet), **CSV** (spreadsheets), or **KML**\n(Google Earth). `bbox`\n\nclips to a viewport; `kinds`\n\nis comma-separated (default\n`aircraft`\n\n); `limit`\n\ncaps features; vessels are best-effort.\n\nThe heavy component is the **client**, a CesiumJS WebGL2 globe. It is GPU- and\nbrowser-main-thread-bound, and the backend is light. WebGL2 is required\n(Chrome/Edge 110+, Firefox 110+). On hybrid-graphics laptops, force the discrete\nGPU (`chrome://gpu`\n\n, look for adapter \"ACTIVE\").\n\n**VRAM depends heavily on which mode you run:**\n\n**2D-dark (default basemap):** light. The globe is a proxied 2D raster basemap plus the entity layers (aircraft/vessels). Runs on integrated graphics / ~2–4 GB VRAM, which is the right mode for modest hardware.**3D-sat (satellite imagery + world terrain + OSM 3D buildings, optional Google Photorealistic 3D):****VRAM-heavy.** CesiumJS streams terrain meshes, high-res imagery, and 3D-tile building/photogrammetry sets, and it caches into whatever VRAM is available, measured at**20+ GB on a 32 GB card**. Tilesets are now individually cache-capped (Google 3D ~1.5 GB, OSM buildings ~0.5 GB) and MSAA is off (FXAA instead), but with terrain + global imagery + a high-DPI/4K canvas the resident set is still large. On a card with less VRAM, Cesium evicts and re-fetches more aggressively (lower fps, more pop-in) and still runs.\n\n| Tier | GPU | RAM | Display | What you get |\n|---|---|---|---|---|\n| Minimum | WebGL2 integrated (Iris Xe / Vega / M1) | 8 GB | 1080p | 2D-dark, regional zoom, ~30 fps. 3D-sat will be rough. |\n| Recommended | Discrete ≥8 GB VRAM (RTX 3060 / RX 6700 / M-Pro) | 16 GB | 1080p–1440p | 2D-dark smooth; 3D-sat usable at city scale. |\n| 3D-sat / 4K | RTX 4070+/16 GB VRAM or better | 32 GB | up to 4K | Full 3D-sat terrain + buildings; high fps. |\n\nThese tiers come from watching it actually run. 3D-sat genuinely wants a lot of VRAM, and the low-VRAM minimum only holds for the 2D-dark map; switch on 3D-sat and you'll want a discrete card with headroom.\n\n**Backend (server):** Python 3.12, ~1 GB RAM, outbound HTTPS. Runs on a small\nVPS or the same box, and it isn't the bottleneck.\n\n**Frontend**: Vite + React 18 + TypeScript + CesiumJS + MapLibre GL JS v5.24 + Tailwind + Zustand** Backend**: FastAPI (Python 3.12) + httpx + websockets. Live Phase 1 state is in-process (bounded observation store + disk tile cache); the 7-day position-track replay buffer persists to SQLite**Agent access**: Model Context Protocol server (`app.mcp_server`\n\n, MCP SDK) + optional local Ollama analysis**Data (Phase 2, planned)**: PostgreSQL 16 + PostGIS + TimescaleDB hypertables + Redis. A SQLite position store backs replay today; the observation store migrates per plan §locked-decisions #5**Infra**: Docker Compose, nginx reverse proxy\n\n```\nosint/\n├── apps/web/                 # React + Cesium console\n├── apps/api/                 # FastAPI backend\n│   └── app/\n│       ├── intel/            # agent-facing analytics + local ontology store\n│       ├── foundry/          # BYO-data layer: datasets, transforms, builds, checks, binding\n│       ├── routes/intel.py   # /api/intel/* deep-query JSON API\n│       ├── routes/foundry.py # /api/foundry/* datasets/pipelines/checks/bindings\n│       └── mcp_server.py     # Model Context Protocol server\n├── apps/web/src/foundry/     # FOUNDRY console surface (datasets, pipeline DAG, builds, ontology)\n├── packages/shared/          # Shared TS types (LayerDescriptor, Observation)\n├── docs/                     # design notes, decisions.md, foundry-plan.md\n└── infra/                    # Docker, nginx, db init\npnpm -r test                          # vitest (web, shared)\ncd apps/api && .venv/bin/pytest -q     # api: unit + route + intel/MCP degradation tests\npnpm -r typecheck\n# manual MCP integration drivers (need backend on :8000):\n#   apps/api/.venv/bin/python tests/mcp_client_check.py   # stdio handshake\n#   apps/api/.venv/bin/python tests/mcp_full_check.py     # tools end-to-end + Ollama\n```\n\nLegend: ✅ shipped · 🚧 in progress\n\n- ✅\n**Phase 0**— Foundation - ✅\n**Phase 1**— MVP: live ADS-B / AIS / quakes / GPS-jamming layers on the globe - ✅\n**Phase 2**— Replay + drill-in. The timeline scrubber and a 7-day history buffer ship as SQLite-backed playback; drilling into any past moment works today. A durable Postgres + PostGIS + TimescaleDB store is a deferred scaling upgrade for multi-week retention, not a blocker - ✅\n**Phase 3**— Fusion engine + alerts (correlation rules) + 2D mirror - 🚧\n**Phase 4**— Advanced sensors + AI. MCP server + intel API (now with a Claude Code plugin and`detail=short|long`\n\ntool variants), Sentinel-1 SAR dark-vessel detection, an autonomous watch-officer that writes cited incident briefs, a keyless infra/domain OSINT layer, a photo-geolocation pipeline (content inference + satellite 3DGS pose), a City 3D Gaussian-splat viewer, optional local-GPU (Ollama) inference, and a first-run onboarding tour. More sensors and deeper analysis are ongoing. - 🚧\n**Phase 5**— Foundry: a keyless, local, single-operator take on Palantir Foundry's data-integration loop. Upload → transform (governed step DSL with lineage) → build (dependency DAG, staleness, cycle rejection) → data-health checks → bind into the local ontology graph. In: immutable versions + rollback, row-level quarantine/dead-letter, freshness/schema-drift SLAs, window/pivot analytics, entity resolution. Deliberately out of scope (single-operator identity): multi-tenant MLS, distributed compute, streaming CDC, connector catalogs. Next: ontology Actions (audited write-back) and dataset branches. - 🚧\n**Phase 6**— Workflows: a node-graph automation layer over the same live feeds and ontology. 20 blocks — sources (aircraft, vessels, quakes, alerts, datasets, ontology, countries), transforms (`op.python`\n\n/`op.sql`\n\n/`op.llm`\n\nsandboxed subprocesses,`op.geo`\n\n,`op.http`\n\n,`op.steps`\n\n), sinks (alert, ontology, dataset, persistent memory), and**external-actuation control blocks** that reach out of the platform:`op.http`\n\n/`control.webhook`\n\nto any server, and`control.drone`\n\n/`control.device`\n\nto command a UAV or hardware via a JSON envelope. A first-class**MAVLink bridge**(`app.mavlink_bridge`\n\n, ArduPilot/PX4, log-only without a vehicle so you can rehearse) ships in-repo. See.`docs/workflows-control-blocks.md`\n\nSee [ docs/](/AndrewCTF/osint-geospatial-console/blob/master/docs) for the per-feature design notes and pipeline writeups.\n\n[Apache-2.0](/AndrewCTF/osint-geospatial-console/blob/master/LICENSE) covers Velocity's **source code**. Upstream **data\ncarries its own licenses**; several feeds are non-commercial / academic (e.g.\nACLED, adsb.fi, OpenSky). See [ NOTICE](/AndrewCTF/osint-geospatial-console/blob/master/NOTICE) for per-source attribution and\nterms, and verify each upstream's current terms before any commercial or\nredistributive use.", "url": "https://wpnews.pro/news/show-hn-velocity-a-keyless-3d-globe-that-fuses-15-live-intel-feeds", "canonical_source": "https://github.com/AndrewCTF/osint-geospatial-console", "published_at": "2026-07-11 02:20:06+00:00", "updated_at": "2026-07-11 02:35:09.926509+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools"], "entities": ["AndrewCTF", "Cesium", "Docker", "Node", "Python", "pnpm", "Vite", "nginx"], "alternates": {"html": "https://wpnews.pro/news/show-hn-velocity-a-keyless-3d-globe-that-fuses-15-live-intel-feeds", "markdown": "https://wpnews.pro/news/show-hn-velocity-a-keyless-3d-globe-that-fuses-15-live-intel-feeds.md", "text": "https://wpnews.pro/news/show-hn-velocity-a-keyless-3d-globe-that-fuses-15-live-intel-feeds.txt", "jsonld": "https://wpnews.pro/news/show-hn-velocity-a-keyless-3d-globe-that-fuses-15-live-intel-feeds.jsonld"}}