Spool
Git-native, event-sourced task management.
Tasks are stored as append-only event logs in .spool/events/. Every change is tracked, branches work naturally, and merge conflicts resolve automatically.
TUI
Run spool-ui for a terminal interface:
| Key | Action |
|---|---|
j/k |
Navigate / scroll detail |
c |
Complete task |
r |
Reopen task |
n |
New task |
v |
Cycle view (Open/Complete/All) |
s |
Cycle sort |
S |
Cycle stream |
/ |
Search |
q |
Quit |
Usage
Initialize
Creates .spool/ with events/ and archive/ directories. Commit this to git.
Create tasks
Options: -p priority (p0-p3), -t tag (repeatable), -d description, -a assignee, --stream stream ID.
List tasks
Show task details
Update tasks
Assign tasks
Complete tasks
Streams
Streams group tasks into collections (features, sprints, areas).
Maintenance
How it works
Event sourcing
Instead of mutable records, every change is an immutable event:
Events are stored in daily JSONL files: .spool/events/2026-01-13.jsonl
State is materialized by replaying events. Caches (.index.json, .state.json) are gitignored and rebuilt on demand with spool rebuild.
Directory structure
.spool/
├── events/ # Daily event logs (committed)
│ └── 2026-01-13.jsonl
├── archive/ # Monthly archives (committed)
│ └── 2026-01.jsonl
├── .index.json # Cache (gitignored)
├── .state.json # Cache (gitignored)
└── .gitignore
Operations
| Operation | Description |
|---|---|
create |
Create task with title, description, priority, assignee, tags |
update |
Update task fields |
assign |
Change assignee (null to unassign) |
complete |
Mark complete with resolution |
reopen |
Reopen completed task |
comment |
Add comment |
link / unlink |
Manage relationships (blocks, blocked_by, parent) |
set_stream |
Set or remove task's stream |
create_stream |
Create stream |
update_stream |
Update stream metadata |
delete_stream |
Delete stream |
archive |
Archive completed task |
Task IDs
Format: {timestamp}-{random} where timestamp is Unix ms in base36 and random is 4 alphanumeric chars.
Example: k8b2x-a1c3
Git integration
Commit with code
Post-merge hook
#!/bin/sh
# .git/hooks/post-merge
Merge conflicts
Event files are append-only. On conflict, keep both sets of events:
# Keep all events from both versions, then:
CI validation
||
Scripting
# Get task IDs
TASKS=
# Process JSON
|
# Batch operations
for; do
done
License
MIT