red-alert-statusline
June 22, 2026 ยท View on GitHub
A Claude Code statusline that shows real-time Pikud HaOref (Israel Home Front Command) rocket and missile alerts directly in your Claude session's status bar.
๐ MISSILES ยท 5 cities ยท ืชื ืืืื - ืืจืื ืืขืืจ
โ ๏ธ PRE-ALERT ยท ื ืชื ืื ยท ืืืจื
โ
ALL CLEAR ยท ืจืืช ืื
Statusline in action:
What it shows
๐ MISSILES ยท ืชื ืืืื - ืืจืื ืืขืืจ ยท ืจืืช ืื - ืืขืจื
^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | Cities affected (โค3 inline; >3 cycles one at a time)
| Alert category label
Alert icon
| Icon | Category | Display duration |
|---|---|---|
| โ ๏ธ PRE-ALERT | Category 14 โ imminent threat warning | Up to 20 minutes |
| ๐ MISSILES | Category 1 | 60s after last siren |
| โ๏ธ HOSTILE AIRCRAFT | Category 2 | 60s after last detection |
| ๐ EARTHQUAKE | Category 3 | 60s |
| ๐ TSUNAMI | Category 4 | 60s |
| โข๏ธ RADIOLOGICAL | Category 5 | 60s |
| โฃ๏ธ HAZMAT | Category 6 | 60s |
| ๐ซ INFILTRATION | Category 7 | 60s |
| โ ALL CLEAR | Category 13 โ event concluded | 15s |
| ๐ DRILL | Categories 101โ107 | 60s |
| ๐ฎ๐ฑ Pikud HaOref: all clear | Fade-out | 10s, then silent |
City display โ no filter set:
When RED_ALERT_CITIES is not set, all cities from the alert are shown using this strategy:
- 3 or fewer cities โ displayed inline, separated by
ยท:๐ MISSILES ยท ืชื ืืืื - ืืจืื ืืขืืจ ยท ืจืืช ืื - ืืขืจื - More than 3 cities โ shows the total count and cycles through cities one at a time:
๐ MISSILES ยท 5 cities ยท ืชื ืืืื โ one Claude response ๐ MISSILES ยท 5 cities ยท ืจืืช ืื โ next response, 2s later ๐ MISSILES ยท 5 cities ยท ืืืืื โ next response after that
The cycling is time-based (no background timer needed): the script divides the current
unix timestamp by 2 and takes % city_count to pick which city to display. Each time
Claude responds and 2+ seconds have passed, the next city in rotation appears.
City display โ filter set, no match: the statusline shows nothing, as if there is no alert.
Pre-alert priority: Category 14 pre-alerts (early warning before sirens) are shown first, above any other alert type. If no real alert (cat 1โ7) follows within 20 minutes, the pre-alert expires automatically.
Why it's useful
The official Home Front Command API is a live snapshot โ alerts appear on the endpoint only for the seconds that sirens are sounding, then disappear. This statusline maintains a 60-second persistence window so you see the alert even after the raw JSON has gone empty, giving you the full shelter window to act.
Prerequisites
- bash 3.2+ (the macOS system bash is fine)
- curl (pre-installed on macOS)
- jq โ install with
brew install jq
Geo-blocking note: The official
oref.org.ilAPI may block non-Israeli IP addresses (Akamai CDN). If you see no alerts during active events, try running the daemon on a server with an Israeli IP (e.g., GCPme-west1). The statusline script will simply stay silent if the API is unreachable.
Quick start
# 1. Install jq if you don't have it
brew install jq
# 2. Clone this repo (or it's already your working directory)
git clone https://github.com/lirantal/red-alert-statusline
cd red-alert-statusline
# 3. Install the statusline
jq --arg p "$(pwd)/red-alert.sh" \
'.statusLine = {"type": "command", "command": $p}' \
~/.claude/settings.json > ~/.claude/settings.json.tmp \
&& mv ~/.claude/settings.json.tmp ~/.claude/settings.json
# 4. Restart Claude Code โ the daemon starts automatically on first response
Manual installation
Add this to ~/.claude/settings.json:
{
"statusLine": {
"type": "command",
"command": "/absolute/path/to/red-alert-statusline/red-alert.sh"
}
}
Configuration
All settings are environment variables. Set them in your shell profile or in the
"env" block of ~/.claude/settings.json.
| Variable | Default | Description |
|---|---|---|
RED_ALERT_CITIES | (unset) | Comma-separated city filter (English or Hebrew). If unset, all cities are shown. |
RED_ALERT_POLL_INTERVAL | 2 | Daemon poll frequency in seconds. |
City filter examples
When RED_ALERT_CITIES is set, the statusline is silent for alerts that don't
affect your cities, and shows only the matching cities from an alert that does.
# Single city โ English name
export RED_ALERT_CITIES="Tel Aviv"
# Multiple cities โ comma-separated, no spaces around commas required
export RED_ALERT_CITIES="Tel Aviv,Ramat Gan,Netanya"
export RED_ALERT_CITIES="Tel Aviv, Ramat Gan, Netanya" # spaces OK, they're trimmed
# Hebrew names โ direct substring match against the API's data[] array
export RED_ALERT_CITIES="ืชื ืืืื,ืจืืช ืื"
# Mixed English and Hebrew
export RED_ALERT_CITIES="Tel Aviv,ืืืคื,Beer Sheva"
# Zone/area name โ matches all cities in that zone if they appear in the alert
export RED_ALERT_CITIES="Gush Dan" # won't work; use individual city names
# Spelling variants โ all of these resolve to the same Hebrew city (ืืืจ ืฉืืข)
export RED_ALERT_CITIES="Beer Sheva"
export RED_ALERT_CITIES="Beersheba"
export RED_ALERT_CITIES="Beersheva"
# Via ~/.claude/settings.json env block (persists across sessions):
{
"env": {
"RED_ALERT_CITIES": "Tel Aviv,Ramat Gan,Netanya"
},
"statusLine": {
"type": "command",
"command": "/path/to/red-alert.sh"
}
}
Important: Alert city names from the API include district suffixes in Hebrew, e.g.:
"ืชื ืืืื - ืืจืื ืืขืืจ"(Tel Aviv - City Center)"ืชื ืืืื - ืืจืื ืืขืืจ"(Tel Aviv - South)"ืืฉืงืืื - ืฆืคืื"(Ashkelon - North)
Filtering by "Tel Aviv" or "ืชื ืืืื" matches all Tel Aviv districts because the
match is substring-based.
Matching logic (applied in order, first match wins):
- Direct substring โ the filter term appears anywhere in the Hebrew city name
- English โ Hebrew lookup โ ~70 major cities with common spelling variants are pre-mapped; the Hebrew value is then substring-matched
- Word-level fuzzy โ each word in your filter (โฅ3 chars) is individually checked against the city name, enabling partial matches
If your city is not in the lookup table, use the Hebrew name directly (copy the value
field from cities.json in eladnava/pikud-haoref-api).
How it works
There are two scripts with distinct jobs:
red-alert-daemon.sh โ the poller
Runs permanently in the background. You never interact with it directly โ red-alert.sh
starts it automatically the first time Claude Code calls the statusline.
What it does every 2 seconds:
curlthe official Pikud HaOref endpoint (alerts.json)- Strip the UTF-8 BOM and NUL bytes that the API sometimes injects
- If the response contains a valid JSON alert, parse
cat(category),id,title, anddata(the cities array) - Update
/tmp/red_alert_state.jsonatomically (write to a temp file, thenmv) sored-alert.shnever reads a half-written file
Key behaviour: when the API returns empty (no active siren), the daemon does nothing โ it leaves the last state untouched. The display script handles expiry. This is intentional: the live endpoint is a narrow snapshot that goes empty within seconds of a siren ending, but the threat window is 60+ seconds.
State file written to /tmp/red_alert_state.json:
{
"alert_id": "134168709720000000",
"cat": "1",
"title": "ืืจื ืจืงืืืช ืืืืืื",
"cities": ["ืชื ืืืื - ืืจืื ืืขืืจ", "ืจืืช ืื - ืืขืจื"],
"last_seen_unix": 1711234567,
"pre_alert_active": false,
"pre_alert_time": 0,
"cleared_unix": 0
}
Daemon log: /tmp/red_alert_daemon.log
red-alert.sh โ the statusline renderer
Called by Claude Code after every response. Must return instantly (no network I/O).
What it does:
- Checks if the daemon is running (by PID file); starts it in the background if not
- Reads
/tmp/red_alert_state.jsonwith a singlejqcall - Computes how many seconds have passed since each event (
last_seen_unix,pre_alert_time,cleared_unix) - Applies city filtering if
RED_ALERT_CITIESis set - Runs the state machine (pre-alert โ all-clear โ active โ fade-out โ silent)
- Prints the formatted string to stdout; Claude Code displays it in the status bar
red-alert.sh (called each response) red-alert-daemon.sh (always running)
โ โ
โโโ is daemon running? โโโโโโโโโโโโโโโโโโ>โ
โ no โ start it in background โ every 2s:
โ โ curl alerts.json
โ โ parse response
โ<โโ read /tmp/red_alert_state.json โโโโโโโ write state (atomic mv)
โ
โ compute event ages
โ filter cities by RED_ALERT_CITIES
โ pick state: pre-alert / alert / clear / fade-out / silent
โ format city list (inline โค3, cycling >3)
โผ
stdout โ Claude Code status bar
Alert timing state machine
Event detected by daemon
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ cat=14 (pre-alert) โ show โ ๏ธ PRE-ALERT for 20 min โ highest priority
โ expires if no cat 1-7 follows โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ superseded by real alert or 20 min elapsed
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ cat=1-7 (active) โ show alert for 60s โ
โ even after API goes empty โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ cat=13 received
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ cat=13 (all clear) โ show โ
ALL CLEAR for 15s โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 15s elapsed (or 60s with no cat=13)
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ fade-out window โ show ๐ฎ๐ฑ Pikud HaOref: all clear โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 10s elapsed
โผ
silent (statusline shows nothing)
Uninstall
# Remove from settings.json
jq 'del(.statusLine)' ~/.claude/settings.json > ~/.claude/settings.json.tmp \
&& mv ~/.claude/settings.json.tmp ~/.claude/settings.json
# Stop the daemon
kill $(cat /tmp/red_alert_daemon.pid 2>/dev/null) 2>/dev/null || true
# Clean up state files
rm -f /tmp/red_alert_state.json /tmp/red_alert_daemon.pid /tmp/red_alert_daemon.log
Troubleshooting
Statusline shows nothing during an active alert
- Check if the daemon is running:
cat /tmp/red_alert_daemon.pid && kill -0 $(cat /tmp/red_alert_daemon.pid) - Check daemon logs:
tail -20 /tmp/red_alert_daemon.log - Test the API directly:
curl -s "https://www.oref.org.il/warningMessages/alert/alerts.json" -H "Referer: https://www.oref.org.il/" - If the API returns a 403 or empty response from your IP, you're geo-blocked โ the API primarily serves Israeli IPs.
Statusline shows โ ๏ธ red-alert: jq not found
Install jq: brew install jq
Daemon keeps restarting
Check /tmp/red_alert_daemon.log for errors. Common cause: curl not in PATH when
launched from a non-interactive shell. Verify: which curl.
City filter not matching
- Use the Hebrew city name directly for reliable matching.
- Check
cities.jsonin eladnava/pikud-haoref-api to find the exactvaluestring used in alerts for your city. - Alert city names include district suffixes (e.g.,
"ืชื ืืืื - ืืจืื ืืขืืจ"). Filtering by"ืชื ืืืื"will match all Tel Aviv districts.
Force a state reset
rm -f /tmp/red_alert_state.json /tmp/red_alert_daemon.pid
kill $(cat /tmp/red_alert_daemon.pid 2>/dev/null) 2>/dev/null || true
The daemon will restart and re-initialize on the next Claude response.
Documentation
- Project documentation - development, testing, architecture, and conventions.
Contributing
Please consult CONTRIBUTING for guidelines on contributing to this project.