Skip to content

fix(auth): enforce org selection post-login and remove duplicate messages#1475

Merged
Crunchyman-ralph merged 7 commits intonextfrom
mfa-fix-2
Dec 2, 2025
Merged

fix(auth): enforce org selection post-login and remove duplicate messages#1475
Crunchyman-ralph merged 7 commits intonextfrom
mfa-fix-2

Conversation

@eyaltoledano
Copy link
Owner

@eyaltoledano eyaltoledano commented Dec 2, 2025

Summary

Enforces organization selection after login across all CLI commands that require authentication, and removes duplicate 'Authentication successful!' messages.

Changes

  • Add ensureOrgSelected to auth-guard.ts for all auth flows (existing & new sessions)
  • Add ensureOrgSelected to parse-prd flow in commands.js (after authentication)
  • Add ensureOrgSelected to init.js cloud storage flow (using shared utility)
  • Remove duplicate 'Authentication successful!' boxen messages
  • Export authenticateWithBrowserMFA and ensureOrgSelected from @tm/cli utils
  • init.js now uses shared authenticateWithBrowserMFA instead of custom OAuth flow
  • auth-guard.ts now checks context.orgId before making API calls (optimization)

Fixes

  • Org selection now happens after login in parse-prd, init, and export commands
  • Single source of truth for browser auth with MFA support
  • Removed redundant auth UI code from init.js

Known Issues (needs investigation)

  • tm init and tm export may hang after completion
  • Root cause: Supabase client's autoRefreshToken: true keeps Node.js event loop alive
  • tm auth login works fine (uses different flow via setupContextInteractive)
  • Proper fix: add cleanup method to SupabaseAuthClient to stop auto-refresh timer

Testing

  • tm auth login - works, sets org properly
  • tm parse-prd - org selection works (may auto-select if only one org)
  • tm export - auth + org works, but may hang after completion
  • tm init (cloud) - auth + org works, but may hang after completion

Summary by CodeRabbit

  • New Features

    • Added organization selection requirement during authentication workflows to ensure proper context configuration.
  • Bug Fixes

    • Improved error handling for team invitation responses to support multiple API response formats and better detect "already member" scenarios.
  • Refactor

    • Streamlined authentication flow with centralized multi-factor authentication handling.
    • Updated success messaging to log user identity instead of displaying a separate success notification.

✏️ Tip: You can customize this high-level summary in your review settings.

- Create shared authenticateWithBrowserMFA utility in auth-ui.ts
- Update auth.command.ts to use shared utility for tm auth login
- Update auth-guard.ts to use shared utility for parse-prd/export
- Fix oauth-service.ts to NOT call onError for MFA_REQUIRED
  (MFA requirement is a continuation, not a failure)

All login paths now use the same MFA-aware browser auth flow:
- tm auth login
- tm parse-prd (Bring it to Hamster)
- tm export
The sendTeamInvitations function was treating 200 OK responses as errors
because it expected a 'success' field that the API doesn't always return.

- Check for invitations array in response body as success indicator
- Handle various response structures (invitations, data.invitations, data)
- Only treat as error when response is not OK or has explicit error field
…ess messages

CHANGES:
- Add ensureOrgSelected to auth-guard.ts for all auth flows (existing & new sessions)
- Add ensureOrgSelected to parse-prd flow in commands.js (after authentication) -- NOT WORKING.
- Add ensureOrgSelected to init.js cloud storage flow (using shared utility)
- Remove duplicate 'Authentication successful!' boxen messages (auth.command.ts, auth-guard.ts)
- Export authenticateWithBrowserMFA and ensureOrgSelected from @tm/cli utils
- init.js now uses shared authenticateWithBrowserMFA instead of custom OAuth flow
- auth-guard.ts now checks context.orgId before making API calls (optimization)

FIXES:
- Org selection now happens after login in parse-prd, init, and export commands
- Single source of truth for browser auth with MFA support
- Removed redundant auth UI code from init.js

KNOWN ISSUES:
- tm init and tm export may hang after completion (Supabase auto-refresh timer)
- Root cause: AuthManager/Supabase client keeps event loop alive
- tm auth login works because it uses setupContextInteractive from ContextCommand
- Proper fix would be to add cleanup method to SupabaseAuthClient to stop auto-refresh
- Workaround (process.exit) was attempted but reverted as too dirty

The hanging issue requires further investigation into how auth login handles
cleanup vs how ensureAuthenticated/ensureOrgSelected interact with Supabase.
@changeset-bot
Copy link

changeset-bot bot commented Dec 2, 2025

⚠️ No Changeset found

Latest commit: ff601e1

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 2, 2025

Walkthrough

This PR centralizes and refactors browser-based OAuth/MFA authentication flows across the CLI by introducing authenticateWithBrowserMFA as a unified handler with integrated MFA support and countdown timer management. It also adds ensureOrgSelected utility with a new forceSelection option to enforce organization context. Multiple commands and initialization scripts are updated to use these centralized utilities, removing custom auth orchestration. The export service also broadens response handling to support multiple API response shapes, and OAuth service error handling excludes MFA_REQUIRED from the onError callback.

Changes

Cohort / File(s) Summary
CLI Authentication Refactoring
apps/cli/src/commands/auth.command.ts, apps/cli/src/utils/auth-guard.ts
Replaces custom browser-auth countdown/MFA flows with centralized authenticateWithBrowserMFA; removes internal timer management and callback structures; integrates ensureOrgSelected for post-auth org context validation; org selection failures now mark auth as successful while returning error state
MFA/OAuth Flow Framework
apps/cli/src/utils/auth-ui.ts
Introduces new BrowserAuthProvider interface and authenticateWithBrowserMFA public function with integrated browser launching, status displays, countdown timer, and MFA retry via handleMFAFlow; changes MFA_REQUIRED error handling to trigger unified MFA flow instead of generic failure; adds OAuthFlowOptions type support
Organization Selection Enhancement
apps/cli/src/utils/org-selection.ts
Adds optional forceSelection boolean to EnsureOrgOptions to bypass cached org context; enhances UX by appending " (current)" label to selected org and setting default selection based on context; changes AuthManager import to type-only
Export & Integration Updates
apps/cli/src/commands/export.command.ts, packages/tm-core/src/modules/integration/services/export.service.ts
Export command adds forced organization selection step after tag selection; export service broadens response handling to support multiple response shapes (data/invitations/direct fields), implements "already member" detection, and improves error message extraction; normalizes invitation objects with defaults
OAuth Service Error Handling
packages/tm-core/src/modules/auth/services/oauth-service.ts
MFA_REQUIRED errors no longer invoke onError callback; MFA remains part of continuation flow instead of treated as generic error
CLI Command & Script Updates
scripts/init.js, scripts/modules/commands.js
Replaces custom OAuth/timeout spinner logic with authenticateWithBrowserMFA and ensureOrgSelected; adds forced org selection in PRD-parsing flows; simplifies auth messaging and removes countdown/ora-based UX
Public API Surface
apps/cli/src/utils/index.ts
Exports new authenticateWithBrowserMFA, ensureOrgSelected, and OrgSelectionResult types

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI Command
    participant AuthUI as authenticateWithBrowserMFA
    participant Browser as Browser/OAuth
    participant MFA as MFA Handler
    participant OrgSel as ensureOrgSelected
    participant AuthMgr as AuthManager

    CLI->>AuthUI: Initiate auth flow
    AuthUI->>Browser: Open browser + show countdown
    Browser->>Browser: User authenticates
    alt MFA Required
        Browser-->>AuthUI: MFA_REQUIRED error
        AuthUI->>MFA: handleMFAFlow
        MFA->>Browser: Prompt for MFA
        Browser->>MFA: MFA verified
        MFA-->>AuthUI: Auth credentials
    else No MFA
        Browser-->>AuthUI: Auth credentials
    end
    AuthUI->>AuthMgr: Return credentials
    AuthUI-->>CLI: Success
    
    CLI->>OrgSel: Ensure org selected
    OrgSel->>AuthMgr: Check current org context
    alt Org not set or forceSelection
        OrgSel->>Browser: Prompt for org selection
        Browser-->>OrgSel: User selection
        OrgSel->>AuthMgr: Set org context
    end
    OrgSel-->>CLI: Success/Error
    
    CLI->>CLI: Proceed with authenticated context
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • auth-ui.ts: New BrowserAuthProvider interface and authenticateWithBrowserMFA function with integrated timer management and MFA flow orchestration—requires verification of countdown stop states ('mfa') and callback wiring
  • export.service.ts: Response handling rewrite supporting multiple API response shapes, "already member" detection logic, and robust error extraction—needs careful validation of all code paths
  • org-selection.ts: forceSelection option logic and UX label/default selection changes—verify prompt behavior and context fallback paths
  • oauth-service.ts: MFA_REQUIRED error callback exclusion is subtle but critical for proper MFA flow continuation—ensure no unintended side effects
  • Cross-file integration: Multiple files call authenticateWithBrowserMFA and ensureOrgSelected; verify correct usage patterns and error handling across auth.command.ts, auth-guard.ts, init.js, and commands.js

Possibly related PRs

Suggested reviewers

  • eyaltoledano
  • maxtuzz

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 directly summarizes the main changes: enforcing org selection after login and removing duplicate authentication messages, which are the primary objectives of the PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mfa-fix-2

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

CHANGES:
- Add forcePrompt option to ensureOrgSelected utility
- When forcePrompt=true, always fetch orgs and prompt (if >1 org exists)
- Pre-select current org in dropdown when forcePrompt is used
- Show '(current)' label next to currently selected org in prompt

PARSE-PRD:
- Force org selection after authentication (forcePrompt: true)
- User can choose which org to create the brief in
- Auto-selects if only one org available

EXPORT:
- Force org selection after tag selection (forcePrompt: true)
- User can choose which org to export to
- Auto-selects if only one org available

INIT:
- Removed process.exit(0) hack that was incorrectly added

This ensures users explicitly choose (or confirm) their target organization
before creating briefs, preventing accidental exports to wrong orgs.
…ger type

CHANGES:
- Rename forcePrompt option to forceSelection in EnsureOrgOptions interface
- Update all call sites in export.command.ts and commands.js
- Fix AuthManager type in export.command.ts by importing from @tm/core
- Replace dirty (this.taskMasterCore.auth as any).authManager hack with AuthManager.getInstance()
- Use type import for AuthManager in org-selection.ts
@Crunchyman-ralph Crunchyman-ralph marked this pull request as ready for review December 2, 2025 17:36
@Crunchyman-ralph Crunchyman-ralph changed the base branch from main to next December 2, 2025 17:36
@Crunchyman-ralph Crunchyman-ralph changed the base branch from next to main December 2, 2025 17:36
Copy link
Collaborator

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

lgtm

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: 0

🧹 Nitpick comments (6)
packages/tm-core/src/modules/integration/services/export.service.ts (1)

1537-1631: Flexible invitation response handling looks solid; consider tightening success/error precedence.

The new logic correctly tolerates multiple JSON shapes (root invitations, nested data.invitations, or bare arrays) and normalizes statuses while treating “already member” as a success, which should make the CLI much more resilient.

One nuance: the success branch returns success: true whenever response.ok and invitations is an array, even if the payload also contains an error object describing partial or global failures. If the backend ever sends { invitations: [...], error: {...} } on a 200 for partial failures, that error would be ignored. If you need stricter semantics, you could check for jsonData.error (or a success flag) before short‑circuiting to the success path, and only treat it as full success when there’s no top‑level error. Otherwise this implementation is fine and a clear improvement over the previous strict shape.

scripts/modules/commands.js (1)

66-67: Consolidate @tm/cli imports for readability (optional).

You now import from @tm/cli in two separate statements (one for command registry utilities and one for checkAndBlockIfAuthenticated / ensureOrgSelected). It’s functionally fine, but grouping these into a single import from @tm/cli would make the top of the file a bit easier to scan.

apps/cli/src/commands/export.command.ts (1)

32-32: Interactive export now correctly enforces org selection before creating briefs.

Using AuthManager.getInstance() plus ensureOrgSelected with forceSelection: true in the interactive tag-selection path ensures the user explicitly decides which org to export to, even if a default org is already set in context. That behavior is aligned with the PR’s goal of enforcing org selection after login.

One minor UX nuance: when ensureAuthenticated has already prompted for org selection in the same command (for users with no org set), this additional forced selection can result in a second org prompt in multi-org scenarios. If that feels noisy in practice, you could gate this second call on a flag (e.g., only when the user wants to override the current org) while still keeping the current behavior as the default.

Also applies to: 339-355

apps/cli/src/utils/auth-guard.ts (1)

6-16: New MFA + org-selection auth guard flow is coherent; note credentials behavior for existing sessions.

The refactor to use authenticateWithBrowserMFA plus AuthManager.getInstance() and ensureOrgSelected is a good consolidation:

  • Existing sessions: you now short‑circuit on hasValidSession(), but still enforce org selection when context.orgId is missing, returning authenticated: true even if org selection fails (with error populated). That matches the idea that the user is logged in but not yet “org‑ready”.
  • New logins: the shared browser/MFA flow handles all UX and then you immediately force org selection, again returning authenticated: true with an error if the user bails on org choice.

One behavioral nuance: for already‑authenticated users you no longer populate credentials on the success path (only the fresh login path returns them). If any callers previously relied on result.credentials when a session already existed, they’ll now see undefined. If that’s not used anywhere, the current shape is fine; otherwise, you may want to fetch and return credentials in the hasSession branch as well.

Also applies to: 69-165

apps/cli/src/utils/org-selection.ts (1)

88-106: Consider: Auto-select still occurs when forceSelection=true with single org.

When a user explicitly requests forceSelection: true, they may expect to see the selection prompt even with a single org. Currently, single-org accounts will auto-select regardless of forceSelection. If this is intentional for UX simplicity, consider documenting this behavior in the JSDoc.

apps/cli/src/utils/auth-ui.ts (1)

344-348: Consider adding a clearer comment on the intentionally empty onError callback.

While the comment explains that the timer is stopped in the catch block, future maintainers might wonder if this is a bug. A more explicit comment would help:

-			// Don't handle onError here - we need to check error type in catch block
-			// to differentiate between MFA_REQUIRED (not a failure) and actual failures
-			onError: () => {
-				// Timer will be stopped in catch block with appropriate status
-			}
+			// Intentionally empty: error handling is deferred to the catch block
+			// because MFA_REQUIRED is not a failure and should stop the timer with 'mfa'
+			// status, while actual errors should stop with 'failure' status.
+			onError: () => {}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e5ca6f5 and ff601e1.

📒 Files selected for processing (10)
  • apps/cli/src/commands/auth.command.ts (4 hunks)
  • apps/cli/src/commands/export.command.ts (4 hunks)
  • apps/cli/src/utils/auth-guard.ts (3 hunks)
  • apps/cli/src/utils/auth-ui.ts (2 hunks)
  • apps/cli/src/utils/index.ts (1 hunks)
  • apps/cli/src/utils/org-selection.ts (5 hunks)
  • packages/tm-core/src/modules/auth/services/oauth-service.ts (1 hunks)
  • packages/tm-core/src/modules/integration/services/export.service.ts (2 hunks)
  • scripts/init.js (4 hunks)
  • scripts/modules/commands.js (3 hunks)
🧰 Additional context used
📓 Path-based instructions (15)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)

TypeScript test files must achieve minimum code coverage thresholds: 80% lines/functions and 70% branches globally, 90% for utilities, and 85% for middleware; new features must meet or exceed these thresholds

Files:

  • apps/cli/src/commands/export.command.ts
  • apps/cli/src/utils/index.ts
  • packages/tm-core/src/modules/auth/services/oauth-service.ts
  • apps/cli/src/commands/auth.command.ts
  • apps/cli/src/utils/org-selection.ts
  • packages/tm-core/src/modules/integration/services/export.service.ts
  • apps/cli/src/utils/auth-ui.ts
  • apps/cli/src/utils/auth-guard.ts
**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)

**/*.{js,ts}: Import and use specific getters from config-manager.js (e.g., getMainProvider(), getLogLevel(), getMainMaxTokens()) to access configuration values needed for application logic
Use isApiKeySet(providerName, session) from config-manager.js to check if a provider's key is available before potentially attempting an AI call
Do not add direct console.log calls outside the logging utility - use the central log function instead
Ensure silent mode is disabled in a finally block to prevent it from staying enabled
Do not access the global silentMode variable directly - use the exported silent mode control functions instead
Do not duplicate task ID formatting logic across modules - centralize formatting utilities
Use ContextGatherer class from utils/contextGatherer.js for AI-powered commands that need project context, supporting tasks, files, custom text, and project tree context
Use FuzzyTaskSearch class from utils/fuzzyTaskSearch.js for automatic task relevance detection with configurable search parameters
Use fuzzy search to supplement user-provided task IDs and display discovered task IDs to users for transparency
Do not replace explicit user task selections with fuzzy results - fuzzy search should supplement, not replace user selections
Use readJSON and writeJSON utilities for all JSON file operations instead of raw fs.readFileSync or fs.writeFileSync
Include error handling for JSON file operations and validate JSON structure after reading
Use path.join() for cross-platform path construction and path.resolve() for absolute paths, validating paths before file operations
Support both .env files and MCP session environment for environment variable resolution with fallbacks for missing values
Prefer updating the core function to accept an outputFormat parameter and check outputFormat === 'json' before displaying UI elements

Files:

  • apps/cli/src/commands/export.command.ts
  • apps/cli/src/utils/index.ts
  • scripts/init.js
  • scripts/modules/commands.js
  • packages/tm-core/src/modules/auth/services/oauth-service.ts
  • apps/cli/src/commands/auth.command.ts
  • apps/cli/src/utils/org-selection.ts
  • packages/tm-core/src/modules/integration/services/export.service.ts
  • apps/cli/src/utils/auth-ui.ts
  • apps/cli/src/utils/auth-guard.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Import modules with .js extension even in TypeScript source files for ESM compatibility

Files:

  • apps/cli/src/commands/export.command.ts
  • apps/cli/src/utils/index.ts
  • packages/tm-core/src/modules/auth/services/oauth-service.ts
  • apps/cli/src/commands/auth.command.ts
  • apps/cli/src/utils/org-selection.ts
  • packages/tm-core/src/modules/integration/services/export.service.ts
  • apps/cli/src/utils/auth-ui.ts
  • apps/cli/src/utils/auth-guard.ts
apps/cli/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

CLI (@tm/cli) should be a thin presentation layer that calls tm-core methods and displays results; handle only CLI-specific concerns like argument parsing, output formatting, and user prompts

Files:

  • apps/cli/src/commands/export.command.ts
  • apps/cli/src/utils/index.ts
  • apps/cli/src/commands/auth.command.ts
  • apps/cli/src/utils/org-selection.ts
  • apps/cli/src/utils/auth-ui.ts
  • apps/cli/src/utils/auth-guard.ts
**/{utils,utilities,helpers}/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)

**/{utils,utilities,helpers}/**/*.{js,ts}: Document all parameters and return values in JSDoc format, include descriptions for complex logic, and add examples for non-obvious usage
Support multiple log levels (debug, info, warn, error) with appropriate icons for different log levels and respect the configured log level

Files:

  • apps/cli/src/utils/index.ts
  • apps/cli/src/utils/org-selection.ts
  • apps/cli/src/utils/auth-ui.ts
  • apps/cli/src/utils/auth-guard.ts
**/{utils,utilities}/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)

Implement the silent mode control functions (enableSilentMode, disableSilentMode, isSilentMode) in utility modules and always use isSilentMode() to check current state

Files:

  • apps/cli/src/utils/index.ts
  • apps/cli/src/utils/org-selection.ts
  • apps/cli/src/utils/auth-ui.ts
  • apps/cli/src/utils/auth-guard.ts
**/{utils,utilities}/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)

**/{utils,utilities}/**/*.{js,ts}: Use try/catch blocks for all file operations and return null or a default value on failure rather than allowing exceptions to propagate unhandled
Log detailed error information using the log utility in catch blocks for file operations
Create utilities for consistent task ID handling that support different ID formats (numeric, string, dot notation)
Implement reusable task finding utilities that support both task and subtask lookups and add context to subtask results
Implement cycle detection using graph traversal by tracking visited nodes and recursion stack, returning specific information about cycles
Detect circular dependencies using DFS and validate task references before operations
Export all utility functions explicitly in logical groups and include configuration constants from utility modules
Do not use default exports in utility modules - use named exports only
Group related exports together in utility modules and avoid creating circular dependencies
Make the log function respect silent mode by skipping logging when silent mode is enabled

Files:

  • apps/cli/src/utils/index.ts
  • apps/cli/src/utils/org-selection.ts
  • apps/cli/src/utils/auth-ui.ts
  • apps/cli/src/utils/auth-guard.ts
**/*.js

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

**/*.js: Always use isSilentMode() function to check current silent mode status instead of directly accessing the global silentMode variable or global.silentMode
Use try/finally block pattern when wrapping core function calls with enableSilentMode/disableSilentMode to ensure silent mode is always restored, even if errors occur
For functions that need to handle both a passed silentMode parameter and check global state, check both the function parameter and global state: const isSilent = options.silentMode || (typeof options.silentMode === 'undefined' && isSilentMode())
Functions should accept their dependencies as parameters rather than using globals to promote testability and explicit dependency injection
Define callbacks as separate functions for easier testing rather than inline functions

Files:

  • scripts/init.js
  • scripts/modules/commands.js
scripts/init.js

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

init.js should create necessary directories and files for new projects, set up tasks.json with tagged structure, configure project metadata, initialize state.json for tag system, handle shell alias creation, and support both interactive and non-interactive modes

Files:

  • scripts/init.js
scripts/**/*.js

📄 CodeRabbit inference engine (.cursor/rules/context_gathering.mdc)

scripts/**/*.js: Use the ContextGatherer class from scripts/modules/utils/contextGatherer.js to extract context from multiple sources (tasks, files, custom text, project tree) with token counting using gpt-tokens library
Initialize ContextGatherer with project root and tasks path, then call gather() method with tasks array, files array, customContext, includeProjectTree, format ('research', 'chat', or 'system-prompt'), and includeTokenCounts options
Use the FuzzyTaskSearch class from scripts/modules/utils/fuzzyTaskSearch.js for intelligent task discovery with semantic matching, purpose categorization, and relevance scoring using Fuse.js
Implement a three-step initialization pattern for context-aware commands: (1) validate and parse parameters, (2) initialize context gatherer and find project root, (3) auto-discover relevant tasks using fuzzy search if task IDs not specified
Display token breakdown using boxen library with sections for tasks, files, and prompts, showing formatted token counts and file sizes in a clean bordered box with title
Process AI result responses using cli-highlight library to apply syntax highlighting to code blocks with language detection in the format language\ncode
Set reasonable file size limits (50KB default) and project tree depth limits (3-5 levels) when gathering context to maintain performance
Implement graceful error handling for context gathering: handle missing files with warnings, validate task IDs with helpful messages, continue processing if some context sources fail, and provide fallback behavior

Files:

  • scripts/init.js
  • scripts/modules/commands.js
**/*.{js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)

JavaScript test files using Jest must follow the same testing patterns as TypeScript files, include proper mocking of external dependencies, and achieve the same coverage thresholds

Files:

  • scripts/init.js
  • scripts/modules/commands.js
scripts/modules/commands.js

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

commands.js should parse command-line arguments and options, invoke appropriate core logic functions from scripts/modules/, handle user input/output for CLI, and implement CLI-specific validation

scripts/modules/commands.js: Follow the basic command template structure when implementing CLI commands: use .command(), .description(), .option(), and .action() in Commander.js with concise action handlers that extract functionality to core modules
Keep command action handlers concise and focused; extract core functionality to appropriate modules like task-manager.js or init.js rather than implementing business logic in handlers
Use kebab-case for command names (e.g., 'analyze-complexity', 'remove-task') and action-oriented descriptions
Use kebab-case for long-form option names (e.g., --output-format) with single-letter shortcuts when appropriate (e.g., -f, --file), and access them in code as camelCase properties (e.g., options.numTasks)
Use positive flags with --skip- prefix for disabling behavior instead of --no- prefix negated flags; use clear variable naming like const generateFiles = !options.skipGenerate to avoid double negatives
Include confirmation prompts by default for destructive operations (delete/remove commands) with a --yes or -y flag to skip confirmation; display what will be deleted in the confirmation message
For file path handling in destructive operations: use path.join() to construct paths, follow naming conventions (e.g., task_001.txt), check file existence before deletion, and handle errors gracefully without string concatenation
Clean up references to deleted items in other parts of the data after destructive operations, handling both direct and indirect references with explanatory console logging
Regenerate task files after destructive operations by explicitly passing all required parameters to generation functions; provide a --skip-generate option if needed
Suggest non-destructive alternatives (like status changes instead of deletion)...

Files:

  • scripts/modules/commands.js
scripts/modules/**/*

📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)

Restart the MCP server if core logic in scripts/modules or MCP tool definitions change

Files:

  • scripts/modules/commands.js
scripts/modules/*.js

📄 CodeRabbit inference engine (.cursor/rules/mcp.mdc)

When implementing MCP support for a command, ensure the core logic function can suppress console output via an outputFormat parameter or other mechanism

scripts/modules/*.js: Use consistent file naming conventions: task_${id.toString().padStart(3, '0')}.txt for task files; use path.join() for composing paths; use appropriate extensions (.txt for tasks, .json for data)
Export all core functions, helper functions, and utility methods needed by dependent code from their respective modules; explicitly verify module export blocks at the bottom of files
Use structured error objects with code and message properties; include clear error messages; handle both function-specific and file system errors; log errors at appropriate severity levels
Use isSilentMode() function to check global silent mode status; wrap core function calls within direct functions using enableSilentMode() and disableSilentMode() in try/finally blocks if the core function produces console output not reliably controlled by outputFormat parameter
Ensure AI calls correctly handle and propagate telemetryData as described in telemetry.mdc
Import context gathering utilities (ContextGatherer, FuzzyTaskSearch) for AI-powered commands; support multiple context types (tasks, files, custom text, project tree); implement detailed token breakdown display
Prefer generateTextService for calls sending large context (like stringified JSON) where incremental display is not needed; import necessary service functions from ai-services-unified.js and prepare parameters (role, session, systemPrompt, prompt)
Create a clear unidirectional flow of dependencies between modules; separate business logic from UI rendering to avoid circular dependencies
Design functions to accept dependencies as parameters; avoid hard-coded dependencies that are difficult to mock
Keep pure logic separate from I/O operations or UI rendering to allow testing logic without mocking complex dependencies
Design core logic to work wi...

Files:

  • scripts/modules/commands.js
scripts/modules/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)

scripts/modules/**/*.{js,ts}: Implement silent migration for tasks.json files that transforms old format to tagged format, marking global flag and performing complete migration
Implement tag resolution functions (getTasksForTag, setTasksForTag, getCurrentTag) that provide backward compatibility with legacy format and default to master tag
Implement complete migration functions for tagged task lists that handle configuration, state file creation, and migration status tracking
When a logger object is passed as a parameter to core functions, ensure the receiving function can call methods like .info, .warn, .error on that object

Files:

  • scripts/modules/commands.js
🧠 Learnings (41)
📚 Learning: 2025-10-08T19:57:00.982Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1282
File: packages/tm-core/src/utils/index.ts:16-34
Timestamp: 2025-10-08T19:57:00.982Z
Learning: For the tm-core package in the eyaltoledano/claude-task-master repository, the team prefers a minimal, need-based export strategy in index files rather than exposing all internal utilities. Exports should only be added when functions are actually consumed by other packages in the monorepo.

Applied to files:

  • apps/cli/src/commands/export.command.ts
  • apps/cli/src/utils/index.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to mcp-server/src/tools/**/*.{js,ts} : Use the withNormalizedProjectRoot Higher-Order Function to wrap tool execute methods, ensuring normalized project root is injected into args

Applied to files:

  • apps/cli/src/commands/export.command.ts
📚 Learning: 2025-11-24T18:02:36.388Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-11-24T18:02:36.388Z
Learning: Applies to scripts/modules/task-manager.js : Extract tasks from PRD documents using AI within the current tag context (defaulting to "master"), providing clear prompts to guide AI task generation and validating/cleaning up AI-generated tasks

Applied to files:

  • apps/cli/src/commands/export.command.ts
  • scripts/modules/commands.js
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/task-manager.js : task-manager.js should handle reading/writing tasks.json with tagged task lists support, implement CRUD operations, delegate AI interactions to ai-services-unified.js layer, and access non-AI configuration via config-manager.js getters

Applied to files:

  • apps/cli/src/commands/export.command.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to scripts/modules/task-manager/**/*.{js,ts} : 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/commands/export.command.ts
📚 Learning: 2025-11-24T17:57:31.417Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-11-24T17:57:31.417Z
Learning: Applies to scripts/modules/task-manager/*.js, scripts/modules/commands.js : Determine the appropriate `role` (`main`, `research`, `fallback`) in core logic and pass it to the AI service call

Applied to files:

  • apps/cli/src/commands/export.command.ts
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : For context-aware AI commands: use ContextGatherer utility for multi-source context extraction, support task IDs/file paths/custom context, implement fuzzy search for task discovery, and display detailed token breakdown for transparency

Applied to files:

  • apps/cli/src/commands/export.command.ts
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : For AI-powered commands that benefit from project context, use the ContextGatherer utility for multi-source context extraction, support task IDs, file paths, custom context, and project tree, implement fuzzy search for automatic task discovery, and display detailed token breakdown for transparency.

Applied to files:

  • apps/cli/src/commands/export.command.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Export all utility functions explicitly in logical groups and include configuration constants from utility modules

Applied to files:

  • apps/cli/src/utils/index.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Group related exports together in utility modules and avoid creating circular dependencies

Applied to files:

  • apps/cli/src/utils/index.ts
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Applies to **/{utils,utilities}/**/*.{js,ts} : Do not use default exports in utility modules - use named exports only

Applied to files:

  • apps/cli/src/utils/index.ts
📚 Learning: 2025-11-24T17:59:00.056Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/context_gathering.mdc:0-0
Timestamp: 2025-11-24T17:59:00.056Z
Learning: Applies to scripts/modules/utils/{contextGatherer,fuzzyTaskSearch}.js : Export utility modules using named exports: `ContextGatherer`, `createContextGatherer` from contextGatherer.js and `FuzzyTaskSearch`, `PURPOSE_CATEGORIES`, `RELEVANCE_THRESHOLDS` from fuzzyTaskSearch.js

Applied to files:

  • apps/cli/src/utils/index.ts
📚 Learning: 2025-11-24T17:57:31.417Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-11-24T17:57:31.417Z
Learning: Applies to scripts/modules/task-manager/*.js, scripts/modules/commands.js, scripts/modules/ai-services-unified.js : Do not import or call anything from deprecated AI service files (`ai-services.js`, `ai-client-factory.js`, `ai-client-utils.js`)

Applied to files:

  • scripts/init.js
📚 Learning: 2025-11-24T17:58:47.030Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-11-24T17:58:47.030Z
Learning: Applies to scripts/modules/commands.js : Organize imports by module/functionality, import only what's needed (not entire modules), and avoid creating circular dependencies

Applied to files:

  • scripts/init.js
  • scripts/modules/commands.js
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/ui.js : ui.js should handle CLI output formatting including tables, colors, boxes, spinners, and display tasks, reports, progress, suggestions, and migration notices

Applied to files:

  • scripts/init.js
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: The Task Master CLI uses a modular architecture with distinct modules responsible for different aspects: commands.js (CLI command handling), task-manager.js (task data & core logic), dependency-manager.js (dependency management), ui.js (output formatting), ai-services-unified.js (unified AI service layer), config-manager.js (configuration management), utils.js (core utility functions), and mcp-server/ (MCP interface)

Applied to files:

  • scripts/init.js
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to apps/cli/src/**/*.{ts,tsx} : CLI (tm/cli) should be a thin presentation layer that calls tm-core methods and displays results; handle only CLI-specific concerns like argument parsing, output formatting, and user prompts

Applied to files:

  • scripts/init.js
📚 Learning: 2025-11-24T22:09:45.455Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T22:09:45.455Z
Learning: Applies to apps/cli/**/*.{spec,test}.ts : In unit tests for apps/cli, mock tm-core responses but use real Commander/chalk/inquirer/other npm packages to test display logic

Applied to files:

  • scripts/init.js
📚 Learning: 2025-11-24T18:04:01.629Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/ui.mdc:0-0
Timestamp: 2025-11-24T18:04:01.629Z
Learning: Applies to scripts/modules/ui.js : Follow the standard display pattern for UI functions: use documented JSDoc comments describing the function's purpose, parameters, and display a task object with consistent formatting using boxen and chalk

Applied to files:

  • scripts/init.js
📚 Learning: 2025-11-24T18:04:01.629Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/ui.mdc:0-0
Timestamp: 2025-11-24T18:04:01.629Z
Learning: Applies to scripts/modules/ui.js : Provide next step suggestions after command completion using a consistent format with a boxen container displaying suggested commands using chalk formatting

Applied to files:

  • scripts/init.js
  • scripts/modules/commands.js
📚 Learning: 2025-11-24T18:04:01.629Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/ui.mdc:0-0
Timestamp: 2025-11-24T18:04:01.629Z
Learning: Applies to scripts/modules/ui.js : Use chalk.blue for informational messages, chalk.green for success messages, chalk.yellow for warnings, chalk.red for errors, chalk.cyan for prompts and highlights, and chalk.magenta for subtask-related information

Applied to files:

  • scripts/init.js
📚 Learning: 2025-11-24T18:04:43.972Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-24T18:04:43.972Z
Learning: Place utilities used primarily by the core task-master CLI logic and command modules into scripts/modules/utils.js

Applied to files:

  • scripts/init.js
📚 Learning: 2025-11-24T18:02:49.782Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/telemetry.mdc:0-0
Timestamp: 2025-11-24T18:02:49.782Z
Learning: Applies to scripts/modules/task-manager/**/*.js : Core logic functions with outputFormat parameter must check if outputFormat === 'text' and call displayAiUsageSummary(aiServiceResponse.telemetryData, 'cli') from scripts/modules/ui.js when applicable

Applied to files:

  • scripts/init.js
📚 Learning: 2025-11-24T18:04:01.629Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/ui.mdc:0-0
Timestamp: 2025-11-24T18:04:01.629Z
Learning: Applies to scripts/modules/ui.js : Use cli-highlight library for syntax highlighting code blocks in terminal output, with support for multiple programming languages and graceful fallback to plain text if highlighting fails

Applied to files:

  • scripts/init.js
📚 Learning: 2025-12-01T20:55:21.598Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/hamster.mdc:0-0
Timestamp: 2025-12-01T20:55:21.598Z
Learning: Reconnect to Hamster brief context using `tm context <brief url>` when commands stop working or authentication fails

Applied to files:

  • scripts/init.js
📚 Learning: 2025-11-24T18:01:44.169Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-11-24T18:01:44.169Z
Learning: Applies to scripts/modules/commands.js : All new user-facing commands should be added to `commands.js` following Commander.js patterns for subcommand structure and consistent option naming

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-20T01:35:05.831Z
Learnt from: rtmcrc
Repo: eyaltoledano/claude-task-master PR: 933
File: scripts/modules/task-manager/parse-prd.js:226-226
Timestamp: 2025-07-20T01:35:05.831Z
Learning: The parsePRD function in scripts/modules/task-manager/parse-prd.js has a different parameter structure than other task-manager functions - it uses `options` parameter instead of `context` parameter because it generates tasks from PRD documents rather than operating on existing tasks.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 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.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for existing dependencies to prevent duplicates

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-11-24T17:59:18.662Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-11-24T17:59:18.662Z
Learning: Applies to scripts/modules/dependency-manager.js : Validate that referenced tasks exist before adding dependencies and provide clear error messages for non-existent dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Validate that referenced tasks exist before adding dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-11-24T17:58:07.992Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-11-24T17:58:07.992Z
Learning: Applies to scripts/modules/dependency-manager.js : dependency-manager.js should manage task dependencies by handling add/remove/validate/fix operations across tagged task contexts

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-11-24T17:59:18.662Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-11-24T17:59:18.662Z
Learning: Applies to scripts/modules/dependency-manager.js : Prevent tasks from depending on themselves, handling both direct and indirect self-dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Remove references to non-existent tasks during validation

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Prevent tasks from depending on themselves

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:08:48.695Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Validate file existence for critical file operations, provide context-specific validation for identifiers, and check required API keys for features that depend on them.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-11-24T17:59:18.662Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-11-24T17:59:18.662Z
Learning: Applies to scripts/modules/dependency-manager.js : Format task and dependency IDs consistently, check for existing dependencies to prevent duplicates, and sort dependencies for better readability when adding dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Check if the dependency exists before removing

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-11-24T18:02:22.305Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/taskmaster.mdc:0-0
Timestamp: 2025-11-24T18:02:22.305Z
Learning: After project initialization with 'init', parse a PRD using parse_prd before attempting any other operations, as no task files will exist until then

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-11-24T18:05:02.114Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: assets/.windsurfrules:0-0
Timestamp: 2025-11-24T18:05:02.114Z
Learning: Start new projects with `task-master init` or `task-master parse-prd --input=<prd-file.txt>` to generate initial tasks.json

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-11-24T18:00:32.617Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/glossary.mdc:0-0
Timestamp: 2025-11-24T18:00:32.617Z
Learning: Refer to commands.mdc for guidelines on implementing CLI commands using Commander.js

Applied to files:

  • apps/cli/src/commands/auth.command.ts
🧬 Code graph analysis (6)
apps/cli/src/commands/export.command.ts (3)
packages/tm-core/src/modules/auth/managers/auth-manager.ts (1)
  • AuthManager (34-384)
packages/tm-core/src/index.ts (1)
  • AuthManager (154-154)
apps/cli/src/utils/org-selection.ts (1)
  • ensureOrgSelected (56-159)
scripts/init.js (4)
apps/cli/src/utils/index.ts (2)
  • authenticateWithBrowserMFA (24-24)
  • ensureOrgSelected (27-27)
scripts/modules/ui.js (1)
  • authManager (87-87)
apps/cli/src/utils/org-selection.ts (1)
  • ensureOrgSelected (56-159)
src/ui/confirm.js (4)
  • inquirer (37-37)
  • inquirer (38-45)
  • inquirer (87-87)
  • inquirer (88-96)
scripts/modules/commands.js (3)
scripts/init.js (2)
  • orgResult (445-447)
  • authManager (414-414)
apps/cli/src/utils/org-selection.ts (1)
  • ensureOrgSelected (56-159)
apps/cli/src/utils/index.ts (1)
  • ensureOrgSelected (27-27)
packages/tm-core/src/modules/auth/services/oauth-service.ts (1)
apps/extension/src/utils/errorHandler.ts (1)
  • onError (372-374)
apps/cli/src/commands/auth.command.ts (3)
packages/tm-core/src/modules/auth/types.ts (1)
  • AuthCredentials (5-14)
apps/cli/src/utils/index.ts (1)
  • authenticateWithBrowserMFA (24-24)
apps/cli/src/utils/auth-ui.ts (1)
  • authenticateWithBrowserMFA (315-379)
apps/cli/src/utils/auth-ui.ts (1)
scripts/modules/commands.js (1)
  • open (264-264)
🔇 Additional comments (21)
packages/tm-core/src/modules/auth/services/oauth-service.ts (1)

117-121: MFA_REQUIRED exclusion from onError is correct; verify all callers handle thrown MFA properly

Treating MFA_REQUIRED as a non-error here aligns with keeping MFA as part of the normal auth continuation, while still surfacing genuinely fatal cases like MFA_REQUIRED_INCOMPLETE via onError. The rethrow preserves the ability for higher layers to branch on authError.code.

Please verify that all OAuthService.authenticate callers which provide onError are written to handle MFA_REQUIRED via the thrown AuthenticationError rather than relying on onError. A focused test asserting that onError is not called for MFA_REQUIRED but is for MFA_REQUIRED_INCOMPLETE would lock this behavior in.

apps/cli/src/utils/index.ts (1)

23-28: New auth/org-selection exports are appropriate and consistent.

Re‑exporting authenticateWithBrowserMFA and ensureOrgSelected through the utilities index cleanly centralizes the CLI surface and aligns with how other helpers are exposed. No issues from a dependency or API standpoint.

scripts/modules/commands.js (2)

206-206: Prompt copy change is fine and improves readability.

Appending a newline in the promptHamsterCollaboration question string is harmless and slightly improves spacing in the interactive prompt.


386-401: Org selection enforcement in PRD→Hamster flow matches the new auth model.

Injecting ensureOrgSelected(AuthManager.getInstance(), { promptMessage, forceSelection: true }) after auth, but before PRD reading and brief creation, correctly enforces that the user explicitly picks an organization for where the brief will live—even if one is already in context. The early return with a clear error message when orgResult.success is false keeps the flow safe and predictable.

Given ensureOrgSelected already handles the “single org, auto-select” case, this looks like the right level of strictness for this path.

apps/cli/src/commands/export.command.ts (1)

994-1003: Switching setContextToBrief to use AuthManager.getInstance() is consistent with the CLI’s shared auth context.

Using the global AuthManager singleton for selectBriefFromInput keeps context updates (org + brief context) in the same shared auth manager used elsewhere in the CLI, rather than relying on whatever this.taskMasterCore.auth happens to expose. This should reduce subtle differences between commands that set context via core vs. via CLI utilities.

apps/cli/src/utils/org-selection.ts (4)

6-6: LGTM: Type-only import is correct for ESM compatibility.

Using import type for AuthManager follows TypeScript best practices when only the type is needed at compile time.


30-31: LGTM: New forceSelection option is well-documented.

The option is properly typed as optional boolean with clear JSDoc describing its purpose.


65-73: LGTM: Early return logic correctly respects forceSelection.

The condition properly checks both context?.orgId and !forceSelection to skip prompting when appropriate.


113-127: LGTM: Default selection and current-org indicator enhance UX.

The logic correctly:

  1. Finds the current org's index for defaulting
  2. Falls back to index 0 if not found (line 127)
  3. Adds "(current)" suffix for visual clarity
scripts/init.js (4)

20-21: LGTM: Imports correctly use shared utilities from @tm/cli.

The imports consolidate authentication logic by using authenticateWithBrowserMFA and ensureOrgSelected from the shared utils, while AuthManager is properly imported from @tm/core.


422-436: LGTM: Authentication now uses the shared MFA-enabled flow.

Replacing the custom OAuth orchestration with authenticateWithBrowserMFA(authManager) eliminates code duplication and ensures consistent auth UX across all CLI entry points.


748-754: LGTM: Updated UX copy improves clarity.

The header and question text changes provide clearer guidance for users during storage selection.


441-450: Org selection failure should fall back to local storage mode, not allow cloud storage to proceed.

The init script currently logs only a warning when ensureOrgSelected fails, allowing cloud storage mode to continue without org context. This is inconsistent with how auth failures are handled (line 451-458), which explicitly sets selectedStorage = 'local' as a fallback. Consider applying the same pattern here: if org selection fails, set selectedStorage = 'local' to prevent downstream operations from attempting cloud storage without required org context.

apps/cli/src/utils/auth-ui.ts (4)

14-19: LGTM: Imports properly extended for MFA flow support.

Added imports for MFA_MAX_ATTEMPTS, OAuthFlowOptions type, and open for browser launching are all necessary for the new authenticateWithBrowserMFA function.


85-99: LGTM: stop() method correctly handles the new 'mfa' state.

The third state ('mfa') appropriately stops the spinner without displaying success/failure, since MFA is an intermediate step, not a terminal outcome.


272-291: LGTM: BrowserAuthProvider interface enables dependency injection.

The interface properly abstracts the auth provider, allowing both AuthManager and AuthDomain to be used interchangeably. The verifyMFAWithRetry signature matches the expected contract.


352-378: LGTM: Error handling correctly differentiates MFA requirement from failures.

The catch block properly:

  1. Checks for MFA_REQUIRED before showing failure
  2. Stops the timer with 'mfa' status for MFA flow
  3. Validates factorId presence before proceeding
  4. Falls through to 'failure' for actual errors
  5. Uses finally for guaranteed cleanup
apps/cli/src/commands/auth.command.ts (4)

15-15: LGTM: Import consolidation aligns with centralized auth flow.

Importing authenticateWithBrowserMFA and handleMFAFlow from the shared auth-ui.js utility ensures consistent auth UX and eliminates code duplication.


430-433: LGTM: Comment accurately reflects the removal of duplicate success message.

The success message is now displayed by authenticateWithBrowserMFA, so this code correctly only shows the user info.


493-497: LGTM: Clean delegation to shared auth utility.

The authenticateWithBrowser method is now a simple one-liner that delegates to the centralized authenticateWithBrowserMFA, ensuring consistent behavior across all auth entry points.


572-575: LGTM: Token auth comment correctly updated.

The comment aligns with the code behavior where the spinner's succeed() call at line 508 displays the success message.

@Crunchyman-ralph Crunchyman-ralph changed the base branch from main to next December 2, 2025 18:45
@Crunchyman-ralph Crunchyman-ralph merged commit c9a2f84 into next Dec 2, 2025
11 checks passed
github-actions bot added a commit that referenced this pull request Dec 2, 2025
  This PR was automatically generated to update documentation based on recent changes.

  Original commit: Merge pull request #1475 from eyaltoledano/mfa-fix-2\n\n\n

  Co-authored-by: Claude <claude-assistant@anthropic.com>
sfc-gh-dflippo pushed a commit to sfc-gh-dflippo/task-master-ai that referenced this pull request Dec 4, 2025
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.

2 participants