A walkthrough · Built with Claude Code
End-of-day rollups
that actually work.
Cross-project status digests synthesized from session journals, commits, and PRs. Posted to Slack daily and weekly. Powered by Claude Code Routines, GitHub, and Slack MCP.
$0 / month. No SaaS. No server.
The flow
click any node →Why this exists
The SaaS landscape is built for question-form bots.
This is artifact-first.
Most stand-up bots ask questions.
Geekbot, DailyBot, Range, they prompt your team. That's friction. Nobody managing a multi-repo workshop wants a bot pinging them at 5 PM with three open-ended questions.
Artifacts already exist.
Every repo has session journals, commits, PRs. The signal is on disk. The job is synthesis, not extraction. An LLM with a fixed schema can do that, no SaaS round-trip.
Routines turn that into infrastructure.
Anthropic's Claude Code Routines run remote sandboxed Claude instances on cron. Same model you already use, scheduled. No server, no Lambda, no Docker. Free with your Claude plan.
Architecture
One Routine. Six steps. Zero servers.
The flow
interactive, click to exploreThe text version
If diagrams aren't your thing, the same flow as ASCII. This is what lives in PLAN.md in the reference repo, the one document that survives across every refactor.
┌─────────────────────────────┐
21:33 UTC daily ──▶│ Claude Code Routine │
└──────────────┬──────────────┘
│ clone meta-repo
▼
┌─────────────────────────────┐
│ collect-activity.sh │ walk projects/<name>/
│ • gh api commits today │ fetch journals
│ • gh api memory/ contents │ list open PRs
│ • gh pr list / issue list │ emit JSON
└──────────────┬──────────────┘
│ activity.json
▼
┌─────────────────────────────┐
│ prompt.md (Claude call) │ schema-bound
│ shipped/in_progress/ │ fixed digest
│ blocked/notable per repo │ empty → null
└──────────────┬──────────────┘
│ digest.json
┌────────────────┼────────────────┐
▼ ▼ ▼
rollups/YYYY/MM/ Slack MCP post git commit + push
YYYY-MM-DD.md #daily-progress (archive back)
via Block KitBuild it · 10 steps
From empty directory to scheduled Slack post.
What arrives at 5:33 PM ET
A real digest, end-to-end.
Claude APP
5:33 PM
📊 EOD Rollup — YYYY-MM-DD
acme-portal ships public pricing page; acme-checkout locks ADRs on payment provider + refund flow
acme-portal
Shipped
- Public pricing page with 4 tiers (commit abc123)
- Wiki architecture doc updated to reflect new pricing/ directory
acme-checkout
Notable
- ADR-0004 (payment provider) and ADR-0005 (refund flow) added, architectural direction locked
- PR #1 still open: mobile responsive cleanup
acme-marketing
Notable
- Scheduled deploy fired twice (cron output, low human signal)
The 8 design insights
What separates a script from a system.
Routines run remotely with single-repo clones
The runtime hydrates one fresh git checkout into a remote sandbox per fire. No local FS, no VPS, no Docker. Once you internalize this, the whole architecture falls into place: everything must live in the meta-repo.
Per-app metadata, not hardcoded lists
projects/<name>/github.json is the source of truth. Adding a new tracked repo is mkdir + a 2-line JSON file. No code changes. The collector discovers tracked apps by walking ./projects/.
Schema-bound LLM output
Pydantic-style fixed schema: shipped/in_progress/blocked/notable per repo, empty arrays omitted. Same schema for daily AND weekly. Same Block Kit converter for both. Schema is leverage.
Slack MCP > webhooks
The Slack MCP server is already attached to your claude.ai account, the Routine inherits it. No webhook URL to manage, no secret in repo, no rotation. The connection is just there.
Empty-day gate
Zero activity → zero output. The prompt returns a literal null token; the runner short-circuits. No "nothing happened today" posts. The channel earns trust by never being noisy.
Two staggered Routines
Daily fires at 21:33 UTC. Weekly fires Friday 22:33 UTC, one hour later, so the Friday daily archive is on disk before the weekly reads it. The weekly is synthesis-of-syntheses, not raw data again.
GitHub Projects v2 is GraphQL-only
REST won't help you. The bootstrap script uses gh api graphql to create one Project per app, adds a Source TEXT field for idempotency, and caches every node ID + field ID + status option ID into github-project.json.
Tools fail open
Slack MCP unreachable? Print the Block Kit JSON to the log. Push fails? Log and continue. The Routine run history captures everything. No silent data loss when external services blink.
Try it · Deploy it
The reference implementation is live.
Reference repo
ProvenLabsAI/claude-rollup-starter
The complete working example, meta-repo layout, both Routine prompts, the Block Kit converter, the Projects v2 bootstrap, and every per-app github.json.
Setup checklist
- 01Use the claude-rollup-starter template to spin up your meta-repo
- 02Replace projects/* with your tracked apps (one github.json each)
- 03Confirm Slack MCP is connected to your claude.ai account
- 04Create the daily Routine via /schedule (cron: 33 21 * * *)
- 05Add the weekly Routine (cron: 33 22 * * 5)