feat: add auto-update to every command when your task-master instance is out of date#1217
feat: add auto-update to every command when your task-master instance is out of date#1217Crunchyman-ralph merged 5 commits intonextfrom
Conversation
🦋 Changeset detectedLatest commit: cdb417b The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Caution Review failedThe pull request is closed. WalkthroughAdds a new CLI auto-update utility, re-exports its APIs, refactors the command runner to use the shared auto-update flow (check, notify, optionally perform update), moves Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant U as User
participant CLI as CLI Binary
participant CMD as scripts/modules/commands.js
participant AU as Auto-update (@tm/cli)
participant REG as npm Registry
participant NPM as npm Installer
U->>CLI: run command
CLI->>CMD: runCLI()
CMD->>CMD: execute command logic
CMD->>AU: checkForUpdate(currentVersion)
AU->>REG: GET /task-master-ai (dist-tags.latest)
REG-->>AU: latestVersion / error
AU-->>CMD: {currentVersion, latestVersion, needsUpdate}
alt needsUpdate == true
CMD->>AU: displayUpgradeNotification(...)
CMD->>AU: performAutoUpdate(latestVersion)
AU->>NPM: npm i -g task-master-ai@latestVersion
NPM-->>AU: success / failure
alt success
AU-->>CMD: true
CMD->>CLI: exit(0)
CLI-->>U: updated and exit
else failure
AU-->>CMD: false
CMD-->>CLI: normal completion + manual update guidance
CLI-->>U: command result + instructions
end
else no update
CMD-->>CLI: normal completion
CLI-->>U: command result
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (1)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/modules/commands.js (1)
5136-5147: Gate the background update check for CI/offline and pass the known version.Avoid network calls in CI/offline and reuse the known version to prevent false updates.
Apply this diff:
- // Start the update check in the background - don't await yet - const updateCheckPromise = checkForUpdate(); + // Start the update check in the background - don't await yet (skippable) + const skipAutoUpdate = + process.env.TASKMASTER_SKIP_AUTO_UPDATE === '1' || !!process.env.CI; + const updateCheckPromise = skipAutoUpdate + ? null + : checkForUpdate(getTaskMasterVersion());
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (5)
.changeset/shiny-regions-teach.md(1 hunks)apps/cli/src/index.ts(1 hunks)apps/cli/src/utils/auto-update.ts(1 hunks)package.json(1 hunks)scripts/modules/commands.js(3 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
.changeset/*.md
📄 CodeRabbit inference engine (.cursor/rules/changeset.mdc)
.changeset/*.md: When runningnpm run changesetornpx changeset add, provide a concise summary of the changes for theCHANGELOG.mdin imperative mood, typically a single line, and not a detailed Git commit message.
The changeset summary should be user-facing, describing what changed in the released version that is relevant to users or consumers of the package.
Do not use your detailed Git commit message body as the changeset summary.
Files:
.changeset/shiny-regions-teach.md
.changeset/*
📄 CodeRabbit inference engine (.cursor/rules/new_features.mdc)
Create appropriate changesets for new features, use semantic versioning, include tagged system information in release notes, and document breaking changes if any.
Files:
.changeset/shiny-regions-teach.md
package.json
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
Add and update test scripts in package.json to include test, test:watch, test:coverage, test:unit, test:integration, test:e2e, and test:ci
Files:
package.json
scripts/modules/commands.js
📄 CodeRabbit inference engine (.cursor/rules/ai_services.mdc)
scripts/modules/commands.js: Centralize all LLM calls throughgenerateTextServiceorgenerateObjectService.
Do not import or call anything from the oldai-services.js,ai-client-factory.js, orai-client-utils.jsfiles.
Do not fetch AI-specific parameters (model ID, max tokens, temp) usingconfig-manager.jsgetters for the AI call. Pass theroleinstead.
Do not implement fallback or retry logic outsideai-services-unified.js.
Do not handle API key resolution outside the service layer (it usesutils.jsinternally).
Determine the appropriaterole(main,research,fallback) in your core logic and pass it to the service.
Pass thesessionobject (received in thecontextparameter, especially from direct function wrappers) to the service call when in MCP context.
UsegenerateTextServiceand implement robust manual JSON parsing (with Zod validation after parsing) when structured output is needed, asgenerateObjectServicehas shown unreliability with some providers/schemas.
Be aware of potential reliability issues withgenerateObjectServiceacross different providers and complex schemas. PrefergenerateTextService+ manual parsing as a more robust alternative for structured data needs.
scripts/modules/commands.js: All new user-facing commands should be added to 'scripts/modules/commands.js'.
Use consistent patterns for option naming and help text in CLI commands.
Follow the Commander.js model for subcommand structure in CLI commands.
When using callbacks (like in Commander.js commands), define them separately to allow testing the callback logic independently.
Add help text to the command definition and update 'dev_workflow.mdc' with command reference when adding a new feature.
Follow the established pattern in 'commands.js' for CLI command implementation, using Commander.js for argument parsing, including comprehensive help text and examples, and supporting tagged task context awareness.
Provide clear error messages for common failu...
Files:
scripts/modules/commands.js
scripts/modules/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
Each module in scripts/modules/ should be focused on a single responsibility, following the modular architecture (e.g., commands.js for CLI command handling, task-manager.js for task data and core logic, dependency-manager.js for dependency management, ui.js for CLI output formatting, ai-services-unified.js for AI service integration, config-manager.js for configuration management, utils.js for utility functions).
scripts/modules/*.js: Export all core functions, helper functions, and utility methods needed by your new function or command from their respective modules. Explicitly review the module's export block to ensure every required dependency is included.
Pass all required parameters to functions you call within your implementation and verify that direct function parameters match their core function counterparts.
Use consistent file naming conventions: 'task_${id.toString().padStart(3, '0')}.txt', use path.join for composing file paths, and use appropriate file extensions (.txt for tasks, .json for data).
Use structured error objects with code and message properties, include clear error messages, and handle both function-specific and file system errors.
Import all silent mode utilities together from 'scripts/modules/utils.js' and always use isSilentMode() to check global silent mode status. Wrap core function calls within direct functions using enableSilentMode() and disableSilentMode() in a try/finally block if the core function might produce console output.
Core functions should check outputFormat === 'text' before displaying UI elements and use internal logging that respects silent mode.
Design functions to accept dependencies as parameters (dependency injection) and avoid hard-coded dependencies that are difficult to mock.
Keep pure logic separate from I/O operations or UI rendering to allow testing the logic without mocking complex dependencies.
When implementing core logic for new features, do so in 'scripts/modules/' before CLI or MCP interfaces, and d...
Files:
scripts/modules/commands.js
scripts/modules/**
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
When using the MCP server, restart it if core logic in
scripts/modulesor MCP tool/direct function definitions change.
Files:
scripts/modules/commands.js
scripts/modules/*
📄 CodeRabbit inference engine (.cursor/rules/tags.mdc)
scripts/modules/*: Every command that reads or writes tasks.json must be tag-aware
All command files must import getCurrentTag from utils.js
Every CLI command that operates on tasks must include the --tag CLI option
All commands must resolve the tag using the pattern: options.tag || getCurrentTag(projectRoot) || 'master'
All commands must find projectRoot with error handling before proceeding
All commands must pass { projectRoot, tag } as context to core functions
MCP direct functions must accept and use a context object containing projectRoot and tag, and pass them to core functions
Do not hard-code tag resolution (e.g., const tag = options.tag || 'master';); always use getCurrentTag
Do not omit the --tag CLI option in commands that operate on tasks
Do not omit the context parameter when calling core functions from commands
Do not call readJSON or writeJSON without passing projectRoot and tag
Files:
scripts/modules/commands.js
**/*.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
**/*.js: Declare and initialize global variables at the top of modules to avoid hoisting issues.
Use proper function declarations to avoid hoisting issues and initialize variables before they are referenced.
Do not reference variables before their declaration in module scope.
Use dynamic imports (import()) to avoid initialization order issues in modules.
Files:
scripts/modules/commands.js
🧠 Learnings (16)
📓 Common learnings
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Integrate version checking in the CLI run function, starting the update check in the background and displaying notifications after command execution.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Implement semantic version comparison and display attractive update notifications using boxen.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Implement semantic version comparison and display attractive update notifications using boxen.
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1178
File: packages/tm-core/src/auth/config.ts:5-7
Timestamp: 2025-09-02T21:51:27.921Z
Learning: The user Crunchyman-ralph prefers not to use node: scheme imports (e.g., 'node:os', 'node:path') for Node.js core modules and considers suggestions to change bare imports to node: scheme as too nitpicky.
📚 Learning: 2025-07-31T22:07:49.716Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Integrate version checking in the CLI run function, starting the update check in the background and displaying notifications after command execution.
Applied to files:
apps/cli/src/index.ts.changeset/shiny-regions-teach.mdapps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:10:12.881Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dev_workflow.mdc:0-0
Timestamp: 2025-07-18T17:10:12.881Z
Learning: For CLI usage, install Taskmaster globally with `npm install -g task-master-ai` or use locally via `npx task-master-ai ...`.
Applied to files:
.changeset/shiny-regions-teach.mdapps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:19:27.365Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-07-18T17:19:27.365Z
Learning: Use the global `task-master` CLI command instead of directly invoking `node scripts/dev.js` for all task management operations.
Applied to files:
.changeset/shiny-regions-teach.md
📚 Learning: 2025-07-18T17:19:27.365Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-07-18T17:19:27.365Z
Learning: Use `task-master add-task` to add a new task to tasks.json using AI.
Applied to files:
.changeset/shiny-regions-teach.md
📚 Learning: 2025-09-03T12:15:03.208Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1178
File: apps/cli/src/commands/auth.command.ts:222-224
Timestamp: 2025-09-03T12:15:03.208Z
Learning: The CLI can be invoked using both "task-master" and "tm" as aliases - both forms are valid and acceptable in help text, documentation, and examples.
Applied to files:
.changeset/shiny-regions-teach.md
📚 Learning: 2025-07-31T22:07:49.716Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Applied to files:
.changeset/shiny-regions-teach.mdapps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:10:12.881Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dev_workflow.mdc:0-0
Timestamp: 2025-07-18T17:10:12.881Z
Learning: Use the Taskmaster command set (`task-master` CLI or MCP tools) for all task management operations: listing, expanding, updating, tagging, and status changes.
Applied to files:
.changeset/shiny-regions-teach.md
📚 Learning: 2025-07-18T17:10:53.657Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/glossary.mdc:0-0
Timestamp: 2025-07-18T17:10:53.657Z
Learning: Guidelines for integrating new features into the Task Master CLI with tagged system considerations (new_features.mdc).
Applied to files:
.changeset/shiny-regions-teach.md
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Provider modules must import the provider's create<ProviderName> function from ai-sdk/<provider-name>, and import generateText, streamText, generateObject from the core ai package, as well as the log utility from ../../scripts/modules/utils.js.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Implement semantic version comparison and display attractive update notifications using boxen.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/commands.js : All new user-facing commands should be added to 'scripts/modules/commands.js'.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:54.131Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/telemetry.mdc:0-0
Timestamp: 2025-07-18T17:14:54.131Z
Learning: Applies to scripts/modules/commands.js : CLI command definitions in scripts/modules/commands.js must call the appropriate core logic function with outputFormat: 'text', and must not call displayAiUsageSummary directly if the core logic function already handles it.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:06:57.833Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-07-18T17:06:57.833Z
Learning: Applies to scripts/modules/commands.js : Do not import or call anything from the old `ai-services.js`, `ai-client-factory.js`, or `ai-client-utils.js` files.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:10:53.657Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/glossary.mdc:0-0
Timestamp: 2025-07-18T17:10:53.657Z
Learning: Guidelines for implementing CLI commands using Commander.js (commands.mdc).
Applied to files:
scripts/modules/commands.js
🧬 Code graph analysis (2)
apps/cli/src/utils/auto-update.ts (3)
index.js (1)
packageJson(37-37)apps/cli/src/index.ts (2)
checkForUpdate(17-17)performAutoUpdate(17-17)test-version-check-full.js (2)
currentVersion(21-21)needsUpdate(27-28)
scripts/modules/commands.js (2)
apps/cli/src/index.ts (1)
performAutoUpdate(17-17)apps/cli/src/utils/auto-update.ts (1)
performAutoUpdate(124-181)
🪛 markdownlint-cli2 (0.17.2)
.changeset/shiny-regions-teach.md
5-5: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🪛 GitHub Actions: CI
apps/cli/src/utils/auto-update.ts
[error] 126-176: Biome format check failed. Formatting differences would be applied (multiline string literals). Run 'biome format .' to fix code style.
scripts/modules/commands.js
[error] 5116-5281: Biome format check failed. Exports statement should be on a single line; Run 'biome format .' to fix code style.
🔇 Additional comments (2)
apps/cli/src/index.ts (1)
16-18: LGTM: public re‑exports are correct.Exports look consistent with existing pattern and ESM paths.
scripts/modules/commands.js (1)
24-27: Blocker: @tm/cli is required at runtime — move it to dependencies or bundle it into the published artifact.package.json shows @tm/cli only in devDependencies ("*") and dist/ is missing so bundling cannot be confirmed; scripts/modules/commands.js imports @tm/cli at runtime — move @tm/cli to root "dependencies" (preferred) or ensure your build/bundler inlines it into dist before publishing.
| "task-master-ai": major | ||
| --- | ||
|
|
||
| @tm/cli: add auto-update functionality to every command |
There was a problem hiding this comment.
🧹 Nitpick
Tighten the user‑facing summary (imperative, package‑agnostic).
Changeset summaries should be concise and user‑facing.
Apply:
-@tm/cli: add auto-update functionality to every command
+Enable automatic update after each command when a newer CLI version is available📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @tm/cli: add auto-update functionality to every command | |
| Enable automatic update after each command when a newer CLI version is available |
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
5-5: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🤖 Prompt for AI Agents
.changeset/shiny-regions-teach.md around line 5: the changeset summary is
package-specific and not in imperative, user-facing form; replace it with a
concise, imperative, package-agnostic summary such as "Add auto-update to all
CLI commands" (or equivalent short imperative sentence) so the summary reads
clearly to users and avoids package names.
| function getCurrentVersion(): string { | ||
| try { | ||
| // Read from the root package.json | ||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
| const packagePath = path.join(__dirname, '../../../../package.json'); | ||
| const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8')); | ||
| return packageJson.version; | ||
| } catch (error) { | ||
| console.warn('Could not read package.json for version info'); | ||
| return '0.0.0'; | ||
| } | ||
| } |
There was a problem hiding this comment.
ESM bug: require and __dirname will throw; version resolution unreliable.
This module is ESM; require and __dirname aren’t available. Today this will either throw or always return "0.0.0", causing forced updates every run.
Apply this diff to make it ESM‑safe and reliably locate task-master-ai’s package.json:
-import { spawn } from 'child_process';
-import https from 'https';
-import chalk from 'chalk';
-import ora from 'ora';
+import { spawn } from 'child_process';
+import https from 'https';
+import chalk from 'chalk';
+import ora from 'ora';
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
@@
-function getCurrentVersion(): string {
- try {
- // Read from the root package.json
- const fs = require('fs');
- const path = require('path');
- const packagePath = path.join(__dirname, '../../../../package.json');
- const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
- return packageJson.version;
- } catch (error) {
- console.warn('Could not read package.json for version info');
- return '0.0.0';
- }
-}
+function getCurrentVersion(): string {
+ try {
+ const __filename = fileURLToPath(import.meta.url);
+ let dir = path.dirname(__filename);
+ const root = path.parse(dir).root;
+ while (dir && dir !== root) {
+ const pkgPath = path.join(dir, 'package.json');
+ if (fs.existsSync(pkgPath)) {
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
+ if (pkg?.name === 'task-master-ai' && pkg?.version) return pkg.version;
+ }
+ dir = path.dirname(dir);
+ }
+ if (process.env.npm_package_name === 'task-master-ai' && process.env.npm_package_version) {
+ return process.env.npm_package_version;
+ }
+ } catch {}
+ console.warn('Could not determine task-master-ai version; using 0.0.0');
+ return '0.0.0';
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function getCurrentVersion(): string { | |
| try { | |
| // Read from the root package.json | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const packagePath = path.join(__dirname, '../../../../package.json'); | |
| const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8')); | |
| return packageJson.version; | |
| } catch (error) { | |
| console.warn('Could not read package.json for version info'); | |
| return '0.0.0'; | |
| } | |
| } | |
| import { spawn } from 'child_process'; | |
| import https from 'https'; | |
| import chalk from 'chalk'; | |
| import ora from 'ora'; | |
| import fs from 'fs'; | |
| import path from 'path'; | |
| import { fileURLToPath } from 'url'; | |
| function getCurrentVersion(): string { | |
| try { | |
| const __filename = fileURLToPath(import.meta.url); | |
| let dir = path.dirname(__filename); | |
| const root = path.parse(dir).root; | |
| while (dir && dir !== root) { | |
| const pkgPath = path.join(dir, 'package.json'); | |
| if (fs.existsSync(pkgPath)) { | |
| const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); | |
| if (pkg?.name === 'task-master-ai' && pkg?.version) return pkg.version; | |
| } | |
| dir = path.dirname(dir); | |
| } | |
| if (process.env.npm_package_name === 'task-master-ai' && process.env.npm_package_version) { | |
| return process.env.npm_package_version; | |
| } | |
| } catch {} | |
| console.warn('Could not determine task-master-ai version; using 0.0.0'); | |
| return '0.0.0'; | |
| } |
🤖 Prompt for AI Agents
In apps/cli/src/utils/auto-update.ts around lines 19 to 31, the function uses
require and __dirname which are unavailable in ESM and causes the code to always
fall back to "0.0.0"; replace the require calls and __dirname usage with
ESM-compatible code: derive a directory with const __filename =
fileURLToPath(import.meta.url) and const __dirname = path.dirname(__filename)
(importing fileURLToPath from 'url' and path from 'path'), then resolve the
package.json path reliably (either path.join(__dirname,
'../../../../package.json') or, more robustly, walk up directories until you
find a package.json with name === 'task-master-ai'), read it using
fs.readFileSync or fs/promises readFile, JSON.parse it and return
packageJson.version, and in the catch include the error in the warning instead
of swallowing it.
| "whatwg-url": "^11.0.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@tm/cli": "*", |
There was a problem hiding this comment.
🧩 Analysis chain
Blocker: @tm/cli must be a runtime dependency (not devDependency).
scripts/modules/commands.js imports @tm/cli at runtime. Publishing with it under devDependencies will break consumers (dev deps aren’t installed). Move it to dependencies and pin via workspace.
Apply this diff to remove it from devDependencies:
- "@tm/cli": "*",Also add under "dependencies" (outside this hunk):
"dependencies": {
"@tm/cli": "workspace:*",
...
}🏁 Script executed:
#!/bin/bash
# Verify dist uses @tm/cli at runtime and dep placement
jq -r '.dependencies["@tm/cli"], .devDependencies["@tm/cli"]' package.json
fd dist -t d >/dev/null 2>&1 && rg -nP '@tm/cli' dist -S -g '!**/*.map' || trueLength of output: 51
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== package.json dependencies =="
jq -c '{dependencies:.dependencies, devDependencies:.devDependencies}' package.json || true
echo
echo "== search for literal @tm/cli in repo (excluding node_modules and .git) =="
rg -nH -S "@tm/cli" -g '!node_modules/**' -g '!.git/**' || true
echo
echo "== search for import/require usages of @tm/cli =="
rg -nH -S "require\(['\"]@tm/cli['\"]\)|from ['\"]@tm/cli['\"]|import .* from ['\"]@tm/cli['\"]" -g '!node_modules/**' -g '!.git/**' || true
echo
echo "== show scripts/modules/commands.js if present =="
if [ -f "scripts/modules/commands.js" ]; then
sed -n '1,240p' scripts/modules/commands.js
else
echo "NOT FOUND: scripts/modules/commands.js"
fiLength of output: 7787
Blocker: Move @tm/cli from devDependencies to dependencies (runtime import present)
scripts/modules/commands.js imports '@tm/cli' at runtime; it's currently only in devDependencies and must be moved to dependencies so published packages work.
File: package.json (remove from devDependencies)
Apply this diff to remove it from devDependencies:
- "@tm/cli": "*",Also add under "dependencies" (pin via workspace):
"dependencies": {
"@tm/cli": "workspace:*",
...
}🤖 Prompt for AI Agents
In package.json around line 123, @tm/cli is currently listed under
devDependencies but is imported at runtime in scripts/modules/commands.js;
remove the @tm/cli entry from devDependencies and add it to the top-level
"dependencies" section using the workspace pin ("@tm/cli": "workspace:*") so
published packages include it at runtime.
There was a problem hiding this comment.
@CodeRabbit @tm/cli is built at build time, meaning it will be compiled into dist, so its fine to put it in devDependencies, make sense ?
There was a problem hiding this comment.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
scripts/modules/commands.js
Outdated
| // Automatically perform the update | ||
| const updateSuccess = await performAutoUpdate(updateInfo.latestVersion); | ||
| if (updateSuccess) { | ||
| // Exit gracefully after successful update | ||
| process.exit(0); | ||
| } |
There was a problem hiding this comment.
Provide a CLI opt‑out and don’t force success exit codes.
Let users skip with --skip-auto-update. Also avoid masking command failures with a forced 0 exit.
Apply this diff:
- const updateInfo = await updateCheckPromise;
- if (updateInfo.needsUpdate) {
- // Automatically perform the update
- const updateSuccess = await performAutoUpdate(updateInfo.latestVersion);
- if (updateSuccess) {
- // Exit gracefully after successful update
- process.exit(0);
- }
- }
+ const updateInfo = updateCheckPromise && (await updateCheckPromise);
+ const cliSkip = argv.includes('--skip-auto-update');
+ if (updateInfo?.needsUpdate && !cliSkip) {
+ const updateSuccess = await performAutoUpdate(updateInfo.latestVersion);
+ // Do not override prior non-zero exits; only exit if still running and you choose to.
+ if (updateSuccess) return; // allow natural 0 from successful command
+ }🤖 Prompt for AI Agents
scripts/modules/commands.js around lines 5148 to 5153, the code unconditionally
performs an auto-update and calls process.exit(0) on success which forces a zero
exit code and prevents users from opting out; modify it to check for a CLI
opt-out flag (e.g., process.argv includes '--skip-auto-update' or use the
existing command options) and skip performAutoUpdate when present, and remove
the unconditional process.exit(0) — instead let the function return normally so
the existing command exit code is preserved, only terminate explicitly on update
errors if necessary and propagate non-zero exit codes from the main command.
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/modules/commands.js (1)
5096-5107: Expose a global--skip-auto-updateoption to avoid “unknown option” errors.Without a declared flag, Commander may reject
--skip-auto-update.Apply this diff (place after
.addHelpCommand(false)):.addHelpCommand(false); // Disable default help command + + // Global: allow users to skip the auto-update behavior + programInstance.option('--skip-auto-update', 'Skip automatic update check and install');
♻️ Duplicate comments (7)
apps/cli/src/utils/auto-update.ts (5)
40-53: Semver comparison doesn’t handle prereleases (rc/beta) correctly.Replace with prerelease-aware compare.
Apply this diff:
-function compareVersions(v1: string, v2: string): number { - const v1Parts = v1.split('.').map((p) => parseInt(p, 10)); - const v2Parts = v2.split('.').map((p) => parseInt(p, 10)); - - for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) { - const v1Part = v1Parts[i] || 0; - const v2Part = v2Parts[i] || 0; - - if (v1Part < v2Part) return -1; - if (v1Part > v2Part) return 1; - } - - return 0; -} +function compareVersions(v1: string, v2: string): number { + const split = (v: string) => { + const [core, pre = ''] = v.split('-', 2); + const nums = core.split('.').map((n) => Number.parseInt(n, 10) || 0); + const preIds = pre ? pre.split('.') : []; + return { nums, preIds }; + }; + const a = split(v1); + const b = split(v2); + const len = Math.max(a.nums.length, b.nums.length); + for (let i = 0; i < len; i++) { + const d = (a.nums[i] ?? 0) - (b.nums[i] ?? 0); + if (d !== 0) return d < 0 ? -1 : 1; + } + const aPre = a.preIds, bPre = b.preIds; + if (aPre.length === 0 && bPre.length === 0) return 0; + if (aPre.length === 0) return 1; // release > prerelease + if (bPre.length === 0) return -1; + const n = Math.max(aPre.length, bPre.length); + for (let i = 0; i < n; i++) { + const ai = aPre[i], bi = bPre[i]; + if (ai === undefined) return -1; + if (bi === undefined) return 1; + const an = /^\d+$/.test(ai) ? Number(ai) : NaN; + const bn = /^\d+$/.test(bi) ? Number(bi) : NaN; + if (!Number.isNaN(an) && !Number.isNaN(bn)) { + if (an !== bn) return an < bn ? -1 : 1; + } else if (Number.isNaN(an) && Number.isNaN(bn)) { + if (ai !== bi) return ai < bi ? -1 : 1; + } else { + return Number.isNaN(an) ? 1 : -1; // numeric < non‑numeric + } + } + return 0; +}
58-60: Allow callers to pass the known current version; avoids brittle pkg.json discovery.Expose an optional override param.
Apply this diff:
-export async function checkForUpdate(): Promise<UpdateInfo> { - const currentVersion = getCurrentVersion(); +export async function checkForUpdate(currentVersionOverride?: string): Promise<UpdateInfo> { + const currentVersion = currentVersionOverride || getCurrentVersion();
61-119: Harden registry call: add User‑Agent, check status codes, avoid deprecated abort().Prevents false positives/negatives and deprecation warnings.
Apply this diff:
@@ - const options = { + const options = { hostname: 'registry.npmjs.org', path: '/task-master-ai', method: 'GET', headers: { - Accept: 'application/vnd.npm.install-v1+json' + Accept: 'application/vnd.npm.install-v1+json', + 'User-Agent': `task-master-ai/${currentVersion}` } }; @@ - const req = https.request(options, (res) => { + const req = https.request(options, (res) => { let data = ''; @@ - res.on('end', () => { + res.on('end', () => { try { - const npmData = JSON.parse(data); + if (res.statusCode !== 200) throw new Error(`npm registry status ${res.statusCode}`); + const npmData = JSON.parse(data); const latestVersion = npmData['dist-tags']?.latest || currentVersion; @@ - req.on('error', () => { + req.on('error', () => { resolve({ currentVersion, latestVersion: currentVersion, needsUpdate: false }); }); @@ - req.setTimeout(3000, () => { - req.abort(); + req.setTimeout(3000, () => { + req.destroy(); resolve({ currentVersion, latestVersion: currentVersion, needsUpdate: false }); });
146-215: Skip auto‑update in CI/offline; quiet npm; validate semver before spawn.Prevents noisy/flaky CI and blocks argument injection via a malformed version.
Apply this diff:
export async function performAutoUpdate( latestVersion: string ): Promise<boolean> { + if (process.env.TASKMASTER_SKIP_AUTO_UPDATE === '1' || process.env.CI) { + console.log(chalk.dim('Skipping auto-update (TASKMASTER_SKIP_AUTO_UPDATE/CI).')); + return false; + } + // Basic semver validation: 1.2.3 or 1.2.3-rc.1 + const semverLike = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/; + if (!semverLike.test(latestVersion)) { + console.log(chalk.red(`Refusing to auto-update: invalid version "${latestVersion}"`)); + return false; + } const spinner = ora({ @@ - const updateProcess = spawn( - 'npm', - ['install', '-g', `task-master-ai@${latestVersion}`], + const updateProcess = spawn( + 'npm', + ['install', '-g', `task-master-ai@${latestVersion}`, '--no-fund', '--no-audit', '--loglevel=warn'], { stdio: ['ignore', 'pipe', 'pipe'] } );#!/bin/bash # Verify no other code triggers auto-update during tests and that skip env is honored rg -nP "performAutoUpdate\\(|TASKMASTER_SKIP_AUTO_UPDATE|process\\.env\\.CI" -C2
20-32: ESM bug: require/__dirname usage will throw; version detection falls back to 0.0.0.This will cause perpetual “update available” and can crash in ESM.
Apply this diff:
@@ -import { spawn } from 'child_process'; -import https from 'https'; -import chalk from 'chalk'; -import ora from 'ora'; -import boxen from 'boxen'; +import { spawn } from 'child_process'; +import https from 'https'; +import chalk from 'chalk'; +import ora from 'ora'; +import boxen from 'boxen'; +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; @@ -function getCurrentVersion(): string { - try { - // Read from the root package.json - const fs = require('fs'); - const path = require('path'); - const packagePath = path.join(__dirname, '../../../../package.json'); - const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8')); - return packageJson.version; - } catch (error) { - console.warn('Could not read package.json for version info'); - return '0.0.0'; - } -} +function getCurrentVersion(): string { + try { + const __filename = fileURLToPath(import.meta.url); + let dir = path.dirname(__filename); + const root = path.parse(dir).root; + while (dir && dir !== root) { + const pkgPath = path.join(dir, 'package.json'); + if (fs.existsSync(pkgPath)) { + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); + if (pkg?.name === 'task-master-ai' && pkg?.version) return pkg.version; + } + dir = path.dirname(dir); + } + if (process.env.npm_package_name === 'task-master-ai' && process.env.npm_package_version) { + return process.env.npm_package_version; + } + } catch (e) { + console.warn('Could not determine task-master-ai version; using 0.0.0'); + } + return '0.0.0'; +}scripts/modules/commands.js (2)
5282-5282: Biome export style fixed — LGTM.Single‑line grouped export resolves the formatter error.
5145-5159: Don’t force a success exit; add opt‑out and make the update check non‑fatal.Currently a successful auto‑update calls
process.exit(0)and there’s no opt‑out. Also, a rejected update check would fail the whole command. Add--skip-auto-update, swallow update‑check errors, and preserve the original command’s exit code.Apply this diff:
- const updateInfo = await updateCheckPromise; - if (updateInfo.needsUpdate) { - // Display the upgrade notification first - displayUpgradeNotification( - updateInfo.currentVersion, - updateInfo.latestVersion - ); - - // Then automatically perform the update - const updateSuccess = await performAutoUpdate(updateInfo.latestVersion); - if (updateSuccess) { - // Exit gracefully after successful update - process.exit(0); - } - } + // Make the update check non-fatal and allow opt-out + let updateInfo = null; + try { + updateInfo = updateCheckPromise && (await updateCheckPromise); + } catch (e) { + if (getDebugFlag()) console.warn('Update check failed:', e?.message || e); + } + const cliSkip = argv.includes('--skip-auto-update'); + if (updateInfo?.needsUpdate && !cliSkip) { + displayUpgradeNotification(updateInfo.currentVersion, updateInfo.latestVersion); + const updateSuccess = await performAutoUpdate(updateInfo.latestVersion); + if (updateSuccess) { + // Do not override prior exit codes; let the process end naturally. + return; + } + }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (6)
apps/cli/src/index.ts(1 hunks)apps/cli/src/utils/auto-update.ts(1 hunks)scripts/modules/commands.js(4 hunks)tests/integration/cli/complex-cross-tag-scenarios.test.js(1 hunks)tests/unit/commands.test.js(2 hunks)tsdown.config.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (15)
tests/{unit,integration,e2e,fixtures}/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
Test files must be organized as follows: unit tests in tests/unit/, integration tests in tests/integration/, end-to-end tests in tests/e2e/, and test fixtures in tests/fixtures/.
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.jstests/unit/commands.test.js
**/*.{test,spec}.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/git_workflow.mdc)
**/*.{test,spec}.{js,ts,jsx,tsx}: Create a test file and ensure all tests pass when all subtasks are complete; commit tests if added or modified
When all subtasks are complete, run final testing using the appropriate test runner (e.g., npm test, jest, or manual testing)
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.jstests/unit/commands.test.js
**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
**/*.test.js: Never use asynchronous operations in tests. Make all mocks return synchronous values when possible.
Always mock tests properly based on the way the tested functions are defined and used.
Follow the test file organization: mocks must be set up before importing modules under test, and spies on mocked modules should be set up after imports.
Use fixtures from tests/fixtures/ for consistent sample data across tests.
Always declare mocks before importing the modules being tested in Jest test files.
Use jest.spyOn() after imports to create spies on mock functions and reference these spies in test assertions.
When testing functions with callbacks, get the callback from your mock's call arguments, execute it directly with test inputs, and verify the results.
For ES modules, use jest.mock() before static imports and jest.unstable_mockModule() before dynamic imports to mock dependencies.
Reset mock functions (mockFn.mockReset()) before dynamic imports if they might have been called previously.
When verifying console assertions, assert against the actual arguments passed (single formatted string), not multiple arguments.
Use mock-fs to mock file system operations in tests, and restore the file system after each test.
Mock API calls (e.g., Anthropic/Claude) by mocking the entire module and providing predictable responses.
Set mock environment variables in test setup and restore them after each test.
Maintain test fixtures separate from test logic.
Follow the mock-first-then-import pattern for all Jest mocks.
Do not define mock variables before jest.mock() calls (they won't be accessible due to hoisting).
Use test-specific file paths (e.g., 'test-tasks.json') for all file operations in tests.
Mock readJSON and writeJSON to avoid real file system interactions in tests.
Verify file operations use the correct paths in expect statements.
Use different file paths for each test to avoid test interdependence.
Verify modifications on the in-memory task objects passed to w...
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.jstests/unit/commands.test.js
tests/integration/**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
Integration tests must be located in tests/integration/, test interactions between modules, and focus on component interfaces rather than implementation details.
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
tests/{unit,integration,e2e}/**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
tests/{unit,integration,e2e}/**/*.test.js: When testing CLI commands built with Commander.js, test the command action handlers directly rather than trying to mock the entire Commander.js chain.
When mocking the Commander.js chain, mock ALL chainable methods (option, argument, action, on, etc.) and return this (or the mock object) from all chainable method mocks.
Explicitly handle all options, including defaults and shorthand flags (e.g., -p for --prompt), and include null/undefined checks in test implementations for parameters that might be optional.
Do not try to use the real action implementation without proper mocking, and do not mock Commander partially—either mock it completely or test the action directly.
Mock the action handlers for CLI commands and verify they're called with correct arguments.
Use sample task fixtures for consistent test data, mock file system operations, and test both success and error paths for task operations.
Mock console output and verify correct formatting in UI function tests. Use flexible assertions like toContain() or toMatch() for formatted output.
Mock chalk functions to return the input text to make testing easier while still verifying correct function calls.
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.jstests/unit/commands.test.js
tests/{integration,e2e}/**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
Properly mock session objects when required by functions, and reset environment variables between tests if modified.
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
**/*.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
**/*.js: Declare and initialize global variables at the top of modules to avoid hoisting issues.
Use proper function declarations to avoid hoisting issues and initialize variables before they are referenced.
Do not reference variables before their declaration in module scope.
Use dynamic imports (import()) to avoid initialization order issues in modules.
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.jstests/unit/commands.test.jsscripts/modules/commands.js
**/*.{test,spec}.*
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
Test files should follow naming conventions: .test., .spec., or _test. depending on the language
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.jstests/unit/commands.test.js
tests/{unit,integration,e2e}/**
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
Organize test directories by test type (unit, integration, e2e) and mirror source structure where possible
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.jstests/unit/commands.test.js
tests/unit/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
Each module should have a corresponding unit test file in tests/unit/ that reflects the module structure (one test file per module).
Files:
tests/unit/commands.test.js
tests/unit/**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
tests/unit/**/*.test.js: Unit tests must be located in tests/unit/, test individual functions and utilities in isolation, mock all external dependencies, and keep tests small, focused, and fast.
Do not include actual command execution in unit tests.
Files:
tests/unit/commands.test.js
scripts/modules/commands.js
📄 CodeRabbit inference engine (.cursor/rules/ai_services.mdc)
scripts/modules/commands.js: Centralize all LLM calls throughgenerateTextServiceorgenerateObjectService.
Do not import or call anything from the oldai-services.js,ai-client-factory.js, orai-client-utils.jsfiles.
Do not fetch AI-specific parameters (model ID, max tokens, temp) usingconfig-manager.jsgetters for the AI call. Pass theroleinstead.
Do not implement fallback or retry logic outsideai-services-unified.js.
Do not handle API key resolution outside the service layer (it usesutils.jsinternally).
Determine the appropriaterole(main,research,fallback) in your core logic and pass it to the service.
Pass thesessionobject (received in thecontextparameter, especially from direct function wrappers) to the service call when in MCP context.
UsegenerateTextServiceand implement robust manual JSON parsing (with Zod validation after parsing) when structured output is needed, asgenerateObjectServicehas shown unreliability with some providers/schemas.
Be aware of potential reliability issues withgenerateObjectServiceacross different providers and complex schemas. PrefergenerateTextService+ manual parsing as a more robust alternative for structured data needs.
scripts/modules/commands.js: All new user-facing commands should be added to 'scripts/modules/commands.js'.
Use consistent patterns for option naming and help text in CLI commands.
Follow the Commander.js model for subcommand structure in CLI commands.
When using callbacks (like in Commander.js commands), define them separately to allow testing the callback logic independently.
Add help text to the command definition and update 'dev_workflow.mdc' with command reference when adding a new feature.
Follow the established pattern in 'commands.js' for CLI command implementation, using Commander.js for argument parsing, including comprehensive help text and examples, and supporting tagged task context awareness.
Provide clear error messages for common failu...
Files:
scripts/modules/commands.js
scripts/modules/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
Each module in scripts/modules/ should be focused on a single responsibility, following the modular architecture (e.g., commands.js for CLI command handling, task-manager.js for task data and core logic, dependency-manager.js for dependency management, ui.js for CLI output formatting, ai-services-unified.js for AI service integration, config-manager.js for configuration management, utils.js for utility functions).
scripts/modules/*.js: Export all core functions, helper functions, and utility methods needed by your new function or command from their respective modules. Explicitly review the module's export block to ensure every required dependency is included.
Pass all required parameters to functions you call within your implementation and verify that direct function parameters match their core function counterparts.
Use consistent file naming conventions: 'task_${id.toString().padStart(3, '0')}.txt', use path.join for composing file paths, and use appropriate file extensions (.txt for tasks, .json for data).
Use structured error objects with code and message properties, include clear error messages, and handle both function-specific and file system errors.
Import all silent mode utilities together from 'scripts/modules/utils.js' and always use isSilentMode() to check global silent mode status. Wrap core function calls within direct functions using enableSilentMode() and disableSilentMode() in a try/finally block if the core function might produce console output.
Core functions should check outputFormat === 'text' before displaying UI elements and use internal logging that respects silent mode.
Design functions to accept dependencies as parameters (dependency injection) and avoid hard-coded dependencies that are difficult to mock.
Keep pure logic separate from I/O operations or UI rendering to allow testing the logic without mocking complex dependencies.
When implementing core logic for new features, do so in 'scripts/modules/' before CLI or MCP interfaces, and d...
Files:
scripts/modules/commands.js
scripts/modules/**
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
When using the MCP server, restart it if core logic in
scripts/modulesor MCP tool/direct function definitions change.
Files:
scripts/modules/commands.js
scripts/modules/*
📄 CodeRabbit inference engine (.cursor/rules/tags.mdc)
scripts/modules/*: Every command that reads or writes tasks.json must be tag-aware
All command files must import getCurrentTag from utils.js
Every CLI command that operates on tasks must include the --tag CLI option
All commands must resolve the tag using the pattern: options.tag || getCurrentTag(projectRoot) || 'master'
All commands must find projectRoot with error handling before proceeding
All commands must pass { projectRoot, tag } as context to core functions
MCP direct functions must accept and use a context object containing projectRoot and tag, and pass them to core functions
Do not hard-code tag resolution (e.g., const tag = options.tag || 'master';); always use getCurrentTag
Do not omit the --tag CLI option in commands that operate on tasks
Do not omit the context parameter when calling core functions from commands
Do not call readJSON or writeJSON without passing projectRoot and tag
Files:
scripts/modules/commands.js
🧠 Learnings (42)
📓 Common learnings
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Integrate version checking in the CLI run function, starting the update check in the background and displaying notifications after command execution.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-08-03T12:13:33.875Z
Learning: Applies to package.json : Add and update test scripts in package.json to include test, test:watch, test:coverage, test:unit, test:integration, test:e2e, and test:ci
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1178
File: packages/tm-core/src/auth/config.ts:5-7
Timestamp: 2025-09-02T21:51:27.921Z
Learning: The user Crunchyman-ralph prefers not to use node: scheme imports (e.g., 'node:os', 'node:path') for Node.js core modules and considers suggestions to change bare imports to node: scheme as too nitpicky.
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/**/*.test.js : Test CLI and MCP interfaces with real task data, verify end-to-end workflows across tag contexts, and test error scenarios and recovery in integration tests.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Verify modifications on the in-memory task objects passed to writeJSON.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{unit,integration,e2e}/**/*.test.js : Use sample task fixtures for consistent test data, mock file system operations, and test both success and error paths for task operations.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently, clean up temporary data structures, and avoid keeping all tag data in memory simultaneously.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Generate task files from the current tag context, include tag information in generated files, and do not mix tasks from different tags in file generation.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to scripts/modules/utils.js : Implement complete migration for all related files in the tagged task system, handle configuration and state file creation, and provide migration status tracking.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Use consistent formatting for task files, include all task properties in text files, and format dependencies with status indicators.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-31T22:07:49.716Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Integrate version checking in the CLI run function, starting the update check in the background and displaying notifications after command execution.
Applied to files:
apps/cli/src/index.tstests/unit/commands.test.jsapps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/**/*.test.js : Test core logic independently with both data formats, mock file system operations, test tag resolution behavior, and verify migration compatibility in unit tests.
Applied to files:
tests/unit/commands.test.js
📚 Learning: 2025-07-31T22:07:49.716Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Implement semantic version comparison and display attractive update notifications using boxen.
Applied to files:
tests/unit/commands.test.jsapps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{unit,integration,e2e}/**/*.test.js : When testing CLI commands built with Commander.js, test the command action handlers directly rather than trying to mock the entire Commander.js chain.
Applied to files:
tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Applied to files:
tests/unit/commands.test.jsapps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Do not import real AI service clients in tests; create fully mocked versions that return predictable responses.
Applied to files:
tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:06:57.833Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-07-18T17:06:57.833Z
Learning: Applies to scripts/modules/commands.js : Do not import or call anything from the old `ai-services.js`, `ai-client-factory.js`, or `ai-client-utils.js` files.
Applied to files:
tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{unit,integration,e2e}/**/*.test.js : Do not try to use the real action implementation without proper mocking, and do not mock Commander partially—either mock it completely or test the action directly.
Applied to files:
tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:06:57.833Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-07-18T17:06:57.833Z
Learning: Applies to scripts/modules/task-manager/*.js : Do not import or call anything from the old `ai-services.js`, `ai-client-factory.js`, or `ai-client-utils.js` files.
Applied to files:
tests/unit/commands.test.jsapps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{unit,integration,e2e}/**/*.test.js : Mock the action handlers for CLI commands and verify they're called with correct arguments.
Applied to files:
tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Module dependencies should be mocked before importing the test module, following Jest's hoisting behavior.
Applied to files:
tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/**/*.test.js : Follow the mock-first-then-import pattern and use jest.spyOn() for testing in Jest, clearing mocks between tests.
Applied to files:
tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{unit,integration,e2e}/**/*.test.js : Mock console output and verify correct formatting in UI function tests. Use flexible assertions like toContain() or toMatch() for formatted output.
Applied to files:
tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Mock external libraries (e.g., fs, commander, anthropic-ai/sdk) at the module level in tests.
Applied to files:
tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Use jest.spyOn() after imports to create spies on mock functions and reference these spies in test assertions.
Applied to files:
tests/unit/commands.test.js
📚 Learning: 2025-07-18T17:19:27.365Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-07-18T17:19:27.365Z
Learning: When implementation differs significantly from planned approach, call `node scripts/dev.js update --from=<futureTaskId> --prompt="<explanation>"` to update tasks.json.
Applied to files:
apps/cli/src/utils/auto-update.ts
📚 Learning: 2025-08-07T13:00:22.966Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1090
File: apps/extension/package.json:241-243
Timestamp: 2025-08-07T13:00:22.966Z
Learning: In monorepos, local packages should use "*" as the version constraint in package.json dependencies, as recommended by npm. This ensures the local version from within the same workspace is always used, rather than attempting to resolve from external registries. This applies to packages like task-master-ai within the eyaltoledano/claude-task-master monorepo.
Applied to files:
apps/cli/src/utils/auto-update.ts
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to scripts/modules/task-manager/**/*.js : Do not call AI-specific getters (like `getMainModelId`, `getMainMaxTokens`) from core logic functions in `scripts/modules/task-manager/*`; instead, pass the `role` to the unified AI service.
Applied to files:
apps/cli/src/utils/auto-update.ts
📚 Learning: 2025-07-18T17:10:12.881Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dev_workflow.mdc:0-0
Timestamp: 2025-07-18T17:10:12.881Z
Learning: For CLI usage, install Taskmaster globally with `npm install -g task-master-ai` or use locally via `npx task-master-ai ...`.
Applied to files:
apps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:06:57.833Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-07-18T17:06:57.833Z
Learning: Applies to scripts/modules/task-manager/*.js : Do not implement fallback or retry logic outside `ai-services-unified.js`.
Applied to files:
apps/cli/src/utils/auto-update.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/commands.js : All new user-facing commands should be added to 'scripts/modules/commands.js'.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:54.131Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/telemetry.mdc:0-0
Timestamp: 2025-07-18T17:14:54.131Z
Learning: Applies to scripts/modules/task-manager/**/*.js : If the core logic function handles CLI output (outputFormat === 'text' or 'cli'), and aiServiceResponse.telemetryData is available, it must call displayAiUsageSummary(aiServiceResponse.telemetryData, 'cli') from scripts/modules/ui.js.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-21T17:51:07.239Z
Learnt from: joedanz
PR: eyaltoledano/claude-task-master#748
File: scripts/modules/task-manager/parse-prd.js:726-733
Timestamp: 2025-07-21T17:51:07.239Z
Learning: In CLI contexts within task-manager modules like scripts/modules/task-manager/parse-prd.js, using process.exit(1) for validation failures and error conditions is correct and preferred over throwing errors, as it provides immediate termination with appropriate exit codes for scripting. The code should distinguish between MCP contexts (throw errors) and CLI contexts (use process.exit).
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to {scripts/modules/utils.js,mcp-server/src/core/utils/path-utils.js,mcp-server/src/tools/utils.js} : Keep utilities relevant to their location, export all utility functions in a single statement per file, group related exports together, export configuration constants, do not use default exports, and do not create circular dependencies.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/*.js : Export all core functions, helper functions, and utility methods needed by your new function or command from their respective modules. Explicitly review the module's export block to ensure every required dependency is included.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to {scripts/modules/utils.js,mcp-server/src/core/utils/path-utils.js,mcp-server/src/tools/utils.js} : Export all utility functions explicitly, group related functions logically, and include new tagged system utilities.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Group related commands together in the code, add related commands in a logical order, and use comments to delineate command groups.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Group imports by module/functionality, import only what's needed (not entire modules), and do not create circular dependencies.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Applies to scripts/modules/*.js : Each module in scripts/modules/ should be focused on a single responsibility, following the modular architecture (e.g., commands.js for CLI command handling, task-manager.js for task data and core logic, dependency-manager.js for dependency management, ui.js for CLI output formatting, ai-services-unified.js for AI service integration, config-manager.js for configuration management, utils.js for utility functions).
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:06:57.833Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-07-18T17:06:57.833Z
Learning: Applies to scripts/modules/task-manager/*.js : Do not fetch AI-specific parameters (model ID, max tokens, temp) using `config-manager.js` getters for the AI call. Pass the `role` instead.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to scripts/modules/config-manager.js : Update scripts/modules/config-manager.js to add the new provider to MODEL_MAP, ensure it is included in VALID_PROVIDERS, and update API key handling logic.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-31T22:08:16.039Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/taskmaster.mdc:0-0
Timestamp: 2025-07-31T22:08:16.039Z
Learning: Applies to .taskmaster/config.json : All other Taskmaster settings (model choice, max tokens, temperature, log level, custom endpoints) are managed in .taskmaster/config.json via the task-master models command or models MCP tool.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:10:02.683Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dev_workflow.mdc:0-0
Timestamp: 2025-07-18T17:10:02.683Z
Learning: Applies to .taskmaster/config.json : Store Taskmaster configuration settings (AI model selections, parameters, logging level, default subtasks/priority, project name, tag management) in `.taskmaster/config.json` in the project root. Do not configure these via environment variables.
Applied to files:
scripts/modules/commands.js
🧬 Code graph analysis (3)
tests/unit/commands.test.js (2)
apps/cli/src/index.ts (1)
displayUpgradeNotification(20-20)apps/cli/src/utils/auto-update.ts (1)
displayUpgradeNotification(125-141)
apps/cli/src/utils/auto-update.ts (2)
index.js (1)
packageJson(37-37)apps/cli/src/index.ts (3)
checkForUpdate(18-18)displayUpgradeNotification(20-20)performAutoUpdate(19-19)
scripts/modules/commands.js (3)
apps/cli/src/index.ts (2)
displayUpgradeNotification(20-20)performAutoUpdate(19-19)apps/cli/src/utils/auto-update.ts (2)
displayUpgradeNotification(125-141)performAutoUpdate(146-215)tests/unit/commands.test.js (1)
displayUpgradeNotification(320-320)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Test
🔇 Additional comments (6)
tests/integration/cli/complex-cross-tag-scenarios.test.js (1)
372-380: Timeout bump is reasonable given CLI work; keep CI threshold tighter if possible.6000 ms (local) vs 10000 ms (CI) is fine once auto‑update is disabled as above.
apps/cli/src/utils/auto-update.ts (1)
125-141: Nice UX for the upgrade notice.Message formatting and guidance look good.
tests/unit/commands.test.js (1)
283-303: Local comparator is fine; ensure we don’t implicitly rely on the module’s internal compareVersions.The imported cv is unused; that’s OK, but avoid accidental dependency on non‑exported internals.
tsdown.config.ts (1)
27-27: Ignoring tests in watcher is fine; confirm your dev workflow doesn’t rely on auto-rebuild from test edits.If you do, drop 'tests' from ignoreWatch locally.
apps/cli/src/index.ts (1)
16-21: Re‑export of auto‑update APIs looks good.Keeps CLI consumers on a stable surface.
scripts/modules/commands.js (1)
88-89: Confirm getDefaultNumTasks export and numeric defaultVerified: getDefaultNumTasks is defined in scripts/modules/config-manager.js (lines 529–532), exported (around lines 1038–1041), and imported/used in scripts/modules/commands.js for the --num-tasks option (around lines 827–831). It returns a Number (parseInt on config with numeric fallback DEFAULTS.global.defaultNumTasks = 10). No change required.
| // Auto-update utilities | ||
| export { | ||
| checkForUpdate, | ||
| performAutoUpdate, | ||
| displayUpgradeNotification | ||
| } from './utils/auto-update.js'; |
There was a problem hiding this comment.
🧹 Nitpick
Also export the UpdateInfo type for consumers.
Minor ergonomics improvement.
Apply this diff:
export {
checkForUpdate,
performAutoUpdate,
displayUpgradeNotification
} from './utils/auto-update.js';
+
+// Types
+export type { UpdateInfo } from './utils/auto-update.js';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Auto-update utilities | |
| export { | |
| checkForUpdate, | |
| performAutoUpdate, | |
| displayUpgradeNotification | |
| } from './utils/auto-update.js'; | |
| // Auto-update utilities | |
| export { | |
| checkForUpdate, | |
| performAutoUpdate, | |
| displayUpgradeNotification | |
| } from './utils/auto-update.js'; | |
| // Types | |
| export type { UpdateInfo } from './utils/auto-update.js'; |
🤖 Prompt for AI Agents
In apps/cli/src/index.ts around lines 16 to 21, the module exports auto-update
functions but doesn't re-export the UpdateInfo type for consumers; add a
re-export for the UpdateInfo type from './utils/auto-update.js' alongside the
existing exports so downstream callers can import the type (use a type-only
export to avoid runtime output).
There was a problem hiding this comment.
@Crunchyman-ralph, understood! I'll note your preference for future reviews.
✏️ Learnings added
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1217
File: apps/cli/src/index.ts:16-21
Timestamp: 2025-09-18T16:35:35.113Z
Learning: The user Crunchyman-ralph considers suggestions to export types for better ergonomics (like exporting UpdateInfo type alongside related functions) as nitpicky and prefers not to implement such suggestions.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Integrate version checking in the CLI run function, starting the update check in the background and displaying notifications after command execution.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1178
File: packages/tm-core/src/auth/config.ts:5-7
Timestamp: 2025-09-02T21:51:27.921Z
Learning: The user Crunchyman-ralph prefers not to use node: scheme imports (e.g., 'node:os', 'node:path') for Node.js core modules and considers suggestions to change bare imports to node: scheme as too nitpicky.
| SetStatusCommand, | ||
| checkForUpdate, | ||
| performAutoUpdate, | ||
| displayUpgradeNotification | ||
| } from '@tm/cli'; |
There was a problem hiding this comment.
🧩 Analysis chain
Verify @tm/cli exports checkForUpdate and keep it as a runtime dependency.
Risk: If @tm/cli doesn’t export checkForUpdate (only performAutoUpdate/displayUpgradeNotification), this import will throw at startup. Also, if @tm/cli was moved to devDependencies, end users won’t have it at runtime.
Action: Confirm the named export and ensure @tm/cli is a production dependency of the package that ships this file. If not, re‑export it from @tm/cli’s index or import from its concrete module.
🏁 Script executed:
#!/bin/bash
# 1) Verify named export exists
rg -nP --glob 'apps/cli/**' 'export\s+\{[^}]*\bcheckForUpdate\b|export\s+(async\s+)?function\s+checkForUpdate\b'
# 2) Verify the package that contains scripts/modules/commands.js depends on @tm/cli (not only dev)
fd package.json -x bash -lc 'echo "FILE:{}"; jq -r ".name,.dependencies[\"@tm/cli\"],.devDependencies[\"@tm/cli\"]" {} | nl -ba'Length of output: 1101
🏁 Script executed:
#!/usr/bin/env bash
# 1. Locate scripts/modules/commands.js
echo "commands.js file(s):"
fd -g "scripts/modules/commands.js"
# 2. Check root package.json for @tm/cli dependency
echo -e "\nRoot package.json dependencies for @tm/cli:"
jq -r '.dependencies["@tm/cli"] // "absent", .devDependencies["@tm/cli"] // "absent"' package.json
# 3. Verify apps/cli package identity
echo -e "\napps/cli package.json name and main entry:"
jq -r '.name, .main // .exports' apps/cli/package.json
# 4. Confirm export in source index
echo -e "\napps/cli/src/index.ts exports checkForUpdate:"
grep -R "export.*checkForUpdate" -n apps/cli/src/index.ts || echo "Not found in apps/cli/src/index.ts"
# 5. Confirm export in built output (if present)
echo -e "\napps/cli/dist/index.js exports checkForUpdate:"
grep -R "checkForUpdate" -n apps/cli/dist/index.js || echo "Not found in apps/cli/dist/index.js"Length of output: 364
Fix missing export and ensure @tm/cli is a runtime dependency.
-
apps/cli/src/utils/auto-update.ts exports checkForUpdate (≈ line 58) but apps/cli/src/index.ts does not re-export it — importing { checkForUpdate } from '@tm/cli' will throw. Fix: re-export checkForUpdate from apps/cli/src/index.ts or change the import in scripts/modules/commands.js (lines 24–28) to the concrete module path that exports it.
-
@tm/cli is only listed as a devDependency (root package.json) and apps/cli/package.json points to ./dist/index.js (dist not present). Fix: ensure @tm/cli is a production dependency of the package that ships scripts/modules/commands.js (move to dependencies or publish a built package whose main exports checkForUpdate).
🤖 Prompt for AI Agents
In scripts/modules/commands.js around lines 24–28, importing checkForUpdate from
'@tm/cli' fails because apps/cli/src/index.ts does not re-export checkForUpdate
(it is exported only from apps/cli/src/utils/auto-update.ts), and additionally
@tm/cli is only a devDependency and the apps/cli package points to ./dist which
isn’t built at runtime; fix by either re-exporting checkForUpdate from
apps/cli/src/index.ts (add a named export that re-exports the symbol from
utils/auto-update) or change the import in scripts/modules/commands.js to import
checkForUpdate from the concrete module path that exports it, and make @tm/cli a
runtime dependency for the package that ships scripts/modules/commands.js (move
@tm/cli from devDependencies to dependencies in the appropriate package.json or
publish a built dist with index.js that includes the re-export so the runtime
import resolves).
There was a problem hiding this comment.
@CodeRabbit doesn't need to be a runtime dependency since all bundled at build time
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if checkForUpdate is actually exported from apps/cli/src/index.ts
echo "=== Checking apps/cli/src/index.ts exports ==="
cat apps/cli/src/index.ts
echo -e "\n=== Verifying the auto-update exports specifically ==="
grep -n "checkForUpdate\|performAutoUpdate\|displayUpgradeNotification" apps/cli/src/index.ts
echo -e "\n=== Checking if auto-update utilities are properly imported in index.ts ==="
grep -n "auto-update" apps/cli/src/index.ts
Length of output: 1080
@Crunchyman-ralph, you're absolutely right! I can see that the exports are properly configured in apps/cli/src/index.ts:
// Auto-update utilities
export {
checkForUpdate,
performAutoUpdate,
displayUpgradeNotification
} from './utils/auto-update.js';The import in scripts/modules/commands.js will resolve correctly at build time, and since everything gets bundled together, the dependency location (dev vs prod) doesn't matter for the final runtime behavior. My initial concern about the missing export was unfounded - the exports are properly set up and the build-time bundling approach handles the dependency resolution.
Thanks for the clarification about the build setup!
🧠 Learnings used
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Integrate version checking in the CLI run function, starting the update check in the background and displaying notifications after command execution.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Implement semantic version comparison and display attractive update notifications using boxen.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Implement semantic version comparison and display attractive update notifications using boxen.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/commands.js : All new user-facing commands should be added to 'scripts/modules/commands.js'.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/commands.js : Follow the established pattern in 'commands.js' for CLI command implementation, using Commander.js for argument parsing, including comprehensive help text and examples, and supporting tagged task context awareness.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Suggest non-destructive alternatives when appropriate, explain the difference between deletion and status changes, and include examples of alternative commands.
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#992
File: .coderabbit.yaml:1-169
Timestamp: 2025-07-16T16:06:07.169Z
Learning: CodeRabbit configuration files like .coderabbit.yaml are internal development tooling that affect the review process but don't impact end users, so changesets are not required for these configuration additions.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/telemetry.mdc:0-0
Timestamp: 2025-07-18T17:14:54.131Z
Learning: Applies to scripts/modules/task-manager/**/*.js : If the core logic function handles CLI output (outputFormat === 'text' or 'cli'), and aiServiceResponse.telemetryData is available, it must call displayAiUsageSummary(aiServiceResponse.telemetryData, 'cli') from scripts/modules/ui.js.
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1178
File: packages/tm-core/src/auth/config.ts:5-7
Timestamp: 2025-09-02T21:51:27.921Z
Learning: The user Crunchyman-ralph prefers not to use node: scheme imports (e.g., 'node:os', 'node:path') for Node.js core modules and considers suggestions to change bare imports to node: scheme as too nitpicky.
| beforeAll(async () => { | ||
| const commandsModule = await import('../../scripts/modules/commands.js'); | ||
| displayUpgradeNotification = commandsModule.displayUpgradeNotification; | ||
| // Import from @tm/cli instead of commands.js | ||
| const cliModule = await import('../../apps/cli/src/utils/auto-update.js'); | ||
| displayUpgradeNotification = cliModule.displayUpgradeNotification; | ||
| }); |
There was a problem hiding this comment.
Tests will throw: current chalk mock doesn’t support blue.bold/dim chaining.
displayUpgradeNotification calls chalk.blue.bold(), chalk.dim(), chalk.green(). Update the mock to be chainable and passthrough strings.
Apply this diff at the chalk mock block:
-jest.mock('chalk', () => ({
- red: jest.fn((text) => text),
- blue: jest.fn((text) => text),
- green: jest.fn((text) => text),
- yellow: jest.fn((text) => text),
- white: jest.fn((text) => ({
- bold: jest.fn((text) => text)
- })),
- reset: jest.fn((text) => text)
-}));
+jest.mock('chalk', () => {
+ const passthru = (s) => String(s);
+ passthru.bold = passthru;
+ passthru.dim = passthru;
+ return {
+ red: passthru,
+ blue: passthru, // supports .bold
+ green: passthru,
+ yellow: passthru,
+ white: passthru,
+ dim: passthru,
+ reset: passthru
+ };
+});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| beforeAll(async () => { | |
| const commandsModule = await import('../../scripts/modules/commands.js'); | |
| displayUpgradeNotification = commandsModule.displayUpgradeNotification; | |
| // Import from @tm/cli instead of commands.js | |
| const cliModule = await import('../../apps/cli/src/utils/auto-update.js'); | |
| displayUpgradeNotification = cliModule.displayUpgradeNotification; | |
| }); | |
| jest.mock('chalk', () => { | |
| const passthru = (s) => String(s); | |
| passthru.bold = passthru; | |
| passthru.dim = passthru; | |
| return { | |
| red: passthru, | |
| blue: passthru, // supports .bold | |
| green: passthru, | |
| yellow: passthru, | |
| white: passthru, | |
| dim: passthru, | |
| reset: passthru | |
| }; | |
| }); |
Crunchyman-ralph
left a comment
There was a problem hiding this comment.
self-reviewed, thanks coderabbit!
| // Auto-update utilities | ||
| export { | ||
| checkForUpdate, | ||
| performAutoUpdate, | ||
| displayUpgradeNotification | ||
| } from './utils/auto-update.js'; |
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (4)
tests/integration/cli/complex-cross-tag-scenarios.test.js (1)
372-372: Make perf timing deterministic by disabling auto‑update in this suite.Auto‑update adds network/installation time and makes this assertion flaky. Set and restore the env var around tests.
@@ beforeEach(() => { // Create test directory testDir = fs.mkdtempSync(path.join(__dirname, 'test-')); process.chdir(testDir); // Initialize task-master execSync(`node ${binPath} init --yes`, { stdio: 'pipe' }); + // Keep timings deterministic across environments + process.env.TASKMASTER_SKIP_AUTO_UPDATE = '1'; }); afterEach(() => { // Change back to project root before cleanup @@ if (testDir && fs.existsSync(testDir)) { fs.rmSync(testDir, { recursive: true, force: true }); } + delete process.env.TASKMASTER_SKIP_AUTO_UPDATE; });scripts/modules/commands.js (2)
5148-5160: Don’t force a 0 exit code; add CLI opt‑out and suppress notification when skipped.
- Forcing process.exit(0) can mask command failures.
- Honor a CLI flag (--skip-auto-update) in addition to env/CI.
- Don’t print the “Auto‑updating…” box if we’re skipping.
- // Display the upgrade notification first - displayUpgradeNotification( - updateInfo.currentVersion, - updateInfo.latestVersion - ); - - // Then automatically perform the update - const updateSuccess = await performAutoUpdate(updateInfo.latestVersion); - if (updateSuccess) { - // Exit gracefully after successful update - process.exit(0); - } + const skipEnv = + process.env.TASKMASTER_SKIP_AUTO_UPDATE === '1' || process.env.CI; + const cliSkip = argv.includes('--skip-auto-update'); + if (skipEnv || cliSkip) { + console.log( + chalk.dim( + `Update available: ${updateInfo.currentVersion} → ${updateInfo.latestVersion}. ` + + (cliSkip + ? 'Skipping due to --skip-auto-update.' + : 'Skipping due to TASKMASTER_SKIP_AUTO_UPDATE/CI.') + ) + ); + } else { + displayUpgradeNotification( + updateInfo.currentVersion, + updateInfo.latestVersion + ); + const updateSuccess = await performAutoUpdate(updateInfo.latestVersion); + if (updateSuccess) return; // preserve prior exit codes + }Add a root option so Commander won’t treat it as unknown:
// outside selected lines; in setupCLI() after .addHelpCommand(false) programInstance.option('--skip-auto-update', 'Disable auto-update for this run');
24-28: Make @tm/cli a runtime dependency — exports verified.
- ./apps/cli/src/index.ts re-exports checkForUpdate, performAutoUpdate, displayUpgradeNotification (from ./apps/cli/src/utils/auto-update.js).
- scripts/modules/commands.js imports those from '@tm/cli' (around lines 24–28).
- ./package.json (root, package name: task-master-ai) currently lists "@tm/cli" in devDependencies ("*"); move "@tm/cli" to dependencies (or otherwise ensure the package that ships scripts/modules/commands.js has @tm/cli as a runtime dependency) so the auto-update utilities are available at runtime.
apps/cli/src/utils/auto-update.ts (1)
10-10: Blocker: stop using static ESM JSON import for package.json — use runtime lookup or raise Node minimumRepo root and packages declare engines.node >=18.0.0, but the ESM import-attribute syntax "with { type: 'json' }" requires Node >= 18.20.0 / newer runtime support and will fail on Node 18.x releases older than 18.20.0. (nodejs.org)
Replace the import in apps/cli/src/utils/auto-update.ts:10 (and the other occurrences found: packages/tm-core/src/auth/oauth-service.ts:20; src/utils/getVersion.js:1; mcp-server/src/index.js:10; mcp-server/src/tools/utils.js:11) with a runtime resolver that uses fileURLToPath + fs and walks upward to the nearest package.json named "task-master-ai" (the original suggested diff is appropriate), or alternatively bump engines.node to >=18.20.0 (or >=20.10.0) and update CI.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (7)
.github/workflows/ci.yml(1 hunks).github/workflows/pre-release.yml(1 hunks).github/workflows/release.yml(2 hunks)apps/cli/src/utils/auto-update.ts(1 hunks)apps/docs/best-practices/configuration-advanced.mdx(1 hunks)scripts/modules/commands.js(5 hunks)tests/integration/cli/complex-cross-tag-scenarios.test.js(1 hunks)
🧰 Additional context used
📓 Path-based instructions (13)
tests/{unit,integration,e2e,fixtures}/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
Test files must be organized as follows: unit tests in tests/unit/, integration tests in tests/integration/, end-to-end tests in tests/e2e/, and test fixtures in tests/fixtures/.
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
**/*.{test,spec}.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/git_workflow.mdc)
**/*.{test,spec}.{js,ts,jsx,tsx}: Create a test file and ensure all tests pass when all subtasks are complete; commit tests if added or modified
When all subtasks are complete, run final testing using the appropriate test runner (e.g., npm test, jest, or manual testing)
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
**/*.test.js: Never use asynchronous operations in tests. Make all mocks return synchronous values when possible.
Always mock tests properly based on the way the tested functions are defined and used.
Follow the test file organization: mocks must be set up before importing modules under test, and spies on mocked modules should be set up after imports.
Use fixtures from tests/fixtures/ for consistent sample data across tests.
Always declare mocks before importing the modules being tested in Jest test files.
Use jest.spyOn() after imports to create spies on mock functions and reference these spies in test assertions.
When testing functions with callbacks, get the callback from your mock's call arguments, execute it directly with test inputs, and verify the results.
For ES modules, use jest.mock() before static imports and jest.unstable_mockModule() before dynamic imports to mock dependencies.
Reset mock functions (mockFn.mockReset()) before dynamic imports if they might have been called previously.
When verifying console assertions, assert against the actual arguments passed (single formatted string), not multiple arguments.
Use mock-fs to mock file system operations in tests, and restore the file system after each test.
Mock API calls (e.g., Anthropic/Claude) by mocking the entire module and providing predictable responses.
Set mock environment variables in test setup and restore them after each test.
Maintain test fixtures separate from test logic.
Follow the mock-first-then-import pattern for all Jest mocks.
Do not define mock variables before jest.mock() calls (they won't be accessible due to hoisting).
Use test-specific file paths (e.g., 'test-tasks.json') for all file operations in tests.
Mock readJSON and writeJSON to avoid real file system interactions in tests.
Verify file operations use the correct paths in expect statements.
Use different file paths for each test to avoid test interdependence.
Verify modifications on the in-memory task objects passed to w...
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
tests/integration/**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
Integration tests must be located in tests/integration/, test interactions between modules, and focus on component interfaces rather than implementation details.
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
tests/{unit,integration,e2e}/**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
tests/{unit,integration,e2e}/**/*.test.js: When testing CLI commands built with Commander.js, test the command action handlers directly rather than trying to mock the entire Commander.js chain.
When mocking the Commander.js chain, mock ALL chainable methods (option, argument, action, on, etc.) and return this (or the mock object) from all chainable method mocks.
Explicitly handle all options, including defaults and shorthand flags (e.g., -p for --prompt), and include null/undefined checks in test implementations for parameters that might be optional.
Do not try to use the real action implementation without proper mocking, and do not mock Commander partially—either mock it completely or test the action directly.
Mock the action handlers for CLI commands and verify they're called with correct arguments.
Use sample task fixtures for consistent test data, mock file system operations, and test both success and error paths for task operations.
Mock console output and verify correct formatting in UI function tests. Use flexible assertions like toContain() or toMatch() for formatted output.
Mock chalk functions to return the input text to make testing easier while still verifying correct function calls.
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
tests/{integration,e2e}/**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
Properly mock session objects when required by functions, and reset environment variables between tests if modified.
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
**/*.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
**/*.js: Declare and initialize global variables at the top of modules to avoid hoisting issues.
Use proper function declarations to avoid hoisting issues and initialize variables before they are referenced.
Do not reference variables before their declaration in module scope.
Use dynamic imports (import()) to avoid initialization order issues in modules.
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.jsscripts/modules/commands.js
**/*.{test,spec}.*
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
Test files should follow naming conventions: .test., .spec., or _test. depending on the language
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
tests/{unit,integration,e2e}/**
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
Organize test directories by test type (unit, integration, e2e) and mirror source structure where possible
Files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
scripts/modules/commands.js
📄 CodeRabbit inference engine (.cursor/rules/ai_services.mdc)
scripts/modules/commands.js: Centralize all LLM calls throughgenerateTextServiceorgenerateObjectService.
Do not import or call anything from the oldai-services.js,ai-client-factory.js, orai-client-utils.jsfiles.
Do not fetch AI-specific parameters (model ID, max tokens, temp) usingconfig-manager.jsgetters for the AI call. Pass theroleinstead.
Do not implement fallback or retry logic outsideai-services-unified.js.
Do not handle API key resolution outside the service layer (it usesutils.jsinternally).
Determine the appropriaterole(main,research,fallback) in your core logic and pass it to the service.
Pass thesessionobject (received in thecontextparameter, especially from direct function wrappers) to the service call when in MCP context.
UsegenerateTextServiceand implement robust manual JSON parsing (with Zod validation after parsing) when structured output is needed, asgenerateObjectServicehas shown unreliability with some providers/schemas.
Be aware of potential reliability issues withgenerateObjectServiceacross different providers and complex schemas. PrefergenerateTextService+ manual parsing as a more robust alternative for structured data needs.
scripts/modules/commands.js: All new user-facing commands should be added to 'scripts/modules/commands.js'.
Use consistent patterns for option naming and help text in CLI commands.
Follow the Commander.js model for subcommand structure in CLI commands.
When using callbacks (like in Commander.js commands), define them separately to allow testing the callback logic independently.
Add help text to the command definition and update 'dev_workflow.mdc' with command reference when adding a new feature.
Follow the established pattern in 'commands.js' for CLI command implementation, using Commander.js for argument parsing, including comprehensive help text and examples, and supporting tagged task context awareness.
Provide clear error messages for common failu...
Files:
scripts/modules/commands.js
scripts/modules/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
Each module in scripts/modules/ should be focused on a single responsibility, following the modular architecture (e.g., commands.js for CLI command handling, task-manager.js for task data and core logic, dependency-manager.js for dependency management, ui.js for CLI output formatting, ai-services-unified.js for AI service integration, config-manager.js for configuration management, utils.js for utility functions).
scripts/modules/*.js: Export all core functions, helper functions, and utility methods needed by your new function or command from their respective modules. Explicitly review the module's export block to ensure every required dependency is included.
Pass all required parameters to functions you call within your implementation and verify that direct function parameters match their core function counterparts.
Use consistent file naming conventions: 'task_${id.toString().padStart(3, '0')}.txt', use path.join for composing file paths, and use appropriate file extensions (.txt for tasks, .json for data).
Use structured error objects with code and message properties, include clear error messages, and handle both function-specific and file system errors.
Import all silent mode utilities together from 'scripts/modules/utils.js' and always use isSilentMode() to check global silent mode status. Wrap core function calls within direct functions using enableSilentMode() and disableSilentMode() in a try/finally block if the core function might produce console output.
Core functions should check outputFormat === 'text' before displaying UI elements and use internal logging that respects silent mode.
Design functions to accept dependencies as parameters (dependency injection) and avoid hard-coded dependencies that are difficult to mock.
Keep pure logic separate from I/O operations or UI rendering to allow testing the logic without mocking complex dependencies.
When implementing core logic for new features, do so in 'scripts/modules/' before CLI or MCP interfaces, and d...
Files:
scripts/modules/commands.js
scripts/modules/**
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
When using the MCP server, restart it if core logic in
scripts/modulesor MCP tool/direct function definitions change.
Files:
scripts/modules/commands.js
scripts/modules/*
📄 CodeRabbit inference engine (.cursor/rules/tags.mdc)
scripts/modules/*: Every command that reads or writes tasks.json must be tag-aware
All command files must import getCurrentTag from utils.js
Every CLI command that operates on tasks must include the --tag CLI option
All commands must resolve the tag using the pattern: options.tag || getCurrentTag(projectRoot) || 'master'
All commands must find projectRoot with error handling before proceeding
All commands must pass { projectRoot, tag } as context to core functions
MCP direct functions must accept and use a context object containing projectRoot and tag, and pass them to core functions
Do not hard-code tag resolution (e.g., const tag = options.tag || 'master';); always use getCurrentTag
Do not omit the --tag CLI option in commands that operate on tasks
Do not omit the context parameter when calling core functions from commands
Do not call readJSON or writeJSON without passing projectRoot and tag
Files:
scripts/modules/commands.js
🧠 Learnings (43)
📓 Common learnings
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Integrate version checking in the CLI run function, starting the update check in the background and displaying notifications after command execution.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-08-03T12:13:33.875Z
Learning: Applies to package.json : Add and update test scripts in package.json to include test, test:watch, test:coverage, test:unit, test:integration, test:e2e, and test:ci
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1178
File: packages/tm-core/src/auth/config.ts:5-7
Timestamp: 2025-09-02T21:51:27.921Z
Learning: The user Crunchyman-ralph prefers not to use node: scheme imports (e.g., 'node:os', 'node:path') for Node.js core modules and considers suggestions to change bare imports to node: scheme as too nitpicky.
📚 Learning: 2025-07-18T17:10:02.683Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dev_workflow.mdc:0-0
Timestamp: 2025-07-18T17:10:02.683Z
Learning: Applies to .taskmaster/config.json : Store Taskmaster configuration settings (AI model selections, parameters, logging level, default subtasks/priority, project name, tag management) in `.taskmaster/config.json` in the project root. Do not configure these via environment variables.
Applied to files:
apps/docs/best-practices/configuration-advanced.mdx
📚 Learning: 2025-07-18T17:10:12.881Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dev_workflow.mdc:0-0
Timestamp: 2025-07-18T17:10:12.881Z
Learning: Applies to .taskmaster/config.json : Store Taskmaster configuration settings (AI model selections, parameters, logging level, default subtasks/priority, project name, etc.) in the `.taskmaster/config.json` file located in the project root directory. Do not configure non-API key settings via environment variables.
Applied to files:
apps/docs/best-practices/configuration-advanced.mdx
📚 Learning: 2025-07-31T22:08:16.039Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/taskmaster.mdc:0-0
Timestamp: 2025-07-31T22:08:16.039Z
Learning: Applies to .taskmaster/config.json : All other Taskmaster settings (model choice, max tokens, temperature, log level, custom endpoints) are managed in .taskmaster/config.json via the task-master models command or models MCP tool.
Applied to files:
apps/docs/best-practices/configuration-advanced.mdxscripts/modules/commands.js
📚 Learning: 2025-07-18T17:19:27.365Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-07-18T17:19:27.365Z
Learning: Applies to assets/**/.env : Environment variables such as ANTHROPIC_API_KEY, MODEL, MAX_TOKENS, TEMPERATURE, DEBUG, TASKMASTER_LOG_LEVEL, DEFAULT_SUBTASKS, DEFAULT_PRIORITY, PROJECT_NAME, PROJECT_VERSION, PERPLEXITY_API_KEY, and PERPLEXITY_MODEL must be configured as described.
Applied to files:
apps/docs/best-practices/configuration-advanced.mdx
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to .taskmasterconfig : Use `.taskmasterconfig` (JSON) in the project root for storing Taskmaster configuration (excluding API keys), and manage it via the `task-master models --setup` CLI command or the `models` MCP tool.
Applied to files:
apps/docs/best-practices/configuration-advanced.mdx
📚 Learning: 2025-07-31T22:07:49.716Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Integrate version checking in the CLI run function, starting the update check in the background and displaying notifications after command execution.
Applied to files:
apps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Implement version checking to notify users of available updates, use non-blocking version checks, and display update notifications after command completion.
Applied to files:
apps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-31T22:07:49.716Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Implement semantic version comparison and display attractive update notifications using boxen.
Applied to files:
apps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:54.131Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/telemetry.mdc:0-0
Timestamp: 2025-07-18T17:14:54.131Z
Learning: Applies to scripts/modules/task-manager/**/*.js : If the core logic function handles CLI output (outputFormat === 'text' or 'cli'), and aiServiceResponse.telemetryData is available, it must call displayAiUsageSummary(aiServiceResponse.telemetryData, 'cli') from scripts/modules/ui.js.
Applied to files:
apps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:19:27.365Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-07-18T17:19:27.365Z
Learning: When implementation differs significantly from planned approach, call `node scripts/dev.js update --from=<futureTaskId> --prompt="<explanation>"` to update tasks.json.
Applied to files:
apps/cli/src/utils/auto-update.ts
📚 Learning: 2025-08-07T13:00:22.966Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1090
File: apps/extension/package.json:241-243
Timestamp: 2025-08-07T13:00:22.966Z
Learning: In monorepos, local packages should use "*" as the version constraint in package.json dependencies, as recommended by npm. This ensures the local version from within the same workspace is always used, rather than attempting to resolve from external registries. This applies to packages like task-master-ai within the eyaltoledano/claude-task-master monorepo.
Applied to files:
apps/cli/src/utils/auto-update.ts
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to scripts/modules/task-manager/**/*.js : Do not call AI-specific getters (like `getMainModelId`, `getMainMaxTokens`) from core logic functions in `scripts/modules/task-manager/*`; instead, pass the `role` to the unified AI service.
Applied to files:
apps/cli/src/utils/auto-update.ts
📚 Learning: 2025-07-18T17:10:12.881Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dev_workflow.mdc:0-0
Timestamp: 2025-07-18T17:10:12.881Z
Learning: For CLI usage, install Taskmaster globally with `npm install -g task-master-ai` or use locally via `npx task-master-ai ...`.
Applied to files:
apps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:06:57.833Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-07-18T17:06:57.833Z
Learning: Applies to scripts/modules/task-manager/*.js : Do not implement fallback or retry logic outside `ai-services-unified.js`.
Applied to files:
apps/cli/src/utils/auto-update.ts
📚 Learning: 2025-07-18T17:06:57.833Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-07-18T17:06:57.833Z
Learning: Applies to scripts/modules/task-manager/*.js : Do not import or call anything from the old `ai-services.js`, `ai-client-factory.js`, or `ai-client-utils.js` files.
Applied to files:
apps/cli/src/utils/auto-update.tsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/**/*.test.js : Test CLI and MCP interfaces with real task data, verify end-to-end workflows across tag contexts, and test error scenarios and recovery in integration tests.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Verify modifications on the in-memory task objects passed to writeJSON.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{unit,integration,e2e}/**/*.test.js : Use sample task fixtures for consistent test data, mock file system operations, and test both success and error paths for task operations.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Use AI to generate detailed subtasks within the current tag context, considering complexity analysis for subtask counts and ensuring proper IDs for newly created subtasks.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{unit,integration,e2e}/**/*.test.js : Explicitly handle all options, including defaults and shorthand flags (e.g., -p for --prompt), and include null/undefined checks in test implementations for parameters that might be optional.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/*.js : Minimize file I/O operations per feature execution, cache tag resolution results when appropriate, use streaming for large task datasets, and avoid loading all tags when only one is needed.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/**/*.test.js : Test core logic independently with both data formats, mock file system operations, test tag resolution behavior, and verify migration compatibility in unit tests.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Create self-contained test implementations rather than using real implementations when testing modules with initialization issues.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Do not modify real task files (tasks.json) during tests.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{integration,e2e}/**/*.test.js : Properly mock session objects when required by functions, and reset environment variables between tests if modified.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/unit/**/*.test.js : Do not include actual command execution in unit tests.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Do not rely on environment variables for API keys in tests; set mock environment variables in test setup.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Isolate tests by properly mocking shared resources and resetting state in beforeEach and afterEach hooks.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/*.js : Process large task lists efficiently, clean up temporary data structures, and avoid keeping all tag data in memory simultaneously.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Generate task files from the current tag context, include tag information in generated files, and do not mix tasks from different tags in file generation.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to scripts/modules/utils.js : Implement complete migration for all related files in the tagged task system, handle configuration and state file creation, and provide migration status tracking.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Use consistent formatting for task files, include all task properties in text files, and format dependencies with status indicators.
Applied to files:
tests/integration/cli/complex-cross-tag-scenarios.test.jsscripts/modules/commands.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-21T17:51:07.239Z
Learnt from: joedanz
PR: eyaltoledano/claude-task-master#748
File: scripts/modules/task-manager/parse-prd.js:726-733
Timestamp: 2025-07-21T17:51:07.239Z
Learning: In CLI contexts within task-manager modules like scripts/modules/task-manager/parse-prd.js, using process.exit(1) for validation failures and error conditions is correct and preferred over throwing errors, as it provides immediate termination with appropriate exit codes for scripting. The code should distinguish between MCP contexts (throw errors) and CLI contexts (use process.exit).
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to {scripts/modules/utils.js,mcp-server/src/core/utils/path-utils.js,mcp-server/src/tools/utils.js} : Keep utilities relevant to their location, export all utility functions in a single statement per file, group related exports together, export configuration constants, do not use default exports, and do not create circular dependencies.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/*.js : Export all core functions, helper functions, and utility methods needed by your new function or command from their respective modules. Explicitly review the module's export block to ensure every required dependency is included.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Group related commands together in the code, add related commands in a logical order, and use comments to delineate command groups.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to {scripts/modules/utils.js,mcp-server/src/core/utils/path-utils.js,mcp-server/src/tools/utils.js} : Export all utility functions explicitly, group related functions logically, and include new tagged system utilities.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Applies to scripts/modules/*.js : Each module in scripts/modules/ should be focused on a single responsibility, following the modular architecture (e.g., commands.js for CLI command handling, task-manager.js for task data and core logic, dependency-manager.js for dependency management, ui.js for CLI output formatting, ai-services-unified.js for AI service integration, config-manager.js for configuration management, utils.js for utility functions).
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Group imports by module/functionality, import only what's needed (not entire modules), and do not create circular dependencies.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:06:57.833Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-07-18T17:06:57.833Z
Learning: Applies to scripts/modules/task-manager/*.js : Do not fetch AI-specific parameters (model ID, max tokens, temp) using `config-manager.js` getters for the AI call. Pass the `role` instead.
Applied to files:
scripts/modules/commands.js
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to scripts/modules/config-manager.js : Update scripts/modules/config-manager.js to add the new provider to MODEL_MAP, ensure it is included in VALID_PROVIDERS, and update API key handling logic.
Applied to files:
scripts/modules/commands.js
🧬 Code graph analysis (2)
apps/cli/src/utils/auto-update.ts (1)
apps/cli/src/index.ts (3)
checkForUpdate(18-18)displayUpgradeNotification(20-20)performAutoUpdate(19-19)
scripts/modules/commands.js (2)
src/utils/getVersion.js (1)
getTaskMasterVersion(8-10)apps/cli/src/utils/auto-update.ts (3)
checkForUpdate(63-130)displayUpgradeNotification(135-151)performAutoUpdate(156-238)
🔇 Additional comments (6)
.github/workflows/ci.yml (1)
95-97: Confirm secrets presence and scope for build.Ensure TM_PUBLIC_BASE_DOMAIN, TM_PUBLIC_SUPABASE_URL, TM_PUBLIC_SUPABASE_ANON_KEY exist in repo/org secrets; otherwise the Build step will fail at PRs from forks. Consider fallbacks or conditionals if public PRs run this workflow.
.github/workflows/release.yml (1)
49-51: Verify secrets availability in the release environment.Confirm these secrets are set for the repository and that exposing “PUBLIC” keys in build output is intentional.
.github/workflows/pre-release.yml (1)
78-80: Propagate/public intent check.Same as CI/Release: confirm the three secrets exist and are intended to be embedded in built artifacts.
scripts/modules/commands.js (2)
89-89: Switch to getDefaultNumTasks() looks good.Cleaner default sourcing and aligns with config-manager exposure.
5283-5284: LGTM — matches Biome style.Single‑line grouped export fixes the formatter complaint.
apps/cli/src/utils/auto-update.ts (1)
68-129: HTTP request hardening and graceful fallbacks look good.Status checks, UA header, timeout, and safe “no update” resolution on errors are solid.
| function compareVersions(v1: string, v2: string): number { | ||
| const toParts = (v: string) => { | ||
| const [core, pre = ''] = v.split('-', 2); | ||
| const nums = core.split('.').map((n) => Number.parseInt(n, 10) || 0); | ||
| return { nums, pre }; | ||
| }; | ||
|
|
||
| const a = toParts(v1); | ||
| const b = toParts(v2); | ||
| const len = Math.max(a.nums.length, b.nums.length); | ||
|
|
||
| // Compare numeric parts | ||
| for (let i = 0; i < len; i++) { | ||
| const d = (a.nums[i] || 0) - (b.nums[i] || 0); | ||
| if (d !== 0) return d < 0 ? -1 : 1; | ||
| } | ||
|
|
||
| // Handle pre-release comparison | ||
| if (a.pre && !b.pre) return -1; // prerelease < release | ||
| if (!a.pre && b.pre) return 1; // release > prerelease | ||
| if (a.pre === b.pre) return 0; // same or both empty | ||
| return a.pre < b.pre ? -1 : 1; // basic prerelease tie-break | ||
| } |
There was a problem hiding this comment.
Semver prerelease handling is still incorrect (e.g., rc.10 vs rc.2).
String tiebreak on pre misorders numeric identifiers. Implement semver rules for prerelease identifiers.
Apply this diff:
-function compareVersions(v1: string, v2: string): number {
- const toParts = (v: string) => {
- const [core, pre = ''] = v.split('-', 2);
- const nums = core.split('.').map((n) => Number.parseInt(n, 10) || 0);
- return { nums, pre };
- };
-
- const a = toParts(v1);
- const b = toParts(v2);
- const len = Math.max(a.nums.length, b.nums.length);
-
- // Compare numeric parts
- for (let i = 0; i < len; i++) {
- const d = (a.nums[i] || 0) - (b.nums[i] || 0);
- if (d !== 0) return d < 0 ? -1 : 1;
- }
-
- // Handle pre-release comparison
- if (a.pre && !b.pre) return -1; // prerelease < release
- if (!a.pre && b.pre) return 1; // release > prerelease
- if (a.pre === b.pre) return 0; // same or both empty
- return a.pre < b.pre ? -1 : 1; // basic prerelease tie-break
-}
+function compareVersions(v1: string, v2: string): number {
+ const toParts = (v: string) => {
+ const [core, pre = ''] = v.split('-', 2);
+ const nums = core.split('.').map((n) => Number.parseInt(n, 10) || 0);
+ const preParts = pre ? pre.split('.') : [];
+ return { nums, preParts };
+ };
+ const cmpId = (a: string, b: string): number => {
+ const an = /^\d+$/.test(a) ? Number(a) : NaN;
+ const bn = /^\d+$/.test(b) ? Number(b) : NaN;
+ if (!Number.isNaN(an) && !Number.isNaN(bn)) return an === bn ? 0 : an < bn ? -1 : 1;
+ if (!Number.isNaN(an) && Number.isNaN(bn)) return -1; // numeric < non-numeric
+ if (Number.isNaN(an) && !Number.isNaN(bn)) return 1;
+ return a < b ? -1 : a > b ? 1 : 0;
+ };
+ const a = toParts(v1);
+ const b = toParts(v2);
+ const len = Math.max(a.nums.length, b.nums.length);
+ for (let i = 0; i < len; i++) {
+ const d = (a.nums[i] || 0) - (b.nums[i] || 0);
+ if (d !== 0) return d < 0 ? -1 : 1;
+ }
+ if (a.preParts.length === 0 && b.preParts.length === 0) return 0;
+ if (a.preParts.length === 0) return 1; // release > prerelease
+ if (b.preParts.length === 0) return -1;
+ const plen = Math.max(a.preParts.length, b.preParts.length);
+ for (let i = 0; i < plen; i++) {
+ const ai = a.preParts[i];
+ const bi = b.preParts[i];
+ if (ai === undefined) return -1;
+ if (bi === undefined) return 1;
+ const c = cmpId(ai, bi);
+ if (c !== 0) return c;
+ }
+ return 0;
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function compareVersions(v1: string, v2: string): number { | |
| const toParts = (v: string) => { | |
| const [core, pre = ''] = v.split('-', 2); | |
| const nums = core.split('.').map((n) => Number.parseInt(n, 10) || 0); | |
| return { nums, pre }; | |
| }; | |
| const a = toParts(v1); | |
| const b = toParts(v2); | |
| const len = Math.max(a.nums.length, b.nums.length); | |
| // Compare numeric parts | |
| for (let i = 0; i < len; i++) { | |
| const d = (a.nums[i] || 0) - (b.nums[i] || 0); | |
| if (d !== 0) return d < 0 ? -1 : 1; | |
| } | |
| // Handle pre-release comparison | |
| if (a.pre && !b.pre) return -1; // prerelease < release | |
| if (!a.pre && b.pre) return 1; // release > prerelease | |
| if (a.pre === b.pre) return 0; // same or both empty | |
| return a.pre < b.pre ? -1 : 1; // basic prerelease tie-break | |
| } | |
| function compareVersions(v1: string, v2: string): number { | |
| const toParts = (v: string) => { | |
| const [core, pre = ''] = v.split('-', 2); | |
| const nums = core.split('.').map((n) => Number.parseInt(n, 10) || 0); | |
| const preParts = pre ? pre.split('.') : []; | |
| return { nums, preParts }; | |
| }; | |
| const cmpId = (a: string, b: string): number => { | |
| const an = /^\d+$/.test(a) ? Number(a) : NaN; | |
| const bn = /^\d+$/.test(b) ? Number(b) : NaN; | |
| if (!Number.isNaN(an) && !Number.isNaN(bn)) return an === bn ? 0 : an < bn ? -1 : 1; | |
| if (!Number.isNaN(an) && Number.isNaN(bn)) return -1; // numeric < non-numeric | |
| if (Number.isNaN(an) && !Number.isNaN(bn)) return 1; | |
| return a < b ? -1 : a > b ? 1 : 0; | |
| }; | |
| const a = toParts(v1); | |
| const b = toParts(v2); | |
| const len = Math.max(a.nums.length, b.nums.length); | |
| for (let i = 0; i < len; i++) { | |
| const d = (a.nums[i] || 0) - (b.nums[i] || 0); | |
| if (d !== 0) return d < 0 ? -1 : 1; | |
| } | |
| if (a.preParts.length === 0 && b.preParts.length === 0) return 0; | |
| if (a.preParts.length === 0) return 1; // release > prerelease | |
| if (b.preParts.length === 0) return -1; | |
| const plen = Math.max(a.preParts.length, b.preParts.length); | |
| for (let i = 0; i < plen; i++) { | |
| const ai = a.preParts[i]; | |
| const bi = b.preParts[i]; | |
| if (ai === undefined) return -1; | |
| if (bi === undefined) return 1; | |
| const c = cmpId(ai, bi); | |
| if (c !== 0) return c; | |
| } | |
| return 0; | |
| } |
🤖 Prompt for AI Agents
In apps/cli/src/utils/auto-update.ts around lines 36 to 58, the current
prerelease tie-break uses a simple string compare which misorders identifiers
like rc.10 vs rc.2; replace that logic by splitting a.pre and b.pre on '.' and
comparing identifier-by-identifier: for each pair, if both are numeric compare
numerically; if one is numeric and the other is alphanumeric consider the
numeric identifier lower precedence; if both are non-numeric compare ASCII
lexically; if they are equal continue to the next identifier; if all identifiers
equal then the shorter prerelease has lower precedence; return -1/1/0
accordingly.
| const currentVersion = currentVersionOverride || getCurrentVersion(); | ||
|
|
||
| return new Promise((resolve) => { | ||
| const options = { | ||
| hostname: 'registry.npmjs.org', |
There was a problem hiding this comment.
🧹 Nitpick
Add a fast opt-out for update checks (CI/offline).
Short-circuit to avoid network in CI and when explicitly skipped.
Apply this diff:
- const currentVersion = currentVersionOverride || getCurrentVersion();
+ const currentVersion = currentVersionOverride || getCurrentVersion();
+ if (process.env.TASKMASTER_SKIP_UPDATE_CHECK === '1' || process.env.CI) {
+ return {
+ currentVersion,
+ latestVersion: currentVersion,
+ needsUpdate: false
+ };
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const currentVersion = currentVersionOverride || getCurrentVersion(); | |
| return new Promise((resolve) => { | |
| const options = { | |
| hostname: 'registry.npmjs.org', | |
| const currentVersion = currentVersionOverride || getCurrentVersion(); | |
| if (process.env.TASKMASTER_SKIP_UPDATE_CHECK === '1' || process.env.CI) { | |
| return { | |
| currentVersion, | |
| latestVersion: currentVersion, | |
| needsUpdate: false | |
| }; | |
| } | |
| return new Promise((resolve) => { | |
| const options = { | |
| hostname: 'registry.npmjs.org', |
🤖 Prompt for AI Agents
In apps/cli/src/utils/auto-update.ts around lines 66 to 70, add a fast opt-out
before starting the network call: detect CI/offline by checking environment
flags (e.g. process.env.CI, process.env.SKIP_UPDATE_CHECK, process.env.OFFLINE
or a similarly named env var) and immediately return a resolved Promise when any
are set so the function short-circuits and avoids network access; otherwise
proceed to build the options and continue with the existing Promise-based
request logic.
| return new Promise((resolve) => { | ||
| const updateProcess = spawn( | ||
| 'npm', | ||
| [ | ||
| 'install', | ||
| '-g', | ||
| `task-master-ai@${latestVersion}`, | ||
| '--no-fund', | ||
| '--no-audit', | ||
| '--loglevel=warn' | ||
| ], | ||
| { | ||
| stdio: ['ignore', 'pipe', 'pipe'] | ||
| } | ||
| ); |
There was a problem hiding this comment.
Use the caller’s package manager (npm/pnpm/yarn/bun) and add a max duration to avoid hanging updates.
Spawning hard-coded npm can fail or create split global installs; also no timeout. Detect PM via npm_config_user_agent and enforce a sane max runtime.
Apply this diff:
- return new Promise((resolve) => {
- const updateProcess = spawn(
- 'npm',
- [
- 'install',
- '-g',
- `task-master-ai@${latestVersion}`,
- '--no-fund',
- '--no-audit',
- '--loglevel=warn'
- ],
- {
- stdio: ['ignore', 'pipe', 'pipe']
- }
- );
+ return new Promise((resolve) => {
+ const ua = process.env.npm_config_user_agent || '';
+ let cmd = 'npm';
+ let args: string[] = [];
+ if (ua.includes('pnpm/')) {
+ cmd = 'pnpm';
+ args = ['add', '-g', `task-master-ai@${latestVersion}`, '--silent', '--no-fund'];
+ } else if (ua.includes('yarn/')) {
+ cmd = 'yarn';
+ args = ['global', 'add', `task-master-ai@${latestVersion}`, '--silent', '--no-progress'];
+ } else if (ua.includes('bun/')) {
+ cmd = 'bun';
+ args = ['add', '-g', `task-master-ai@${latestVersion}`];
+ } else {
+ cmd = 'npm';
+ args = ['install', '-g', `task-master-ai@${latestVersion}`, '--no-fund', '--no-audit', '--loglevel=warn'];
+ }
+ const updateProcess = spawn(cmd, args, { stdio: ['ignore', 'pipe', 'pipe'] });
+ const maxMs = Number.parseInt(process.env.TASKMASTER_UPDATE_MAX_MS || '180000', 10);
+ const timeout = setTimeout(() => {
+ try { updateProcess.kill(); } catch {}
+ }, maxMs);
@@
- updateProcess.on('close', (code) => {
+ updateProcess.on('close', (code) => {
+ clearTimeout(timeout);
if (code === 0) {
@@
- resolve(false);
+ resolve(false);
}
});
@@
- updateProcess.on('error', (error) => {
+ updateProcess.on('error', (error) => {
+ clearTimeout(timeout);
spinner.fail(chalk.red('Auto-update failed'));
console.log(chalk.red('Error:'), error.message);Also applies to: 202-237
| - **Optional Auto-Update Control:** | ||
| - `TASKMASTER_SKIP_AUTO_UPDATE`: Set to '1' to disable automatic updates. Also automatically disabled in CI environments (when `CI` environment variable is set). |
There was a problem hiding this comment.
🧹 Nitpick
Clarify skip behavior and document CLI opt-out.
Current code still prints the “Auto‑updating…” box when skipping via TASKMASTER_SKIP_AUTO_UPDATE/CI. Either suppress that message in code (preferred; see my commands.js comment) or clarify docs. Also document a CLI flag for single‑run opt‑out.
Apply this doc tweak:
- - `TASKMASTER_SKIP_AUTO_UPDATE`: Set to '1' to disable automatic updates. Also automatically disabled in CI environments (when `CI` environment variable is set).
+ - `TASKMASTER_SKIP_AUTO_UPDATE`: Set to '1' to disable automatic updates and the update notification. Also automatically disabled in CI environments (when `CI` is set).
+ - CLI opt‑out: pass `--skip-auto-update` to disable for a single run.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - **Optional Auto-Update Control:** | |
| - `TASKMASTER_SKIP_AUTO_UPDATE`: Set to '1' to disable automatic updates. Also automatically disabled in CI environments (when `CI` environment variable is set). | |
| - **Optional Auto-Update Control:** | |
| - `TASKMASTER_SKIP_AUTO_UPDATE`: Set to '1' to disable automatic updates and the update notification. Also automatically disabled in CI environments (when `CI` is set). | |
| - CLI opt-out: pass `--skip-auto-update` to disable for a single run. |
🤖 Prompt for AI Agents
In apps/docs/best-practices/configuration-advanced.mdx around lines 86-87, the
docs imply TASKMASTER_SKIP_AUTO_UPDATE/CI fully disables auto-update behavior
but do not mention that the “Auto‑updating…” UI box may still be printed; update
the text to clarify that setting TASKMASTER_SKIP_AUTO_UPDATE=1 or running in CI
disables background auto-update behavior but may still show the informational
“Auto‑updating…” message unless the code suppresses it, and add a short note
documenting the CLI flag to opt-out of a single-run auto-update (e.g.,
--no-auto-update or equivalent) including its exact flag name and effect; if the
code change to suppress the box is implemented instead, update the docs to state
that the message is suppressed when skipping via env vars.
| const currentVersion = getTaskMasterVersion(); | ||
| const updateCheckPromise = checkForUpdate(currentVersion); | ||
|
|
There was a problem hiding this comment.
🧹 Nitpick
Avoid passing non‑semver overrides to updater.
If getTaskMasterVersion() returns "unknown", forcing it into checkForUpdate can break semver compare. Only pass an override when valid.
-const currentVersion = getTaskMasterVersion();
-const updateCheckPromise = checkForUpdate(currentVersion);
+const currentVersion = getTaskMasterVersion();
+const updateCheckPromise =
+ currentVersion && currentVersion !== 'unknown'
+ ? checkForUpdate(currentVersion)
+ : checkForUpdate();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const currentVersion = getTaskMasterVersion(); | |
| const updateCheckPromise = checkForUpdate(currentVersion); | |
| const currentVersion = getTaskMasterVersion(); | |
| const updateCheckPromise = | |
| currentVersion && currentVersion !== 'unknown' | |
| ? checkForUpdate(currentVersion) | |
| : checkForUpdate(); |
🤖 Prompt for AI Agents
In scripts/modules/commands.js around lines 5136-5138, getTaskMasterVersion()
may return "unknown" and passing that as an override into checkForUpdate can
break semver comparisons; change the call to only pass currentVersion when it is
a valid semver (e.g. use semver.valid(currentVersion) or equivalent check) and
otherwise call checkForUpdate() without an override so the updater uses its
default version detection.
What type of PR is this?
Description
Related Issues
How to Test This
# Example commands or stepsExpected result:
Contributor Checklist
npm run changesetnpm testnpm run format-check(ornpm run formatto fix)Changelog Entry
For Maintainers
Summary by CodeRabbit
New Features
Documentation
Chores
Tests