Skip to content

zllovesuki/anvil

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

19 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ”¨ anvil

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.

Deploy to Cloudflare

πŸ’‘ 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. πŸ€–βœ¨


🎯 What is anvil?

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.


πŸ“‹ Your pipeline in 10 lines

# .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 build

Drop this in your repo root, point anvil at it, and you're running CI. ⚑


✨ Features

πŸ”§ 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

▢️ Manual triggers β€” kick off a run from the dashboard with optional branch override

πŸ“Š 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


πŸ—οΈ How it works

  • 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

🧰 Tech stack

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

⚑ Quick start

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                          # πŸš€ go

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


πŸ“ Project structure

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

πŸ“œ Common scripts

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.


🚒 Deploying

npx wrangler login
npm run deploy

npm 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. πŸ“˜


πŸ›‘οΈ Security

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


🀝 Contributing

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.


πŸ“„ License

MIT β€” Rachel Chen, 2026