Development Setup
May 10, 2026 · View on GitHub
This guide is for contributors working on Taskplane itself.
Prerequisites
- Node.js 22+
- Git
- pi
Clone and install
git clone https://github.com/HenryLach/taskplane.git
cd taskplane
Install extension test/dev dependencies:
cd extensions
npm install
cd ..
Run extensions locally
Load the orchestrator
pi -e extensions/task-orchestrator.ts
Work on the CLI
CLI entrypoint:
bin/taskplane.mjs
Typical manual checks:
node bin/taskplane.mjs help
node bin/taskplane.mjs version
node bin/taskplane.mjs init --dry-run
node bin/taskplane.mjs doctor
Work on the dashboard
Dashboard files:
dashboard/server.cjsdashboard/public/index.htmldashboard/public/app.jsdashboard/public/style.css
Launch via CLI:
taskplane dashboard
Or direct server invocation:
node dashboard/server.cjs --root . --port 8099 --no-open
Work on skills/templates
- Skills:
skills/ - Templates:
templates/
Template changes affect taskplane init output and must be tested by running init in a scratch repo.
Running tests
Tests use the Node.js native test runner (node:test) exclusively — no vitest or vite dependency.
cd extensions
# Full suite (unit + integration)
npm test
# Fast suite (unit only, skip integration)
npm run test:fast
# Single file
node --experimental-strip-types --experimental-test-module-mocks --no-warnings --import ./tests/loader.mjs --test tests/some-file.test.ts
Key flags:
--experimental-strip-types— run TypeScript directly without transpilation--experimental-test-module-mocks— enablemock.module()for ESM module mocking--import ./tests/loader.mjs— register module resolution hooks
The custom loader (tests/loader.mjs) redirects @mariozechner/pi-coding-agent
and @mariozechner/pi-tui to local mock stubs so tests don't need the real packages.
Test authoring patterns
- Use
import { describe, it, mock, beforeEach, afterEach } from "node:test"for test structure - Use
import { expect } from "./expect.ts"for a familiar matcher API (legacy Vitest-style surface backed bynode:assert) - Use
mock.fn()for function mocks,mock.method(obj, key)for spies - Use
mock.module("mod", { namedExports: {...} })for ESM module mocking (must be beforeawait import()of consumer) - Use
mock.timers.enable()/mock.timers.tick(ms)/mock.timers.reset()for fake timers
Code-quality gates (required for every PR)
Three static checks are required CI gates — every PR must pass all three
before it can be merged. Each runs as a separate step in .github/workflows/ci.yml
and a failure blocks the merge:
npm run typecheck # TypeScript type-check (tsc --noEmit against extensions/tsconfig.ci.json)
npm run lint # Biome lint check
npm run format:check # Biome format check (non-zero exit on diff)
Run these locally before pushing for PR — they are cheap (each runs in a few
seconds) and catch regressions before CI does. The rationale for the three-gate
baseline is documented in
docs/specifications/taskplane/code-quality-gates.md
(the spec that introduced these gates via TP-191/TP-192/TP-193/TP-194).
To auto-fix the lint/format gates locally:
npm run lint:fix # apply safe Biome lint autofixes
npm run format # rewrite files in-place to match the format check
The typecheck gate has no auto-fix — type errors must be addressed by hand.
Code style and git blame.ignoreRevsFile (recommended one-time config)
Taskplane uses Biome as both linter and formatter. The
formatter rules are pinned in biome.json and applied uniformly across the
codebase.
Available scripts (run from the repo root):
npm run lint # report lint issues (no fixes)
npm run lint:fix # apply safe lint autofixes
npm run format # format files in-place
npm run format:check # check formatting (CI-style; non-zero exit on diff)
.git-blame-ignore-revs
The repo ships a .git-blame-ignore-revs file at the root that lists
commits whose changes are purely mechanical — chiefly the one-shot Biome
formatter adoption commit (TP-193). Without this file, git blame would
bottom out on the formatter commit for nearly every line in the codebase
and hide the real authoring history.
Recommended one-time per-developer setup:
git config blame.ignoreRevsFile .git-blame-ignore-revs
This is recommended, not required. Without it, git blame still works
— it just attributes every formatter-touched line to the format-adoption
commit instead of the underlying author. The same .git-blame-ignore-revs
file is also picked up automatically by GitHub's web Blame view (no
client-side config needed there).
When you add a future bulk-mechanical commit (e.g., a one-shot codemod or
another formatter migration), append its full 40-character SHA + a
comment block describing what it did to .git-blame-ignore-revs.
Recommended local dev loop
- Edit extension/CLI/template code
- Run tests (
cd extensions && npm test) - Run pi with local extension flags
- Execute manual smoke flows:
/orch-plan all/orch alltaskplane doctor
Suggested scratch-repo smoke test
mkdir ../tp-scratch && cd ../tp-scratch
git init
pi install -l npm:taskplane
npx taskplane init --preset full
pi
Inside pi:
/orch-plan all
/orch all
/orch taskplane-tasks/EXAMPLE-001-hello-world/PROMPT.md
File map for core implementation
extensions/task-orchestrator.ts— orchestrator facade exportextensions/taskplane/discovery.ts— task discovery + dependency parsingextensions/taskplane/waves.ts— DAG + wave computation + lane assignmentextensions/taskplane/execution.ts— lane spawning/monitoringextensions/taskplane/merge.ts— merge orchestrationextensions/taskplane/persistence.ts— batch state persistenceextensions/taskplane/resume.ts— resume reconciliation and continuationextensions/taskplane/worktree.ts— worktree lifecycle