The seismograph for the agent ecosystem. Sign, govern, and debug the skills your agents run — before they slide.
Tiltmeter gives agent skills (SKILL.md files, plugins, MCP servers) what software packages got decades ago: cryptographic signatures, a governed registry, auditable approvals, and runtime debugging. It answers three questions about every skill:
- What is this? — signed, attributed, and tamper-evident (Ed25519 + content hashing)
- Is it allowed? — registry with namespaces, policies, and human approvals
- What did it do? — capture sessions, decision trees, deadlock detection, context drift
This is the Go implementation (pure-Go SQLite, no cgo). The original Python
implementation is preserved in python-legacy/ for reference.
Web Console — dashboard & verification
CLI — sign & verify (tamper detection)
Server & REST API
- Ed25519 key-pair signing of skill content (SHA-256 content hash)
- Sigstore keyless signing (
sign --keyless): OIDC → Fulcio cert → Rekor transparency log, verified withverify --keyless - Provenance statement generation — in-toto Statement/v1 + SLSA v1.0 provenance
- SBOM generation for skill dependencies
- OCI artifact packaging: bundle signed skills as OCI images, push/pull any registry (
oci bundle/extract/push/pull) - Tamper detection: any byte change breaks verification
- Skill registry with namespaces (public/team/private)
- Policies per namespace:
auto_allow/auto_deny/require_approval - Human approval workflow: pending → approve/reject with reviewer + reason
- Audit log with JSON export (who approved what, when, why)
- Default-safe: unknown namespaces default to
require_approval
- Debug sessions capture events (LLM calls, tool calls, state changes)
- Decision tree reconstruction, deadlock detection, context drift scoring
- Timeline replay of any captured run
- Single-page console (dashboard, registry, approvals, policies, audit, debug)
- Full REST API for automation and CI integration
- SQLite storage (zero-config, pure-Go driver)
Requirements: Go 1.25+ (no cgo, no C toolchain — SQLite is pure Go).
# build the CLI
go build -o tiltmeter ./cmd/tiltmeter
# start the server (REST + web console, default :8765)
./tiltmeter serve --host 0.0.0.0 --port 8765
# sign a skill file (Ed25519 keypair)
./tiltmeter sign skill.md --author "Your Name" --output sig.json
# ...or sigstore keyless (OIDC → Fulcio → Rekor)
./tiltmeter sign skill.md --keyless --output keyless.json
# verify it (tamper → INVALID, exit 1)
./tiltmeter verify skill.md --signature <sig> --public-key <key>
./tiltmeter verify skill.md --keyless --bundle keyless.json
# OCI artifact packaging
./tiltmeter oci bundle skill.md sig.json -o layout/
./tiltmeter oci push layout/ myorg/skills --tag 1.0.0 --registry https://ghcr.io -u user -p $TOKEN
./tiltmeter oci pull myorg/skills --tag 1.0.0 -o pulled/ --registry https://ghcr.io
# publish to the registry & manage
./tiltmeter publish skill.md --name my-skill --namespace public --version 0.1.0
./tiltmeter search my-skill
./tiltmeter approve <skill_id> --action approve --reviewer you
# debug & replay
./tiltmeter replay <session_id>
./tiltmeter list --namespace publicOpen http://localhost:8765 for the web console.
Database selection: all registry commands and the server honour the
TILTMETER_DBenvironment variable; the server also accepts--db <path>. Default isdata/tiltmeter.db(created automatically).
| command | description |
|---|---|
sign <file> [--author] [--output] [--keyless] |
Sign a skill file (Ed25519 or sigstore keyless) |
verify <file> --signature --public-key | --keyless --bundle |
Verify signature + content hash |
oci bundle/extract/push/pull |
Package signed skills as OCI artifacts |
publish <file> --name [--namespace] [--version] |
Publish skill to registry |
search <query> [--namespace] |
Search the registry |
approve <skill_id> --action approve|reject [--reviewer] |
Approve/reject a skill |
policy-set <namespace> --type auto_allow|auto_deny|require_approval |
Set namespace policy |
replay <session_id> |
Replay a debug session |
list [--namespace] [--status] |
List registry skills |
serve [--host] [--port] [--db] [--static] |
Run the REST API + web console |
| method | path | description |
|---|---|---|
| GET | /api/stats |
Dashboard statistics |
| POST | /api/skills/sign · /api/skills/verify |
Sign / verify |
| GET/POST | /api/skills · /api/skills/{id} |
Registry CRUD + details |
| GET | /api/skills/search |
Search |
| POST | /api/skills/{id}/approve |
Approval decision |
| GET | /api/approvals |
Approval queue |
| GET/POST | /api/policies |
Policy management |
| GET | /api/audit-logs · /api/audit-logs/export |
Audit + export |
| POST | /api/debug/sessions · /api/debug/sessions/{id}/events |
Capture events |
| GET | /api/debug/sessions/{id}/tree · /deadlocks · /drift · /timeline |
Debug views |
| GET | /health |
Health check |
Full API reference: see AGENTS.md or the server source (internal/server/server.go).
GitHub Actions: every push/PR runs the full Go test suite (with the race
detector), go vet, a gofmt check, the E2E smoke test, and the comprehensive
user test — plus a signature-gate job that verifies a signed example skill and
proves tampering is caught, and a keyless E2E job using GitHub OIDC.
The reusable signature gate is a self-contained composite action — drop it into any pipeline that consumes signed skills:
- uses: LandslideLab/Tiltmeter/.github/actions/tiltmeter-verify@main
with:
skill-file: path/to/skill.md
signature-file: path/to/skill.sig.json # output of `tiltmeter sign`It only needs cryptography (Python, standalone — not the Tiltmeter install)
and fails the job on any mismatch (content hash or Ed25519 signature). See
.github/actions/tiltmeter-verify/ and examples/signed-skill/ for a working
example. The committed example signature verifies with the Go CLI.
# unit + integration tests (85 tests)
go test ./...
# with race detector
go test -race ./...
# coverage
go test -cover ./...
# E2E smoke test (real server + CLI)
scripts/e2e-smoke.sh
# comprehensive user test — every CLI command, every API endpoint,
# web console, OCI push/pull over real HTTP, cross-process DB sharing
scripts/user-test.shSee TEST_REPORT.md for the full report: all 85 tests pass,
the race detector is clean, go vet and gofmt are clean, and the live
user test passes 103/103 checks against the real binary.
├── cmd/tiltmeter/ # CLI entry point
├── internal/
│ ├── database/ # SQLite schema & helpers (pure-Go driver)
│ ├── signing/ # Ed25519 sign/verify, provenance, SBOM, keyless
│ ├── policy/ # Policy engine (Rego-like, pure Go)
│ ├── replay/ # Debug sessions: tree, deadlock, drift, timeline
│ ├── oci/ # OCI bundle/extract/push/pull
│ ├── server/ # REST API + web console
│ └── cli/ # all CLI commands
├── scripts/
│ ├── e2e-smoke.sh # CLI + server smoke test
│ ├── user-test.sh # comprehensive user test (103 checks)
│ └── dev-registry/ # minimal Docker Registry v2 server for tests
├── static/ # Web console (native HTML/CSS/JS, no build step)
├── examples/signed-skill/ # signed example + demo signature
├── .github/
│ ├── actions/tiltmeter-verify/ # reusable signature-gate action
│ └── workflows/ci.yml # Go tests + gates on push/PR
├── python-legacy/ # superseded Python implementation (reference)
├── TEST_REPORT.md # test & verification report
└── AGENTS.md
Go 1.25 · pure-Go SQLite (modernc.org/sqlite, no cgo) · stdlib HTTP · vanilla HTML/CSS/JS
Apache-2.0 · Built for the LANDSLIDE human-machine collaboration initiative.


