One repository, one Go module, one Bazel module: the public half of a private infrastructure monorepo, published whole.
It is not a framework and not a grab bag. It is a working agent-operated deployment system and the pieces it is built from, released together so that the pieces are usable on their own and the system is reproducible as a whole.
| CandaceOS | An agent-operated app lab: a harness proposes, Core approves and fences, a node executor reconciles Compose applications, and an operator UI watches. Its deployment kit is candaceos/. |
| Warden | A fleet watchdog: Raft-style leader election over a static peer set, liveness, incidents, and an authoritative view every mutation is fenced against. |
| gotth-live | Server-driven live user interfaces from Go. State and rendering stay in your process; one WebSocket per tab carries events up and re-rendered fragments down. No npm, no CDN. |
| xetcas | A self-hosted Xet content-addressable storage server with a Git LFS front door. Re-pushing a 48 MiB model after editing 2% of it costs about 1 MiB. |
| pkg/ | The primitives the rest is built on: pgmem (a process-local PostgreSQL emulator for tests), liquidproto (protobuf refinement types), cron, config, redact, telemetry, and more. |
Everything is Apache-2.0.
Go 1.26 and a clone. There is no npm install, no bundler, and no code
generation step to run first:
go run ./examples/gotth/countercounter: http://127.0.0.1:8080
counter: allowed origins [http://127.0.0.1:8080 http://localhost:8080]
Open that URL in two browser tabs. The number lives in the Go process and
neither tab holds a copy of it: click in one and the other repaints, reload
either and the count survives, and the client runtime that carried the patch
was compiled into the binary and served by the same handler that serves the
WebSocket. examples/gotth/counter/README.md
follows one click all the way through and names the file each step lives in.
candace/
├── pkg/ domain-neutral primitives — nothing in them knows what CandaceOS is
├── services/ composable business logic — candaceos, warden
├── app/ runnable compositions — candaceos-core, candaceos-agent, warden
├── proto/ .proto sources and their committed Go bindings
├── candaceos/ the deployment kit: Compose stack, installer, fleet driver, updater
├── xetcas/ a Rust workspace (xetcasd) plus its generated Go bindings
├── examples/ one worked consumer per extension seam, each with its own suite
├── extensions/ copilot-pair, a GitHub Copilot CLI extension
├── docs/ extending.md — the four compile-time seams
└── bazel/ the legacy WORKSPACE shim
The three Go trees are separated by one rule, about who may import whom:
flowchart LR
app["<b>app/</b><br/>runnable compositions<br/>each owns a cmd/"]
services["<b>services/</b><br/>composable business logic"]
pkg["<b>pkg/</b><br/>domain-neutral primitives"]
app --> services --> pkg
app --> pkg
Nothing in pkg/ imports services/ or app/, which is what makes the
primitives usable on their own:
| Package | What it is |
|---|---|
gotth |
Server-driven live UI. Large enough to have its own documentation set. |
pgmem |
A process-local PostgreSQL emulator for fast tests — real PostgreSQL AST, no server. |
cron |
Durable in-process scheduling with human-readable declarations and an explicit state store. |
liquidproto |
The runtime for Liquid Proto: protobuf with refinement predicates compiled into the generated Go. |
telemetry |
Trace propagation and structured JSONL over the candace.telemetry.v1 contracts, with no observability SDK. |
config |
Configuration-boundary parsing: environment lookup, private-origin validation, provider/model strings. |
mailbox |
Serializes ownership of a mutable value onto one goroutine — commands run in turn, so no field needs a lock. |
boundedbuffer |
An io.Writer that retains at most a fixed number of bytes while still reporting the true write lengths. |
redact |
Removes caller-declared sensitive values, and their URL-userinfo spellings, from log-bound text. |
labels |
Canonicalizes case-insensitive label lists so services compare and deduplicate them one way. |
core |
The zerolog logger the Go trees log through, plus the few formatters operator pages share. |
patience |
The one typed await for tests: poll a value, judge it with a predicate, get the value that satisfied it back. |
widget |
The widget dialect and its toolchain: interpreter, validator, generator, and the typed SDK that mounts generated cards into a gotth-live host. |
pkg/proto and pkg/scripts hold tooling rather than a package.
It is a one-way snapshot of a private monorepo's candace/ folder at one
exact revision, published with no upstream history. There is no PR flow here
and no maintainer watching for contributions; a commit made here wedges the
next export rather than being merged.
Each snapshot carries an immutable export-<sha12> tag, a matching GitHub
Release, and a provenance marker, .candace-export.json, naming the exact
source revision it came from. Cite the tag, not a branch.
Each Release carries candace-<sha12>.tar.gz and its .sha256. The tarball is
this tree re-rooted so MODULE.bazel is at the archive root, built twice and
byte-compared before it is kept. In your own MODULE.bazel:
bazel_dep(name = "candace", version = "0.0.0")
archive_override(
module_name = "candace",
integrity = "sha256-...", # from the Release's .sha256
strip_prefix = "candace-<sha12>",
urls = ["https://github.com/candacelabs/candace/releases/download/export-<sha12>/candace-<sha12>.tar.gz"],
)Then depend on what you use — @candace//services/candaceos/component,
@candace//pkg/gotth/live, @candace//services/warden — and build.
Not a Bazel repository? The module path is the repository path:
go get github.com/candacelabs/candace@export-<sha12>There is no semantic-version tag, so @latest resolves a moving pseudo-version
of the default branch; naming the export tag is what pins a build.
docs/extending.md covers both shapes in full, plus the
http_archive fallback and the legacy WORKSPACE path.
Every extension seam has a worked example with its own test suite. They are the contract's executable half — the documentation says what is guaranteed, and these fail if it stops being true.
| Example | Shows |
|---|---|
external-consumer |
A complete outside repository choosing every seam at once: its own identity and overlay, its own sidebar entry and page, three composed services, a custom agent harness, and the Core binary linked from them — built and tested both supported Bazel ways. This is also the acceptance test every release archive passes. |
custom-brand |
Core wearing another product's identity — name, agent, wordmark, palette, an overlay asset, an extra sidebar entry and page — with no edit to Core. |
custom-ui-page |
The smallest useful UI extension: stock identity, one sidebar entry, one page of your own. |
gotth/counter |
gotth-live at its smallest: a number that lives in Go, four buttons, and every open tab kept in step by the server. |
gotth/chat |
One room in Go, several browsers, and every message reaching every session over a server push. |
gotth/dashboard |
A feed pushing twenty times a second, three live regions patched independently, and two plain-HTMX regions on the same page. |
Bazel is the primary build and comes from a pinned container, so the command is the same on a laptop and on a runner. Docker is the only prerequisite:
tools/bazel.sh build -- //... -//xetcas/... # everything but the Rust workspace
tools/bazel.sh test -- //... -//xetcas/...
tools/bazel.sh build //xetcas/... # the Rust workspace and its Go bindings
tools/bazel.sh test //xetcas/...The plain go command works on the same tree and needs no Bazel:
go build ./...
go test ./...The Rust workspace builds with plain Cargo too — that is the path its demo,
container images, and just targets take:
cd xetcas && cargo build --workspace && cargo test --workspace.bazelversion (Bazel 9.2.0) and MODULE.bazel (rules_go 0.62.0, Gazelle
0.52.2, Go SDK 1.26.5, rules_rust 0.73.0) are the only version authority. BUILD
files are generated by Gazelle (tools/bazel.sh run //:gazelle) and CI fails on
drift.
The deployment kit installs and runs the whole one-box stack from this clone. The default install is deliberately harmless: a simulated harness, a dry-run executor, and no Docker socket mounted anywhere.
./candaceos/install.sh # then open http://<host>:7780
./candaceos/status.sh
./candaceos/uninstall.shCore publishes on all host IPv4 interfaces with no built-in authentication:
put it behind your own authenticating proxy before exposing it beyond a trusted
network. candaceos/README.md is the operations manual,
and candaceos/AGENTS.md states the trust model as eight
invariants with their enforcement points.
AGENTS.md— the repository's own guide: taxonomy, seams, invariants, conventions.docs/extending.md— the four compile-time seams and how to pin a snapshot.pkg/gotth/README.md,xetcas/README.md— each subsystem's own front page.app/*/CLAUDE.md— what may not be changed casually in each binary.
Apache License 2.0. See LICENSE.
AI systems assisted with work in this repository. Their output is not presumed correct, secure, reviewed, or production-ready.