with one click
hzl
// OpenClaw's persistent task database. Coordinate sub-agents, checkpoint progress, survive session boundaries.
// OpenClaw's persistent task database. Coordinate sub-agents, checkpoint progress, survive session boundaries.
[HINT] Download the complete skill directory including SKILL.md and all related files
| 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 (https://github.com/tmchow/hzl) is a local-first task ledger (database-backed, optionally cloud-synced for backup) that an agent can use to:
This skill teaches an agent how to use the hzl CLI.
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-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:
hzl serve)Only skip HZL for:
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.
openclaw project—this keeps hzl task next simple. Check hzl project list before creating.--parent <id>). Max 1 level of nesting. Parent tasks are organizational containers—never returned by hzl task next.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:
hzl task next --project X requires knowing which project to queryhzl task next --project openclaw always worksHZL 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.
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:
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).
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 historyhzl task prune deletes only tasks in terminal states (done/archived) older than the specified ageSetup:
hzl project list # Always check first
hzl project create openclaw # Only if needed
Adding work:
hzl task add "Feature X" -P openclaw -s ready # Ready to claim
hzl task add "Subtask A" --parent <id> # Subtask
hzl task add "Subtask B" --parent <id> --depends-on <subtask-a-id> # With dependency
Working on a task:
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
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> # 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> |
# 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.
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:
hzl task claim 1 --assignee "Claude Code" --agent-id "session-abc123"
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
Checkpoint at notable milestones or before pausing work. A checkpoint should be short and operational:
hzl task claim <id> --assignee orchestrator
# ...do work...
hzl task checkpoint <id> "Implemented login flow. Next: add token refresh." --progress 50
# ...more work...
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
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"
# Later, when unblocked:
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:
Blocked tasks stay visible in the dashboard (Blocked column) and keep their assignee, but don't appear in --available lists.
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:
Monitor:
hzl task show <id> --json
hzl task stuck
hzl task steal <id> --if-expired --author orchestrator
Use parent/subtask hierarchy to organize complex work:
# Create parent task
hzl task add "Implement vacation booking" -P portland-trip --priority 2
# → abc123
# Create subtasks (project inherited automatically)
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
# View breakdown
hzl task show abc123
# Work through subtasks
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>
# Check parent status
hzl task show abc123 --json # Any subtasks left?
hzl task complete abc123 # If all done, complete parent
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.
For always-on access on your OpenClaw box, set up as a systemd service (Linux only):
# Create the systemd user directory if needed
mkdir -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).
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.
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.
--json for programmatic outputopenclaw project for all workHZL is deliberately limited:
These are features for your orchestration layer, not for the task tracker.
hzl ... via the Exec tool.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).--assignee ids (for example: orchestrator, subagent-claude, subagent-gemini) and rely on leases to avoid collisions.