▰ IN DEVELOPMENT
2026
vigil
The internet doesn’t send webhooks. This gives it some.
Point Vigil at a webpage and it becomes an event stream: it extracts real values, decides what’s worth acting on with a proper rule engine, and fires signed webhooks, Slack messages or chained action DAGs. When the page gets redesigned, the extractor heals itself and hands you a diff instead of silence.
not public yet — the screens below are the real thing, running locally.

- CEL
- RULE ENGINE
- T0→T2
- EXTRACT LADDER
- 22
- DESIGN DOCS
- 0
- LLMS PER CHECK
the problem
Two things go wrong with watching a webpage. The first is that scrapers break on redesign, and they break quietly — the selector stops matching, extraction returns empty, and the monitor reports healthy forever because nothing threw.
The second is that “the page changed” is almost never the question. The question is whether this change is worth waking someone for. A diff-and-email tool fires on a cookie banner and a rotating testimonial, and within a week it’s muted — which is the same as not having it.
The tempting fix for both is to put a language model in the loop. Do that per check and you’ve bought nondeterminism and a bill that scales with your polling interval.
how it works
The pipeline is explicit end to end: a source becomes a monitor, a scheduled check fetches and extracts and diffs, that emits an event, rules evaluate it, a trigger fans out into an action DAG, and every invocation is recorded and replayable. Each stage is inspectable, and the whole shape renders on one canvas you can fire a simulated event through.
The design principle is AI at the edges, determinism in the core. A model runs exactly twice: when you first set up an extractor, and when one needs healing. Never in the per-check hot loop. So a check costs a fraction of a cent and behaves identically every run — and the interesting AI work moves to where nondeterminism is actually acceptable.
Extractors carry contracts — type, bounds, shape — so breakage is caught the moment a value stops satisfying them rather than whenever somebody notices. Healing then works from the failing snapshot and emits a diff of what it changed, so a redesign produces a reviewable changelog entry instead of a hole in your data.
Rules are CEL expressions plus stateful policies — cooldowns, hysteresis, escalation — and you can backtest one against recorded history before enabling it. The scheduler claims work with SKIP LOCKED so horizontal workers never double-fire, and the same capabilities are exposed as an MCP server: “watch this pricing page and tell me when it changes” becomes one tool call for an agent.
▸ ATTRACT MODE
the rest of the screens.

▸ RUNS ON
the back of the box.
- core
- Go 1.26chipgxsqlcgoosemodular monolith
- engine
- google/cel-goRiver queueRedisSKIP LOCKED claim loopcircuit breakers
- web
- Next.js 15ReactTypeScriptTailwind
- surfaces
- Chrome MV3 extensionvisual field pickerstdio MCP servermonitors-as-code CLI
- api
- OpenAPIRFC 7807 problemsIdempotency-Keycursor paginationscoped API keys
- platform
- PostgreSQL + RLSenvelope-encrypted secretsOpenTelemetryStripe
- tests
- race detectortestcontainersPlaywrightrule backtests
▸ GAME OVER · CONTINUE?
the bit that bit.
Writing the AI boundary down as a rule — edges only, never the hot loop — settled a dozen later arguments before they started. The architecture decisions that hold are the ones phrased as a constraint rather than a preference.