-
Notifications
You must be signed in to change notification settings - Fork 0
Scheduling
Signal has two automated jobs — a daily brief at 5:00 AM and a weekly summary every Sunday at 11:00 PM. Both are managed by macOS launchd.
| Job | Schedule | Script | Config |
|---|---|---|---|
| Daily brief | Every day, 5:00 AM | run_and_publish.sh |
com.flexrpl.signal.plist |
| Weekly summary | Every Sunday, 11:00 PM | run_weekly_and_publish.sh |
com.flexrpl.signal.weekly.plist |
launchd is macOS's native service management framework. It reads .plist (property list) configuration files from ~/Library/LaunchAgents/ and triggers scripts at the specified calendar intervals.
Daily flow:
launchd (5:00 AM daily)
→ run_and_publish.sh
→ python main.py --no-venv # Passes 1–5, fetches articles
→ git add reports/ index.html archive.html
→ git commit -m "signal: daily brief YYYY-MM-DD"
→ git push origin main
→ GitHub Actions deploys to GitHub PagesWeekly flow:
launchd (11:00 PM every Sunday)
→ run_weekly_and_publish.sh
→ python main.py --weekly --no-venv # Pass 6 only, reads DB
→ git add reports/weekly_*.html index.html archive.html
→ git commit -m "signal: weekly brief YYYY-WNN"
→ git push origin main
→ GitHub Actions deploys to GitHub Pages| File | Purpose |
|---|---|
scripts/com.flexrpl.signal.plist |
Daily source of truth — commit changes here |
~/Library/LaunchAgents/com.flexrpl.signal.plist |
Daily active copy — what launchd reads |
scripts/com.flexrpl.signal.weekly.plist |
Weekly source of truth — commit changes here |
~/Library/LaunchAgents/com.flexrpl.signal.weekly.plist |
Weekly active copy — what launchd reads |
Important: Editing a repo plist does NOT automatically update the active copy. You must copy and reload after every change.
Daily job:
cp scripts/com.flexrpl.signal.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.flexrpl.signal.plistWeekly job:
cp scripts/com.flexrpl.signal.weekly.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.flexrpl.signal.weekly.plistVerify both loaded:
launchctl list | grep flexrpl
# Should show:
# - 0 com.flexrpl.signal
# - 0 com.flexrpl.signal.weeklyAny time you edit scripts/com.flexrpl.signal.plist:
launchctl unload ~/Library/LaunchAgents/com.flexrpl.signal.plist
cp scripts/com.flexrpl.signal.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.flexrpl.signal.plistSame pattern for the weekly plist:
launchctl unload ~/Library/LaunchAgents/com.flexrpl.signal.weekly.plist
cp scripts/com.flexrpl.signal.weekly.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.flexrpl.signal.weekly.plistVerify the change took effect:
cat ~/Library/LaunchAgents/com.flexrpl.signal.plist | grep -A4 StartCalendarInterval
cat ~/Library/LaunchAgents/com.flexrpl.signal.weekly.plist | grep -A8 StartCalendarIntervalEdit the StartCalendarInterval block in scripts/com.flexrpl.signal.plist:
<!-- Run daily at 5:00 AM local time -->
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>5</integer> <!-- 0–23, local time -->
<key>Minute</key>
<integer>0</integer>
</dict>Current schedule: 5:00 AM local time daily.
5am was chosen to capture overnight wire service content and early-morning news cycle updates before peak traffic hits news servers.
Common alternatives:
| Schedule | Hour | Minute |
|---|---|---|
| 5:00 AM (current) | 5 | 0 |
| 6:00 AM | 6 | 0 |
| 7:00 AM | 7 | 0 |
| 12:01 AM | 0 | 1 |
After changing, always apply with the unload/copy/reload sequence above.
The plist injects SIGNAL_LLM_PROVIDER=claude into the job's environment:
<key>EnvironmentVariables</key>
<dict>
<key>SIGNAL_LLM_PROVIDER</key>
<string>claude</string>
</dict>Do not change this to
ollama— Ollama's Metal GPU access from a launchd daemon context causes kernel panics. See LLM Providers and Troubleshooting.
Daily:
# Run the script exactly as launchd does (output → logs/cron.log)
bash /Users/garotconklin/garotm/fleXRPL/signal/scripts/run_and_publish.sh
# Run the pipeline only (live terminal output, no git push)
python3 /Users/garotconklin/garotm/fleXRPL/signal/main.py
# Trigger via launchd directly (identical environment to scheduled run)
launchctl start com.flexrpl.signalWeekly:
# Run the weekly script exactly as launchd does (output → logs/weekly.log)
bash /Users/garotconklin/garotm/fleXRPL/signal/scripts/run_weekly_and_publish.sh
# Run weekly synthesis only (live terminal output, no git push)
python3 /Users/garotconklin/garotm/fleXRPL/signal/main.py --weekly
# Run over a custom window (e.g. past 5 days instead of 7)
python3 /Users/garotconklin/garotm/fleXRPL/signal/main.py --weekly --days 5
# Trigger via launchd directly
launchctl start com.flexrpl.signal.weekly| Log file | Written by |
|---|---|
logs/cron.log |
Daily pipeline (run_and_publish.sh) |
logs/weekly.log |
Weekly synthesis (run_weekly_and_publish.sh) |
Both logs rotate automatically when they exceed 1MB (.log → .log.bak). Log files are gitignored and never committed to the repository.
# Watch daily run live
tail -f logs/cron.log
# Watch weekly run live
tail -f logs/weekly.log
# Last daily run summary
grep -A5 "Signal run started" logs/cron.log | tail -20
# Last weekly run summary
grep -A5 "Signal WEEKLY run started" logs/weekly.log | tail -20<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.flexrpl.signal</string>
<key>EnvironmentVariables</key>
<dict>
<key>SIGNAL_LLM_PROVIDER</key>
<string>claude</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/garotconklin/garotm/fleXRPL/signal/scripts/run_and_publish.sh</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>5</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<key>StandardOutPath</key>
<string>/Users/garotconklin/garotm/fleXRPL/signal/logs/cron.log</string>
<key>StandardErrorPath</key>
<string>/Users/garotconklin/garotm/fleXRPL/signal/logs/cron.log</string>
<!-- Do not re-run on login/reboot if the scheduled time was missed -->
<key>RunAtLoad</key>
<false/>
</dict>
</plist>Neither job runs automatically when the plist is loaded or on login. They only fire at their scheduled calendar intervals. If the Mac is off or asleep at the scheduled time, that run is skipped until the next occurrence.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.flexrpl.signal.weekly</string>
<key>EnvironmentVariables</key>
<dict>
<key>SIGNAL_LLM_PROVIDER</key>
<string>claude</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/garotconklin/garotm/fleXRPL/signal/scripts/run_weekly_and_publish.sh</string>
</array>
<!-- Every Sunday at 11:00 PM local time (Weekday 0 = Sunday) -->
<key>StartCalendarInterval</key>
<dict>
<key>Weekday</key>
<integer>0</integer>
<key>Hour</key>
<integer>23</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<key>StandardOutPath</key>
<string>/Users/garotconklin/garotm/fleXRPL/signal/logs/weekly.log</string>
<key>StandardErrorPath</key>
<string>/Users/garotconklin/garotm/fleXRPL/signal/logs/weekly.log</string>
<key>RunAtLoad</key>
<false/>
</dict>
</plist>launchd Weekday values: 0 = Sunday, 1 = Monday, ..., 6 = Saturday.
Job not appearing in launchctl list:
launchctl load ~/Library/LaunchAgents/com.flexrpl.signal.plist
launchctl load ~/Library/LaunchAgents/com.flexrpl.signal.weekly.plist
launchctl list | grep flexrplJob shows error code (non-zero) in launchctl list:
cat logs/cron.log # check daily pipeline errors
cat logs/weekly.log # check weekly synthesis errorsSchedule didn't update after editing the plist:
The active copy in ~/Library/LaunchAgents/ was not updated. Run the unload/copy/reload sequence for the relevant plist.
Run completed but no new report on GitHub Pages: Check the relevant log file for git errors. The most common cause is a merge conflict or stale branch.
Weekly synthesis: "No complete runs with briefs found":
The weekly pipeline requires at least one successful daily run in the past 7 days. Run python3 main.py first to generate at least one daily brief, then re-run python3 main.py --weekly.
Signal · Repository · fleXRPL · Daily political intelligence — powered by local AI