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
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"# Now you have to track which project to query
Correct (single project, parent tasks):
# Check for existing project first
hzl project list
# Use single openclaw project
hzl task add "Install garage sensors" -P openclaw
# → Created task abc123
hzl task add "Wire sensor to hub" --parent abc123
hzl task add "Configure alerts" --parent abc123
# hzl task next --project openclaw always works
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 next -P openclaw # Next available task
hzl task next --parent <id> # Next subtask of parent
hzl task next -P openclaw --claim # Find and claim in one step
hzl task claim <id> # Claim specific task
hzl task checkpoint <id> "milestone X"# Notable progress or before pausing
Changing status:
hzl task set-status <id> ready # Make claimable (from backlog)
hzl task set-status <id> backlog # Move back to planning
hzl task block <id> --comment "Waiting for API keys from DevOps"
hzl task unblock <id> # When resolved
Finishing work:
hzl task comment <id> "Implemented X, tested Y"# Optional: final notes
hzl task complete <id>
# After completing a subtask, check parent:
hzl task show <parent-id> --json # Any subtasks left?
hzl task complete <parent-id> # If all done, complete parent
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
# Setup
hzl init # Initialize (safe, won't overwrite)
hzl init --reset-config # Reset config to default location
hzl status # Database mode, paths, sync state
hzl doctor # Health check for debugging# Create with options
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> # Create and claim# List and find
hzl task list -P openclaw --available # Ready tasks with met dependencies
hzl task list --parent <id> # Subtasks of a parent
hzl task list --root # Top-level tasks only# Dependencies
hzl task add-dep <task-id> <depends-on-id>
hzl validate # Check for circular dependencies# Web Dashboard
hzl serve # Start on port 3456 (network accessible)
hzl serve --host 127.0.0.1 # Restrict to localhost only
hzl serve --background # Fork to background
hzl serve --status # Check if running
hzl serve --stop # Stop background server# Multi-agent recovery
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:
# Alice owns the task
hzl task claim 1 --assignee alice
# Bob adds a checkpoint (doesn't change ownership)
hzl task checkpoint 1 "Reviewed the code" --author bob
# Task is still assigned to Alice, but checkpoint was recorded by Bob
For AI agents that need session tracking, use --agent-id on claim:
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>
# Check parent status
hzl task show abc123 --json # Any subtasks left?
hzl task complete abc123 # If all done, complete parent
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):
# Create the systemd user directory if neededmkdir -p ~/.config/systemd/user
# Generate and install the service file
hzl serve --print-systemd > ~/.config/systemd/user/hzl-web.service
# Enable and start
systemctl --user daemon-reload
systemctl --user enable --now hzl-web
# IMPORTANT: Enable lingering so the service runs even when logged out
loginctl enable-linger $USER# Verify it's running
systemctl --user status hzl-web
The dashboard will be available at http://<your-box>:3456 (accessible over Tailscale).
macOS note: systemd is Linux-only. On macOS, use hzl serve --background or create a launchd plist manually.
Quick commands
hzl serve # Start in foreground (port 3456)
hzl serve --background # Fork to background process
hzl serve --status # Check if background server is running
hzl serve --stop # Stop background server
hzl serve --host 127.0.0.1 # Restrict to localhost only
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.