Dependency-aware task management extension for Pi Coding Agent.
This extension provides a comprehensive task management system with dependency tracking, status management, and real-time UI updates for organizing complex development workflows.
- Persistent Task Store: Tasks are stored under
~/.pi/tasks/<list-id>/as individual JSON files - Bidirectional Dependency Links: Automatic maintenance of
blockedByandblocksrelationships - Dependency-Aware Status Transitions: Blocked tasks cannot move to
in_progressorcompletedstatus - Live Task Widget: Real-time task overview in the Pi UI footer
- Multi-List Support: Isolated task lists via UUID or environment variable
- Parallel Task Execution: Identify tasks ready for parallel execution with
get_batch_of_tasks - Owner Assignment: Track who is responsible for each task
- Rich Metadata: Attach custom metadata to tasks for categorization and filtering
Create a new dependency-aware task.
Required fields:
subject(string, non-empty): Task titleaddBlockedBy(string array): Task IDs this task depends on (can be[])
Optional fields:
description(string): Detailed task description (defaults to"")activeForm(string): Present continuous form for display (defaults tosubject)metadata(object): Custom key-value pairs for categorization (defaults to{})
Example:
{
"subject": "Implement auth middleware",
"description": "Add JWT verification and role checks",
"activeForm": "Implementing auth middleware",
"addBlockedBy": ["2"],
"metadata": { "priority": "high", "component": "api" }
}Returns: Created task with generated ID and all fields.
Update task status, assignment, text fields, and dependencies.
Required field:
taskId(string, non-empty): ID of task to update
Optional fields:
status("pending"|"in_progress"|"completed"): Task statusowner(string): Assign task to owner (empty string clears owner)subject(string, non-empty): Update task titledescription(string): Update task descriptionactiveForm(string): Update active form textaddBlockedBy(string array): Add new dependency IDs (appended and deduplicated)addBlocks(string array): Add tasks that depend on this task (appended and deduplicated)
Behavior:
- Dependencies are validated; missing task IDs cause errors
- Blocked tasks cannot transition to
in_progressorcompleted - Reciprocal dependency links are maintained automatically
- Owner is trimmed and cleared if empty
Example:
{
"taskId": "3",
"status": "in_progress",
"owner": "frontend-team",
"addBlockedBy": ["1", "2"]
}Retrieve full details for a specific task with formatted output.
Input:
{
"taskId": "3"
}Returns: Formatted text summary and structured task details including:
- Task ID and subject
- Status (with blocked indicator)
- Owner assignment
- Blocked-by dependencies
- Tasks this task blocks
- Description
List all tasks with dependency-aware blocked state.
Input:
{}Returns: Structured data with all tasks and computed isBlocked field.
Example Response:
{
"content": [{ "type": "text", "text": "Listed 5 task(s)." }],
"details": {
"tasks": [
{
"id": "1",
"subject": "Setup project",
"status": "completed",
"isBlocked": false,
"blockedBy": [],
"blocks": ["2", "3"],
...
}
]
}
}Return all pending, unblocked tasks that can be executed in parallel.
Use case: Ideal for distributing work across multiple agents or workers.
Inclusion criteria:
statusis"pending"isBlockedisfalse(all dependencies completed)
Input:
{}Returns: Text summary and array of ready tasks.
Example Response:
{
"content": [{ "type": "text", "text": "3 task(s) ready to run in parallel:\n#2: Implement API endpoints\n#3: Setup database schema\n#5: Write unit tests" }],
"details": {
"tasks": [
{ "id": "2", "subject": "Implement API endpoints", ... },
{ "id": "3", "subject": "Setup database schema", ... },
{ "id": "5", "subject": "Write unit tests", ... }
]
}
}Delete all tasks in the current task list.
Input:
{}Returns: Number of cleared tasks.
Note: This action is irreversible. Use with caution.
Display all tasks in markdown format with:
- Status symbols:
✓(done),■(in progress),□(pending),⚠(blocked) - Owner assignment (if present)
- Blocked-by dependency labels
- Aggregated counts (done / in progress / open)
Example Output:
## Tasks (2 done, 1 in progress, 3 open)
- ✓ **#1** Setup project — Done
- ■ **#2** Implement API endpoints (backend-team) — In Progress
- □ **#3** Setup database schema — Pending
- ⚠ **#4** Write integration tests — Pending ⚠ blocked by #2, #3
- □ **#5** Deploy to staging — Pending
- □ **#6** Update documentation — Pending
Delete all tasks from the current task list and refresh the widget immediately.
Output: Confirmation message with count of cleared tasks.
pending ──→ in_progress ──→ completed
↑ │
└──────────────────────────────┘
Rules:
- Tasks start in
pendingstatus - Blocked tasks (with unfinished dependencies) cannot transition to
in_progressorcompleted - Tasks can move from
in_progressback topending - Completed tasks cannot be reverted
The extension resolves the active list ID in priority order:
PI_TASK_LIST_IDenvironment variable (if set)- Previously persisted session entry (
pi-taskgraph-state) - Generated UUID (new list)
~/.pi/tasks/
└── <list-id>/
├── 1.json
├── 2.json
├── 3.json
└── ...
Each task is stored as an individual JSON file with the task ID as the filename.
The resolved list ID is persisted in session state (pi-taskgraph-state) and automatically restored on session restart, maintaining continuity across Pi sessions.
{
"id": "3",
"subject": "Implement auth middleware",
"description": "Add JWT verification and role checks",
"activeForm": "Implementing auth middleware",
"owner": "backend-team",
"status": "in_progress",
"blocks": ["5"],
"blockedBy": ["1", "2"],
"metadata": {
"priority": "high",
"component": "api"
}
}Fields:
id: Auto-incremented string IDsubject: Task title (required, non-empty)description: Detailed descriptionactiveForm: Present continuous form for displayowner: Assigned owner (optional)status: One ofpending,in_progress,completedblocks: Task IDs that depend on this taskblockedBy: Task IDs this task depends onmetadata: Custom key-value pairs
pi install ./
pi remove ./Use this repo directly as an extension entrypoint:
pi --extension "$(pwd)/extensions/index.ts"pi install pi-taskgraph- Node.js 18+
- npm
npm installnpx tsc --noEmitRun all tests:
npm testRun in watch mode:
npx vitestRun specific test file:
npx vitest src/task-store.core.test.ts-
Create a dependency task:
task_create({ subject: "Setup database" }) -
Create a dependent task:
task_create({ subject: "Implement models" }) -
Add dependency:
task_update({ taskId: "2", addBlockedBy: ["1"] }) -
Try to set blocked task to in_progress (should fail):
task_update({ taskId: "2", status: "in_progress" }) # Error: Task #2 is blocked by unfinished dependencies. -
Mark dependency task completed:
task_update({ taskId: "1", status: "completed" }) -
Set blocked task to in_progress (should succeed):
task_update({ taskId: "2", status: "in_progress" }) -
Verify with task_list and get_batch_of_tasks:
task_list({}) get_batch_of_tasks({}) -
Check markdown output:
/list-tasks
Ideal for multi-agent or team workflows:
-
Create tasks with dependencies:
task_create({ subject: "Setup project", addBlockedBy: [] }) task_create({ subject: "Implement API", addBlockedBy: ["1"] }) task_create({ subject: "Setup tests", addBlockedBy: ["1"] }) task_create({ subject: "Write docs", addBlockedBy: [] }) -
Get tasks ready for parallel execution:
get_batch_of_tasks({}) # Returns: #1 (Setup project), #4 (Write docs) -
Assign to different agents:
task_update({ taskId: "1", owner: "backend-agent" }) task_update({ taskId: "4", owner: "docs-agent" }) -
Mark completed and get next batch:
task_update({ taskId: "1", status: "completed" }) task_update({ taskId: "4", status: "completed" }) get_batch_of_tasks({}) # Returns: #2 (Implement API), #3 (Setup tests)
All tools return structured responses with:
content: Human-readable messagedetails: Structured data or error information
Error examples:
Task #X does not exist.Task #X cannot depend on itself.Task #X is blocked by unfinished dependencies.Task store is not initialized yet.
MIT