Leonxlnx/unlazy
unlazy is an agent skill for Claude Code, Codex CLI and other agent harnesses that enforces "completion discipline": before AI-agent work is reported done, it must satisfy a ledger of runnable gates (GATES.md) whose shell/Node checks are executed and whose output must match a declared EXPECT: string, with digest-bound evidence, approval records, and --reverify to re-run already-"complete" gates. It also provides scoped multi-leaf/branch orchestration with lease-based claiming for parallel agent dispatch, a Claude Code Stop-hook that blocks premature completion, and documentation of the threat model (shell resolution, PATH, approval storage) around executing arbitrary checker commands. The README grounds the design in cited research on LLM laziness, premature truncation, and over/under-thinking (e.g. METR's Time Horizon, SlopCodeBench, OptimalThinkingBench, s1), while being explicit that this research motivates but does not prove the tool's effectiveness.
What it claims
unlazy makes "done" mean "a declared command oracle passed." Each gate in GATES.md passes only when its CHECK: process exits 0 and its EXPECT: string matches combined stdout/stderr. The source targets version 2.1.0, which is not a tagged GitHub release. The authors advise pinning an exact commit if you need an immutable install. The checker and hook need Node 16+ and have no third-party runtime dependencies.
How it works
The checker's mode decides whether anything executes:
flowchart TD
A[gate-check.mjs GATES.md] --> B{mode}
B -->|--status| C[validate evidence binding, never executes]
B -->|normal| D{exact approval record?}
D -->|no| E[print command, EXPECT, CWD, shell, PATH; do not run]
D -->|yes| F[execute CHECK]
B -->|--approve / --reverify| F
F --> G{exit 0 AND EXPECT matches?}
G -->|yes| H[write digest-bound evidence]
G -->|no| I[gate unmet]- Normal mode is not a permanent dry run. Once a gate is approved, normal mode runs it.
- Output limit. Captured output over 1 MiB fails. It is never truncated into a success.
- Evidence binding. Evidence begins with a SHA-256 digest of
CHECK:/EXPECT:/CWD:. Gates with prose, legacy or mismatched evidence count as stale and unmet. Manual gates with human evidence still work. - Parser rejections. It rejects zero-gate ledgers, duplicate ids, and abandonments that lack a reason.
- Abandonment. A valid abandonment exits 1 with
HANDOFF REQUIRED. It is never a success. - Shell selection. The order is
--shell, thenUNLAZY_SHELL, then the platform default (/bin/sh, orComSpecon Windows). Checks inheritPATH, so Git Bash and PowerShell launches can behave differently. - Parallel orchestration. This lives under
.unlazy/<scope>/(PLAN.md, GATES.md,gates/leaf-*.md,gates/node-*.md). - Leaves move through WAITING, READY, IN-FLIGHT, VERIFIED and ABANDONED.
- Before running in parallel, leaves must claim disjoint
OWNS:paths. - Gate checks run sequentially unless you pass
--jobs N, where N is 1–64. - Stop hook. It blocks while gates are unmet or launch waves are incomplete, but it never executes checks. After six consecutive blocks without semantic progress it gives up and lets the session stop. Metadata-only edits do not reset that count.
How to use it
npx skills add Leonxlnx/unlazyAdd -g for a user-level install or --all for every detected agent. For a manual install, clone into ~/.claude/skills/unlazy or ~/.codex/skills/unlazy. Invoke it as /unlazy or as $unlazy in Codex:
/unlazy tree 5 refactor the payment module and verify every migration pathFor a solo task, copy templates/gates-leaf.md to GATES.md and run:
node <path-to-skill>/scripts/gate-check.mjs --status GATES.md
node <path-to-skill>/scripts/gate-check.mjs --approve GATES.md
node <path-to-skill>/scripts/gate-check.mjs --reverify GATES.md
node <path-to-skill>/scripts/gate-check.mjs --scope api --leaf leaf-1.2.1 --claim
node <path-to-skill>/scripts/install-hooks.mjs # also --scope api, --uninstallscripts/gate-lint.mjs is an advisory, non-executing linter for weak ledgers; add --strict to make warnings fail.
By default the hook installer writes .claude/settings.local.json and backs up the old file as <settings-file>.unlazy.bak. Add that file, .unlazy/ and .unlazy-hook-state.json to your ignore rules. --shared writes absolute paths into project settings, which usually isn't portable and can leak directory names. Run the test suite with npm test.
Limits
- Approval is consent, not a sandbox. Checks run with ambient filesystem, credential and network access.
- Approvals are stored in
~/.unlazy/approved, or whereverUNLAZY_APPROVAL_DIRpoints as long as it is outside the repo. - Each approval binds the exact command, shell, CWD, limits, platform and full
PATH. - Approvals do not hash called scripts, fixtures or dependencies. If those change, re-inspect them and run
--reverify. - Evidence can be forged. The digest catches structural drift, not tampering. Anyone who can edit the ledger can forge evidence.
- Leases coordinate but don't isolate. They are conservative and may reject safe pairs. Use separate worktrees and caches when writes can collide.
- A gate only checks what you declare. The checker cannot tell whether a shell command actually matches the gate's English title. Gate quality is the user's responsibility.
- No benchmark evidence for the tool itself. Earlier README versions cited a six-run internal comparison, but its raw artifacts aren't in the repository. Treat it as historical, not a guarantee; a rerun protocol is in
research/validation-protocol.md. - The cited research motivates the design only. For example, SlopCodeBench's best agent passed 14.8% of checkpoints and none solved a problem end to end. The README says such work does not prove unlazy helps.
Organisations named here
- METR
- OpenAI
- Anthropic
- Claude Code
- OptimalThinkingBench
- s1
- SlopCodeBench
Technologies named here
- unlazy
- GPT-4 Turbo
- skills CLI
- gate-check.mjs
- gate-lint.mjs
- install-hooks.mjs
- Claude Code
- Codex CLI
- Codex
- Node.js
- Git
Techniques named here
- Acceptance ledger / gate checking
- Approval binding
- Depth Tree decomposition
- Scoped pipelines with lease coordination
- Rolling dispatch with native launch waves
- Budget forcing
Related in coding-agents
