Compare commits
107 Commits
update.fro
...
v017-adds
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c2e6b2466 | ||
|
|
f07945734d | ||
|
|
d5360f625f | ||
|
|
2e2d290c63 | ||
|
|
d3edd24b5a | ||
|
|
60c0f26f3c | ||
|
|
be0bf18f41 | ||
|
|
32236a0bc5 | ||
|
|
a047886910 | ||
|
|
92234323d7 | ||
|
|
514fdb0b78 | ||
|
|
932825c2d6 | ||
|
|
3c8c62434f | ||
|
|
9d755b9e79 | ||
|
|
fcc2351b3d | ||
|
|
3db62b5b88 | ||
|
|
6b929fa9fa | ||
|
|
ddaa1dceef | ||
|
|
cac8c234d6 | ||
|
|
b205e52d08 | ||
|
|
4585a6bbc7 | ||
|
|
b3ec151b27 | ||
|
|
5d9748af89 | ||
|
|
b28479a09d | ||
|
|
9efbd38f10 | ||
|
|
75e017e371 | ||
|
|
a84cd1a492 | ||
|
|
3888ef41d4 | ||
|
|
83d6405b17 | ||
|
|
bb775e3180 | ||
|
|
2328efe482 | ||
|
|
f3fe481f3f | ||
|
|
f43b5fdd75 | ||
|
|
153b190e0d | ||
|
|
0be5ae59fe | ||
|
|
f1d593f887 | ||
|
|
efd14544f0 | ||
|
|
ef9439d441 | ||
|
|
a49071a6b8 | ||
|
|
c2d83690a1 | ||
|
|
b40a94c4ac | ||
|
|
05a389e171 | ||
|
|
3352a6a99f | ||
|
|
d391f3b5b3 | ||
|
|
f2c5911e58 | ||
|
|
bb5a0211f4 | ||
|
|
4234cc3d87 | ||
|
|
d942db4868 | ||
|
|
3cf718a718 | ||
|
|
a2ff8a97b7 | ||
|
|
b1b888a5f3 | ||
|
|
f817de9da6 | ||
|
|
806c505aac | ||
|
|
6f225cf81a | ||
|
|
74eb9907f3 | ||
|
|
5c29969741 | ||
|
|
8e794e18ac | ||
|
|
3ce4d2cc74 | ||
|
|
2d85fcc6a7 | ||
|
|
0102be4f3b | ||
|
|
b6f1376625 | ||
|
|
d4f21be1a3 | ||
|
|
f28de8b729 | ||
|
|
e50230f9ce | ||
|
|
01992ebd0b | ||
|
|
af652978a0 | ||
|
|
54005d5486 | ||
|
|
65b70d746a | ||
|
|
f533fd0931 | ||
|
|
7db7cf3859 | ||
|
|
2434b97247 | ||
|
|
bac58c606d | ||
|
|
89f8bff219 | ||
|
|
366cd161da | ||
|
|
a346dd5020 | ||
|
|
c2709edd78 | ||
|
|
e53006066e | ||
|
|
2d11b94804 | ||
|
|
a5e36cf7b4 | ||
|
|
9cd18caa3c | ||
|
|
9058d7dfdd | ||
|
|
199e32c2d1 | ||
|
|
a874a12e17 | ||
|
|
eb343287ae | ||
|
|
94eeb5117b | ||
|
|
87c85d3d66 | ||
|
|
0b8f594ac7 | ||
|
|
15b190b87b | ||
|
|
9ae255ccb4 | ||
|
|
518f73eefa | ||
|
|
78397fe0be | ||
|
|
f9b89dc25c | ||
|
|
ca69e1294f | ||
|
|
ac36e2497e | ||
|
|
1d4b80fe6f | ||
|
|
023f51c579 | ||
|
|
1e020023ed | ||
|
|
325f5a2aa3 | ||
|
|
de46bfd84b | ||
|
|
cc26c36366 | ||
|
|
15ad34928d | ||
|
|
f74d639110 | ||
|
|
de58e9ede5 | ||
|
|
947541e4ee | ||
|
|
275cd55da7 | ||
|
|
67ac212973 | ||
|
|
235371ff47 |
5
.changeset/curly-dragons-design.md
Normal file
5
.changeset/curly-dragons-design.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
improve findTasks algorithm for resolving tasks path
|
||||
5
.changeset/eleven-news-check.md
Normal file
5
.changeset/eleven-news-check.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fix update tool on MCP giving `No valid tasks found`
|
||||
39
.changeset/four-cups-enter.md
Normal file
39
.changeset/four-cups-enter.md
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Enhanced add-task fuzzy search intelligence and improved user experience
|
||||
|
||||
**Smarter Task Discovery:**
|
||||
|
||||
- Remove hardcoded category system that always matched "Task management"
|
||||
- Eliminate arbitrary limits on fuzzy search results (5→25 high relevance, 3→10 medium relevance, 8→20 detailed tasks)
|
||||
- Improve semantic weighting in Fuse.js search (details=3, description=2, title=1.5) for better relevance
|
||||
- Generate context-driven task recommendations based on true semantic similarity
|
||||
|
||||
**Enhanced Terminal Experience:**
|
||||
|
||||
- Fix duplicate banner display issue that was "eating" terminal history (closes #553)
|
||||
- Remove console.clear() and redundant displayBanner() calls from UI functions
|
||||
- Preserve command history for better development workflow
|
||||
- Streamline banner display across all commands (list, next, show, set-status, clear-subtasks, dependency commands)
|
||||
|
||||
**Visual Improvements:**
|
||||
|
||||
- Replace emoji complexity indicators with clean filled circle characters (●) for professional appearance
|
||||
- Improve consistency and readability of task complexity display
|
||||
|
||||
**AI Provider Compatibility:**
|
||||
|
||||
- Change generateObject mode from 'tool' to 'auto' for better cross-provider compatibility
|
||||
- Add qwen3-235n-a22b:free model support (closes #687)
|
||||
- Add smart warnings for free OpenRouter models with limitations (rate limits, restricted context, no tool_use)
|
||||
|
||||
**Technical Improvements:**
|
||||
|
||||
- Enhanced context generation in add-task to rely on semantic similarity rather than rigid pattern matching
|
||||
- Improved dependency analysis and common pattern detection
|
||||
- Better handling of task relationships and relevance scoring
|
||||
- More intelligent task suggestion algorithms
|
||||
|
||||
The add-task system now provides truly relevant task context based on semantic understanding rather than arbitrary categories and limits, while maintaining a cleaner and more professional terminal experience.
|
||||
7
.changeset/pink-houses-lay.md
Normal file
7
.changeset/pink-houses-lay.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fix double .taskmaster directory paths in file resolution utilities
|
||||
|
||||
- Closes #636
|
||||
5
.changeset/polite-areas-shave.md
Normal file
5
.changeset/polite-areas-shave.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Add one-click MCP server installation for Cursor
|
||||
@@ -2,30 +2,10 @@
|
||||
"mode": "exit",
|
||||
"tag": "rc",
|
||||
"initialVersions": {
|
||||
"task-master-ai": "0.16.2"
|
||||
"task-master-ai": "0.16.1"
|
||||
},
|
||||
"changesets": [
|
||||
"bright-windows-sing",
|
||||
"chatty-rats-talk",
|
||||
"cold-pears-poke",
|
||||
"curly-dragons-design",
|
||||
"eleven-news-check",
|
||||
"fluffy-waves-allow",
|
||||
"four-cups-enter",
|
||||
"free-pants-rescue",
|
||||
"large-wolves-strive",
|
||||
"late-dryers-relax",
|
||||
"nasty-chefs-add",
|
||||
"pink-houses-lay",
|
||||
"polite-areas-shave",
|
||||
"quick-flies-sniff",
|
||||
"six-cups-see",
|
||||
"slick-webs-lead",
|
||||
"slow-lies-make",
|
||||
"stale-bats-sin",
|
||||
"tiny-ads-decide",
|
||||
"two-lies-start",
|
||||
"vast-shrimps-happen",
|
||||
"yellow-olives-admire"
|
||||
"polite-areas-shave"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
22
.changeset/vast-shrimps-happen.md
Normal file
22
.changeset/vast-shrimps-happen.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Add sync-readme command for a task export to GitHub README
|
||||
|
||||
Introduces a new `sync-readme` command that exports your task list to your project's README.md file.
|
||||
|
||||
**Features:**
|
||||
|
||||
- **Flexible filtering**: Supports `--status` filtering (e.g., pending, done) and `--with-subtasks` flag
|
||||
- **Smart content management**: Automatically replaces existing exports or appends to new READMEs
|
||||
- **Metadata display**: Shows export timestamp, subtask inclusion status, and filter settings
|
||||
|
||||
**Usage:**
|
||||
|
||||
- `task-master sync-readme` - Export tasks without subtasks
|
||||
- `task-master sync-readme --with-subtasks` - Include subtasks in export
|
||||
- `task-master sync-readme --status=pending` - Only export pending tasks
|
||||
- `task-master sync-readme --status=done --with-subtasks` - Export completed tasks with subtasks
|
||||
|
||||
Perfect for showcasing project progress on GitHub. Experimental. Open to feedback.
|
||||
@@ -49,11 +49,13 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* **Key Parameters/Options:**
|
||||
* `input`: `Path to your PRD or requirements text file that Taskmaster should parse for tasks.` (CLI: `[file]` positional or `-i, --input <file>`)
|
||||
* `output`: `Specify where Taskmaster should save the generated 'tasks.json' file. Defaults to '.taskmaster/tasks/tasks.json'.` (CLI: `-o, --output <file>`)
|
||||
* `output`: `Specify where Taskmaster should save the generated 'tasks.json' file. Defaults to '.taskmaster/tasks/tasks.json'.` (CLI: `-o, --output <file>`)
|
||||
* `numTasks`: `Approximate number of top-level tasks Taskmaster should aim to generate from the document.` (CLI: `-n, --num-tasks <number>`)
|
||||
* `force`: `Use this to allow Taskmaster to overwrite an existing 'tasks.json' without asking for confirmation.` (CLI: `-f, --force`)
|
||||
* **Usage:** Useful for bootstrapping a project from an existing requirements document.
|
||||
* **Notes:** Task Master will strictly adhere to any specific requirements mentioned in the PRD, such as libraries, database schemas, frameworks, tech stacks, etc., while filling in any gaps where the PRD isn't fully specified. Tasks are designed to provide the most direct implementation path while avoiding over-engineering.
|
||||
* **Important:** This MCP tool makes AI calls and can take up to a minute to complete. Please inform users to hang tight while the operation is in progress. If the user does not have a PRD, suggest discussing their idea and then use the example PRD in `.taskmaster/templates/example_prd.txt` as a template for creating the PRD based on their idea, for use with `parse-prd`.
|
||||
* **Important:** This MCP tool makes AI calls and can take up to a minute to complete. Please inform users to hang tight while the operation is in progress. If the user does not have a PRD, suggest discussing their idea and then use the example PRD in `.taskmaster/templates/example_prd.txt` as a template for creating the PRD based on their idea, for use with `parse-prd`.
|
||||
|
||||
---
|
||||
|
||||
@@ -81,9 +83,11 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* **Usage (MCP):** Call without set flags to get current config. Use `setMain`, `setResearch`, or `setFallback` with a valid model ID to update the configuration. Use `listAvailableModels: true` to get a list of unassigned models. To set a custom model, provide the model ID and set `ollama: true` or `openrouter: true`.
|
||||
* **Usage (CLI):** Run without flags to view current configuration and available models. Use set flags to update specific roles. Use `--setup` for guided configuration, including custom models. To set a custom model via flags, use `--set-<role>=<model_id>` along with either `--ollama` or `--openrouter`.
|
||||
* **Notes:** Configuration is stored in `.taskmaster/config.json` in the project root. This command/tool modifies that file. Use `listAvailableModels` or `task-master models` to see internally supported models. OpenRouter custom models are validated against their live API. Ollama custom models are not validated live.
|
||||
* **Notes:** Configuration is stored in `.taskmaster/config.json` in the project root. This command/tool modifies that file. Use `listAvailableModels` or `task-master models` to see internally supported models. OpenRouter custom models are validated against their live API. Ollama custom models are not validated live.
|
||||
* **API note:** API keys for selected AI providers (based on their model) need to exist in the mcp.json file to be accessible in MCP context. The API keys must be present in the local .env file for the CLI to be able to read them.
|
||||
* **Model costs:** The costs in supported models are expressed in dollars. An input/output value of 3 is $3.00. A value of 0.8 is $0.80.
|
||||
* **Warning:** DO NOT MANUALLY EDIT THE .taskmaster/config.json FILE. Use the included commands either in the MCP or CLI format as needed. Always prioritize MCP tools when available and use the CLI as a fallback.
|
||||
* **Warning:** DO NOT MANUALLY EDIT THE .taskmaster/config.json FILE. Use the included commands either in the MCP or CLI format as needed. Always prioritize MCP tools when available and use the CLI as a fallback.
|
||||
|
||||
---
|
||||
|
||||
@@ -374,6 +378,7 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* **Description:** `Display the task complexity analysis report in a readable format.`
|
||||
* **Key Parameters/Options:**
|
||||
* `file`: `Path to the complexity report (default: '.taskmaster/reports/task-complexity-report.json').` (CLI: `-f, --file <file>`)
|
||||
* `file`: `Path to the complexity report (default: '.taskmaster/reports/task-complexity-report.json').` (CLI: `-f, --file <file>`)
|
||||
* **Usage:** Review and understand the complexity analysis results after running analyze-complexity.
|
||||
|
||||
---
|
||||
@@ -512,6 +517,7 @@ This new suite of commands allows you to manage different task contexts (tags).
|
||||
|
||||
## Environment Variables Configuration (Updated)
|
||||
|
||||
Taskmaster primarily uses the **`.taskmaster/config.json`** file (in project root) for configuration (models, parameters, logging level, etc.), managed via `task-master models --setup`.
|
||||
Taskmaster primarily uses the **`.taskmaster/config.json`** file (in project root) for configuration (models, parameters, logging level, etc.), managed via `task-master models --setup`.
|
||||
|
||||
Environment variables are used **only** for sensitive API keys related to AI providers and specific overrides like the Ollama base URL:
|
||||
@@ -526,11 +532,14 @@ Environment variables are used **only** for sensitive API keys related to AI pro
|
||||
* `OPENROUTER_API_KEY`
|
||||
* `XAI_API_KEY`
|
||||
* `OLLAMA_API_KEY` (Requires `OLLAMA_BASE_URL` too)
|
||||
* **Endpoints (Optional/Provider Specific inside .taskmaster/config.json):**
|
||||
* `OLLAMA_API_KEY` (Requires `OLLAMA_BASE_URL` too)
|
||||
* **Endpoints (Optional/Provider Specific inside .taskmaster/config.json):**
|
||||
* `AZURE_OPENAI_ENDPOINT`
|
||||
* `OLLAMA_BASE_URL` (Default: `http://localhost:11434/api`)
|
||||
|
||||
**Set API keys** in your **`.env`** file in the project root (for CLI use) or within the `env` section of your **`.cursor/mcp.json`** file (for MCP/Cursor integration). All other settings (model choice, max tokens, temperature, log level, custom endpoints) are managed in `.taskmaster/config.json` via `task-master models` command or `models` MCP tool.
|
||||
**Set API keys** in your **`.env`** file in the project root (for CLI use) or within the `env` section of your **`.cursor/mcp.json`** file (for MCP/Cursor integration). All other settings (model choice, max tokens, temperature, log level, custom endpoints) are managed in `.taskmaster/config.json` via `task-master models` command or `models` MCP tool.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"meta": {
|
||||
"generatedAt": "2025-05-27T16:34:53.088Z",
|
||||
"tasksAnalyzed": 1,
|
||||
"totalTasks": 84,
|
||||
"analysisCount": 45,
|
||||
"generatedAt": "2025-05-22T05:48:33.026Z",
|
||||
"tasksAnalyzed": 6,
|
||||
"totalTasks": 88,
|
||||
"analysisCount": 43,
|
||||
"thresholdScore": 5,
|
||||
"projectName": "Taskmaster",
|
||||
"usedResearch": true
|
||||
@@ -313,6 +313,14 @@
|
||||
"expansionPrompt": "Break down the update of ai-services-unified.js for dynamic token limits into subtasks such as: (1) Import and integrate the token counting utility, (2) Refactor _unifiedServiceRunner to calculate and enforce dynamic token limits, (3) Update error handling for token limit violations, (4) Add and verify logging for token usage, (5) Write and execute tests for various prompt and model scenarios.",
|
||||
"reasoning": "This task involves significant code changes to a core function, integration of a new utility, dynamic logic for multiple models, and robust error handling. It also requires comprehensive testing for edge cases and integration, making it moderately complex and best managed by splitting into focused subtasks."
|
||||
},
|
||||
{
|
||||
"taskId": 86,
|
||||
"taskTitle": "Update .taskmasterconfig schema and user guide",
|
||||
"complexityScore": 6,
|
||||
"recommendedSubtasks": 4,
|
||||
"expansionPrompt": "Expand this task into subtasks: (1) Draft a migration guide for users, (2) Update user documentation to explain new config fields, (3) Modify schema validation logic in config-manager.js, (4) Test and validate backward compatibility and error messaging.",
|
||||
"reasoning": "The task spans documentation, schema changes, migration guidance, and validation logic. While not algorithmically complex, it requires careful coordination and thorough testing to ensure a smooth user transition and robust validation."
|
||||
},
|
||||
{
|
||||
"taskId": 87,
|
||||
"taskTitle": "Implement validation and error handling",
|
||||
@@ -344,30 +352,6 @@
|
||||
"recommendedSubtasks": 5,
|
||||
"expansionPrompt": "Expand this task into: (1) Implement move logic for tasks and subtasks, (2) Handle edge cases (invalid ids, non-existent parents, circular dependencies), (3) Update CLI to support move command with flags, (4) Ensure data integrity and update relationships, (5) Write and execute tests for various move scenarios.",
|
||||
"reasoning": "Moving tasks and subtasks requires careful handling of hierarchical data, edge cases, and data integrity. The command must be robust and user-friendly, necessitating multiple focused subtasks for safe implementation."
|
||||
},
|
||||
{
|
||||
"taskId": 92,
|
||||
"taskTitle": "Add Global Joke Flag to All CLI Commands",
|
||||
"complexityScore": 8,
|
||||
"recommendedSubtasks": 7,
|
||||
"expansionPrompt": "Break down the implementation of the global --joke flag into the following subtasks: (1) Update CLI foundation to support global flags, (2) Develop the joke-service module with joke management and category support, (3) Integrate joke output into existing output utilities, (4) Update all CLI commands for joke flag compatibility, (5) Add configuration options for joke categories and custom jokes, (6) Implement comprehensive testing (flag recognition, output, content, integration, performance, regression), (7) Update documentation and usage examples.",
|
||||
"reasoning": "This task requires changes across the CLI foundation, output utilities, all command modules, and configuration management. It introduces a new service module, global flag handling, and output logic that must not interfere with existing features (including JSON output). The need for robust testing and backward compatibility further increases complexity. The scope spans multiple code areas and requires careful integration, justifying a high complexity score and a detailed subtask breakdown to manage risk and ensure maintainability.[2][3][5]"
|
||||
},
|
||||
{
|
||||
"taskId": 94,
|
||||
"taskTitle": "Implement Standalone 'research' CLI Command for AI-Powered Queries",
|
||||
"complexityScore": 7,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "Break down the implementation of the 'research' CLI command into logical subtasks covering command registration, parameter handling, context gathering, AI service integration, output formatting, and documentation.",
|
||||
"reasoning": "This task has moderate to high complexity (7/10) due to multiple interconnected components: CLI argument parsing, integration with AI services, context gathering from various sources, and output formatting with different modes. The cyclomatic complexity would be significant with multiple decision paths for handling different flags and options. The task requires understanding existing patterns and extending the codebase in a consistent manner, suggesting the need for careful decomposition into manageable subtasks."
|
||||
},
|
||||
{
|
||||
"taskId": 86,
|
||||
"taskTitle": "Implement GitHub Issue Export Feature",
|
||||
"complexityScore": 9,
|
||||
"recommendedSubtasks": 10,
|
||||
"expansionPrompt": "Break down the implementation of the GitHub Issue Export Feature into detailed subtasks covering: command structure and CLI integration, GitHub API client development, authentication and error handling, task-to-issue mapping logic, content formatting and markdown conversion, bidirectional linking and metadata management, extensible architecture and adapter interfaces, configuration and settings management, documentation, and comprehensive testing (unit, integration, edge cases, performance).",
|
||||
"reasoning": "This task involves designing and implementing a robust, extensible export system with deep integration into GitHub, including bidirectional workflows, complex data mapping, error handling, and support for future platforms. The requirements span CLI design, API integration, content transformation, metadata management, extensibility, configuration, and extensive testing. The breadth and depth of these requirements, along with the need for maintainability and future extensibility, place this task at a high complexity level. Breaking it into at least 10 subtasks will ensure each major component and concern is addressed systematically, reducing risk and improving quality."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
461
CHANGELOG.md
461
CHANGELOG.md
@@ -1,466 +1,5 @@
|
||||
# task-master-ai
|
||||
|
||||
## 0.17.0-rc.1
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add comprehensive AI-powered research command with intelligent context gathering and interactive follow-ups.
|
||||
|
||||
The new `research` command provides AI-powered research capabilities that automatically gather relevant project context to answer your questions. The command intelligently selects context from multiple sources and supports interactive follow-up questions in CLI mode.
|
||||
|
||||
**Key Features:**
|
||||
|
||||
- **Intelligent Task Discovery**: Automatically finds relevant tasks and subtasks using fuzzy search based on your query keywords, supplementing any explicitly provided task IDs
|
||||
- **Multi-Source Context**: Gathers context from tasks, files, project structure, and custom text to provide comprehensive answers
|
||||
- **Interactive Follow-ups**: CLI users can ask follow-up questions that build on the conversation history while allowing fresh context discovery for each question
|
||||
- **Flexible Detail Levels**: Choose from low (concise), medium (balanced), or high (comprehensive) response detail levels
|
||||
- **Token Transparency**: Displays detailed token breakdown showing context size, sources, and estimated costs
|
||||
- **Enhanced Display**: Syntax-highlighted code blocks and structured output with clear visual separation
|
||||
|
||||
**Usage Examples:**
|
||||
|
||||
```bash
|
||||
# Basic research with auto-discovered context
|
||||
task-master research "How should I implement user authentication?"
|
||||
|
||||
# Research with specific task context
|
||||
task-master research "What's the best approach for this?" --id=15,23.2
|
||||
|
||||
# Research with file context and project tree
|
||||
task-master research "How does the current auth system work?" --files=src/auth.js,config/auth.json --tree
|
||||
|
||||
# Research with custom context and low detail
|
||||
task-master research "Quick implementation steps?" --context="Using JWT tokens" --detail=low
|
||||
```
|
||||
|
||||
**Context Sources:**
|
||||
|
||||
- **Tasks**: Automatically discovers relevant tasks/subtasks via fuzzy search, plus any explicitly specified via `--id`
|
||||
- **Files**: Include specific files via `--files` for code-aware responses
|
||||
- **Project Tree**: Add `--tree` to include project structure overview
|
||||
- **Custom Context**: Provide additional context via `--context` for domain-specific information
|
||||
|
||||
**Interactive Features (CLI only):**
|
||||
|
||||
- Follow-up questions that maintain conversation history
|
||||
- Fresh fuzzy search for each follow-up to discover newly relevant tasks
|
||||
- Cumulative context building across the conversation
|
||||
- Clean visual separation between exchanges
|
||||
- **Save to Tasks**: Save entire research conversations (including follow-ups) directly to task or subtask details with timestamps
|
||||
- **Clean Menu Interface**: Streamlined inquirer-based menu for follow-up actions without redundant UI elements
|
||||
|
||||
**Save Functionality:**
|
||||
|
||||
The research command now supports saving complete conversation threads to tasks or subtasks:
|
||||
|
||||
- Save research results and follow-up conversations to any task (e.g., "15") or subtask (e.g., "15.2")
|
||||
- Automatic timestamping and formatting of conversation history
|
||||
- Validation of task/subtask existence before saving
|
||||
- Appends to existing task details without overwriting content
|
||||
- Supports both CLI interactive mode and MCP programmatic access via `--save-to` flag
|
||||
|
||||
**Enhanced CLI Options:**
|
||||
|
||||
```bash
|
||||
# Auto-save research results to a task
|
||||
task-master research "Implementation approach?" --save-to=15
|
||||
|
||||
# Combine auto-save with context gathering
|
||||
task-master research "How to optimize this?" --id=23 --save-to=23.1
|
||||
```
|
||||
|
||||
**MCP Integration:**
|
||||
|
||||
- `saveTo` parameter for automatic saving to specified task/subtask ID
|
||||
- Structured response format with telemetry data
|
||||
- Silent operation mode for programmatic usage
|
||||
- Full feature parity with CLI except interactive follow-ups
|
||||
|
||||
The research command integrates with the existing AI service layer and supports all configured AI providers. Both CLI and MCP interfaces provide comprehensive research capabilities with intelligent context gathering and flexible output options.
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Enhance update-task with --append flag for timestamped task updates
|
||||
|
||||
Adds the `--append` flag to `update-task` command, enabling it to behave like `update-subtask` with timestamped information appending. This provides more flexible task updating options:
|
||||
|
||||
**CLI Enhancement:**
|
||||
|
||||
- `task-master update-task --id=5 --prompt="New info"` - Full task update (existing behavior)
|
||||
- `task-master update-task --id=5 --append --prompt="Progress update"` - Append timestamped info to task details
|
||||
|
||||
**Full MCP Integration:**
|
||||
|
||||
- MCP tool `update_task` now supports `append` parameter
|
||||
- Seamless integration with Cursor and other MCP clients
|
||||
- Consistent behavior between CLI and MCP interfaces
|
||||
|
||||
Instead of requiring separate subtask creation for progress tracking, you can now append timestamped information directly to parent tasks while preserving the option for comprehensive task updates.
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add --tag flag support to core commands for multi-context task management. Commands like parse-prd, analyze-complexity, and others now support targeting specific task lists, enabling rapid prototyping and parallel development workflows.
|
||||
|
||||
Key features:
|
||||
|
||||
- parse-prd --tag=feature-name: Parse PRDs into separate task contexts on the fly
|
||||
- analyze-complexity --tag=branch: Generate tag-specific complexity reports
|
||||
- All task operations can target specific contexts while preserving other lists
|
||||
- Non-existent tags are created automatically for seamless workflow
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Introduces Tagged Lists: AI Multi-Context Task Management System
|
||||
|
||||
This major release introduces Tagged Lists, a comprehensive system that transforms Task Master into a multi-context task management powerhouse. You can now organize tasks into completely isolated contexts, enabling parallel (agentic) development workflows, team collaboration, and project experimentation without conflicts.
|
||||
|
||||
**🏷️ Tagged Task Lists Architecture:**
|
||||
|
||||
The new tagged system fundamentally changes how tasks are organized:
|
||||
|
||||
- **Legacy Format**: `{ "tasks": [...] }`
|
||||
- **New Tagged Format**: `{ "master": { "tasks": [...], "metadata": {...} }, "feature-xyz": { "tasks": [...], "metadata": {...} } }`
|
||||
- **Automatic Migration**: Existing projects seamlessly migrate to tagged format with zero user intervention
|
||||
- **State Management**: New `.taskmaster/state.json` tracks current tag, last switched time, and migration status
|
||||
- **Configuration Integration**: Enhanced `.taskmaster/config.json` with tag-specific settings and defaults
|
||||
|
||||
**🚀 Complete Tag Management Suite:**
|
||||
|
||||
**Core Tag Commands:**
|
||||
|
||||
- `task-master tags [--show-metadata]` - List all tags with task counts, completion stats, and metadata
|
||||
- `task-master add-tag <name> [options]` - Create new tag contexts with optional task copying
|
||||
- `task-master delete-tag <name> [--yes]` - Delete tags with double confirmation protection
|
||||
- `task-master use-tag <name>` - Switch contexts and immediately see next available task
|
||||
- `task-master rename-tag <old> <new>` - Rename tags with automatic current tag reference updates
|
||||
- `task-master copy-tag <source> <target> [options]` - Duplicate tag contexts for experimentation
|
||||
|
||||
**🤖 Full MCP Integration for Tag Management:**
|
||||
|
||||
Task Master's multi-context capabilities are now fully exposed through the MCP server, enabling powerful agentic workflows:
|
||||
|
||||
- **`list_tags`**: List all available tag contexts.
|
||||
- **`add_tag`**: Programmatically create new tags.
|
||||
- **`delete_tag`**: Remove tag contexts.
|
||||
- **`use_tag`**: Switch the agent's active task context.
|
||||
- **`rename_tag`**: Rename existing tags.
|
||||
- **`copy_tag`**: Duplicate entire task contexts for experimentation.
|
||||
|
||||
**Tag Creation Options:**
|
||||
|
||||
- `--copy-from-current` - Copy tasks from currently active tag
|
||||
- `--copy-from=<tag>` - Copy tasks from specific tag
|
||||
- `--from-branch` - Creates a new tag usin active git branch name (for `add-tag` only)
|
||||
- `--description="<text>"` - Add custom tag descriptions
|
||||
- Empty tag creation for fresh contexts
|
||||
|
||||
**🎯 Universal --tag Flag Support:**
|
||||
|
||||
Every task operation now supports tag-specific execution:
|
||||
|
||||
- `task-master list --tag=feature-branch` - View tasks in specific context
|
||||
- `task-master add-task --tag=experiment --prompt="..."` - Create tasks in specific tag
|
||||
- `task-master parse-prd document.txt --tag=v2-redesign` - Parse PRDs into dedicated contexts
|
||||
- `task-master analyze-complexity --tag=performance-work` - Generate tag-specific reports
|
||||
- `task-master set-status --tag=hotfix --id=5 --status=done` - Update tasks in specific contexts
|
||||
- `task-master expand --tag=research --id=3` - Break down tasks within tag contexts
|
||||
|
||||
**📊 Enhanced Workflow Features:**
|
||||
|
||||
**Smart Context Switching:**
|
||||
|
||||
- `use-tag` command shows immediate next task after switching
|
||||
- Automatic tag creation when targeting non-existent tags
|
||||
- Current tag persistence across terminal sessions
|
||||
- Branch-tag mapping for future Git integration
|
||||
|
||||
**Intelligent File Management:**
|
||||
|
||||
- Tag-specific complexity reports: `task-complexity-report_tagname.json`
|
||||
- Master tag uses default filenames: `task-complexity-report.json`
|
||||
- Automatic file isolation prevents cross-tag contamination
|
||||
|
||||
**Advanced Confirmation Logic:**
|
||||
|
||||
- Commands only prompt when target tag has existing tasks
|
||||
- Empty tags allow immediate operations without confirmation
|
||||
- Smart append vs overwrite detection
|
||||
|
||||
**🔄 Seamless Migration & Compatibility:**
|
||||
|
||||
**Zero-Disruption Migration:**
|
||||
|
||||
- Existing `tasks.json` files automatically migrate on first command
|
||||
- Master tag receives proper metadata (creation date, description)
|
||||
- Migration notice shown once with helpful explanation
|
||||
- All existing commands work identically to before
|
||||
|
||||
**State Management:**
|
||||
|
||||
- `.taskmaster/state.json` tracks current tag and migration status
|
||||
- Automatic state creation and maintenance
|
||||
- Branch-tag mapping foundation for Git integration
|
||||
- Migration notice tracking to avoid repeated notifications
|
||||
- Grounds for future context additions
|
||||
|
||||
**Backward Compatibility:**
|
||||
|
||||
- All existing workflows continue unchanged
|
||||
- Legacy commands work exactly as before
|
||||
- Gradual adoption - users can ignore tags entirely if desired
|
||||
- No breaking changes to existing tasks or file formats
|
||||
|
||||
**💡 Real-World Use Cases:**
|
||||
|
||||
**Team Collaboration:**
|
||||
|
||||
- `task-master add-tag alice --copy-from-current` - Create teammate-specific contexts
|
||||
- `task-master add-tag bob --copy-from=master` - Onboard new team members
|
||||
- `task-master use-tag alice` - Switch to teammate's work context
|
||||
|
||||
**Feature Development:**
|
||||
|
||||
- `task-master parse-prd feature-spec.txt --tag=user-auth` - Dedicated feature planning
|
||||
- `task-master add-tag experiment --copy-from=user-auth` - Safe experimentation
|
||||
- `task-master analyze-complexity --tag=user-auth` - Feature-specific analysis
|
||||
|
||||
**Release Management:**
|
||||
|
||||
- `task-master add-tag v2.0 --description="Next major release"` - Version-specific planning
|
||||
- `task-master copy-tag master v2.1` - Release branch preparation
|
||||
- `task-master use-tag hotfix` - Emergency fix context
|
||||
|
||||
**Project Phases:**
|
||||
|
||||
- `task-master add-tag research --description="Discovery phase"` - Research tasks
|
||||
- `task-master add-tag implementation --copy-from=research` - Development phase
|
||||
- `task-master add-tag testing --copy-from=implementation` - QA phase
|
||||
|
||||
**🛠️ Technical Implementation:**
|
||||
|
||||
**Data Structure:**
|
||||
|
||||
- Tagged format with complete isolation between contexts
|
||||
- Rich metadata per tag (creation date, description, update tracking)
|
||||
- Automatic metadata enhancement for existing tags
|
||||
- Clean separation of tag data and internal state
|
||||
|
||||
**Performance Optimizations:**
|
||||
|
||||
- Dynamic task counting without stored counters
|
||||
- Efficient tag resolution and caching
|
||||
- Minimal file I/O with smart data loading
|
||||
- Responsive table layouts adapting to terminal width
|
||||
|
||||
**Error Handling:**
|
||||
|
||||
- Comprehensive validation for tag names (alphanumeric, hyphens, underscores)
|
||||
- Reserved name protection (master, main, default)
|
||||
- Graceful handling of missing tags and corrupted data
|
||||
- Detailed error messages with suggested corrections
|
||||
|
||||
This release establishes the foundation for advanced multi-context workflows while maintaining the simplicity and power that makes Task Master effective for individual developers.
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Research Save-to-File Feature & Critical MCP Tag Corruption Fix
|
||||
|
||||
**🔬 New Research Save-to-File Functionality:**
|
||||
|
||||
Added comprehensive save-to-file capability to the research command, enabling users to preserve research sessions for future reference and documentation.
|
||||
|
||||
**CLI Integration:**
|
||||
|
||||
- New `--save-file` flag for `task-master research` command
|
||||
- Consistent with existing `--save` and `--save-to` flags for intuitive usage
|
||||
- Interactive "Save to file" option in follow-up questions menu
|
||||
|
||||
**MCP Integration:**
|
||||
|
||||
- New `saveToFile` boolean parameter for the `research` MCP tool
|
||||
- Enables programmatic research saving for AI agents and integrated tools
|
||||
|
||||
**File Management:**
|
||||
|
||||
- Automatically creates `.taskmaster/docs/research/` directory structure
|
||||
- Generates timestamped, slugified filenames (e.g., `2025-01-13_what-is-typescript.md`)
|
||||
- Comprehensive Markdown format with metadata headers including query, timestamp, and context sources
|
||||
- Clean conversation history formatting without duplicate information
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - No longer automatically creates individual task files as they are not used by the applicatoin. You can still generate them anytime using the `generate` command.
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Enhanced get-task/show command to support comma-separated task IDs for efficient batch operations
|
||||
|
||||
**New Features:**
|
||||
|
||||
- **Multiple Task Retrieval**: Pass comma-separated IDs to get/show multiple tasks at once (e.g., `task-master show 1,3,5` or MCP `get_task` with `id: "1,3,5"`)
|
||||
- **Smart Display Logic**: Single ID shows detailed view, multiple IDs show compact summary table with interactive options
|
||||
- **Batch Action Menu**: Interactive menu for multiple tasks with copy-paste ready commands for common operations (mark as done/in-progress, expand all, view dependencies, etc.)
|
||||
- **MCP Array Response**: MCP tool returns structured array of task objects for efficient AI agent context gathering
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- **Faster Context Gathering**: AI agents can collect multiple tasks/subtasks in one call instead of iterating
|
||||
- **Improved Workflow**: Interactive batch operations reduce repetitive command execution
|
||||
- **Better UX**: Responsive layout adapts to terminal width, maintains consistency with existing UI patterns
|
||||
- **API Efficiency**: RESTful array responses in MCP format enable more sophisticated integrations
|
||||
|
||||
This enhancement maintains full backward compatibility while significantly improving efficiency for both human users and AI agents working with multiple tasks.
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Adds support for filtering tasks by multiple statuses at once using comma-separated statuses.
|
||||
|
||||
Example: `cancelled,deferred`
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Adds tag to CLI output so you know which tag you are performing operations on. Already supported in the MCP response.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#723](https://github.com/eyaltoledano/claude-task-master/pull/723) [`40a5238`](https://github.com/eyaltoledano/claude-task-master/commit/40a52385baf43a5ed97ce29bc5c4fb3fea766b70) Thanks [@joedanz](https://github.com/joedanz)! - Fix Cursor deeplink installation by providing copy-paste instructions for GitHub compatibility
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix critical bugs in task move functionality:
|
||||
|
||||
- **Fixed moving tasks to become subtasks of empty parents**: When moving a task to become a subtask of a parent that had no existing subtasks (e.g., task 89 → task 98.1), the operation would fail with validation errors.
|
||||
- **Fixed moving subtasks between parents**: Subtasks can now be properly moved between different parent tasks, including to parents that previously had no subtasks.
|
||||
- **Improved comma-separated batch moves**: Multiple tasks can now be moved simultaneously using comma-separated IDs (e.g., "88,90" → "92,93") with proper error handling and atomic operations.
|
||||
|
||||
These fixes enables proper task hierarchy reorganization for corner cases that were previously broken.
|
||||
|
||||
- [#695](https://github.com/eyaltoledano/claude-task-master/pull/695) [`1ece6f1`](https://github.com/eyaltoledano/claude-task-master/commit/1ece6f19048df6ae2a0b25cbfb84d2c0f430642c) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - improve findTasks algorithm for resolving tasks path
|
||||
|
||||
- [#695](https://github.com/eyaltoledano/claude-task-master/pull/695) [`ee0be04`](https://github.com/eyaltoledano/claude-task-master/commit/ee0be04302cc602246de5cd296291db69bc8b300) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix update tool on MCP giving `No valid tasks found`
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Adds ability to automatically create/switch tags to match the current git branch. The configuration to enable the git workflow and then use the auto switching is in config.json."
|
||||
|
||||
- [#699](https://github.com/eyaltoledano/claude-task-master/pull/699) [`27edbd8`](https://github.com/eyaltoledano/claude-task-master/commit/27edbd8f3fe5e2ac200b80e7f27f4c0e74a074d6) Thanks [@eyaltoledano](https://github.com/eyaltoledano)! - Enhanced add-task fuzzy search intelligence and improved user experience
|
||||
|
||||
**Smarter Task Discovery:**
|
||||
|
||||
- Remove hardcoded category system that always matched "Task management"
|
||||
- Eliminate arbitrary limits on fuzzy search results (5→25 high relevance, 3→10 medium relevance, 8→20 detailed tasks)
|
||||
- Improve semantic weighting in Fuse.js search (details=3, description=2, title=1.5) for better relevance
|
||||
- Generate context-driven task recommendations based on true semantic similarity
|
||||
|
||||
**Enhanced Terminal Experience:**
|
||||
|
||||
- Fix duplicate banner display issue that was "eating" terminal history (closes #553)
|
||||
- Remove console.clear() and redundant displayBanner() calls from UI functions
|
||||
- Preserve command history for better development workflow
|
||||
- Streamline banner display across all commands (list, next, show, set-status, clear-subtasks, dependency commands)
|
||||
|
||||
**Visual Improvements:**
|
||||
|
||||
- Replace emoji complexity indicators with clean filled circle characters (●) for professional appearance
|
||||
- Improve consistency and readability of task complexity display
|
||||
|
||||
**AI Provider Compatibility:**
|
||||
|
||||
- Change generateObject mode from 'tool' to 'auto' for better cross-provider compatibility
|
||||
- Add qwen3-235n-a22b:free model support (closes #687)
|
||||
- Add smart warnings for free OpenRouter models with limitations (rate limits, restricted context, no tool_use)
|
||||
|
||||
**Technical Improvements:**
|
||||
|
||||
- Enhanced context generation in add-task to rely on semantic similarity rather than rigid pattern matching
|
||||
- Improved dependency analysis and common pattern detection
|
||||
- Better handling of task relationships and relevance scoring
|
||||
- More intelligent task suggestion algorithms
|
||||
|
||||
The add-task system now provides truly relevant task context based on semantic understanding rather than arbitrary categories and limits, while maintaining a cleaner and more professional terminal experience.
|
||||
|
||||
- [#751](https://github.com/eyaltoledano/claude-task-master/pull/751) [`4901908`](https://github.com/eyaltoledano/claude-task-master/commit/4901908f5d1f5c39e82a23d650047074691deda4) Thanks [@zahorniak](https://github.com/zahorniak)! - Update o3 model price
|
||||
|
||||
- [#755](https://github.com/eyaltoledano/claude-task-master/pull/755) [`dc7a541`](https://github.com/eyaltoledano/claude-task-master/commit/dc7a5414c0364a87412192ac01ccc49cf7b68768) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fixes issue with expand CLI command "Complexity report not found"
|
||||
|
||||
- Closes #735
|
||||
- Closes #728
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix issue with generate command which was creating tasks in the legacy tasks location.
|
||||
|
||||
- [#771](https://github.com/eyaltoledano/claude-task-master/pull/771) [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Improves dependency management when moving tasks by updating subtask dependencies that reference sibling subtasks by their old parent-based ID
|
||||
|
||||
- [#699](https://github.com/eyaltoledano/claude-task-master/pull/699) [`2e55757`](https://github.com/eyaltoledano/claude-task-master/commit/2e55757b2698ba20b78f09ec0286951297510b8e) Thanks [@eyaltoledano](https://github.com/eyaltoledano)! - Add sync-readme command for a task export to GitHub README
|
||||
|
||||
Introduces a new `sync-readme` command that exports your task list to your project's README.md file.
|
||||
|
||||
**Features:**
|
||||
|
||||
- **Flexible filtering**: Supports `--status` filtering (e.g., pending, done) and `--with-subtasks` flag
|
||||
- **Smart content management**: Automatically replaces existing exports or appends to new READMEs
|
||||
- **Metadata display**: Shows export timestamp, subtask inclusion status, and filter settings
|
||||
|
||||
**Usage:**
|
||||
|
||||
- `task-master sync-readme` - Export tasks without subtasks
|
||||
- `task-master sync-readme --with-subtasks` - Include subtasks in export
|
||||
- `task-master sync-readme --status=pending` - Only export pending tasks
|
||||
- `task-master sync-readme --status=done --with-subtasks` - Export completed tasks with subtasks
|
||||
|
||||
Perfect for showcasing project progress on GitHub. Experimental. Open to feedback.
|
||||
|
||||
- Updated dependencies [[`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4), [`40a5238`](https://github.com/eyaltoledano/claude-task-master/commit/40a52385baf43a5ed97ce29bc5c4fb3fea766b70), [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4), [`1ece6f1`](https://github.com/eyaltoledano/claude-task-master/commit/1ece6f19048df6ae2a0b25cbfb84d2c0f430642c), [`ee0be04`](https://github.com/eyaltoledano/claude-task-master/commit/ee0be04302cc602246de5cd296291db69bc8b300), [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4), [`27edbd8`](https://github.com/eyaltoledano/claude-task-master/commit/27edbd8f3fe5e2ac200b80e7f27f4c0e74a074d6), [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4), [`4901908`](https://github.com/eyaltoledano/claude-task-master/commit/4901908f5d1f5c39e82a23d650047074691deda4), [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4), [`dc7a541`](https://github.com/eyaltoledano/claude-task-master/commit/dc7a5414c0364a87412192ac01ccc49cf7b68768), [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4), [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4), [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4), [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4), [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4), [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4), [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4), [`2e55757`](https://github.com/eyaltoledano/claude-task-master/commit/2e55757b2698ba20b78f09ec0286951297510b8e), [`7250241`](https://github.com/eyaltoledano/claude-task-master/commit/72502416c6969055e0d139e408e726e03371c4f4)]:
|
||||
- task-master-ai@0.17.0-rc.1
|
||||
|
||||
## 0.16.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#695](https://github.com/eyaltoledano/claude-task-master/pull/695) [`1ece6f1`](https://github.com/eyaltoledano/claude-task-master/commit/1ece6f19048df6ae2a0b25cbfb84d2c0f430642c) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - improve findTasks algorithm for resolving tasks path
|
||||
|
||||
- [#695](https://github.com/eyaltoledano/claude-task-master/pull/695) [`ee0be04`](https://github.com/eyaltoledano/claude-task-master/commit/ee0be04302cc602246de5cd296291db69bc8b300) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix update tool on MCP giving `No valid tasks found`
|
||||
|
||||
- [#699](https://github.com/eyaltoledano/claude-task-master/pull/699) [`27edbd8`](https://github.com/eyaltoledano/claude-task-master/commit/27edbd8f3fe5e2ac200b80e7f27f4c0e74a074d6) Thanks [@eyaltoledano](https://github.com/eyaltoledano)! - Enhanced add-task fuzzy search intelligence and improved user experience
|
||||
|
||||
**Smarter Task Discovery:**
|
||||
|
||||
- Remove hardcoded category system that always matched "Task management"
|
||||
- Eliminate arbitrary limits on fuzzy search results (5→25 high relevance, 3→10 medium relevance, 8→20 detailed tasks)
|
||||
- Improve semantic weighting in Fuse.js search (details=3, description=2, title=1.5) for better relevance
|
||||
- Generate context-driven task recommendations based on true semantic similarity
|
||||
|
||||
**Enhanced Terminal Experience:**
|
||||
|
||||
- Fix duplicate banner display issue that was "eating" terminal history (closes #553)
|
||||
- Remove console.clear() and redundant displayBanner() calls from UI functions
|
||||
- Preserve command history for better development workflow
|
||||
- Streamline banner display across all commands (list, next, show, set-status, clear-subtasks, dependency commands)
|
||||
|
||||
**Visual Improvements:**
|
||||
|
||||
- Replace emoji complexity indicators with clean filled circle characters (●) for professional appearance
|
||||
- Improve consistency and readability of task complexity display
|
||||
|
||||
**AI Provider Compatibility:**
|
||||
|
||||
- Change generateObject mode from 'tool' to 'auto' for better cross-provider compatibility
|
||||
- Add qwen3-235n-a22b:free model support (closes #687)
|
||||
- Add smart warnings for free OpenRouter models with limitations (rate limits, restricted context, no tool_use)
|
||||
|
||||
**Technical Improvements:**
|
||||
|
||||
- Enhanced context generation in add-task to rely on semantic similarity rather than rigid pattern matching
|
||||
- Improved dependency analysis and common pattern detection
|
||||
- Better handling of task relationships and relevance scoring
|
||||
- More intelligent task suggestion algorithms
|
||||
|
||||
The add-task system now provides truly relevant task context based on semantic understanding rather than arbitrary categories and limits, while maintaining a cleaner and more professional terminal experience.
|
||||
|
||||
- [#655](https://github.com/eyaltoledano/claude-task-master/pull/655) [`edaa5fe`](https://github.com/eyaltoledano/claude-task-master/commit/edaa5fe0d56e0e4e7c4370670a7a388eebd922ac) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix double .taskmaster directory paths in file resolution utilities
|
||||
|
||||
- Closes #636
|
||||
|
||||
- [#671](https://github.com/eyaltoledano/claude-task-master/pull/671) [`86ea6d1`](https://github.com/eyaltoledano/claude-task-master/commit/86ea6d1dbc03eeb39f524f565b50b7017b1d2c9c) Thanks [@joedanz](https://github.com/joedanz)! - Add one-click MCP server installation for Cursor
|
||||
|
||||
- [#699](https://github.com/eyaltoledano/claude-task-master/pull/699) [`2e55757`](https://github.com/eyaltoledano/claude-task-master/commit/2e55757b2698ba20b78f09ec0286951297510b8e) Thanks [@eyaltoledano](https://github.com/eyaltoledano)! - Add sync-readme command for a task export to GitHub README
|
||||
|
||||
Introduces a new `sync-readme` command that exports your task list to your project's README.md file.
|
||||
|
||||
**Features:**
|
||||
|
||||
- **Flexible filtering**: Supports `--status` filtering (e.g., pending, done) and `--with-subtasks` flag
|
||||
- **Smart content management**: Automatically replaces existing exports or appends to new READMEs
|
||||
- **Metadata display**: Shows export timestamp, subtask inclusion status, and filter settings
|
||||
|
||||
**Usage:**
|
||||
|
||||
- `task-master sync-readme` - Export tasks without subtasks
|
||||
- `task-master sync-readme --with-subtasks` - Include subtasks in export
|
||||
- `task-master sync-readme --status=pending` - Only export pending tasks
|
||||
- `task-master sync-readme --status=done --with-subtasks` - Export completed tasks with subtasks
|
||||
|
||||
Perfect for showcasing project progress on GitHub. Experimental. Open to feedback.
|
||||
|
||||
## 0.16.2-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -6,5 +6,4 @@ GOOGLE_API_KEY="your_google_api_key_here" # Optional, for Google Gem
|
||||
MISTRAL_API_KEY="your_mistral_key_here" # Optional, for Mistral AI models.
|
||||
XAI_API_KEY="YOUR_XAI_KEY_HERE" # Optional, for xAI AI models.
|
||||
AZURE_OPENAI_API_KEY="your_azure_key_here" # Optional, for Azure OpenAI models (requires endpoint in .taskmaster/config.json).
|
||||
OLLAMA_API_KEY="your_ollama_api_key_here" # Optional: For remote Ollama servers that require authentication.
|
||||
GITHUB_API_KEY="your_github_api_key_here" # Optional: For GitHub import/export features. Format: ghp_... or github_pat_...
|
||||
OLLAMA_API_KEY="your_ollama_api_key_here" # Optional: For remote Ollama servers that require authentication.
|
||||
@@ -8,6 +8,8 @@ Taskmaster uses two primary methods for configuration:
|
||||
- This JSON file stores most configuration settings, including AI model selections, parameters, logging levels, and project defaults.
|
||||
- **Location:** This file is created in the `.taskmaster/` directory when you run the `task-master models --setup` interactive setup or initialize a new project with `task-master init`.
|
||||
- **Migration:** Existing projects with `.taskmasterconfig` in the root will continue to work, but should be migrated to the new structure using `task-master migrate`.
|
||||
- **Location:** This file is created in the `.taskmaster/` directory when you run the `task-master models --setup` interactive setup or initialize a new project with `task-master init`.
|
||||
- **Migration:** Existing projects with `.taskmasterconfig` in the root will continue to work, but should be migrated to the new structure using `task-master migrate`.
|
||||
- **Management:** Use the `task-master models --setup` command (or `models` MCP tool) to interactively create and manage this file. You can also set specific models directly using `task-master models --set-<role>=<model_id>`, adding `--ollama` or `--openrouter` flags for custom models. Manual editing is possible but not recommended unless you understand the structure.
|
||||
- **Example Structure:**
|
||||
```json
|
||||
@@ -58,6 +60,35 @@ Taskmaster uses two primary methods for configuration:
|
||||
|
||||
## Environment Variables (`.env` file or MCP `env` block - For API Keys Only)
|
||||
|
||||
- Used **exclusively** for sensitive API keys and specific endpoint URLs.
|
||||
- **Location:**
|
||||
- For CLI usage: Create a `.env` file in your project root.
|
||||
- For MCP/Cursor usage: Configure keys in the `env` section of your `.cursor/mcp.json` file.
|
||||
- **Required API Keys (Depending on configured providers):**
|
||||
- `ANTHROPIC_API_KEY`: Your Anthropic API key.
|
||||
- `PERPLEXITY_API_KEY`: Your Perplexity API key.
|
||||
- `OPENAI_API_KEY`: Your OpenAI API key.
|
||||
- `GOOGLE_API_KEY`: Your Google API key (also used for Vertex AI provider).
|
||||
- `MISTRAL_API_KEY`: Your Mistral API key.
|
||||
- `AZURE_OPENAI_API_KEY`: Your Azure OpenAI API key (also requires `AZURE_OPENAI_ENDPOINT`).
|
||||
- `OPENROUTER_API_KEY`: Your OpenRouter API key.
|
||||
- `XAI_API_KEY`: Your X-AI API key.
|
||||
- **Optional Endpoint Overrides:**
|
||||
- **Per-role `baseURL` in `.taskmasterconfig`:** You can add a `baseURL` property to any model role (`main`, `research`, `fallback`) to override the default API endpoint for that provider. If omitted, the provider's standard endpoint is used.
|
||||
- `AZURE_OPENAI_ENDPOINT`: Required if using Azure OpenAI key (can also be set as `baseURL` for the Azure model role).
|
||||
- `OLLAMA_BASE_URL`: Override the default Ollama API URL (Default: `http://localhost:11434/api`).
|
||||
- `VERTEX_PROJECT_ID`: Your Google Cloud project ID for Vertex AI. Required when using the 'vertex' provider.
|
||||
- `VERTEX_LOCATION`: Google Cloud region for Vertex AI (e.g., 'us-central1'). Default is 'us-central1'.
|
||||
- `GOOGLE_APPLICATION_CREDENTIALS`: Path to service account credentials JSON file for Google Cloud auth (alternative to API key for Vertex AI).
|
||||
2. **Legacy `.taskmasterconfig` File (Backward Compatibility)**
|
||||
|
||||
- For projects that haven't migrated to the new structure yet.
|
||||
- **Location:** Project root directory.
|
||||
- **Migration:** Use `task-master migrate` to move this to `.taskmaster/config.json`.
|
||||
- **Deprecation:** While still supported, you'll see warnings encouraging migration to the new structure.
|
||||
|
||||
## Environment Variables (`.env` file or MCP `env` block - For API Keys Only)
|
||||
|
||||
- Used **exclusively** for sensitive API keys and specific endpoint URLs.
|
||||
- **Location:**
|
||||
- For CLI usage: Create a `.env` file in your project root.
|
||||
@@ -145,6 +176,9 @@ PERPLEXITY_API_KEY=pplx-your-key-here
|
||||
|
||||
### Configuration Errors
|
||||
|
||||
- If Task Master reports errors about missing configuration or cannot find the config file, run `task-master models --setup` in your project root to create or repair the file.
|
||||
- For new projects, config will be created at `.taskmaster/config.json`. For legacy projects, you may want to use `task-master migrate` to move to the new structure.
|
||||
- Ensure API keys are correctly placed in your `.env` file (for CLI) or `.cursor/mcp.json` (for MCP) and are valid for the providers selected in your config file.
|
||||
- If Task Master reports errors about missing configuration or cannot find the config file, run `task-master models --setup` in your project root to create or repair the file.
|
||||
- For new projects, config will be created at `.taskmaster/config.json`. For legacy projects, you may want to use `task-master migrate` to move to the new structure.
|
||||
- Ensure API keys are correctly placed in your `.env` file (for CLI) or `.cursor/mcp.json` (for MCP) and are valid for the providers selected in your config file.
|
||||
|
||||
@@ -43,6 +43,7 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage }
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -54,6 +55,7 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'INVALID_SUBTASK_ID', message: errorMessage }
|
||||
error: { code: 'INVALID_SUBTASK_ID', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -64,6 +66,7 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_PROMPT', message: errorMessage }
|
||||
error: { code: 'MISSING_PROMPT', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -75,6 +78,7 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'INVALID_SUBTASK_ID_TYPE', message: errorMessage }
|
||||
error: { code: 'INVALID_SUBTASK_ID_TYPE', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -85,6 +89,7 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'INVALID_SUBTASK_ID_FORMAT', message: errorMessage }
|
||||
error: { code: 'INVALID_SUBTASK_ID_FORMAT', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -124,6 +129,7 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'SUBTASK_NOT_FOUND', message: message }
|
||||
error: { code: 'SUBTASK_NOT_FOUND', message: message }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -151,6 +157,7 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
code: 'UPDATE_SUBTASK_CORE_ERROR',
|
||||
message: error.message || 'Unknown error updating subtask'
|
||||
}
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
if (!wasSilent && isSilentMode()) {
|
||||
@@ -168,6 +175,7 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
code: 'DIRECT_FUNCTION_SETUP_ERROR',
|
||||
message: error.message || 'Unknown setup error'
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
/**
|
||||
* tools/next-task.js
|
||||
* Tool to find the next task to work on based on dependencies and status
|
||||
* Tool to find the next task to work on based on dependencies and status
|
||||
*/
|
||||
|
||||
import { z } from 'zod';
|
||||
import {
|
||||
createErrorResponse,
|
||||
handleApiResult,
|
||||
handleApiResult,
|
||||
withNormalizedProjectRoot
|
||||
} from './utils.js';
|
||||
import { nextTaskDirect } from '../core/task-master-core.js';
|
||||
import {
|
||||
resolveTasksPath,
|
||||
resolveComplexityReportPath
|
||||
findTasksPath,
|
||||
findComplexityReportPath
|
||||
} from '../core/utils/path-utils.js';
|
||||
|
||||
/**
|
||||
* Register the nextTask tool with the MCP server
|
||||
* Register the nextTask tool with the MCP server
|
||||
* @param {Object} server - FastMCP server instance
|
||||
*/
|
||||
@@ -40,10 +43,13 @@ export function registerNextTaskTool(server) {
|
||||
try {
|
||||
log.info(`Finding next task with args: ${JSON.stringify(args)}`);
|
||||
|
||||
// Resolve the path to tasks.json using new path utilities
|
||||
// Resolve the path to tasks.json
|
||||
let tasksJsonPath;
|
||||
try {
|
||||
tasksJsonPath = resolveTasksPath(args, session);
|
||||
tasksJsonPath = findTasksPath(
|
||||
{ projectRoot: args.projectRoot, file: args.file },
|
||||
log
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(`Error finding tasks.json: ${error.message}`);
|
||||
return createErrorResponse(
|
||||
@@ -51,16 +57,26 @@ export function registerNextTaskTool(server) {
|
||||
);
|
||||
}
|
||||
|
||||
// Resolve the path to complexity report (optional)
|
||||
// Resolve the path to complexity report (optional)
|
||||
let complexityReportPath;
|
||||
try {
|
||||
complexityReportPath = resolveComplexityReportPath(args, session);
|
||||
complexityReportPath = findComplexityReportPath(
|
||||
{
|
||||
projectRoot: args.projectRoot,
|
||||
complexityReport: args.complexityReport
|
||||
},
|
||||
log
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(`Error finding complexity report: ${error.message}`);
|
||||
// This is optional, so we don't fail the operation
|
||||
complexityReportPath = null;
|
||||
// This is optional, so we don't fail the operation
|
||||
complexityReportPath = null;
|
||||
}
|
||||
|
||||
|
||||
const result = await nextTaskDirect(
|
||||
{
|
||||
tasksJsonPath: tasksJsonPath,
|
||||
@@ -80,6 +96,7 @@ export function registerNextTaskTool(server) {
|
||||
args.projectRoot
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(`Error finding next task: ${error.message}`);
|
||||
log.error(`Error finding next task: ${error.message}`);
|
||||
return createErrorResponse(error.message);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
handleApiResult,
|
||||
withNormalizedProjectRoot,
|
||||
createErrorResponse
|
||||
withNormalizedProjectRoot,
|
||||
createErrorResponse
|
||||
} from './utils.js';
|
||||
import { parsePRDDirect } from '../core/task-master-core.js';
|
||||
import {
|
||||
@@ -15,6 +17,11 @@ import {
|
||||
TASKMASTER_DOCS_DIR,
|
||||
TASKMASTER_TASKS_FILE
|
||||
} from '../../../src/constants/paths.js';
|
||||
import {
|
||||
PRD_FILE,
|
||||
TASKMASTER_DOCS_DIR,
|
||||
TASKMASTER_TASKS_FILE
|
||||
} from '../../../src/constants/paths.js';
|
||||
|
||||
/**
|
||||
* Register the parse_prd tool
|
||||
@@ -24,11 +31,13 @@ export function registerParsePRDTool(server) {
|
||||
server.addTool({
|
||||
name: 'parse_prd',
|
||||
description: `Parse a Product Requirements Document (PRD) text file to automatically generate initial tasks. Reinitializing the project is not necessary to run this tool. It is recommended to run parse-prd after initializing the project and creating/importing a prd.txt file in the project root's ${TASKMASTER_DOCS_DIR} directory.`,
|
||||
description: `Parse a Product Requirements Document (PRD) text file to automatically generate initial tasks. Reinitializing the project is not necessary to run this tool. It is recommended to run parse-prd after initializing the project and creating/importing a prd.txt file in the project root's ${TASKMASTER_DOCS_DIR} directory.`,
|
||||
parameters: z.object({
|
||||
input: z
|
||||
.string()
|
||||
.optional()
|
||||
.default(PRD_FILE)
|
||||
.default(PRD_FILE)
|
||||
.describe('Absolute path to the PRD document file (.txt, .md, etc.)'),
|
||||
projectRoot: z
|
||||
.string()
|
||||
@@ -39,6 +48,15 @@ export function registerParsePRDTool(server) {
|
||||
.describe(
|
||||
`Output path for tasks.json file (default: ${TASKMASTER_TASKS_FILE})`
|
||||
),
|
||||
projectRoot: z
|
||||
.string()
|
||||
.describe('The directory of the project. Must be an absolute path.'),
|
||||
output: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
`Output path for tasks.json file (default: ${TASKMASTER_TASKS_FILE})`
|
||||
),
|
||||
numTasks: z
|
||||
.string()
|
||||
.optional()
|
||||
@@ -55,11 +73,16 @@ export function registerParsePRDTool(server) {
|
||||
.optional()
|
||||
.describe(
|
||||
'Enable Taskmaster to use the research role for potentially more informed task generation. Requires appropriate API key.'
|
||||
'Enable Taskmaster to use the research role for potentially more informed task generation. Requires appropriate API key.'
|
||||
),
|
||||
append: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe('Append generated tasks to existing file.')
|
||||
append: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe('Append generated tasks to existing file.')
|
||||
}),
|
||||
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
|
||||
try {
|
||||
@@ -74,6 +97,8 @@ export function registerParsePRDTool(server) {
|
||||
} catch (error) {
|
||||
log.error(`Error in parse_prd: ${error.message}`);
|
||||
return createErrorResponse(`Failed to parse PRD: ${error.message}`);
|
||||
log.error(`Error in parse_prd: ${error.message}`);
|
||||
return createErrorResponse(`Failed to parse PRD: ${error.message}`);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -304,6 +304,7 @@ function getProjectRootFromSession(session, log) {
|
||||
* @param {string} [projectRoot] - Optional project root for tag information
|
||||
* @returns {Object} - Standardized MCP response object
|
||||
*/
|
||||
async function handleApiResult(
|
||||
async function handleApiResult(
|
||||
result,
|
||||
log,
|
||||
@@ -329,11 +330,14 @@ async function handleApiResult(
|
||||
: result.data;
|
||||
|
||||
log.info('Successfully completed operation');
|
||||
log.info('Successfully completed operation');
|
||||
|
||||
// Create the response payload including version info and tag info
|
||||
const responsePayload = {
|
||||
data: processedData,
|
||||
version: versionInfo
|
||||
data: processedData,
|
||||
version: versionInfo
|
||||
};
|
||||
|
||||
// Add tag information if available
|
||||
@@ -436,6 +440,8 @@ function executeTaskMasterCommand(
|
||||
* @param {Object} options.log - The logger instance.
|
||||
* @returns {Promise<Object>} - An object containing the result.
|
||||
* Format: { success: boolean, data?: any, error?: { code: string, message: string } }
|
||||
* @returns {Promise<Object>} - An object containing the result.
|
||||
* Format: { success: boolean, data?: any, error?: { code: string, message: string } }
|
||||
*/
|
||||
async function getCachedOrExecute({ cacheKey, actionFn, log }) {
|
||||
// Check cache first
|
||||
@@ -444,6 +450,7 @@ async function getCachedOrExecute({ cacheKey, actionFn, log }) {
|
||||
if (cachedResult !== undefined) {
|
||||
log.info(`Cache hit for key: ${cacheKey}`);
|
||||
return cachedResult;
|
||||
return cachedResult;
|
||||
}
|
||||
|
||||
log.info(`Cache miss for key: ${cacheKey}. Executing action function.`);
|
||||
@@ -451,10 +458,12 @@ async function getCachedOrExecute({ cacheKey, actionFn, log }) {
|
||||
// Execute the action function if cache missed
|
||||
const result = await actionFn();
|
||||
|
||||
// If the action was successful, cache the result
|
||||
// If the action was successful, cache the result
|
||||
if (result.success && result.data !== undefined) {
|
||||
log.info(`Action successful. Caching result for key: ${cacheKey}`);
|
||||
contextManager.setCachedData(cacheKey, result);
|
||||
contextManager.setCachedData(cacheKey, result);
|
||||
} else if (!result.success) {
|
||||
log.warn(
|
||||
`Action failed for cache key ${cacheKey}. Result not cached. Error: ${result.error?.message}`
|
||||
@@ -466,6 +475,7 @@ async function getCachedOrExecute({ cacheKey, actionFn, log }) {
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
24211
package-lock.json
generated
24211
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "task-master-ai",
|
||||
"version": "0.17.0-rc.1",
|
||||
"version": "0.16.2-rc.0",
|
||||
"description": "A task management system for ambitious AI-driven development that doesn't overwhelm and confuse Cursor.",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
@@ -72,7 +72,7 @@
|
||||
"ollama-ai-provider": "^1.2.0",
|
||||
"openai": "^4.89.0",
|
||||
"ora": "^8.2.0",
|
||||
"task-master-ai": "0.17.0-rc.1",
|
||||
"task-master-ai": "0.16.2",
|
||||
"uuid": "^11.1.0",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
|
||||
@@ -42,6 +42,8 @@ import {
|
||||
taskExists,
|
||||
moveTask,
|
||||
migrateProject
|
||||
moveTask,
|
||||
migrateProject
|
||||
} from './task-manager.js';
|
||||
|
||||
import {
|
||||
@@ -111,6 +113,8 @@ import {
|
||||
import { getTaskMasterVersion } from '../../src/utils/getVersion.js';
|
||||
import { syncTasksToReadme } from './sync-readme.js';
|
||||
|
||||
import { syncTasksToReadme } from './sync-readme.js';
|
||||
|
||||
/**
|
||||
* Runs the interactive setup process for model configuration.
|
||||
* @param {string|null} projectRoot - The resolved project root directory.
|
||||
@@ -327,6 +331,7 @@ async function runInteractiveSetup(projectRoot) {
|
||||
commonPrefix.push(customOllamaOption);
|
||||
commonPrefix.push(customBedrockOption);
|
||||
|
||||
const prefixLength = commonPrefix.length; // Initial prefix length
|
||||
const prefixLength = commonPrefix.length; // Initial prefix length
|
||||
|
||||
if (allowNone) {
|
||||
@@ -521,6 +526,7 @@ async function runInteractiveSetup(projectRoot) {
|
||||
console.error(
|
||||
chalk.red(
|
||||
'Error: AWS_ACCESS_KEY_ID and/or AWS_SECRET_ACCESS_KEY environment variables are missing. Please set them before using custom Bedrock models.'
|
||||
'Error: AWS_ACCESS_KEY_ID and/or AWS_SECRET_ACCESS_KEY environment variables are missing. Please set them before using custom Bedrock models.'
|
||||
)
|
||||
);
|
||||
setupSuccess = false;
|
||||
@@ -679,6 +685,7 @@ function registerCommands(programInstance) {
|
||||
'Path to the PRD file (alternative to positional argument)'
|
||||
)
|
||||
.option('-o, --output <file>', 'Output file path', TASKMASTER_TASKS_FILE)
|
||||
.option('-o, --output <file>', 'Output file path', TASKMASTER_TASKS_FILE)
|
||||
.option('-n, --num-tasks <number>', 'Number of tasks to generate', '10')
|
||||
.option('-f, --force', 'Skip confirmation when overwriting existing tasks')
|
||||
.option(
|
||||
@@ -694,6 +701,7 @@ function registerCommands(programInstance) {
|
||||
// Use input option if file argument not provided
|
||||
const inputFile = file || options.input;
|
||||
const defaultPrdPath = PRD_FILE;
|
||||
const defaultPrdPath = PRD_FILE;
|
||||
const numTasks = parseInt(options.numTasks, 10);
|
||||
const outputPath = options.output;
|
||||
const force = options.force || false;
|
||||
@@ -778,10 +786,12 @@ function registerCommands(programInstance) {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
`No PRD file specified and default PRD file not found at ${PRD_FILE}.`
|
||||
`No PRD file specified and default PRD file not found at ${PRD_FILE}.`
|
||||
)
|
||||
);
|
||||
console.log(
|
||||
boxen(
|
||||
`${chalk.white.bold('Parse PRD Help')}\n\n${chalk.cyan('Usage:')}\n task-master parse-prd <prd-file.txt> [options]\n\n${chalk.cyan('Options:')}\n -i, --input <file> Path to the PRD file (alternative to positional argument)\n -o, --output <file> Output file path (default: "${TASKMASTER_TASKS_FILE}")\n -n, --num-tasks <number> Number of tasks to generate (default: 10)\n -f, --force Skip confirmation when overwriting existing tasks\n --append Append new tasks to existing tasks.json instead of overwriting\n -r, --research Use Perplexity AI for research-backed task generation\n\n${chalk.cyan('Example:')}\n task-master parse-prd requirements.txt --num-tasks 15\n task-master parse-prd --input=requirements.txt\n task-master parse-prd --force\n task-master parse-prd requirements_v2.txt --append\n task-master parse-prd requirements.txt --research\n\n${chalk.yellow('Note: This command will:')}\n 1. Look for a PRD file at ${PRD_FILE} by default\n 2. Use the file specified by --input or positional argument if provided\n 3. Generate tasks from the PRD and either:\n - Overwrite any existing tasks.json file (default)\n - Append to existing tasks.json if --append is used`,
|
||||
`${chalk.white.bold('Parse PRD Help')}\n\n${chalk.cyan('Usage:')}\n task-master parse-prd <prd-file.txt> [options]\n\n${chalk.cyan('Options:')}\n -i, --input <file> Path to the PRD file (alternative to positional argument)\n -o, --output <file> Output file path (default: "${TASKMASTER_TASKS_FILE}")\n -n, --num-tasks <number> Number of tasks to generate (default: 10)\n -f, --force Skip confirmation when overwriting existing tasks\n --append Append new tasks to existing tasks.json instead of overwriting\n -r, --research Use Perplexity AI for research-backed task generation\n\n${chalk.cyan('Example:')}\n task-master parse-prd requirements.txt --num-tasks 15\n task-master parse-prd --input=requirements.txt\n task-master parse-prd --force\n task-master parse-prd requirements_v2.txt --append\n task-master parse-prd requirements.txt --research\n\n${chalk.yellow('Note: This command will:')}\n 1. Look for a PRD file at ${PRD_FILE} by default\n 2. Use the file specified by --input or positional argument if provided\n 3. Generate tasks from the PRD and either:\n - Overwrite any existing tasks.json file (default)\n - Append to existing tasks.json if --append is used`,
|
||||
{ padding: 1, borderColor: 'blue', borderStyle: 'round' }
|
||||
)
|
||||
@@ -841,6 +851,11 @@ function registerCommands(programInstance) {
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-f, --file <file>',
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'--from <id>',
|
||||
'Task ID to start updating from (tasks with ID >= this value will be updated)',
|
||||
@@ -856,6 +871,7 @@ function registerCommands(programInstance) {
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const fromId = parseInt(options.from, 10); // Validation happens here
|
||||
const prompt = options.prompt;
|
||||
@@ -939,6 +955,11 @@ function registerCommands(programInstance) {
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-f, --file <file>',
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option('-i, --id <id>', 'Task ID to update (required)')
|
||||
.option(
|
||||
'-p, --prompt <text>',
|
||||
@@ -982,6 +1003,7 @@ function registerCommands(programInstance) {
|
||||
|
||||
// Parse the task ID and validate it's a number
|
||||
const taskId = parseInt(options.id, 10);
|
||||
if (Number.isNaN(taskId) || taskId <= 0) {
|
||||
if (Number.isNaN(taskId) || taskId <= 0) {
|
||||
console.error(
|
||||
chalk.red(
|
||||
@@ -1018,6 +1040,7 @@ function registerCommands(programInstance) {
|
||||
console.error(
|
||||
chalk.red(`Error: Tasks file not found at path: ${tasksPath}`)
|
||||
);
|
||||
if (tasksPath === TASKMASTER_TASKS_FILE) {
|
||||
if (tasksPath === TASKMASTER_TASKS_FILE) {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
@@ -1116,6 +1139,11 @@ function registerCommands(programInstance) {
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-f, --file <file>',
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-i, --id <id>',
|
||||
'Subtask ID to update in format "parentId.subtaskId" (required)'
|
||||
@@ -1191,6 +1219,7 @@ function registerCommands(programInstance) {
|
||||
console.error(
|
||||
chalk.red(`Error: Tasks file not found at path: ${tasksPath}`)
|
||||
);
|
||||
if (tasksPath === TASKMASTER_TASKS_FILE) {
|
||||
if (tasksPath === TASKMASTER_TASKS_FILE) {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
@@ -1295,6 +1324,7 @@ function registerCommands(programInstance) {
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const outputDir = options.output;
|
||||
const tag = options.tag;
|
||||
@@ -1332,6 +1362,7 @@ function registerCommands(programInstance) {
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const taskId = options.id;
|
||||
const status = options.status;
|
||||
@@ -1379,10 +1410,16 @@ function registerCommands(programInstance) {
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-f, --file <file>',
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-r, --report <report>',
|
||||
'Path to the complexity report file',
|
||||
COMPLEXITY_REPORT_FILE
|
||||
COMPLEXITY_REPORT_FILE
|
||||
)
|
||||
.option('-s, --status <status>', 'Filter by status')
|
||||
.option('--with-subtasks', 'Show subtasks for each task')
|
||||
@@ -1446,6 +1483,7 @@ function registerCommands(programInstance) {
|
||||
'--file <file>',
|
||||
'Path to the tasks file (relative to project root)',
|
||||
TASKMASTER_TASKS_FILE // Allow file override
|
||||
TASKMASTER_TASKS_FILE // Allow file override
|
||||
) // Allow file override
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
@@ -1526,6 +1564,7 @@ function registerCommands(programInstance) {
|
||||
'-o, --output <file>',
|
||||
'Output file path for the report',
|
||||
COMPLEXITY_REPORT_FILE
|
||||
COMPLEXITY_REPORT_FILE
|
||||
)
|
||||
.option(
|
||||
'-m, --model <model>',
|
||||
@@ -1541,6 +1580,11 @@ function registerCommands(programInstance) {
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-f, --file <file>',
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-r, --research',
|
||||
'Use Perplexity AI for research-backed complexity analysis'
|
||||
@@ -1969,6 +2013,11 @@ ${result.result}
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-f, --file <file>',
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-i, --id <ids>',
|
||||
'Task IDs (comma-separated) to clear subtasks from'
|
||||
@@ -1976,6 +2025,7 @@ ${result.result}
|
||||
.option('--all', 'Clear subtasks from all tasks')
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const taskIds = options.id;
|
||||
const all = options.all;
|
||||
@@ -2022,6 +2072,11 @@ ${result.result}
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-f, --file <file>',
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-p, --prompt <prompt>',
|
||||
'Description of the task to add (required if not using manual fields)'
|
||||
@@ -2064,6 +2119,14 @@ ${result.result}
|
||||
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
|
||||
if (!fs.existsSync(tasksPath)) {
|
||||
console.error(
|
||||
`❌ No tasks.json file found. Please run "task-master init" or create a tasks.json file at ${TASKMASTER_TASKS_FILE}`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
|
||||
if (!fs.existsSync(tasksPath)) {
|
||||
console.error(
|
||||
`❌ No tasks.json file found. Please run "task-master init" or create a tasks.json file at ${TASKMASTER_TASKS_FILE}`
|
||||
@@ -2156,13 +2219,20 @@ ${result.result}
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-f, --file <file>',
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-r, --report <report>',
|
||||
'Path to the complexity report file',
|
||||
COMPLEXITY_REPORT_FILE
|
||||
COMPLEXITY_REPORT_FILE
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const reportPath = options.report;
|
||||
const tag = options.tag;
|
||||
@@ -2200,6 +2270,7 @@ ${result.result}
|
||||
'-r, --report <report>',
|
||||
'Path to the complexity report file',
|
||||
COMPLEXITY_REPORT_FILE
|
||||
COMPLEXITY_REPORT_FILE
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (taskId, options) => {
|
||||
@@ -2221,6 +2292,7 @@ ${result.result}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const reportPath = options.report;
|
||||
|
||||
@@ -2265,6 +2337,7 @@ ${result.result}
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const taskId = options.id;
|
||||
const dependencyId = options.dependsOn;
|
||||
@@ -2316,6 +2389,7 @@ ${result.result}
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const taskId = options.id;
|
||||
const dependencyId = options.dependsOn;
|
||||
@@ -2425,6 +2499,7 @@ ${result.result}
|
||||
'-f, --file <file>',
|
||||
'Path to the report file',
|
||||
COMPLEXITY_REPORT_FILE
|
||||
COMPLEXITY_REPORT_FILE
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
@@ -2458,6 +2533,11 @@ ${result.result}
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-f, --file <file>',
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option('-p, --parent <id>', 'Parent task ID (required)')
|
||||
.option('-i, --task-id <id>', 'Existing task ID to convert to subtask')
|
||||
.option(
|
||||
@@ -2633,6 +2713,7 @@ ${result.result}
|
||||
function showAddSubtaskHelp() {
|
||||
console.log(
|
||||
boxen(
|
||||
`${chalk.white.bold('Add Subtask Command Help')}\n\n${chalk.cyan('Usage:')}\n task-master add-subtask --parent=<id> [options]\n\n${chalk.cyan('Options:')}\n -p, --parent <id> Parent task ID (required)\n -i, --task-id <id> Existing task ID to convert to subtask\n -t, --title <title> Title for the new subtask\n -d, --description <text> Description for the new subtask\n --details <text> Implementation details for the new subtask\n --dependencies <ids> Comma-separated list of dependency IDs\n -s, --status <status> Status for the new subtask (default: "pending")\n -f, --file <file> Path to the tasks file (default: "${TASKMASTER_TASKS_FILE}")\n --skip-generate Skip regenerating task files\n\n${chalk.cyan('Examples:')}\n task-master add-subtask --parent=5 --task-id=8\n task-master add-subtask -p 5 -t "Implement login UI" -d "Create the login form"`,
|
||||
`${chalk.white.bold('Add Subtask Command Help')}\n\n${chalk.cyan('Usage:')}\n task-master add-subtask --parent=<id> [options]\n\n${chalk.cyan('Options:')}\n -p, --parent <id> Parent task ID (required)\n -i, --task-id <id> Existing task ID to convert to subtask\n -t, --title <title> Title for the new subtask\n -d, --description <text> Description for the new subtask\n --details <text> Implementation details for the new subtask\n --dependencies <ids> Comma-separated list of dependency IDs\n -s, --status <status> Status for the new subtask (default: "pending")\n -f, --file <file> Path to the tasks file (default: "${TASKMASTER_TASKS_FILE}")\n --skip-generate Skip regenerating task files\n\n${chalk.cyan('Examples:')}\n task-master add-subtask --parent=5 --task-id=8\n task-master add-subtask -p 5 -t "Implement login UI" -d "Create the login form"`,
|
||||
{ padding: 1, borderColor: 'blue', borderStyle: 'round' }
|
||||
)
|
||||
@@ -2648,6 +2729,11 @@ ${result.result}
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-f, --file <file>',
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-i, --id <id>',
|
||||
'Subtask ID(s) to remove in format "parentId.subtaskId" (can be comma-separated for multiple subtasks)'
|
||||
@@ -2659,6 +2745,7 @@ ${result.result}
|
||||
.option('--skip-generate', 'Skip regenerating task files')
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const subtaskIds = options.id;
|
||||
const convertToTask = options.convert || false;
|
||||
@@ -2790,6 +2877,9 @@ ${result.result}
|
||||
' -f, --file <file> Path to the tasks file (default: "' +
|
||||
TASKMASTER_TASKS_FILE +
|
||||
'")\n' +
|
||||
' -f, --file <file> Path to the tasks file (default: "' +
|
||||
TASKMASTER_TASKS_FILE +
|
||||
'")\n' +
|
||||
' --skip-generate Skip regenerating task files\n\n' +
|
||||
chalk.cyan('Examples:') +
|
||||
'\n' +
|
||||
@@ -2959,9 +3049,15 @@ ${result.result}
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-f, --file <file>',
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option('-y, --yes', 'Skip confirmation prompt', false)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const taskIdsString = options.id;
|
||||
|
||||
@@ -3479,6 +3575,11 @@ Examples:
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'-f, --file <file>',
|
||||
'Path to the tasks file',
|
||||
TASKMASTER_TASKS_FILE
|
||||
)
|
||||
.option(
|
||||
'--from <id>',
|
||||
'ID of the task/subtask to move (e.g., "5" or "5.2"). Can be comma-separated to move multiple tasks (e.g., "5,6,7")'
|
||||
@@ -3489,6 +3590,7 @@ Examples:
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||
const sourceId = options.from;
|
||||
const destinationId = options.to;
|
||||
@@ -4289,6 +4391,7 @@ async function runCLI(argv = process.argv) {
|
||||
// Setup and parse
|
||||
// NOTE: getConfig() might be called during setupCLI->registerCommands if commands need config
|
||||
// This means the ConfigurationError might be thrown here if configuration file is missing.
|
||||
// This means the ConfigurationError might be thrown here if configuration file is missing.
|
||||
const programInstance = setupCLI();
|
||||
await programInstance.parseAsync(argv);
|
||||
|
||||
@@ -4348,7 +4451,10 @@ async function runCLI(argv = process.argv) {
|
||||
'\n\n' +
|
||||
chalk.white('Taskmaster now uses a ') +
|
||||
chalk.yellow.bold('configuration file') +
|
||||
chalk.white('Taskmaster now uses a ') +
|
||||
chalk.yellow.bold('configuration file') +
|
||||
chalk.white(
|
||||
' in your project for AI model choices and settings.\n\n' +
|
||||
' in your project for AI model choices and settings.\n\n' +
|
||||
'This file appears to be '
|
||||
) +
|
||||
@@ -4362,6 +4468,7 @@ async function runCLI(argv = process.argv) {
|
||||
'\n' +
|
||||
chalk.white('* ') +
|
||||
chalk.yellow.bold('Configuration file') +
|
||||
chalk.yellow.bold('Configuration file') +
|
||||
chalk.white(
|
||||
': Stores your AI model settings (do not manually edit)\n'
|
||||
) +
|
||||
|
||||
@@ -421,7 +421,10 @@ async function expandTask(
|
||||
const outputFormat = mcpLog ? 'json' : 'text';
|
||||
|
||||
// Determine projectRoot: Use from context if available, otherwise derive from tasksPath
|
||||
const projectRoot = contextProjectRoot || findProjectRoot(tasksPath);
|
||||
const projectRoot =
|
||||
contextProjectRoot ||
|
||||
findProjectRoot() ||
|
||||
path.dirname(path.dirname(tasksPath));
|
||||
|
||||
// Use mcpLog if available, otherwise use the default console log wrapper
|
||||
const logger = mcpLog || {
|
||||
|
||||
@@ -213,6 +213,78 @@ function listTasks(
|
||||
// Find next task to work on, passing the complexity report
|
||||
const nextItem = findNextTask(data.tasks, complexityReport);
|
||||
|
||||
// Calculate dependency statistics (moved up to be available for all output formats)
|
||||
const completedTaskIds = new Set(
|
||||
data.tasks
|
||||
.filter((t) => t.status === 'done' || t.status === 'completed')
|
||||
.map((t) => t.id)
|
||||
);
|
||||
|
||||
const tasksWithNoDeps = data.tasks.filter(
|
||||
(t) =>
|
||||
t.status !== 'done' &&
|
||||
t.status !== 'completed' &&
|
||||
(!t.dependencies || t.dependencies.length === 0)
|
||||
).length;
|
||||
|
||||
const tasksWithAllDepsSatisfied = data.tasks.filter(
|
||||
(t) =>
|
||||
t.status !== 'done' &&
|
||||
t.status !== 'completed' &&
|
||||
t.dependencies &&
|
||||
t.dependencies.length > 0 &&
|
||||
t.dependencies.every((depId) => completedTaskIds.has(depId))
|
||||
).length;
|
||||
|
||||
const tasksWithUnsatisfiedDeps = data.tasks.filter(
|
||||
(t) =>
|
||||
t.status !== 'done' &&
|
||||
t.status !== 'completed' &&
|
||||
t.dependencies &&
|
||||
t.dependencies.length > 0 &&
|
||||
!t.dependencies.every((depId) => completedTaskIds.has(depId))
|
||||
).length;
|
||||
|
||||
// Calculate total tasks ready to work on (no deps + satisfied deps)
|
||||
const tasksReadyToWork = tasksWithNoDeps + tasksWithAllDepsSatisfied;
|
||||
|
||||
// Calculate most depended-on tasks
|
||||
const dependencyCount = {};
|
||||
data.tasks.forEach((task) => {
|
||||
if (task.dependencies && task.dependencies.length > 0) {
|
||||
task.dependencies.forEach((depId) => {
|
||||
dependencyCount[depId] = (dependencyCount[depId] || 0) + 1;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Find the most depended-on task
|
||||
let mostDependedOnTaskId = null;
|
||||
let maxDependents = 0;
|
||||
|
||||
for (const [taskId, count] of Object.entries(dependencyCount)) {
|
||||
if (count > maxDependents) {
|
||||
maxDependents = count;
|
||||
mostDependedOnTaskId = parseInt(taskId);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the most depended-on task
|
||||
const mostDependedOnTask =
|
||||
mostDependedOnTaskId !== null
|
||||
? data.tasks.find((t) => t.id === mostDependedOnTaskId)
|
||||
: null;
|
||||
|
||||
// Calculate average dependencies per task
|
||||
const totalDependencies = data.tasks.reduce(
|
||||
(sum, task) => sum + (task.dependencies ? task.dependencies.length : 0),
|
||||
0
|
||||
);
|
||||
const avgDependenciesPerTask = totalDependencies / data.tasks.length;
|
||||
|
||||
// Find next task to work on, passing the complexity report
|
||||
const nextItem = findNextTask(data.tasks, complexityReport);
|
||||
|
||||
// For JSON output, return structured data
|
||||
if (outputFormat === 'json') {
|
||||
// *** Modification: Remove 'details' field for JSON output ***
|
||||
@@ -1045,4 +1117,232 @@ function generateMarkdownOutput(data, filteredTasks, stats) {
|
||||
return markdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate markdown-formatted output for README files
|
||||
* @param {Object} data - Full tasks data
|
||||
* @param {Array} filteredTasks - Filtered tasks array
|
||||
* @param {Object} stats - Statistics object
|
||||
* @returns {string} - Formatted markdown string
|
||||
*/
|
||||
function generateMarkdownOutput(data, filteredTasks, stats) {
|
||||
const {
|
||||
totalTasks,
|
||||
completedTasks,
|
||||
completionPercentage,
|
||||
doneCount,
|
||||
inProgressCount,
|
||||
pendingCount,
|
||||
blockedCount,
|
||||
deferredCount,
|
||||
cancelledCount,
|
||||
totalSubtasks,
|
||||
completedSubtasks,
|
||||
subtaskCompletionPercentage,
|
||||
inProgressSubtasks,
|
||||
pendingSubtasks,
|
||||
blockedSubtasks,
|
||||
deferredSubtasks,
|
||||
cancelledSubtasks,
|
||||
tasksWithNoDeps,
|
||||
tasksReadyToWork,
|
||||
tasksWithUnsatisfiedDeps,
|
||||
mostDependedOnTask,
|
||||
mostDependedOnTaskId,
|
||||
maxDependents,
|
||||
avgDependenciesPerTask,
|
||||
complexityReport,
|
||||
withSubtasks,
|
||||
nextItem
|
||||
} = stats;
|
||||
|
||||
let markdown = '';
|
||||
|
||||
// Create progress bars for markdown (using Unicode block characters)
|
||||
const createMarkdownProgressBar = (percentage, width = 20) => {
|
||||
const filled = Math.round((percentage / 100) * width);
|
||||
const empty = width - filled;
|
||||
return '█'.repeat(filled) + '░'.repeat(empty);
|
||||
};
|
||||
|
||||
// Dashboard section
|
||||
markdown += '```\n';
|
||||
markdown +=
|
||||
'╭─────────────────────────────────────────────────────────╮╭─────────────────────────────────────────────────────────╮\n';
|
||||
markdown +=
|
||||
'│ ││ │\n';
|
||||
markdown +=
|
||||
'│ Project Dashboard ││ Dependency Status & Next Task │\n';
|
||||
markdown += `│ Tasks Progress: ${createMarkdownProgressBar(completionPercentage, 20)} ${Math.round(completionPercentage)}% ││ Dependency Metrics: │\n`;
|
||||
markdown += `│ ${Math.round(completionPercentage)}% ││ • Tasks with no dependencies: ${tasksWithNoDeps} │\n`;
|
||||
markdown += `│ Done: ${doneCount} In Progress: ${inProgressCount} Pending: ${pendingCount} Blocked: ${blockedCount} ││ • Tasks ready to work on: ${tasksReadyToWork} │\n`;
|
||||
markdown += `│ Deferred: ${deferredCount} Cancelled: ${cancelledCount} ││ • Tasks blocked by dependencies: ${tasksWithUnsatisfiedDeps} │\n`;
|
||||
markdown += `│ ││ • Most depended-on task: #${mostDependedOnTaskId} (${maxDependents} dependents) │\n`;
|
||||
markdown += `│ Subtasks Progress: ${createMarkdownProgressBar(subtaskCompletionPercentage, 20)} ││ • Avg dependencies per task: ${avgDependenciesPerTask.toFixed(1)} │\n`;
|
||||
markdown += `│ ${Math.round(subtaskCompletionPercentage)}% ${Math.round(subtaskCompletionPercentage)}% ││ │\n`;
|
||||
markdown += `│ Completed: ${completedSubtasks}/${totalSubtasks} In Progress: ${inProgressSubtasks} Pending: ${pendingSubtasks} ││ Next Task to Work On: │\n`;
|
||||
|
||||
const nextTaskTitle = nextItem
|
||||
? nextItem.title.length > 40
|
||||
? nextItem.title.substring(0, 37) + '...'
|
||||
: nextItem.title
|
||||
: 'No task available';
|
||||
|
||||
markdown += `│ Blocked: ${blockedSubtasks} Deferred: ${deferredSubtasks} Cancelled: ${cancelledSubtasks} ││ ID: ${nextItem ? nextItem.id : 'N/A'} - ${nextTaskTitle} │\n`;
|
||||
markdown += `│ ││ Priority: ${nextItem ? nextItem.priority || 'medium' : ''} Dependencies: ${nextItem && nextItem.dependencies && nextItem.dependencies.length > 0 ? 'Some' : 'None'} │\n`;
|
||||
markdown += `│ Priority Breakdown: ││ Complexity: ${nextItem && nextItem.complexityScore ? '● ' + nextItem.complexityScore : 'N/A'} │\n`;
|
||||
markdown += `│ • High priority: ${data.tasks.filter((t) => t.priority === 'high').length} │╰─────────────────────────────────────────────────────────╯\n`;
|
||||
markdown += `│ • Medium priority: ${data.tasks.filter((t) => t.priority === 'medium').length} │\n`;
|
||||
markdown += `│ • Low priority: ${data.tasks.filter((t) => t.priority === 'low').length} │\n`;
|
||||
markdown += '│ │\n';
|
||||
markdown += '╰─────────────────────────────────────────────────────────╯\n';
|
||||
|
||||
// Tasks table
|
||||
markdown +=
|
||||
'┌───────────┬──────────────────────────────────────┬─────────────────┬──────────────┬───────────────────────┬───────────┐\n';
|
||||
markdown +=
|
||||
'│ ID │ Title │ Status │ Priority │ Dependencies │ Complexi… │\n';
|
||||
markdown +=
|
||||
'├───────────┼──────────────────────────────────────┼─────────────────┼──────────────┼───────────────────────┼───────────┤\n';
|
||||
|
||||
// Helper function to format status with symbols
|
||||
const getStatusSymbol = (status) => {
|
||||
switch (status) {
|
||||
case 'done':
|
||||
case 'completed':
|
||||
return '✓ done';
|
||||
case 'in-progress':
|
||||
return '► in-progress';
|
||||
case 'pending':
|
||||
return '○ pending';
|
||||
case 'blocked':
|
||||
return '⭕ blocked';
|
||||
case 'deferred':
|
||||
return 'x deferred';
|
||||
case 'cancelled':
|
||||
return 'x cancelled';
|
||||
case 'review':
|
||||
return '? review';
|
||||
default:
|
||||
return status || 'pending';
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to format dependencies without color codes
|
||||
const formatDependenciesForMarkdown = (deps, allTasks) => {
|
||||
if (!deps || deps.length === 0) return 'None';
|
||||
return deps
|
||||
.map((depId) => {
|
||||
const depTask = allTasks.find((t) => t.id === depId);
|
||||
return depTask ? depId.toString() : depId.toString();
|
||||
})
|
||||
.join(', ');
|
||||
};
|
||||
|
||||
// Process all tasks
|
||||
filteredTasks.forEach((task) => {
|
||||
const taskTitle = task.title; // No truncation for README
|
||||
const statusSymbol = getStatusSymbol(task.status);
|
||||
const priority = task.priority || 'medium';
|
||||
const deps = formatDependenciesForMarkdown(task.dependencies, data.tasks);
|
||||
const complexity = task.complexityScore
|
||||
? `● ${task.complexityScore}`
|
||||
: 'N/A';
|
||||
|
||||
markdown += `│ ${task.id.toString().padEnd(9)} │ ${taskTitle.substring(0, 36).padEnd(36)} │ ${statusSymbol.padEnd(15)} │ ${priority.padEnd(12)} │ ${deps.substring(0, 21).padEnd(21)} │ ${complexity.padEnd(9)} │\n`;
|
||||
|
||||
// Add subtasks if requested
|
||||
if (withSubtasks && task.subtasks && task.subtasks.length > 0) {
|
||||
task.subtasks.forEach((subtask) => {
|
||||
const subtaskTitle = `└─ ${subtask.title}`; // No truncation
|
||||
const subtaskStatus = getStatusSymbol(subtask.status);
|
||||
const subtaskDeps = formatDependenciesForMarkdown(
|
||||
subtask.dependencies,
|
||||
data.tasks
|
||||
);
|
||||
const subtaskComplexity = subtask.complexityScore
|
||||
? subtask.complexityScore.toString()
|
||||
: 'N/A';
|
||||
|
||||
markdown +=
|
||||
'├───────────┼──────────────────────────────────────┼─────────────────┼──────────────┼───────────────────────┼───────────┤\n';
|
||||
markdown += `│ ${task.id}.${subtask.id}${' '.padEnd(6)} │ ${subtaskTitle.substring(0, 36).padEnd(36)} │ ${subtaskStatus.padEnd(15)} │ - │ ${subtaskDeps.substring(0, 21).padEnd(21)} │ ${subtaskComplexity.padEnd(9)} │\n`;
|
||||
});
|
||||
}
|
||||
|
||||
markdown +=
|
||||
'├───────────┼──────────────────────────────────────┼─────────────────┼──────────────┼───────────────────────┼───────────┤\n';
|
||||
});
|
||||
|
||||
// Close the table
|
||||
markdown = markdown.slice(
|
||||
0,
|
||||
-1 *
|
||||
'├───────────┼──────────────────────────────────────┼─────────────────┼──────────────┼───────────────────────┼───────────┤\n'
|
||||
.length
|
||||
);
|
||||
markdown +=
|
||||
'└───────────┴──────────────────────────────────────┴─────────────────┴──────────────┴───────────────────────┴───────────┘\n';
|
||||
markdown += '```\n\n';
|
||||
|
||||
// Next task recommendation
|
||||
if (nextItem) {
|
||||
markdown +=
|
||||
'╭────────────────────────────────────────────── ⚡ RECOMMENDED NEXT TASK ⚡ ──────────────────────────────────────────────╮\n';
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown += `│ 🔥 Next Task to Work On: #${nextItem.id} - ${nextItem.title} │\n`;
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown += `│ Priority: ${nextItem.priority || 'medium'} Status: ${getStatusSymbol(nextItem.status)} │\n`;
|
||||
markdown += `│ Dependencies: ${nextItem.dependencies && nextItem.dependencies.length > 0 ? formatDependenciesForMarkdown(nextItem.dependencies, data.tasks) : 'None'} │\n`;
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown += `│ Description: ${getWorkItemDescription(nextItem, data.tasks)} │\n`;
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
|
||||
// Add subtasks if they exist
|
||||
const parentTask = data.tasks.find((t) => t.id === nextItem.id);
|
||||
if (parentTask && parentTask.subtasks && parentTask.subtasks.length > 0) {
|
||||
markdown +=
|
||||
'│ Subtasks: │\n';
|
||||
parentTask.subtasks.forEach((subtask) => {
|
||||
markdown += `│ ${nextItem.id}.${subtask.id} [${subtask.status || 'pending'}] ${subtask.title} │\n`;
|
||||
});
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
}
|
||||
|
||||
markdown += `│ Start working: task-master set-status --id=${nextItem.id} --status=in-progress │\n`;
|
||||
markdown += `│ View details: task-master show ${nextItem.id} │\n`;
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown +=
|
||||
'╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\n\n';
|
||||
}
|
||||
|
||||
// Suggested next steps
|
||||
markdown += '\n';
|
||||
markdown +=
|
||||
'╭──────────────────────────────────────────────────────────────────────────────────────╮\n';
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown +=
|
||||
'│ Suggested Next Steps: │\n';
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown +=
|
||||
'│ 1. Run task-master next to see what to work on next │\n';
|
||||
markdown +=
|
||||
'│ 2. Run task-master expand --id=<id> to break down a task into subtasks │\n';
|
||||
markdown +=
|
||||
'│ 3. Run task-master set-status --id=<id> --status=done to mark a task as complete │\n';
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown +=
|
||||
'╰──────────────────────────────────────────────────────────────────────────────────────╯\n';
|
||||
|
||||
return markdown;
|
||||
}
|
||||
|
||||
export default listTasks;
|
||||
|
||||
@@ -28,6 +28,10 @@ import {
|
||||
TASKMASTER_CONFIG_FILE,
|
||||
TASKMASTER_TASKS_FILE
|
||||
} from '../../src/constants/paths.js';
|
||||
import {
|
||||
TASKMASTER_CONFIG_FILE,
|
||||
TASKMASTER_TASKS_FILE
|
||||
} from '../../src/constants/paths.js';
|
||||
import { getTaskMasterVersion } from '../../src/utils/getVersion.js';
|
||||
|
||||
// Create a color gradient for the banner
|
||||
|
||||
Reference in New Issue
Block a user