External task ledger for coding agents and OpenClaw.
Claude Code has Tasks. If you use Claude Code for short, self-contained work, that's probably enough.
HZL is for when work outlives a single session: days-long projects, switching between Claude Code and Codex, OpenClaw juggling parallel workstreams.
📚 Full Documentation — Concepts, scenarios, and tutorials
Coding agents (Claude Code, Codex, Gemini)
You're working across several projects over days or weeks. You switch between agents. Each has its own task tracking (or none).
HZL is the shared ledger underneath. Claim a task in Claude Code, pick it up in Codex tomorrow. One source of truth across tools and sessions.
OpenClaw
OpenClaw has tools for user memory—context, preferences, past chats. It doesn't have a tool for tracking task execution state: workstreams, dependencies, checkpoints.
That all lives in-context today. It burns space. It fragments when chats compact.
HZL fills that gap. Say you ask OpenClaw to plan a family vacation—flights, hotels, activities, reservations. That's multiple tasks with dependencies (can't book hotels until you know the dates). Instead of tracking all of it in the chat, OpenClaw creates tasks in HZL:
hzl task list --project family-vacation --available --json
{"tasks":[{"task_id":"t_abc123","title":"Book hotel","project":"family-vacation","status":"ready","priority":3,"created_at":"2025-01-15T10:00:00.000Z"}],"total":1}OpenClaw queries HZL, sees what's unblocked, and picks up the next task—without reconstructing state from a compacted chat. If you ever run multiple OpenClaw instances, they coordinate through the same ledger.
Local-first with built-in cloud sync
Fast reads and writes to local SQLite. Enable sync to Turso with one command (hzl init --sync-url ...) for automatic backup and multi-device access.
Also
- Leases: time-limited claims that expire, so callers can find and reclaim stuck work
- Checkpoints: save progress notes so work can resume after interruption
- Event history: full audit trail of what happened
Using OpenClaw? Start here: OpenClaw integration
Using Claude Code, Codex, or Gemini? See: Using HZL with coding agents
Data is stored in SQLite. Default location: $XDG_DATA_HOME/hzl/ (fallback ~/.local/share/hzl/); Windows: %LOCALAPPDATA%\\hzl\\. Contains events.db (source of truth) and cache.db (projections).
Because most task trackers are built for humans.
HZL is built for agents:
- It is backend-first, not UI-first. Think "task database with a CLI," not "another Trello."
- It is model-agnostic. Your tasks live outside any one vendor's memory or chat history.
- It is multi-agent safe. Leases prevent orphaned work and enable clean handoffs.
- It is resumable. Checkpoints let an agent crash, reboot, or swap models and keep going.
If you already have a favorite human todo app, keep it. If you need a shared task state that multiple agents can read/write, that is HZL.
flowchart LR
You[You] --> OC["OpenClaw (orchestrator)"]
OC --> Tools["OpenClaw tools<br/>(browser, exec, email, etc.)"]
OC <--> HZL[(HZL task ledger)]
OC --> S1[Claude Code]
OC --> S2[Codex / other]
S1 <--> HZL
S2 <--> HZL
OpenClaw coordinates the work. HZL is the shared, durable task board that OpenClaw and its sub-agents can use across sessions.
flowchart LR
U[You] --> O["Orchestrator (human or agent)"]
O <--> HZL[(HZL)]
O --> C[Claude Code]
O --> X[Codex]
O --> G[Gemini]
C <--> HZL
X <--> HZL
G <--> HZL
Same idea: once you are switching tools/models, you need a shared ledger.
flowchart LR
U[You] --> A["Coding agent<br>(Claude Code, Codex, etc)"]
A <--> HZL
A --> R[Repo / files]
Use HZL to persist "what's next" and "what changed" between sessions.
flowchart LR
UI[Lightweight web app] --> HZL
Agents[Agents + scripts] --> HZL
HZL includes a basic Kanban dashboard for human visibility. For richer interfaces, build your own frontend using hzl-core directly—HZL stays the durable backend that both humans and agents can use.
Requires Node.js 22.14+.
brew tap tmchow/hzl
brew install hzlnpm install -g hzl-cli
hzl initSync with a Turso database for multi-device/multi-agent access:
hzl init --sync-url libsql://<db>.turso.io --auth-token <token>hzl project create portland-trip
hzl task add "Check calendars for March weekends" -P portland-trip --priority 5
hzl task add "Research neighborhoods + activities" -P portland-trip --priority 4
hzl task add "Shortlist 2-3 weekend options" -P portland-trip --priority 3 \
--depends-on <calendar-task-id> --depends-on <research-task-id>hzl task claim <calendar-task-id> --author trevin-agent
hzl task checkpoint <calendar-task-id> "Found 3 options: Mar 7-9, 14-16, 21-23"
hzl task complete <calendar-task-id>Tasks stay lightweight. Use --links to reference design docs, brainstorms, or specs:
# Create a task that links to context documents
hzl task add "Implement auth flow per design" -P myapp --priority 3 \
--links docs/designs/auth-flow.md \
--links docs/brainstorm/2026-01-auth-options.md
# The agent reads linked files for context, task stays focused on the work
hzl task show <id> --json
# → { "links": ["docs/designs/auth-flow.md", "https://somedomain/resource.md"], ... }This pattern keeps tasks actionable while pointing agents to richer context stored elsewhere.
hzl task show <id> --json
hzl task next --project portland-trip --jsonHZL is optimized for "do work, report progress, unblock the next step."
If you need time-based reminders, pair HZL with a scheduler (cron, OpenClaw cron, etc.).
A checkpoint is a compact, durable record of what happened:
- what you tried
- what you found
- what's still missing
- links, commands, or file paths needed to resume
Dependencies are how an agent avoids premature work:
- "Don't search flights before you know dates."
- "Don't open a PR before tests pass."
Leases are time-limited claims:
- A worker agent claims a task with
--lease 30 - If it disappears, the lease expires
- Another agent can detect stuck work and take over
HZL uses a local-first architecture. You always read/write to a fast local database. Sync happens in the background via Turso/libSQL.
flowchart TD
CLI[User / Agent CLI]
subgraph Local["Local Machine"]
Cache[(cache.db<br/>Reads)]
Events[(events.db<br/>Writes)]
Sync[Sync Engine]
end
Cloud[(Turso / Cloud)]
CLI -->|Read| Cache
CLI -->|Write| Events
Events -->|Rebuild| Cache
Events <-->|Sync| Sync
Sync <-->|Replication| Cloud
Conventions that help:
- Use consistent author IDs:
openclaw,claude-code,codex,gemini, etc. - Claim tasks before work.
- Checkpoint whenever you learn something that would be painful to rediscover.
Example handoff:
# Orchestrator creates task
hzl task add "Implement REST API endpoints" -P myapp --priority 2
TASK_ID=<id>
# Worker agent claims with a lease
hzl task claim "$TASK_ID" --author claude-code --lease 30
hzl task checkpoint "$TASK_ID" "Endpoints scaffolded; next: auth middleware"
hzl task complete "$TASK_ID"HZL supports one level of parent/subtask hierarchy for organizing related work.
Key behavior: Parent tasks are organizational containers, not actionable work.
When you call hzl task next, only leaf tasks (tasks without children) are returned. Parent tasks are never returned because they represent the umbrella—work happens on the subtasks.
# Create parent task
hzl task add "Implement user authentication" -P myapp --priority 2
# → Created task abc123
# Create subtasks (project inherited automatically from parent)
hzl task add "Add login endpoint" --parent abc123
hzl task add "Add logout endpoint" --parent abc123
hzl task add "Add session management" --parent abc123
# View the breakdown
hzl task show abc123
# Shows task details plus list of subtasks
# Get next available subtask (parent is never returned)
hzl task next --project myapp
# → [def456] Add login endpoint
# Scope work to a specific parent's subtasks
hzl task next --parent abc123
# → [def456] Add login endpoint
# When all subtasks done, manually complete the parent
hzl task complete abc123Constraints:
- Maximum 1 level of nesting (subtasks cannot have their own subtasks)
- Subtasks are always in the same project as parent (auto-inherited)
- Moving a parent moves all subtasks atomically
Filtering:
# See all subtasks of a task
hzl task list --parent abc123
# See only top-level tasks (no parent)
hzl task list --root
# Combine with other filters
hzl task list --root --status readyArchiving:
# Archive parent with all subtasks
hzl task archive abc123 --cascade
# Archive parent only (subtasks promoted to top-level)
hzl task archive abc123 --orphanHZL can track personal tasks and has the advantage of centralizing agent and personal tasks. This enables scenarios like OpenClaw assigning you tasks without needing to sync with other todo systems.
HZL itself is not trying to be a polished, human-first todo app. You bring other pieces for that.
If you want a todo app, build or use a UI:
- a tiny web app
- a TUI wrapper
- a menu bar widget
HZL stays the storage layer and concurrency-safe ledger underneath.
Why HZL when your agent already has task tracking?
Many coding agents (like Claude Code) have built-in task management. HZL complements rather than replaces it:
- Cross-agent workflows: If you use Claude Code and Codex and Gemini, each has its own task system. HZL is the shared ledger they can all read/write.
- Session persistence: Built-in task trackers often reset between sessions. HZL persists to disk (and optionally to cloud).
- Orchestration: When one agent delegates to another, HZL provides the handoff mechanism (claim, checkpoint, complete).
- Backup: With cloud sync enabled, your task state survives machine failures.
If you only ever use one agent and never need cross-session persistence, the built-in tracker is fine. Once you need durability or multi-agent coordination, reach for HZL.
If your coding agent supports an instruction file (for example CLAUDE.md, AGENTS.md, GEMINI.md, etc.), add a short policy so the agent reaches for HZL consistently.
### HZL task ledger (external task tracking for multi-session/multi-agent work)
HZL is an external task database. Use it when work outlives this session or involves other agents.
Built-in task tracking (if available) is fine for single-session work you'll complete now.
**When to use HZL:**
- Work spanning multiple sessions or days
- Coordination with other agents (Claude Code ↔ Codex ↔ Gemini)
- Delegating to sub-agents with explicit handoff
- User explicitly asks to track work in HZL
**When NOT to use HZL:**
- Single-session work you'll complete in this conversation
- User hasn't mentioned persistence or multi-agent needs
**Structure:**
- **Project** = stable container (typically one per repo or long-running initiative). Check `hzl project list` before creating.
- **Task** = top-level work item (often a feature). Use `--depends-on` to sequence separate tasks.
- **Subtask** = breakdown of a task into parts (`--parent <id>`). Max 1 level of nesting.
**Workflow:**
1. `hzl project list` to find existing, or `hzl project create <name>`
2. Add tasks. Use `--depends-on` for sequencing, `--parent` for breakdown, `--links` for context docs.
3. Claim before work, checkpoint progress, complete when done.
4. Use `--json` for scripted output.
**Key commands:**
- `hzl task add "<title>" -P <project> [--depends-on <id>] [--parent <id>] [--links <file>]`
- `hzl task claim <id> --author claude-code [--lease 30]`
- `hzl task checkpoint <id> "<progress>"`
- `hzl task complete <id>`
- `hzl task next --project <project>` (returns next available; never returns parent tasks)That snippet is intentionally concise. The goal is clear triggers and structure, not ceremony.
HZL includes a Claude Code plugin marketplace with skills that help agents work effectively with HZL.
# Add the marketplace
/plugin marketplace add tmchow/hzl
# Install the skills plugin
/plugin install hzl-skills@hzl-marketplaceSee packages/hzl-marketplace for details.
OpenClaw is a self-hosted AI assistant that can coordinate tools and sub-agents. HZL fits well as the task ledger that OpenClaw (and its sub-agents) can share.
Copy/paste this into an OpenClaw chat (single prompt):
Install HZL from https://github.com/tmchow/hzl and run hzl init. Install the HZL skill from https://www.clawhub.ai/tmchow/hzl. Then append the HZL policy from https://raw.githubusercontent.com/tmchow/hzl/main/docs/openclaw/tools-prompt.md to my TOOLS.md.
- Install HZL on the machine running OpenClaw:
npm install -g hzl-cli
hzl init-
Install the HZL skill from https://www.clawhub.ai/tmchow/hzl
Skill source (for reference only):docs/openclaw/skill-hzl.md -
Teach OpenClaw when to use HZL (important):
- Copy/paste from:
docs/openclaw/tools-prompt.md - Or tell OpenClaw to add this policy to
TOOLS.md:
- Copy/paste from:
HZL is a tool available to you for task management in certain cases. I want you to add this information to your TOOLS.md in the right way so you remember how to use it:
https://raw.githubusercontent.com/tmchow/hzl/main/docs/openclaw/tools-prompt.md
- work has multiple steps and you want explicit sequencing
- work spans multiple sessions (resume tomorrow with confidence)
- you are coordinating multiple agents or model providers
- you need durable status reporting (done / in progress / blocked / next)
- you want a task ledger your own UI can sit on top of
- you need time-based reminders or notifications (use a scheduler + a notifier)
- you need rich human workflow features (due dates, recurring tasks, calendar views)
- you are tracking an org-wide backlog (GitHub/Jira/etc. may be a better fit)
# Setup
hzl init # Initialize database (add --sync-url for cloud)
hzl init --reset-config # Reset config to default database location
# Projects
hzl project create <name> # Create a project
hzl project list # List all projects
# Tasks
hzl task add "<title>" -P <project> # Create task (--depends-on, --links, --priority)
hzl task list --project <project> # List tasks (--available for claimable only)
hzl task next --project <project> # Get highest priority available task
# Working
hzl task claim <id> --author <name> # Claim task (--lease <minutes> for expiry)
hzl task checkpoint <id> "<message>" # Save progress snapshot
hzl task complete <id> # Mark done
# Coordination
hzl task stuck # Find expired leases
hzl task steal <id> --if-expired # Take over abandoned task
hzl task show <id> --json # Task details (--json for scripting)
# Subtasks (organization)
hzl task add "<title>" --parent <id> # Create subtask (inherits project)
hzl task list --parent <id> # List subtasks of a task
hzl task list --root # List only top-level tasks
hzl task next --parent <id> # Next available subtask
hzl task show <id> # Shows subtasks inline
hzl task archive <id> --cascade # Archive parent and all subtasks
hzl task archive <id> --orphan # Archive parent, promote subtasks
# Diagnostics
hzl sync # Sync with cloud (if configured)
hzl status # Show database and sync state
hzl doctor # Health checks
# ⚠️ DESTRUCTIVE - deletes all data
hzl init --force # Prompts for confirmation before deleting
hzl init --force --yes # Deletes WITHOUT confirmation (dangerous)
# Web Dashboard
hzl serve # Start dashboard (network accessible)
hzl serve --port 8080 # Custom port
hzl serve --host 127.0.0.1 # Restrict to localhost only
hzl serve --background # Fork to background
hzl serve --stop # Stop background server
hzl serve --status # Check if runningHZL includes a lightweight Kanban dashboard for monitoring tasks in near real-time.
hzl serve # Start on port 3456 (network accessible by default)
hzl serve --host 127.0.0.1 # Restrict to localhost onlyOpen http://localhost:3456 to see:
- Kanban board with columns: Backlog → Blocked → Ready → In Progress → Done
- Date filtering: Today, Last 3d, 7d, 14d, 30d
- Project filtering: Focus on a single project
- Task details: Click any card to see description, comments, and checkpoints
- Activity panel: Recent status changes and events
- Mobile support: Tabs layout on smaller screens
The dashboard polls automatically (configurable 1-30s interval) and pauses when the tab is hidden.
Run the dashboard as a background process:
hzl serve --background # Fork to background, write PID
hzl serve --status # Check if running
hzl serve --stop # Stop the background serverFor always-on access (e.g., on an OpenClaw box via Tailscale):
hzl serve --print-systemd > ~/.config/systemd/user/hzl-web.service
systemctl --user daemon-reload
systemctl --user enable --now hzl-webThe server binds to 0.0.0.0 by default, making it accessible over the network (including Tailscale). Use --host 127.0.0.1 to restrict to localhost only.
HZL is a monorepo with three packages:
| Package | Description | Install |
|---|---|---|
hzl-cli |
CLI for task management (hzl command) |
brew install hzlnpm install -g hzl-cli |
hzl-core |
Core library for programmatic use | npm install hzl-core |
hzl-web |
Web server and Kanban dashboard | npm install hzl-web |
Most users should install hzl-cli. Use hzl-core or hzl-web directly if you're building your own tooling or UI on top of HZL.
MIT