Files
intercept/AGENTS.md
James Smith efb7d0ed20 chore: add AGENTS.md and superpowers plan docs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 12:59:51 +01:00

7.6 KiB

AGENTS.md

This file provides guidance to Codex (Codex.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)

# First-time setup (interactive wizard with install profiles)
./setup.sh

# Or headless full install
./setup.sh --non-interactive

# Or install specific profiles
./setup.sh --profile=core,weather

# 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

# Other setup utilities
./setup.sh --health-check      # Verify installation
./setup.sh --postgres-setup    # Set up ADS-B history database
./setup.sh --menu              # Force interactive menu

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

  • setup.sh - Menu-driven installer with profile system (wizard, health check, PostgreSQL setup, env configurator, update, uninstall). Sources .env on startup via start.sh.
  • start.sh - Production startup script (gunicorn + gevent auto-detection, CLI flags, HTTPS, .env sourcing, 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-ng
  • sensor.py - 433MHz IoT sensors via rtl_433
  • adsb.py - Aircraft tracking via dump1090 (SBS protocol on port 30003)
  • acars.py - Aircraft datalink messages via acarsdec
  • wifi.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 data
  • sstv.py - ISS SSTV image decoding via slowrx
  • weather_sat.py - NOAA APT & Meteor LRPT via SatDump
  • ais.py - AIS vessel tracking and VHF DSC distress monitoring
  • aprs.py - Amateur packet radio via direwolf
  • rtlamr.py - Utility meter reading
  • meshtastic_routes.py - Meshtastic LoRa mesh networking

Core Utilities (utils/)

SDR Abstraction Layer (utils/sdr/):

  • SDRFactory with factory pattern for multiple SDR types (RTL-SDR, LimeSDR, HackRF, Airspy, SDRPlay)
  • Each type has a CommandBuilder for generating CLI commands

Bluetooth Module (utils/bluetooth/):

  • Multi-backend: DBus/BlueZ primary, fallback for systems without BlueZ
  • aggregator.py - Merges observations across time
  • tracker_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 environment
  • detector.py - Compare current scan to baseline, flag anomalies
  • device_identity.py - Track devices despite MAC randomization
  • correlation.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 WeatherSatDecoder using 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.html at ~12 points: CSS include, welcome card, partial include, visuals container, JS include, validModes set, modeGroups map, classList toggle, modeNames, visuals display toggle, titles, and init call in switchMode()

Docker

  • Dockerfile - Single-stage build with all SDR tools compiled from source (dump1090, AIS-catcher, slowrx, SatDump, etc.). CMD runs start.sh (gunicorn + gevent)
  • docker-compose.yml - Two profiles: basic (standalone) and history (with Postgres for ADS-B)
  • build-multiarch.sh - Multi-arch build script for amd64 + arm64 (RPi5)
  • Data persisted via ./data:/app/data volume mount

Configuration

  • config.py - Environment variable support with INTERCEPT_ 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.