Docs
Read it from your own code
Everything on this site comes from a public API: no keys, no accounts. Agents get the same data over MCP, and every night can be verified against Base without trusting us.
REST API
Base URL https://lights-on-watch.vercel.app. JSON over HTTPS, no keys, open CORS, cached for 5 minutes. Unknown query parameters are answered with a redirect to the canonical URL.
Every listed project with its latest status and 30-night record. history adds the last 90 nights as one 90-letter string, oldest first, last = today (UTC): S shipped, B building, Q quiet, D down, U unavailable, . no night. Community-added watches are unlisted.
{ generatedAt, projects: [{ slug, name, tagline, source, bay, status, statusSource?,
confirmedAt, summary, record: { streak, lit30, lastShip }, history? }] }One project: sources, status, record, its latest night with reasons and attestation, and the Vibestarter tranche schedule with any open challenge window.
A project's nights, observed and reconstructed, each with its reasons, evidence hash and attestation. An observed night also carries its Merkle proof into that night's root attestation (attestProof, attestLeaf, attestRoot, attestLit30) and the hash of the night manifest. Default: the last 90 nights; at most 366.
The evidence bundle of one night, as canonical JSON: keccak256 of the response body equals the hash. Cached forever (content-addressed); 404 when unknown.
The night manifest behind a nightly root attestation (its manifestURI), as canonical JSON: every project-night of the root with its project key, status, lit30, evidence hash and leaf, and its slug unless the project is unlisted. keccak256 of the body equals the hash; cached forever.
{ v: 1, schema: "lights-on/night-manifest", night, count, root, agentId,
leaves: [{ slug, projectKey, night, kind: 0, status, statusCode, lit30, evidenceHash, leaf }] }The projects a wallet backed on Vibestarter or holds as a watched token, and its morning briefing. Accepts a 0x address or an ENS name.
{ address, projects: [{ slug, name, via, amountWei?, balance?, symbol? }],
briefing: { text, aiOk }, degraded }Ask the watcher to add a project: { liveUrl, repo?, contract? }. Rate limited (3 a day per caller, 50 a day overall). The project stays unlisted and is reachable by slug once its first check succeeds.
{ slug?, status: "queued" | "exists" }The OpenAPI 3.1 description of every endpoint above, and a plain-text guide for language models (rules, endpoints, how to verify).
MCP for agents
A Streamable HTTP MCP server at https://lights-on-watch.vercel.app/api/mcp (live) exposes the same reads as tools, and the agent's ERC-8004 registration is at https://lights-on-watch.vercel.app/.well-known/agent-registration.json:
list_projects: every listed project with its latest status; history: true adds the 90-letter historyget_project: one project by slug, with its tranche scheduleget_night: one project's night: status, reasons, evidence hash, attestationis_still_shipping: { slug, status, streak, lit30, lastShip, lastNight, attestationUid, proof, manifestUri, schemaUid }get_briefing: the briefing for a wallet address or .eth namewatch_project: ask the agent to watch a project (rate limited)
Claude Code:
claude mcp add --transport http lights-on https://lights-on-watch.vercel.app/api/mcp
Cursor, in .cursor/mcp.json:
{
"mcpServers": {
"lights-on": { "url": "https://lights-on-watch.vercel.app/api/mcp" }
}
}Verify a night
Three checks, none of which trust this site:
- The bundle is what was hashed. keccak256 of the response body equals the hash in the URL:
curl -s https://lights-on-watch.vercel.app/api/v1/evidence/<hash> -o evidence.json cast keccak "$(cat evidence.json)" # prints <hash>
- The hash is what was attested. Each night is one attestation on EAS on Base (
0x4200…0021): a Merkle root of every project's verdict. Rebuild this night's leaf from the bundle and the row's status and lit30, fold in the row'sattestProof, and you must land on the attested root. The attester must be the watcher, and it must not be revoked. Live runs are attested one by one: there theevidenceHashfield itself must equal the hash. - All of it at once with the repo's script, or in the browser from any night on a project page:
pnpm tsx scripts/verify-night.ts --network base \ --uid <attestation uid> --bundle evidence.json --site https://lights-on-watch.vercel.app --attester <watcher address>
The rules that turn evidence into a status are on the methodology page.