Skip to content

feat: add auto-update to every command when your task-master instance is out of date#1217

Merged
Crunchyman-ralph merged 5 commits intonextfrom
ralph/feat/auto-update
Sep 18, 2025
Merged

feat: add auto-update to every command when your task-master instance is out of date#1217
Crunchyman-ralph merged 5 commits intonextfrom
ralph/feat/auto-update

Conversation

@Crunchyman-ralph
Copy link
Collaborator

@Crunchyman-ralph Crunchyman-ralph commented Sep 18, 2025

What type of PR is this?

  • 🐛 Bug fix
  • ✨ Feature
  • 🔌 Integration
  • 📝 Docs
  • 🧹 Refactor
  • Other:

Description

Related Issues

How to Test This

# Example commands or steps
  • change root package.json to 0.25.0
  • run any command
  • see it automatically try to update to latest (0.26.0)

Expected result:

Contributor Checklist

  • Created changeset: npm run changeset
  • Tests pass: npm test
  • Format check passes: npm run format-check (or npm run format to fix)
  • Addressed CodeRabbit comments (if any)
  • Linked related issues (if any)
  • Manually tested the changes

Changelog Entry


For Maintainers

  • PR title follows conventional commits
  • Target branch correct
  • Labels added
  • Milestone assigned (if applicable)

Summary by CodeRabbit

  • New Features

    • CLI now checks for updates after each command, notifies when a newer version is available, and can auto-install updates with progress indicators and fallback guidance.
  • Documentation

    • Added docs describing TASKMASTER_SKIP_AUTO_UPDATE to opt out of automatic updates.
  • Chores

    • Added changelog entry for a major release and moved @tm/cli to devDependencies.
    • CI/build workflows updated to include additional environment variables.
  • Tests

    • Tests made deterministic around auto-update (skip flag) and updated imports/timeouts.

@changeset-bot
Copy link

changeset-bot bot commented Sep 18, 2025

🦋 Changeset detected

Latest 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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 18, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Adds 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 @tm/cli to devDependencies, updates tests, CI/workflow env vars, adds a changeset, and updates tsdown watcher config.

Changes

Cohort / File(s) Summary
Release metadata
\.changeset/shiny-regions-teach.md
Adds a changeset declaring a major version bump and noting that the CLI now auto-updates on commands.
CLI public exports
apps/cli/src/index.ts
Re-exports auto-update helpers: checkForUpdate, performAutoUpdate, displayUpgradeNotification. (Additive export change.)
CLI auto-update implementation
apps/cli/src/utils/auto-update.ts
New module with UpdateInfo interface and exported APIs: checkForUpdate(currentVersionOverride?), performAutoUpdate(latestVersion), displayUpgradeNotification(currentVersion, latestVersion); includes registry fetch, version compare, spinner/UI, CI and TASKMASTER_SKIP_AUTO_UPDATE handling, and safe fallbacks.
Command runner refactor
scripts/modules/commands.js
Removed local update helpers and local compare; imports checkForUpdate, performAutoUpdate, displayUpgradeNotification from @tm/cli; starts background update check after commands, notifies and may auto-update; reduced public exports to registerCommands, setupCLI, runCLI.
Package manifest
package.json
Moves @tm/cli from dependencies to devDependencies.
Tests adjusted
tests/unit/commands.test.js, tests/integration/cli/complex-cross-tag-scenarios.test.js
Unit tests now source compare/display utilities from the new auto-update module and introduce a local compareVersions; integration tests set TASKMASTER_SKIP_AUTO_UPDATE='1' in hooks and increase a timeout (CI: 11000ms, non-CI: 6000ms).
Tooling config
tsdown.config.ts
Adds ignoreWatch: ['node_modules', 'dist', 'tests'] to tsdown config.
CI / release workflows
.github/workflows/*.yml
Adds TM_PUBLIC_BASE_DOMAIN, TM_PUBLIC_SUPABASE_URL, TM_PUBLIC_SUPABASE_ANON_KEY env vars to build steps; minor quoting/formatting tweak in release.yml.
Docs
apps/docs/best-practices/configuration-advanced.mdx
Documents TASKMASTER_SKIP_AUTO_UPDATE environment variable to disable automatic updates (honored in CI).

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • eyaltoledano

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title accurately and concisely summarizes the primary change — adding automatic update behavior to commands when a task-master instance is out of date. It is a single clear sentence that uses a conventional commit prefix and avoids noisy file lists or emojis. The wording maps directly to the changes in the PR (new auto-update utilities and integration into command flow), so a reviewer scanning history will understand the main intent.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6640c0a and cdb417b.

📒 Files selected for processing (1)
  • tests/integration/cli/complex-cross-tag-scenarios.test.js (3 hunks)

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between cf3339f and 5af4e22.

⛔ Files ignored due to path filters (1)
  • package-lock.json is 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 running npm run changeset or npx changeset add, provide a concise summary of the changes for the CHANGELOG.md in 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 through generateTextService or generateObjectService.
Do not import or call anything from the old ai-services.js, ai-client-factory.js, or ai-client-utils.js files.
Do not fetch AI-specific parameters (model ID, max tokens, temp) using config-manager.js getters for the AI call. Pass the role instead.
Do not implement fallback or retry logic outside ai-services-unified.js.
Do not handle API key resolution outside the service layer (it uses utils.js internally).
Determine the appropriate role (main, research, fallback) in your core logic and pass it to the service.
Pass the session object (received in the context parameter, especially from direct function wrappers) to the service call when in MCP context.
Use generateTextService and implement robust manual JSON parsing (with Zod validation after parsing) when structured output is needed, as generateObjectService has shown unreliability with some providers/schemas.
Be aware of potential reliability issues with generateObjectService across different providers and complex schemas. Prefer generateTextService + 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/modules or 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.md
  • apps/cli/src/utils/auto-update.ts
  • scripts/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.md
  • apps/cli/src/utils/auto-update.ts
  • scripts/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.md
  • apps/cli/src/utils/auto-update.ts
  • scripts/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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 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.

Suggested change
@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.

Comment on lines 19 to 31
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';
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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": "*",
Copy link
Contributor

@coderabbitai coderabbitai bot Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 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' || true

Length 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"
fi

Length 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.

Copy link
Collaborator Author

@Crunchyman-ralph Crunchyman-ralph Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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 ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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!

Comment on lines 5148 to 5153
// Automatically perform the update
const updateSuccess = await performAutoUpdate(updateInfo.latestVersion);
if (updateSuccess) {
// Exit gracefully after successful update
process.exit(0);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-update option 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

📥 Commits

Reviewing files that changed from the base of the PR and between 5af4e22 and 5fc762a.

📒 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.js
  • tests/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.js
  • tests/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.js
  • tests/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.js
  • tests/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.js
  • tests/unit/commands.test.js
  • scripts/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/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.js
  • tests/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 through generateTextService or generateObjectService.
Do not import or call anything from the old ai-services.js, ai-client-factory.js, or ai-client-utils.js files.
Do not fetch AI-specific parameters (model ID, max tokens, temp) using config-manager.js getters for the AI call. Pass the role instead.
Do not implement fallback or retry logic outside ai-services-unified.js.
Do not handle API key resolution outside the service layer (it uses utils.js internally).
Determine the appropriate role (main, research, fallback) in your core logic and pass it to the service.
Pass the session object (received in the context parameter, especially from direct function wrappers) to the service call when in MCP context.
Use generateTextService and implement robust manual JSON parsing (with Zod validation after parsing) when structured output is needed, as generateObjectService has shown unreliability with some providers/schemas.
Be aware of potential reliability issues with generateObjectService across different providers and complex schemas. Prefer generateTextService + 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/modules or 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.ts
  • tests/unit/commands.test.js
  • apps/cli/src/utils/auto-update.ts
  • 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/**/*.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.js
  • apps/cli/src/utils/auto-update.ts
  • scripts/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.js
  • apps/cli/src/utils/auto-update.ts
  • scripts/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.js
  • apps/cli/src/utils/auto-update.ts
  • scripts/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.ts
  • 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 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 default

Verified: 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.

Comment on lines +16 to +21
// Auto-update utilities
export {
checkForUpdate,
performAutoUpdate,
displayUpgradeNotification
} from './utils/auto-update.js';
Copy link
Contributor

@coderabbitai coderabbitai bot Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 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.

Suggested change
// 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).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CodeRabbit, nitpick, won't do

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Comment on lines +24 to 28
SetStatusCommand,
checkForUpdate,
performAutoUpdate,
displayUpgradeNotification
} from '@tm/cli';
Copy link
Contributor

@coderabbitai coderabbitai bot Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 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).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CodeRabbit doesn't need to be a runtime dependency since all bundled at build time

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 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.

Comment on lines 323 to 327
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;
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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
};
});

Copy link
Collaborator Author

@Crunchyman-ralph Crunchyman-ralph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self-reviewed, thanks coderabbit!

Comment on lines +16 to +21
// Auto-update utilities
export {
checkForUpdate,
performAutoUpdate,
displayUpgradeNotification
} from './utils/auto-update.js';
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CodeRabbit, nitpick, won't do

@Crunchyman-ralph Crunchyman-ralph merged commit e6de285 into next Sep 18, 2025
8 of 9 checks passed
@Crunchyman-ralph Crunchyman-ralph deleted the ralph/feat/auto-update branch September 18, 2025 16:35
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 minimum

Repo 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

📥 Commits

Reviewing files that changed from the base of the PR and between 5fc762a and 6640c0a.

📒 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.js
  • scripts/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 through generateTextService or generateObjectService.
Do not import or call anything from the old ai-services.js, ai-client-factory.js, or ai-client-utils.js files.
Do not fetch AI-specific parameters (model ID, max tokens, temp) using config-manager.js getters for the AI call. Pass the role instead.
Do not implement fallback or retry logic outside ai-services-unified.js.
Do not handle API key resolution outside the service layer (it uses utils.js internally).
Determine the appropriate role (main, research, fallback) in your core logic and pass it to the service.
Pass the session object (received in the context parameter, especially from direct function wrappers) to the service call when in MCP context.
Use generateTextService and implement robust manual JSON parsing (with Zod validation after parsing) when structured output is needed, as generateObjectService has shown unreliability with some providers/schemas.
Be aware of potential reliability issues with generateObjectService across different providers and complex schemas. Prefer generateTextService + 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/modules or 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.mdx
  • scripts/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.ts
  • 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 : 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.ts
  • scripts/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.ts
  • 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:

  • apps/cli/src/utils/auto-update.ts
  • scripts/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.ts
  • 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 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.ts
  • 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/**/*.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.js
  • 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-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.

Comment on lines +36 to +58
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
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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.

Comment on lines +66 to +70
const currentVersion = currentVersionOverride || getCurrentVersion();

return new Promise((resolve) => {
const options = {
hostname: 'registry.npmjs.org',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 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.

Suggested change
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.

Comment on lines +173 to +187
return new Promise((resolve) => {
const updateProcess = spawn(
'npm',
[
'install',
'-g',
`task-master-ai@${latestVersion}`,
'--no-fund',
'--no-audit',
'--loglevel=warn'
],
{
stdio: ['ignore', 'pipe', 'pipe']
}
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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

Comment on lines +86 to +87
- **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).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 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.

Suggested change
- **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.

Comment on lines +5136 to 5138
const currentVersion = getTaskMasterVersion();
const updateCheckPromise = checkForUpdate(currentVersion);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 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.

Suggested change
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant