Agent skill

ShadowBroker Intelligence Client

by BigBodyCobain in BigBodyCobain/Shadowbroker

Lets an agent query a ShadowBroker OSINT platform for tracked flights, ships, satellites and news, and place its findings on the map as intel pins.

AGPL-3.0Auto-check: warningsSecurity

Install ShadowBroker Intelligence Client

The automated check flagged lines worth reading first. See the safety section below.

skills CLI
$ npx skills add BigBodyCobain/Shadowbroker --skill shadowbroker -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install BigBodyCobain/Shadowbroker shadowbroker --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/BigBodyCobain/Shadowbroker.git skills-src && mkdir -p .claude/skills && cp -r skills-src/openclaw-skills/shadowbroker .claude/skills/shadowbroker && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
shadowbroker
GitHub stars
11k
Token cost
~8.9k tokens
SKILL.md length
2,634 words
Files
11
Skills in repo
1
Repo updated
First seen
Licence
AGPL-3.0

At a glance

Lets an agent query a ShadowBroker OSINT platform for tracked flights, ships, satellites and news, and place its findings on the map as intel pins.

  • Works in 12 steps: Telemetry Queries → Pin Placement (AI Intel Map Layer) → Geocoding → …
  • Asking where a tracked aircraft or ship is right now
  • SKILL.md covers Agent Fast Path (read first), How to Use This Skill, Available Tools and Message Signatures, plus 2 more sections
  • Runs Python scripts from its folder; calls python; reaches nuforc.org and discord.com; needs SHADOWBROKER_HMAC_SECRET and SHADOWBROKER_KEY

What it does

ShadowBroker is a real-time OSINT platform that runs on `localhost:8000` by default and tracks flights, ships, satellites, earthquakes, fires, conflict events and prediction markets, with coordinates on every data layer. The agent imports `ShadowBrokerClient` from `sb_query` and relies on three calls: `ask` for natural-language reads, `run_playbook` for pre-batched snapshots such as `morning_brief` and `hot_snapshot`, and `channel_status` for a quick liveness check.

Slow commands such as telemetry searches are blocked unless `confirm_expensive=true` is set, and the notes list anti-patterns like sequential command loops. Beyond reading, the skill covers pinning AI intel on the map, managing autonomous monitoring, injecting data into layers, fetching satellite imagery, aggregating news, generating reports and joining the Wormhole mesh network, with scripts such as `sb_monitor.py`, `sb_alerts.py` and `sb_briefing.py`. A remote agent sets `SHADOWBROKER_URL` and an HMAC secret, which the client uses to sign requests and which must never be sent as a plain header.

When your agent uses it

  • Asking where a tracked aircraft or ship is right now
  • Getting a morning briefing across the map's data layers
  • Placing an AI-generated intel pin on the ShadowBroker map
  • Setting up monitoring that raises alerts on changes

Example prompts

  • “Show me the ships and flights near the Strait of Hormuz right now.”
  • “Run the morning_brief playbook and summarize anything unusual.”
  • “Check ShadowBroker's channel status and tell me whether the local instance is reachable.”
  • “Pull recent news about Red Sea shipping and pin the key locations on the map.”

Requirements

  • A running ShadowBroker instance, local on port 8000 or remote
  • `SHADOWBROKER_URL` and `SHADOWBROKER_HMAC_SECRET` for remote mode
  • Python to run the bundled client

Workflow steps

12 steps, taken from the step headings in SKILL.md.

  1. Telemetry Queries
  2. Pin Placement (AI Intel Map Layer)
  3. Geocoding
  4. Satellite Imagery
  5. News & GDELT Near Location
  6. Near Me (Full Proximity Scan)
  7. Native Layer Data Injection
  8. Wormhole / InfoNet / Mesh Network
  9. Alert Delivery
  10. Intelligence Reports
  11. SAR (Synthetic Aperture Radar) Layer
  12. Analysis Zones (Agent-Authored Map Notes)

What it can do on your machine

Read from SKILL.md and the folder at commit 84ab6cb. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Ships script files (Python), which the agent can run.

    Shell commands in SKILL.md call:

    • python

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • nuforc.org
    • discord.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • SHADOWBROKER_HMAC_SECRET
    • SHADOWBROKER_KEY
    • BOT_TOKEN

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

ShadowBroker Intelligence Client loads about 8.9k tokens when it runs. Until then it costs about 79 tokens; SKILL.md has 2,634 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~79
When it runs · the whole SKILL.md, loaded when a task matches
~8.9k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: warnings

The automated check found patterns that need a careful read before installing.

  • WarningMentions a paste, webhook or tunnelling service often used to send data outSKILL.md:470
    alerts.add_discord("https://discord.com/api/webhooks/YOUR/WEBHOOK")

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from BigBodyCobain/Shadowbroker at commit 84ab6cb, republished under its AGPL-3.0 licence (© BigBodyCobain). 2,634 words, ~8,904 tokens.

Download SKILL.mdSave it as .claude/skills/shadowbroker/SKILL.md (or your agent's skills folder). This skill also uses 10 other files; get the full folder from GitHub.
name
shadowbroker
description
Query the ShadowBroker OSINT intelligence platform for real-time geospatial intelligence, place AI intel pins on the map, manage autonomous monitoring, inject data into native layers, fetch satellite imagery, aggregate news, generate intelligence reports, and participate in the Wormhole mesh network.

ShadowBroker Intelligence Skill

You have access to ShadowBroker, a real-time global OSINT intelligence platform running on localhost:8000. It tracks military flights, ships, satellites, SIGINT, earthquakes, fires, GDELT conflict events, prediction markets, and 30+ other data layers — all with geographic coordinates.

Agent Fast Path (read first)

ShadowBroker exposes dozens of read commands. Do not explore them. Use the three-tool surface:

ToolWhen
await sb.ask("natural language question")Default for reads — server routes to fastest command
await sb.run_playbook("hot_snapshot")Pre-batched snapshots (morning brief, monitor poll, status)
await sb.channel_status()Liveness (~5 ms) — never /api/health

Latency tiers: get_entity_profile / find_entity / get_entity_trail / find_flights / search_news / entities_near → ⚡ <30 ms. search_telemetry / get_telemetry / get_report → 🔴 seconds — blocked unless confirm_expensive=true.

python
# Default read path (route + execute)
answer = await sb.ask("where is the Patriots jet")

# Named batch plans
brief = await sb.run_playbook("hot_snapshot")
monitor = await sb.run_playbook("monitor_heartbeat")

# Structured lookup when you already parsed fields
entity = await sb.send_command("find_entity", {"owner": "musk", "compact": True})

# Multi-command — always batch, never sequential loops
batch = await sb.send_batch([
    {"cmd": "get_summary", "args": {"compact": True}},
    {"cmd": "what_changed", "args": {"compact": True}},
])

Playbooks: hot_snapshot, morning_brief, status_check, monitor_heartbeat, track_snapshot, jet_recon, area_brief, entity_recon.

Anti-patterns: search_telemetry for known tail numbers; get_telemetry for routine polls; sequential send_command loops; empty layers: [] on get_layer_slice.

Load machine-readable routing hints once: GET /api/ai/capabilities → routing.

How to Use This Skill

Import the client and call methods:

python
from sb_query import ShadowBrokerClient
sb = ShadowBrokerClient()  # auto-detects local or remote mode
Local Mode (same machine)

No configuration needed. The client connects to localhost:8000 automatically.

Remote Mode (agent on different machine/VPS)

Set these environment variables in your agent's config:

bash
SHADOWBROKER_URL=https://your-shadowbroker-host:8000
SHADOWBROKER_HMAC_SECRET=your-hmac-secret-here

The HMAC secret is found in ShadowBroker's Connect OpenClaw modal (AI Intel panel). SHADOWBROKER_HMAC_SECRET is a shared signing secret, not a raw API key. Do not send it as X-Admin-Key, Authorization: Bearer, a query parameter, or any plain request header. The ShadowBrokerClient signs every direct request with X-SB-Timestamp, X-SB-Nonce, and X-SB-Signature using:

text
HMAC-SHA256(secret, METHOD|path|timestamp|nonce|sha256(body))

For compatibility with older snippets, SHADOWBROKER_KEY is also accepted by the client as the same HMAC signing secret. Prefer SHADOWBROKER_HMAC_SECRET for new setups.

Docker Compose: host-side agents (localhost:8000 from the Kali/macOS host) are not loopback inside the backend container — HMAC is required. After Connect OpenClaw → Bootstrap → Reveal, the secret is persisted under data/openclaw.env on the backend_data volume. Restart the backend once, then verify with:

bash
python openclaw-skills/shadowbroker/verify_hmac.py

Hand-rolled signers must hash the exact POST bytes. Use compact JSON: json.dumps(payload, separators=(",", ":"), sort_keys=True).

SSE Stream (Preferred — Low-Latency Push)

Open the SSE stream first and keep it open for the session. The server pushes layer_changed events whenever any data layer refreshes — you know exactly which layers to fetch instead of blind-polling.

python
# Open the stream — authenticates once via HMAC, then stays open
async for event in sb.stream_updates():
    if event["event"] == "connected":
        # Initial handshake — contains full layer_versions snapshot
        print(f"Connected: {event['data']['layer_versions']}")

    elif event["event"] == "layer_changed":
        # Server tells you which layers updated and their new version/count
        changed = event["data"]["layers"]  # e.g. {"ships": {"version": 43, "count": 1287}}
        # Fetch ONLY the layers that actually changed
        data = await sb.get_layer_slice(list(changed.keys()))
        # get_layer_slice uses per-layer versions internally — only changed
        # layers are serialized, unchanged layers transfer zero bytes

    elif event["event"] == "alert":
        # Watchdog alert — geofence hit, callsign spotted, keyword matched
        print(f"Alert: {event['data']}")

    elif event["event"] == "task":
        # Operator-pushed task
        print(f"Task: {event['data']}")
Command Channel (Bidirectional)

Send commands via HTTP alongside the SSE stream:

python
# Send a command and get the result
result = await sb.send_command("get_summary")

# Batch multiple commands in one HTTP round-trip (concurrent execution)
results = await sb.send_batch([
    {"cmd": "find_flights", "args": {"query": "N189AM", "compact": True}},
    {"cmd": "search_news", "args": {"query": "carrier", "compact": True}},
])

# Check channel status and security tier
status = await sb.channel_status()
print(f"Tier {status['tier']}: {status['reason']}")

The channel operates over HMAC-authenticated HTTP with body-integrity binding:

  • HMAC Direct: Commands are signed with HMAC-SHA256. Wire privacy relies on TLS.
  • SSE Stream: Authenticates once at connection open — no per-event HMAC overhead.
  • MLS E2EE (planned, not yet available): Future upgrade to route commands via Wormhole DM with forward secrecy.

Available Tools

1. Telemetry Queries

Primary pattern (lowest latency): Use the SSE stream + targeted get_layer_slice:

MethodWhat It ReturnsWhen to Use
sb.stream_updates()SSE push: layer_changed, alerts, tasksOpen first, keep open — tells you exactly which layers updated
await sb.get_layer_slice(["ships", "gdelt"])Only the requested layers, with per-layer incrementalPrimary fetch method — automatically skips layers you already have
await sb.send_command("get_summary")Lightweight counts-only summaryDiscover what data exists before pulling anything
await sb.get_fetch_health()Sanitized process-local outcomes for instrumented fetch and maintenance tasksResults reset on backend restart; condition is the latest recorded task completion, not data freshness
await sb.ask("...")Route + executeDefault for natural-language reads
await sb.send_command("get_entity_profile", {...})Preferred aircraft/vessel dossier — identity, VIP tags, trail, route, ACARS, jamming/correlations, newsTail, owner, callsign, MMSI
await sb.send_command("get_entity_trail", {...})Observed path + route + ACARS hints onlyWhen you don't need full dossier
await sb.send_command("find_entity", {...})Exact-first entity resolverParsed person/tail/callsign/MMSI — skips fuzzy unless fallback_search=true
await sb.send_command("find_flights", {...})Targeted flight searchWhen you know the domain (callsign, tail number)
await sb.send_command("route_query", {...})Routing plan onlyInspect recommended command before executing
await sb.send_command("search_telemetry", {...})Cross-layer fuzzy searchLast resort — requires confirm_expensive=true

Full telemetry dumps (use sparingly — large payloads):

MethodWhat It Returns
await sb.get_telemetry()Fast-tier: flights, ships, satellites, SIGINT, LiveUAMap, CCTV, GPS jamming
await sb.get_slow_telemetry()Slow-tier: GDELT, news, earthquakes, markets, correlations, Telegram OSINT, malware/cyber threats, SCM suppliers
await sb.get_report()Full structured intelligence report
Strategic Risk Analytics (GT early warning)

Requires GT_ANALYTICS_ENABLED=true on the ShadowBroker backend.

Method / commandWhat It Returns
await sb.ask("Run GT analysis on UK/Europe feeds")Routes to gt_analyze
await sb.gt_analyze(region="ukraine")Refresh beliefs from Telegram/news/GDELT + dossier
await sb.gt_risk_heatmap()GeoJSON posterior risk overlay + Louvain clusters
await sb.gt_dossier("ukraine")Costly signals, domain risks, scenarios
await sb.gt_backtest()Static benchmark — labeled historical cases (regression test)
await sb.gt_backtest(tune=True)Grid-search alert threshold for target confidence
await sb.gt_rolling_backtest()Macro operational — week-over-week accuracy on frozen weekly alerts
await sb.gt_micro_rolling()Micro 3-day rolling avg — spot vs baseline, ignition detection
await sb.gt_rolling_freeze()Freeze this ISO week's GT scores before outcomes are known
await sb.gt_rolling_label(week_id, region=..., label=...)Label prior-week outcomes (true_escalation, false_alarm, benign)
await sb.gt_top_alerts()Ranked top GT regions with map coordinates
await sb.ask("Run GT historical backtest")Routes to gt_backtest (benchmark, not operational)
await sb.ask("GT rolling operational backtest trend")Routes to gt_rolling_backtest
python sb_gt_report.pyLocal helper — backtest + heatmap (+ optional --region)
await sb.send_command("gt_analyze", {"region": "europe"})Same as gt_analyze()

Benchmark vs rolling: Static gt_backtest checks the classifier on known textbook cases. gt_rolling_backtest scores frozen weekly live predictions against delayed operator labels — that week-over-week trend (e.g. 54% → 62% → 71%) is the macro real-world metric. gt_micro_rolling adds a 3-day rolling average per region: spot risk vs the trailing baseline catches fast ignitions the weekly roll can miss. Threshold is fixed (GT_ROLLING_ALERT_THRESHOLD, default 0.26); ignition when spot − 3d avg ≥ GT_MICRO_IGNITION_DELTA (default 0.10).

When to use: Use get_summary() first. Use get_layer_slice() for the layers you actually need. Reserve full get_telemetry() / get_slow_telemetry() for rare cases where you genuinely need every field across every layer.

Enriched Data Fields by Layer

Every layer returns maximum telemetry. Key enriched fields:

LayerKey Fields
GDELTevent_date, actors (list), goldstein (intensity -10 to +10), num_mentions, num_sources, num_articles, avg_tone, quad_class
LiveUAMaptitle, description, region, category, date (formatted UTC), timestamp, source, image, link
CrowdThreattitle, summary, category, subcategory, type, country, occurred_iso, verification, severity, source_url, media_urls, votes, reporter
UAP Sightingslat, lng, location, state, count, shape (normalized), shape_raw, duration, summary (witness report), city, from_date, to_date
Wastewatername, lat, lng, alert (boolean), pathogen, concentration, trend, last_sample_date
FIRMS Fireslat, lng, brightness, confidence, frp (fire radiative power), satellite, acq_date
GPS Jamminglat, lng, name/region, intensity, source
Earthquakeslat, lng, magnitude, depth, place, time
Correlationstype, severity, score, lat, lng, drivers (triggering layers)
Telegram OSINTtitle, description, channel, source, link, published, risk_score, coords [lat, lng]
Malware Threatsip, malware, threat_type, status, country, lat, lng (Feodo + URLhaus)
Cyber Threatsid (CVE), name, vendor, product, severity, date (CISA KEV)
SCM Suppliersname, city, country, category, risk_level, active_threats, lat, lng

Layer aliases for get_layer_slice / search_telemetry: telegram → telegram_osint, malware/botnet → malware_threats, cyber/cisa/kev → cyber_threats, scm/suppliers → scm_suppliers.

1b. Recon / OSINT Toolkit

The Recon panel lookups are available on the OpenClaw command channel — no need to hit /api/osint/* directly.

python
# List supported tools
await sb.send_command("osint_tools")

# IP geolocation + threat context
await sb.send_command("osint_lookup", {"tool": "ip", "ip": "8.8.8.8"})

# DNS, WHOIS, certificate transparency
await sb.send_command("osint_lookup", {"tool": "dns", "domain": "example.com"})
await sb.send_command("osint_lookup", {"tool": "whois", "domain": "example.com"})
await sb.send_command("osint_lookup", {"tool": "certs", "domain": "example.com"})

# BGP/ASN, sanctions, CVE, MAC vendor, GitHub, breach check
await sb.send_command("osint_lookup", {"tool": "bgp", "query": "AS15169"})
await sb.send_command("osint_lookup", {"tool": "sanctions", "query": "Rosneft"})
await sb.send_command("osint_lookup", {"tool": "cve", "cve": "CVE-2024-1234"})
await sb.send_command("osint_lookup", {"tool": "mac", "mac": "00:11:22:33:44:55"})
await sb.send_command("osint_lookup", {"tool": "github", "username": "octocat"})
await sb.send_command("osint_lookup", {"tool": "leaks", "email": "user@example.com"})

# Entity relationship graph (aircraft, vessel, ip, company, person, country)
await sb.send_command("entity_expand", {"type": "ip", "id": "8.8.8.8"})
await sb.send_command("entity_expand", {"type": "aircraft", "id": "N400QS", "icao24": "a0f011"})

# Subnet sweep (full tier only — active Shodan InternetDB scan)
await sb.send_command("osint_sweep", {"ip": "1.2.3.4", "cidr": 24})
osint_lookup toolArgsWhat you get
ipipGeo, ISP, ASN, proxy/hosting flags, sanctions cross-check
dnsdomainA/AAAA/MX/NS/TXT records
whoisdomainRegistrar, dates, nameservers
certsdomainCertificate transparency hits
threatsquery (optional)Aggregated threat intel
bgpqueryASN/prefix routing data
sanctionsquery, schema, limitOFAC / sanctions index matches
cvecveNVD CVE details
macmacVendor OUI lookup
githubusernamePublic profile metadata
leaksemailBreach exposure check
sweep_initip, cidrPassive geolocation context for a sweep target
2. Pin Placement (AI Intel Map Layer)

Pins appear on the user's map in a dedicated "AI Intel" layer.

python
# Single pin
await sb.place_pin(
    lat=34.05, lng=-118.24,
    label="UAP Sighting #1",
    category="anomaly",       # see categories below
    description="Multiple witnesses reported lights over Griffith Observatory",
    source="NUFORC Database",
    source_url="https://nuforc.org/...",
    confidence=0.8,            # 0.0 to 1.0
    ttl_hours=48,              # auto-delete after 48 hours (0 = permanent)
)

# Batch pins (up to 100 at once)
await sb.place_pins_batch([
    {"lat": 34.05, "lng": -118.24, "label": "Site A", "category": "research"},
    {"lat": 34.10, "lng": -118.30, "label": "Site B", "category": "research"},
])

# List pins
pins = await sb.get_pins(category="anomaly")

# Delete
await sb.clear_pins(category="anomaly")  # by category
await sb.clear_pins()                     # all

Pin Categories (each has a specific color on the map):

CategoryColorUse For
threat🔴 RedMilitary threats, conflict events, danger zones
anomaly🟠 OrangeUAPs, unusual signals, unexpected patterns
military🟡 YellowMilitary bases, flights, exercises
news🟢 GreenNews events, protests, political events
maritime🔵 BlueShips, ports, maritime events
aviation🟣 PurpleFlights, airports, airspace events
infrastructure⚪ GrayPower plants, data centers, cables
sigint🩷 PinkRF signals, jamming, radio activity
geolocation🫧 TealGeolocated images, placed-from-text
satellite🌌 IndigoSatellite imagery findings
seismic🤎 BrownEarthquakes, volcanic activity
weather🩶 Light grayWeather events, storms
research💜 VioletGeneral research findings
customDefault violetEverything else
3. Geocoding
python
# Place name → coordinates
results = await sb.geocode("Griffith Observatory, Los Angeles")
# Returns: [{"lat": 34.1184, "lon": -118.3004, "display_name": "..."}]

# Always geocode before placing pins if you have a place name, not coordinates.
4. Satellite Imagery
python
# Get latest Sentinel-2 satellite scenes for any location
scenes = await sb.get_satellite_images(lat=35.68, lng=51.38, count=3)
# Returns: {"scenes": [{"scene_id", "datetime", "cloud_cover", "thumbnail_url", "fullres_url"}]}

When to use: When the user asks to "see satellite images of [place]" or wants visual intelligence of a location. Geocode first, then fetch imagery.

5. News & GDELT Near Location
python
# Get GDELT conflict events + news articles near a coordinate
nearby = await sb.get_news_near(lat=-15.4, lng=28.3, radius=500)
# Returns: {"gdelt": [...], "news": [...]} with headlines, source URLs, distances

When to use: When the user asks "what's happening in [country/city]" or wants news from a specific region. Geocode the place name first.

6. Near Me (Full Proximity Scan)
python
# Get ALL telemetry within a radius of a location
everything = await sb.get_near_me(lat=39.74, lng=-104.99, radius_miles=100)
# Returns EVERY layer within radius, each item tagged with distance_miles:
#   military_flights, commercial_flights, tracked_flights, private_jets,
#   ships, sigint, earthquakes, volcanoes, gdelt, liveuamap, crowdthreat,
#   uap_sightings, wastewater, firms_fires, weather_alerts, air_quality,
#   cctv, gps_jamming, satellites, news, correlations

When to use: When the user says "what's near me" or wants a proximity digest. This pulls from both fast and slow tiers automatically.

7. Native Layer Data Injection

Inject custom data directly into ShadowBroker's native layers (CCTV, ships, etc.):

python
# Add a custom CCTV camera to the CCTV layer
await sb.inject_data("cctv", [
    {"lat": 34.1, "lng": -118.3, "url": "https://stream.example.com/cam1",
     "name": "My Traffic Camera"}
])

# Remove all user-injected data
await sb.clear_injected()           # all layers
await sb.clear_injected("cctv")     # just CCTV

Injectable layers: cctv, ships, sigint, kiwisdr, military_bases, datacenters, power_plants, satnogs_stations, volcanoes, earthquakes, news, viirs_change_nodes, air_quality

When to use: When the user wants to add their own data sources to existing layers (e.g., "add this CCTV camera I found", "add this military base").

8. Wormhole / InfoNet / Mesh Network

OpenClaw agents participate in the private Infonet on behalf of the operator who configured the skill. All traffic uses the operator's wormhole persona and local node runtime (MLS gate crypto, Ed25519 signing, Tor onion transport) — the agent does not get a separate fleet identity.

Access tiers

  • restricted (default): read Infonet status, list gates, read gate messages, poll DMs.
  • full (OPENCLAW_ACCESS_TIER=full): also warm Tor, join the swarm, post gate messages, cast votes, and send DMs when the user commands it.

Remote agents authenticate with HMAC on /api/ai/channel/command; loopback uses the local operator lane.

python
# Warm Tor, enable the node, announce to fleet seed (full tier)
await sb.ensure_infonet_ready(join_swarm=True)

# Status snapshot (chain health, wormhole, runtime)
status = await sb.infonet_status()

# Read the public Infonet gate (MLS-encrypted, decrypt with operator keys)
messages = await sb.read_gate_messages("infonet", limit=20, decrypt=True)

# Post on behalf of the operator (full tier) — propagates via peer-push
await sb.post_to_gate("infonet", "Intelligence bulletin: 3 carriers underway in Med")
# Legacy alias:
await sb.post_to_infonet("same as post_to_gate on infonet gate")

# Upvote / downvote a node (full tier)
await sb.cast_vote("!sb_peer_id_or_pubkey", vote=1, gate="infonet")

# Encrypted DMs (peer_id / !sb_... recipient)
await sb.send_encrypted_dm("!sb_recipient", "Eyes only: carrier update")
dms = await sb.read_encrypted_dms(limit=20)

gates = await sb.list_gates()
await sb.join_infonet_swarm()  # re-announce + refresh manifest

# Meshtastic radio
signals = await sb.listen_mesh(region="US", limit=20)
await sb.send_mesh("US", "ShadowBroker AI: SIGINT anomaly detected in sector 7")

# Dead drops
await sb.dead_drop_leave("location_hash", "anonymous intelligence payload")
found = await sb.dead_drop_check("location_hash")
9. Alert Delivery

Send branded alerts to the user's messaging channels:

python
from sb_alerts import AlertDispatcher
alerts = AlertDispatcher()
alerts.add_discord("https://discord.com/api/webhooks/YOUR/WEBHOOK")
alerts.add_telegram("BOT_TOKEN", "CHAT_ID")

await alerts.send_brief("Morning intelligence digest here...")
await alerts.send_warning("Earthquake M5.2 detected 43mi from your location")
await alerts.send_threat("Threat level changed: GUARDED → ELEVATED")
await alerts.send_news("Breaking: GPS jamming detected over Baltic Sea")
await alerts.send_intel("USS Ford entered Mediterranean, heading east")
10. Intelligence Reports
python
# Full structured report
report = await sb.get_report()
# Contains: summary stats, top military flights, correlations, earthquakes, SIGINT, pin counts

# Lightweight summary (counts only)
summary = await sb.get_summary()
Show full SKILL.md (1,108 more words)Show less
11. SAR (Synthetic Aperture Radar) Layer

ShadowBroker can ingest free SAR data in two modes:

  • Mode A (default-on, no account): Sentinel-1 scene catalog from the Alaska Satellite Facility — pure metadata, no downloads, no DSP. Lets the agent answer "what radar passes have happened over this AOI in the last 36 hours and when's the next pass?"
  • Mode B (opt-in, free account): Pre-processed ground-change anomalies from NASA OPERA, Copernicus EGMS, GFM, EMS, and UNOSAT — already-computed flood polygons, deformation maps, and damage assessments. Requires the user to enable Mode B in Settings → SAR (sets two env flags) and add a free Earthdata token.
python
# Always check status first — when Mode B is off the response includes a
# step-by-step help block with signup URLs the agent can paste to the user.
status = await sb.sar_status()
if not status["data"]["products"]["enabled"]:
    # Mode B disabled — surface the in-app links to the user
    for step in status["data"]["products"]["help"]["steps"]:
        print(f"Step {step['step']}: {step['label']} → {step['url']}")

# Recent anomalies (Mode B; empty list when disabled)
anomalies = await sb.sar_anomalies_recent(kind="flood_extent", limit=20)

# Anomalies near a coordinate
near = await sb.sar_anomalies_near(lat=50.45, lng=30.52, radius_km=50)

# Scene catalog (Mode A; always populated when AOIs exist)
scenes = await sb.sar_scene_search(aoi_id="kyiv_metro", limit=10)

# Per-AOI coverage + next-pass estimate
coverage = await sb.sar_coverage_for_aoi(aoi_id="kyiv_metro")

# AOI management
aois = await sb.sar_aoi_list()
await sb.sar_aoi_add(
    id="port_of_odesa", name="Port of Odesa",
    center_lat=46.4858, center_lon=30.7333, radius_km=15,
    category="conflict",
)

# Promote an anomaly to an AI Intel pin (writes into the dashboard)
await sb.sar_pin_from_anomaly(anomaly_id="opera-disp-...", label="OPERA deformation")

# Continuous watchdog — fire when matching anomalies appear in an AOI
await sb.sar_watch_anomaly(aoi_id="port_of_odesa", kind="surface_water_change")

# Inspect the same detail payload the operator's map popup shows for a pin
detail = await sb.sar_pin_click(anomaly_id="opera-disp-...")
# -> {"anomaly": {...}, "aoi": {...}, "recent_scenes": [...]}

# Fly the operator's map to an AOI center (useful after adding a new AOI,
# or to direct attention after a fresh anomaly arrives).  The frontend
# picks this up via useAgentActions and calls its map flyTo handler.
await sb.sar_focus_aoi(aoi_id="kyiv_metro", zoom=9.0)

SAR rules of engagement:

  1. Call sar_status() first when the user asks about SAR/radar/deformation/floods.
  2. If Mode B is off, paste the help.steps URLs to the user — never tell them to "search for it", the links are right there in the response.
  3. SAR anomalies carry an evidence_hash — preserve it when promoting to a pin so other nodes can verify lineage.
  4. Mode B writes signed mesh events only when the local node is at private_transitional or higher. Otherwise the data stays local.

12. Analysis Zones (Agent-Authored Map Notes)

The old regex-based "contradiction detector" has been removed — it pattern matched denial keywords against internet outages and produced constant false positives. It has been replaced with analysis zones: colored square overlays you drop on the map with a written assessment. Think of them as sticky notes: "I noticed X in this area, here is what I think it means."

The operator reads your assessment by clicking the zone and can delete any zone from the popup with a trash icon. Zones persist across restarts.

python
# List zones currently on the map
zones = await sb.list_analysis_zones()

# Drop a new zone — general assessment (cyan)
await sb.place_analysis_zone(
    lat=50.45, lng=30.52,
    title="Kyiv metro unusual quiet",
    body=(
        "Transit ridership dropped ~60% vs baseline over the last 6 hours "
        "while ADS-B shows two Russian ELINT orbits north of the city. "
        "No official advisory posted yet.  Possible pre-strike posture, "
        "but could also be routine drill.  Watching for next 2h."
    ),
    category="observation",
    severity="medium",
    drivers=[
        "Transit -60% vs 7-day baseline",
        "2x Russian ELINT orbits at 34k ft N of city",
        "No advisory posted on official channels",
    ],
    cell_size_deg=0.8,  # city-scale
)

# Drop a contradiction note (amber) when statements conflict with telemetry
await sb.place_analysis_zone(
    lat=36.2, lng=37.1,
    title="Damascus 'normal operations' claim",
    body=(
        "MoD statement at 14:00 claimed 'normal operations' across Syria. "
        "At the same timestamp, Cloudflare radar shows 42% internet "
        "outage across the western corridor and three military bases "
        "went dark on SIGINT.  Worth a closer look."
    ),
    category="contradiction",
    severity="high",
    drivers=[
        "Official statement: 'normal operations'",
        "Cloudflare radar: 42% outage western corridor",
        "3 bases lost SIGINT emissions simultaneously",
    ],
)

# Delete a stale zone
await sb.delete_analysis_zone(zone_id="abc123def456")

# Wipe all zones (use sparingly)
await sb.clear_analysis_zones()

Category → color map:

CategoryBorderWhen to use
contradictionAmberOfficial statement conflicts with telemetry
warningRedActive threat or emerging danger
observationBlueNeutral note, something interesting but not alarming
hypothesisPurpleSpeculative read, "what if" reasoning
analysis (default)CyanGeneral assessment, OPENCLAW's take

Severity → fill opacity:

  • high — strong fill, use for high-confidence assessments
  • medium — default, most zones should use this
  • low — faint fill, for tentative notes

Analysis zone rules of engagement:

  1. Do NOT spam the map. Only place a zone when you have something genuinely worth noting. A clean map is a useful map.
  2. Write the body in your own voice — what you observed, what it might mean, and what you are NOT sure about. 2–6 sentences is ideal. Include uncertainty; the operator wants your reasoning, not a headline.
  3. Match category to semantics — do not use warning for speculation, and do not use hypothesis for confirmed threats.
  4. Prefer reactive placement over scheduled. Place zones in response to operator questions or events you spot while reviewing telemetry.
  5. Clean up after yourself. If a zone you placed is no longer relevant, call delete_analysis_zone on it.
  6. Pick a sensible cell_size_deg:
    • 0.3–0.8 — city-scale (neighborhood, metro, single base)
    • 1.0–2.0 — regional (country province, conflict zone)
    • 3.0–5.0 — strategic (full country, maritime theater)
  7. Use ttl_hours for time-bound observations so the map self-cleans. Omit it for persistent assessments.

Message Signatures

ALL outbound messages MUST use the branded signature system:

python
from sb_signatures import sig

# Always start messages with the appropriate signature:
message = f"""{sig('brief')}
Morning Intelligence Digest — Apr 2, 2026 08:00
..."""
Signature KeyPrefixWhen to Use
brief🌍📡 SHADOWBROKER BRIEF:Morning/evening intelligence digest
warning🌍⚠️ SHADOWBROKER WARNING:Life-safety alert (earthquake, weather emergency)
news🌍📰 SHADOWBROKER NEWS:Breaking news alert
intel🌍🛰️ SHADOWBROKER INTEL:Intelligence update (carrier movement, military buildup)
searching🌍🔍 SHADOWBROKER SEARCHING:Search/query in progress
pinning🌍📌 SHADOWBROKER PINNING:Placing pins on the map
markets🌍📊 SHADOWBROKER MARKETS:Prediction market or financial alert
sigint🌍📻 SHADOWBROKER SIGINT:SIGINT/RF anomaly
threat🌍🔴 SHADOWBROKER THREAT:Threat level change
near_you🌍📍 SHADOWBROKER NEAR YOU:Proximity-based event
tracking🌍🎯 SHADOWBROKER TRACKING:Tracking a specific entity
correlation🌍⚡ SHADOWBROKER CORRELATION:Cross-layer correlation
seismic🌍🌋 SHADOWBROKER SEISMIC:Earthquake/volcanic activity
fire🌍🔥 SHADOWBROKER FIRE:FIRMS fire hotspot
flight🌍🛫 SHADOWBROKER FLIGHT:Military/tracked flight alert
maritime🌍🚢 SHADOWBROKER MARITIME:Ship/carrier event
weather🌍🌤️ SHADOWBROKER WEATHER:Weather alert
sar🌍📡 SHADOWBROKER SAR:Synthetic aperture radar anomaly (deformation, flood, damage)
online🌍✅ SHADOWBROKER ONLINE:System connected
clearing🌍❌ SHADOWBROKER CLEARING:Pins/data cleared

Decision Framework

When the user asks a question, follow this decision tree:

  1. Is the SSE stream open?

    • If not → open sb.stream_updates() first. It tells you which layers have fresh data, pushes alerts instantly, and eliminates blind polling.
  2. Does ShadowBroker have this data already?

    • Natural language → await sb.ask(question) (routes server-side)
    • Batch snapshot → await sb.run_playbook("hot_snapshot")
    • Known domain → find_entity, find_flights, find_ships, search_news, entities_near
    • Unknown domain → find_entity first; only then search_telemetry with confirm_expensive=true
    • Need specific layers → get_layer_slice(["military_flights", "gdelt"]) — only fetches layers that changed since your last call (per-layer incremental).
    • Near a location → entities_near() or get_near_me() (scans all layers within radius)
    • Full dump (rare) → get_telemetry() / get_slow_telemetry() only when targeted commands are insufficient. Always pass compact=true.
  3. Does it need geocoding first?

    • User mentions a place name → geocode() first, then query with coordinates
  4. Does it need external research?

    • Use your web browser to search, then geocode findings and place pins
  5. Should I place pins?

    • YES if the answer has geographic locations
    • Use place_pin() for single locations, place_pins_batch() for multiple
    • Always include source URLs and confidence scores
  6. Should I inject into native layers?

    • YES if the user explicitly wants data in a specific layer (CCTV, ships, etc.)
    • Use inject_data() — items tagged automatically for later removal
  7. Should I set up persistent monitoring?

    • YES if the user wants ongoing tracking (aircraft, ship, geofence, keyword)
    • Use add_watch — alerts push instantly via SSE, no polling needed
  8. Should I send an alert?

    • YES if the user has configured alert channels
    • Use the AlertDispatcher with the correct signature
Telegram rhetoric monitoring (watchdog)

Use watchdog watches for push alerts over SSE — no polling required. Keyword watches now scan Telegram OSINT too (translated and original text).

python
# Alert when "nuclear" appears in news, GDELT, or Telegram OSINT
await sb.send_command("add_watch", {
    "type": "keyword",
    "params": {"keyword": "nuclear", "include_telegram": True},
})

# Alert on new high-risk Telegram posts (LVL >= 7) — rhetoric/escalation monitor
await sb.send_command("add_watch", {
    "type": "telegram_rhetoric",
    "params": {"min_risk_score": 7, "channels": ["nexta_live", "war_monitor"]},
})

# Combine risk threshold + topic filter
await sb.send_command("add_watch", {
    "type": "telegram_rhetoric",
    "params": {"min_risk_score": 8, "keywords": ["crimea", "escalation", "missile"]},
})

When a watch fires, you receive an SSE alert event. Forward it with sb_alerts.send_intel() if the user has Discord/Telegram notification channels.


Important Rules

  1. Open SSE stream first — call sb.stream_updates() at session start and keep it open. It pushes layer_changed events so you know exactly which layers to fetch, and delivers watchdog alerts instantly.
  2. Fetch targeted, not everything — use get_layer_slice(), find_flights(), search_telemetry(), entities_near() instead of full get_telemetry() dumps. Per-layer incremental versioning means unchanged layers transfer zero bytes.
  3. Always use signatures — every outbound message starts with the appropriate sig() prefix
  4. Geocode before pinning — never guess coordinates, always use geocode()
  5. Include sources — every pin should have source and source_url when available
  6. Set confidence scores — 1.0 for verified/official data, 0.5-0.8 for web research, <0.5 for unverified
  7. Set TTL for temporary pins — research results get ttl_hours=48, permanent infrastructure gets 0
  8. Use batch for >3 commands — send_batch() runs up to 20 commands concurrently in one HTTP round-trip
  9. Check summary first — use get_summary() before fetching full telemetry to save bandwidth
  10. Tag injected data — the system auto-tags, but use descriptive source names

© BigBodyCobain, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 10 other files in openclaw-skills/shadowbroker of BigBodyCobain/Shadowbroker.

  • SKILL.md
  • __init__.py
  • sb_alerts.py
  • sb_briefing.py
  • sb_get_summary.py
  • sb_gt_report.py
  • sb_monitor.py
  • sb_query.py
  • sb_signatures.py
  • skill.yaml
  • verify_hmac.py

Open the folder on GitHubat commit 84ab6cb

Compare with similar skills

ShadowBroker Intelligence Client next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

ShadowBroker Intelligence Client compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
ShadowBroker Intelligence Client this skillBigBodyCobain/Shadowbroker11k—~8.9kAutomated safety check: WarnAGPL-3.0
Analyzing Threat Landscape With Mispmukul975/Anthropic-Cybersecurity-Skills34k—~597Automated safety check: PassApache-2.0
Metabigor OSINT Reconj3ssie/metabigor1.8k—~2.4kAutomated safety check: PassMIT
Ctf Osintljagiello/ctf-skills3.4k1 repos~2.3kAutomated safety check: NotesMIT
Awesome Osint Operatorshoyann/RZK-The-Hunter141—~4.8kAutomated safety check: PassCC-BY-SA-4.0
Run Claude Osintelementalsouls/Claude-OSINT2.8k—~1.2kAutomated safety check: PassMIT

Similar skills

  • Analyzing Threat Landscape With Misp

    mukul975/Anthropic-Cybersecurity-Skills

    Query a MISP (Malware Information Sharing Platform) instance via PyMISP to compute event statistics, IOC type breakdowns, threat actor galaxy clusters, and tag trends, and generate threat landscape…

    34k GitHub stars~597 tokensUpdated 1 mo ago
    SecurityAuto-check passed
  • Metabigor OSINT Recon

    j3ssie/metabigor

    Operates the metabigor CLI to map a target's network ranges, subdomains, ports, related domains, CDNs and archived URLs from free sources without API keys.

    1.8k GitHub stars~2.4k tokensUpdated 2 mo ago
    SecurityAuto-check passed
  • Ctf Osint

    ljagiello/ctf-skills

    Provides open source intelligence techniques for CTF challenges.

    3.4k GitHub starsUsed in 1 repo~2.3k tokens
    SecurityAuto-check: notes
  • Awesome Osint Operator

    shoyann/RZK-The-Hunter

    Ethical, evidence-first OSINT planning, tool selection, verification, monitoring, reporting, and guarded official wanted/fugitive-person location intelligence using a structured catalog adapted from…

    141 GitHub stars~4.8k tokensUpdated yesterday
    SecurityAuto-check passed
  • Run Claude Osint

    elementalsouls/Claude-OSINT

    Build, validate, and run the claude-osint skills repo — check SKILL.md frontmatter, run the secretscan.py and h1reference.py helpers, run sync-skill-content.sh, run the smoke test.

    2.8k GitHub stars~1.2k tokensUpdated 1 mo ago
    SecurityAuto-check passed
  • Osint

    smixs/osint-skill

    Conduct deep OSINT research on individuals. An agent skill from smixs/osint-skill.

    141 GitHub stars~5.5k tokensUpdated 7 mo ago
    SecurityAuto-check passed

Questions about ShadowBroker Intelligence Client

What does ShadowBroker Intelligence Client do?

Lets an agent query a ShadowBroker OSINT platform for tracked flights, ships, satellites and news, and place its findings on the map as intel pins. ShadowBroker is a real-time OSINT platform that runs on `localhost:8000` by default and tracks flights, ships, satellites, earthquakes, fires, conflict events and prediction markets, with coordinates on every data layer. The agent imports `ShadowBrokerClient` from `sb_query` and relies on three calls: `ask` for natural-language reads, `run_playbook` for pre-batched snapshots such as `morning_brief` and `hot_snapshot`, and `channel_status` for a quick liveness check.

When should I use ShadowBroker Intelligence Client?

ShadowBroker Intelligence Client fits situations like: asking where a tracked aircraft or ship is right now; getting a morning briefing across the map's data layers; placing an AI-generated intel pin on the ShadowBroker map; setting up monitoring that raises alerts on changes.

How do I install ShadowBroker Intelligence Client in Claude Code?

Run `npx skills add BigBodyCobain/Shadowbroker --skill shadowbroker -a claude-code`. Or copy the skill folder (openclaw-skills/shadowbroker in BigBodyCobain/Shadowbroker) into .claude/skills/shadowbroker in your project. Claude Code loads it when a task matches its description.

How do I install ShadowBroker Intelligence Client in Codex?

Run `npx skills add BigBodyCobain/Shadowbroker --skill shadowbroker -a codex`. Or copy the skill folder (openclaw-skills/shadowbroker in BigBodyCobain/Shadowbroker) into .agents/skills/shadowbroker in your project. Codex loads it when a task matches its description.

Can I use ShadowBroker Intelligence Client in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add BigBodyCobain/Shadowbroker --skill shadowbroker -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/shadowbroker, .gemini/skills/shadowbroker, .github/skills/shadowbroker and .opencode/skills/shadowbroker in your project.

What does ShadowBroker Intelligence Client need to run?

Going by SKILL.md and its folder, ShadowBroker Intelligence Client needs Python for the scripts in its folder, the command-line tools its instructions call (python) and credentials named SHADOWBROKER_HMAC_SECRET, SHADOWBROKER_KEY and BOT_TOKEN. Our summary lists: A running ShadowBroker instance, local on port 8000 or remote; `SHADOWBROKER_URL` and `SHADOWBROKER_HMAC_SECRET` for remote mode; Python to run the bundled client.

Does ShadowBroker Intelligence Client access the network?

SKILL.md names 2 domains. In commands or code: nuforc.org and discord.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.

Is ShadowBroker Intelligence Client safe to install?

Our automated static check of SKILL.md flagged 1 warning(s): mentions a paste, webhook or tunnelling service often used to send data out. Read the flagged lines before installing; the check is not a guarantee either way.

What licence does ShadowBroker Intelligence Client use?

ShadowBroker Intelligence Client is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does ShadowBroker Intelligence Client use?

About 8.9k tokens (SKILL.md is roughly 36k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to ShadowBroker Intelligence Client?

Skills that share tags, products or a category with ShadowBroker Intelligence Client: Analyzing Threat Landscape With Misp (mukul975/Anthropic-Cybersecurity-Skills, 34k stars), Metabigor OSINT Recon (j3ssie/metabigor, 1.8k stars), Ctf Osint (ljagiello/ctf-skills, 3.4k stars) and Awesome Osint Operator (shoyann/RZK-The-Hunter, 141 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains ShadowBroker Intelligence Client?

BigBodyCobain (a GitHub user) maintains it in BigBodyCobain/Shadowbroker, which has 11,295 GitHub stars. The repository was last updated on October 8, 2026.

Source: BigBodyCobain/Shadowbroker on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.