Your CI, on the edge. Define your pipeline in .anvil.yml, push to trigger, and watch runs execute in isolated containers β all on Cloudflare Workers. No servers to manage, no runners to babysit.
π‘ Container execution requires a Workers Paid plan ($5/mo). D1, Queues, Workflows, KV, and Durable Objects work on Free or Paid with platform-specific limits.
Built with GPT-5.4 and Claude Opus 4.6 agentic workflows. π€β¨
anvil is a Cloudflare-native CI runner built for personal projects and small teams. If you've ever wanted a simple, self-hosted CI that doesn't require maintaining VMs, Docker daemons, or long-running processes β anvil runs entirely on Cloudflare's managed platform.
Push code β anvil picks it up β runs your steps in an isolated container β streams logs back to your browser in real time. That's it.
# .anvil.yml
version: 1
checkout:
depth: 1
run:
workingDirectory: .
timeoutSeconds: 720
steps:
- name: install
run: npm ci
- name: test
run: npm test
- name: build
run: npm run buildDrop this in your repo root, point anvil at it, and you're running CI. β‘
π§ Repository-defined pipelines β version your CI config in .anvil.yml, right next to your code
π¦ Isolated sandbox execution β every run gets a fresh container. No leftover state, no cross-run contamination
π‘ Live log streaming β watch stdout/stderr flow in real time via WebSocket, with ANSI color support
π Webhook triggers β push to GitHub, GitLab, or Gitea and anvil picks it up automatically. Per-provider secrets with rotation and delivery history
π FIFO run queue β one active run per project, the rest queue up in order. No race conditions, no surprises
π§ Selectable dispatch mode β keep the existing Queue-backed path or use Cloudflare Workflows for durable orchestration
π Invite-only access β no open registration. Add teammates via time-bounded invite links
π Any HTTPS Git repo β GitHub, GitLab, Gitea, or any repo reachable over HTTPS with optional token auth
π‘οΈ Security baked in β encrypted credentials at rest, automatic secret redaction in logs, strict CSP, PBKDF2 password hashing
- Workers β stateless HTTP frontdoor: routing, auth, dispatch trigger
- ProjectDO β per-project state machine: active run lock, pending queue, dispatch mode, webhook config
- RunDO β per-run state: steps, rolling logs, WebSocket fanout to browsers
- D1 β durable relational index: users, projects, run history, invites
- KV β ephemeral session storage with TTL
- Dispatch β Queue-backed or Workflow-backed run orchestration, both preserving FIFO at the project level
- Sandbox β isolated container per run via
@cloudflare/sandbox
| What | Why | |
|---|---|---|
| π₯οΈ | React 19, React Router 7, Tailwind CSS 4, Vite 7 | Modern frontend with fast HMR |
| βοΈ | Hono on Cloudflare Workers | Lightweight, edge-native HTTP framework |
| πΎ | D1 (SQLite), Durable Objects (SQLite), KV | Right storage for each access pattern |
| ποΈ | Drizzle ORM | Type-safe database access across D1 and DO SQLite |
| π¦ | Cloudflare Containers, Queues, Workflows | Isolated execution with ordered dispatch |
| β | @cloudflare/util-en-garde |
Runtime codec validation at every boundary |
| π€ | TypeScript (strict) throughout | One language, zero escape hatches |
git clone <repo-url>
cd anvil
npm install
cp .dev.vars.example .dev.vars # local encryption keys
npm run db:migrate:d1:local # set up local D1
npm run db:seed-initial-user -- --local # create bootstrap invite
npm run dev # π goOpen the URL from the terminal, accept the invite, and you're in. π
π§ͺ Frontend-only? On localhost, the frontend starts in mock mode β a localStorage-backed API that simulates the full backend. No Workers, no D1, no migrations needed. Great for UI work and especially useful for agentic workflows where an AI agent browses the local dev server to verify frontend changes.
src/
client/ π₯οΈ React frontend (pages, components, hooks)
worker/ βοΈ Cloudflare Workers backend
api/ Route handlers (public + private)
auth/ Sessions and password handling
db/ D1 and Durable Object schemas (Drizzle)
dispatch/ Queue + Workflow dispatch and shared execution
durable/ ProjectDO and RunDO
sandbox/ Container lifecycle
contracts/ π Shared client/server API types
lib/ π§ Shared utilities
tests/
worker/ β‘ Fast Vitest unit tests
e2e/ π Playwright browser tests
integration/ π Queue and Workflow runner integration tests
drizzle/ π¦ Generated migrations (do not edit)
docker/ π³ Runner container image
reference/ π Specs and design docs
| Command | What it does |
|---|---|
npm run dev |
Start local dev server |
npm run build |
Production build |
npm test |
Fast Vitest suite |
npm run test:e2e |
Playwright browser tests |
npm run test:integration:queue |
Queue-backed live integration test |
npm run test:integration:workflows |
Workflow-backed live integration test |
npm run typecheck |
Full TypeScript type check |
npm run db:generate |
Regenerate Drizzle migrations from schema |
npm run deploy |
Remote D1 migrate, production build, deploy |
npm run format |
Prettier formatting |
See OPERATOR.md for the full script reference, deployment guide, database operations, testing strategy, and Cloudflare binding details.
npx wrangler login
npm run deploynpm run deploy applies remote D1 migrations first, then builds and deploys the Worker. For the full deployment guide, environment setup, and binding reference, see OPERATOR.md. π
anvil takes security seriously even at v1:
- π AES-GCM encryption at rest for repo tokens and webhook secrets
- π Automatic secret redaction in all run logs
- π Strict CSP β no inline scripts, no
eval - π PBKDF2 password hashing (SHA-256, 100k iterations, per-user salt)
- π₯ Invite-only registration β no open signup surface
- πͺ KV sessions with TTL β Bearer auth, not cookies
For rate limiting and WAF configuration, see waf.md. π§±
anvil is under active development. The codebase uses strict TypeScript throughout, with codec-validated boundaries and a clear separation between Workers (stateless) and Durable Objects (stateful, transactional).
If you're diving in, start with the spec and the operator guide.
MIT β Rachel Chen, 2026