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.

You don't need a stand-up tool. You need a synthesis layer that reads what's already on disk, writes it to one place, and never asks anyone a question.

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.

Click any node below to see what happens at that step. The whole pipeline is six shell scripts and a prompt, held together by a schema and a cron expression.

The flow

interactive, click to explore

The 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.

PLAN.md
                    ┌─────────────────────────────┐
   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 Kit

Build it · 10 steps

From empty directory to scheduled Slack post.

Every step has a "why this works" callout. These are the moves that turn a hand-rolled script into infrastructure. Follow in order; each step assumes the previous one is in place.
  1. Make a sibling directory to your apps and treat it as the source-of-truth ops repo. Push it to GitHub (private is fine).

    Why this works

    Routines clone exactly one repo per run. The meta-repo is what they clone, it owns the scripts, the schemas, and the per-app config.

    scaffold.sh
    mkdir -p .provenlabs/{tools,projects,templates,rollups}
    cd .provenlabs
    git init
    git remote add origin git@github.com:<your-org>/<your-ops-repo>.git

What arrives at 5:33 PM ET

A real digest, end-to-end.

Switch tabs to walk back through the pipeline from output to input. The Slack post is rendered from the digest JSON; the digest JSON was synthesized from the activity JSON.
C

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.

These are the moves that compound. Each one looks small in isolation; together they're the difference between a one-off shell script and a piece of infrastructure you trust at 5pm every weekday.
INSIGHT · 01

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.

INSIGHT · 02

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/.

INSIGHT · 03

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.

INSIGHT · 04

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.

INSIGHT · 05

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.

INSIGHT · 06

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.

INSIGHT · 07

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.

INSIGHT · 08

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.

The methodology on this page is open source. The repo below is a public template: same scripts, same prompts, same schemas. Use it to spin up your own meta-repo, swap in your repos, schedule the Routine.

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

  1. 01Use the claude-rollup-starter template to spin up your meta-repo
  2. 02Replace projects/* with your tracked apps (one github.json each)
  3. 03Confirm Slack MCP is connected to your claude.ai account
  4. 04Create the daily Routine via /schedule (cron: 33 21 * * *)
  5. 05Add the weekly Routine (cron: 33 22 * * 5)