Compare commits
60 Commits
ralph/fix/
...
ralph/feat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b74e4a98ef | ||
|
|
efd1a91177 | ||
|
|
0d9939348c | ||
|
|
968c38c31d | ||
|
|
c770f10265 | ||
|
|
b9e644c556 | ||
|
|
7265a6cf53 | ||
|
|
db6f405f23 | ||
|
|
7b5a7c4495 | ||
|
|
caee040907 | ||
|
|
4b5473860b | ||
|
|
b43b7ce201 | ||
|
|
86027f1ee4 | ||
|
|
4f984f8a69 | ||
|
|
f7646f41b5 | ||
|
|
20004a39ea | ||
|
|
f1393f47b1 | ||
|
|
738ec51c04 | ||
|
|
c7418c4594 | ||
|
|
0747f1c772 | ||
|
|
ffe24a2e35 | ||
|
|
604b94baa9 | ||
|
|
2ea4bb6a81 | ||
|
|
3e96387715 | ||
|
|
100c3dc47d | ||
|
|
986ac117ae | ||
|
|
18aa416035 | ||
|
|
3b3dbabed1 | ||
|
|
af53525cbc | ||
|
|
0079b7defd | ||
|
|
0b2c6967c4 | ||
|
|
c0682ac795 | ||
|
|
01a7faea8f | ||
|
|
b7f32eac5a | ||
|
|
044a7bfc98 | ||
|
|
814265cd33 | ||
|
|
9b7b2ca7b2 | ||
|
|
949f091179 | ||
|
|
51a351760c | ||
|
|
732b2c61ad | ||
|
|
32c2b03c23 | ||
|
|
3bfd999d81 | ||
|
|
9fa79eb026 | ||
|
|
875134247a | ||
|
|
4c2801d5eb | ||
|
|
c911608f60 | ||
|
|
8f1497407f | ||
|
|
10b64ec6f5 | ||
|
|
1a1879483b | ||
|
|
d691cbb7ae | ||
|
|
1b7c9637a5 | ||
|
|
9ff5f158d5 | ||
|
|
b2ff06e8c5 | ||
|
|
c2fc61ddb3 | ||
|
|
6438f6c7c8 | ||
|
|
6bbd777552 | ||
|
|
100482722f | ||
|
|
7ff882bf23 | ||
|
|
6ab768f6ec | ||
|
|
f487736670 |
11
.changeset/brave-lions-sing.md
Normal file
11
.changeset/brave-lions-sing.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add Codex CLI provider with OAuth authentication
|
||||||
|
|
||||||
|
- Added codex-cli provider for GPT-5 and GPT-5-Codex models (272K input / 128K output)
|
||||||
|
- OAuth-first authentication via `codex login` - no API key required
|
||||||
|
- Optional OPENAI_CODEX_API_KEY support
|
||||||
|
- Codebase analysis capabilities automatically enabled
|
||||||
|
- Command-specific settings and approval/sandbox modes
|
||||||
@@ -11,9 +11,6 @@
|
|||||||
"access": "public",
|
"access": "public",
|
||||||
"baseBranch": "main",
|
"baseBranch": "main",
|
||||||
"ignore": [
|
"ignore": [
|
||||||
"docs",
|
"docs"
|
||||||
"@tm/cli",
|
|
||||||
"@tm/core",
|
|
||||||
"@tm/build-config"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
7
.changeset/cursor-slash-commands.md
Normal file
7
.changeset/cursor-slash-commands.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add Cursor IDE custom slash command support
|
||||||
|
|
||||||
|
Expose Task Master commands as Cursor slash commands by copying assets/claude/commands to .cursor/commands on profile add and cleaning up on remove.
|
||||||
5
.changeset/curvy-weeks-flow.md
Normal file
5
.changeset/curvy-weeks-flow.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Change parent task back to "pending" when all subtasks are in "pending" state
|
||||||
5
.changeset/easy-spiders-wave.md
Normal file
5
.changeset/easy-spiders-wave.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Do a quick fix on build
|
||||||
5
.changeset/fix-mcp-connection-errors.md
Normal file
5
.changeset/fix-mcp-connection-errors.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix MCP connection errors caused by deprecated generateTaskFiles calls. Resolves "Cannot read properties of null (reading 'toString')" errors when using MCP tools for task management operations.
|
||||||
5
.changeset/fix-mcp-default-tasks-path.md
Normal file
5
.changeset/fix-mcp-default-tasks-path.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix MCP server error when file parameter not provided - now properly constructs default tasks.json path instead of failing with 'tasksJsonPath is required' error.
|
||||||
5
.changeset/flat-cities-say.md
Normal file
5
.changeset/flat-cities-say.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Added api keys page on docs website: docs.task-master.dev/getting-started/api-keys
|
||||||
10
.changeset/forty-tables-invite.md
Normal file
10
.changeset/forty-tables-invite.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Move to AI SDK v5:
|
||||||
|
|
||||||
|
- Works better with claude-code and gemini-cli as ai providers
|
||||||
|
- Improved openai model family compatibility
|
||||||
|
- Migrate ollama provider to v2
|
||||||
|
- Closes #1223, #1013, #1161, #1174
|
||||||
30
.changeset/gentle-cats-dance.md
Normal file
30
.changeset/gentle-cats-dance.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Migrate AI services to use generateObject for structured data generation
|
||||||
|
|
||||||
|
This update migrates all AI service calls from generateText to generateObject, ensuring more reliable and structured responses across all commands.
|
||||||
|
|
||||||
|
### Key Changes:
|
||||||
|
|
||||||
|
- **Unified AI Service**: Replaced separate generateText implementations with a single generateObjectService that handles structured data generation
|
||||||
|
- **JSON Mode Support**: Added proper JSON mode configuration for providers that support it (OpenAI, Anthropic, Google, Groq)
|
||||||
|
- **Schema Validation**: Integrated Zod schemas for all AI-generated content with automatic validation
|
||||||
|
- **Provider Compatibility**: Maintained compatibility with all existing providers while leveraging their native structured output capabilities
|
||||||
|
- **Improved Reliability**: Structured output generation reduces parsing errors and ensures consistent data formats
|
||||||
|
|
||||||
|
### Technical Improvements:
|
||||||
|
|
||||||
|
- Centralized provider configuration in `ai-providers-unified.js`
|
||||||
|
- Added `generateObject` support detection for each provider
|
||||||
|
- Implemented proper error handling for schema validation failures
|
||||||
|
- Maintained backward compatibility with existing prompt structures
|
||||||
|
|
||||||
|
### Bug Fixes:
|
||||||
|
|
||||||
|
- Fixed subtask ID numbering issue where AI was generating inconsistent IDs (101-105, 601-603) instead of sequential numbering (1, 2, 3...)
|
||||||
|
- Enhanced prompt instructions to enforce proper ID generation patterns
|
||||||
|
- Ensured subtasks display correctly as X.1, X.2, X.3 format
|
||||||
|
|
||||||
|
This migration improves the reliability and consistency of AI-generated content throughout the Task Master application.
|
||||||
17
.changeset/nice-ways-hope.md
Normal file
17
.changeset/nice-ways-hope.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add RPG (Repository Planning Graph) method template for structured PRD creation. The new `example_prd_rpg.txt` template teaches AI agents and developers the RPG methodology through embedded instructions, inline good/bad examples, and XML-style tags for structure. This template enables creation of dependency-aware PRDs that automatically generate topologically-ordered task graphs when parsed with Task Master.
|
||||||
|
|
||||||
|
Key features:
|
||||||
|
- Method-as-template: teaches RPG principles (dual-semantics, explicit dependencies, topological order) while being used
|
||||||
|
- Inline instructions at decision points guide AI through each section
|
||||||
|
- Good/bad examples for immediate pattern matching
|
||||||
|
- Flexible plain-text format with XML-style tags for parseability
|
||||||
|
- Critical dependency-graph section ensures correct task ordering
|
||||||
|
- Automatic inclusion during `task-master init`
|
||||||
|
- Comprehensive documentation at [docs.task-master.dev/capabilities/rpg-method](https://docs.task-master.dev/capabilities/rpg-method)
|
||||||
|
- Tool recommendations for code-context-aware PRD creation (Claude Code, Cursor, Gemini CLI, Codex/Grok)
|
||||||
|
|
||||||
|
The RPG template complements the existing `example_prd.txt` and provides a more structured approach for complex projects requiring clear module boundaries and dependency chains.
|
||||||
26
.changeset/pre.json
Normal file
26
.changeset/pre.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"mode": "pre",
|
||||||
|
"tag": "rc",
|
||||||
|
"initialVersions": {
|
||||||
|
"task-master-ai": "0.27.3",
|
||||||
|
"docs": "0.0.4",
|
||||||
|
"extension": "0.25.4"
|
||||||
|
},
|
||||||
|
"changesets": [
|
||||||
|
"brave-lions-sing",
|
||||||
|
"chore-fix-docs",
|
||||||
|
"cursor-slash-commands",
|
||||||
|
"curvy-weeks-flow",
|
||||||
|
"easy-spiders-wave",
|
||||||
|
"fix-mcp-connection-errors",
|
||||||
|
"fix-mcp-default-tasks-path",
|
||||||
|
"flat-cities-say",
|
||||||
|
"forty-tables-invite",
|
||||||
|
"gentle-cats-dance",
|
||||||
|
"mcp-timeout-configuration",
|
||||||
|
"petite-ideas-grab",
|
||||||
|
"silly-pandas-find",
|
||||||
|
"sweet-maps-rule",
|
||||||
|
"whole-pigs-say"
|
||||||
|
]
|
||||||
|
}
|
||||||
5
.changeset/sweet-maps-rule.md
Normal file
5
.changeset/sweet-maps-rule.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Upgrade grok-cli ai provider to ai sdk v5
|
||||||
8
.changeset/whole-pigs-say.md
Normal file
8
.changeset/whole-pigs-say.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix complexity score not showing for `task-master show` and `task-master list`
|
||||||
|
|
||||||
|
- Added complexity score on "next task" when running `task-master list`
|
||||||
|
- Added colors to complexity to reflect complexity (easy, medium, hard)
|
||||||
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
@@ -6,9 +6,6 @@ on:
|
|||||||
- main
|
- main
|
||||||
- next
|
- next
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- next
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
|
|||||||
5
.github/workflows/extension-ci.yml
vendored
5
.github/workflows/extension-ci.yml
vendored
@@ -41,8 +41,7 @@ jobs:
|
|||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-node-
|
${{ runner.os }}-node-
|
||||||
|
|
||||||
- name: Install Extension Dependencies
|
- name: Install Monorepo Dependencies
|
||||||
working-directory: apps/extension
|
|
||||||
run: npm ci
|
run: npm ci
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
|
|
||||||
@@ -68,7 +67,6 @@ jobs:
|
|||||||
${{ runner.os }}-node-
|
${{ runner.os }}-node-
|
||||||
|
|
||||||
- name: Install if cache miss
|
- name: Install if cache miss
|
||||||
working-directory: apps/extension
|
|
||||||
run: npm ci
|
run: npm ci
|
||||||
timeout-minutes: 3
|
timeout-minutes: 3
|
||||||
|
|
||||||
@@ -100,7 +98,6 @@ jobs:
|
|||||||
${{ runner.os }}-node-
|
${{ runner.os }}-node-
|
||||||
|
|
||||||
- name: Install if cache miss
|
- name: Install if cache miss
|
||||||
working-directory: apps/extension
|
|
||||||
run: npm ci
|
run: npm ci
|
||||||
timeout-minutes: 3
|
timeout-minutes: 3
|
||||||
|
|
||||||
|
|||||||
3
.github/workflows/extension-release.yml
vendored
3
.github/workflows/extension-release.yml
vendored
@@ -31,8 +31,7 @@ jobs:
|
|||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-node-
|
${{ runner.os }}-node-
|
||||||
|
|
||||||
- name: Install Extension Dependencies
|
- name: Install Monorepo Dependencies
|
||||||
working-directory: apps/extension
|
|
||||||
run: npm ci
|
run: npm ci
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
|
|
||||||
|
|||||||
6
.manypkg.json
Normal file
6
.manypkg.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://unpkg.com/@manypkg/get-packages@1.1.3/schema.json",
|
||||||
|
"defaultBranch": "main",
|
||||||
|
"ignoredRules": ["ROOT_HAS_DEPENDENCIES", "INTERNAL_MISMATCH"],
|
||||||
|
"ignoredPackages": ["@tm/core", "@tm/cli", "@tm/build-config"]
|
||||||
|
}
|
||||||
511
.taskmaster/templates/example_prd_rpg.txt
Normal file
511
.taskmaster/templates/example_prd_rpg.txt
Normal file
@@ -0,0 +1,511 @@
|
|||||||
|
<rpg-method>
|
||||||
|
# Repository Planning Graph (RPG) Method - PRD Template
|
||||||
|
|
||||||
|
This template teaches you (AI or human) how to create structured, dependency-aware PRDs using the RPG methodology from Microsoft Research. The key insight: separate WHAT (functional) from HOW (structural), then connect them with explicit dependencies.
|
||||||
|
|
||||||
|
## Core Principles
|
||||||
|
|
||||||
|
1. **Dual-Semantics**: Think functional (capabilities) AND structural (code organization) separately, then map them
|
||||||
|
2. **Explicit Dependencies**: Never assume - always state what depends on what
|
||||||
|
3. **Topological Order**: Build foundation first, then layers on top
|
||||||
|
4. **Progressive Refinement**: Start broad, refine iteratively
|
||||||
|
|
||||||
|
## How to Use This Template
|
||||||
|
|
||||||
|
- Follow the instructions in each `<instruction>` block
|
||||||
|
- Look at `<example>` blocks to see good vs bad patterns
|
||||||
|
- Fill in the content sections with your project details
|
||||||
|
- The AI reading this will learn the RPG method by following along
|
||||||
|
- Task Master will parse the resulting PRD into dependency-aware tasks
|
||||||
|
|
||||||
|
## Recommended Tools for Creating PRDs
|
||||||
|
|
||||||
|
When using this template to **create** a PRD (not parse it), use **code-context-aware AI assistants** for best results:
|
||||||
|
|
||||||
|
**Why?** The AI needs to understand your existing codebase to make good architectural decisions about modules, dependencies, and integration points.
|
||||||
|
|
||||||
|
**Recommended tools:**
|
||||||
|
- **Claude Code** (claude-code CLI) - Best for structured reasoning and large contexts
|
||||||
|
- **Cursor/Windsurf** - IDE integration with full codebase context
|
||||||
|
- **Gemini CLI** (gemini-cli) - Massive context window for large codebases
|
||||||
|
- **Codex/Grok CLI** - Strong code generation with context awareness
|
||||||
|
|
||||||
|
**Note:** Once your PRD is created, `task-master parse-prd` works with any configured AI model - it just needs to read the PRD text itself, not your codebase.
|
||||||
|
</rpg-method>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<overview>
|
||||||
|
<instruction>
|
||||||
|
Start with the problem, not the solution. Be specific about:
|
||||||
|
- What pain point exists?
|
||||||
|
- Who experiences it?
|
||||||
|
- Why existing solutions don't work?
|
||||||
|
- What success looks like (measurable outcomes)?
|
||||||
|
|
||||||
|
Keep this section focused - don't jump into implementation details yet.
|
||||||
|
</instruction>
|
||||||
|
|
||||||
|
## Problem Statement
|
||||||
|
[Describe the core problem. Be concrete about user pain points.]
|
||||||
|
|
||||||
|
## Target Users
|
||||||
|
[Define personas, their workflows, and what they're trying to achieve.]
|
||||||
|
|
||||||
|
## Success Metrics
|
||||||
|
[Quantifiable outcomes. Examples: "80% task completion via autopilot", "< 5% manual intervention rate"]
|
||||||
|
|
||||||
|
</overview>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<functional-decomposition>
|
||||||
|
<instruction>
|
||||||
|
Now think about CAPABILITIES (what the system DOES), not code structure yet.
|
||||||
|
|
||||||
|
Step 1: Identify high-level capability domains
|
||||||
|
- Think: "What major things does this system do?"
|
||||||
|
- Examples: Data Management, Core Processing, Presentation Layer
|
||||||
|
|
||||||
|
Step 2: For each capability, enumerate specific features
|
||||||
|
- Use explore-exploit strategy:
|
||||||
|
* Exploit: What features are REQUIRED for core value?
|
||||||
|
* Explore: What features make this domain COMPLETE?
|
||||||
|
|
||||||
|
Step 3: For each feature, define:
|
||||||
|
- Description: What it does in one sentence
|
||||||
|
- Inputs: What data/context it needs
|
||||||
|
- Outputs: What it produces/returns
|
||||||
|
- Behavior: Key logic or transformations
|
||||||
|
|
||||||
|
<example type="good">
|
||||||
|
Capability: Data Validation
|
||||||
|
Feature: Schema validation
|
||||||
|
- Description: Validate JSON payloads against defined schemas
|
||||||
|
- Inputs: JSON object, schema definition
|
||||||
|
- Outputs: Validation result (pass/fail) + error details
|
||||||
|
- Behavior: Iterate fields, check types, enforce constraints
|
||||||
|
|
||||||
|
Feature: Business rule validation
|
||||||
|
- Description: Apply domain-specific validation rules
|
||||||
|
- Inputs: Validated data object, rule set
|
||||||
|
- Outputs: Boolean + list of violated rules
|
||||||
|
- Behavior: Execute rules sequentially, short-circuit on failure
|
||||||
|
</example>
|
||||||
|
|
||||||
|
<example type="bad">
|
||||||
|
Capability: validation.js
|
||||||
|
(Problem: This is a FILE, not a CAPABILITY. Mixing structure into functional thinking.)
|
||||||
|
|
||||||
|
Capability: Validation
|
||||||
|
Feature: Make sure data is good
|
||||||
|
(Problem: Too vague. No inputs/outputs. Not actionable.)
|
||||||
|
</example>
|
||||||
|
</instruction>
|
||||||
|
|
||||||
|
## Capability Tree
|
||||||
|
|
||||||
|
### Capability: [Name]
|
||||||
|
[Brief description of what this capability domain covers]
|
||||||
|
|
||||||
|
#### Feature: [Name]
|
||||||
|
- **Description**: [One sentence]
|
||||||
|
- **Inputs**: [What it needs]
|
||||||
|
- **Outputs**: [What it produces]
|
||||||
|
- **Behavior**: [Key logic]
|
||||||
|
|
||||||
|
#### Feature: [Name]
|
||||||
|
- **Description**:
|
||||||
|
- **Inputs**:
|
||||||
|
- **Outputs**:
|
||||||
|
- **Behavior**:
|
||||||
|
|
||||||
|
### Capability: [Name]
|
||||||
|
...
|
||||||
|
|
||||||
|
</functional-decomposition>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<structural-decomposition>
|
||||||
|
<instruction>
|
||||||
|
NOW think about code organization. Map capabilities to actual file/folder structure.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
1. Each capability maps to a module (folder or file)
|
||||||
|
2. Features within a capability map to functions/classes
|
||||||
|
3. Use clear module boundaries - each module has ONE responsibility
|
||||||
|
4. Define what each module exports (public interface)
|
||||||
|
|
||||||
|
The goal: Create a clear mapping between "what it does" (functional) and "where it lives" (structural).
|
||||||
|
|
||||||
|
<example type="good">
|
||||||
|
Capability: Data Validation
|
||||||
|
→ Maps to: src/validation/
|
||||||
|
├── schema-validator.js (Schema validation feature)
|
||||||
|
├── rule-validator.js (Business rule validation feature)
|
||||||
|
└── index.js (Public exports)
|
||||||
|
|
||||||
|
Exports:
|
||||||
|
- validateSchema(data, schema)
|
||||||
|
- validateRules(data, rules)
|
||||||
|
</example>
|
||||||
|
|
||||||
|
<example type="bad">
|
||||||
|
Capability: Data Validation
|
||||||
|
→ Maps to: src/utils.js
|
||||||
|
(Problem: "utils" is not a clear module boundary. Where do I find validation logic?)
|
||||||
|
|
||||||
|
Capability: Data Validation
|
||||||
|
→ Maps to: src/validation/everything.js
|
||||||
|
(Problem: One giant file. Features should map to separate files for maintainability.)
|
||||||
|
</example>
|
||||||
|
</instruction>
|
||||||
|
|
||||||
|
## Repository Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
project-root/
|
||||||
|
├── src/
|
||||||
|
│ ├── [module-name]/ # Maps to: [Capability Name]
|
||||||
|
│ │ ├── [file].js # Maps to: [Feature Name]
|
||||||
|
│ │ └── index.js # Public exports
|
||||||
|
│ └── [module-name]/
|
||||||
|
├── tests/
|
||||||
|
└── docs/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Module Definitions
|
||||||
|
|
||||||
|
### Module: [Name]
|
||||||
|
- **Maps to capability**: [Capability from functional decomposition]
|
||||||
|
- **Responsibility**: [Single clear purpose]
|
||||||
|
- **File structure**:
|
||||||
|
```
|
||||||
|
module-name/
|
||||||
|
├── feature1.js
|
||||||
|
├── feature2.js
|
||||||
|
└── index.js
|
||||||
|
```
|
||||||
|
- **Exports**:
|
||||||
|
- `functionName()` - [what it does]
|
||||||
|
- `ClassName` - [what it does]
|
||||||
|
|
||||||
|
</structural-decomposition>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<dependency-graph>
|
||||||
|
<instruction>
|
||||||
|
This is THE CRITICAL SECTION for Task Master parsing.
|
||||||
|
|
||||||
|
Define explicit dependencies between modules. This creates the topological order for task execution.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
1. List modules in dependency order (foundation first)
|
||||||
|
2. For each module, state what it depends on
|
||||||
|
3. Foundation modules should have NO dependencies
|
||||||
|
4. Every non-foundation module should depend on at least one other module
|
||||||
|
5. Think: "What must EXIST before I can build this module?"
|
||||||
|
|
||||||
|
<example type="good">
|
||||||
|
Foundation Layer (no dependencies):
|
||||||
|
- error-handling: No dependencies
|
||||||
|
- config-manager: No dependencies
|
||||||
|
- base-types: No dependencies
|
||||||
|
|
||||||
|
Data Layer:
|
||||||
|
- schema-validator: Depends on [base-types, error-handling]
|
||||||
|
- data-ingestion: Depends on [schema-validator, config-manager]
|
||||||
|
|
||||||
|
Core Layer:
|
||||||
|
- algorithm-engine: Depends on [base-types, error-handling]
|
||||||
|
- pipeline-orchestrator: Depends on [algorithm-engine, data-ingestion]
|
||||||
|
</example>
|
||||||
|
|
||||||
|
<example type="bad">
|
||||||
|
- validation: Depends on API
|
||||||
|
- API: Depends on validation
|
||||||
|
(Problem: Circular dependency. This will cause build/runtime issues.)
|
||||||
|
|
||||||
|
- user-auth: Depends on everything
|
||||||
|
(Problem: Too many dependencies. Should be more focused.)
|
||||||
|
</example>
|
||||||
|
</instruction>
|
||||||
|
|
||||||
|
## Dependency Chain
|
||||||
|
|
||||||
|
### Foundation Layer (Phase 0)
|
||||||
|
No dependencies - these are built first.
|
||||||
|
|
||||||
|
- **[Module Name]**: [What it provides]
|
||||||
|
- **[Module Name]**: [What it provides]
|
||||||
|
|
||||||
|
### [Layer Name] (Phase 1)
|
||||||
|
- **[Module Name]**: Depends on [[module-from-phase-0], [module-from-phase-0]]
|
||||||
|
- **[Module Name]**: Depends on [[module-from-phase-0]]
|
||||||
|
|
||||||
|
### [Layer Name] (Phase 2)
|
||||||
|
- **[Module Name]**: Depends on [[module-from-phase-1], [module-from-foundation]]
|
||||||
|
|
||||||
|
[Continue building up layers...]
|
||||||
|
|
||||||
|
</dependency-graph>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<implementation-roadmap>
|
||||||
|
<instruction>
|
||||||
|
Turn the dependency graph into concrete development phases.
|
||||||
|
|
||||||
|
Each phase should:
|
||||||
|
1. Have clear entry criteria (what must exist before starting)
|
||||||
|
2. Contain tasks that can be parallelized (no inter-dependencies within phase)
|
||||||
|
3. Have clear exit criteria (how do we know phase is complete?)
|
||||||
|
4. Build toward something USABLE (not just infrastructure)
|
||||||
|
|
||||||
|
Phase ordering follows topological sort of dependency graph.
|
||||||
|
|
||||||
|
<example type="good">
|
||||||
|
Phase 0: Foundation
|
||||||
|
Entry: Clean repository
|
||||||
|
Tasks:
|
||||||
|
- Implement error handling utilities
|
||||||
|
- Create base type definitions
|
||||||
|
- Setup configuration system
|
||||||
|
Exit: Other modules can import foundation without errors
|
||||||
|
|
||||||
|
Phase 1: Data Layer
|
||||||
|
Entry: Phase 0 complete
|
||||||
|
Tasks:
|
||||||
|
- Implement schema validator (uses: base types, error handling)
|
||||||
|
- Build data ingestion pipeline (uses: validator, config)
|
||||||
|
Exit: End-to-end data flow from input to validated output
|
||||||
|
</example>
|
||||||
|
|
||||||
|
<example type="bad">
|
||||||
|
Phase 1: Build Everything
|
||||||
|
Tasks:
|
||||||
|
- API
|
||||||
|
- Database
|
||||||
|
- UI
|
||||||
|
- Tests
|
||||||
|
(Problem: No clear focus. Too broad. Dependencies not considered.)
|
||||||
|
</example>
|
||||||
|
</instruction>
|
||||||
|
|
||||||
|
## Development Phases
|
||||||
|
|
||||||
|
### Phase 0: [Foundation Name]
|
||||||
|
**Goal**: [What foundational capability this establishes]
|
||||||
|
|
||||||
|
**Entry Criteria**: [What must be true before starting]
|
||||||
|
|
||||||
|
**Tasks**:
|
||||||
|
- [ ] [Task name] (depends on: [none or list])
|
||||||
|
- Acceptance criteria: [How we know it's done]
|
||||||
|
- Test strategy: [What tests prove it works]
|
||||||
|
|
||||||
|
- [ ] [Task name] (depends on: [none or list])
|
||||||
|
|
||||||
|
**Exit Criteria**: [Observable outcome that proves phase complete]
|
||||||
|
|
||||||
|
**Delivers**: [What can users/developers do after this phase?]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 1: [Layer Name]
|
||||||
|
**Goal**:
|
||||||
|
|
||||||
|
**Entry Criteria**: Phase 0 complete
|
||||||
|
|
||||||
|
**Tasks**:
|
||||||
|
- [ ] [Task name] (depends on: [[tasks-from-phase-0]])
|
||||||
|
- [ ] [Task name] (depends on: [[tasks-from-phase-0]])
|
||||||
|
|
||||||
|
**Exit Criteria**:
|
||||||
|
|
||||||
|
**Delivers**:
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[Continue with more phases...]
|
||||||
|
|
||||||
|
</implementation-roadmap>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<test-strategy>
|
||||||
|
<instruction>
|
||||||
|
Define how testing will be integrated throughout development (TDD approach).
|
||||||
|
|
||||||
|
Specify:
|
||||||
|
1. Test pyramid ratios (unit vs integration vs e2e)
|
||||||
|
2. Coverage requirements
|
||||||
|
3. Critical test scenarios
|
||||||
|
4. Test generation guidelines for Surgical Test Generator
|
||||||
|
|
||||||
|
This section guides the AI when generating tests during the RED phase of TDD.
|
||||||
|
|
||||||
|
<example type="good">
|
||||||
|
Critical Test Scenarios for Data Validation module:
|
||||||
|
- Happy path: Valid data passes all checks
|
||||||
|
- Edge cases: Empty strings, null values, boundary numbers
|
||||||
|
- Error cases: Invalid types, missing required fields
|
||||||
|
- Integration: Validator works with ingestion pipeline
|
||||||
|
</example>
|
||||||
|
</instruction>
|
||||||
|
|
||||||
|
## Test Pyramid
|
||||||
|
|
||||||
|
```
|
||||||
|
/\
|
||||||
|
/E2E\ ← [X]% (End-to-end, slow, comprehensive)
|
||||||
|
/------\
|
||||||
|
/Integration\ ← [Y]% (Module interactions)
|
||||||
|
/------------\
|
||||||
|
/ Unit Tests \ ← [Z]% (Fast, isolated, deterministic)
|
||||||
|
/----------------\
|
||||||
|
```
|
||||||
|
|
||||||
|
## Coverage Requirements
|
||||||
|
- Line coverage: [X]% minimum
|
||||||
|
- Branch coverage: [X]% minimum
|
||||||
|
- Function coverage: [X]% minimum
|
||||||
|
- Statement coverage: [X]% minimum
|
||||||
|
|
||||||
|
## Critical Test Scenarios
|
||||||
|
|
||||||
|
### [Module/Feature Name]
|
||||||
|
**Happy path**:
|
||||||
|
- [Scenario description]
|
||||||
|
- Expected: [What should happen]
|
||||||
|
|
||||||
|
**Edge cases**:
|
||||||
|
- [Scenario description]
|
||||||
|
- Expected: [What should happen]
|
||||||
|
|
||||||
|
**Error cases**:
|
||||||
|
- [Scenario description]
|
||||||
|
- Expected: [How system handles failure]
|
||||||
|
|
||||||
|
**Integration points**:
|
||||||
|
- [What interactions to test]
|
||||||
|
- Expected: [End-to-end behavior]
|
||||||
|
|
||||||
|
## Test Generation Guidelines
|
||||||
|
[Specific instructions for Surgical Test Generator about what to focus on, what patterns to follow, project-specific test conventions]
|
||||||
|
|
||||||
|
</test-strategy>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<architecture>
|
||||||
|
<instruction>
|
||||||
|
Describe technical architecture, data models, and key design decisions.
|
||||||
|
|
||||||
|
Keep this section AFTER functional/structural decomposition - implementation details come after understanding structure.
|
||||||
|
</instruction>
|
||||||
|
|
||||||
|
## System Components
|
||||||
|
[Major architectural pieces and their responsibilities]
|
||||||
|
|
||||||
|
## Data Models
|
||||||
|
[Core data structures, schemas, database design]
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
[Languages, frameworks, key libraries]
|
||||||
|
|
||||||
|
**Decision: [Technology/Pattern]**
|
||||||
|
- **Rationale**: [Why chosen]
|
||||||
|
- **Trade-offs**: [What we're giving up]
|
||||||
|
- **Alternatives considered**: [What else we looked at]
|
||||||
|
|
||||||
|
</architecture>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<risks>
|
||||||
|
<instruction>
|
||||||
|
Identify risks that could derail development and how to mitigate them.
|
||||||
|
|
||||||
|
Categories:
|
||||||
|
- Technical risks (complexity, unknowns)
|
||||||
|
- Dependency risks (blocking issues)
|
||||||
|
- Scope risks (creep, underestimation)
|
||||||
|
</instruction>
|
||||||
|
|
||||||
|
## Technical Risks
|
||||||
|
**Risk**: [Description]
|
||||||
|
- **Impact**: [High/Medium/Low - effect on project]
|
||||||
|
- **Likelihood**: [High/Medium/Low]
|
||||||
|
- **Mitigation**: [How to address]
|
||||||
|
- **Fallback**: [Plan B if mitigation fails]
|
||||||
|
|
||||||
|
## Dependency Risks
|
||||||
|
[External dependencies, blocking issues]
|
||||||
|
|
||||||
|
## Scope Risks
|
||||||
|
[Scope creep, underestimation, unclear requirements]
|
||||||
|
|
||||||
|
</risks>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<appendix>
|
||||||
|
## References
|
||||||
|
[Papers, documentation, similar systems]
|
||||||
|
|
||||||
|
## Glossary
|
||||||
|
[Domain-specific terms]
|
||||||
|
|
||||||
|
## Open Questions
|
||||||
|
[Things to resolve during development]
|
||||||
|
</appendix>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<task-master-integration>
|
||||||
|
# How Task Master Uses This PRD
|
||||||
|
|
||||||
|
When you run `task-master parse-prd <file>.txt`, the parser:
|
||||||
|
|
||||||
|
1. **Extracts capabilities** → Main tasks
|
||||||
|
- Each `### Capability:` becomes a top-level task
|
||||||
|
|
||||||
|
2. **Extracts features** → Subtasks
|
||||||
|
- Each `#### Feature:` becomes a subtask under its capability
|
||||||
|
|
||||||
|
3. **Parses dependencies** → Task dependencies
|
||||||
|
- `Depends on: [X, Y]` sets task.dependencies = ["X", "Y"]
|
||||||
|
|
||||||
|
4. **Orders by phases** → Task priorities
|
||||||
|
- Phase 0 tasks = highest priority
|
||||||
|
- Phase N tasks = lower priority, properly sequenced
|
||||||
|
|
||||||
|
5. **Uses test strategy** → Test generation context
|
||||||
|
- Feeds test scenarios to Surgical Test Generator during implementation
|
||||||
|
|
||||||
|
**Result**: A dependency-aware task graph that can be executed in topological order.
|
||||||
|
|
||||||
|
## Why RPG Structure Matters
|
||||||
|
|
||||||
|
Traditional flat PRDs lead to:
|
||||||
|
- ❌ Unclear task dependencies
|
||||||
|
- ❌ Arbitrary task ordering
|
||||||
|
- ❌ Circular dependencies discovered late
|
||||||
|
- ❌ Poorly scoped tasks
|
||||||
|
|
||||||
|
RPG-structured PRDs provide:
|
||||||
|
- ✅ Explicit dependency chains
|
||||||
|
- ✅ Topological execution order
|
||||||
|
- ✅ Clear module boundaries
|
||||||
|
- ✅ Validated task graph before implementation
|
||||||
|
|
||||||
|
## Tips for Best Results
|
||||||
|
|
||||||
|
1. **Spend time on dependency graph** - This is the most valuable section for Task Master
|
||||||
|
2. **Keep features atomic** - Each feature should be independently testable
|
||||||
|
3. **Progressive refinement** - Start broad, use `task-master expand` to break down complex tasks
|
||||||
|
4. **Use research mode** - `task-master parse-prd --research` leverages AI for better task generation
|
||||||
|
</task-master-integration>
|
||||||
125
CHANGELOG.md
125
CHANGELOG.md
@@ -1,5 +1,130 @@
|
|||||||
# task-master-ai
|
# task-master-ai
|
||||||
|
|
||||||
|
## 0.28.0-rc.2
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- [#1273](https://github.com/eyaltoledano/claude-task-master/pull/1273) [`b43b7ce`](https://github.com/eyaltoledano/claude-task-master/commit/b43b7ce201625eee956fb2f8cd332f238bb78c21) Thanks [@ben-vargas](https://github.com/ben-vargas)! - Add Codex CLI provider with OAuth authentication
|
||||||
|
- Added codex-cli provider for GPT-5 and GPT-5-Codex models (272K input / 128K output)
|
||||||
|
- OAuth-first authentication via `codex login` - no API key required
|
||||||
|
- Optional OPENAI_CODEX_API_KEY support
|
||||||
|
- Codebase analysis capabilities automatically enabled
|
||||||
|
- Command-specific settings and approval/sandbox modes
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#1277](https://github.com/eyaltoledano/claude-task-master/pull/1277) [`7b5a7c4`](https://github.com/eyaltoledano/claude-task-master/commit/7b5a7c4495a68b782f7407fc5d0e0d3ae81f42f5) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix MCP connection errors caused by deprecated generateTaskFiles calls. Resolves "Cannot read properties of null (reading 'toString')" errors when using MCP tools for task management operations.
|
||||||
|
|
||||||
|
- [#1276](https://github.com/eyaltoledano/claude-task-master/pull/1276) [`caee040`](https://github.com/eyaltoledano/claude-task-master/commit/caee040907f856d31a660171c9e6d966f23c632e) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix MCP server error when file parameter not provided - now properly constructs default tasks.json path instead of failing with 'tasksJsonPath is required' error.
|
||||||
|
|
||||||
|
## 0.28.0-rc.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#1274](https://github.com/eyaltoledano/claude-task-master/pull/1274) [`4f984f8`](https://github.com/eyaltoledano/claude-task-master/commit/4f984f8a6965da9f9c7edd60ddfd6560ac022917) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Do a quick fix on build
|
||||||
|
|
||||||
|
## 0.28.0-rc.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- [#1215](https://github.com/eyaltoledano/claude-task-master/pull/1215) [`0079b7d`](https://github.com/eyaltoledano/claude-task-master/commit/0079b7defdad550811f704c470fdd01955d91d4d) Thanks [@joedanz](https://github.com/joedanz)! - Add Cursor IDE custom slash command support
|
||||||
|
|
||||||
|
Expose Task Master commands as Cursor slash commands by copying assets/claude/commands to .cursor/commands on profile add and cleaning up on remove.
|
||||||
|
|
||||||
|
- [#1246](https://github.com/eyaltoledano/claude-task-master/pull/1246) [`18aa416`](https://github.com/eyaltoledano/claude-task-master/commit/18aa416035f44345bde1c7321490345733a5d042) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Added api keys page on docs website: docs.task-master.dev/getting-started/api-keys
|
||||||
|
|
||||||
|
- [#1246](https://github.com/eyaltoledano/claude-task-master/pull/1246) [`18aa416`](https://github.com/eyaltoledano/claude-task-master/commit/18aa416035f44345bde1c7321490345733a5d042) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Move to AI SDK v5:
|
||||||
|
- Works better with claude-code and gemini-cli as ai providers
|
||||||
|
- Improved openai model family compatibility
|
||||||
|
- Migrate ollama provider to v2
|
||||||
|
- Closes #1223, #1013, #1161, #1174
|
||||||
|
|
||||||
|
- [#1262](https://github.com/eyaltoledano/claude-task-master/pull/1262) [`738ec51`](https://github.com/eyaltoledano/claude-task-master/commit/738ec51c049a295a12839b2dfddaf05e23b8fede) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Migrate AI services to use generateObject for structured data generation
|
||||||
|
|
||||||
|
This update migrates all AI service calls from generateText to generateObject, ensuring more reliable and structured responses across all commands.
|
||||||
|
|
||||||
|
### Key Changes:
|
||||||
|
- **Unified AI Service**: Replaced separate generateText implementations with a single generateObjectService that handles structured data generation
|
||||||
|
- **JSON Mode Support**: Added proper JSON mode configuration for providers that support it (OpenAI, Anthropic, Google, Groq)
|
||||||
|
- **Schema Validation**: Integrated Zod schemas for all AI-generated content with automatic validation
|
||||||
|
- **Provider Compatibility**: Maintained compatibility with all existing providers while leveraging their native structured output capabilities
|
||||||
|
- **Improved Reliability**: Structured output generation reduces parsing errors and ensures consistent data formats
|
||||||
|
|
||||||
|
### Technical Improvements:
|
||||||
|
- Centralized provider configuration in `ai-providers-unified.js`
|
||||||
|
- Added `generateObject` support detection for each provider
|
||||||
|
- Implemented proper error handling for schema validation failures
|
||||||
|
- Maintained backward compatibility with existing prompt structures
|
||||||
|
|
||||||
|
### Bug Fixes:
|
||||||
|
- Fixed subtask ID numbering issue where AI was generating inconsistent IDs (101-105, 601-603) instead of sequential numbering (1, 2, 3...)
|
||||||
|
- Enhanced prompt instructions to enforce proper ID generation patterns
|
||||||
|
- Ensured subtasks display correctly as X.1, X.2, X.3 format
|
||||||
|
|
||||||
|
This migration improves the reliability and consistency of AI-generated content throughout the Task Master application.
|
||||||
|
|
||||||
|
- [#1112](https://github.com/eyaltoledano/claude-task-master/pull/1112) [`d67b81d`](https://github.com/eyaltoledano/claude-task-master/commit/d67b81d25ddd927fabb6f5deb368e8993519c541) Thanks [@olssonsten](https://github.com/olssonsten)! - Enhanced Roo Code profile with MCP timeout configuration for improved reliability during long-running AI operations. The Roo profile now automatically configures a 300-second timeout for MCP server operations, preventing timeouts during complex tasks like `parse-prd`, `expand-all`, `analyze-complexity`, and `research` operations. This change also replaces static MCP configuration files with programmatic generation for better maintainability.
|
||||||
|
|
||||||
|
**What's New:**
|
||||||
|
- 300-second timeout for MCP operations (up from default 60 seconds)
|
||||||
|
- Programmatic MCP configuration generation (replaces static asset files)
|
||||||
|
- Enhanced reliability for AI-powered operations
|
||||||
|
- Consistent with other AI coding assistant profiles
|
||||||
|
|
||||||
|
**Migration:** No user action required - existing Roo Code installations will automatically receive the enhanced MCP configuration on next initialization.
|
||||||
|
|
||||||
|
- [#1246](https://github.com/eyaltoledano/claude-task-master/pull/1246) [`986ac11`](https://github.com/eyaltoledano/claude-task-master/commit/986ac117aee00bcd3e6830a0f76e1ad6d10e0bca) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Upgrade grok-cli ai provider to ai sdk v5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#1235](https://github.com/eyaltoledano/claude-task-master/pull/1235) [`aaacc3d`](https://github.com/eyaltoledano/claude-task-master/commit/aaacc3dae36247b4de72b2d2697f49e5df6d01e3) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Improve `analyze-complexity` cli docs and `--research` flag documentation
|
||||||
|
|
||||||
|
- [#1251](https://github.com/eyaltoledano/claude-task-master/pull/1251) [`0b2c696`](https://github.com/eyaltoledano/claude-task-master/commit/0b2c6967c4605c33a100cff16f6ce8ff09ad06f0) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Change parent task back to "pending" when all subtasks are in "pending" state
|
||||||
|
|
||||||
|
- [#1172](https://github.com/eyaltoledano/claude-task-master/pull/1172) [`b5fe723`](https://github.com/eyaltoledano/claude-task-master/commit/b5fe723f8ead928e9f2dbde13b833ee70ac3382d) Thanks [@jujax](https://github.com/jujax)! - Fix Claude Code settings validation for pathToClaudeCodeExecutable
|
||||||
|
|
||||||
|
- [#1192](https://github.com/eyaltoledano/claude-task-master/pull/1192) [`2b69936`](https://github.com/eyaltoledano/claude-task-master/commit/2b69936ee7b34346d6de5175af20e077359e2e2a) Thanks [@nukunga](https://github.com/nukunga)! - Fix sonar deep research model failing, should be called `sonar-deep-research`
|
||||||
|
|
||||||
|
- [#1270](https://github.com/eyaltoledano/claude-task-master/pull/1270) [`20004a3`](https://github.com/eyaltoledano/claude-task-master/commit/20004a39ea848f747e1ff48981bfe176554e4055) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix complexity score not showing for `task-master show` and `task-master list`
|
||||||
|
- Added complexity score on "next task" when running `task-master list`
|
||||||
|
- Added colors to complexity to reflect complexity (easy, medium, hard)
|
||||||
|
|
||||||
|
## 0.27.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#1254](https://github.com/eyaltoledano/claude-task-master/pull/1254) [`af53525`](https://github.com/eyaltoledano/claude-task-master/commit/af53525cbc660a595b67d4bb90d906911c71f45d) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fixed issue where `tm show` command could not find subtasks using dotted notation IDs (e.g., '8.1').
|
||||||
|
- The command now properly searches within parent task subtasks and returns the correct subtask information.
|
||||||
|
|
||||||
|
## 0.27.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#1248](https://github.com/eyaltoledano/claude-task-master/pull/1248) [`044a7bf`](https://github.com/eyaltoledano/claude-task-master/commit/044a7bfc98049298177bc655cf341d7a8b6a0011) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix set-status for subtasks:
|
||||||
|
- Parent tasks are now set as `done` when subtasks are all `done`
|
||||||
|
- Parent tasks are now set as `in-progress` when at least one subtask is `in-progress` or `done`
|
||||||
|
|
||||||
|
## 0.27.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#1232](https://github.com/eyaltoledano/claude-task-master/pull/1232) [`f487736`](https://github.com/eyaltoledano/claude-task-master/commit/f487736670ef8c484059f676293777eabb249c9e) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix module not found for new 0.27.0 release
|
||||||
|
|
||||||
|
- [#1233](https://github.com/eyaltoledano/claude-task-master/pull/1233) [`c911608`](https://github.com/eyaltoledano/claude-task-master/commit/c911608f60454253f4e024b57ca84e5a5a53f65c) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix Zed MCP configuration by adding required "source" property
|
||||||
|
- Add "source": "custom" property to task-master-ai server in Zed settings.json
|
||||||
|
|
||||||
|
## 0.27.1-rc.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#1233](https://github.com/eyaltoledano/claude-task-master/pull/1233) [`1a18794`](https://github.com/eyaltoledano/claude-task-master/commit/1a1879483b86c118a4e46c02cbf4acebfcf6bcf9) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - One last testing final final
|
||||||
|
|
||||||
|
## 0.27.1-rc.0
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#1232](https://github.com/eyaltoledano/claude-task-master/pull/1232) [`f487736`](https://github.com/eyaltoledano/claude-task-master/commit/f487736670ef8c484059f676293777eabb249c9e) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix module not found for new 0.27.0 release
|
||||||
|
|
||||||
## 0.27.0
|
## 0.27.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|||||||
22
CLAUDE.md
22
CLAUDE.md
@@ -4,6 +4,28 @@
|
|||||||
**Import Task Master's development workflow commands and guidelines, treat as if import is in the main CLAUDE.md file.**
|
**Import Task Master's development workflow commands and guidelines, treat as if import is in the main CLAUDE.md file.**
|
||||||
@./.taskmaster/CLAUDE.md
|
@./.taskmaster/CLAUDE.md
|
||||||
|
|
||||||
|
## Test Guidelines
|
||||||
|
|
||||||
|
### Synchronous Tests
|
||||||
|
- **NEVER use async/await in test functions** unless testing actual asynchronous operations
|
||||||
|
- Use synchronous top-level imports instead of dynamic `await import()`
|
||||||
|
- Test bodies should be synchronous whenever possible
|
||||||
|
- Example:
|
||||||
|
```javascript
|
||||||
|
// ✅ CORRECT - Synchronous imports
|
||||||
|
import { MyClass } from '../src/my-class.js';
|
||||||
|
|
||||||
|
it('should verify behavior', () => {
|
||||||
|
expect(new MyClass().property).toBe(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// ❌ INCORRECT - Async imports
|
||||||
|
it('should verify behavior', async () => {
|
||||||
|
const { MyClass } = await import('../src/my-class.js');
|
||||||
|
expect(new MyClass().property).toBe(value);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## Changeset Guidelines
|
## Changeset Guidelines
|
||||||
|
|
||||||
- When creating changesets, remember that it's user-facing, meaning we don't have to get into the specifics of the code, but rather mention what the end-user is getting or fixing from this changeset.
|
- When creating changesets, remember that it's user-facing, meaning we don't have to get into the specifics of the code, but rather mention what the end-user is getting or fixing from this changeset.
|
||||||
@@ -88,8 +88,9 @@ At least one (1) of the following is required:
|
|||||||
- xAI API Key (for research or main model)
|
- xAI API Key (for research or main model)
|
||||||
- OpenRouter API Key (for research or main model)
|
- OpenRouter API Key (for research or main model)
|
||||||
- Claude Code (no API key required - requires Claude Code CLI)
|
- Claude Code (no API key required - requires Claude Code CLI)
|
||||||
|
- Codex CLI (OAuth via ChatGPT subscription - requires Codex CLI)
|
||||||
|
|
||||||
Using the research model is optional but highly recommended. You will need at least ONE API key (unless using Claude Code). Adding all API keys enables you to seamlessly switch between model providers at will.
|
Using the research model is optional but highly recommended. You will need at least ONE API key (unless using Claude Code or Codex CLI with OAuth). Adding all API keys enables you to seamlessly switch between model providers at will.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -105,10 +106,11 @@ MCP (Model Control Protocol) lets you run Task Master directly from your editor.
|
|||||||
| | Project | `<project_folder>/.cursor/mcp.json` | `<project_folder>\.cursor\mcp.json` | `mcpServers` |
|
| | Project | `<project_folder>/.cursor/mcp.json` | `<project_folder>\.cursor\mcp.json` | `mcpServers` |
|
||||||
| **Windsurf** | Global | `~/.codeium/windsurf/mcp_config.json` | `%USERPROFILE%\.codeium\windsurf\mcp_config.json` | `mcpServers` |
|
| **Windsurf** | Global | `~/.codeium/windsurf/mcp_config.json` | `%USERPROFILE%\.codeium\windsurf\mcp_config.json` | `mcpServers` |
|
||||||
| **VS Code** | Project | `<project_folder>/.vscode/mcp.json` | `<project_folder>\.vscode\mcp.json` | `servers` |
|
| **VS Code** | Project | `<project_folder>/.vscode/mcp.json` | `<project_folder>\.vscode\mcp.json` | `servers` |
|
||||||
|
| **Q CLI** | Global | `~/.aws/amazonq/mcp.json` | | `mcpServers` |
|
||||||
|
|
||||||
##### Manual Configuration
|
##### Manual Configuration
|
||||||
|
|
||||||
###### Cursor & Windsurf (`mcpServers`)
|
###### Cursor & Windsurf & Q Developer CLI (`mcpServers`)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
# @tm/cli
|
# @tm/cli
|
||||||
|
|
||||||
|
## null
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies []:
|
||||||
|
- @tm/core@null
|
||||||
|
|
||||||
## 0.27.0
|
## 0.27.0
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@tm/cli",
|
"name": "@tm/cli",
|
||||||
"version": "0.27.0",
|
|
||||||
"description": "Task Master CLI - Command line interface for task management",
|
"description": "Task Master CLI - Command line interface for task management",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
@@ -24,19 +23,19 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tm/core": "*",
|
"@tm/core": "*",
|
||||||
"boxen": "^7.1.1",
|
"boxen": "^8.0.1",
|
||||||
"chalk": "5.6.2",
|
"chalk": "5.6.2",
|
||||||
"cli-table3": "^0.6.5",
|
"cli-table3": "^0.6.5",
|
||||||
"commander": "^12.1.0",
|
"commander": "^12.1.0",
|
||||||
"inquirer": "^9.2.10",
|
"inquirer": "^12.5.0",
|
||||||
"ora": "^8.1.0"
|
"ora": "^8.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^1.9.4",
|
"@biomejs/biome": "^1.9.4",
|
||||||
"@types/inquirer": "^9.0.3",
|
"@types/inquirer": "^9.0.3",
|
||||||
"@types/node": "^22.10.5",
|
"@types/node": "^22.10.5",
|
||||||
"tsx": "^4.20.4",
|
"tsx": "^4.20.4",
|
||||||
"typescript": "^5.7.3",
|
"typescript": "^5.9.2",
|
||||||
"vitest": "^2.1.8"
|
"vitest": "^2.1.8"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
255
apps/cli/src/command-registry.ts
Normal file
255
apps/cli/src/command-registry.ts
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
/**
|
||||||
|
* @fileoverview Centralized Command Registry
|
||||||
|
* Provides a single location for registering all CLI commands
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Command } from 'commander';
|
||||||
|
|
||||||
|
// Import all commands
|
||||||
|
import { ListTasksCommand } from './commands/list.command.js';
|
||||||
|
import { ShowCommand } from './commands/show.command.js';
|
||||||
|
import { AuthCommand } from './commands/auth.command.js';
|
||||||
|
import { ContextCommand } from './commands/context.command.js';
|
||||||
|
import { StartCommand } from './commands/start.command.js';
|
||||||
|
import { SetStatusCommand } from './commands/set-status.command.js';
|
||||||
|
import { ExportCommand } from './commands/export.command.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command metadata for registration
|
||||||
|
*/
|
||||||
|
export interface CommandMetadata {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
commandClass: typeof Command;
|
||||||
|
category?: 'task' | 'auth' | 'utility' | 'development';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registry of all available commands
|
||||||
|
*/
|
||||||
|
export class CommandRegistry {
|
||||||
|
/**
|
||||||
|
* All available commands with their metadata
|
||||||
|
*/
|
||||||
|
private static commands: CommandMetadata[] = [
|
||||||
|
// Task Management Commands
|
||||||
|
{
|
||||||
|
name: 'list',
|
||||||
|
description: 'List all tasks with filtering and status overview',
|
||||||
|
commandClass: ListTasksCommand as any,
|
||||||
|
category: 'task'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'show',
|
||||||
|
description: 'Display detailed information about a specific task',
|
||||||
|
commandClass: ShowCommand as any,
|
||||||
|
category: 'task'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'start',
|
||||||
|
description: 'Start working on a task with claude-code',
|
||||||
|
commandClass: StartCommand as any,
|
||||||
|
category: 'task'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'set-status',
|
||||||
|
description: 'Update the status of one or more tasks',
|
||||||
|
commandClass: SetStatusCommand as any,
|
||||||
|
category: 'task'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'export',
|
||||||
|
description: 'Export tasks to external systems',
|
||||||
|
commandClass: ExportCommand as any,
|
||||||
|
category: 'task'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Authentication & Context Commands
|
||||||
|
{
|
||||||
|
name: 'auth',
|
||||||
|
description: 'Manage authentication with tryhamster.com',
|
||||||
|
commandClass: AuthCommand as any,
|
||||||
|
category: 'auth'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'context',
|
||||||
|
description: 'Manage workspace context (organization/brief)',
|
||||||
|
commandClass: ContextCommand as any,
|
||||||
|
category: 'auth'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register all commands on a program instance
|
||||||
|
* @param program - Commander program to register commands on
|
||||||
|
*/
|
||||||
|
static registerAll(program: Command): void {
|
||||||
|
for (const cmd of this.commands) {
|
||||||
|
this.registerCommand(program, cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register specific commands by category
|
||||||
|
* @param program - Commander program to register commands on
|
||||||
|
* @param category - Category of commands to register
|
||||||
|
*/
|
||||||
|
static registerByCategory(
|
||||||
|
program: Command,
|
||||||
|
category: 'task' | 'auth' | 'utility' | 'development'
|
||||||
|
): void {
|
||||||
|
const categoryCommands = this.commands.filter(
|
||||||
|
(cmd) => cmd.category === category
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const cmd of categoryCommands) {
|
||||||
|
this.registerCommand(program, cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a single command by name
|
||||||
|
* @param program - Commander program to register the command on
|
||||||
|
* @param name - Name of the command to register
|
||||||
|
*/
|
||||||
|
static registerByName(program: Command, name: string): void {
|
||||||
|
const cmd = this.commands.find((c) => c.name === name);
|
||||||
|
if (cmd) {
|
||||||
|
this.registerCommand(program, cmd);
|
||||||
|
} else {
|
||||||
|
throw new Error(`Command '${name}' not found in registry`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a single command
|
||||||
|
* @param program - Commander program to register the command on
|
||||||
|
* @param metadata - Command metadata
|
||||||
|
*/
|
||||||
|
private static registerCommand(
|
||||||
|
program: Command,
|
||||||
|
metadata: CommandMetadata
|
||||||
|
): void {
|
||||||
|
const CommandClass = metadata.commandClass as any;
|
||||||
|
|
||||||
|
// Use the static registration method that all commands have
|
||||||
|
if (CommandClass.registerOn) {
|
||||||
|
CommandClass.registerOn(program);
|
||||||
|
} else if (CommandClass.register) {
|
||||||
|
CommandClass.register(program);
|
||||||
|
} else {
|
||||||
|
// Fallback to creating instance and adding
|
||||||
|
const instance = new CommandClass();
|
||||||
|
program.addCommand(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all registered command names
|
||||||
|
*/
|
||||||
|
static getCommandNames(): string[] {
|
||||||
|
return this.commands.map((cmd) => cmd.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get commands by category
|
||||||
|
*/
|
||||||
|
static getCommandsByCategory(
|
||||||
|
category: 'task' | 'auth' | 'utility' | 'development'
|
||||||
|
): CommandMetadata[] {
|
||||||
|
return this.commands.filter((cmd) => cmd.category === category);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new command to the registry
|
||||||
|
* @param metadata - Command metadata to add
|
||||||
|
*/
|
||||||
|
static addCommand(metadata: CommandMetadata): void {
|
||||||
|
// Check if command already exists
|
||||||
|
if (this.commands.some((cmd) => cmd.name === metadata.name)) {
|
||||||
|
throw new Error(`Command '${metadata.name}' already exists in registry`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.commands.push(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a command from the registry
|
||||||
|
* @param name - Name of the command to remove
|
||||||
|
*/
|
||||||
|
static removeCommand(name: string): boolean {
|
||||||
|
const index = this.commands.findIndex((cmd) => cmd.name === name);
|
||||||
|
if (index >= 0) {
|
||||||
|
this.commands.splice(index, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get command metadata by name
|
||||||
|
* @param name - Name of the command
|
||||||
|
*/
|
||||||
|
static getCommand(name: string): CommandMetadata | undefined {
|
||||||
|
return this.commands.find((cmd) => cmd.name === name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a command exists
|
||||||
|
* @param name - Name of the command
|
||||||
|
*/
|
||||||
|
static hasCommand(name: string): boolean {
|
||||||
|
return this.commands.some((cmd) => cmd.name === name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a formatted list of all commands for display
|
||||||
|
*/
|
||||||
|
static getFormattedCommandList(): string {
|
||||||
|
const categories = {
|
||||||
|
task: 'Task Management',
|
||||||
|
auth: 'Authentication & Context',
|
||||||
|
utility: 'Utilities',
|
||||||
|
development: 'Development'
|
||||||
|
};
|
||||||
|
|
||||||
|
let output = '';
|
||||||
|
|
||||||
|
for (const [category, title] of Object.entries(categories)) {
|
||||||
|
const cmds = this.getCommandsByCategory(
|
||||||
|
category as keyof typeof categories
|
||||||
|
);
|
||||||
|
if (cmds.length > 0) {
|
||||||
|
output += `\n${title}:\n`;
|
||||||
|
for (const cmd of cmds) {
|
||||||
|
output += ` ${cmd.name.padEnd(20)} ${cmd.description}\n`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience function to register all CLI commands
|
||||||
|
* @param program - Commander program instance
|
||||||
|
*/
|
||||||
|
export function registerAllCommands(program: Command): void {
|
||||||
|
CommandRegistry.registerAll(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience function to register commands by category
|
||||||
|
* @param program - Commander program instance
|
||||||
|
* @param category - Category to register
|
||||||
|
*/
|
||||||
|
export function registerCommandsByCategory(
|
||||||
|
program: Command,
|
||||||
|
category: 'task' | 'auth' | 'utility' | 'development'
|
||||||
|
): void {
|
||||||
|
CommandRegistry.registerByCategory(program, category);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export the registry for direct access if needed
|
||||||
|
export default CommandRegistry;
|
||||||
@@ -493,18 +493,7 @@ export class AuthCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static method to register this command on an existing program
|
* Register this command on an existing program
|
||||||
* This is for gradual migration - allows commands.js to use this
|
|
||||||
*/
|
|
||||||
static registerOn(program: Command): Command {
|
|
||||||
const authCommand = new AuthCommand();
|
|
||||||
program.addCommand(authCommand);
|
|
||||||
return authCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alternative registration that returns the command for chaining
|
|
||||||
* Can also configure the command name if needed
|
|
||||||
*/
|
*/
|
||||||
static register(program: Command, name?: string): AuthCommand {
|
static register(program: Command, name?: string): AuthCommand {
|
||||||
const authCommand = new AuthCommand(name);
|
const authCommand = new AuthCommand(name);
|
||||||
|
|||||||
@@ -694,16 +694,7 @@ export class ContextCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static method to register this command on an existing program
|
* Register this command on an existing program
|
||||||
*/
|
|
||||||
static registerOn(program: Command): Command {
|
|
||||||
const contextCommand = new ContextCommand();
|
|
||||||
program.addCommand(contextCommand);
|
|
||||||
return contextCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alternative registration that returns the command for chaining
|
|
||||||
*/
|
*/
|
||||||
static register(program: Command, name?: string): ContextCommand {
|
static register(program: Command, name?: string): ContextCommand {
|
||||||
const contextCommand = new ContextCommand(name);
|
const contextCommand = new ContextCommand(name);
|
||||||
|
|||||||
379
apps/cli/src/commands/export.command.ts
Normal file
379
apps/cli/src/commands/export.command.ts
Normal file
@@ -0,0 +1,379 @@
|
|||||||
|
/**
|
||||||
|
* @fileoverview Export command for exporting tasks to external systems
|
||||||
|
* Provides functionality to export tasks to Hamster briefs
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Command } from 'commander';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
import inquirer from 'inquirer';
|
||||||
|
import ora, { Ora } from 'ora';
|
||||||
|
import {
|
||||||
|
AuthManager,
|
||||||
|
AuthenticationError,
|
||||||
|
type UserContext
|
||||||
|
} from '@tm/core/auth';
|
||||||
|
import { TaskMasterCore, type ExportResult } from '@tm/core';
|
||||||
|
import * as ui from '../utils/ui.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result type from export command
|
||||||
|
*/
|
||||||
|
export interface ExportCommandResult {
|
||||||
|
success: boolean;
|
||||||
|
action: 'export' | 'validate' | 'cancelled';
|
||||||
|
result?: ExportResult;
|
||||||
|
message?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ExportCommand extending Commander's Command class
|
||||||
|
* Handles task export to external systems
|
||||||
|
*/
|
||||||
|
export class ExportCommand extends Command {
|
||||||
|
private authManager: AuthManager;
|
||||||
|
private taskMasterCore?: TaskMasterCore;
|
||||||
|
private lastResult?: ExportCommandResult;
|
||||||
|
|
||||||
|
constructor(name?: string) {
|
||||||
|
super(name || 'export');
|
||||||
|
|
||||||
|
// Initialize auth manager
|
||||||
|
this.authManager = AuthManager.getInstance();
|
||||||
|
|
||||||
|
// Configure the command
|
||||||
|
this.description('Export tasks to external systems (e.g., Hamster briefs)');
|
||||||
|
|
||||||
|
// Add options
|
||||||
|
this.option('--org <id>', 'Organization ID to export to');
|
||||||
|
this.option('--brief <id>', 'Brief ID to export tasks to');
|
||||||
|
this.option('--tag <tag>', 'Export tasks from a specific tag');
|
||||||
|
this.option(
|
||||||
|
'--status <status>',
|
||||||
|
'Filter tasks by status (pending, in-progress, done, etc.)'
|
||||||
|
);
|
||||||
|
this.option('--exclude-subtasks', 'Exclude subtasks from export');
|
||||||
|
this.option('-y, --yes', 'Skip confirmation prompt');
|
||||||
|
|
||||||
|
// Accept optional positional argument for brief ID or Hamster URL
|
||||||
|
this.argument('[briefOrUrl]', 'Brief ID or Hamster brief URL');
|
||||||
|
|
||||||
|
// Default action
|
||||||
|
this.action(async (briefOrUrl?: string, options?: any) => {
|
||||||
|
await this.executeExport(briefOrUrl, options);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the TaskMasterCore
|
||||||
|
*/
|
||||||
|
private async initializeServices(): Promise<void> {
|
||||||
|
if (this.taskMasterCore) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize TaskMasterCore
|
||||||
|
this.taskMasterCore = await TaskMasterCore.create({
|
||||||
|
projectPath: process.cwd()
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to initialize services: ${(error as Error).message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the export command
|
||||||
|
*/
|
||||||
|
private async executeExport(
|
||||||
|
briefOrUrl?: string,
|
||||||
|
options?: any
|
||||||
|
): Promise<void> {
|
||||||
|
let spinner: Ora | undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check authentication
|
||||||
|
if (!this.authManager.isAuthenticated()) {
|
||||||
|
ui.displayError('Not authenticated. Run "tm auth login" first.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize services
|
||||||
|
await this.initializeServices();
|
||||||
|
|
||||||
|
// Get current context
|
||||||
|
const context = this.authManager.getContext();
|
||||||
|
|
||||||
|
// Determine org and brief IDs
|
||||||
|
let orgId = options?.org || context?.orgId;
|
||||||
|
let briefId = options?.brief || briefOrUrl || context?.briefId;
|
||||||
|
|
||||||
|
// If a URL/ID was provided as argument, resolve it
|
||||||
|
if (briefOrUrl && !options?.brief) {
|
||||||
|
spinner = ora('Resolving brief...').start();
|
||||||
|
const resolvedBrief = await this.resolveBriefInput(briefOrUrl);
|
||||||
|
if (resolvedBrief) {
|
||||||
|
briefId = resolvedBrief.briefId;
|
||||||
|
orgId = resolvedBrief.orgId;
|
||||||
|
spinner.succeed('Brief resolved');
|
||||||
|
} else {
|
||||||
|
spinner.fail('Could not resolve brief');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate we have necessary IDs
|
||||||
|
if (!orgId) {
|
||||||
|
ui.displayError(
|
||||||
|
'No organization selected. Run "tm context org" or use --org flag.'
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!briefId) {
|
||||||
|
ui.displayError(
|
||||||
|
'No brief specified. Run "tm context brief", provide a brief ID/URL, or use --brief flag.'
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirm export if not auto-confirmed
|
||||||
|
if (!options?.yes) {
|
||||||
|
const confirmed = await this.confirmExport(orgId, briefId, context);
|
||||||
|
if (!confirmed) {
|
||||||
|
ui.displayWarning('Export cancelled');
|
||||||
|
this.lastResult = {
|
||||||
|
success: false,
|
||||||
|
action: 'cancelled',
|
||||||
|
message: 'User cancelled export'
|
||||||
|
};
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform export
|
||||||
|
spinner = ora('Exporting tasks...').start();
|
||||||
|
|
||||||
|
const exportResult = await this.taskMasterCore!.exportTasks({
|
||||||
|
orgId,
|
||||||
|
briefId,
|
||||||
|
tag: options?.tag,
|
||||||
|
status: options?.status,
|
||||||
|
excludeSubtasks: options?.excludeSubtasks || false
|
||||||
|
});
|
||||||
|
|
||||||
|
if (exportResult.success) {
|
||||||
|
spinner.succeed(
|
||||||
|
`Successfully exported ${exportResult.taskCount} task(s) to brief`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Display summary
|
||||||
|
console.log(chalk.cyan('\n📤 Export Summary\n'));
|
||||||
|
console.log(chalk.white(` Organization: ${orgId}`));
|
||||||
|
console.log(chalk.white(` Brief: ${briefId}`));
|
||||||
|
console.log(chalk.white(` Tasks exported: ${exportResult.taskCount}`));
|
||||||
|
if (options?.tag) {
|
||||||
|
console.log(chalk.gray(` Tag: ${options.tag}`));
|
||||||
|
}
|
||||||
|
if (options?.status) {
|
||||||
|
console.log(chalk.gray(` Status filter: ${options.status}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exportResult.message) {
|
||||||
|
console.log(chalk.gray(`\n ${exportResult.message}`));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spinner.fail('Export failed');
|
||||||
|
if (exportResult.error) {
|
||||||
|
console.error(chalk.red(`\n✗ ${exportResult.error.message}`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastResult = {
|
||||||
|
success: exportResult.success,
|
||||||
|
action: 'export',
|
||||||
|
result: exportResult
|
||||||
|
};
|
||||||
|
} catch (error: any) {
|
||||||
|
if (spinner?.isSpinning) spinner.fail('Export failed');
|
||||||
|
this.handleError(error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve brief input to get brief and org IDs
|
||||||
|
*/
|
||||||
|
private async resolveBriefInput(
|
||||||
|
briefOrUrl: string
|
||||||
|
): Promise<{ briefId: string; orgId: string } | null> {
|
||||||
|
try {
|
||||||
|
// Extract brief ID from input
|
||||||
|
const briefId = this.extractBriefId(briefOrUrl);
|
||||||
|
if (!briefId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch brief to get organization
|
||||||
|
const brief = await this.authManager.getBrief(briefId);
|
||||||
|
if (!brief) {
|
||||||
|
ui.displayError('Brief not found or you do not have access');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
briefId: brief.id,
|
||||||
|
orgId: brief.accountId
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error(chalk.red(`Failed to resolve brief: ${error}`));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract a brief ID from raw input (ID or URL)
|
||||||
|
*/
|
||||||
|
private extractBriefId(input: string): string | null {
|
||||||
|
const raw = input?.trim() ?? '';
|
||||||
|
if (!raw) return null;
|
||||||
|
|
||||||
|
const parseUrl = (s: string): URL | null => {
|
||||||
|
try {
|
||||||
|
return new URL(s);
|
||||||
|
} catch {}
|
||||||
|
try {
|
||||||
|
return new URL(`https://${s}`);
|
||||||
|
} catch {}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const fromParts = (path: string): string | null => {
|
||||||
|
const parts = path.split('/').filter(Boolean);
|
||||||
|
const briefsIdx = parts.lastIndexOf('briefs');
|
||||||
|
const candidate =
|
||||||
|
briefsIdx >= 0 && parts.length > briefsIdx + 1
|
||||||
|
? parts[briefsIdx + 1]
|
||||||
|
: parts[parts.length - 1];
|
||||||
|
return candidate?.trim() || null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Try URL parsing
|
||||||
|
const url = parseUrl(raw);
|
||||||
|
if (url) {
|
||||||
|
const qId = url.searchParams.get('id') || url.searchParams.get('briefId');
|
||||||
|
const candidate = (qId || fromParts(url.pathname)) ?? null;
|
||||||
|
if (candidate) {
|
||||||
|
if (this.isLikelyId(candidate) || candidate.length >= 8) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it looks like a path
|
||||||
|
if (raw.includes('/')) {
|
||||||
|
const candidate = fromParts(raw);
|
||||||
|
if (candidate && (this.isLikelyId(candidate) || candidate.length >= 8)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return raw if it looks like an ID
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a string looks like a brief ID
|
||||||
|
*/
|
||||||
|
private isLikelyId(value: string): boolean {
|
||||||
|
const uuidRegex =
|
||||||
|
/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
||||||
|
const ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/i;
|
||||||
|
const slugRegex = /^[A-Za-z0-9_-]{16,}$/;
|
||||||
|
return (
|
||||||
|
uuidRegex.test(value) || ulidRegex.test(value) || slugRegex.test(value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirm export with the user
|
||||||
|
*/
|
||||||
|
private async confirmExport(
|
||||||
|
orgId: string,
|
||||||
|
briefId: string,
|
||||||
|
context: UserContext | null
|
||||||
|
): Promise<boolean> {
|
||||||
|
console.log(chalk.cyan('\n📤 Export Tasks\n'));
|
||||||
|
|
||||||
|
// Show org name if available
|
||||||
|
if (context?.orgName) {
|
||||||
|
console.log(chalk.white(` Organization: ${context.orgName}`));
|
||||||
|
console.log(chalk.gray(` ID: ${orgId}`));
|
||||||
|
} else {
|
||||||
|
console.log(chalk.white(` Organization ID: ${orgId}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show brief info
|
||||||
|
if (context?.briefName) {
|
||||||
|
console.log(chalk.white(`\n Brief: ${context.briefName}`));
|
||||||
|
console.log(chalk.gray(` ID: ${briefId}`));
|
||||||
|
} else {
|
||||||
|
console.log(chalk.white(`\n Brief ID: ${briefId}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { confirmed } = await inquirer.prompt([
|
||||||
|
{
|
||||||
|
type: 'confirm',
|
||||||
|
name: 'confirmed',
|
||||||
|
message: 'Do you want to proceed with export?',
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
return confirmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle errors
|
||||||
|
*/
|
||||||
|
private handleError(error: any): void {
|
||||||
|
if (error instanceof AuthenticationError) {
|
||||||
|
console.error(chalk.red(`\n✗ ${error.message}`));
|
||||||
|
|
||||||
|
if (error.code === 'NOT_AUTHENTICATED') {
|
||||||
|
ui.displayWarning('Please authenticate first: tm auth login');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const msg = error?.message ?? String(error);
|
||||||
|
console.error(chalk.red(`Error: ${msg}`));
|
||||||
|
|
||||||
|
if (error.stack && process.env.DEBUG) {
|
||||||
|
console.error(chalk.gray(error.stack));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last export result (useful for testing)
|
||||||
|
*/
|
||||||
|
public getLastResult(): ExportCommandResult | undefined {
|
||||||
|
return this.lastResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up resources
|
||||||
|
*/
|
||||||
|
async cleanup(): Promise<void> {
|
||||||
|
// No resources to clean up
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register this command on an existing program
|
||||||
|
*/
|
||||||
|
static register(program: Command, name?: string): ExportCommand {
|
||||||
|
const exportCommand = new ExportCommand(name);
|
||||||
|
program.addCommand(exportCommand);
|
||||||
|
return exportCommand;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -246,7 +246,7 @@ export class ListTasksCommand extends Command {
|
|||||||
task.subtasks.forEach((subtask) => {
|
task.subtasks.forEach((subtask) => {
|
||||||
const subIcon = STATUS_ICONS[subtask.status];
|
const subIcon = STATUS_ICONS[subtask.status];
|
||||||
console.log(
|
console.log(
|
||||||
` ${chalk.gray(`${task.id}.${subtask.id}`)} ${subIcon} ${chalk.gray(subtask.title)}`
|
` ${chalk.gray(String(subtask.id))} ${subIcon} ${chalk.gray(subtask.title)}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -281,9 +281,14 @@ export class ListTasksCommand extends Command {
|
|||||||
const priorityBreakdown = getPriorityBreakdown(tasks);
|
const priorityBreakdown = getPriorityBreakdown(tasks);
|
||||||
|
|
||||||
// Find next task following the same logic as findNextTask
|
// Find next task following the same logic as findNextTask
|
||||||
const nextTask = this.findNextTask(tasks);
|
const nextTaskInfo = this.findNextTask(tasks);
|
||||||
|
|
||||||
// Display dashboard boxes
|
// Get the full task object with complexity data already included
|
||||||
|
const nextTask = nextTaskInfo
|
||||||
|
? tasks.find((t) => String(t.id) === String(nextTaskInfo.id))
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
// Display dashboard boxes (nextTask already has complexity from storage enrichment)
|
||||||
displayDashboards(
|
displayDashboards(
|
||||||
taskStats,
|
taskStats,
|
||||||
subtaskStats,
|
subtaskStats,
|
||||||
@@ -292,7 +297,7 @@ export class ListTasksCommand extends Command {
|
|||||||
nextTask
|
nextTask
|
||||||
);
|
);
|
||||||
|
|
||||||
// Task table - no title, just show the table directly
|
// Task table
|
||||||
console.log(
|
console.log(
|
||||||
ui.createTaskTable(tasks, {
|
ui.createTaskTable(tasks, {
|
||||||
showSubtasks: withSubtasks,
|
showSubtasks: withSubtasks,
|
||||||
@@ -303,14 +308,16 @@ export class ListTasksCommand extends Command {
|
|||||||
|
|
||||||
// Display recommended next task section immediately after table
|
// Display recommended next task section immediately after table
|
||||||
if (nextTask) {
|
if (nextTask) {
|
||||||
// Find the full task object to get description
|
const description = getTaskDescription(nextTask);
|
||||||
const fullTask = tasks.find((t) => String(t.id) === String(nextTask.id));
|
|
||||||
const description = fullTask ? getTaskDescription(fullTask) : undefined;
|
|
||||||
|
|
||||||
displayRecommendedNextTask({
|
displayRecommendedNextTask({
|
||||||
...nextTask,
|
id: nextTask.id,
|
||||||
status: 'pending', // Next task is typically pending
|
title: nextTask.title,
|
||||||
description
|
priority: nextTask.priority,
|
||||||
|
status: nextTask.status,
|
||||||
|
dependencies: nextTask.dependencies,
|
||||||
|
description,
|
||||||
|
complexity: nextTask.complexity as number | undefined
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
displayRecommendedNextTask(undefined);
|
displayRecommendedNextTask(undefined);
|
||||||
@@ -467,18 +474,7 @@ export class ListTasksCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static method to register this command on an existing program
|
* Register this command on an existing program
|
||||||
* This is for gradual migration - allows commands.js to use this
|
|
||||||
*/
|
|
||||||
static registerOn(program: Command): Command {
|
|
||||||
const listCommand = new ListTasksCommand();
|
|
||||||
program.addCommand(listCommand);
|
|
||||||
return listCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alternative registration that returns the command for chaining
|
|
||||||
* Can also configure the command name if needed
|
|
||||||
*/
|
*/
|
||||||
static register(program: Command, name?: string): ListTasksCommand {
|
static register(program: Command, name?: string): ListTasksCommand {
|
||||||
const listCommand = new ListTasksCommand(name);
|
const listCommand = new ListTasksCommand(name);
|
||||||
|
|||||||
@@ -258,9 +258,6 @@ export class SetStatusCommand extends Command {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show storage info
|
|
||||||
console.log(chalk.gray(`\nUsing ${result.storageType} storage`));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -290,18 +287,7 @@ export class SetStatusCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static method to register this command on an existing program
|
* Register this command on an existing program
|
||||||
* This is for gradual migration - allows commands.js to use this
|
|
||||||
*/
|
|
||||||
static registerOn(program: Command): Command {
|
|
||||||
const setStatusCommand = new SetStatusCommand();
|
|
||||||
program.addCommand(setStatusCommand);
|
|
||||||
return setStatusCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alternative registration that returns the command for chaining
|
|
||||||
* Can also configure the command name if needed
|
|
||||||
*/
|
*/
|
||||||
static register(program: Command, name?: string): SetStatusCommand {
|
static register(program: Command, name?: string): SetStatusCommand {
|
||||||
const setStatusCommand = new SetStatusCommand(name);
|
const setStatusCommand = new SetStatusCommand(name);
|
||||||
|
|||||||
@@ -322,18 +322,7 @@ export class ShowCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static method to register this command on an existing program
|
* Register this command on an existing program
|
||||||
* This is for gradual migration - allows commands.js to use this
|
|
||||||
*/
|
|
||||||
static registerOn(program: Command): Command {
|
|
||||||
const showCommand = new ShowCommand();
|
|
||||||
program.addCommand(showCommand);
|
|
||||||
return showCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alternative registration that returns the command for chaining
|
|
||||||
* Can also configure the command name if needed
|
|
||||||
*/
|
*/
|
||||||
static register(program: Command, name?: string): ShowCommand {
|
static register(program: Command, name?: string): ShowCommand {
|
||||||
const showCommand = new ShowCommand(name);
|
const showCommand = new ShowCommand(name);
|
||||||
|
|||||||
@@ -493,16 +493,7 @@ export class StartCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static method to register this command on an existing program
|
* Register this command on an existing program
|
||||||
*/
|
|
||||||
static registerOn(program: Command): Command {
|
|
||||||
const startCommand = new StartCommand();
|
|
||||||
program.addCommand(startCommand);
|
|
||||||
return startCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alternative registration that returns the command for chaining
|
|
||||||
*/
|
*/
|
||||||
static register(program: Command, name?: string): StartCommand {
|
static register(program: Command, name?: string): StartCommand {
|
||||||
const startCommand = new StartCommand(name);
|
const startCommand = new StartCommand(name);
|
||||||
|
|||||||
@@ -10,6 +10,15 @@ export { AuthCommand } from './commands/auth.command.js';
|
|||||||
export { ContextCommand } from './commands/context.command.js';
|
export { ContextCommand } from './commands/context.command.js';
|
||||||
export { StartCommand } from './commands/start.command.js';
|
export { StartCommand } from './commands/start.command.js';
|
||||||
export { SetStatusCommand } from './commands/set-status.command.js';
|
export { SetStatusCommand } from './commands/set-status.command.js';
|
||||||
|
export { ExportCommand } from './commands/export.command.js';
|
||||||
|
|
||||||
|
// Command Registry
|
||||||
|
export {
|
||||||
|
CommandRegistry,
|
||||||
|
registerAllCommands,
|
||||||
|
registerCommandsByCategory,
|
||||||
|
type CommandMetadata
|
||||||
|
} from './command-registry.js';
|
||||||
|
|
||||||
// UI utilities (for other commands to use)
|
// UI utilities (for other commands to use)
|
||||||
export * as ui from './utils/ui.js';
|
export * as ui from './utils/ui.js';
|
||||||
@@ -18,7 +27,8 @@ export * as ui from './utils/ui.js';
|
|||||||
export {
|
export {
|
||||||
checkForUpdate,
|
checkForUpdate,
|
||||||
performAutoUpdate,
|
performAutoUpdate,
|
||||||
displayUpgradeNotification
|
displayUpgradeNotification,
|
||||||
|
compareVersions
|
||||||
} from './utils/auto-update.js';
|
} from './utils/auto-update.js';
|
||||||
|
|
||||||
// Re-export commonly used types from tm-core
|
// Re-export commonly used types from tm-core
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import boxen from 'boxen';
|
import boxen from 'boxen';
|
||||||
import type { Task, TaskPriority } from '@tm/core/types';
|
import type { Task, TaskPriority } from '@tm/core/types';
|
||||||
|
import { getComplexityWithColor } from '../../utils/ui.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Statistics for task collection
|
* Statistics for task collection
|
||||||
@@ -479,7 +480,7 @@ export function displayDependencyDashboard(
|
|||||||
? chalk.cyan(nextTask.dependencies.join(', '))
|
? chalk.cyan(nextTask.dependencies.join(', '))
|
||||||
: chalk.gray('None')
|
: chalk.gray('None')
|
||||||
}\n` +
|
}\n` +
|
||||||
`Complexity: ${nextTask?.complexity || chalk.gray('N/A')}`;
|
`Complexity: ${nextTask?.complexity !== undefined ? getComplexityWithColor(nextTask.complexity) : chalk.gray('N/A')}`;
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import boxen from 'boxen';
|
import boxen from 'boxen';
|
||||||
import type { Task } from '@tm/core/types';
|
import type { Task } from '@tm/core/types';
|
||||||
|
import { getComplexityWithColor } from '../../utils/ui.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Next task display options
|
* Next task display options
|
||||||
@@ -17,6 +18,7 @@ export interface NextTaskDisplayOptions {
|
|||||||
status?: string;
|
status?: string;
|
||||||
dependencies?: (string | number)[];
|
dependencies?: (string | number)[];
|
||||||
description?: string;
|
description?: string;
|
||||||
|
complexity?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,6 +84,11 @@ export function displayRecommendedNextTask(
|
|||||||
: chalk.cyan(task.dependencies.join(', '));
|
: chalk.cyan(task.dependencies.join(', '));
|
||||||
content.push(`Dependencies: ${depsDisplay}`);
|
content.push(`Dependencies: ${depsDisplay}`);
|
||||||
|
|
||||||
|
// Complexity with color and label
|
||||||
|
if (typeof task.complexity === 'number') {
|
||||||
|
content.push(`Complexity: ${getComplexityWithColor(task.complexity)}`);
|
||||||
|
}
|
||||||
|
|
||||||
// Description if available
|
// Description if available
|
||||||
if (task.description) {
|
if (task.description) {
|
||||||
content.push('');
|
content.push('');
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ import Table from 'cli-table3';
|
|||||||
import { marked, MarkedExtension } from 'marked';
|
import { marked, MarkedExtension } from 'marked';
|
||||||
import { markedTerminal } from 'marked-terminal';
|
import { markedTerminal } from 'marked-terminal';
|
||||||
import type { Task } from '@tm/core/types';
|
import type { Task } from '@tm/core/types';
|
||||||
import { getStatusWithColor, getPriorityWithColor } from '../../utils/ui.js';
|
import {
|
||||||
|
getStatusWithColor,
|
||||||
|
getPriorityWithColor,
|
||||||
|
getComplexityWithColor
|
||||||
|
} from '../../utils/ui.js';
|
||||||
|
|
||||||
// Configure marked to use terminal renderer with subtle colors
|
// Configure marked to use terminal renderer with subtle colors
|
||||||
marked.use(
|
marked.use(
|
||||||
@@ -108,7 +112,9 @@ export function displayTaskProperties(task: Task): void {
|
|||||||
getStatusWithColor(task.status),
|
getStatusWithColor(task.status),
|
||||||
getPriorityWithColor(task.priority),
|
getPriorityWithColor(task.priority),
|
||||||
deps,
|
deps,
|
||||||
'N/A',
|
typeof task.complexity === 'number'
|
||||||
|
? getComplexityWithColor(task.complexity)
|
||||||
|
: chalk.gray('N/A'),
|
||||||
task.description || ''
|
task.description || ''
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
@@ -186,8 +192,7 @@ export function displaySubtasks(
|
|||||||
status: any;
|
status: any;
|
||||||
description?: string;
|
description?: string;
|
||||||
dependencies?: string[];
|
dependencies?: string[];
|
||||||
}>,
|
}>
|
||||||
parentId: string | number
|
|
||||||
): void {
|
): void {
|
||||||
const terminalWidth = process.stdout.columns * 0.95 || 100;
|
const terminalWidth = process.stdout.columns * 0.95 || 100;
|
||||||
// Display subtasks header
|
// Display subtasks header
|
||||||
@@ -222,7 +227,7 @@ export function displaySubtasks(
|
|||||||
});
|
});
|
||||||
|
|
||||||
subtasks.forEach((subtask) => {
|
subtasks.forEach((subtask) => {
|
||||||
const subtaskId = `${parentId}.${subtask.id}`;
|
const subtaskId = String(subtask.id);
|
||||||
|
|
||||||
// Format dependencies
|
// Format dependencies
|
||||||
const deps =
|
const deps =
|
||||||
@@ -323,7 +328,7 @@ export function displayTaskDetails(
|
|||||||
console.log(chalk.gray(` No subtasks with status '${statusFilter}'`));
|
console.log(chalk.gray(` No subtasks with status '${statusFilter}'`));
|
||||||
} else if (filteredSubtasks.length > 0) {
|
} else if (filteredSubtasks.length > 0) {
|
||||||
console.log(); // Empty line for spacing
|
console.log(); // Empty line for spacing
|
||||||
displaySubtasks(filteredSubtasks, task.id);
|
displaySubtasks(filteredSubtasks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import https from 'https';
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import ora from 'ora';
|
import ora from 'ora';
|
||||||
import boxen from 'boxen';
|
import boxen from 'boxen';
|
||||||
import packageJson from '../../../../package.json' with { type: 'json' };
|
|
||||||
|
|
||||||
export interface UpdateInfo {
|
export interface UpdateInfo {
|
||||||
currentVersion: string;
|
currentVersion: string;
|
||||||
@@ -16,15 +15,18 @@ export interface UpdateInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current version from package.json
|
* Get current version from build-time injected environment variable
|
||||||
*/
|
*/
|
||||||
function getCurrentVersion(): string {
|
function getCurrentVersion(): string {
|
||||||
try {
|
// Version is injected at build time via TM_PUBLIC_VERSION
|
||||||
return packageJson.version;
|
const version = process.env.TM_PUBLIC_VERSION;
|
||||||
} catch (error) {
|
if (version && version !== 'unknown') {
|
||||||
console.warn('Could not read package.json for version info');
|
return version;
|
||||||
return '0.0.0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fallback for development or if injection failed
|
||||||
|
console.warn('Could not read version from TM_PUBLIC_VERSION, using fallback');
|
||||||
|
return '0.0.0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +35,7 @@ function getCurrentVersion(): string {
|
|||||||
* @param v2 - Second version
|
* @param v2 - Second version
|
||||||
* @returns -1 if v1 < v2, 0 if v1 = v2, 1 if v1 > v2
|
* @returns -1 if v1 < v2, 0 if v1 = v2, 1 if v1 > v2
|
||||||
*/
|
*/
|
||||||
function compareVersions(v1: string, v2: string): number {
|
export function compareVersions(v1: string, v2: string): number {
|
||||||
const toParts = (v: string) => {
|
const toParts = (v: string) => {
|
||||||
const [core, pre = ''] = v.split('-', 2);
|
const [core, pre = ''] = v.split('-', 2);
|
||||||
const nums = core.split('.').map((n) => Number.parseInt(n, 10) || 0);
|
const nums = core.split('.').map((n) => Number.parseInt(n, 10) || 0);
|
||||||
@@ -156,10 +158,18 @@ export function displayUpgradeNotification(
|
|||||||
export async function performAutoUpdate(
|
export async function performAutoUpdate(
|
||||||
latestVersion: string
|
latestVersion: string
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
if (process.env.TASKMASTER_SKIP_AUTO_UPDATE === '1' || process.env.CI) {
|
if (
|
||||||
console.log(
|
process.env.TASKMASTER_SKIP_AUTO_UPDATE === '1' ||
|
||||||
chalk.dim('Skipping auto-update (TASKMASTER_SKIP_AUTO_UPDATE/CI).')
|
process.env.CI ||
|
||||||
);
|
process.env.NODE_ENV === 'test'
|
||||||
|
) {
|
||||||
|
const reason =
|
||||||
|
process.env.TASKMASTER_SKIP_AUTO_UPDATE === '1'
|
||||||
|
? 'TASKMASTER_SKIP_AUTO_UPDATE=1'
|
||||||
|
: process.env.CI
|
||||||
|
? 'CI environment'
|
||||||
|
: 'NODE_ENV=test';
|
||||||
|
console.log(chalk.dim(`Skipping auto-update (${reason})`));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const spinner = ora({
|
const spinner = ora({
|
||||||
|
|||||||
@@ -84,7 +84,23 @@ export function getPriorityWithColor(priority: TaskPriority): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get colored complexity display
|
* Get complexity color and label based on score thresholds
|
||||||
|
*/
|
||||||
|
function getComplexityLevel(score: number): {
|
||||||
|
color: (text: string) => string;
|
||||||
|
label: string;
|
||||||
|
} {
|
||||||
|
if (score >= 7) {
|
||||||
|
return { color: chalk.hex('#CC0000'), label: 'High' };
|
||||||
|
} else if (score >= 4) {
|
||||||
|
return { color: chalk.hex('#FF8800'), label: 'Medium' };
|
||||||
|
} else {
|
||||||
|
return { color: chalk.green, label: 'Low' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get colored complexity display with dot indicator (simple format)
|
||||||
*/
|
*/
|
||||||
export function getComplexityWithColor(complexity: number | string): string {
|
export function getComplexityWithColor(complexity: number | string): string {
|
||||||
const score =
|
const score =
|
||||||
@@ -94,13 +110,20 @@ export function getComplexityWithColor(complexity: number | string): string {
|
|||||||
return chalk.gray('N/A');
|
return chalk.gray('N/A');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (score >= 8) {
|
const { color } = getComplexityLevel(score);
|
||||||
return chalk.red.bold(`${score} (High)`);
|
return color(`● ${score}`);
|
||||||
} else if (score >= 5) {
|
}
|
||||||
return chalk.yellow(`${score} (Medium)`);
|
|
||||||
} else {
|
/**
|
||||||
return chalk.green(`${score} (Low)`);
|
* Get colored complexity display with /10 format (for dashboards)
|
||||||
|
*/
|
||||||
|
export function getComplexityWithScore(complexity: number | undefined): string {
|
||||||
|
if (typeof complexity !== 'number') {
|
||||||
|
return chalk.gray('N/A');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { color, label } = getComplexityLevel(complexity);
|
||||||
|
return color(`${complexity}/10 (${label})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -263,12 +286,12 @@ export function createTaskTable(
|
|||||||
// Adjust column widths to better match the original layout
|
// Adjust column widths to better match the original layout
|
||||||
const baseColWidths = showComplexity
|
const baseColWidths = showComplexity
|
||||||
? [
|
? [
|
||||||
Math.floor(terminalWidth * 0.06),
|
Math.floor(terminalWidth * 0.1),
|
||||||
Math.floor(terminalWidth * 0.4),
|
Math.floor(terminalWidth * 0.4),
|
||||||
Math.floor(terminalWidth * 0.15),
|
Math.floor(terminalWidth * 0.15),
|
||||||
Math.floor(terminalWidth * 0.12),
|
Math.floor(terminalWidth * 0.1),
|
||||||
Math.floor(terminalWidth * 0.2),
|
Math.floor(terminalWidth * 0.2),
|
||||||
Math.floor(terminalWidth * 0.12)
|
Math.floor(terminalWidth * 0.1)
|
||||||
] // ID, Title, Status, Priority, Dependencies, Complexity
|
] // ID, Title, Status, Priority, Dependencies, Complexity
|
||||||
: [
|
: [
|
||||||
Math.floor(terminalWidth * 0.08),
|
Math.floor(terminalWidth * 0.08),
|
||||||
@@ -323,9 +346,13 @@ export function createTaskTable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (showComplexity) {
|
if (showComplexity) {
|
||||||
// Show N/A if no complexity score
|
// Show complexity score from report if available
|
||||||
|
if (typeof task.complexity === 'number') {
|
||||||
|
row.push(getComplexityWithColor(task.complexity));
|
||||||
|
} else {
|
||||||
row.push(chalk.gray('N/A'));
|
row.push(chalk.gray('N/A'));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
table.push(row);
|
table.push(row);
|
||||||
|
|
||||||
@@ -350,7 +377,11 @@ export function createTaskTable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (showComplexity) {
|
if (showComplexity) {
|
||||||
subRow.push(chalk.gray('--'));
|
const complexityDisplay =
|
||||||
|
typeof subtask.complexity === 'number'
|
||||||
|
? getComplexityWithColor(subtask.complexity)
|
||||||
|
: '--';
|
||||||
|
subRow.push(chalk.gray(complexityDisplay));
|
||||||
}
|
}
|
||||||
|
|
||||||
table.push(subRow);
|
table.push(subRow);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# docs
|
# docs
|
||||||
|
|
||||||
|
## 0.0.4
|
||||||
|
|
||||||
## 0.0.3
|
## 0.0.3
|
||||||
|
|
||||||
## 0.0.2
|
## 0.0.2
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
# Task Master Documentation
|
# Task Master Documentation
|
||||||
|
|
||||||
Welcome to the Task Master documentation. Use the links below to navigate to the information you need:
|
Welcome to the Task Master documentation. This documentation site provides comprehensive guides for getting started with Task Master.
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
- [Configuration Guide](archive/configuration.md) - Set up environment variables and customize Task Master
|
- [Quick Start Guide](/getting-started/quick-start) - Complete setup and first-time usage guide
|
||||||
- [Tutorial](archive/ctutorial.md) - Step-by-step guide to getting started with Task Master
|
- [Requirements](/getting-started/quick-start/requirements) - What you need to get started
|
||||||
|
- [Installation](/getting-started/quick-start/installation) - How to install Task Master
|
||||||
|
|
||||||
## Reference
|
## Core Capabilities
|
||||||
|
|
||||||
- [Command Reference](archive/ccommand-reference.md) - Complete list of all available commands
|
- [MCP Tools](/capabilities/mcp) - Model Control Protocol integration
|
||||||
- [Task Structure](archive/ctask-structure.md) - Understanding the task format and features
|
- [CLI Commands](/capabilities/cli-root-commands) - Command line interface reference
|
||||||
|
- [Task Structure](/capabilities/task-structure) - Understanding tasks and subtasks
|
||||||
|
|
||||||
## Examples & Licensing
|
## Best Practices
|
||||||
|
|
||||||
- [Example Interactions](archive/cexamples.md) - Common Cursor AI interaction examples
|
- [Advanced Configuration](/best-practices/configuration-advanced) - Detailed configuration options
|
||||||
- [Licensing Information](archive/clicensing.md) - Detailed information about the license
|
- [Advanced Tasks](/best-practices/advanced-tasks) - Working with complex task structures
|
||||||
|
|
||||||
## Need More Help?
|
## Need More Help?
|
||||||
|
|
||||||
If you can't find what you're looking for in these docs, please check the [main README](../README.md) or visit our [GitHub repository](https://github.com/eyaltoledano/claude-task-master).
|
If you can't find what you're looking for in these docs, please check the root README.md or visit our [GitHub repository](https://github.com/eyaltoledano/claude-task-master).
|
||||||
|
|||||||
326
apps/docs/capabilities/rpg-method.mdx
Normal file
326
apps/docs/capabilities/rpg-method.mdx
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
---
|
||||||
|
title: RPG Method for PRD Creation
|
||||||
|
sidebarTitle: "RPG Method"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Repository Planning Graph (RPG) Method
|
||||||
|
|
||||||
|
The RPG (Repository Planning Graph) method is an advanced approach to creating Product Requirements Documents that generate highly-structured, dependency-aware task graphs. It's based on Microsoft Research's methodology for scalable codebase generation.
|
||||||
|
|
||||||
|
## When to Use RPG
|
||||||
|
|
||||||
|
Use the RPG template (`example_prd_rpg.txt`) for:
|
||||||
|
|
||||||
|
- **Complex multi-module systems** with intricate dependencies
|
||||||
|
- **Large-scale codebases** being built from scratch
|
||||||
|
- **Projects requiring explicit architecture** and clear module boundaries
|
||||||
|
- **Teams needing dependency visibility** for parallel development
|
||||||
|
|
||||||
|
For simpler features or smaller projects, the standard `example_prd.txt` template may be more appropriate.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core Principles
|
||||||
|
|
||||||
|
### 1. Dual-Semantics
|
||||||
|
|
||||||
|
Separate **functional** thinking (WHAT) from **structural** thinking (HOW):
|
||||||
|
|
||||||
|
```
|
||||||
|
Functional: "Data Validation capability with schema checking and rule enforcement"
|
||||||
|
↓
|
||||||
|
Structural: "src/validation/ with schema-validator.js and rule-validator.js"
|
||||||
|
```
|
||||||
|
|
||||||
|
This separation prevents mixing concerns and creates clearer module boundaries.
|
||||||
|
|
||||||
|
### 2. Explicit Dependencies
|
||||||
|
|
||||||
|
Never assume dependencies - always state them explicitly:
|
||||||
|
|
||||||
|
```
|
||||||
|
Good:
|
||||||
|
Module: data-ingestion
|
||||||
|
Depends on: [schema-validator, config-manager]
|
||||||
|
|
||||||
|
Bad:
|
||||||
|
Module: data-ingestion
|
||||||
|
(Assumes schema-validator exists somewhere)
|
||||||
|
```
|
||||||
|
|
||||||
|
Explicit dependencies enable:
|
||||||
|
- Topological ordering of implementation
|
||||||
|
- Parallel development of independent modules
|
||||||
|
- Clear build/test order
|
||||||
|
- Early detection of circular dependencies
|
||||||
|
|
||||||
|
### 3. Topological Order
|
||||||
|
|
||||||
|
Build foundation layers before higher layers:
|
||||||
|
|
||||||
|
```
|
||||||
|
Phase 0 (Foundation): error-handling, base-types, config
|
||||||
|
↓
|
||||||
|
Phase 1 (Data): validation, ingestion (depend on Phase 0)
|
||||||
|
↓
|
||||||
|
Phase 2 (Core): algorithms, pipelines (depend on Phase 1)
|
||||||
|
↓
|
||||||
|
Phase 3 (API): routes, handlers (depend on Phase 2)
|
||||||
|
```
|
||||||
|
|
||||||
|
Task Master automatically orders tasks based on this dependency chain.
|
||||||
|
|
||||||
|
### 4. Progressive Refinement
|
||||||
|
|
||||||
|
Start broad, refine iteratively:
|
||||||
|
|
||||||
|
1. High-level capabilities → Main tasks
|
||||||
|
2. Features per capability → Subtasks
|
||||||
|
3. Implementation details → Expanded subtasks
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template Structure
|
||||||
|
|
||||||
|
The RPG template guides you through 7 key sections:
|
||||||
|
|
||||||
|
### 1. Overview
|
||||||
|
- Problem statement
|
||||||
|
- Target users
|
||||||
|
- Success metrics
|
||||||
|
|
||||||
|
### 2. Functional Decomposition (WHAT)
|
||||||
|
- High-level capability domains
|
||||||
|
- Features per capability
|
||||||
|
- Inputs/outputs/behavior for each feature
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
Capability: Data Management
|
||||||
|
Feature: Schema validation
|
||||||
|
Description: Validate JSON against defined schemas
|
||||||
|
Inputs: JSON object, schema definition
|
||||||
|
Outputs: Validation result + error details
|
||||||
|
Behavior: Iterate fields, check types, enforce constraints
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Structural Decomposition (HOW)
|
||||||
|
- Repository folder structure
|
||||||
|
- Module-to-capability mapping
|
||||||
|
- File organization
|
||||||
|
- Public interfaces/exports
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
Capability: Data Management
|
||||||
|
→ Maps to: src/data/
|
||||||
|
├── schema-validator.js (Schema validation feature)
|
||||||
|
├── rule-validator.js (Rule validation feature)
|
||||||
|
└── index.js (Exports)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Dependency Graph (CRITICAL)
|
||||||
|
- Foundation layer (no dependencies)
|
||||||
|
- Each subsequent layer's dependencies
|
||||||
|
- Explicit "depends on" declarations
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
Foundation Layer (Phase 0):
|
||||||
|
- error-handling: No dependencies
|
||||||
|
- base-types: No dependencies
|
||||||
|
|
||||||
|
Data Layer (Phase 1):
|
||||||
|
- schema-validator: Depends on [base-types, error-handling]
|
||||||
|
- data-ingestion: Depends on [schema-validator]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Implementation Roadmap
|
||||||
|
- Phases with entry/exit criteria
|
||||||
|
- Tasks grouped by phase
|
||||||
|
- Clear deliverables per phase
|
||||||
|
|
||||||
|
### 6. Test Strategy
|
||||||
|
- Test pyramid ratios
|
||||||
|
- Coverage requirements
|
||||||
|
- Critical test scenarios per module
|
||||||
|
- Guidelines for test generation
|
||||||
|
|
||||||
|
### 7. Architecture & Risks
|
||||||
|
- Technical architecture
|
||||||
|
- Data models
|
||||||
|
- Technology decisions
|
||||||
|
- Risk mitigation strategies
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Using RPG with Task Master
|
||||||
|
|
||||||
|
### Step 1: Create PRD with RPG Template
|
||||||
|
|
||||||
|
Use a code-context-aware tool to fill out the template:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In Claude Code, Cursor, or similar
|
||||||
|
"Create a PRD using @.taskmaster/templates/example_prd_rpg.txt for [your project]"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Why code context matters:** The AI needs to understand your existing codebase to make informed decisions about:
|
||||||
|
- Module boundaries
|
||||||
|
- Dependency relationships
|
||||||
|
- Integration points
|
||||||
|
- Naming conventions
|
||||||
|
|
||||||
|
**Recommended tools:**
|
||||||
|
- Claude Code (claude-code CLI)
|
||||||
|
- Cursor/Windsurf
|
||||||
|
- Gemini CLI (large contexts)
|
||||||
|
- Codex/Grok CLI
|
||||||
|
|
||||||
|
### Step 2: Parse PRD into Tasks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
task-master parse-prd .taskmaster/docs/your-prd.txt --research
|
||||||
|
```
|
||||||
|
|
||||||
|
Task Master will:
|
||||||
|
1. Extract capabilities → Main tasks
|
||||||
|
2. Extract features → Subtasks
|
||||||
|
3. Parse dependencies → Task dependencies
|
||||||
|
4. Order by phases → Task priorities
|
||||||
|
|
||||||
|
**Result:** A dependency-aware task graph ready for topological execution.
|
||||||
|
|
||||||
|
### Step 3: Analyze Complexity
|
||||||
|
|
||||||
|
```bash
|
||||||
|
task-master analyze-complexity --research
|
||||||
|
```
|
||||||
|
|
||||||
|
Review the complexity report to identify tasks that need expansion.
|
||||||
|
|
||||||
|
### Step 4: Expand Tasks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
task-master expand --all --research
|
||||||
|
```
|
||||||
|
|
||||||
|
Break down complex tasks into manageable subtasks while preserving dependency chains.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## RPG Benefits
|
||||||
|
|
||||||
|
### For Solo Developers
|
||||||
|
- Clear roadmap for implementing complex features
|
||||||
|
- Prevents architectural mistakes early
|
||||||
|
- Explicit dependency tracking avoids integration issues
|
||||||
|
- Enables resuming work after interruptions
|
||||||
|
|
||||||
|
### For Teams
|
||||||
|
- Parallel development of independent modules
|
||||||
|
- Clear contracts between modules (explicit dependencies)
|
||||||
|
- Reduced merge conflicts (proper module boundaries)
|
||||||
|
- Onboarding aid (architectural overview in PRD)
|
||||||
|
|
||||||
|
### For AI Agents
|
||||||
|
- Structured context for code generation
|
||||||
|
- Clear scope boundaries per task
|
||||||
|
- Dependency awareness prevents incomplete implementations
|
||||||
|
- Test strategy guidance for TDD workflows
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## RPG vs Standard Template
|
||||||
|
|
||||||
|
| Aspect | Standard Template | RPG Template |
|
||||||
|
|--------|------------------|--------------|
|
||||||
|
| **Best for** | Simple features | Complex systems |
|
||||||
|
| **Dependency handling** | Implicit | Explicit graph |
|
||||||
|
| **Structure guidance** | Minimal | Step-by-step |
|
||||||
|
| **Examples** | Few | Inline good/bad examples |
|
||||||
|
| **Module boundaries** | Vague | Precise mapping |
|
||||||
|
| **Task ordering** | Manual | Automatic (topological) |
|
||||||
|
| **Learning curve** | Low | Medium |
|
||||||
|
| **Resulting task quality** | Good | Excellent |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tips for Best Results
|
||||||
|
|
||||||
|
### 1. Spend Time on Dependencies
|
||||||
|
The dependency graph section is the most valuable. List all dependencies explicitly, even if they seem obvious.
|
||||||
|
|
||||||
|
### 2. Keep Features Atomic
|
||||||
|
Each feature should be independently testable. If a feature description is vague ("handle data"), break it into specific features.
|
||||||
|
|
||||||
|
### 3. Progressive Refinement
|
||||||
|
Don't try to get everything perfect on the first pass:
|
||||||
|
1. Fill out high-level sections
|
||||||
|
2. Review and refine
|
||||||
|
3. Add detail where needed
|
||||||
|
4. Let `task-master expand` break down complex tasks further
|
||||||
|
|
||||||
|
### 4. Use Research Mode
|
||||||
|
```bash
|
||||||
|
task-master parse-prd --research
|
||||||
|
```
|
||||||
|
The `--research` flag leverages AI to enhance task generation with domain knowledge.
|
||||||
|
|
||||||
|
### 5. Validate Early
|
||||||
|
```bash
|
||||||
|
task-master validate-dependencies
|
||||||
|
```
|
||||||
|
Check for circular dependencies or orphaned modules before starting implementation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Pitfalls
|
||||||
|
|
||||||
|
### ❌ Mixing Functional and Structural
|
||||||
|
```
|
||||||
|
Bad: "Capability: validation.js"
|
||||||
|
Good: "Capability: Data Validation" → maps to "src/validation/"
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ Vague Module Boundaries
|
||||||
|
```
|
||||||
|
Bad: "Module: utils"
|
||||||
|
Good: "Module: string-utilities" with clear exports
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ Implicit Dependencies
|
||||||
|
```
|
||||||
|
Bad: "Module: API handlers (needs validation)"
|
||||||
|
Good: "Module: API handlers, Depends on: [validation, error-handling]"
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ Skipping Test Strategy
|
||||||
|
Without test strategy, the AI won't know what to test during implementation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example Workflow
|
||||||
|
|
||||||
|
1. **Discuss idea with AI**: Explain your project concept
|
||||||
|
2. **Reference RPG template**: Show AI the `example_prd_rpg.txt`
|
||||||
|
3. **Co-create PRD**: Work through each section with AI guidance
|
||||||
|
4. **Save to docs**: Place in `.taskmaster/docs/your-project.txt`
|
||||||
|
5. **Parse PRD**: `task-master parse-prd .taskmaster/docs/your-project.txt --research`
|
||||||
|
6. **Analyze**: `task-master analyze-complexity --research`
|
||||||
|
7. **Expand**: `task-master expand --all --research`
|
||||||
|
8. **Start work**: `task-master next`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Further Reading
|
||||||
|
|
||||||
|
- [PRD Creation and Parsing Guide](/getting-started/quick-start/prd-quick)
|
||||||
|
- [Task Structure Documentation](/capabilities/task-structure)
|
||||||
|
- [Microsoft Research RPG Paper](https://arxiv.org/abs/2410.21376) (Original methodology)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<Tip>
|
||||||
|
The RPG template includes inline `<instruction>` and `<example>` blocks that teach the method as you use it. Read these sections carefully - they provide valuable guidance at each decision point.
|
||||||
|
</Tip>
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
"getting-started/quick-start/execute-quick"
|
"getting-started/quick-start/execute-quick"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"getting-started/api-keys",
|
||||||
"getting-started/faq",
|
"getting-started/faq",
|
||||||
"getting-started/contribute"
|
"getting-started/contribute"
|
||||||
]
|
]
|
||||||
|
|||||||
267
apps/docs/getting-started/api-keys.mdx
Normal file
267
apps/docs/getting-started/api-keys.mdx
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
# API Keys Configuration
|
||||||
|
|
||||||
|
Task Master supports multiple AI providers through environment variables. This page lists all available API keys and their configuration requirements.
|
||||||
|
|
||||||
|
## Required API Keys
|
||||||
|
|
||||||
|
> **Note**: At least one required API key must be configured for Task Master to function.
|
||||||
|
>
|
||||||
|
> "Required: Yes" below means "required to use that specific provider," not "required globally." You only need at least one provider configured.
|
||||||
|
|
||||||
|
### ANTHROPIC_API_KEY (Recommended)
|
||||||
|
- **Provider**: Anthropic Claude models
|
||||||
|
- **Format**: `sk-ant-api03-...`
|
||||||
|
- **Required**: ✅ **Yes**
|
||||||
|
- **Models**: Claude 3.5 Sonnet, Claude 3 Haiku, Claude 3 Opus
|
||||||
|
- **Get Key**: [Anthropic Console](https://console.anthropic.com/)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ANTHROPIC_API_KEY="sk-ant-api03-your-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
### PERPLEXITY_API_KEY (Highly Recommended for Research)
|
||||||
|
- **Provider**: Perplexity AI (Research features)
|
||||||
|
- **Format**: `pplx-...`
|
||||||
|
- **Required**: ✅ **Yes**
|
||||||
|
- **Purpose**: Enables research-backed task expansions and updates
|
||||||
|
- **Models**: Perplexity Sonar models
|
||||||
|
- **Get Key**: [Perplexity API](https://www.perplexity.ai/settings/api)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PERPLEXITY_API_KEY="pplx-your-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
### OPENAI_API_KEY
|
||||||
|
- **Provider**: OpenAI GPT models
|
||||||
|
- **Format**: `sk-proj-...` or `sk-...`
|
||||||
|
- **Required**: ✅ **Yes**
|
||||||
|
- **Models**: GPT-4, GPT-4 Turbo, GPT-3.5 Turbo, O1 models
|
||||||
|
- **Get Key**: [OpenAI Platform](https://platform.openai.com/api-keys)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
OPENAI_API_KEY="sk-proj-your-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
### GOOGLE_API_KEY
|
||||||
|
- **Provider**: Google Gemini models
|
||||||
|
- **Format**: Various formats
|
||||||
|
- **Required**: ✅ **Yes**
|
||||||
|
- **Models**: Gemini Pro, Gemini Flash, Gemini Ultra
|
||||||
|
- **Get Key**: [Google AI Studio](https://aistudio.google.com/app/apikey)
|
||||||
|
- **Alternative**: Use `GOOGLE_APPLICATION_CREDENTIALS` for service account (Google Vertex)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GOOGLE_API_KEY="your-google-api-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
### GROQ_API_KEY
|
||||||
|
- **Provider**: Groq (High-performance inference)
|
||||||
|
- **Required**: ✅ **Yes**
|
||||||
|
- **Models**: Llama models, Mixtral models (via Groq)
|
||||||
|
- **Get Key**: [Groq Console](https://console.groq.com/keys)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GROQ_API_KEY="your-groq-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
### OPENROUTER_API_KEY
|
||||||
|
- **Provider**: OpenRouter (Multiple model access)
|
||||||
|
- **Required**: ✅ **Yes**
|
||||||
|
- **Models**: Access to various models through single API
|
||||||
|
- **Get Key**: [OpenRouter](https://openrouter.ai/keys)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
OPENROUTER_API_KEY="your-openrouter-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
### AZURE_OPENAI_API_KEY
|
||||||
|
- **Provider**: Azure OpenAI Service
|
||||||
|
- **Required**: ✅ **Yes**
|
||||||
|
- **Requirements**: Also requires `AZURE_OPENAI_ENDPOINT` configuration
|
||||||
|
- **Models**: GPT models via Azure
|
||||||
|
- **Get Key**: [Azure Portal](https://portal.azure.com/)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
AZURE_OPENAI_API_KEY="your-azure-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
### XAI_API_KEY
|
||||||
|
- **Provider**: xAI (Grok) models
|
||||||
|
- **Required**: ✅ **Yes**
|
||||||
|
- **Models**: Grok models
|
||||||
|
- **Get Key**: [xAI Console](https://console.x.ai/)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
XAI_API_KEY="your-xai-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Optional API Keys
|
||||||
|
|
||||||
|
> **Note**: These API keys are optional - providers will work without them or use alternative authentication methods.
|
||||||
|
|
||||||
|
### AWS_ACCESS_KEY_ID (Bedrock)
|
||||||
|
- **Provider**: AWS Bedrock
|
||||||
|
- **Required**: ❌ **No** (uses AWS credential chain)
|
||||||
|
- **Models**: Claude models via AWS Bedrock
|
||||||
|
- **Authentication**: Uses AWS credential chain (profiles, IAM roles, etc.)
|
||||||
|
- **Get Key**: [AWS Console](https://console.aws.amazon.com/iam/)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Optional - AWS credential chain is preferred
|
||||||
|
AWS_ACCESS_KEY_ID="your-aws-access-key"
|
||||||
|
AWS_SECRET_ACCESS_KEY="your-aws-secret-key"
|
||||||
|
```
|
||||||
|
|
||||||
|
### CLAUDE_CODE_API_KEY
|
||||||
|
- **Provider**: Claude Code CLI
|
||||||
|
- **Required**: ❌ **No** (uses OAuth tokens)
|
||||||
|
- **Purpose**: Integration with local Claude Code CLI
|
||||||
|
- **Authentication**: Uses OAuth tokens, no API key needed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Not typically needed
|
||||||
|
CLAUDE_CODE_API_KEY="not-usually-required"
|
||||||
|
```
|
||||||
|
|
||||||
|
### GEMINI_API_KEY
|
||||||
|
- **Provider**: Gemini CLI
|
||||||
|
- **Required**: ❌ **No** (uses OAuth authentication)
|
||||||
|
- **Purpose**: Integration with Gemini CLI
|
||||||
|
- **Authentication**: Primarily uses OAuth via CLI, API key is optional
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Optional - OAuth via CLI is preferred
|
||||||
|
GEMINI_API_KEY="your-gemini-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
### GROK_CLI_API_KEY
|
||||||
|
- **Provider**: Grok CLI
|
||||||
|
- **Required**: ❌ **No** (can use CLI config)
|
||||||
|
- **Purpose**: Integration with Grok CLI
|
||||||
|
- **Authentication**: Can use Grok CLI's own config file
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Optional - CLI config is preferred
|
||||||
|
GROK_CLI_API_KEY="your-grok-cli-key"
|
||||||
|
```
|
||||||
|
|
||||||
|
### OLLAMA_API_KEY
|
||||||
|
- **Provider**: Ollama (Local/Remote)
|
||||||
|
- **Required**: ❌ **No** (local installation doesn't need key)
|
||||||
|
- **Purpose**: For remote Ollama servers that require authentication
|
||||||
|
- **Requirements**: Only needed for remote servers with authentication
|
||||||
|
- **Note**: Not needed for local Ollama installations
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Only needed for remote Ollama servers
|
||||||
|
OLLAMA_API_KEY="your-ollama-api-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
### GITHUB_API_KEY
|
||||||
|
- **Provider**: GitHub (Import/Export features)
|
||||||
|
- **Format**: `ghp_...` or `github_pat_...`
|
||||||
|
- **Required**: ❌ **No** (for GitHub features only)
|
||||||
|
- **Purpose**: GitHub import/export features
|
||||||
|
- **Get Key**: [GitHub Settings](https://github.com/settings/tokens)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GITHUB_API_KEY="ghp-your-github-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Methods
|
||||||
|
|
||||||
|
### Method 1: Environment File (.env)
|
||||||
|
Create a `.env` file in your project root:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy from .env.example
|
||||||
|
cp .env.example .env
|
||||||
|
|
||||||
|
# Edit with your keys
|
||||||
|
vim .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### Method 2: System Environment Variables
|
||||||
|
```bash
|
||||||
|
export ANTHROPIC_API_KEY="your-key-here"
|
||||||
|
export PERPLEXITY_API_KEY="your-key-here"
|
||||||
|
# ... other keys
|
||||||
|
```
|
||||||
|
|
||||||
|
### Method 3: MCP Server Configuration
|
||||||
|
For Claude Code integration, configure keys in `.mcp.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"task-master-ai": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": ["-y", "task-master-ai"],
|
||||||
|
"env": {
|
||||||
|
"ANTHROPIC_API_KEY": "your-key-here",
|
||||||
|
"PERPLEXITY_API_KEY": "your-key-here",
|
||||||
|
"OPENAI_API_KEY": "your-key-here"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Requirements
|
||||||
|
|
||||||
|
### Minimum Requirements
|
||||||
|
- **At least one** AI provider key is required
|
||||||
|
- **ANTHROPIC_API_KEY** is recommended as the primary provider
|
||||||
|
- **PERPLEXITY_API_KEY** is highly recommended for research features
|
||||||
|
|
||||||
|
### Provider-Specific Requirements
|
||||||
|
- **Azure OpenAI**: Requires both `AZURE_OPENAI_API_KEY` and `AZURE_OPENAI_ENDPOINT` configuration
|
||||||
|
- **Google Vertex**: Requires `VERTEX_PROJECT_ID` and `VERTEX_LOCATION` environment variables
|
||||||
|
- **AWS Bedrock**: Uses AWS credential chain (profiles, IAM roles, etc.) instead of API keys
|
||||||
|
- **Ollama**: Only needs API key for remote servers with authentication
|
||||||
|
- **CLI Providers**: Gemini CLI, Grok CLI, and Claude Code use OAuth/CLI config instead of API keys
|
||||||
|
|
||||||
|
## Model Configuration
|
||||||
|
|
||||||
|
After setting up API keys, configure which models to use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Interactive model setup
|
||||||
|
task-master models --setup
|
||||||
|
|
||||||
|
# Set specific models
|
||||||
|
task-master models --set-main claude-3-5-sonnet-20241022
|
||||||
|
task-master models --set-research perplexity-llama-3.1-sonar-large-128k-online
|
||||||
|
task-master models --set-fallback gpt-4o-mini
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Best Practices
|
||||||
|
|
||||||
|
1. **Never commit API keys** to version control
|
||||||
|
2. **Use .env files** and add them to `.gitignore`
|
||||||
|
3. **Rotate keys regularly** especially if compromised
|
||||||
|
4. **Use minimal permissions** for service accounts
|
||||||
|
5. **Monitor usage** to detect unauthorized access
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Key Validation
|
||||||
|
```bash
|
||||||
|
# Check if keys are properly configured
|
||||||
|
task-master models
|
||||||
|
|
||||||
|
# Test specific provider
|
||||||
|
task-master add-task --prompt="test task" --model=claude-3-5-sonnet-20241022
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
- **Invalid key format**: Check the expected format for each provider
|
||||||
|
- **Insufficient permissions**: Ensure keys have necessary API access
|
||||||
|
- **Rate limits**: Some providers have usage limits
|
||||||
|
- **Regional restrictions**: Some models may not be available in all regions
|
||||||
|
|
||||||
|
### Getting Help
|
||||||
|
If you encounter issues with API key configuration:
|
||||||
|
- Check the [FAQ](/getting-started/faq) for common solutions
|
||||||
|
- Join our [Discord community](https://discord.gg/fWJkU7rf) for support
|
||||||
|
- Report issues on [GitHub](https://github.com/eyaltoledano/claude-task-master/issues)
|
||||||
@@ -108,5 +108,5 @@ You don’t need to configure everything up front. Most settings can be left as
|
|||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
For advanced configuration options and detailed customization, see our [Advanced Configuration Guide](/docs/best-practices/configuration-advanced) page.
|
For advanced configuration options and detailed customization, see our [Advanced Configuration Guide](/best-practices/configuration-advanced) page.
|
||||||
</Note>
|
</Note>
|
||||||
@@ -56,4 +56,4 @@ If you ran into problems and had to debug errors you can create new rules as you
|
|||||||
|
|
||||||
By now you have all you need to get started executing code faster and smarter with Task Master.
|
By now you have all you need to get started executing code faster and smarter with Task Master.
|
||||||
|
|
||||||
If you have any questions please check out [Frequently Asked Questions](/docs/getting-started/faq)
|
If you have any questions please check out [Frequently Asked Questions](/getting-started/faq)
|
||||||
|
|||||||
@@ -32,7 +32,11 @@ The more context you give the model, the better the breakdown and results.
|
|||||||
|
|
||||||
## Writing a PRD for Task Master
|
## Writing a PRD for Task Master
|
||||||
|
|
||||||
<Note>An example PRD can be found in .taskmaster/templates/example_prd.txt</Note>
|
<Note>
|
||||||
|
Two example PRD templates are available in `.taskmaster/templates/`:
|
||||||
|
- `example_prd.txt` - Simple template for straightforward projects
|
||||||
|
- `example_prd_rpg.txt` - Advanced RPG (Repository Planning Graph) template for complex projects with dependencies
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
|
||||||
You can co-write your PRD with an LLM model using the following workflow:
|
You can co-write your PRD with an LLM model using the following workflow:
|
||||||
@@ -43,6 +47,29 @@ You can co-write your PRD with an LLM model using the following workflow:
|
|||||||
|
|
||||||
This approach works great in Cursor, or anywhere you use a chat-based LLM.
|
This approach works great in Cursor, or anywhere you use a chat-based LLM.
|
||||||
|
|
||||||
|
### Choosing Between Templates
|
||||||
|
|
||||||
|
**Use `example_prd.txt` when:**
|
||||||
|
- Building straightforward features
|
||||||
|
- Working on smaller projects
|
||||||
|
- Dependencies are simple and obvious
|
||||||
|
|
||||||
|
**Use `example_prd_rpg.txt` when:**
|
||||||
|
- Building complex systems with multiple modules
|
||||||
|
- Need explicit dependency management
|
||||||
|
- Want structured guidance on architecture decisions
|
||||||
|
- Planning a large codebase from scratch
|
||||||
|
|
||||||
|
The RPG template teaches you to think about:
|
||||||
|
1. **Functional decomposition** (WHAT the system does)
|
||||||
|
2. **Structural decomposition** (HOW it's organized in code)
|
||||||
|
3. **Explicit dependencies** (WHAT depends on WHAT)
|
||||||
|
4. **Topological ordering** (build foundation first, then layers)
|
||||||
|
|
||||||
|
<Tip>
|
||||||
|
For complex projects, using the RPG template with a code-context-aware ai agent produces the best results because the AI can understand your existing codebase structure. [Learn more about the RPG method →](/capabilities/rpg-method)
|
||||||
|
</Tip>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Where to Save Your PRD
|
## Where to Save Your PRD
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ sidebarTitle: "Quick Start"
|
|||||||
This guide is for new users who want to start using Task Master with minimal setup time.
|
This guide is for new users who want to start using Task Master with minimal setup time.
|
||||||
|
|
||||||
It covers:
|
It covers:
|
||||||
- [Requirements](/docs/getting-started/quick-start/requirements): You will need Node.js and an AI model API Key.
|
- [Requirements](/getting-started/quick-start/requirements): You will need Node.js and an AI model API Key.
|
||||||
- [Installation](/docs/getting-started/quick-start/installation): How to Install Task Master.
|
- [Installation](/getting-started/quick-start/installation): How to Install Task Master.
|
||||||
- [Configuration](/docs/getting-started/quick-start/configuration-quick): Setting up your API Key, MCP, and more.
|
- [Configuration](/getting-started/quick-start/configuration-quick): Setting up your API Key, MCP, and more.
|
||||||
- [PRD](/docs/getting-started/quick-start/prd-quick): Writing and parsing your first PRD.
|
- [PRD](/getting-started/quick-start/prd-quick): Writing and parsing your first PRD.
|
||||||
- [Task Setup](/docs/getting-started/quick-start/tasks-quick): Preparing your tasks for execution.
|
- [Task Setup](/getting-started/quick-start/tasks-quick): Preparing your tasks for execution.
|
||||||
- [Executing Tasks](/docs/getting-started/quick-start/execute-quick): Using Task Master to execute tasks.
|
- [Executing Tasks](/getting-started/quick-start/execute-quick): Using Task Master to execute tasks.
|
||||||
- [Rules & Context](/docs/getting-started/quick-start/rules-quick): Learn how and why to build context in your project over time.
|
- [Rules & Context](/getting-started/quick-start/rules-quick): Learn how and why to build context in your project over time.
|
||||||
|
|
||||||
<Tip>
|
<Tip>
|
||||||
By the end of this guide, you'll have everything you need to begin working productively with Task Master.
|
By the end of this guide, you'll have everything you need to begin working productively with Task Master.
|
||||||
|
|||||||
@@ -80,6 +80,6 @@ You can view the report in a friendly table using:
|
|||||||
Can you show me the complexity report in a more readable format?
|
Can you show me the complexity report in a more readable format?
|
||||||
```
|
```
|
||||||
|
|
||||||
For more detailed CLI options, see the [Analyze Task Complexity](/docs/capabilities/cli-root-commands#analyze-task-complexity) section.
|
For more detailed CLI options, see the [Analyze Task Complexity](/capabilities/cli-root-commands#analyze-task-complexity) section.
|
||||||
|
|
||||||
<Check>Now you are ready to begin [executing tasks](/docs/getting-started/quick-start/execute-quick)</Check>
|
<Check>Now you are ready to begin [executing tasks](/getting-started/quick-start/execute-quick)</Check>
|
||||||
@@ -4,7 +4,7 @@ Welcome to v1 of the Task Master Docs. Expect weekly updates as we expand and re
|
|||||||
|
|
||||||
We've organized the docs into three sections depending on your experience level and goals:
|
We've organized the docs into three sections depending on your experience level and goals:
|
||||||
|
|
||||||
### Getting Started - Jump in to [Quick Start](/docs/getting-started/quick-start)
|
### Getting Started - Jump in to [Quick Start](/getting-started/quick-start)
|
||||||
Designed for first-time users. Get set up, create your first PRD, and run your first task.
|
Designed for first-time users. Get set up, create your first PRD, and run your first task.
|
||||||
|
|
||||||
### Best Practices
|
### Best Practices
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "docs",
|
"name": "docs",
|
||||||
"version": "0.0.3",
|
"version": "0.0.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Task Master documentation powered by Mintlify",
|
"description": "Task Master documentation powered by Mintlify",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,5 +1,47 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 0.25.5-rc.0
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`aaacc3d`](https://github.com/eyaltoledano/claude-task-master/commit/aaacc3dae36247b4de72b2d2697f49e5df6d01e3), [`0079b7d`](https://github.com/eyaltoledano/claude-task-master/commit/0079b7defdad550811f704c470fdd01955d91d4d), [`0b2c696`](https://github.com/eyaltoledano/claude-task-master/commit/0b2c6967c4605c33a100cff16f6ce8ff09ad06f0), [`18aa416`](https://github.com/eyaltoledano/claude-task-master/commit/18aa416035f44345bde1c7321490345733a5d042), [`18aa416`](https://github.com/eyaltoledano/claude-task-master/commit/18aa416035f44345bde1c7321490345733a5d042), [`738ec51`](https://github.com/eyaltoledano/claude-task-master/commit/738ec51c049a295a12839b2dfddaf05e23b8fede), [`d67b81d`](https://github.com/eyaltoledano/claude-task-master/commit/d67b81d25ddd927fabb6f5deb368e8993519c541), [`b5fe723`](https://github.com/eyaltoledano/claude-task-master/commit/b5fe723f8ead928e9f2dbde13b833ee70ac3382d), [`2b69936`](https://github.com/eyaltoledano/claude-task-master/commit/2b69936ee7b34346d6de5175af20e077359e2e2a), [`986ac11`](https://github.com/eyaltoledano/claude-task-master/commit/986ac117aee00bcd3e6830a0f76e1ad6d10e0bca), [`20004a3`](https://github.com/eyaltoledano/claude-task-master/commit/20004a39ea848f747e1ff48981bfe176554e4055)]:
|
||||||
|
- task-master-ai@0.28.0-rc.0
|
||||||
|
|
||||||
|
## 0.25.4
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`af53525`](https://github.com/eyaltoledano/claude-task-master/commit/af53525cbc660a595b67d4bb90d906911c71f45d)]:
|
||||||
|
- task-master-ai@0.27.3
|
||||||
|
|
||||||
|
## 0.25.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`044a7bf`](https://github.com/eyaltoledano/claude-task-master/commit/044a7bfc98049298177bc655cf341d7a8b6a0011)]:
|
||||||
|
- task-master-ai@0.27.2
|
||||||
|
|
||||||
|
## 0.25.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`f487736`](https://github.com/eyaltoledano/claude-task-master/commit/f487736670ef8c484059f676293777eabb249c9e), [`c911608`](https://github.com/eyaltoledano/claude-task-master/commit/c911608f60454253f4e024b57ca84e5a5a53f65c), [`1a18794`](https://github.com/eyaltoledano/claude-task-master/commit/1a1879483b86c118a4e46c02cbf4acebfcf6bcf9)]:
|
||||||
|
- task-master-ai@0.27.1
|
||||||
|
|
||||||
|
## 0.25.2-rc.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`1a18794`](https://github.com/eyaltoledano/claude-task-master/commit/1a1879483b86c118a4e46c02cbf4acebfcf6bcf9)]:
|
||||||
|
- task-master-ai@0.27.1-rc.1
|
||||||
|
|
||||||
|
## 0.25.2-rc.0
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`f487736`](https://github.com/eyaltoledano/claude-task-master/commit/f487736670ef8c484059f676293777eabb249c9e)]:
|
||||||
|
- task-master-ai@0.27.1-rc.0
|
||||||
|
|
||||||
## 0.25.0
|
## 0.25.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"displayName": "TaskMaster",
|
"displayName": "TaskMaster",
|
||||||
"description": "A visual Kanban board interface for TaskMaster projects in VS Code",
|
"description": "A visual Kanban board interface for TaskMaster projects in VS Code",
|
||||||
"version": "0.25.0",
|
"version": "0.25.5-rc.0",
|
||||||
"publisher": "Hamster",
|
"publisher": "Hamster",
|
||||||
"icon": "assets/icon.png",
|
"icon": "assets/icon.png",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -254,8 +254,9 @@
|
|||||||
"@radix-ui/react-separator": "^1.1.7",
|
"@radix-ui/react-separator": "^1.1.7",
|
||||||
"@radix-ui/react-slot": "^1.2.3",
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
"@tailwindcss/postcss": "^4.1.11",
|
"@tailwindcss/postcss": "^4.1.11",
|
||||||
|
"@tanstack/react-query": "^5.83.0",
|
||||||
"@types/mocha": "^10.0.10",
|
"@types/mocha": "^10.0.10",
|
||||||
"@types/node": "20.x",
|
"@types/node": "^22.10.5",
|
||||||
"@types/react": "19.1.8",
|
"@types/react": "19.1.8",
|
||||||
"@types/react-dom": "19.1.6",
|
"@types/react-dom": "19.1.6",
|
||||||
"@types/vscode": "^1.101.0",
|
"@types/vscode": "^1.101.0",
|
||||||
@@ -271,12 +272,12 @@
|
|||||||
"lucide-react": "^0.525.0",
|
"lucide-react": "^0.525.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"postcss": "8.5.6",
|
"postcss": "8.5.6",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-dom": "^19.0.0",
|
||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.3.1",
|
||||||
"tailwindcss": "4.1.11",
|
"tailwindcss": "4.1.11",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.9.2",
|
||||||
"@tanstack/react-query": "^5.83.0",
|
"@tm/core": "*"
|
||||||
"react": "^19.0.0",
|
|
||||||
"react-dom": "^19.0.0"
|
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"glob@<8": "^10.4.5",
|
"glob@<8": "^10.4.5",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "task-master-hamster",
|
"name": "task-master-hamster",
|
||||||
"displayName": "Taskmaster AI",
|
"displayName": "Taskmaster AI",
|
||||||
"description": "A visual Kanban board interface for Taskmaster projects in VS Code",
|
"description": "A visual Kanban board interface for Taskmaster projects in VS Code",
|
||||||
"version": "0.23.1",
|
"version": "0.25.3",
|
||||||
"publisher": "Hamster",
|
"publisher": "Hamster",
|
||||||
"icon": "assets/icon.png",
|
"icon": "assets/icon.png",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
"outDir": "out",
|
"outDir": "out",
|
||||||
"lib": ["ES2022", "DOM"],
|
"lib": ["ES2022", "DOM"],
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"rootDir": "src",
|
|
||||||
"strict": true /* enable all strict type-checking options */,
|
"strict": true /* enable all strict type-checking options */,
|
||||||
"moduleResolution": "Node",
|
"moduleResolution": "Node",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
@@ -21,8 +20,10 @@
|
|||||||
"@/*": ["./src/*"],
|
"@/*": ["./src/*"],
|
||||||
"@/components/*": ["./src/components/*"],
|
"@/components/*": ["./src/components/*"],
|
||||||
"@/lib/*": ["./src/lib/*"],
|
"@/lib/*": ["./src/lib/*"],
|
||||||
"@tm/core": ["../core/src"]
|
"@tm/core": ["../../packages/tm-core/src/index.ts"],
|
||||||
|
"@tm/core/*": ["../../packages/tm-core/src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
"exclude": ["node_modules", ".vscode-test", "out", "dist"]
|
"exclude": ["node_modules", ".vscode-test", "out", "dist"]
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user