Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .cursor/rules/commands.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ alwaysApply: false
.option('-p, --path <dir>', 'Output directory') // Should be --output
```

> **Note**: Although options are defined with kebab-case (`--num-tasks`), Commander.js stores them internally as camelCase properties. Access them in code as `options.numTasks`, not `options['num-tasks']`.

## Input Validation

- **Required Parameters**:
Expand Down
2 changes: 1 addition & 1 deletion .cursor/rules/new_features.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ For features requiring components in multiple modules:

- **Naming Conventions**:
- Use kebab-case for command names (`analyze-complexity`, not `analyzeComplexity`)
- Use camelCase for option names (`--outputFormat`, not `--output-format`)
- Use kebab-case for option names (`--output-format`, not `--outputFormat`)
- Use the same option names across commands when they represent the same concept

- **Command Structure**:
Expand Down
23 changes: 20 additions & 3 deletions bin/task-master.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,22 @@ function createDevScriptAction(commandName) {

// Add Commander-provided defaults for options not specified by user
Object.entries(options).forEach(([key, value]) => {
// Debug output to see what keys we're getting
if (process.env.DEBUG === '1') {
console.error(`DEBUG - Processing option: ${key} = ${value}`);
}

// Special case for numTasks > num-tasks (a known problem case)
if (key === 'numTasks') {
if (process.env.DEBUG === '1') {
console.error('DEBUG - Converting numTasks to num-tasks');
}
if (!userOptions.has('num-tasks') && !userOptions.has('numTasks')) {
args.push(`--num-tasks=${value}`);
}
return;
}

// Skip built-in Commander properties and options the user provided
if (['parent', 'commands', 'options', 'rawArgs'].includes(key) || userOptions.has(key)) {
return;
Expand All @@ -154,16 +170,17 @@ function createDevScriptAction(commandName) {
return;
}

// Add default values
// Add default values, using kebab-case for the parameter name
if (value !== undefined) {
if (typeof value === 'boolean') {
if (value === true) {
args.push(`--${key}`);
args.push(`--${kebabKey}`);
} else if (value === false && key === 'generate') {
args.push('--no-generate');
}
} else {
args.push(`--${key}=${value}`);
// Always use kebab-case for option names
args.push(`--${kebabKey}=${value}`);
}
}
});
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "task-master-ai",
"version": "0.9.26",
"version": "0.9.28",
"description": "A task management system for ambitious AI-driven development that doesn't overwhelm and confuse Cursor.",
"main": "index.js",
"type": "module",
"bin": {
"task-master": "./bin/task-master.js",
"task-master-init": "./bin/task-master-init.js"
"task-master": "bin/task-master.js",
"task-master-init": "bin/task-master-init.js"
},
"scripts": {
"test": "node --experimental-vm-modules node_modules/.bin/jest",
Expand Down
18 changes: 12 additions & 6 deletions scripts/modules/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,26 @@ function registerCommands(programInstance) {
.command('parse-prd')
.description('Parse a PRD file and generate tasks')
.argument('[file]', 'Path to the PRD file')
.option('-i, --input <file>', 'Path to the PRD file (alternative to positional argument)')
.option('-o, --output <file>', 'Output file path', 'tasks/tasks.json')
.option('-n, --num-tasks <number>', 'Number of tasks to generate', '10')
.action(async (file, options) => {
if (!file) {
// Use input option if file argument not provided
const inputFile = file || options.input;

if (!inputFile) {
console.log(chalk.yellow('No PRD file specified.'));
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' +
' -o, --output <file> Output file path (default: "tasks/tasks.json")\n' +
' -n, --num-tasks <number> Number of tasks to generate (default: 10)\n\n' +
' -i, --input <file> Path to the PRD file (alternative to positional argument)\n' +
' -o, --output <file> Output file path (default: "tasks/tasks.json")\n' +
' -n, --num-tasks <number> Number of tasks to generate (default: 10)\n\n' +
chalk.cyan('Example:') + '\n' +
' task-master parse-prd requirements.txt --num-tasks 15\n\n' +
' task-master parse-prd requirements.txt --num-tasks 15\n' +
' task-master parse-prd --input=requirements.txt\n\n' +
chalk.yellow('Note: This command will generate tasks from a PRD document and will overwrite any existing tasks.json file.'),
{ padding: 1, borderColor: 'blue', borderStyle: 'round' }
));
Expand All @@ -79,10 +85,10 @@ function registerCommands(programInstance) {
const numTasks = parseInt(options.numTasks, 10);
const outputPath = options.output;

console.log(chalk.blue(`Parsing PRD file: ${file}`));
console.log(chalk.blue(`Parsing PRD file: ${inputFile}`));
console.log(chalk.blue(`Generating ${numTasks} tasks...`));

await parsePRD(file, outputPath, numTasks);
await parsePRD(inputFile, outputPath, numTasks);
});

// update command
Expand Down
3 changes: 3 additions & 0 deletions scripts/sample-prd.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Task Master PRD

Create a CLI tool for task management