hzl-cli 1.5.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +307 -127
- package/dist/__tests__/integration/cli-integration.test.js +10 -9
- package/dist/__tests__/integration/cli-integration.test.js.map +1 -1
- package/dist/__tests__/integration/config.test.js +1 -1
- package/dist/__tests__/integration/config.test.js.map +1 -1
- package/dist/__tests__/integration/helpers.d.ts +1 -0
- package/dist/__tests__/integration/helpers.d.ts.map +1 -1
- package/dist/__tests__/integration/helpers.js +2 -0
- package/dist/__tests__/integration/helpers.js.map +1 -1
- package/dist/__tests__/integration/project-workflow.test.js +6 -5
- package/dist/__tests__/integration/project-workflow.test.js.map +1 -1
- package/dist/commands/config.test.js +2 -2
- package/dist/commands/config.test.js.map +1 -1
- package/dist/commands/doctor.d.ts +39 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +249 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/doctor.test.d.ts +2 -0
- package/dist/commands/doctor.test.d.ts.map +1 -0
- package/dist/commands/doctor.test.js +54 -0
- package/dist/commands/doctor.test.js.map +1 -0
- package/dist/commands/export-events.js +3 -3
- package/dist/commands/export-events.js.map +1 -1
- package/dist/commands/export-events.test.js +2 -2
- package/dist/commands/export-events.test.js.map +1 -1
- package/dist/commands/init.d.ts +13 -7
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +97 -34
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/init.test.js +83 -81
- package/dist/commands/init.test.js.map +1 -1
- package/dist/commands/lock.d.ts +39 -0
- package/dist/commands/lock.d.ts.map +1 -0
- package/dist/commands/lock.js +142 -0
- package/dist/commands/lock.js.map +1 -0
- package/dist/commands/lock.test.d.ts +2 -0
- package/dist/commands/lock.test.d.ts.map +1 -0
- package/dist/commands/lock.test.js +130 -0
- package/dist/commands/lock.test.js.map +1 -0
- package/dist/commands/project/create.js +3 -3
- package/dist/commands/project/create.js.map +1 -1
- package/dist/commands/project/create.test.js +2 -2
- package/dist/commands/project/create.test.js.map +1 -1
- package/dist/commands/project/delete.js +12 -12
- package/dist/commands/project/delete.js.map +1 -1
- package/dist/commands/project/delete.test.js +2 -2
- package/dist/commands/project/delete.test.js.map +1 -1
- package/dist/commands/project/list.js +4 -4
- package/dist/commands/project/list.js.map +1 -1
- package/dist/commands/project/list.test.js +2 -2
- package/dist/commands/project/list.test.js.map +1 -1
- package/dist/commands/project/rename.js +3 -3
- package/dist/commands/project/rename.js.map +1 -1
- package/dist/commands/project/rename.test.js +2 -2
- package/dist/commands/project/rename.test.js.map +1 -1
- package/dist/commands/project/show.js +4 -4
- package/dist/commands/project/show.js.map +1 -1
- package/dist/commands/project/show.test.js +2 -2
- package/dist/commands/project/show.test.js.map +1 -1
- package/dist/commands/sample-project.d.ts +10 -6
- package/dist/commands/sample-project.d.ts.map +1 -1
- package/dist/commands/sample-project.js +23 -13
- package/dist/commands/sample-project.js.map +1 -1
- package/dist/commands/sample-project.test.js +26 -24
- package/dist/commands/sample-project.test.js.map +1 -1
- package/dist/commands/stats.js +12 -12
- package/dist/commands/stats.js.map +1 -1
- package/dist/commands/stats.test.js +2 -2
- package/dist/commands/stats.test.js.map +1 -1
- package/dist/commands/status.d.ts +28 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +88 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/status.test.d.ts +2 -0
- package/dist/commands/status.test.d.ts.map +1 -0
- package/dist/commands/status.test.js +47 -0
- package/dist/commands/status.test.js.map +1 -0
- package/dist/commands/sync.d.ts +47 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +218 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/sync.test.d.ts +2 -0
- package/dist/commands/sync.test.d.ts.map +1 -0
- package/dist/commands/sync.test.js +49 -0
- package/dist/commands/sync.test.js.map +1 -0
- package/dist/commands/task/add-dep.js +5 -5
- package/dist/commands/task/add-dep.js.map +1 -1
- package/dist/commands/task/add-dep.test.js +2 -2
- package/dist/commands/task/add-dep.test.js.map +1 -1
- package/dist/commands/task/add.js +3 -3
- package/dist/commands/task/add.js.map +1 -1
- package/dist/commands/task/add.test.js +2 -2
- package/dist/commands/task/add.test.js.map +1 -1
- package/dist/commands/task/archive.js +3 -3
- package/dist/commands/task/archive.js.map +1 -1
- package/dist/commands/task/archive.test.js +2 -2
- package/dist/commands/task/archive.test.js.map +1 -1
- package/dist/commands/task/checkpoint.js +3 -3
- package/dist/commands/task/checkpoint.js.map +1 -1
- package/dist/commands/task/checkpoint.test.js +2 -2
- package/dist/commands/task/checkpoint.test.js.map +1 -1
- package/dist/commands/task/claim.js +3 -3
- package/dist/commands/task/claim.js.map +1 -1
- package/dist/commands/task/claim.test.js +2 -2
- package/dist/commands/task/claim.test.js.map +1 -1
- package/dist/commands/task/comment.js +3 -3
- package/dist/commands/task/comment.js.map +1 -1
- package/dist/commands/task/comment.test.js +2 -2
- package/dist/commands/task/comment.test.js.map +1 -1
- package/dist/commands/task/complete.js +3 -3
- package/dist/commands/task/complete.js.map +1 -1
- package/dist/commands/task/complete.test.js +2 -2
- package/dist/commands/task/complete.test.js.map +1 -1
- package/dist/commands/task/history.js +3 -3
- package/dist/commands/task/history.js.map +1 -1
- package/dist/commands/task/history.test.js +2 -2
- package/dist/commands/task/history.test.js.map +1 -1
- package/dist/commands/task/list.js +4 -4
- package/dist/commands/task/list.js.map +1 -1
- package/dist/commands/task/list.test.js +2 -2
- package/dist/commands/task/list.test.js.map +1 -1
- package/dist/commands/task/move.js +3 -3
- package/dist/commands/task/move.js.map +1 -1
- package/dist/commands/task/move.test.js +2 -2
- package/dist/commands/task/move.test.js.map +1 -1
- package/dist/commands/task/next.js +3 -3
- package/dist/commands/task/next.js.map +1 -1
- package/dist/commands/task/next.test.js +2 -2
- package/dist/commands/task/next.test.js.map +1 -1
- package/dist/commands/task/release.js +3 -3
- package/dist/commands/task/release.js.map +1 -1
- package/dist/commands/task/release.test.js +2 -2
- package/dist/commands/task/release.test.js.map +1 -1
- package/dist/commands/task/remove-dep.js +3 -3
- package/dist/commands/task/remove-dep.js.map +1 -1
- package/dist/commands/task/remove-dep.test.js +2 -2
- package/dist/commands/task/remove-dep.test.js.map +1 -1
- package/dist/commands/task/reopen.js +3 -3
- package/dist/commands/task/reopen.js.map +1 -1
- package/dist/commands/task/reopen.test.js +2 -2
- package/dist/commands/task/reopen.test.js.map +1 -1
- package/dist/commands/task/search.js +4 -4
- package/dist/commands/task/search.js.map +1 -1
- package/dist/commands/task/search.test.js +2 -2
- package/dist/commands/task/search.test.js.map +1 -1
- package/dist/commands/task/set-status.js +3 -3
- package/dist/commands/task/set-status.js.map +1 -1
- package/dist/commands/task/set-status.test.js +2 -2
- package/dist/commands/task/set-status.test.js.map +1 -1
- package/dist/commands/task/show.js +3 -3
- package/dist/commands/task/show.js.map +1 -1
- package/dist/commands/task/show.test.js +2 -2
- package/dist/commands/task/show.test.js.map +1 -1
- package/dist/commands/task/steal.js +3 -3
- package/dist/commands/task/steal.js.map +1 -1
- package/dist/commands/task/steal.test.js +2 -2
- package/dist/commands/task/steal.test.js.map +1 -1
- package/dist/commands/task/stuck.js +4 -4
- package/dist/commands/task/stuck.js.map +1 -1
- package/dist/commands/task/stuck.test.js +2 -2
- package/dist/commands/task/stuck.test.js.map +1 -1
- package/dist/commands/task/update.js +3 -3
- package/dist/commands/task/update.js.map +1 -1
- package/dist/commands/task/update.test.js +2 -2
- package/dist/commands/task/update.test.js.map +1 -1
- package/dist/commands/validate.js +3 -3
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/validate.test.js +3 -3
- package/dist/commands/validate.test.js.map +1 -1
- package/dist/commands/which-db.d.ts +4 -4
- package/dist/commands/which-db.d.ts.map +1 -1
- package/dist/commands/which-db.js +8 -11
- package/dist/commands/which-db.js.map +1 -1
- package/dist/commands/which-db.test.js +9 -8
- package/dist/commands/which-db.test.js.map +1 -1
- package/dist/config.d.ts +18 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +120 -13
- package/dist/config.js.map +1 -1
- package/dist/config.test.js +34 -110
- package/dist/config.test.js.map +1 -1
- package/dist/db.d.ts +16 -2
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +47 -17
- package/dist/db.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +1 -1
- package/dist/index.test.js.map +1 -1
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,164 +1,314 @@
|
|
|
1
|
-
# HZL
|
|
1
|
+
# HZL (Hazel)
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**A shared task ledger for OpenClaw and poly-agent workflows.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
OpenClaw is great at doing work: running tools, coordinating sub-agents, and maintaining memory.
|
|
6
|
+
What it (and most agent tools) do not give you is a durable, shared backlog that survives:
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
- session boundaries
|
|
9
|
+
- crashes/reboots
|
|
10
|
+
- switching between different agent runtimes (Claude Code, Codex, Gemini, etc.)
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
HZL fills that gap: a lightweight, local-first task tracker that any agent can read/write.
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
Using OpenClaw? Start here: [OpenClaw integration](#openclaw-integration)
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
Not using OpenClaw? Jump to: [Using HZL with Claude Code, Codex, Gemini CLI, or any coding agent](#using-hzl-with-claude-code-codex-gemini-cli-or-any-coding-agent)
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
HZL provides:
|
|
16
19
|
|
|
17
|
-
-
|
|
20
|
+
- Projects and tasks
|
|
21
|
+
- Dependencies (`B` waits for `A`)
|
|
22
|
+
- Checkpoints (progress snapshots you can resume from)
|
|
23
|
+
- Leases (time-limited claims for multi-agent coordination)
|
|
24
|
+
- Event history (audit trail)
|
|
25
|
+
- Cloud Sync (multi-device/multi-agent synchronization with Turso)
|
|
26
|
+
- A CLI + JSON output that agents can script against
|
|
18
27
|
|
|
19
|
-
|
|
28
|
+
Data is stored in SQLite. Default location: `$XDG_DATA_HOME/hzl/data.db` (fallback `~/.local/share/hzl/data.db`); Windows: `%LOCALAPPDATA%\\hzl\\data.db`.
|
|
20
29
|
|
|
21
|
-
|
|
30
|
+
---
|
|
22
31
|
|
|
23
|
-
|
|
32
|
+
## Why another task tracker?
|
|
24
33
|
|
|
25
|
-
|
|
34
|
+
Because most task trackers are built for humans.
|
|
26
35
|
|
|
27
|
-
|
|
36
|
+
HZL is built for agents:
|
|
28
37
|
|
|
29
|
-
|
|
38
|
+
- It is backend-first, not UI-first. Think "task database with a CLI," not "another Trello."
|
|
39
|
+
- It is model-agnostic. Your tasks live outside any one vendor's memory or chat history.
|
|
40
|
+
- It is multi-agent safe. Leases prevent orphaned work and enable clean handoffs.
|
|
41
|
+
- It is resumable. Checkpoints let an agent crash, reboot, or swap models and keep going.
|
|
30
42
|
|
|
31
|
-
|
|
43
|
+
If you already have a favorite human todo app, keep it.
|
|
44
|
+
If you need a shared task state that multiple agents can read/write, that is HZL.
|
|
32
45
|
|
|
33
|
-
|
|
46
|
+
---
|
|
34
47
|
|
|
35
|
-
|
|
48
|
+
## Where HZL fits
|
|
36
49
|
|
|
37
|
-
|
|
50
|
+
### 1) OpenClaw orchestrator + sub-agents
|
|
38
51
|
|
|
39
|
-
|
|
52
|
+
```mermaid
|
|
53
|
+
flowchart LR
|
|
54
|
+
You[You] --> OC["OpenClaw (orchestrator)"]
|
|
55
|
+
OC --> Tools["OpenClaw tools<br/>(browser, exec, email, etc.)"]
|
|
56
|
+
OC <--> HZL[(HZL task ledger)]
|
|
57
|
+
OC --> S1[Claude Code]
|
|
58
|
+
OC --> S2[Codex / other]
|
|
59
|
+
S1 <--> HZL
|
|
60
|
+
S2 <--> HZL
|
|
61
|
+
```
|
|
40
62
|
|
|
41
|
-
|
|
63
|
+
OpenClaw coordinates the work. HZL is the shared, durable task board that OpenClaw and its sub-agents can use across sessions.
|
|
42
64
|
|
|
43
|
-
|
|
65
|
+
### 2) Any poly-agent system (no OpenClaw required)
|
|
44
66
|
|
|
45
|
-
|
|
67
|
+
```mermaid
|
|
68
|
+
flowchart LR
|
|
69
|
+
U[You] --> O["Orchestrator (human or agent)"]
|
|
70
|
+
O <--> HZL[(HZL)]
|
|
71
|
+
O --> C[Claude Code]
|
|
72
|
+
O --> X[Codex]
|
|
73
|
+
O --> G[Gemini]
|
|
74
|
+
C <--> HZL
|
|
75
|
+
X <--> HZL
|
|
76
|
+
G <--> HZL
|
|
77
|
+
```
|
|
46
78
|
|
|
47
|
-
|
|
48
|
-
|
|
79
|
+
Same idea: once you are switching tools/models, you need a shared ledger.
|
|
80
|
+
|
|
81
|
+
### 3) One agent, many sessions
|
|
82
|
+
|
|
83
|
+
```mermaid
|
|
84
|
+
flowchart LR
|
|
85
|
+
U[You] --> A["Coding agent<br>(Claude Code, Codex, etc)"]
|
|
86
|
+
A <--> HZL
|
|
87
|
+
A --> R[Repo / files]
|
|
49
88
|
```
|
|
50
89
|
|
|
51
|
-
|
|
90
|
+
Use HZL to persist "what's next" and "what changed" between sessions.
|
|
52
91
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
92
|
+
### 4) HZL as the backend for your own UI
|
|
93
|
+
|
|
94
|
+
```mermaid
|
|
95
|
+
flowchart LR
|
|
96
|
+
UI[Lightweight web app] --> HZL
|
|
97
|
+
Agents[Agents + scripts] --> HZL
|
|
59
98
|
```
|
|
60
99
|
|
|
61
|
-
|
|
100
|
+
If you want a human-friendly interface, build one. HZL stays the durable backend that both humans and agents can use.
|
|
62
101
|
|
|
63
|
-
|
|
64
|
-
# Initialize the database
|
|
65
|
-
hzl init
|
|
102
|
+
---
|
|
66
103
|
|
|
67
|
-
|
|
68
|
-
hzl project create myapp
|
|
104
|
+
## Quickstart
|
|
69
105
|
|
|
70
|
-
|
|
71
|
-
hzl task add "Set up authentication" -P myapp --priority 2 --tags backend,auth
|
|
72
|
-
hzl task add "Write API tests" -P myapp --depends-on <task-id>
|
|
106
|
+
### Install
|
|
73
107
|
|
|
74
|
-
|
|
75
|
-
hzl task list --project myapp --available
|
|
108
|
+
Requires Node.js 22.14+.
|
|
76
109
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
hzl
|
|
80
|
-
hzl task checkpoint <task-id> "Completed OAuth flow"
|
|
81
|
-
hzl task complete <task-id>
|
|
110
|
+
```bash
|
|
111
|
+
npm install -g hzl-cli
|
|
112
|
+
hzl init
|
|
82
113
|
```
|
|
83
114
|
|
|
84
|
-
|
|
115
|
+
### Enable Cloud Sync (Optional)
|
|
85
116
|
|
|
86
|
-
|
|
117
|
+
Sync with a Turso database for multi-device/multi-agent access:
|
|
87
118
|
|
|
88
119
|
```bash
|
|
89
|
-
hzl
|
|
90
|
-
hzl task list [--project] [--status] # List tasks
|
|
91
|
-
hzl task next [--project] # Show next claimable task
|
|
92
|
-
hzl task claim <id> # Claim a task
|
|
93
|
-
hzl task complete <id> # Mark done
|
|
120
|
+
hzl init --sync-url libsql://<db>.turso.io --auth-token <token>
|
|
94
121
|
```
|
|
95
122
|
|
|
96
|
-
###
|
|
123
|
+
### Create a project and tasks
|
|
97
124
|
|
|
98
125
|
```bash
|
|
99
|
-
|
|
100
|
-
hzl task list --project myapp --available --json
|
|
101
|
-
hzl task claim <id> --author agent-1 --json
|
|
126
|
+
hzl project create portland-trip
|
|
102
127
|
|
|
103
|
-
|
|
104
|
-
hzl task
|
|
105
|
-
hzl task
|
|
128
|
+
hzl task add "Check calendars for March weekends" -P portland-trip --priority 5
|
|
129
|
+
hzl task add "Research neighborhoods + activities" -P portland-trip --priority 4
|
|
130
|
+
hzl task add "Shortlist 2-3 weekend options" -P portland-trip --priority 3 \
|
|
131
|
+
--depends-on <calendar-task-id> --depends-on <research-task-id>
|
|
106
132
|
```
|
|
107
133
|
|
|
108
|
-
###
|
|
134
|
+
### Work with checkpoints
|
|
109
135
|
|
|
110
136
|
```bash
|
|
111
|
-
hzl task claim <id> --
|
|
112
|
-
hzl task
|
|
113
|
-
hzl task
|
|
137
|
+
hzl task claim <calendar-task-id> --author trevin-agent
|
|
138
|
+
hzl task checkpoint <calendar-task-id> "Found 3 options: Mar 7-9, 14-16, 21-23"
|
|
139
|
+
hzl task complete <calendar-task-id>
|
|
114
140
|
```
|
|
115
141
|
|
|
116
|
-
###
|
|
142
|
+
### Link to supporting documents
|
|
143
|
+
|
|
144
|
+
Tasks stay lightweight. Use `--links` to reference design docs, brainstorms, or specs:
|
|
117
145
|
|
|
118
146
|
```bash
|
|
119
|
-
|
|
120
|
-
hzl task
|
|
121
|
-
|
|
147
|
+
# Create a task that links to context documents
|
|
148
|
+
hzl task add "Implement auth flow per design" -P myapp --priority 3 \
|
|
149
|
+
--links docs/designs/auth-flow.md \
|
|
150
|
+
--links docs/brainstorm/2026-01-auth-options.md
|
|
151
|
+
|
|
152
|
+
# The agent reads linked files for context, task stays focused on the work
|
|
153
|
+
hzl task show <id> --json
|
|
154
|
+
# → { "links": ["docs/designs/auth-flow.md", "https://somedomain/resource.md"], ... }
|
|
122
155
|
```
|
|
123
156
|
|
|
124
|
-
|
|
157
|
+
This pattern keeps tasks actionable while pointing agents to richer context stored elsewhere.
|
|
158
|
+
|
|
159
|
+
### Use JSON output when scripting
|
|
125
160
|
|
|
126
161
|
```bash
|
|
127
|
-
hzl task
|
|
128
|
-
hzl task
|
|
129
|
-
hzl validate # Check for cycles
|
|
162
|
+
hzl task show <id> --json
|
|
163
|
+
hzl task next --project portland-trip --json
|
|
130
164
|
```
|
|
131
165
|
|
|
132
|
-
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Core concepts (the stuff that matters)
|
|
169
|
+
|
|
170
|
+
### Tasks are units of work, not reminders
|
|
171
|
+
|
|
172
|
+
HZL is optimized for "do work, report progress, unblock the next step."
|
|
173
|
+
|
|
174
|
+
If you need time-based reminders, pair HZL with a scheduler (cron, OpenClaw cron, etc.).
|
|
175
|
+
|
|
176
|
+
### Checkpoints are progress snapshots
|
|
177
|
+
|
|
178
|
+
A checkpoint is a compact, durable record of what happened:
|
|
179
|
+
|
|
180
|
+
- what you tried
|
|
181
|
+
- what you found
|
|
182
|
+
- what's still missing
|
|
183
|
+
- links, commands, or file paths needed to resume
|
|
184
|
+
|
|
185
|
+
### Dependencies encode ordering
|
|
186
|
+
|
|
187
|
+
Dependencies are how an agent avoids premature work:
|
|
188
|
+
|
|
189
|
+
- "Don't search flights before you know dates."
|
|
190
|
+
- "Don't open a PR before tests pass."
|
|
191
|
+
|
|
192
|
+
### Leases make multi-agent handoffs reliable
|
|
193
|
+
|
|
194
|
+
Leases are time-limited claims:
|
|
195
|
+
|
|
196
|
+
- A worker agent claims a task with `--lease 30`
|
|
197
|
+
- If it disappears, the lease expires
|
|
198
|
+
- Another agent can detect stuck work and take over
|
|
199
|
+
|
|
200
|
+
### Cloud Sync & Offline-First
|
|
201
|
+
|
|
202
|
+
HZL uses a **local-first** architecture. You always read/write to a fast local database. Sync happens in the background via Turso/libSQL.
|
|
203
|
+
|
|
204
|
+
```mermaid
|
|
205
|
+
flowchart TD
|
|
206
|
+
CLI[User / Agent CLI]
|
|
207
|
+
subgraph Local["Local Machine"]
|
|
208
|
+
Cache[(cache.db<br/>Reads)]
|
|
209
|
+
Events[(events.db<br/>Writes)]
|
|
210
|
+
Sync[Sync Engine]
|
|
211
|
+
end
|
|
212
|
+
Cloud[(Turso / Cloud)]
|
|
213
|
+
|
|
214
|
+
CLI -->|Read| Cache
|
|
215
|
+
CLI -->|Write| Events
|
|
216
|
+
Events -->|Rebuild| Cache
|
|
217
|
+
Events <-->|Sync| Sync
|
|
218
|
+
Sync <-->|Replication| Cloud
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Patterns
|
|
133
224
|
|
|
134
|
-
|
|
225
|
+
### Pattern: Poly-agent backlog (recommended)
|
|
135
226
|
|
|
136
|
-
|
|
227
|
+
Conventions that help:
|
|
228
|
+
|
|
229
|
+
- Use consistent author IDs: `openclaw`, `claude-code`, `codex`, `gemini`, etc.
|
|
230
|
+
- Claim tasks before work.
|
|
231
|
+
- Checkpoint whenever you learn something that would be painful to rediscover.
|
|
232
|
+
|
|
233
|
+
Example handoff:
|
|
137
234
|
|
|
138
235
|
```bash
|
|
139
|
-
|
|
236
|
+
# Orchestrator creates task
|
|
237
|
+
hzl task add "Implement REST API endpoints" -P myapp --priority 2
|
|
238
|
+
TASK_ID=<id>
|
|
239
|
+
|
|
240
|
+
# Worker agent claims with a lease
|
|
241
|
+
hzl task claim "$TASK_ID" --author claude-code --lease 30
|
|
242
|
+
hzl task checkpoint "$TASK_ID" "Endpoints scaffolded; next: auth middleware"
|
|
243
|
+
hzl task complete "$TASK_ID"
|
|
140
244
|
```
|
|
141
245
|
|
|
142
|
-
|
|
246
|
+
### Pattern: Personal todo list (it works, but bring your own UI)
|
|
247
|
+
|
|
248
|
+
HZL can track personal tasks and has the advantage of centralizing agent and personal tasks.
|
|
249
|
+
This enables scenarios like OpenClaw assigning you tasks without needing to sync with other todo systems.
|
|
250
|
+
|
|
251
|
+
HZL itself is not trying to be a polished, human-first todo app. You bring other pieces for that.
|
|
252
|
+
|
|
253
|
+
If you want a todo app, build or use a UI:
|
|
254
|
+
|
|
255
|
+
- a tiny web app
|
|
256
|
+
- a TUI wrapper
|
|
257
|
+
- a menu bar widget
|
|
258
|
+
|
|
259
|
+
HZL stays the storage layer and concurrency-safe ledger underneath.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Using HZL with Claude Code, Codex, Gemini CLI, or any coding agent
|
|
264
|
+
|
|
265
|
+
**Why HZL when your agent already has task tracking?**
|
|
143
266
|
|
|
144
|
-
|
|
145
|
-
1. `--db` flag
|
|
146
|
-
2. `HZL_DB` environment variable
|
|
147
|
-
3. `~/.hzl/config.json`
|
|
148
|
-
4. Default: `~/.hzl/data.db`
|
|
267
|
+
Many coding agents (like Claude Code) have built-in task management. HZL complements rather than replaces it:
|
|
149
268
|
|
|
150
|
-
|
|
269
|
+
- **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.
|
|
270
|
+
- **Session persistence**: Built-in task trackers often reset between sessions. HZL persists to disk (and optionally to cloud).
|
|
271
|
+
- **Orchestration**: When one agent delegates to another, HZL provides the handoff mechanism (claim, checkpoint, complete).
|
|
272
|
+
- **Backup**: With cloud sync enabled, your task state survives machine failures.
|
|
151
273
|
|
|
152
|
-
|
|
153
|
-
|----------|-------------|
|
|
154
|
-
| `HZL_DB` | Override database location |
|
|
155
|
-
| `HZL_CONFIG` | Override config file location (default: `~/.hzl/config.json`) |
|
|
156
|
-
| `HZL_AUTHOR` | Default author for claims/comments |
|
|
157
|
-
| `HZL_AGENT_ID` | Default agent identifier |
|
|
274
|
+
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.
|
|
158
275
|
|
|
159
|
-
|
|
276
|
+
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.
|
|
160
277
|
|
|
161
|
-
|
|
278
|
+
### Drop-in policy snippet
|
|
279
|
+
|
|
280
|
+
```md
|
|
281
|
+
### HZL task ledger (durable, cross-agent task tracking)
|
|
282
|
+
|
|
283
|
+
HZL is a shared task database that persists across sessions and works across different agents.
|
|
284
|
+
Use it when work spans multiple sessions, involves handoffs to other agents, or needs durable backup.
|
|
285
|
+
If this agent has built-in task tracking, HZL complements it for cross-agent and multi-session work.
|
|
286
|
+
|
|
287
|
+
When to use HZL:
|
|
288
|
+
- Multi-session work that must survive restarts
|
|
289
|
+
- Coordination with other agents (Claude Code ↔ Codex ↔ Gemini, etc.)
|
|
290
|
+
- Work delegated to sub-agents that need explicit handoff
|
|
291
|
+
- When you need task state backed up to cloud
|
|
292
|
+
|
|
293
|
+
Workflow:
|
|
294
|
+
1) Create or use an HZL project for the work.
|
|
295
|
+
2) Break work into tasks with dependencies. Use `--links` to reference design docs or specs.
|
|
296
|
+
3) Claim tasks before work and checkpoint after meaningful progress.
|
|
297
|
+
4) Use `--json` when producing output another tool will parse.
|
|
298
|
+
|
|
299
|
+
Key commands:
|
|
300
|
+
- `hzl project create <name>`
|
|
301
|
+
- `hzl task add "<title>" -P <project> [--depends-on <id>] [--links <file>]`
|
|
302
|
+
- `hzl task claim <id> --author <agent-id> [--lease 30]`
|
|
303
|
+
- `hzl task checkpoint <id> "<progress + next step>"`
|
|
304
|
+
- `hzl task complete <id>`
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
That snippet is intentionally short. The goal is consistency, not ceremony.
|
|
308
|
+
|
|
309
|
+
### Claude Code marketplace (optional)
|
|
310
|
+
|
|
311
|
+
HZL includes a Claude Code plugin marketplace with skills that help agents work effectively with HZL.
|
|
162
312
|
|
|
163
313
|
```bash
|
|
164
314
|
# Add the marketplace
|
|
@@ -170,62 +320,92 @@ HZL includes a [Claude Code](https://claude.ai/code) plugin marketplace with ski
|
|
|
170
320
|
|
|
171
321
|
See [`packages/hzl-marketplace`](./packages/hzl-marketplace) for details.
|
|
172
322
|
|
|
173
|
-
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## OpenClaw integration
|
|
174
326
|
|
|
175
|
-
|
|
176
|
-
|
|
327
|
+
OpenClaw is a self-hosted AI assistant that can coordinate tools and sub-agents.
|
|
328
|
+
HZL fits well as the task ledger that OpenClaw (and its sub-agents) can share.
|
|
177
329
|
|
|
178
|
-
|
|
330
|
+
### Quick start (recommended)
|
|
179
331
|
|
|
180
|
-
|
|
332
|
+
Copy/paste this into an OpenClaw chat (single prompt):
|
|
181
333
|
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
334
|
+
```
|
|
335
|
+
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.
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Manual setup
|
|
339
|
+
|
|
340
|
+
1) Install HZL on the machine running OpenClaw:
|
|
187
341
|
|
|
188
|
-
|
|
189
|
-
|
|
342
|
+
```bash
|
|
343
|
+
npm install -g hzl-cli
|
|
344
|
+
hzl init
|
|
190
345
|
```
|
|
191
346
|
|
|
192
|
-
|
|
347
|
+
2) Install the HZL skill from https://www.clawhub.ai/tmchow/hzl
|
|
348
|
+
Skill source (for reference only): **[`docs/openclaw/skill-hzl.md`](./docs/openclaw/skill-hzl.md)**
|
|
193
349
|
|
|
194
|
-
|
|
350
|
+
3) Teach OpenClaw when to use HZL (important):
|
|
351
|
+
- Copy/paste from: **[`docs/openclaw/tools-prompt.md`](./docs/openclaw/tools-prompt.md)**
|
|
352
|
+
- Or tell OpenClaw to add this policy to `TOOLS.md`:
|
|
195
353
|
|
|
196
|
-
|
|
354
|
+
```
|
|
355
|
+
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:
|
|
356
|
+
https://raw.githubusercontent.com/tmchow/hzl/main/docs/openclaw/tools-prompt.md
|
|
357
|
+
```
|
|
197
358
|
|
|
198
|
-
|
|
199
|
-
## Task Management
|
|
359
|
+
---
|
|
200
360
|
|
|
201
|
-
|
|
361
|
+
## When to use HZL (and when not to)
|
|
202
362
|
|
|
203
|
-
###
|
|
363
|
+
### Use HZL when:
|
|
204
364
|
|
|
205
|
-
|
|
365
|
+
- work has multiple steps and you want explicit sequencing
|
|
366
|
+
- work spans multiple sessions (resume tomorrow with confidence)
|
|
367
|
+
- you are coordinating multiple agents or model providers
|
|
368
|
+
- you need durable status reporting (done / in progress / blocked / next)
|
|
369
|
+
- you want a task ledger your own UI can sit on top of
|
|
206
370
|
|
|
207
|
-
|
|
208
|
-
- **Long-lived agent?** Use your agent identity (e.g., `openclaw`, `kalids-openclaw`)
|
|
371
|
+
### Consider something else when:
|
|
209
372
|
|
|
210
|
-
|
|
373
|
+
- you need time-based reminders or notifications (use a scheduler + a notifier)
|
|
374
|
+
- you need rich human workflow features (due dates, recurring tasks, calendar views)
|
|
375
|
+
- you are tracking an org-wide backlog (GitHub/Jira/etc. may be a better fit)
|
|
211
376
|
|
|
212
|
-
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## CLI reference (short)
|
|
213
380
|
|
|
214
381
|
```bash
|
|
382
|
+
# Setup
|
|
383
|
+
hzl init # Initialize database (add --sync-url for cloud)
|
|
384
|
+
|
|
215
385
|
# Projects
|
|
216
|
-
hzl project
|
|
217
|
-
hzl project
|
|
386
|
+
hzl project create <name> # Create a project
|
|
387
|
+
hzl project list # List all projects
|
|
218
388
|
|
|
219
389
|
# Tasks
|
|
220
|
-
hzl task add "
|
|
221
|
-
hzl task
|
|
222
|
-
hzl task
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
390
|
+
hzl task add "<title>" -P <project> # Create task (--depends-on, --links, --priority)
|
|
391
|
+
hzl task list --project <project> # List tasks (--available for claimable only)
|
|
392
|
+
hzl task next --project <project> # Get highest priority available task
|
|
393
|
+
|
|
394
|
+
# Working
|
|
395
|
+
hzl task claim <id> --author <name> # Claim task (--lease <minutes> for expiry)
|
|
396
|
+
hzl task checkpoint <id> "<message>" # Save progress snapshot
|
|
397
|
+
hzl task complete <id> # Mark done
|
|
226
398
|
|
|
227
|
-
|
|
228
|
-
|
|
399
|
+
# Coordination
|
|
400
|
+
hzl task stuck # Find expired leases
|
|
401
|
+
hzl task steal <id> --if-expired # Take over abandoned task
|
|
402
|
+
hzl task show <id> --json # Task details (--json for scripting)
|
|
403
|
+
|
|
404
|
+
# Diagnostics
|
|
405
|
+
hzl sync # Sync with cloud (if configured)
|
|
406
|
+
hzl status # Show database and sync state
|
|
407
|
+
hzl doctor # Health checks
|
|
408
|
+
```
|
|
229
409
|
|
|
230
410
|
---
|
|
231
411
|
|
|
@@ -3,8 +3,8 @@ import fs from 'fs';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
|
-
import Database from '
|
|
7
|
-
import {
|
|
6
|
+
import Database from 'libsql';
|
|
7
|
+
import { initializeDbFromPath, closeDb } from '../../db.js';
|
|
8
8
|
import { createTestContext, hzlJson, hzlMayFail, } from './helpers.js';
|
|
9
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
10
|
const __dirname = path.dirname(__filename);
|
|
@@ -32,7 +32,7 @@ describe('CLI Integration Tests', () => {
|
|
|
32
32
|
it('creates database file', () => {
|
|
33
33
|
const result = hzlJson(ctx, 'init');
|
|
34
34
|
expect(result.created).toBe(true);
|
|
35
|
-
expect(result.
|
|
35
|
+
expect(result.eventsDbPath).toBe(ctx.dbPath);
|
|
36
36
|
expect(fs.existsSync(ctx.dbPath)).toBe(true);
|
|
37
37
|
});
|
|
38
38
|
it('is idempotent', () => {
|
|
@@ -44,15 +44,15 @@ describe('CLI Integration Tests', () => {
|
|
|
44
44
|
});
|
|
45
45
|
it('returns path information', () => {
|
|
46
46
|
const result = hzlJson(ctx, 'init');
|
|
47
|
-
expect(result.
|
|
47
|
+
expect(result.eventsDbPath).toBe(ctx.dbPath);
|
|
48
48
|
expect(result.created).toBe(true);
|
|
49
49
|
});
|
|
50
50
|
});
|
|
51
51
|
describe('which-db command', () => {
|
|
52
52
|
it('returns resolved database path', () => {
|
|
53
53
|
const result = hzlJson(ctx, 'which-db');
|
|
54
|
-
expect(result.
|
|
55
|
-
expect(result.
|
|
54
|
+
expect(result.eventsDbPath).toBe(ctx.dbPath);
|
|
55
|
+
expect(result.cacheDbPath).toBe(ctx.cachePath);
|
|
56
56
|
});
|
|
57
57
|
});
|
|
58
58
|
describe('task lifecycle round-trip', () => {
|
|
@@ -107,14 +107,14 @@ describe('CLI Integration Tests', () => {
|
|
|
107
107
|
const addResult = hzlJson(ctx, `task add-dep ${task2.task_id} ${task1.task_id}`);
|
|
108
108
|
expect(addResult.task_id).toBe(task2.task_id);
|
|
109
109
|
expect(addResult.depends_on_id).toBe(task1.task_id);
|
|
110
|
-
const db = new Database(ctx.
|
|
110
|
+
const db = new Database(ctx.cachePath);
|
|
111
111
|
const deps = db
|
|
112
112
|
.prepare('SELECT depends_on_id FROM task_dependencies WHERE task_id = ?')
|
|
113
113
|
.all(task2.task_id);
|
|
114
114
|
expect(deps.map((d) => d.depends_on_id)).toContain(task1.task_id);
|
|
115
115
|
db.close();
|
|
116
116
|
hzlJson(ctx, `task remove-dep ${task2.task_id} ${task1.task_id}`);
|
|
117
|
-
const dbAfter = new Database(ctx.
|
|
117
|
+
const dbAfter = new Database(ctx.cachePath);
|
|
118
118
|
const depsAfter = dbAfter
|
|
119
119
|
.prepare('SELECT depends_on_id FROM task_dependencies WHERE task_id = ?')
|
|
120
120
|
.all(task2.task_id);
|
|
@@ -243,6 +243,7 @@ describe('CLI Integration Tests', () => {
|
|
|
243
243
|
expect(fs.existsSync(exportPath)).toBe(true);
|
|
244
244
|
const content = fs.readFileSync(exportPath, 'utf-8');
|
|
245
245
|
const lines = content.trim().split('\n').filter((line) => line.length > 0);
|
|
246
|
+
// 1 project_created (inbox) + 2 task_created events
|
|
246
247
|
expect(lines).toHaveLength(3);
|
|
247
248
|
const events = lines.map((line) => JSON.parse(line));
|
|
248
249
|
expect(events[0].type).toBe('project_created');
|
|
@@ -283,7 +284,7 @@ describe('CLI Integration Tests', () => {
|
|
|
283
284
|
const task = addTask('inbox', 'Stuck task');
|
|
284
285
|
hzlJson(ctx, `task set-status ${task.task_id} ready`);
|
|
285
286
|
const pastLease = new Date(Date.now() - 60000).toISOString();
|
|
286
|
-
const services =
|
|
287
|
+
const services = initializeDbFromPath(ctx.dbPath);
|
|
287
288
|
try {
|
|
288
289
|
services.taskService.claimTask(task.task_id, {
|
|
289
290
|
author: 'stalled-agent',
|