A Herdr extension that assists with the management and orchestration of teams of AI agents. It browses and selects work from the backlog, dispatches agents into panes, tracks their live status, and releases claims abandoned by agents that have gone away.
At the heart of that orchestration is Worklog: a lightweight, Git-friendly issue tracker that also serves as the project's history. Every work item records its description, acceptance criteria, and comment trail, so each agent gets the relevant context for the job it is given. Track hierarchical work items with a CLI or REST API — all backed by SQLite with JSONL-based Git syncing.
- Herdr Orchestration: Browse and select work items, dispatch Pi agent panes, track live agent status, and self-heal abandoned
in_progressclaims from a Herdr pane (see Herdr plugin) - AI Agent Integration: Pi agent plugin modules that auto-load into every session — activity indicator, session health, model/provider display, guardrails, error recovery (
/retry), and skill-path tool (see Pi extension). - Heartbeat Skill: Automated work item monitoring via the Pi agent — run
/skill:heartbeatto flag items needing producer review or to audit completed items for closure readiness (see skill/heartbeat/SKILL.md). - Hierarchical Work Items: Parent-child relationships for organizing epics, features, and tasks
- Plugin System: Extend the CLI with custom commands (see Plugin Guide)
- CLI + API: Manage work items from the command line or a REST API
- Git-Friendly Syncing: JSONL format enables seamless team collaboration via Git with automatic conflict resolution
- Multi-Project Support: Custom prefixes for issue IDs per project
npm install
npm run build
npm link # or: npm install -g .After installing, worklog and wl are available globally. For development without global install, use npm run cli -- <command>.
# Initialize your project
wl init
# Create your first work item
wl create -t "My first task" -d "Let's get started!"
# See it in the list
wl list
# Update its status
wl update <id> -s in-progress
# Add a comment
wl comment add <id> -c "Making progress" -a "Your Name"
# Mark it complete
wl update <id> -s completed
# View hierarchy (create children with -P <parent-id>)
wl create -t "Sub-task" -P <parent-id>
wl show <parent-id> -c# Sync work items via Git (pull, merge, push)
wl sync
# Mirror to GitHub Issues (optional)
wl github push # add --verbose for a per-item synced list + timing breakdown
wl github importThe repository includes a Pi extension that auto-loads into every pi session
(via a global symlink under ~/.pi/agent/extensions). It provides the
agent-side capabilities that complement the Herdr plugin: an activity
indicator and session health/model display in the pi footer, guardrails that
protect worklog database files, a skill_path tool, automatic error recovery
(/retry), and proactive Local Proxy model lease release. Work item titles in
the footer resolve across sibling projects (an ID from another project's
worklog is looked up with the project's own --worklog-dir, via the same
prefix-to-sibling scan the skills layer uses — see
docs/wl-integration.md). Work item browsing
and management is provided by the Herdr plugin.
Install the extension globally:
npm run install:pi-extensionInstaller guards.
scripts/install-pi-extension.shonly points the global symlink at a checkout it can actually load. It is a safe no-op (exit0, no mutation of~/.pi/agent/extensions) when either of the following holds:
- Worktree context —
REPO_ROOTcontains the.worklog/worktrees/path segment (as created by/skill:implement). This prevents an unbuilt, short-lived worktree from repointing — and then breaking — the machine-global extension once the worktree is removed.- Unbuilt checkout —
dist/wl-integration/spawn.jsis absent. The extension resolves this compiled output at runtime, so installing from an unbuilt checkout would produce a broken extension. Runnpm run buildfirst.Because the guards exit
0rather than failing,npm installin a worktree still succeeds and leaves the existing global symlink untouched.
For a single-command install of all integrations (herdr plugin + Pi extension):
npm run installThen start (or restart) pi and run:
/reload
You can get a lot of value from using Worklog as a memory for your agents. But you can go further by building a personal workflow. Worklog brings a minimal workflow installed via wl init, and you can customize it in your AGENTS.md. For inspiration, see the Sorra Agents Repository.
| Document | Description |
|---|---|
| CONFIG.md | Configuration system, wl init, and setup options |
| CLI.md | Complete CLI command reference |
| EXAMPLES.md | Practical usage examples |
| Document | Description |
|---|---|
| DATA_FORMAT.md | JSONL data format, storage architecture, and field reference |
| DATA_SYNCING.md | Git-backed syncing and GitHub Issue mirroring |
| docs/design/incremental-sync.md | Incremental (delta) sync architecture: delta format, full-snapshot cadence, fallback, backward compatibility (WL-0MSAKUBKW006FN8Q) |
| GIT_WORKFLOW.md | Team collaboration patterns and Git hooks |
| Document | Description |
|---|---|
| Heartbeat Skill | Automated work item monitoring and audit orchestration for the Pi agent |
| PLUGIN_GUIDE.md | Plugin development guide and API reference |
| LOCAL_LLM.md | Configure local LLM providers (Ollama, Foundry) and the direct llm.* chat config used by wl interview |
| MULTI_PROJECT_GUIDE.md | Multi-project setup with custom prefixes |
| API.md | REST API endpoints and usage |
| docs/FILE_PATH_CONVENTION.md | File path convention for work item descriptions |
| docs/CROSS_PROJECT_POLLUTION_CLEANUP.md | Detecting and removing cross-project worklog pollution (wl doctor foreign-items) |
| DOCTOR_AND_MIGRATIONS.md | Reporting and waiving audit gaps: wl doctor audit-gaps, wl audit-waive / wl audit-unwaive |
| docs/SYNC_IDENTITY_GATE.md | Refusing foreign/empty-author commits on sync (--allow-foreign-author, polluted-ref recovery) |
| docs/AGENTS-INSTALL.md | How wl init installs AGENTS.md / workflow guidance and how local rules relate to the global agent file |
| Document | Description |
|---|---|
| IMPLEMENTATION_SUMMARY.md | Architecture overview and file structure |
| MIGRATING_FROM_BEADS.md | Migration guide from Beads issue tracker |
| AGENTS.md | AI agent onboarding and workflow instructions |
| tests/README.md | Test suite documentation |
| examples/README.md | Example plugins |
| Document | Description |
|---|---|
| docs/opencode-to-pi-migration.md | Migration guide from OpenCode to Pi framework |
| docs/migrations.md | Database migration system |
| docs/prd/sort_order_PRD.md | Sort order product requirements |
| docs/validation/status-stage-inventory.md | Status/stage validation rules |
| docs/SKILL_AUTHORING.md | Skill authoring guide with script best practices |
| docs/dev/wl-process-healthcheck.md | wl process healthcheck watchdog usage (cron/systemd, thresholds) |
| docs/dev/audit-debug-log-retention.md | Audit debug log retention policy + runbook: sweep locations/thresholds, dry-run/--apply/--check, cron install/removal, safety guarantees |
| docs/dev/downtime-dispatcher.md | Leader-election + shared-coordination downtime dispatcher architecture (herdr); critical-first dispatch tier + freeze split-by-skill; automated per-project tabs (one tab per work-item prefix) and interactive item-ID-tab placement (invoking workspace, fail-open) |
| docs/dev/test-suite-baseline.md | Test gates reference (which suites each gate runs, canonical full suite, and the separate opt-in herdr profile: run_tests.py --type herdr / --group herdr), plus test file-count and suite runtime baselines (reproducible commands + metrics) |
| docs/pane-triage-skill.md | Approval-gated pane-triage skill and the cross-language pane-close bridge that exposes the shared classifier to Python skills |
Step-by-step guides for learning Worklog:
| Tutorial | Audience | Description |
|---|---|---|
| Your First Work Item | New users | Install, init, create, update, and close work items |
| Team Collaboration | Team leads | Git sync, GitHub mirroring, multi-user workflow |
| Building a Plugin | Developers | Plugin API, database access, testing |
| Planning an Epic | Project leads | Epics, child items, dependencies, wl next |
See docs/tutorials/README.md for the full tutorial index.
Worklog ships with shell completion scripts for bash and zsh. The wl completion command generates a completion script that provides tab-completion for all subcommands, options, and dynamic work-item IDs.
# Source directly (current shell only)
source <(wl completion bash)
# Permanent installation
wl completion bash > ~/.wl-completion.bash
echo "source ~/.wl-completion.bash" >> ~/.bashrc# Source directly (current shell only)
source <(wl completion zsh)
# Permanent installation
wl completion zsh > ~/.wl-completion.zsh
echo "source ~/.wl-completion.zsh" >> ~/.zshrcNote: Dynamic work-item ID completion (e.g.,
wl show <TAB>) callswl list --jsonin the background to fetch open work items. This may add a slight delay on first tab press in large repositories.
npm run build # Build the project
npm run dev # Development mode with auto-reload
npm test # Run all tests
npm run test:watch # Tests in watch mode
npm run test:coverage # Tests with coverage reportThe project uses Vitest with the following settings in vitest.config.ts:
- Pool:
'forks'(child processes) — supports tests that useprocess.chdir()for temp directory setup - maxWorkers:
4— limits concurrent worker count to prevent unbounded memory growth during test execution - Exclusions: Worktree directories (
.worklog/worktrees/**) are excluded to prevent duplicate test file discovery
See tests/README.md for detailed testing documentation.
Test runtime is dominated by per-spawn TypeScript transpilation, not by
assertion work. A test that needs real process isolation spawns the CLI, and
tsx src/cli.ts re-transpiles the whole src/ import graph on every process
start: measured 2.5–8 s per spawn on a loaded host, versus 1.1–1.6 s
for a pre-compiled build. That is why the CLI suite used to take 8–12 minutes
and why its runtime swung by ~50 % with host load.
Two rules keep the suite fast:
- Prefer the in-process harness.
execAsync('tsx <cliPath> …')fromtests/cli/cli-helpers.tsruns the CLI in-process (cli-inproc.ts), so it pays no process start at all. Use it for any command that does not need a fresh process. - When a real process is unavoidable, spawn the bundle. Use
runCliProcess()/cliInvocation()fromtests/cli/cli-bundle.tsinstead of spawningtsx src/cli.tsdirectly. It buildssrc/cli.tsonce per test process with esbuild — same entry, same command graph, ~5× cheaper per spawn — and transparently falls back totsxif the build fails.
Use a real tsx/dist spawn only when the test must observe the real entry
point or measure startup cost (tests/cli/startup-import-budget.test.ts,
tests/cli/entry-point-split.test.ts).
npm run test:timings writes a per-test timing report to test-timings.json;
the current baseline and the latest top-20 slow-test table are recorded in
docs/dev/test-suite-baseline.md.
Work item tests under tests/cli/ and tests/unit/ demonstrate the mock
patterns used by this project:
- Comprehensive
node:fsmock: Rather than stubbing only the few fs functions used directly by the code under test, the mock covers the broader set that may be called during module initialization, preventing cascading errors and heap OOM during import. - Stale-import grep guard:
tests/unit/icons.test.tsfails the build if any file imports from the removedicons.jswrapper paths, preventing the deprecatedicons.tsfiles from drifting back in. - Infinite loop guard:
custom()mocks return a terminating shortcut instead ofnullto break long-running TUI loops, preventing infinite-loop-based OOM in test mocks.
MIT