The discipline layer for ZCode.
Plan → execute → take evidence → never stop half-done.
A local, evidence-bound coding goal protocol with durable continuation — not a general workflow engine.
Docs · Install · Commands · What is this?
English · 简体中文
Note
ZCode already writes code. LazyZCode makes it finish.
Coding agents are great at starting work and optimistic about declaring it done. The fix is not another prompt — it is a loop: a decision-complete plan gate, evidence captured on real surfaces and bound to a git tree hash, and a Stop hook that pulls the agent back until the goal is verifiably complete.
One discipline, three beats:
Finish what you start — the goal loop with plan & evidence gates.
Remember what you build — layered AGENTS.md project memory.
Keep going while you're away — scheduled wake-ups that continue the open
goal only, off-peak by design.
npm i -g lazyzcode && lzy installPrerequisites: macOS, Windows, or Linux; the ZCode desktop app (logged in),
Node ≥ 24, git (evidence binds tree hashes, so git is required — lzy loop register
hard-rejects a non-git host with git init guidance, ADR-0019). Engine
layouts are detected on all three platforms (macOS app bundle, Linux deb
/opt/ZCode, Windows per-user %LOCALAPPDATA%\Programs\ZCode).
npm i -g lazyzcode # the lzy CLI + the plugin payload
lzy install # deploy to the engine cache + register + enable
lzy doctor # local health report (zero telemetry)lzy install never writes your config.json — enabling flows only through the
engine's official plugins enable (ADR-0001).
Prefer the plugin marketplace? In ZCode's /plugin panel run
/plugin marketplace add Acfufu/lazyzcode, then install lazyzcode from it —
the same engine code path as the official marketplace, pinned to release tags.
The marketplace route installs the plugin layer only (skills, hooks, agents);
the lzy CLI still comes from npm, so npm i -g lazyzcode remains the
recommended full install.
Open a fresh ZCode session in any project and type:
zw implement <your goal>
The zw trigger injects the full orchestration protocol: the model registers
the goal → writes a decision-complete plan (HEAVY goals must pass the
plan-reviewer gate and declare their known unknowns, each with a falsification
path; every step carries its own pointers so a fresh claimer can run it) →
executes step by step → captures real-surface evidence
for every final-verification item (bound to git rev-parse HEAD^{tree}) →
runs an evidence comparison per item, and lzy loop finish must pass before
anything counts as done. Stop early, and the Stop hook pulls the agent back
(at most 2 continuations per session).
lzy status # quick check; exit code 0 = no fail-level findings
lzy doctor # deep local diagnostics, all offlineThe first goal loop is the whole product in miniature. Two more beats wait behind it:
- Remember what you build. In a mature project, run the
lazyzcode:init-deepskill to draft a layeredAGENTS.mdproject map — draft first, nothing written until you approve.lzy agents-mdaudits coverage;lzy doctor'sagents-mdline patrols adoption (warn-only). - Keep going while you're away. Mount a wake-up in the engine's own
automation with
zw continue (unattended: …). Unattended sessions continue the open goal only — never start a new one — andlzy doctor'sscheduleline suggests an off-peak window from your measured rate-limit hours, cross-checked against a declared table of platform pricing peaks (UTC+8, hand-maintained).
The scaffolding thesis has external proof: Anthropic reported its model formalized Fermat's Last Theorem in Lean in 11 days on the Prove2Me scaffold, and three consumer subscriptions proved Vinogradov's three-primes theorem in three days — what multiplied the output was not the model alone but the right scaffold. LazyZCode is that idea for software engineering.
From 0.0.7 on, one command does it:
lzy update # npm pulls the latest package, then a fresh child process runs lzy syncOn 0.0.6 or earlier, upgrade with the manual two steps (which is exactly what
lzy update automates):
npm i -g lazyzcode@latest && lzy syncWhy two steps: live sessions read the plugin payload from the engine cache's
versioned directory (~/.zcode/cli/plugins/cache/.../<version>/), not from the
npm package — so upgrading the npm package alone changes nothing in your
sessions. lzy sync atomically deploys the new payload into a new cache
directory and updates the registry. Running sessions are unaffected; new
sessions pick up the new version. Your enable state hangs off the plugin id in
enabledPlugins, so it survives version bumps — no re-enable needed.
lzy uninstall # prefers the engine's official plugins uninstall| Command | Type this | What it does |
|---|---|---|
install |
lzy install |
Deploy the plugin payload to the engine cache, register, and enable (official engine path only; zero config.json writes) |
sync |
lzy sync [--watch] |
Hot-reload the payload after edits; --watch keeps syncing on change |
update |
lzy update |
One-command upgrade: npm pulls the latest package, then a fresh child process from the new install runs lzy sync (skips when already latest; manual two-step hints on any failure) |
status |
lzy status |
Quick health check; exit 0 = no fail-level findings (warn/skip do not flip it) |
doctor |
lzy doctor |
Full diagnostics — see below |
| Goal loop | lzy loop register <slug> --title "…" [--tier heavy] → lzy loop plan <plan.md> → lzy loop start → lzy step done <ID> --evidence … → lzy loop finish |
The state machine: register → plan gate → execute → evidence → finish gate (evidence binds the composite fingerprint over the host + declared subjects; finish requires every tree clean). Plan adoption passes a human gate (0.1.1): the first run rejects with a short code — a human replies 「批准 <短码>」 and the UPS hook records the approval; the model cannot approve itself |
| Attempt lineage | lzy loop supersede <plan.md> [--review …] · lzy loop attempts |
Forward-only plan change mid-execution (0.1.0): the old attempt is marked superseded and a new one opens with every adoption gate re-run — no in-place re-planning; lineage is a checksummed ledger surviving reset |
| Subjects | lzy loop subject add <path> · remove · list |
Declare sibling repo roots for multi-tree goals (executing-only; validated git repos, no host containment) — any set change invalidates captured F evidence |
| Tier | lzy loop tier heavy |
One-way LIGHT→HEAVY upgrade; HEAVY adoption without a PASS review is machine-rejected (adoption-time gate) |
| Risk | lzy loop risk <level> |
One-way risk_class upgrade (low/med/high/restricted); HIGH+ barred from unattended lanes by the drive-entry gate (ADR-0020) |
| Lease | lzy loop lease acquire|heartbeat|release|reclaim |
Run-level lease: minutes-scale mutex with heartbeat; fence token declares write paths; reclaim is the zombie-lease exit (auto when the holder pid is gone, --force when it is not) (ADR-0020) |
| Budget | lzy loop budget init|spend|remaining |
Drive budget: wall-clock limit and approximate points limit; in-flight overspend remains recorded, then dispatch stops (ADR-0020/0027) |
| Drive | lzy loop drive [--wall-ms N] [--max-segments N] [--mode m] |
In-wake unattended execution channel: headless segments inside one wake, risk/lease/budget gates between segments, fence-tokened segment writes; wind-down authors the handoff snapshot itself; exit 0 = done or clean wind-down, 1 = gate reject / segment failure (ADR-0020) |
| Drive workers | lzy loop drive --workers N · --fast |
Multi-worker waves (0.2.4): N worker chains on sibling worktrees, claim-based step split, wave-terminal merge + evidence re-anchor; --fast ≡ --workers 2; env-auth required, H3R wake switches off; measured turns ≈2× — see the experiment report before enabling |
| Step claims | lzy loop claim [<id>] [--release] |
Anonymous per-step claiming for same-goal multi-worker runs: 48h mutex, blocked-step checks against plan deps: edges, step done auto-releases; bare form lists claimable steps |
| Evidence bundle | lzy loop export |
Re-export the evidence bundle (<slug>.report.md); also auto-archived at finish |
| Red-green manifest | lzy evidence red <Fid> --evidence … · waive-red <Fid> --reason · list |
Dual-evidence machine ledger: the red half binds its own surface (composite fingerprint by default, --surface for external); waive is the one-line exemption's machine form; greens mirror at step done; list reads the per-F manifest |
| Invalidation DAG | `lzy dag dependents <id | surface> · lzy dag stale` |
| Attestations | lzy attest comparator --file <json> |
Comparator verdicts as machine attestations (HEAVY finish enforces a current MATCH); every finish writes the LOOP_COMPLETE final attestation |
| Handoff | lzy loop handoff --snapshot <file> |
Register a clean handoff — the next Stop releases once, without spending the continue budget |
| Cross-repo list | lzy loop list [--root <dir>] |
Read-only sweep of sibling repos' goal loops (status, progress, claims, staleness, salvage stubs); anonymous release counters survive reset |
| Goal lineage | lzy loop history |
Read-only union of evidence bundles, salvage stubs, and git ledger trailers — every past goal with status, commit count, and latest activity |
| Requirement contracts | lzy contract show · lzy contract auth |
The human approves what to build and the boundary (immutable contractHash via the UPS human gate); the agent replans inside it without re-approval. Approval/withdrawal live only in UPS phrases — the CLI is read-only (ADR-0024) |
| Project manifest | lzy project check · lzy project discover |
Versioned lzy.project.json recipes (six capability classes; explicit argv, env names only, root-confined write paths) with validation, readiness, and a read-only missing list |
| Verification receipts & scope tier | lzy verify run/reuse/qualify/list/show/ci |
Controlled executor records checksum receipts (raw output separated) under .lazyzcode/verify/; declared-input reuse only after an adversarial qualification, with named conservative fallbacks (ADR-0025); read-only CI check-runs binding with honest not-current/blocked faces |
| Bounded queue & cumulative budget | lzy queue add/list/show/budget/dispatch/reconcile/cancel |
Multiple authorized items run continuously across interruptions (.lazyzcode/queue/ + .lazyzcode/budget/, reset-surviving): state-machine authorization gate, dispatch-transaction crash recovery (reconcile before action), cumulative budget bound to the contract hash that never refreshes across restarts; metering absence / unsettled occupancy is never counted as zero — point-limited dispatch stops with an explicit record (ADR-0027); since 0.3.1 items may target endpoint B/C with delivery contracts attached and HEAVY items enter the queue on a pre-enqueue plan-review PASS (ADR-0030) |
| Limited delivery B/C | lzy delivery request/status/act/readback |
Merge-to-main (B) and Pages live verification (C) via per-endpoint delivery contracts riding the UPS approval channel (ADR-0028): merge gated on dual B∧C authorization + PR head/base drift re-check + green CI, bound to the PR head, reads back the actual merge SHA and polls CI on it; C aligns the Pages build commit with the merge SHA and checks live HTTPS content against an expected marker; an intent ledger records identity before any external call and read-back classifies outcomes — no blind re-execution. Since 0.3.1 the queue orchestrates the chain (queue item → merge/verify after the goal finishes; completed only on a done read-back) and action parameters may come from the delivery contract (repo/base/branch/pr-title/pr-body, expect-marker, content-url, multi-page page: checks); approvals can be obtained at enqueue time (ADR-0030) |
| Complete migration machine | lzy migrate preview/apply/status |
Explicit legacy-tree migration (ADR-0029): read-only preview → six-family backup (sha256 manifest) → in-flight draft staging → validation → atomic switch, stamping the .lazyzcode/state.json version entry (written last = commit point); in-flight goals become drafts carrying authorization NONE with no scope (not directly registrable — old approvals never escalate); crash-safe and idempotent per task identity via a per-run journal; corrupt goal.json stops before any write, corrupt preserve-family records are warned and kept byte-exact; a live lease/process refuses migration; update/sync never migrate automatically |
| Migration preview | lzy migrate preview <root> |
Read-only scan of legacy goal records producing contract drafts with authorization: NONE — old approvals never upgrade into new authorizations |
| Cost report | lzy loop cost |
Points report from the engine's local billing ledger (standing coefficients + dated promo overlay; simplified-OR goal attribution with a human-review note; read-only) |
agents-md |
lzy agents-md |
Project-memory audit: qualifying directories and coverage gaps |
uninstall |
lzy uninstall |
Removes the deployed cache and the registry entry |
Engine and install state, enabled flags, hook syntax self-check (vm-parsed in a
worker, including hooks.json registry validation), node version floor,
hook-node resolution (the launcher's node fallback chain — nvm/homebrew on
POSIX, nvm-windows/Program Files on Windows — for GUI-launched sessions), the
lzy PATH shim, a payload-version cross-check (payload-ver: the cached
version directories versus the CLI's own package.json — the ADR-0012
intermediate-state self-check), .lazyzcode/ state hygiene, an H3R word-list payload check (h3r-words: the one word list both the CLI and the command-layer hook read — missing = warn; awake-time behavior splits by reader: the drive-side gate hard-rejects (throws), the command-layer hook fails open — ADR-0022's failure semantics), an attestation-trailer
check (attest-trailer: git-history Lzy-Attestation: trailers compared one-by-one against content sha256 of files in .lazyzcode/attestations/ — dangling warn names each, warn-only), a handoff-lane
usage counter (handoff-usage: registered versus consumed markers — a
difference means reset cleanup or bad markers, never lost handoffs), an
optional code-index probe (codegraph: user-level MCP config plus CLI
availability; absent = skip, never flips the exit code), a platform notice,
GLM plan rate-limit pressure (last 2 days of engine logs, read-only:
deduplicated 429 turns, fatal turns, longest sustained run, and an empirical
concurrency band — warn-only, never flips the exit code), transport-death
turns counted as a separate family (transport: request-never-reached-server
failures such as ENETDOWN, never fed into the concurrency math), content-moderation
stream kills counted as a separate family (content: provider content-filter
mid-stream kills such as 1301 — an in-place retry reproduces, never fed into
the concurrency math), a per-provider band line (band-by-provider:
completed-side clean buckets × 429 dirty buckets, emitted only when the
window has ≥1 429 and ≥2 providers — a provider with no 429 of its own gets
an honest "no dirty-face sample" row), a mixed-account caveat (provider-mix:
account-level advice pools 429 data across providers — one provider hitting
the wall says nothing about the others) and a model-tier advisory (cost: a
zero-429 window with a low rolling waterline suggests trying a lighter tier
for routine goals — advisory text only, never predicate math), a project-memory
adoption audit (agents-md, warn-only, with a staleness hint: ≥50 covered-dir
commits since the map's last commit suggests re-running init-deep), a claim
patrol for the open goal loop, and a headless-drive line (headless: engine
probe plus credential two-state — oauth credentials file or desktop-injected
config env; absent engine = skip, missing credentials = warn-only, 0.1.0) and —
0.2.0 — the unattended drive channel (drive: credential two-state, active
lease, run budget, and whether the open goal is drive-eligible; ADR-0020)
(claims: who claimed it, stuck markers; zero claims = nobody is pullable under claim-gated pull-back — warn-only),
an approval-record audit (approvals: recorded approvals counted with per-record shape validation, identity = file + at/sessionId fields — the ADR-0018 audit face), a contract authorization row (contract: the goal's bound contractHash has an approval on record with no later withdrawal; goals without a contract skip on the legacy planHash gate — ADR-0024), a project-manifest row (project: lzy.project.json parse, entry-present readiness, sha256 echo; skip without a manifest) and a migration census (migrate: legacy record family counts, version-entry presence, pointer to lzy migrate preview — apply is always explicit, never automatic; ADR-0029),
whether the host is a git repository (host-git: warn with git init guidance when not — evidence binds git trees, ADR-0019),
commit-ledger coverage (ledger: goal-era commits missing the Goal: trailer — warn-only),
a waterline line (rolling 5-hour point burn vs the self-calibrated nudge threshold, plus
its fail-open reason when sqlite3 is absent) and an orphan-wake idle-burn patrol for
unbound wake automations anchored here (skip when no mounts),
a lock contention line (lock acquisitions, how many had to wait, total and max wait,
and wait timeouts, measured against LOCK_WAIT_MS — skip without samples, warn once a
wait times out; readings are lower bounds),
and a suggested off-peak window for
unattended runs (schedule, derived from the same measured concentration
data and cross-checked against declared platform pricing peaks — skipped,
never guessed, when the data is silent). Fully local, zero telemetry, no new
configuration surface.
LazyZCode should be judged by what it actually installs: one plugin — two
skills (zw, init-deep), six hooks, three read-only agents — and the
lzy CLI.
| Trigger | Fires |
|---|---|
zw |
at the start of the prompt only |
lazyzcode:zw |
anywhere; the full-width colon : works too |
ulw / ultrawork |
anywhere, word-bounded |
Injection is conditional: an invocation engages the protocol, a mere mention
("how does the zw trigger work?") is ignored and answered directly.
- Plan gate. Plans are N/F checklists (
- [N1] …implementation items,- [F1] …final-verification items). Undecided items (TBD) are rejected; the plan must be decision-complete. HEAVY goals must additionally pass the plan-reviewer: aREVISEverdict refuses adoption and--forcecannot bypass it. - Evidence gate. Every F item needs evidence from a real surface (CLI
stdout, an HTTP response, a screenshot) bound to
git rev-parse HEAD^{tree}— commit first, capture after. Change the code and the evidence expires;finishrejects stale evidence and demands a re-capture on the current tree. - Continuation, bounded. While a loop is open, the Stop hook requests up to 2 continuations per session — deliberately reserving 1 of the engine's shared pool of 3 for background notifications. Counters are isolated per sessionId; any hook error fails open and never hijacks unrelated sessions.
Loop state lives in .lazyzcode/ (loop/goal.json, plans/), clearly
separated from the host's .zcode/. A finished loop frees its slot via
lzy loop reset.
Three read-only roles ship inside the plugin's agents/ directory; the engine
discovers them automatically:
| Role | Use it for |
|---|---|
lazyzcode:explorer |
Pre-plan reconnaissance; codegraph index guidance for large repos |
lazyzcode:plan-reviewer |
The plan review gate (decision-completeness, hidden risks, real F-item surfaces) |
lazyzcode:qa-executor |
Real-surface evidence capture; ego-browser/curl for web surfaces |
Spawn them through the Agent tool with the role as subagent_type — the child
runs read-only with that contract:
comment-checker watches Edit/Write output for TODO/FIXME/XXX/HACK
markers and debug residue (console.log, console.debug, debugger) and nudges through
additionalContext — inject-only, never blocks, capped at 5 hits per event,
and active only in workspaces with an open goal loop. SessionStart re-injects
loop state so a fresh session picks up where the last one left off.
lazyzcode:init-deep drafts a layered AGENTS.md map of the repo (root plus
qualifying subdirectories). You approve before anything is written; existing
files get patch suggestions only, and secrets or machine-local paths stay out.
ZCode reads AGENTS.md natively, so the map rides into every later session —
and HEAVY planning consults it before spending the plan gate. lzy agents-md
lists qualifying directories and coverage gaps.
The engine's built-in automation can wake a fresh session on a schedule with
zw continue (unattended: …). The wake protocol is continue-only: it never
registers a new goal and never adopts a plan — the decision-complete gate
stays human. It is bounded by the continuation budget, fatal-429 handling,
serial subagents, and ≥1-hour spacing, and lzy doctor's schedule line
derives an off-peak window from your measured rate-limit concentration hours,
cross-checked against the declared pricing-peak table.
[1302] rate limit(GLM plan): account-level concurrency limiting.lzy doctor'srate-limitline reports measured pressure and an empirical bound; keep one goal loop at a time, few parallel main sessions, and after a fatal 429 wait a few minutes, thenzw continue— state in.lazyzcode/survives.- Hooks do nothing at all: usually the engine's hook environment lacks
node(ZCode.app launched from the Dock).lzy doctor'shook-nodeline diagnoses it; the bundledrun-hooklauncher (with itsrun-hook.cmdtwin on Windows) falls back automatically (nvm/homebrew on POSIX, nvm-windows/Program Files on Windows). Details: docs/diagnostics/2026-09-07-hook-spawn-env.md. lzy: command not found: install globally (npm i -g lazyzcode) or callnode <repo>/cli/lzy.js …directly.
LazyZCode packages the lazycodex discipline workflow as a native ZCode plugin plus a lightweight CLI.
Think LazyVim for lazy.nvim — but for ZCode.
The harness part is discipline: a plan gate, evidence-bound completion, and a bounded continuation budget. ZCode already ships the skills/hooks/agents machinery; LazyZCode is the workflow that makes them finish what they start.
| Feature | Description |
|---|---|
| 🎯 Goal loop | Register → plan → execute → verify, as a CLI state machine that survives session restarts |
| 🚧 Plan gate | Decision-complete plans only; TBD rejected; HEAVY plans must pass the reviewer gate (REVISE refuses adoption) |
| 🔬 Evidence discipline | F-item evidence bound to a git tree hash; stale evidence cannot pass finish |
| 📦 Evidence bundle | --evidence-file attachments (hash-bound copies) and lzy loop export — finish auto-archives a <slug>.report.md |
| 🗂️ Project memory | init-deep drafts layered AGENTS.md maps; human-approved writes, lzy agents-md audits gaps |
| 🌙 Unattended | Scheduled wake-ups continue the open goal only, never start new ones; off-peak window from lzy doctor schedule (measured rate-limit ∩ pricing-peak cross-check) |
| 🪝 Bounded continuation | Stop hook pulls the agent back, max 2 per session, budget shared fairly with background notifications |
| ⌨️ Trigger words | zw / lazyzcode:zw / ulw / ultrawork, stratified matching, mention ≠ invocation |
| 🕵️ Read-only agents | explorer / plan-reviewer / qa-executor, auto-discovered by the engine |
| 💬 comment-checker | Advisory TODO/debug-residue nudges; never blocks |
🩺 lzy doctor |
Offline health report incl. hook-node resolution and rate-limit pressure |
| 🔒 Privacy & red lines | Zero telemetry; lzy never writes your config.json; all state local (declared exceptions: the user-private review usage ledger ~/.zcode/cli/lzy-usage/ and --workers sibling worktrees <dir>/<repo>-fast/ — see SECURITY.md) |
As of September 2026 the official ZCode marketplace lists 19 plugins and none of them is a discipline layer — so instead of a competitor table, here is what only LazyZCode ships, and the one capability we have not built yet.
| # | Only here | In one line |
|---|---|---|
| 1 | Tree-hash evidence binding | F-item evidence binds to git rev-parse HEAD^{tree} — change the code and old evidence is stale by construction |
| 2 | Engine-internal Stop pull-back | a lazy stop gets pulled back to work: at most 2 continuations per session, 1 of the engine's shared 3 reserved for background notifications |
| 3 | Handoff release | a lint-enforced handoff snapshot lets the agent wrap up cleanly — the next Stop releases once, without spending the continuation budget |
| 4 | Claim-scoped sessions | the pull-back only reaches sessions that claimed the goal; bystander sessions in the same repo are never hijacked; per-step claims coordinate multi-worker runs |
| 5 | Measured rate-limit triage | lzy doctor reads your own engine logs: deduplicated 429 turns, an empirical concurrency band, and an off-peak window cross-checked against declared pricing peaks |
| 6 | Failure families, not "unknown" | transport deaths (request never reached the server) and content-moderation kills (mid-stream; an in-place retry reproduces) are counted separately, never fed into the concurrency math |
| 7 | Known unknowns, mandatory | HEAVY plans must declare 1–3 unverified premises, each with a falsification path — "none" requires a one-line note of where you looked |
| 8 | Project memory with a staleness fingerprint | init-deep drafts layered AGENTS.md maps; a commit-lag signal says when the map has fallen behind |
| 9 | A review gate that cannot be forced | a REVISE verdict refuses plan adoption; --force does not bypass it |
| 10 | Zero telemetry by constitution | diagnostics are local-only, there is no configuration surface, and nothing phones home |
| 11 | Loop-complete machine attestation | every finish writes a LOOP_COMPLETE proof (plan hash, per-root trees, composite fingerprint, comparator verdict, report sha256) that survives reset; HEAVY goals additionally need a recorded comparator MATCH |
The one gap we own: a self-evolution loop (the harness improving its own discipline) is not built — it stays a recorded long-horizon item rather than shipping early.
Do not be surprised when LazyZCode refuses to celebrate. A plan checkbox is a
claim; only real-surface evidence is a fact. That is why F items must name the
surface they will capture (a CLI's stdout, an HTTP response, a screenshot), why
the evidence is bound to git rev-parse HEAD^{tree} (content snapshot of the
commit — the moment code changes, old evidence is stale by construction), and
why lzy loop finish re-checks freshness instead of trusting a summary. Tests
being green is not evidence; a test run is one surface among several.
The same philosophy sets the continuation budget. ZCode gives a session 3 stop-continuations, shared with background task notifications; LazyZCode's Stop hook spends at most 2 of them, per session, and fails open on any error — the loop is meant to pull work back across a lazy stop, not to trap the session.
LazyZCode is a plugin (the discipline layer) plus a CLI (the loop state machine). Zero npm dependencies, Node ≥ 24, pure ESM.
lazyzcode/
├── plugin/ → the lazyzcode plugin: skills/zw + skills/init-deep, hooks/ (6, via the run-hook launcher), agents/ (3)
├── core/ → shared logic: loop, installer, doctor, ratelimit, agentsmd, engine, git, paths, status, update, cost, dag, attempt, attest, runtime, drive, h3r, progress, headless, hostdb
├── cli/ → the lzy entry (cli/lzy.js) + syntax-check worker
├── test/ → contract tests (node:test, zero deps) + GitHub Actions (node 24)
└── docs/ → research notes, ADRs, five review rounds, diagnostics
Design rule of thumb: Skill > MCP > Tool > Hook. Anything that survives
being offline lives in skill text; hooks are the last resort. The installer
installs plugins and nothing else — enabling goes through the engine's official
plugins enable, so your config.json is never touched.
- Platform support boundary (ADR-0011): macOS, Windows and Linux are all supported; engine layouts are measured on each, the distribution matrix is arm64-live-verified (Windows 11 / Ubuntu ARM VMs), and x64 coverage follows the official download matrix by documentation. The CI matrix (node 24 × ubuntu/windows, four legs) stays green on main; three test families are explicitly skipped on win32 (kept until VM verification): SIGTERM kill receipt semantics, gh CLI parsing semantics, and EACCES permission-denial semantics (POSIX permission bits do not apply on win32) — skipped groups are a support boundary, not a verified surface (debt-G recheck 2026-09-25: the CI win32 legs run the rest of the suite green).
- Driving the engine headlessly (
--prompt) requires the desktop's injected model credentials; the mechanism is validated by probes, live headless acceptance is deferred.
What runs on your machine, where it installs, and what it deliberately does not defend against:
- Hooks execute local code. Six lifecycle events run this plugin's local Node scripts (UserPromptSubmit, SessionStart, Stop, PreToolUse, PostToolUse, PostToolUseFailure); their output is injected context for the model, not a sandbox boundary.
- Independent review OS sandbox (available since 0.6.0): macOS Seatbelt
applies when its probe passes and an allowed personal API key is available.
Otherwise, including Linux/Windows and OAuth-only setups, reviews use app-layer
isolation; the run record and doctor disclose the actual tier. In the OS sandbox,
Seatbelt restricts the review engine and descendants; candidate/factual inputs are read-only
and isolated HOME/tmp are writable. An environment allowlist and controlled proxy
restrict access to allowed API endpoints. HTTP checks the exact origin; HTTPS checks
CONNECT hostname:port, not tunneled SNI/Host/paths. DNS addresses are pinned at startup;
explicitly allowed local/private APIs remain reachable. An unresolved endpoint or
unavailable proxy refuses sandbox launch. Other drive/queue defaults are unchanged.
Cleanup targets the managed process group; descendants in independent groups can
survive, including ordinary host shell children. After SIGKILL, doctor reports
registered residues;
lzy review cleanup <runId>removes dead-owner configuration copies/tmp and does not prove all descendants have stopped. Allowed API credentials remain readable and the endpoint can receive data. This does not promise prevention of all exfiltration, complete descendant reclamation, review correctness or a hard spending cap. Scope and recovery. - Install footprint is the engine's official plugin cache — enabling flows
through the engine's official CLI, and LazyZCode never writes your
config.json. - Dual distribution chains, user-verifiable. npm: compare the published
shasum with
npm view lazyzcode dist.integrity. Marketplace: the manifest pins a commit sha, so the loaded payload is the pinned tree. - Threat-model boundary, stated plainly: LazyZCode guards against laziness (fake done, silent scope abandonment). Outside the dedicated review sandbox, local ledgers, approval records, and counters are readable/writable by any process with your permissions; integrity claims are enforced by protocol text plus the audit ring, not tamper-proof hardware.
MIT — see LICENSE.
The name and workflow are inspired by lazycodex (MIT); structure and installer patterns are borrowed within its license, with credit. oh-my-openagent (OmO) is SUL-1.0: only ideas were learned, no code or text was copied.
Agent({ "subagent_type": "lazyzcode:explorer", "prompt": "TASK: map the auth flow end to end." })