Add start.sh as the recommended production entry point with: - gunicorn + gevent worker for concurrent SSE/WebSocket handling - CLI flags for port, host, debug, HTTPS, and dependency checks - Auto-fallback to Flask dev server if gunicorn not installed - Conditional gevent monkey-patch in app.py via INTERCEPT_USE_GEVENT env var - Docker CMD updated to use start.sh - Updated all docs, setup.sh, and requirements.txt accordingly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.1 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
INTERCEPT is a web-based Signal Intelligence (SIGINT) platform providing a unified Flask interface for software-defined radio (SDR) tools. It supports pager decoding, 433MHz sensors, ADS-B aircraft tracking, ACARS messaging, WiFi/Bluetooth scanning, satellite tracking, ISS SSTV decoding, AIS vessel tracking, weather satellite imagery (NOAA APT & Meteor LRPT), and Meshtastic mesh networking.
Common Commands
Docker (Primary)
# Build and run (basic profile)
docker compose --profile basic up -d
# Build and run with ADS-B history (Postgres)
docker compose --profile history up -d
# Rebuild after code changes
docker compose --profile basic up -d --build
# Multi-arch build (amd64 + arm64 for RPi)
./build-multiarch.sh
Local Setup (Alternative)
# Initial setup (installs dependencies and configures SDR tools)
./setup.sh
# Run with production server (gunicorn + gevent, handles concurrent SSE/WebSocket)
sudo ./start.sh
# Or for quick local dev (Flask dev server)
sudo -E venv/bin/python intercept.py
Testing
# Run all tests
pytest
# Run specific test file
pytest tests/test_bluetooth.py
# Run with coverage
pytest --cov=routes --cov=utils
# Run a specific test
pytest tests/test_bluetooth.py::test_function_name -v
Linting and Formatting
# Lint with ruff
ruff check .
# Auto-fix linting issues
ruff check --fix .
# Format with black
black .
# Type checking
mypy .
Architecture
Entry Points
start.sh- Production startup script (gunicorn + gevent auto-detection, CLI flags, HTTPS, fallback to Flask dev server)intercept.py- Direct Flask dev server entry point (quick local development)app.py- Flask application initialization, global state management, process lifecycle, SSE streaming infrastructure, conditional gevent monkey-patch
Route Blueprints (routes/)
Each signal type has its own Flask blueprint:
pager.py- POCSAG/FLEX decoding via rtl_fm + multimon-ngsensor.py- 433MHz IoT sensors via rtl_433adsb.py- Aircraft tracking via dump1090 (SBS protocol on port 30003)acars.py- Aircraft datalink messages via acarsdecwifi.py,wifi_v2.py- WiFi scanning (legacy and unified APIs)bluetooth.py,bluetooth_v2.py- Bluetooth scanning (legacy and unified APIs)satellite.py- Pass prediction using TLE datasstv.py- ISS SSTV image decoding via slowrxweather_sat.py- NOAA APT & Meteor LRPT via SatDumpais.py- AIS vessel tracking and VHF DSC distress monitoringaprs.py- Amateur packet radio via direwolfrtlamr.py- Utility meter readingmeshtastic_routes.py- Meshtastic LoRa mesh networking
Core Utilities (utils/)
SDR Abstraction Layer (utils/sdr/):
SDRFactorywith factory pattern for multiple SDR types (RTL-SDR, LimeSDR, HackRF, Airspy, SDRPlay)- Each type has a
CommandBuilderfor generating CLI commands
Bluetooth Module (utils/bluetooth/):
- Multi-backend: DBus/BlueZ primary, fallback for systems without BlueZ
aggregator.py- Merges observations across timetracker_signatures.py- 47K+ known tracker fingerprints (AirTag, Tile, SmartTag)heuristics.py- Behavioral analysis for device classification
TSCM (Counter-Surveillance) (utils/tscm/):
baseline.py- Snapshot "normal" RF environmentdetector.py- Compare current scan to baseline, flag anomaliesdevice_identity.py- Track devices despite MAC randomizationcorrelation.py- Cross-reference Bluetooth and WiFi observations
WiFi Utilities (utils/wifi/):
- Platform-agnostic scanner with parsers for airodump-ng, nmcli, iw, iwlist, airport (macOS)
channel_analyzer.py- Frequency band analysis
Weather Satellite (utils/weather_sat.py):
- Singleton
WeatherSatDecoderusing SatDump CLI for NOAA APT and Meteor LRPT - Subprocess management with stdout parsing, image watcher via rglob
- Pass prediction using skyfield TLE data
SSTV Decoder (utils/sstv.py):
- ISS SSTV reception via slowrx with Doppler tracking
- Singleton pattern, image gallery with timestamped filenames
Key Patterns
Server-Sent Events (SSE): All real-time features stream via SSE endpoints (/stream_pager, /stream_sensor, etc.). Pattern uses queue.Queue with timeout and keepalive messages. Under gunicorn + gevent, each SSE connection is a lightweight greenlet instead of an OS thread.
Process Management: External decoders run as subprocesses with output threads feeding queues. Use safe_terminate() for cleanup. Global locks prevent race conditions.
Data Stores: DataStore class with TTL-based automatic cleanup (WiFi: 10min, Bluetooth: 5min, Aircraft: 5min).
Input Validation: Centralized in utils/validation.py - always validate frequencies, gains, device indices before spawning processes.
External Tool Integrations
| Tool | Purpose | Integration |
|---|---|---|
| rtl_fm | FM demodulation | Subprocess, pipes to multimon-ng |
| multimon-ng | Pager decoding | Reads from rtl_fm stdout |
| rtl_433 | 433MHz sensors | JSON output parsing |
| dump1090 | ADS-B decoding | SBS protocol socket (port 30003) |
| acarsdec | ACARS messages | Output parsing |
| airmon-ng/airodump-ng | WiFi scanning | Monitor mode, CSV parsing |
| bluetoothctl/hcitool | Bluetooth | Fallback when DBus unavailable |
| slowrx | SSTV decoding | Subprocess with audio pipe |
| SatDump | Weather satellites | CLI live mode, NOAA APT + Meteor LRPT |
| AIS-catcher | AIS vessel tracking | JSON output parsing |
| direwolf | APRS | TNC modem for packet radio |
Frontend Structure
- Templates:
templates/index.html(main SPA),templates/partials/modes/*.html(sidebar panels),templates/partials/nav.html(global nav) - JS Modules:
static/js/modes/*.js- IIFE pattern per mode (e.g.,WeatherSat,SSTV,Meshtastic) - CSS:
static/css/modes/*.css- scoped styles per mode, CSS variables for theming (--bg-card,--accent-cyan,--font-mono) - Mode Integration: Each mode needs entries in
index.htmlat ~12 points: CSS include, welcome card, partial include, visuals container, JS include,validModesset,modeGroupsmap, classList toggle,modeNames, visuals display toggle, titles, and init call inswitchMode()
Docker
Dockerfile- Single-stage build with all SDR tools compiled from source (dump1090, AIS-catcher, slowrx, SatDump, etc.). CMD runsstart.sh(gunicorn + gevent)docker-compose.yml- Two profiles:basic(standalone) andhistory(with Postgres for ADS-B)build-multiarch.sh- Multi-arch build script for amd64 + arm64 (RPi5)- Data persisted via
./data:/app/datavolume mount
Configuration
config.py- Environment variable support withINTERCEPT_prefix (e.g.,INTERCEPT_PORT,INTERCEPT_WEATHER_SAT_GAIN)- Database: SQLite in
instance/directory for settings, baselines, history
Testing Notes
Tests use pytest with extensive mocking of external tools. Key fixtures in tests/conftest.py. Mock subprocess calls when testing decoder integration.