calnode README

The project's README from github.com/Calnode/calnode. As one markdown file: README.md.

Calnode

A lean, self-hostable scheduling engine that lives in your AI stack.

Calnode is a Calendly-style booking app — with first-party video meetings, recording, and AI notetaking built in — shipped as a single Go binary with an embedded SQLite database: no Redis, no Postgres, no separate API server, no multi-gigabyte image. It's API-first, webhook-native, and built for a world where agents do the booking. Self-host the whole thing on a $5 box; nothing is paywalled.

Calnode runs for pennies on a small VPS — it's a single static binary serving a SQLite file, so there's almost nothing to pay for.

Apache-2.0 · Go 1.26 · single static binary · SQLite + Litestream

OpenSSF Scorecard · Audit it yourself


Quick start

Kick the tires — one command, no config:

docker run -p 3000:3000 -v ./data:/data ghcr.io/calnode/calnode:latest
# → open http://localhost:3000

The whole app — booking pages, admin UI, SQLite — in one container, with data in ./data. With no encryption key set it runs on an ephemeral one (fine for a look; stored credentials won't survive a restart). Deploying for real — HTTPS, a persistent encryption key, backups — see Deploy for real below, or the full DEPLOY.md.


Why Calnode


Calnode vs cal.com

The default open-source scheduler is a SaaS monolith. Calnode is the opposite.

cal.com Calnode
Codebase 500k+ LOC TS across ~100 packages Lean Go + one SvelteKit app
Runtime deps 4 GB+ image; needs Redis + Postgres + API server One static binary + a SQLite file
Database Postgres (+ Redis) SQLite (WAL) + Litestream point-in-time backup
Webhooks UI-only API-first, HMAC-signed, per-webhook payloads
AI / agents None REST API + webhooks + a native MCP server (stdio + HTTP)
Video & recording Third-party links (Zoom / Meet) Built-in in-browser rooms + recording + AI notes (self-hosted LiveKit)
Deploy Orchestrate several services docker run one container
Isolation Shared multi-tenant DB (org_id everywhere) Instance-per-tenant — isolation is the default
Licence AGPL-3.0 Apache-2.0, nothing paywalled for self-host

(cal.com figures reflect its public footprint; see the the design docs for the full rationale.)

If you're weighing self-hosted schedulers and you want small, fast, scriptable, and AI-ready over feature-maximal, Calnode is built for you.


AI-native

Everything a human can do, an agent can do — over the API today:

# Find slots and book, with an API key
curl -s "$BASE/v1/event-types/intro-call/slots?from=2026-06-16&to=2026-06-20&tz=Pacific/Auckland" \
  -H "Authorization: Bearer $API_KEY"

curl -s -X POST "$BASE/v1/bookings" -H "Authorization: Bearer $API_KEY" \
  -H 'Idempotency-Key: 9f3c…' -H 'Content-Type: application/json' \
  -d '{"event_type_slug":"intro-call","start_at":"2026-06-17T21:00:00Z","name":"Alex","email":"[email protected]","timezone":"Pacific/Auckland"}'

Wire booking lifecycle events (booking.created / .rescheduled / .cancelled) to n8n / Make / your own service with HMAC-signed webhooks — all configured through the API, not buried in a UI.

Native MCP server. A Model Context Protocol server is compiled into the binary (official Go SDK), exposing eight first-class tools — list_event_types, get_event_type, get_available_slots, create_booking, get_booking, reschedule_booking, cancel_booking, list_bookings. The MCP tools call the same internal services as the REST API (no parallel code path), so booking side effects — calendar events, confirmation emails, webhooks, reminders — fire identically.

Two transports:

User:  "Book a 30-min call with Wynne next week — I'm in Auckland."
Agent: get_available_slots("intro-call", "2026-06-16", "2026-06-20", "Pacific/Auckland")
       → presents options → create_booking(…) → returns confirmation + meeting link

Conversational booking — in the booking page itself. Beyond agents, the booking page (and the embed widget) ships an optional "Book by chat" assistant: a visitor types "free Tuesday afternoon or next week" and it resolves real availability and books — the deterministic engine still computes the slots (the model never invents times), and the assistant only ever sees free/busy windows, never your calendar contents. Bring your own model — any OpenAI-compatible endpoint (a hosted model or one you run yourself); off by default, with the standard calendar always there as the fallback.

Connecting Claude (remote / HTTP). In Claude (claude.ai or Desktop) → Settings → Connectors → Add custom connector → enter https://<your-instance>/mcp → Connect → sign in → Allow. Custom connectors need a paid Claude plan; the server must be on HTTPS. Local stdio alternative (any plan): point an MCP client at the calnode mcp subcommand via its config file — no OAuth, runs against the local DB.

Permissions. MCP tools are role-scoped, mirroring the rest of the app: an owner/admin acts across the whole workspace, a member sees and manages only bookings they host. (The stdio subcommand is the local operator → full access.) Booking creation and availability are the public booking surface, open to all. Roles are fixed (owner / admin / member); configurable RBAC is intentionally out of the lean core.


Deploy for real

docker run -d -p 3000:3000 \
  -e BASE_URL=https://booking.example.com \
  -e CALNODE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
  -e CALNODE_RECOVERY_SECRET="$(openssl rand -hex 32)" \
  -e DATABASE_URL=sqlite:///data/calnode.db \
  -v calnode-data:/data \
  ghcr.io/calnode/calnode:latest

Pinning a version. :latest follows the newest tagged release; :edge tracks main. For reproducible deploys, pin a release — :0.1 (tracks patches within the minor) or an exact :0.1.0. See releases.

Open / → it redirects to /admin/ and walks you through first-run setup (create the owner account, connect a calendar, add an event type). Put a TLS-terminating proxy in front that forwards the original Host header.

Full guide → DEPLOY.md (env vars, Railway step-by-step, custom domains, Resend email, Google & Microsoft OAuth, Litestream backups, troubleshooting).


Features

Shipped

On the roadmap


Stack


Design principles

A few load-bearing decisions (full detail in the the design docs):


Audit it yourself in 10 minutes

Calnode's backend is small enough to fit entirely in one LLM's context window — most scheduling software (cal.com included) can't say that. AUDIT.md turns that into a self-serve check: a copy-paste scanner block (govulncheck, gosec, gitleaks across full history, SBOM, semgrep — all neutral, standard tooling you run yourself), an adversarial LLM prompt-pack for your own coding agent, and a claims → verification manifest mapping every security claim we make to exactly how to check it in the source. Not a certification — a due-diligence accelerator.


Commercial support

Self-hosting is free forever — docker run it and you own the whole thing. If you'd rather not run it yourself, Orchestratr — the team behind Calnode — will deploy and operate it for you:

Built for regulated and mid-to-large orgs that need Calnode on their own infrastructure, fully integrated. → calnode.com/services


License

Apache-2.0. The full scheduler is self-hostable, and nothing previously free is ever paywalled.

The code is Apache-2.0; the "Calnode" name and logo are not — see TRADEMARK.md (use the code freely; name your fork something else). Contributions are accepted under a CLA so the project can stand behind every line and keep its future licensing options open — see CONTRIBUTING.md.

calnode (Calnode/calnode)

scheduling
Searching Database…

What is this?Calnode is a self-hostable scheduling app like Calendly or Cal.com, shipped as a single Go binary with an embedded SQLite database. It includes first-party video meetings, recording, AI notetaking, and is built API-first with a native MCP server for AI agents.
Is this a full app or just a library I'd embed?It's a complete self-contained app: a single static Go binary that serves the admin UI, public booking pages, and REST/MCP APIs, with no external database or services required.
How do I get it running?Run it with one docker command for a quick look (data stored in ./data), or follow DEPLOY.md for a production setup with HTTPS, a persistent encryption key, and backups.
Do I need Postgres or Redis to run this?No — Calnode deliberately avoids those. The only optional external dependency is a LiveKit server if you enable built-in video meetings.
Any catches with the default setup or missing features?Without setting an encryption key it runs on an ephemeral one, so stored credentials won't survive a restart. Also, RBAC is fixed to owner/admin/member roles (no custom permissions), and non-English translations are machine-drafted without native review.
Who is this for instead of cal.com?It's aimed at people who want a small, fast, scriptable, AI-ready self-hosted scheduler instead of a feature-maximal SaaS-style monolith like cal.com.
Can I run this cheaply on a tiny VPS?Yes — it's designed to run on a $5 VPS since it's just a static binary serving a SQLite file.
Does the AI assistant ever see my real calendar data?No — the conversational 'Book by chat' assistant only ever sees free/busy windows, never calendar contents, and the deterministic engine (not the model) computes actual available slots.
Not Stated In READMECalnode is licensed under Apache-2.0, with nothing paywalled for self-hosting, unlike cal.com's AGPL-3.0.
What can the MCP server actually let an agent do?The built-in MCP server exposes tools like listeventtypes, getavailableslots, createbooking, getbooking, reschedulebooking, cancelbooking, and listbookings, plus meeting notes/transcript tools, over stdio or Streamable HTTP, using the same internal services as the REST API.
How does Calnode handle time zones and daylight saving time?It stores time as a UTC instant plus an IANA timezone name rather than a fixed offset, so availability always resolves correctly across DST shifts instead of corrupting a slot.
Does it support taking payments for bookings?Yes — via Stripe Checkout using a pay-then-book flow: the slot is held, confirmed on the payment webhook, and auto-refunded if the booking is cancelled.
How do I connect Claude or ChatGPT to my Calnode instance?For Claude, add it as a custom connector via Settings → Connectors using your HTTPS URL and OAuth sign-in (requires a paid Claude plan); for local agents without OAuth, run the calnode mcp subcommand over stdio against the local database.
Creator
Calnode
Size
2.8 MB
Stars
118
Age
3mo
Commits · 90 Days