unlazy: A Depth Tree Method and Runnable Gates Against AI Agent Laziness
Anti-laziness skill for AI agents. Core: the Depth Tree method, which splits a task N layers deep and gives every leaf the full time budget of the whole task, so effort multiplies with depth. Grounded in 2025-2026 research on model laziness, underthinking and premature completion.
At a glance
- What is it?
- unlazy is a skill for Claude Code and Codex CLI that fights premature completion in AI agents by splitting tasks into a depth tree and enforcing every leaf with runnable, evidence-backed gates. The Depth Tree method gives each leaf the full time budget of the whole task, but the real discipline comes from the gate checker scripts.
- Who is it for?
- Adopt unlazy if you delegate substantial, multi-step work to Claude Code or Codex CLI and you are willing to write explicit acceptance ledgers and review every shell command before approval. Do not adopt it if you want a hands-off productivity boost or if your tasks are small enough that a single prompt suffices.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 13 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The Problem: Model Laziness and Premature Completion
AI agents often stop early. They produce a plausible answer, declare victory, and skip the verification steps that a careful human would run. The README cites 2025-2026 research on model laziness, underthinking, and premature completion as the motivation. The specific problem unlazy addresses is not that agents are lazy in a moral sense. It is that they lack a mechanism to prove their own work. A prompt that says 'be thorough' does not bind the agent to any concrete check. unlazy tries to replace that vague instruction with a structural method and a runnable enforcement layer. The intended user is someone running Claude Code or Codex CLI on substantial tasks, like refactoring a payment module, where a silent failure is costly.
The Depth Tree Method: Effort Multiplies with Depth
The core idea is the Depth Tree method. You split a task N layers deep, and every leaf gets the full time budget of the whole task. That means if the root task has a 60-minute budget, each leaf also gets 60 minutes, not a fraction. The README claims this makes effort multiply with depth. The logic is that a shallow decomposition gives the agent one chance to do everything; a deep decomposition forces it to revisit each subtask with the same seriousness as the original. The trigger command is '/unlazy tree 5 refactor the payment module and verify every migration path'. The number 5 is the depth. This is a prompt-engineering pattern, not a runtime scheduler. The agent is supposed to respect the tree structure because the skill description instructs it to. Whether the model actually follows that instruction is a separate question, and the gate system exists to catch failures.
The Gate Contract: What Makes a Gate Runnable
A gate is a markdown checklist item that includes a CHECK line, an EXPECT line, and an EVIDENCE field. The example in the README shows a gate for pricing fixtures: CHECK runs a Node script, EXPECT says 'pricing verification passed', and EVIDENCE starts as pending. A gate passes only when the process exits 0 and the EXPECT string matches the combined output. The checker also enforces a 1 MiB limit on the captured output and the matcher string. It never truncates a larger string into success. This is a meaningful design choice: many ad-hoc checkers would just grep for a substring. unlazy requires an exact match on the full combined output, which forces the CHECK script to print a clean, success-only marker after all assertions pass. The README warns that the checker cannot infer that an English title and arbitrary shell code mean the same thing. So a gate that says 'verify pricing' but runs a script that does nothing will fail because the output will not match the expectation.
Getting It Running: Commands and Modes
Installation uses the skills CLI: 'npx skills add Leonxlnx/unlazy'. Add '-g' for a user-level install or '--all' for every detected agent. Manual installation means cloning the repository into ~/.claude/skills/unlazy or ~/.codex/skills/unlazy. The core is SKILL.md. The checker script requires Node 16 or newer and has no third-party runtime packages. The CLI has several modes. '--status' is always non-executing; it inspects GATES.md without running anything. A normal run without '--approve' prints the resolved command, expectation, working directory, shell, and PATH without executing, but only on a new oracle with no exact approval record. Once the exact oracle is approved, normal mode can execute it. '--approve' runs the ledger after you have read every command. '--reverify' re-runs all runnable gates, including those marked complete. The README gives a concrete example of writing a GATES.md from a template and running 'node <path>/gate-check.mjs --status GATES.md'. This is a real workflow, not a theoretical one.
Security Boundary: Approval Is Not a Sandbox
The security model is explicit and limited. Approval records live under ~/.unlazy/approved by default, and UNLAZY_APPROVAL_DIR can select another owner-private directory, but it must be outside the checked repository. Symlinked stores and linked, replaced, or non-private records fail closed. Each approval record is specific to the absolute ledger and gate, exact CHECK and EXPECT strings, resolved CWD and shell, timeout, output and regex limits, platform, and full inherited PATH. Editing any bound input requires approval again. The README states plainly: 'Approval is consent, not a sandbox.' The checker does not hash called scripts, fixtures, dependencies, or other transitive inputs. That means a gate that runs a script can execute anything that script does, and the approval does not cover changes to that script. The README suggests using '--reverify' after reinspecting changed dependencies. This is an honest limitation. The security boundary protects against accidental changes to the ledger, not against a malicious or compromised dependency.
Limitations and Failure Modes
The most obvious limitation is that the checker cannot prove semantic correctness. It can only match output against an EXPECT string. A gate that checks the wrong thing will pass. The README warns about this directly. Another limitation is the Windows shell issue. The checker uses '--shell' first, then UNLAZY_SHELL, then Node's platform default. On Windows, a checker launched from Git Bash can see Unix-like tools that the same checker launched from PowerShell does not. '--shell' changes the interpreter, but it does not install grep, tail, tr, or other external programs. So a gate that works in one environment may fail in another. The README says a shell or PATH mismatch is a failed verification, not successful evidence. This is a real operational burden for teams with mixed environments. Also, the current source targets version 2.1.0 but is not identified as a tagged GitHub release. The README advises pinning an exact commit for immutable installation. That is a practical caveat for anyone who wants reproducibility.
Alternatives and Comparisons
A common alternative is to write a plain checklist in a prompt and trust the agent to follow it. That approach has no enforcement mechanism. Another alternative is to use a testing framework like Jest or pytest to verify code changes. Those frameworks are excellent for deterministic unit tests, but they do not integrate with an agent's task decomposition or provide a gate ledger for non-code outcomes. unlazy sits between a prompt and a test suite. It gives you a structured way to declare acceptance criteria and a script that checks whether the agent actually ran the checks. The difference in approach is that unlazy treats the ledger itself as an artifact that must be kept in sync with the actual checks. The unkeyed binding detects structural drift, but not ledger tampering. The README notes that anyone who can edit a ledger can forge canonical-looking evidence. So if you need tamper-evident proof, you would need an external signing mechanism, which unlazy does not provide.
Maintenance and Upgrade Cost
The README includes a CHANGELOG.md for the unreleased change set, but no tagged releases were retrieved. That means you cannot rely on semantic versioning from npm or GitHub releases. You must pin a commit. The skill uses no third-party runtime packages, which reduces dependency risk. The checker scripts are plain Node.js, so they should run on any Node 16+ environment. The main maintenance cost is writing and maintaining the GATES.md file for each task. The parser rejects zero-gate ledgers, duplicate ids, incomplete runnable gates, invalid expectations, and abandonment with a missing reason. That strictness means you cannot skip writing a proper expectation. The README also mentions an advisory, non-executing gate-lint.mjs script that catches mechanically weak ledger patterns. Using '--strict' makes warnings fail. This adds a quality gate on your own gate definitions, which is useful but adds another tool to learn. The license is MIT, so you can modify and redistribute, but you should read the license text yourself for full terms.
Editorial conclusion
Adopt unlazy if you delegate substantial, multi-step work to Claude Code or Codex CLI and you are willing to write explicit acceptance ledgers and review every shell command before approval. Do not adopt it if you want a hands-off productivity boost or if your tasks are small enough that a single prompt suffices. Before relying on it, verify that your agent supports slash skills, pin an exact commit because the current source targets 2.1.0 without a tagged release, and read SECURITY.md to understand that approval is consent, not a sandbox, and that transitive dependencies are not hashed.
Community notes