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.cjs
  • dashboard/public/index.html
  • dashboard/public/app.js
  • dashboard/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 — enable mock.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 by node:assert)
  • Use mock.fn() for function mocks, mock.method(obj, key) for spies
  • Use mock.module("mod", { namedExports: {...} }) for ESM module mocking (must be before await 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.

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.


  1. Edit extension/CLI/template code
  2. Run tests (cd extensions && npm test)
  3. Run pi with local extension flags
  4. Execute manual smoke flows:
    • /orch-plan all
    • /orch all
    • taskplane 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 export
  • extensions/taskplane/discovery.ts — task discovery + dependency parsing
  • extensions/taskplane/waves.ts — DAG + wave computation + lane assignment
  • extensions/taskplane/execution.ts — lane spawning/monitoring
  • extensions/taskplane/merge.ts — merge orchestration
  • extensions/taskplane/persistence.ts — batch state persistence
  • extensions/taskplane/resume.ts — resume reconciliation and continuation
  • extensions/taskplane/worktree.ts — worktree lifecycle