| name | hzl |
| description | OpenClaw's persistent task database. Coordinate sub-agents, checkpoint progress, survive session boundaries. |
| homepage | https://github.com/tmchow/hzl |
| metadata | {"openclaw":{"emoji":"🧾","homepage":"https://github.com/tmchow/hzl","requires":{"bins":["hzl"]},"install":[{"id":"brew","kind":"brew","package":"hzl","bins":["hzl"],"label":"Install HZL (Homebrew)"},{"id":"node","kind":"node","package":"hzl-cli","bins":["hzl"],"label":"Install HZL (npm)"}]}} |
HZL: Persistent task tracking for agents
HZL (https://github.com/tmchow/hzl) is a local-first task ledger (database-backed, optionally cloud-synced for backup) that an agent can use to:
- plan multi-step work into projects + tasks
- checkpoint progress (so work survives session boundaries)
- coordinate sub-agents or multiple coding tools with leases
- generate reliable status reports ("what's done vs what's left")
This skill teaches an agent how to use the hzl CLI.
When to use HZL
OpenClaw has NO native task tracking tools. Unlike Claude Code (which has TodoWrite) or Codex (which has update_plan), OpenClaw relies on memory and markdown files for tracking work. This makes HZL especially valuable for OpenClaw.
Use HZL by default for any non-trivial task tracking:
- Multi-step projects with real sequencing (dependencies) and handoffs
- Work that may outlive this session or span multiple tools/agents
- Orchestration: delegating work to sub-agents and needing recovery if they crash
- Anything where "resume exactly where we left off" matters
- Any work you want to persist beyond this session
- Any work that needs structure (nesting, dependencies, progress tracking)
- Any work that benefits from a durable record of decisions or ownership
Multi-session or multi-agent work are common reasons to use HZL, not requirements.
Use HZL for single-session, single-agent work when the task is non-trivial.
Why HZL is the right choice for OpenClaw:
Without HZL, OpenClaw tracks tasks in-context (burns space, fragments during compaction) or in markdown files (requires manual management, no nesting/dependencies, no dashboard). HZL provides:
- Persistent storage that survives session boundaries
- Nesting (parent tasks + subtasks) and dependencies
- Web dashboard for human visibility (
hzl serve)
- Leases for multi-agent coordination
- Checkpoints for progress recovery
Only skip HZL for:
- Truly trivial, one-step tasks you will complete immediately in this session
- Time-based reminders/alerts (use OpenClaw Cron instead)
- Longform notes or knowledge capture (use a notes or memory system)
Rule of thumb: If you feel tempted to make a multi-step plan or there is any chance you will not finish in this session, use HZL.
Example: "Investigate failing tests and fix root cause" -> use HZL because it likely involves multiple subtasks, even if you expect to finish within a session.
Personal tasks: HZL is not a polished human to-do app, but it is usable for personal task tracking, and it can also serve as a backend for a lightweight UI.
Core concepts
- Project: stable container. For OpenClaw, use a single
openclaw project—this keeps hzl task next simple. Check hzl project list before creating.
- Task: top-level work item. For multi-step requests, this becomes a parent task.
- Subtask: breakdown of a task into parts (
--parent <id>). Max 1 level of nesting. Parent tasks are organizational containers—never returned by hzl task next.
- Checkpoint: short progress snapshot to support recovery
- Lease: time-limited claim (prevents orphaned work in multi-agent flows)
Anti-pattern: Project Sprawl
Use a single openclaw project. Requests and initiatives become parent tasks, not new projects.
Wrong (creates sprawl):
hzl project create "garage-sensors"
hzl project create "query-perf"
Correct (single project, parent tasks):
hzl project list
hzl task add "Install garage sensors" -P openclaw
hzl task add "Wire sensor to hub" --parent abc123
hzl task add "Configure alerts" --parent abc123
Why this matters:
- Projects accumulate forever; you'll have dozens of abandoned one-off projects
hzl task next --project X requires knowing which project to query
- With a single project,
hzl task next --project openclaw always works
Sizing Parent Tasks
HZL supports one level of nesting (parent → subtasks). Scope parent tasks to completable outcomes.
The completability test: "I finished [parent task]" should describe a real outcome.
- ✓ "Finished installing garage motion sensors"
- ✓ "Finished fixing query performance"
- ✗ "Finished home automation" (open-ended domain, never done)
- ✗ "Finished backend work" (if frontend still pending for feature to ship)
Scope by problem, not technical layer. A full-stack feature (frontend + backend + tests) is usually one parent if it ships together.
Split into multiple parents when:
- Parts deliver independent value (can ship separately)
- You're solving distinct problems that happen to be related
Adding context: Use -d for details, -l for reference docs:
hzl task add "Install garage sensors" -P openclaw \
-d "Per linked spec. Mount sensors at 7ft height." \
-l docs/sensor-spec.md,https://example.com/wiring-guide
Don't duplicate specs into descriptions—this creates drift. Reference docs instead.
If no docs exist, include enough detail for another agent to complete the task:
hzl task add "Configure motion alerts" -P openclaw -d "$(cat <<'EOF'
Trigger alert when motion detected between 10pm-6am.
Use Home Assistant automation. Notify via Pushover.
EOF
)"
Description supports markdown (16KB max).
⚠️ DESTRUCTIVE COMMANDS - READ CAREFULLY
The following commands PERMANENTLY DELETE HZL DATA and cannot be undone:
| Command | Effect |
|---|
hzl init --force | DELETES ALL DATA. Prompts for confirmation. |
hzl init --force --yes | DELETES ALL DATA WITHOUT CONFIRMATION. Extremely dangerous. |
hzl task prune ... --yes | PERMANENTLY DELETES old done/archived tasks and their event history. |
AI agents: NEVER run these commands unless the user EXPLICITLY asks you to delete data.
hzl init --force deletes the entire event database: all projects, tasks, checkpoints, and history
hzl task prune deletes only tasks in terminal states (done/archived) older than the specified age
- There is NO undo. There is NO recovery without a backup.
Core Workflows
Setup:
hzl project list
hzl project create openclaw
Adding work:
hzl task add "Feature X" -P openclaw -s ready
hzl task add "Subtask A" --parent <id>
hzl task add "Subtask B" --parent <id> --depends-on <subtask-a-id>
Working on a task:
hzl task next -P openclaw
hzl task next --parent <id>
hzl task next -P openclaw --claim
hzl task claim <id>
hzl task checkpoint <id> "milestone X"
Changing status:
hzl task set-status <id> ready
hzl task set-status <id> backlog
Statuses: backlog → ready → in_progress → done (or blocked)
When blocked:
hzl task block <id> --comment "Waiting for API keys from DevOps"
hzl task unblock <id>
Finishing work:
hzl task comment <id> "Implemented X, tested Y"
hzl task complete <id>
hzl task show <parent-id> --json
hzl task complete <parent-id>
Troubleshooting:
| Error | Fix |
|---|
| "not claimable (status: backlog)" | hzl task set-status <id> ready |
| "Cannot complete: status is X" | Claim first: hzl task claim <id> |
Extended Reference
hzl init
hzl init --reset-config
hzl status
hzl doctor
hzl task add "<title>" -P openclaw --priority 2 --tags backend,auth
hzl task add "<title>" -P openclaw --depends-on <other-id>
hzl task add "<title>" -P openclaw -s in_progress --assignee <name>
hzl task list -P openclaw --available
hzl task list --parent <id>
hzl task list --root
hzl task add-dep <task-id> <depends-on-id>
hzl validate
hzl serve
hzl serve --host 127.0.0.1
hzl serve --background
hzl serve --status
hzl serve --stop
hzl task claim <id> --assignee <agent-id> --lease 30
hzl task stuck
hzl task steal <id> --if-expired --author <agent-id>
Tip: When a tool needs to parse output, prefer --json.
Authorship tracking
HZL tracks authorship at two levels:
| Concept | What it tracks | Set by |
|---|
| Assignee | Who owns the task | --assignee on claim or add |
| Event author | Who performed an action | --author on other commands |
The --assignee flag on claim and add (with -s in_progress) sets task ownership. The --author flag on other commands (checkpoint, comment, block, etc.) records who performed each action:
hzl task claim 1 --assignee alice
hzl task checkpoint 1 "Reviewed the code" --author bob
For AI agents that need session tracking, use --agent-id on claim:
hzl task claim 1 --assignee "Claude Code" --agent-id "session-abc123"
Recommended patterns
Start a multi-step project
- Create (or reuse) a stable project name.
- Decompose into tasks.
- Use dependencies to encode sequencing, not just priority.
- Validate.
hzl project create myapp-auth
hzl task add "Clarify requirements + acceptance criteria" -P myapp-auth --priority 5
hzl task add "Design API + data model" -P myapp-auth --priority 4 --depends-on <reqs-id>
hzl task add "Implement endpoints" -P myapp-auth --priority 3 --depends-on <design-id>
hzl task add "Write tests" -P myapp-auth --priority 2 --depends-on <impl-id>
hzl task add "Docs + rollout plan" -P myapp-auth --priority 1 --depends-on <tests-id>
hzl validate
Work a task with checkpoints
Checkpoint at notable milestones or before pausing work. A checkpoint should be short and operational:
- what you accomplished
- what's next (if continuing)
hzl task claim <id> --assignee orchestrator
hzl task checkpoint <id> "Implemented login flow. Next: add token refresh." --progress 50
hzl task checkpoint <id> "Added token refresh. Testing complete." --progress 100
hzl task complete <id>
You can also set progress without a checkpoint:
hzl task progress <id> 75
Handle blocked tasks
When stuck on external dependencies, mark the task as blocked:
hzl task claim <id> --assignee orchestrator
hzl task checkpoint <id> "Implemented login flow. Blocked: need API key for staging."
hzl task block <id> --comment "Blocked: waiting for staging API key from DevOps"
hzl task unblock <id> --comment "Unblocked: received API key from DevOps"
hzl task checkpoint <id> "Got API key, resuming work"
hzl task complete <id>
Comment best practices: Include context about the action, not just the state:
- Good: "Blocked: waiting for API keys from infra team"
- Good: "Unblocked: keys received, resuming work"
- Bad: "waiting for API keys" (missing action context)
Blocked tasks stay visible in the dashboard (Blocked column) and keep their assignee, but don't appear in --available lists.
Coordinate sub-agents with leases
Use leases when delegating, so you can detect abandoned work and recover.
hzl task add "Implement REST endpoints" -P myapp-auth --priority 3 --json
hzl task claim <id> --assignee subagent-claude-code --lease 30
Delegate with explicit instructions:
- claim the task (with their author id)
- checkpoint progress as they go
- complete when done
Monitor:
hzl task show <id> --json
hzl task stuck
hzl task steal <id> --if-expired --author orchestrator
Break down work with subtasks
Use parent/subtask hierarchy to organize complex work:
hzl task add "Implement vacation booking" -P portland-trip --priority 2
hzl task add "Research flights" --parent abc123
hzl task add "Book hotel" --parent abc123 --depends-on <flights-id>
hzl task add "Plan activities" --parent abc123
hzl task show abc123
hzl task next --parent abc123
Important: hzl task next only returns leaf tasks (tasks without children). Parent tasks are organizational containers—they are never returned as "next available work."
Finishing subtasks: After completing each subtask, check if the parent has remaining work:
hzl task complete <subtask-id>
hzl task show abc123 --json
hzl task complete abc123
Web Dashboard
HZL includes a built-in Kanban dashboard for monitoring task state. The dashboard shows tasks in columns (Backlog → Blocked → Ready → In Progress → Done), with filtering by date and project.
Setting up the dashboard (recommended for OpenClaw)
For always-on access on your OpenClaw box, set up as a systemd service (Linux only):
mkdir -p ~/.config/systemd/user
hzl serve --print-systemd > ~/.config/systemd/user/hzl-web.service
systemctl --user daemon-reload
systemctl --user enable --now hzl-web
loginctl enable-linger $USER
systemctl --user status hzl-web
The dashboard will be available at http://<your-box>:3456 (accessible over Tailscale).
To use a different port:
hzl serve --port 8080 --print-systemd > ~/.config/systemd/user/hzl-web.service
macOS note: systemd is Linux-only. On macOS, use hzl serve --background or create a launchd plist manually.
Quick commands
hzl serve
hzl serve --background
hzl serve --status
hzl serve --stop
hzl serve --host 127.0.0.1
Use --background for temporary sessions. Use systemd for always-on access.
Best Practices
- Always use
--json for programmatic output
- Checkpoint at milestones or before pausing work
- Check for comments before completing tasks
- Use a single
openclaw project for all work
- Use dependencies to express sequencing, not priority
- Use leases for long-running work to enable stuck detection
- Review checkpoints before stealing stuck tasks
What HZL Does Not Do
HZL is deliberately limited:
- No orchestration - Does not spawn agents or assign work
- No task decomposition - Does not break down tasks automatically
- No smart scheduling - Uses simple priority + FIFO ordering
These are features for your orchestration layer, not for the task tracker.
OpenClaw-specific notes
- Run
hzl ... via the Exec tool.
- OpenClaw skill gating checks
requires.bins on the host at skill load time. If sandboxing is enabled, the binary must also exist inside the sandbox container too. Install it via agents.defaults.sandbox.docker.setupCommand (or use a custom image).
- If multiple agents share the same HZL database, use distinct
--assignee ids (for example: orchestrator, subagent-claude, subagent-gemini) and rely on leases to avoid collisions.