CronSnap (Update: project work has moved! Link)
CronSnap is a local workflow kernel for AI-assisted development workflows. It enforces deterministic, repository-local policy gates for high-risk operations through a tiny CLI and event/receipt artifacts.
- Initializes and stores workflow state in
.harness/state.json. - Tracks receipts for named gates (for example
human-signoff) in.harness/receipts/<gate>.jsonl. - Evaluates whether actions are allowed in
cronsnap canandcronsnap status. - Writes decision events to
.harness/events.ndjson. - Can install a local git shim for command interception (
cronsnap hooks enable git). - Can install a local gh (GitHub CLI) shim for comment/PR/issue interception (
cronsnap hooks enable gh). - Can install a local gog (gogcli / Google Suite CLI) shim for send/create/write/update/delete interception (
cronsnap hooks enable gog).
- Go 1.22+ (or compatible with project toolchain)
- Git repository (for repo-root discovery)
jqruntime dependency for adapter shims (git, gh, and gog wrappers parse kernel JSON output)
| Method | Command | Notes |
|---|---|---|
| Source build (current working copy) | go build -o ./cronsnap ./cmd/cronsnap |
Useful for local development |
| User/global install | go build -o "$HOME/.local/bin/cronsnap" ./cmd/cronsnap |
Adds CLI for new terminals if ~/.local/bin is on PATH |
| Optional system path | sudo go build -o /usr/local/bin/cronsnap ./cmd/cronsnap |
Requires elevated permissions |
| Release artifacts | Download from GitHub Releases | See docs/RELEASING.md |
Tip:
~/.local/binis already in the common shell PATH for many setups. If needed, addexport PATH="$HOME/.local/bin:$PATH"to your shell profile.
cronsnap init [--goal <goal>] [--action-gate action=gate1,gate2] [--profile <name>] [--phases <minimal|standard|full|custom=a,b,c>] [--json]cronsnap ok [<summary>] [--summary <text>] [--json]cronsnap onboard [--goal <goal>] [--action-gate action=gate1,gate2] [--profile <name>] [--phases <preset>] [--auto-install-git] [--json]cronsnap doctor [--json]cronsnap hooks enable git [--force] [--shim-dir <path>] [--mode enforced|observe] [--json]cronsnap hooks enable gh [--force] [--shim-dir <path>] [--mode enforced|observe] [--json]cronsnap hooks enable gog [--force] [--shim-dir <path>] [--mode enforced|observe] [--json]cronsnap hooks status [--json]cronsnap status [--json]cronsnap can <action> [--mode enforced|observe] [--json]cronsnap run-gate <gate> [--status pass|fail] [--exec <cmd>] [--summary <text>] [--source <provider>] [--json]cronsnap run-gates <gate=status> ... [--json]cronsnap advance-phase [--to <phase>] [--json]cronsnap next [--json]cronsnap reset [--full] [--force] [--json]
Known profile: pi-mono (--profile pi-mono) applies a conservative default for commit, push, and merge actions, plus phase-gate defaults used by the harness workflow.
--execflag:cronsnap run-gate tests-pass --exec "go test ./..."runs a command and records pass/fail based on exit code.--sourceflag:cronsnap run-gate tests-pass --source github-actionsrecords the provider that produced the result.cronsnap next: Shows which gates are missing and suggests commands to satisfy them.cronsnap reset: Clears all receipts. Use--fullto also remove state.json.cronsnap run-gates: Batch gate recording:cronsnap run-gates tests-pass=pass lint-pass=pass.--phasesflag: Phases are now opt-in. Use--phases minimal|standard|full|custom=a,b,cduring init/onboard.- Gate name validation:
run-gatewarns when a gate name isn't required by any configured action or phase. - Atomic state writes: State file writes use write-then-rename for crash safety.
- File locking: Advisory file locks prevent concurrent corruption.
- JSON error handling: All
--jsonmode output is guaranteed valid; errors go to stdout with non-zero exit code.
Decision results include a reason_code field:
ok— all required receipts present, action allowedmissing_receipt— one or more required gate receipts are missing or failedunknown_action_denied— no policy configured for the requested action (deny-by-default)blocked— one or more actions have missing gates (used in status)phase_advanced— phase transition completed successfullyadvance_phase_failed— phase transition denied (missing requirements or phases not enabled)
Two commands are all you need:
cd /path/to/project
cronsnap init # set up state, gates, and git shim
# ... agent works ...
cronsnap ok # human signs off — agent can now push/mergeFor more control, the full commands still work:
cronsnap onboard --goal my-goal --profile pi-mono
cronsnap hooks enable git
cronsnap run-gate human-signoff --status pass --summary "checks passed"
cronsnap can mergePrevent an agent from pushing or merging without human approval:
cronsnap init --goal my-project
export PATH=$PWD/.harness/bin:$PATH
# Agent tries to push — blocked by policy
git push origin main
# {"cronsnap":"deny", "message": "cronsnap policy denied action (missing_receipt): ...", ...}
# Human reviews and signs off
cronsnap ok "changes look good"
# Agent can now push
git push origin mainPrevent an agent from creating PRs, posting comments, or merging without approval:
cronsnap hooks enable gh
export PATH=$PWD/.harness/bin:$PATH
# Agent tries to comment on a PR — blocked
gh pr comment 42 --body "LGTM"
# {"cronsnap":"deny", ...}
# Human signs off
cronsnap ok
gh pr comment 42 --body "LGTM" # now allowedPrevent an agent from sending emails, creating calendar events, uploading files, or modifying spreadsheets through gogcli:
cronsnap hooks enable gog
export PATH=$PWD/.harness/bin:$PATH
# Agent tries to send an email — blocked
gog gmail send --to user@example.com --subject "Report" --body "See attached"
# {"cronsnap":"deny", ...}
# Agent tries to create a calendar event — blocked
gog calendar create primary --summary "Standup" --from 2026-02-22T09:00:00 --to 2026-02-22T09:30:00
# {"cronsnap":"deny", ...}
# Read-only commands always pass through
gog gmail search "from:boss" # allowed — no policy check
gog calendar events primary --today # allowed — no policy check
gog drive ls # allowed — no policy check
# Human signs off, then write operations are allowed
cronsnap ok
gog gmail send --to user@example.com --subject "Report" --body "See attached" # allowedThe gog adapter maps commands to six action categories:
| Action | What it gates |
|---|---|
gog-send |
Sending emails (gmail send) and chat messages (chat dm send) |
gog-create |
Creating events, contacts, tasks, documents, forms, etc. |
gog-write |
Uploading files, writing to spreadsheets/docs, sharing |
gog-update |
Modifying existing resources and settings |
gog-delete |
Deleting files, events, contacts, clearing data |
gog-execute |
Running Apps Script functions (appscript run) |
See docs/cronsnap/contracts/gog-adapter.md for the full command mapping.
Any adapter can run in observe mode to log policy decisions without blocking commands:
cronsnap hooks enable git --mode observe
cronsnap hooks enable gh --mode observe
cronsnap hooks enable gog --mode observe
export PATH=$PWD/.harness/bin:$PATH
# Commands proceed but deny events are still logged to .harness/events.ndjson
git push origin main # runs, but logs the deny decision
gog gmail send --to ... # runs, but logs the deny decisionAll three adapters can be active simultaneously:
cronsnap init --goal my-project
cronsnap hooks enable git
cronsnap hooks enable gh
cronsnap hooks enable gog
export PATH=$PWD/.harness/bin:$PATH
# Check which adapters are active
cronsnap hooks statusUse --exec to record gate results from automated checks:
cronsnap run-gate tests-pass --exec "go test ./..."
cronsnap run-gate lint-pass --exec "shellcheck scripts/adapters/*.sh"go test ./...
shellcheck scripts/adapters/cronsnap-git-wrapper.sh
shellcheck scripts/adapters/cronsnap-gh-wrapper.sh
shellcheck scripts/adapters/cronsnap-gog-wrapper.sh
bash scripts/ci/cs-docs-lint.sh
bash scripts/ci/cs-plans-lint.sh
bash scripts/ci/cs-spikes-lint.sh
bash scripts/ci/cs-specs-lint.sh
bash scripts/ci/cs-runbooks-lint.sh
bash scripts/ci/cs-git-wrapper-smoke.shTerminal recordings of core scenarios are generated as GIFs using Charmbracelet VHS. Install VHS locally (brew install vhs on macOS), then:
bash scripts/ci/cs-visual-smoke.shThis runs all scripts/visual/scenario-*.tape files and outputs GIFs to scripts/visual/output/. The four built-in scenarios are:
- happy-path — full deny-to-allow cycle (run-gate + ok + push allowed)
- deny-path — push blocked, status shows blockers, shim returns deny payload
- observe-mode — push proceeds in observe mode but deny event is logged
- phase-advance — advance phases, blocked at implement, unblocked after receipt
- gh-happy-path — gh pr comment blocked, human signs off, comment allowed
- gh-deny-path — multiple gh actions (comment, issue create, merge) all blocked
To add a new scenario, create a scripts/visual/scenario-<name>.tape file — the runner picks it up automatically.
In CI, the visual-qa job runs these recordings on every PR and uploads the GIFs as downloadable artifacts.
- If you add or change a public command, update the command list and examples in this README.
- If you add a new adapter, update "What it does today", "Current commands", "Common use cases", and the Validation section.
- If policy/state/event semantics change, update the corresponding sections in this README and
docs/DESIGN.md. - If CI/lint scripts move or change names, update this validation section.
- Run tests and docs checks after any architectural refactor that alters command/decision behavior.
- Adapter contracts are documented in
docs/cronsnap/contracts/— update the relevant contract when changing adapter behavior.
.harness/state.json: current goal, phase, and policy gates..harness/receipts/: append-only per-gate receipt logs..harness/events.ndjson: append-only decision/event log.
docs/PLANS.md: workflow contract for this repo.docs/specs/: intake specs.docs/spikes/: investigation notes.docs/plans/: active/completed plans.docs/cronsnap/contracts/: adapter and kernel operation contracts.