Public beta - pre-stable release line. Single-operator bearer auth is available, but there is no RBAC or multi-tenancy. Bind to localhost, a trusted subnet, VPN, Tailscale, or a reverse-proxied private network. See SECURITY.md.
Wakeplane is a durable scheduling control plane for long-running systems.
It decides when work is due, records the occurrence durably, dispatches execution through typed targets, and keeps an append-only ledger of what happened.
This is not a thin wrapper around cron. Cron is only one schedule input. The control plane above it is the product:
- durable schedules
- typed job targets
- retries and backoff
- missed-run handling
- overlap and concurrency policy
- append-only run ledger
- operator visibility
- pluggable executors
- reusable API and CLI surface
Wakeplane is designed as a reusable primitive across JCN systems. Nothing here is treated as disposable.
Current shipped state:
- pre-stable public beta release line
- core boundary preserved across distinct planner, dispatcher, store, executor, API, and CLI packages
- single-process Go daemon and CLI
- SQLite-first storage with embedded migrations and a Postgres production backend seam
- planner and dispatcher loops
- HTTP, shell, and in-process workflow executors
- HTTP JSON API and Cobra CLI
- embedded single-operator console at
/console/ - metrics, health, readiness, and status endpoints
- structured shutdown and drain logging
- restart, stale-lease, contention, and non-cooperative shutdown coverage
Current limits:
- native Postgres column types are still conservative/text-compatible in this first production backend slice
- no RBAC, distributed coordination, visual schedule editor, or plugin loading
- workflow handlers must be registered explicitly by the embedding application or tests
replaceis cooperative and best-effort, not forceful- shell targets inherit the daemon environment; per-target env or secret injection is not implemented
- the current embedding surface is source-level and internal-package based, not a stable public library API
Core invariants currently enforced in code:
- execution only starts after a durable run record exists and the dispatcher has claimed it
timezoneis required and validated as an IANA timezone- targets are typed as
http,shell, orworkflow - retries append new attempts under the same
occurrence_key - policy enforcement happens at claim time, not inside executors
Wakeplane has a real local-operator deployment that remains an important proving ground for the product.
That provenance is operational context, not product lock-in. Wakeplane is still intended to stand on its own:
- as the local scheduler on a personal machine
- as the control plane for small internal systems
- as a standalone tool other operators can run without inheriting any private operator environment
Single-machine operation is a first-class use case, not a temporary bootstrap mode. Changes here should not regress the local system Wakeplane was built to support.
Scheduling:
- cron schedules
- interval schedules
- once schedules
- timezone-aware next-run calculation
- pause and resume
- manual trigger-now without changing normal cadence
Execution:
- HTTP executor
- shell executor
- in-process workflow executor backed by a registry
- durable claim before execution
- execution receipts for stdout, stderr, HTTP response summary, and workflow result
- configurable receipt body size bounds and terminal run retention
- retry with exponential backoff
Policy:
- overlap policies:
allow,forbid,queue_latest,replace - misfire policies:
skip,run_once_if_late,catch_up - timeout enforcement
- max concurrency per schedule
Durability and audit:
- SQLite-backed schedules and runs by default; Postgres is selectable for production installs
- append-only attempt history per logical occurrence
- worker leases with stale-claim recovery
- dead-letter capture for exhausted failures
- Prometheus text metrics at
/v1/metrics - operational status counts for due, running, failed, retry-queued, dead-lettered, and expired-claim work
- Build the binary, or plan to run the daemon directly from source.
- Start the daemon.
- Create schedules from a YAML manifest.
- Inspect schedules and runs with the console, CLI, or HTTP API.
- Register workflow handlers explicitly if you use workflow targets.
Build both entry points:
go build -o dist/wakeplane ./cmd/wakeplane
go build -o dist/wakeplaned ./cmd/wakeplanedIf you are running directly from source, use go run ./cmd/wakeplane serve in place of the binary invocation below. If you built into dist/ and did not install into PATH, prefix commands with ./dist/.
For local console development from source:
make console
# or, if you use just:
just consoleThen open http://127.0.0.1:8080/console/. Override the address or dev database with make console ADDR=127.0.0.1:18080 DB=./tmp/wakeplane.db or just console 127.0.0.1:18080 ./tmp/wakeplane.db.
Preferred operator path: download tagged archives and checksums from GitHub Releases.
One-command install for macOS or Linux:
curl -fsSL https://wakeplane.dev/install.sh | shAdditional install paths:
go install github.com/justyn-clark/wakeplane/cmd/wakeplane@latestgo install github.com/justyn-clark/wakeplane/cmd/wakeplaned@latest- source build with the repo's declared Go version (
go 1.25.0)
See docs/public/install.md for the full install and smoke-test flow.
Example daemon start:
WAKEPLANE_DB_PATH=./wakeplane.db \
WAKEPLANE_HTTP_ADDR=:8080 \
WAKEPLANE_WORKER_ID=wrk_local \
wakeplane serveCreate a schedule from one of the shipped examples:
wakeplane schedule create -f ./examples/nightly-sync.yamlCommon operator commands:
wakeplane schedule list
wakeplane schedule get <id>
wakeplane schedule pause <id>
wakeplane schedule resume <id>
wakeplane schedule delete <id>
wakeplane schedule trigger <id>
wakeplane run list
wakeplane run get <id>
Both wakeplane and wakeplaned currently expose the same command surface.
HTTP surface:
GET /healthz
GET /readyz
GET /v1/status
POST /v1/schedules
GET /v1/schedules
GET /v1/schedules/{id}
PUT /v1/schedules/{id}
PATCH /v1/schedules/{id}
DELETE /v1/schedules/{id}
POST /v1/schedules/{id}/pause
POST /v1/schedules/{id}/resume
POST /v1/schedules/{id}/trigger
GET /v1/schedules/{id}/runs
GET /v1/runs
GET /v1/runs/{id}
GET /v1/runs/{id}/receipts
GET /v1/metrics
The daemon also serves the local operator console at http://localhost:8080/console/. The console uses the same /v1/... API as the CLI. If WAKEPLANE_AUTH_TOKEN is set, open the console and enter the bearer token with the Token button before inspecting runs or schedules.
Wakeplane does not ship hidden workflow handlers. Embedding applications must register each workflow explicitly.
See examples/embedded/main.go for a minimal daemon that:
- constructs
app.NewWithOptions(...) - registers a workflow with
app.WithWorkflowHandler(...) - exposes the HTTP control-plane API with
api.NewMux(...) - coordinates service and HTTP shutdown on process cancellation
Minimal registration shape:
service, err := app.NewWithOptions(ctx, cfg,
app.WithWorkflowHandler("sync.customers", func(ctx context.Context, input map[string]any) (map[string]any, error) {
return map[string]any{"status": "completed"}, nil
}),
)The daemon reads configuration from environment variables:
WAKEPLANE_HTTP_ADDRdefault:8080WAKEPLANE_STOREdefaultsqlite; set topostgresfor the production Postgres backendWAKEPLANE_DB_PATHdefault./wakeplane.dbWAKEPLANE_DATABASE_URLrequired whenWAKEPLANE_STORE=postgresWAKEPLANE_SCHEDULER_INTERVAL_SECONDSdefault5WAKEPLANE_DISPATCHER_INTERVAL_SECONDSdefault2WAKEPLANE_LEASE_TTL_SECONDSdefault30WAKEPLANE_WORKER_IDdefaultwrk_localWAKEPLANE_RECEIPT_MAX_BYTESdefault262144WAKEPLANE_RUN_RETENTION_DAYSdefault0(disabled)WAKEPLANE_AUTH_TOKENdefault unset; when set,/v1/...requiresAuthorization: Bearer <token>WAKEPLANE_REQUEST_AUDITdefaulttrue
SQLite remains the default local mode. To move schedules to Postgres, export an import-compatible schedule manifest from the SQLite-backed daemon, start a fresh Postgres-backed daemon, then import it:
wakeplane schedule export > schedules.json
WAKEPLANE_STORE=postgres \
WAKEPLANE_DATABASE_URL=postgres://wakeplane:secret@db.example.com:5432/wakeplane \
wakeplane serve
wakeplane schedule import --file schedules.json
wakeplane statusThis bridge moves schedule definitions. Run history, receipts, audit logs, leases, and dead letters stay in the source database unless restored with database-native backup tooling.
- Public Docs Home
- Install
- CLI Reference
- Public API Reference
- Operator Console
- Public Status
- Current Status
- Architecture
- API Contract
- Run States
- Embedding Contract
- Operator Runbook
- Storage Interface
- Storage Portability
- Replace Semantics
- SQLite Audit
- Release Discipline
- Deployment Notes
For the current coherence audit, hardening gaps, and scale path, see Current Status.
See CONTRIBUTING.md.
See SECURITY.md.
MIT - see LICENSE.
Runtime and build execution state in this repo is tracked through small.
- Use
small plan,small checkpoint,small handoff, andsmall check --strictfor agent-owned state. - Use
small draftandsmall acceptfor human-owned.smallartifacts. - Use
small apply --task ... --cmd ...for build, test, and verification commands.