Skip to content

breaching/krill-watch

Repository files navigation

krill-watch

Independent maritime OSINT dashboard for industrial krill, whaling, and IUU fishing fleets.

Disclaimer. Personal project. Built by a supporter of the Captain Paul Watson Foundation and Sea Shepherd, not affiliated with either organisation. The donate CTA routes to CPWF.

CI License: GPL-3.0 Python Node Scoring

Landing page in dark mode showing the fan project banner, hero, sources strip, featured CPWF video, mission tiles, and methodology

What it does

Four campaigns share one pipeline.

  • Antarctic krill in the CCAMLR Convention Area. Aker BioMarine and the Chinese fleet.
  • Commercial whaling. Kangei Maru in Japan, Hvalur 8 and 9 in Iceland.
  • Galápagos. Chinese squid jiggers massed at the reserve boundary.
  • West Africa. Chinese and Russian super-trawlers in the Senegal, Mauritania, and Guinea EEZs.

The tool ingests public AIS, Global Fishing Watch encounters and gaps, and official registries. It flags vessels that cross protected-area boundaries, runs a six-signal transhipment scorer over rolling encounters, and publishes the result on a French and English Next.js dashboard.

Where to look first

Three files carry most of the technical signal:

  • calibration.md : frozen scoring weights v0.4.2 with per-signal justification against CM 10-09 / 10-04 / 10-06 and a validation case set.
  • INVESTIGATOR_PLAYBOOK.md : three worked walkthroughs for CPWF analysts (Monday triage, encounter deep dive, dossier prep).
  • python main.py --mode transhipment-review --since 7d : generates the weekly investigator HTML report. Self-contained, send by email, print to A4, archive next to an investigation.

Screens

Live tracker with severity filters, CCAMLR zone overlays, AIS panel, dark MapLibre basemap centred on the Antarctic peninsula

Live tracker. MapLibre dark basemap. Filter panel for severity, zone overlays (CCAMLR areas, proposed MPAs), FIRMS hotspots, NASA satellite passes. Click a vessel to open its dossier.

Antarctic Endurance vessel dossier with CRITICAL severity badge, CCAMLR-48.1 zone tag, 30-day track on the South Georgia map, and event log

Vessel dossier. One page per vessel. Severity badge, current zones, 30-day MapLibre track with a scrubbable timeline, event log filtered by zone entry, severity change, AIS gap, AIS regain.

Run locally

git clone https://github.com/breaching/krill-watch.git
cd krill-watch

# Python deps (FastAPI, DuckDB, shapely)
pip install -r requirements-core.txt

# Node deps (root launcher and web/)
npm run setup

# Boot both: API on :8000, UI on :3000
npm run dev

Open http://localhost:3000/fr.

Optional environment variables. The UI degrades to seeded data without them.

Variable Purpose
GFW_API_KEY Global Fishing Watch v3. Enables encounter and gap enrichment.
AISSTREAM_API_KEY AISStream.io WebSocket. Enables live AIS.
DISCORD_WEBHOOK_URL Discord alert dispatch.
SLACK_WEBHOOK_URL Slack alert dispatch.

GFW_REFRESH_HOURS, DISABLE_WORKERS, and LOG_LEVEL are documented in server/workers.py.

API only: npm run dev:api. UI against an existing API: npm run dev:web-only.

Stack

Backend. FastAPI plus DuckDB on Python 3.11. One file at data/krill_watch.duckdb holds positions, zone transitions, vessel status, auto-incidents, and contributions. Background workers cover AISStream subscription and GFW profile refresh.

Key files: server/app.py, server/store.py, server/workers.py.

Frontend. Next.js 15 App Router with TypeScript. MapLibre GL for maps, dark-matter basemap. Server components fetch the API on page load. Client components subscribe to /api/stream for SSE updates.

Key files: web/app/[locale]/page.tsx, web/lib/krill-watch.ts.

Detector. src/transhipment_detector.py and src/reefer_watch.py. Calibration v0.4.2. Weights and validation cases in calibration.md.

Local dev needs no external service. Vessel registry, CCAMLR zone GeoJSON, and watchlists ship as static JSON in config/.

krill-watch/
├── server/   FastAPI app, DuckDB store, AIS and GFW workers
├── src/      Shared library: detector, monitor, profiler, notifier
├── web/      Next.js investigator UI
├── config/   Vessel registry, zone GeoJSONs, watchlists
├── tests/    pytest suite
├── scripts/  Utilities (zone builder, fleet verifier, seed)
├── docs/     Screenshots, audit notes, integration plans
└── data/     Runtime DuckDB and cache (gitignored)

Transhipment review

The weekly investigator deliverable. A multi-signal review of suspect at-sea transhipments inside the CCAMLR Convention Area.

python main.py --mode transhipment-review --since 7d --out output/transhipments_$(date +%Y-W%V).html

The HTML report is self-contained. Send it as an email attachment, print to A4, or archive it next to an investigation. The /transhipments page gives the same view interactively, with date and tier filters.

Scoring is investigative, not evidentiary. A score of 0.78 is a lead, not a verdict. Every flagged encounter needs independent verification (photographs, manifests, witness statements) before any public action. Scoring follows CCAMLR Conservation Measures 10-04, 10-06, 10-07, and 10-09.

Tier thresholds. Score at or above 0.50 is FLAGGED. Score at or above 0.75 is CRITICAL. Maximum reachable: 0.90.

Signal weights (v0.4.2):

Signal Weight Reference
Reefer not on CM 10-09 authorized list 0.25 CM 10-09
AIS gap during encounter 0.20 CM 10-04
IUU list or sanctions hit 0.20 CM 10-06/07, OFAC SDN
Outside authorized transhipment zone 0.15 CM 10-09 spatial
Flag of Convenience 0.05 ITF FOC list
Duration over 6 hours 0.05 Operational context

Weight justifications, validation cases, and the re-calibration procedure live in calibration.md.

Live sources powering the scorer.

  • OpenSanctions (src/sanctions_client.py). Queried at vessel-build time for SDN, EU, UK, UN, FOC, and NCP-IUU matches. The frozen config/ofac_fishing_sanctions.json is an offline fallback when the OpenSanctions API is unreachable (air-gapped runs, weekly digest jobs without network).
  • GFW v3 events regions block (src/osint_profiler._summarise_event_regions). Classifies fishing events against MPA, no-take, FAO, and RFMO geofences. The simplified bboxes in config/ccamlr_areas.geojson are kept as a fallback for AIS-gap zone classification only.
  • Marine Regions EEZ, GMR, and IWC sanctuary GeoJSONs in config/maritime_zones/. Covers Galápagos, Senegal, Mauritania, Guinea, and the IWC Southern Ocean Whale Sanctuary.

Known gap. config/ccamlr_transhipment_authorized.json is empty because the CM 10-09 authorized-reefer list lives behind the CCAMLR member-state portal. config/reefer_watchlist.json covers the Aker BioMarine declared reefers used in our test cases. When an encounter cannot be matched against either list, the report shows a warning banner instead of asserting unauthorized status.

Investigator playbook

INVESTIGATOR_PLAYBOOK.md covers weekly fleet triage, encounter deep dives, and dossier preparation for external partners.

Status

Feature Status Notes
Live AIS triage dashboard Shipped Triage, fleet map, vessel detail, transhipments UI
Transhipment detector Shipped v0.4.2, six signals, 107 tests, weekly HTML report
Weekly HTML review report Shipped python main.py --mode transhipment-review
Investigator UI (web/) Shipped Home triage, /vessels, /vessels/{slug}, /transhipments
Datasets compilation Live and curated OpenSanctions live, GFW-native MPA/RFMO regions, Marine Regions EEZs. CM 10-09 authorized reefer list still requires CCAMLR member-state access.
RPi / offline vessel mode Deferred Architecture documented, hardware integration not implemented

Contributing

Open an issue or pull request. Follow Conventional Commits (feat:, fix:, docs:, chore:). Before submitting: npx tsc --noEmit in web/ and python -m pytest tests/ must pass. The CI gate enforces both.

Refresh README screenshots when the UI changes. With npm run dev running:

cd web
node scripts/capture-readme-screenshots.mjs

Output lands in docs/screenshots/. Commit the regenerated PNGs in the same PR. The script is documented in docs/SCREENSHOTS.md.

License

GPL-3.0.

Author

Personal, independent project. Built by a supporter of CPWF and Sea Shepherd. Not officially affiliated with either organisation.

About

Maritime OSINT dashboard tracking industrial krill, whaling and IUU fishing fleets. CCAMLR transhipment scoring (CM 10-04/06/07/09), AIS gap detection, OpenSanctions hits, Global Fishing Watch encounters. Next.js + FastAPI + DuckDB.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors