mirror of
https://github.com/tiennm99/claude-code-routine-trigger-worker.git
synced 2026-07-18 18:17:44 +00:00
chore: park worker, recommend cron-job.org as primary scheduler
Comment out [triggers].crons in wrangler.toml — migrated this routine to cron-job.org (free, verified) to keep the CF cron-trigger free-tier quota available for other workers. Worker code, secrets, and observability config stay intact so re-enabling is one toml uncomment + redeploy. README restructured: lead with cron-job.org setup (signup → headers → JSON body), demote CF Worker setup to a secondary path under "Using Cloudflare Workers" for users who specifically want CF infra.
This commit is contained in:
@@ -5,7 +5,44 @@ Cloudflare Worker that fires a [Claude Code routine](https://code.claude.com/doc
|
||||
> [!TIP]
|
||||
> **Anthropic's routine editor now ships a built-in cron trigger** — it runs on Anthropic's infra, no setup. Use it first.
|
||||
>
|
||||
> This worker is for users who want self-hosted-like control without operating their own infra: secrets in CF, logs in CF, schedule in code review.
|
||||
> If you need an external scheduler (Anthropic cron disabled, custom payloads, audit trail outside Anthropic), I recommend **[cron-job.org](https://cron-job.org)** — free, no infra, ~2-min setup. I tried it on this exact routine and am satisfied, so I've parked this worker (cron triggers are commented out in `wrangler.toml`) to keep my CF cron-trigger quota free for other projects. See [Recommended: cron-job.org](#recommended-cron-joborg).
|
||||
>
|
||||
> This worker is still a valid path if you specifically want secrets in CF / logs in CF / schedule in code review. See [Using Cloudflare Workers](#using-cloudflare-workers).
|
||||
|
||||
## Recommended: cron-job.org
|
||||
|
||||
[cron-job.org](https://cron-job.org) is a free hosted cron service with a clean dashboard, per-fire history, and 1-min granularity on the free tier. Setup:
|
||||
|
||||
1. Sign up at [console.cron-job.org/signup](https://console.cron-job.org/signup).
|
||||
2. Click **CREATE CRONJOB**.
|
||||
3. **Common** tab:
|
||||
- **Title**: anything (e.g. `claude-code-routine`)
|
||||
- **URL**: paste the `/fire` URL from the Anthropic routine editor → *API trigger* → *URL* (looks like `https://api.anthropic.com/v1/claude_code/routines/trig_.../fire`)
|
||||
- **Schedule**: pick your timezone and the times to fire — cron-job.org accepts both UI selectors and raw cron syntax
|
||||
4. **Advanced** tab → set **Request method** to `POST`.
|
||||
5. **Headers** tab → add four headers:
|
||||
|
||||
| Key | Value |
|
||||
| ------------------- | ---------------------------------------------- |
|
||||
| `Authorization` | `Bearer sk-ant-oat01-...` (your routine token) |
|
||||
| `anthropic-version` | `2023-06-01` |
|
||||
| `anthropic-beta` | `experimental-cc-routine-2026-04-01` |
|
||||
| `Content-Type` | `application/json` |
|
||||
|
||||
6. **Body** tab → select `Raw` and paste:
|
||||
```json
|
||||
{"text": "Scheduled trigger"}
|
||||
```
|
||||
7. **Notifications** tab (optional) → enable email on failure so you know if the token expires.
|
||||
8. **Save**.
|
||||
|
||||
Each fire shows up in *History* with status code and response body — open `claude_code_session_url` from the response JSON to watch the run.
|
||||
|
||||
**Operational notes:**
|
||||
- **Token rotation**: edit the cronjob → swap the `Authorization` header value. No redeploy.
|
||||
- **Beta header**: when Anthropic ships a new dated `anthropic-beta` value, update the header. Older dated values keep working for a transition window per Anthropic's beta policy.
|
||||
- **No retry on failure**: each `/fire` POST creates a new Claude Code session, so retrying would multiply sessions and burn quota. cron-job.org's default is one attempt per fire, which is what you want.
|
||||
- **Limits**: cron-job.org's free tier allows up to 50 cronjobs and unlimited executions at 1-min granularity — way more than enough for routine triggering.
|
||||
|
||||
## Why this vs the siblings
|
||||
|
||||
@@ -17,7 +54,11 @@ Cloudflare Worker that fires a [Claude Code routine](https://code.claude.com/doc
|
||||
| Setup | fork + 2 repo secrets | env vars + Docker | `wrangler deploy` + 2 secrets |
|
||||
| Audit trail | GitHub Actions runs page | container stdout | CF dashboard / `wrangler tail` |
|
||||
|
||||
## Quickstart
|
||||
## Using Cloudflare Workers
|
||||
|
||||
> The default `wrangler.toml` ships with the `[triggers]` block **commented out** — see the note in the file. To activate this worker, uncomment the block (and edit the schedule) before deploying.
|
||||
|
||||
### Quickstart
|
||||
|
||||
```bash
|
||||
git clone https://github.com/tiennm99/claude-code-routine-trigger-worker
|
||||
@@ -30,7 +71,7 @@ echo -n 'https://api.anthropic.com/v1/claude_code/routines/trig_.../fire' \
|
||||
echo -n 'sk-ant-oat01-...' \
|
||||
| npx wrangler secret put ROUTINE_FIRE_TOKEN
|
||||
|
||||
# Edit the cron schedule and timezone in wrangler.toml, then:
|
||||
# Uncomment [triggers].crons in wrangler.toml, edit the schedule + timezone, then:
|
||||
npx wrangler deploy
|
||||
```
|
||||
|
||||
@@ -42,7 +83,7 @@ npx wrangler tail
|
||||
|
||||
A successful fire logs a JSON line with `session_url`. Open it to watch the run.
|
||||
|
||||
## Environment variables
|
||||
### Environment variables
|
||||
|
||||
Configured in `wrangler.toml` (`[vars]` for plain values) or via `wrangler secret put` (for secrets).
|
||||
|
||||
@@ -53,9 +94,9 @@ Configured in `wrangler.toml` (`[vars]` for plain values) or via `wrangler secre
|
||||
| `TEXT_TEMPLATE` | var | no | `Scheduled trigger at {LocalTime}` | Token-substitution template. See *Templates*. |
|
||||
| `TZ` | var | no | `UTC` | IANA tz name (`Asia/Ho_Chi_Minh`, `America/New_York`, …). Used for `{LocalTime}` formatting. |
|
||||
|
||||
## Customize the schedule
|
||||
### Customize the schedule
|
||||
|
||||
Edit `wrangler.toml` `[triggers].crons` — Cloudflare requires literal cron expressions (same constraint as GitHub Actions). To change when the routine fires:
|
||||
Uncomment and edit `wrangler.toml` `[triggers].crons` — Cloudflare requires literal cron expressions (same constraint as GitHub Actions). To change when the routine fires:
|
||||
|
||||
```toml
|
||||
[triggers]
|
||||
@@ -72,7 +113,7 @@ Tips:
|
||||
- **Free tier limit:** 5 cron expressions per worker. Default config uses 1.
|
||||
- Standard 5-field syntax — supports `*`, `,`, `-`, `/`. Comma lists (`22,23,0,1,2`) and ranges (`3-7`) let you cram many fires into one expression.
|
||||
|
||||
## Templates
|
||||
### Templates
|
||||
|
||||
`TEXT_TEMPLATE` supports these `{Token}` substitutions, rendered per fire. Unknown tokens are left intact in the output.
|
||||
|
||||
@@ -90,7 +131,7 @@ TEXT_TEMPLATE = "Daily digest at {LocalTime} (cron {Cron})"
|
||||
TZ = "America/New_York"
|
||||
```
|
||||
|
||||
## Local development
|
||||
### Local development
|
||||
|
||||
Copy `.dev.vars.example` to `.dev.vars` and fill in your routine credentials:
|
||||
|
||||
@@ -109,7 +150,7 @@ curl "http://localhost:8787/__scheduled?cron=*+*+*+*+*"
|
||||
|
||||
`.dev.vars` is gitignored — never commit it.
|
||||
|
||||
## Tests
|
||||
### Tests
|
||||
|
||||
```bash
|
||||
npm test
|
||||
@@ -117,7 +158,7 @@ npm test
|
||||
|
||||
Vitest runs in the Workers runtime via `@cloudflare/vitest-pool-workers`. Tests mock `fetch`, so they consume no Anthropic quota.
|
||||
|
||||
## Secret rotation
|
||||
### Secret rotation
|
||||
|
||||
`wrangler secret put` overwrites silently. Rotate by re-running it with the new value:
|
||||
|
||||
@@ -127,18 +168,18 @@ echo -n 'sk-ant-oat01-newvalue' | npx wrangler secret put ROUTINE_FIRE_TOKEN
|
||||
|
||||
The change takes effect on the next deploy or within a few seconds via the live config.
|
||||
|
||||
## Beta header
|
||||
### Beta header
|
||||
|
||||
The request pins `anthropic-beta: experimental-cc-routine-2026-04-01` (constant in `worker.js`). When Anthropic ships a new dated beta, bump it via a release. Older dated values keep working for a transition window per Anthropic's beta policy.
|
||||
|
||||
## Operational notes
|
||||
### Operational notes
|
||||
|
||||
- **Time accuracy**: cron precision on CF Workers is within ~15 seconds — adequate for routine triggering.
|
||||
- **No retry**: each `/fire` POST creates a new Claude Code session — retrying multiplies sessions and burns quota. The worker logs failures and moves on.
|
||||
- **Logs / traces**: `[observability]` is enabled in `wrangler.toml` with `head_sampling_rate = 1` and `invocation_logs = true` — every invocation produces a structured log + trace, retained per the [Workers Logs retention policy](https://developers.cloudflare.com/workers/observability/logs/workers-logs/) (3 days on the free plan). View live with `npx wrangler tail`, or browse history in the CF dashboard under **Workers & Pages → your worker → Logs**.
|
||||
- **Cost**: scheduled handlers count against the Workers Free plan's 100k requests/day budget. 5 daily fires × 30 days = 150 requests/month — negligible.
|
||||
|
||||
## Security
|
||||
### Security
|
||||
|
||||
- The token is **per-routine**: a leak only fires that one routine.
|
||||
- Secrets live in CF's encrypted secret store, never in the bundle, never in logs (verified by tests).
|
||||
|
||||
+9
-7
@@ -11,13 +11,15 @@ TZ = "Asia/Ho_Chi_Minh"
|
||||
|
||||
# Cron triggers fire from this list. CF Workers requires literal cron
|
||||
# expressions here — they cannot be loaded from env vars or secrets.
|
||||
# Schedule (Asia/Ho_Chi_Minh, UTC+7): hourly at :00 from 05:00 to 23:00,
|
||||
# plus a single fire at 00:00 — 20 fires/day, every hour except 01-04.
|
||||
# Crons evaluate in UTC; UTC+7 hours {00, 05..23} map to UTC {17, 22-23, 0-16}.
|
||||
[triggers]
|
||||
crons = [
|
||||
"0 0-17,22-23 * * *", # UTC+7: 00:00 + 05:00..23:00 hourly
|
||||
]
|
||||
#
|
||||
# DISABLED: this worker is parked. I migrated this routine to cron-job.org
|
||||
# to keep my CF cron-trigger quota free for other workers (see README).
|
||||
# To re-enable, uncomment the block below and `npx wrangler deploy`.
|
||||
#
|
||||
# [triggers]
|
||||
# crons = [
|
||||
# "0 0-17,22-23 * * *", # UTC+7: 00:00 + 05:00..23:00 hourly
|
||||
# ]
|
||||
|
||||
# Workers Logs / traces. `head_sampling_rate = 1` keeps 100% of invocations
|
||||
# (low volume here — ~20/day — so full retention is free). Drop to e.g. 0.1
|
||||
|
||||
Reference in New Issue
Block a user