| Step | Action |
|---|---|
| 1 | Put prompt, send_to_telegram.py, plist.example, newsyslog.example under personal/telegram_digest/... in a project root |
| 2 | Implement a runner from the spec (time window, state, Codex + prompt, send_to_telegram) |
| 3 | Add .env with TELEGRAM_BOT_TOKEN_RPOD, TELEGRAM_CHAT_ID_MY, CODEX_BIN, CODEX_MODEL |
| 4 | Install Python deps, Codex CLI, telegram-mcp |
| 5 | Edit prompt/channels if needed |
| 6 | Copy plist example → replace paths and label → symlink to ~/Library/LaunchAgents → launchctl load |
| 7 | Copy newsyslog example → replace path and user:group → sudo cp ... /etc/newsyslog.d/telegram-digest.conf |
| 8 | Create logs/ and state/, run the runner once by hand |
| 9 | Confirm job in launchctl list and wait or trigger a run in the time window |
Telegram Digest Runner — what it does and why you need it
The runner is the script that decides when to run the digest once per day and then runs Codex. The actual digest (channels, summarization, sending) is defined in the prompt and done by Codex; the runner only does scheduling and orchestration.
Why it’s needed
- Run the digest at most once per day, and only within a time window (e.g. 07:00–13:00 local).
- Invoke Codex CLI with the prompt from
prompt/telegram_channels_summary.md; Codex uses telegram-mcp, builds the digest, and sends it viasend_to_telegram.py(or equivalent). - Remember “already ran today” so repeated scheduler runs don’t start the job again.
What it does, step by step
-
Config
Reads from env: bot token, chat ID, path to Codex (CODEX_BIN), model (CODEX_MODEL). If any required value is missing, exit with an error. -
Time window
Compares current local time to the window (e.g. 07:00–13:00). Outside the window it exits without running (exit 0). -
“Already ran today” check
Reads a state file (e.g.state/last_run.json) withrun_dateandstatus(success/failed).- If there was a successful run today → exit without running.
- If the last run today was
failed→ allow a retry (run again).
-
Start notification
Sends a short “Digest started for <date>” message to Telegram. -
Run Codex
Runs Codex, e.g.:
codex exec --model <CODEX_MODEL> --sandbox danger-full-access <contents of prompt/telegram_channels_summary.md>
with a timeout (e.g. 10 minutes).
Writes Codex stdout/stderr to logs (e.g.logs/codex_stdout_<run_id>.log,logs/codex_stderr_<run_id>.log). -
Interpret result
- Non‑zero exit code → treat as failure.
- Even on exit 0, scan stdout for
__FATAL_ERROR__at the start or for error phrases (“can’t start”, “MCP can’t connect”, “fatal error”, etc.). If found → treat as failure.
-
After the run
- Success: update state with
run_date,status: success, and completion time. - Failure: set
status: failed, send an error notification to Telegram (short message + “check logs at …”).
- Success: update state with
-
Log pruning
Delete old Codex log files (e.g.codex_*.log), keeping only the last N (e.g. 10). -
Job log
Append each run to a job log (e.g.logs/job_runs.log): timestamp, result (START / SUCCESS / FAILED / SKIP / RETRY), and optional details.
Integrations
- send_to_telegram: either call functions from
send_to_telegram.py(escaping, sending) or run it as a subprocess with a JSON array of messages on stdin. - Error notifications: send plain‑text messages to the same Telegram chat (no Markdown to avoid escaping issues).
Scheduling
The runner is intended to be run from cron or launchd every N minutes (e.g. 30). Each run checks the time window and state and either runs the digest once or exits. No changes to files are required for this description; it’s enough to implement your own runner.
===
- TELEGRAM_BOT_TOKEN_RPOD
- TELEGRAM_CHAT_ID_MY
- CODEX_BIN=codex
- CODEX_MODEL=gpt-4o
- paths to files
- limit on request depending on how many you have total subscriptions
- list of channels
- paths to files.
However, just ask for this your coding agent. The groups can also be changed.