2026-05-08 23:41:47 +07:00
2026-05-08 23:41:47 +07:00
2026-05-08 23:41:47 +07:00
2026-05-08 23:41:47 +07:00

claude-code-routine-cron

Self-hosted Go daemon that fires a Claude Code routine on a precise cron schedule via the /fire API. Packaged as a multi-arch Docker image on GHCR.

Tip

Anthropic's routine editor now ships a built-in cron trigger — that runs on Anthropic's infra, no setup. Use it first.

This repo is for users who explicitly want self-hosted scheduling: precise timing (no GitHub Actions delays), behind-firewall, on-prem audit trail, or to integrate with their own infra.

Why this vs claude-code-routine-trigger

claude-code-routine-trigger claude-code-routine-cron (this repo)
Runs on GitHub Actions runners your infra (Docker host, k8s, NAS, RPi)
Cost free (within GitHub minutes) minimal (your infra)
Cron precision ±30 min 2 h, can drop runs sub-second
Setup fork + 2 repo secrets 2 env vars + cron + Docker
Secret storage GitHub repo secrets host env / Docker secrets / k8s Secret
Audit trail GitHub Actions runs page container stdout

Quickstart

docker run -d --name claude-routine \
  --restart unless-stopped \
  -e ROUTINE_FIRE_URL='https://api.anthropic.com/v1/claude_code/routines/trig_.../fire' \
  -e ROUTINE_FIRE_TOKEN='sk-ant-oat01-...' \
  -e CRON_SCHEDULE='0 9 * * *;0 18 * * *' \
  -e TZ='Asia/Ho_Chi_Minh' \
  ghcr.io/tiennm99/claude-code-routine-cron:latest

Tail logs:

docker logs -f claude-routine

A successful fire logs a JSON line with claude_code_session_url. Open it to watch the run.

Environment variables

Name Required Default Notes
ROUTINE_FIRE_URL yes Anthropic /fire endpoint. From routine editor → API trigger.
ROUTINE_FIRE_TOKEN yes sk-ant-oat01-... per-routine token. Shown once in the editor.
CRON_SCHEDULE yes One or more standard 5-field cron expressions. Split on ; or newlines.
TZ no UTC IANA tz name (Asia/Ho_Chi_Minh, America/New_York, …). Cron evaluates in this zone.
TEXT_TEMPLATE no Scheduled trigger at {{.LocalTime}} Go text/template; see Templates.
LOG_LEVEL no info debug, info, warn, error.

Validation is fail-fast: missing required vars or malformed crons/timezones/templates cause the daemon to exit with a clear error before any HTTP traffic.

Multiple schedules

Use ; (or newlines, in YAML block scalars) to register multiple crons:

environment:
  CRON_SCHEDULE: |
    0 9 * * *
    0 13 * * *
    0 18 * * *

Each schedule fires independently; all use the same TEXT_TEMPLATE, URL, and token.

Templates

The TEXT_TEMPLATE env var is rendered as a Go text/template per fire with these variables:

Var Type Example
.Now time.Time UTC time of the fire
.LocalTime string 2026-05-08 23:30 +07
.Cron string 0 9 * * * — the expression that fired

Example:

-e TEXT_TEMPLATE='Daily digest at {{.LocalTime}} (cron {{.Cron}})'

docker-compose

See docker-compose.example.yml and .env.example:

cp docker-compose.example.yml docker-compose.yml
cp .env.example .env       # then edit secrets
docker compose up -d

Security

  • The token is per-routine: a leak only fires that one routine.
  • Token never appears in logs (verified by tests).
  • No retry on failure — each /fire POST creates a new session, retries would multiply sessions and burn quota.
  • Image is gcr.io/distroless/static-debian12:nonroot — no shell, no package manager, runs as UID 65532.
  • TLS to api.anthropic.com uses standard Go cert verification.

Beta header

The request pins anthropic-beta: experimental-cc-routine-2026-04-01. When Anthropic ships a new dated beta, bump it via a new release. Older dated values keep working for a transition window per Anthropic's beta policy.

Operational notes

  • Time accuracy: cron correctness depends on the host clock. Run NTP / sync on the Docker host.
  • Restart policy: use --restart unless-stopped (or k8s Deployment) — the daemon does not self-restart on panic.
  • Pin tags in production: prefer :vX.Y.Z over :latest.
  • No idempotency: avoid retry loops in upstream automation that POSTs the same alert twice.

Build from source

git clone https://github.com/tiennm99/claude-code-routine-cron
cd claude-code-routine-cron
go build .
./claude-code-routine-cron     # uses env vars from your shell

Tests:

go test -race -cover ./...

License

Apache-2.0

S
Description
Self-hosted Go daemon to trigger Claude Code routines on a precise cron schedule. Docker image on GHCR.
Readme Apache-2.0 65 KiB
Languages
Go 98.2%
Dockerfile 1.8%