This is page 3 of 38. Use http://codebase.md/eyaltoledano/claude-task-master?lines=false&page={x} to view the full context. # Directory Structure ``` ├── .changeset │ ├── config.json │ └── README.md ├── .claude │ ├── agents │ │ ├── task-checker.md │ │ ├── task-executor.md │ │ └── task-orchestrator.md │ ├── commands │ │ ├── dedupe.md │ │ └── tm │ │ ├── add-dependency │ │ │ └── add-dependency.md │ │ ├── add-subtask │ │ │ ├── add-subtask.md │ │ │ └── convert-task-to-subtask.md │ │ ├── add-task │ │ │ └── add-task.md │ │ ├── analyze-complexity │ │ │ └── analyze-complexity.md │ │ ├── complexity-report │ │ │ └── complexity-report.md │ │ ├── expand │ │ │ ├── expand-all-tasks.md │ │ │ └── expand-task.md │ │ ├── fix-dependencies │ │ │ └── fix-dependencies.md │ │ ├── generate │ │ │ └── generate-tasks.md │ │ ├── help.md │ │ ├── init │ │ │ ├── init-project-quick.md │ │ │ └── init-project.md │ │ ├── learn.md │ │ ├── list │ │ │ ├── list-tasks-by-status.md │ │ │ ├── list-tasks-with-subtasks.md │ │ │ └── list-tasks.md │ │ ├── models │ │ │ ├── setup-models.md │ │ │ └── view-models.md │ │ ├── next │ │ │ └── next-task.md │ │ ├── parse-prd │ │ │ ├── parse-prd-with-research.md │ │ │ └── parse-prd.md │ │ ├── remove-dependency │ │ │ └── remove-dependency.md │ │ ├── remove-subtask │ │ │ └── remove-subtask.md │ │ ├── remove-subtasks │ │ │ ├── remove-all-subtasks.md │ │ │ └── remove-subtasks.md │ │ ├── remove-task │ │ │ └── remove-task.md │ │ ├── set-status │ │ │ ├── to-cancelled.md │ │ │ ├── to-deferred.md │ │ │ ├── to-done.md │ │ │ ├── to-in-progress.md │ │ │ ├── to-pending.md │ │ │ └── to-review.md │ │ ├── setup │ │ │ ├── install-taskmaster.md │ │ │ └── quick-install-taskmaster.md │ │ ├── show │ │ │ └── show-task.md │ │ ├── status │ │ │ └── project-status.md │ │ ├── sync-readme │ │ │ └── sync-readme.md │ │ ├── tm-main.md │ │ ├── update │ │ │ ├── update-single-task.md │ │ │ ├── update-task.md │ │ │ └── update-tasks-from-id.md │ │ ├── utils │ │ │ └── analyze-project.md │ │ ├── validate-dependencies │ │ │ └── validate-dependencies.md │ │ └── workflows │ │ ├── auto-implement-tasks.md │ │ ├── command-pipeline.md │ │ └── smart-workflow.md │ └── TM_COMMANDS_GUIDE.md ├── .coderabbit.yaml ├── .cursor │ ├── mcp.json │ └── rules │ ├── ai_providers.mdc │ ├── ai_services.mdc │ ├── architecture.mdc │ ├── changeset.mdc │ ├── commands.mdc │ ├── context_gathering.mdc │ ├── cursor_rules.mdc │ ├── dependencies.mdc │ ├── dev_workflow.mdc │ ├── git_workflow.mdc │ ├── glossary.mdc │ ├── mcp.mdc │ ├── new_features.mdc │ ├── self_improve.mdc │ ├── tags.mdc │ ├── taskmaster.mdc │ ├── tasks.mdc │ ├── telemetry.mdc │ ├── test_workflow.mdc │ ├── tests.mdc │ ├── ui.mdc │ └── utilities.mdc ├── .cursorignore ├── .env.example ├── .github │ ├── ISSUE_TEMPLATE │ │ ├── bug_report.md │ │ ├── enhancements---feature-requests.md │ │ └── feedback.md │ ├── PULL_REQUEST_TEMPLATE │ │ ├── bugfix.md │ │ ├── config.yml │ │ ├── feature.md │ │ └── integration.md │ ├── PULL_REQUEST_TEMPLATE.md │ ├── scripts │ │ ├── auto-close-duplicates.mjs │ │ ├── backfill-duplicate-comments.mjs │ │ ├── check-pre-release-mode.mjs │ │ ├── parse-metrics.mjs │ │ ├── release.mjs │ │ ├── tag-extension.mjs │ │ └── utils.mjs │ └── workflows │ ├── auto-close-duplicates.yml │ ├── backfill-duplicate-comments.yml │ ├── ci.yml │ ├── claude-dedupe-issues.yml │ ├── claude-docs-trigger.yml │ ├── claude-docs-updater.yml │ ├── claude-issue-triage.yml │ ├── claude.yml │ ├── extension-ci.yml │ ├── extension-release.yml │ ├── log-issue-events.yml │ ├── pre-release.yml │ ├── release-check.yml │ ├── release.yml │ ├── update-models-md.yml │ └── weekly-metrics-discord.yml ├── .gitignore ├── .kiro │ ├── hooks │ │ ├── tm-code-change-task-tracker.kiro.hook │ │ ├── tm-complexity-analyzer.kiro.hook │ │ ├── tm-daily-standup-assistant.kiro.hook │ │ ├── tm-git-commit-task-linker.kiro.hook │ │ ├── tm-pr-readiness-checker.kiro.hook │ │ ├── tm-task-dependency-auto-progression.kiro.hook │ │ └── tm-test-success-task-completer.kiro.hook │ ├── settings │ │ └── mcp.json │ └── steering │ ├── dev_workflow.md │ ├── kiro_rules.md │ ├── self_improve.md │ ├── taskmaster_hooks_workflow.md │ └── taskmaster.md ├── .manypkg.json ├── .mcp.json ├── .npmignore ├── .nvmrc ├── .taskmaster │ ├── CLAUDE.md │ ├── config.json │ ├── docs │ │ ├── MIGRATION-ROADMAP.md │ │ ├── prd-tm-start.txt │ │ ├── prd.txt │ │ ├── README.md │ │ ├── research │ │ │ ├── 2025-06-14_how-can-i-improve-the-scope-up-and-scope-down-comm.md │ │ │ ├── 2025-06-14_should-i-be-using-any-specific-libraries-for-this.md │ │ │ ├── 2025-06-14_test-save-functionality.md │ │ │ ├── 2025-06-14_test-the-fix-for-duplicate-saves-final-test.md │ │ │ └── 2025-08-01_do-we-need-to-add-new-commands-or-can-we-just-weap.md │ │ ├── task-template-importing-prd.txt │ │ ├── test-prd.txt │ │ └── tm-core-phase-1.txt │ ├── reports │ │ ├── task-complexity-report_cc-kiro-hooks.json │ │ ├── task-complexity-report_test-prd-tag.json │ │ ├── task-complexity-report_tm-core-phase-1.json │ │ ├── task-complexity-report.json │ │ └── tm-core-complexity.json │ ├── state.json │ ├── tasks │ │ ├── task_001_tm-start.txt │ │ ├── task_002_tm-start.txt │ │ ├── task_003_tm-start.txt │ │ ├── task_004_tm-start.txt │ │ ├── task_007_tm-start.txt │ │ └── tasks.json │ └── templates │ └── example_prd.txt ├── .vscode │ ├── extensions.json │ └── settings.json ├── apps │ ├── cli │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ │ ├── commands │ │ │ │ ├── auth.command.ts │ │ │ │ ├── context.command.ts │ │ │ │ ├── list.command.ts │ │ │ │ ├── set-status.command.ts │ │ │ │ ├── show.command.ts │ │ │ │ └── start.command.ts │ │ │ ├── index.ts │ │ │ ├── ui │ │ │ │ ├── components │ │ │ │ │ ├── dashboard.component.ts │ │ │ │ │ ├── header.component.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── next-task.component.ts │ │ │ │ │ ├── suggested-steps.component.ts │ │ │ │ │ └── task-detail.component.ts │ │ │ │ └── index.ts │ │ │ └── utils │ │ │ ├── auto-update.ts │ │ │ └── ui.ts │ │ └── tsconfig.json │ ├── docs │ │ ├── archive │ │ │ ├── ai-client-utils-example.mdx │ │ │ ├── ai-development-workflow.mdx │ │ │ ├── command-reference.mdx │ │ │ ├── configuration.mdx │ │ │ ├── cursor-setup.mdx │ │ │ ├── examples.mdx │ │ │ └── Installation.mdx │ │ ├── best-practices │ │ │ ├── advanced-tasks.mdx │ │ │ ├── configuration-advanced.mdx │ │ │ └── index.mdx │ │ ├── capabilities │ │ │ ├── cli-root-commands.mdx │ │ │ ├── index.mdx │ │ │ ├── mcp.mdx │ │ │ └── task-structure.mdx │ │ ├── CHANGELOG.md │ │ ├── docs.json │ │ ├── favicon.svg │ │ ├── getting-started │ │ │ ├── contribute.mdx │ │ │ ├── faq.mdx │ │ │ └── quick-start │ │ │ ├── configuration-quick.mdx │ │ │ ├── execute-quick.mdx │ │ │ ├── installation.mdx │ │ │ ├── moving-forward.mdx │ │ │ ├── prd-quick.mdx │ │ │ ├── quick-start.mdx │ │ │ ├── requirements.mdx │ │ │ ├── rules-quick.mdx │ │ │ └── tasks-quick.mdx │ │ ├── introduction.mdx │ │ ├── licensing.md │ │ ├── logo │ │ │ ├── dark.svg │ │ │ ├── light.svg │ │ │ └── task-master-logo.png │ │ ├── package.json │ │ ├── README.md │ │ ├── style.css │ │ ├── vercel.json │ │ └── whats-new.mdx │ └── extension │ ├── .vscodeignore │ ├── assets │ │ ├── banner.png │ │ ├── icon-dark.svg │ │ ├── icon-light.svg │ │ ├── icon.png │ │ ├── screenshots │ │ │ ├── kanban-board.png │ │ │ └── task-details.png │ │ └── sidebar-icon.svg │ ├── CHANGELOG.md │ ├── components.json │ ├── docs │ │ ├── extension-CI-setup.md │ │ └── extension-development-guide.md │ ├── esbuild.js │ ├── LICENSE │ ├── package.json │ ├── package.mjs │ ├── package.publish.json │ ├── README.md │ ├── src │ │ ├── components │ │ │ ├── ConfigView.tsx │ │ │ ├── constants.ts │ │ │ ├── TaskDetails │ │ │ │ ├── AIActionsSection.tsx │ │ │ │ ├── DetailsSection.tsx │ │ │ │ ├── PriorityBadge.tsx │ │ │ │ ├── SubtasksSection.tsx │ │ │ │ ├── TaskMetadataSidebar.tsx │ │ │ │ └── useTaskDetails.ts │ │ │ ├── TaskDetailsView.tsx │ │ │ ├── TaskMasterLogo.tsx │ │ │ └── ui │ │ │ ├── badge.tsx │ │ │ ├── breadcrumb.tsx │ │ │ ├── button.tsx │ │ │ ├── card.tsx │ │ │ ├── collapsible.tsx │ │ │ ├── CollapsibleSection.tsx │ │ │ ├── dropdown-menu.tsx │ │ │ ├── label.tsx │ │ │ ├── scroll-area.tsx │ │ │ ├── separator.tsx │ │ │ ├── shadcn-io │ │ │ │ └── kanban │ │ │ │ └── index.tsx │ │ │ └── textarea.tsx │ │ ├── extension.ts │ │ ├── index.ts │ │ ├── lib │ │ │ └── utils.ts │ │ ├── services │ │ │ ├── config-service.ts │ │ │ ├── error-handler.ts │ │ │ ├── notification-preferences.ts │ │ │ ├── polling-service.ts │ │ │ ├── polling-strategies.ts │ │ │ ├── sidebar-webview-manager.ts │ │ │ ├── task-repository.ts │ │ │ ├── terminal-manager.ts │ │ │ └── webview-manager.ts │ │ ├── test │ │ │ └── extension.test.ts │ │ ├── utils │ │ │ ├── configManager.ts │ │ │ ├── connectionManager.ts │ │ │ ├── errorHandler.ts │ │ │ ├── event-emitter.ts │ │ │ ├── logger.ts │ │ │ ├── mcpClient.ts │ │ │ ├── notificationPreferences.ts │ │ │ └── task-master-api │ │ │ ├── cache │ │ │ │ └── cache-manager.ts │ │ │ ├── index.ts │ │ │ ├── mcp-client.ts │ │ │ ├── transformers │ │ │ │ └── task-transformer.ts │ │ │ └── types │ │ │ └── index.ts │ │ └── webview │ │ ├── App.tsx │ │ ├── components │ │ │ ├── AppContent.tsx │ │ │ ├── EmptyState.tsx │ │ │ ├── ErrorBoundary.tsx │ │ │ ├── PollingStatus.tsx │ │ │ ├── PriorityBadge.tsx │ │ │ ├── SidebarView.tsx │ │ │ ├── TagDropdown.tsx │ │ │ ├── TaskCard.tsx │ │ │ ├── TaskEditModal.tsx │ │ │ ├── TaskMasterKanban.tsx │ │ │ ├── ToastContainer.tsx │ │ │ └── ToastNotification.tsx │ │ ├── constants │ │ │ └── index.ts │ │ ├── contexts │ │ │ └── VSCodeContext.tsx │ │ ├── hooks │ │ │ ├── useTaskQueries.ts │ │ │ ├── useVSCodeMessages.ts │ │ │ └── useWebviewHeight.ts │ │ ├── index.css │ │ ├── index.tsx │ │ ├── providers │ │ │ └── QueryProvider.tsx │ │ ├── reducers │ │ │ └── appReducer.ts │ │ ├── sidebar.tsx │ │ ├── types │ │ │ └── index.ts │ │ └── utils │ │ ├── logger.ts │ │ └── toast.ts │ └── tsconfig.json ├── assets │ ├── .windsurfrules │ ├── AGENTS.md │ ├── claude │ │ ├── agents │ │ │ ├── task-checker.md │ │ │ ├── task-executor.md │ │ │ └── task-orchestrator.md │ │ ├── commands │ │ │ └── tm │ │ │ ├── add-dependency │ │ │ │ └── add-dependency.md │ │ │ ├── add-subtask │ │ │ │ ├── add-subtask.md │ │ │ │ └── convert-task-to-subtask.md │ │ │ ├── add-task │ │ │ │ └── add-task.md │ │ │ ├── analyze-complexity │ │ │ │ └── analyze-complexity.md │ │ │ ├── clear-subtasks │ │ │ │ ├── clear-all-subtasks.md │ │ │ │ └── clear-subtasks.md │ │ │ ├── complexity-report │ │ │ │ └── complexity-report.md │ │ │ ├── expand │ │ │ │ ├── expand-all-tasks.md │ │ │ │ └── expand-task.md │ │ │ ├── fix-dependencies │ │ │ │ └── fix-dependencies.md │ │ │ ├── generate │ │ │ │ └── generate-tasks.md │ │ │ ├── help.md │ │ │ ├── init │ │ │ │ ├── init-project-quick.md │ │ │ │ └── init-project.md │ │ │ ├── learn.md │ │ │ ├── list │ │ │ │ ├── list-tasks-by-status.md │ │ │ │ ├── list-tasks-with-subtasks.md │ │ │ │ └── list-tasks.md │ │ │ ├── models │ │ │ │ ├── setup-models.md │ │ │ │ └── view-models.md │ │ │ ├── next │ │ │ │ └── next-task.md │ │ │ ├── parse-prd │ │ │ │ ├── parse-prd-with-research.md │ │ │ │ └── parse-prd.md │ │ │ ├── remove-dependency │ │ │ │ └── remove-dependency.md │ │ │ ├── remove-subtask │ │ │ │ └── remove-subtask.md │ │ │ ├── remove-subtasks │ │ │ │ ├── remove-all-subtasks.md │ │ │ │ └── remove-subtasks.md │ │ │ ├── remove-task │ │ │ │ └── remove-task.md │ │ │ ├── set-status │ │ │ │ ├── to-cancelled.md │ │ │ │ ├── to-deferred.md │ │ │ │ ├── to-done.md │ │ │ │ ├── to-in-progress.md │ │ │ │ ├── to-pending.md │ │ │ │ └── to-review.md │ │ │ ├── setup │ │ │ │ ├── install-taskmaster.md │ │ │ │ └── quick-install-taskmaster.md │ │ │ ├── show │ │ │ │ └── show-task.md │ │ │ ├── status │ │ │ │ └── project-status.md │ │ │ ├── sync-readme │ │ │ │ └── sync-readme.md │ │ │ ├── tm-main.md │ │ │ ├── update │ │ │ │ ├── update-single-task.md │ │ │ │ ├── update-task.md │ │ │ │ └── update-tasks-from-id.md │ │ │ ├── utils │ │ │ │ └── analyze-project.md │ │ │ ├── validate-dependencies │ │ │ │ └── validate-dependencies.md │ │ │ └── workflows │ │ │ ├── auto-implement-tasks.md │ │ │ ├── command-pipeline.md │ │ │ └── smart-workflow.md │ │ └── TM_COMMANDS_GUIDE.md │ ├── config.json │ ├── env.example │ ├── example_prd.txt │ ├── gitignore │ ├── kiro-hooks │ │ ├── tm-code-change-task-tracker.kiro.hook │ │ ├── tm-complexity-analyzer.kiro.hook │ │ ├── tm-daily-standup-assistant.kiro.hook │ │ ├── tm-git-commit-task-linker.kiro.hook │ │ ├── tm-pr-readiness-checker.kiro.hook │ │ ├── tm-task-dependency-auto-progression.kiro.hook │ │ └── tm-test-success-task-completer.kiro.hook │ ├── roocode │ │ ├── .roo │ │ │ ├── rules-architect │ │ │ │ └── architect-rules │ │ │ ├── rules-ask │ │ │ │ └── ask-rules │ │ │ ├── rules-code │ │ │ │ └── code-rules │ │ │ ├── rules-debug │ │ │ │ └── debug-rules │ │ │ ├── rules-orchestrator │ │ │ │ └── orchestrator-rules │ │ │ └── rules-test │ │ │ └── test-rules │ │ └── .roomodes │ ├── rules │ │ ├── cursor_rules.mdc │ │ ├── dev_workflow.mdc │ │ ├── self_improve.mdc │ │ ├── taskmaster_hooks_workflow.mdc │ │ └── taskmaster.mdc │ └── scripts_README.md ├── bin │ └── task-master.js ├── biome.json ├── CHANGELOG.md ├── CLAUDE.md ├── context │ ├── chats │ │ ├── add-task-dependencies-1.md │ │ └── max-min-tokens.txt.md │ ├── fastmcp-core.txt │ ├── fastmcp-docs.txt │ ├── MCP_INTEGRATION.md │ ├── mcp-js-sdk-docs.txt │ ├── mcp-protocol-repo.txt │ ├── mcp-protocol-schema-03262025.json │ └── mcp-protocol-spec.txt ├── CONTRIBUTING.md ├── docs │ ├── CLI-COMMANDER-PATTERN.md │ ├── command-reference.md │ ├── configuration.md │ ├── contributor-docs │ │ └── testing-roo-integration.md │ ├── cross-tag-task-movement.md │ ├── examples │ │ └── claude-code-usage.md │ ├── examples.md │ ├── licensing.md │ ├── mcp-provider-guide.md │ ├── mcp-provider.md │ ├── migration-guide.md │ ├── models.md │ ├── providers │ │ └── gemini-cli.md │ ├── README.md │ ├── scripts │ │ └── models-json-to-markdown.js │ ├── task-structure.md │ └── tutorial.md ├── images │ └── logo.png ├── index.js ├── jest.config.js ├── jest.resolver.cjs ├── LICENSE ├── llms-install.md ├── mcp-server │ ├── server.js │ └── src │ ├── core │ │ ├── __tests__ │ │ │ └── context-manager.test.js │ │ ├── context-manager.js │ │ ├── direct-functions │ │ │ ├── add-dependency.js │ │ │ ├── add-subtask.js │ │ │ ├── add-tag.js │ │ │ ├── add-task.js │ │ │ ├── analyze-task-complexity.js │ │ │ ├── cache-stats.js │ │ │ ├── clear-subtasks.js │ │ │ ├── complexity-report.js │ │ │ ├── copy-tag.js │ │ │ ├── create-tag-from-branch.js │ │ │ ├── delete-tag.js │ │ │ ├── expand-all-tasks.js │ │ │ ├── expand-task.js │ │ │ ├── fix-dependencies.js │ │ │ ├── generate-task-files.js │ │ │ ├── initialize-project.js │ │ │ ├── list-tags.js │ │ │ ├── list-tasks.js │ │ │ ├── models.js │ │ │ ├── move-task-cross-tag.js │ │ │ ├── move-task.js │ │ │ ├── next-task.js │ │ │ ├── parse-prd.js │ │ │ ├── remove-dependency.js │ │ │ ├── remove-subtask.js │ │ │ ├── remove-task.js │ │ │ ├── rename-tag.js │ │ │ ├── research.js │ │ │ ├── response-language.js │ │ │ ├── rules.js │ │ │ ├── scope-down.js │ │ │ ├── scope-up.js │ │ │ ├── set-task-status.js │ │ │ ├── show-task.js │ │ │ ├── update-subtask-by-id.js │ │ │ ├── update-task-by-id.js │ │ │ ├── update-tasks.js │ │ │ ├── use-tag.js │ │ │ └── validate-dependencies.js │ │ ├── task-master-core.js │ │ └── utils │ │ ├── env-utils.js │ │ └── path-utils.js │ ├── custom-sdk │ │ ├── errors.js │ │ ├── index.js │ │ ├── json-extractor.js │ │ ├── language-model.js │ │ ├── message-converter.js │ │ └── schema-converter.js │ ├── index.js │ ├── logger.js │ ├── providers │ │ └── mcp-provider.js │ └── tools │ ├── add-dependency.js │ ├── add-subtask.js │ ├── add-tag.js │ ├── add-task.js │ ├── analyze.js │ ├── clear-subtasks.js │ ├── complexity-report.js │ ├── copy-tag.js │ ├── delete-tag.js │ ├── expand-all.js │ ├── expand-task.js │ ├── fix-dependencies.js │ ├── generate.js │ ├── get-operation-status.js │ ├── get-task.js │ ├── get-tasks.js │ ├── index.js │ ├── initialize-project.js │ ├── list-tags.js │ ├── models.js │ ├── move-task.js │ ├── next-task.js │ ├── parse-prd.js │ ├── remove-dependency.js │ ├── remove-subtask.js │ ├── remove-task.js │ ├── rename-tag.js │ ├── research.js │ ├── response-language.js │ ├── rules.js │ ├── scope-down.js │ ├── scope-up.js │ ├── set-task-status.js │ ├── update-subtask.js │ ├── update-task.js │ ├── update.js │ ├── use-tag.js │ ├── utils.js │ └── validate-dependencies.js ├── mcp-test.js ├── output.json ├── package-lock.json ├── package.json ├── packages │ ├── build-config │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ │ └── tsdown.base.ts │ │ └── tsconfig.json │ └── tm-core │ ├── .gitignore │ ├── CHANGELOG.md │ ├── docs │ │ └── listTasks-architecture.md │ ├── package.json │ ├── POC-STATUS.md │ ├── README.md │ ├── src │ │ ├── auth │ │ │ ├── auth-manager.test.ts │ │ │ ├── auth-manager.ts │ │ │ ├── config.ts │ │ │ ├── credential-store.test.ts │ │ │ ├── credential-store.ts │ │ │ ├── index.ts │ │ │ ├── oauth-service.ts │ │ │ ├── supabase-session-storage.ts │ │ │ └── types.ts │ │ ├── clients │ │ │ ├── index.ts │ │ │ └── supabase-client.ts │ │ ├── config │ │ │ ├── config-manager.spec.ts │ │ │ ├── config-manager.ts │ │ │ ├── index.ts │ │ │ └── services │ │ │ ├── config-loader.service.spec.ts │ │ │ ├── config-loader.service.ts │ │ │ ├── config-merger.service.spec.ts │ │ │ ├── config-merger.service.ts │ │ │ ├── config-persistence.service.spec.ts │ │ │ ├── config-persistence.service.ts │ │ │ ├── environment-config-provider.service.spec.ts │ │ │ ├── environment-config-provider.service.ts │ │ │ ├── index.ts │ │ │ ├── runtime-state-manager.service.spec.ts │ │ │ └── runtime-state-manager.service.ts │ │ ├── constants │ │ │ └── index.ts │ │ ├── entities │ │ │ └── task.entity.ts │ │ ├── errors │ │ │ ├── index.ts │ │ │ └── task-master-error.ts │ │ ├── executors │ │ │ ├── base-executor.ts │ │ │ ├── claude-executor.ts │ │ │ ├── executor-factory.ts │ │ │ ├── executor-service.ts │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── index.ts │ │ ├── interfaces │ │ │ ├── ai-provider.interface.ts │ │ │ ├── configuration.interface.ts │ │ │ ├── index.ts │ │ │ └── storage.interface.ts │ │ ├── logger │ │ │ ├── factory.ts │ │ │ ├── index.ts │ │ │ └── logger.ts │ │ ├── mappers │ │ │ └── TaskMapper.ts │ │ ├── parser │ │ │ └── index.ts │ │ ├── providers │ │ │ ├── ai │ │ │ │ ├── base-provider.ts │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── repositories │ │ │ ├── supabase-task-repository.ts │ │ │ └── task-repository.interface.ts │ │ ├── services │ │ │ ├── index.ts │ │ │ ├── organization.service.ts │ │ │ ├── task-execution-service.ts │ │ │ └── task-service.ts │ │ ├── storage │ │ │ ├── api-storage.ts │ │ │ ├── file-storage │ │ │ │ ├── file-operations.ts │ │ │ │ ├── file-storage.ts │ │ │ │ ├── format-handler.ts │ │ │ │ ├── index.ts │ │ │ │ └── path-resolver.ts │ │ │ ├── index.ts │ │ │ └── storage-factory.ts │ │ ├── subpath-exports.test.ts │ │ ├── task-master-core.ts │ │ ├── types │ │ │ ├── database.types.ts │ │ │ ├── index.ts │ │ │ └── legacy.ts │ │ └── utils │ │ ├── id-generator.ts │ │ └── index.ts │ ├── tests │ │ ├── integration │ │ │ └── list-tasks.test.ts │ │ ├── mocks │ │ │ └── mock-provider.ts │ │ ├── setup.ts │ │ └── unit │ │ ├── base-provider.test.ts │ │ ├── executor.test.ts │ │ └── smoke.test.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── README-task-master.md ├── README.md ├── scripts │ ├── dev.js │ ├── init.js │ ├── modules │ │ ├── ai-services-unified.js │ │ ├── commands.js │ │ ├── config-manager.js │ │ ├── dependency-manager.js │ │ ├── index.js │ │ ├── prompt-manager.js │ │ ├── supported-models.json │ │ ├── sync-readme.js │ │ ├── task-manager │ │ │ ├── add-subtask.js │ │ │ ├── add-task.js │ │ │ ├── analyze-task-complexity.js │ │ │ ├── clear-subtasks.js │ │ │ ├── expand-all-tasks.js │ │ │ ├── expand-task.js │ │ │ ├── find-next-task.js │ │ │ ├── generate-task-files.js │ │ │ ├── is-task-dependent.js │ │ │ ├── list-tasks.js │ │ │ ├── migrate.js │ │ │ ├── models.js │ │ │ ├── move-task.js │ │ │ ├── parse-prd │ │ │ │ ├── index.js │ │ │ │ ├── parse-prd-config.js │ │ │ │ ├── parse-prd-helpers.js │ │ │ │ ├── parse-prd-non-streaming.js │ │ │ │ ├── parse-prd-streaming.js │ │ │ │ └── parse-prd.js │ │ │ ├── remove-subtask.js │ │ │ ├── remove-task.js │ │ │ ├── research.js │ │ │ ├── response-language.js │ │ │ ├── scope-adjustment.js │ │ │ ├── set-task-status.js │ │ │ ├── tag-management.js │ │ │ ├── task-exists.js │ │ │ ├── update-single-task-status.js │ │ │ ├── update-subtask-by-id.js │ │ │ ├── update-task-by-id.js │ │ │ └── update-tasks.js │ │ ├── task-manager.js │ │ ├── ui.js │ │ ├── update-config-tokens.js │ │ ├── utils │ │ │ ├── contextGatherer.js │ │ │ ├── fuzzyTaskSearch.js │ │ │ └── git-utils.js │ │ └── utils.js │ ├── task-complexity-report.json │ ├── test-claude-errors.js │ └── test-claude.js ├── src │ ├── ai-providers │ │ ├── anthropic.js │ │ ├── azure.js │ │ ├── base-provider.js │ │ ├── bedrock.js │ │ ├── claude-code.js │ │ ├── custom-sdk │ │ │ ├── claude-code │ │ │ │ ├── errors.js │ │ │ │ ├── index.js │ │ │ │ ├── json-extractor.js │ │ │ │ ├── language-model.js │ │ │ │ ├── message-converter.js │ │ │ │ └── types.js │ │ │ └── grok-cli │ │ │ ├── errors.js │ │ │ ├── index.js │ │ │ ├── json-extractor.js │ │ │ ├── language-model.js │ │ │ ├── message-converter.js │ │ │ └── types.js │ │ ├── gemini-cli.js │ │ ├── google-vertex.js │ │ ├── google.js │ │ ├── grok-cli.js │ │ ├── groq.js │ │ ├── index.js │ │ ├── ollama.js │ │ ├── openai.js │ │ ├── openrouter.js │ │ ├── perplexity.js │ │ └── xai.js │ ├── constants │ │ ├── commands.js │ │ ├── paths.js │ │ ├── profiles.js │ │ ├── providers.js │ │ ├── rules-actions.js │ │ ├── task-priority.js │ │ └── task-status.js │ ├── profiles │ │ ├── amp.js │ │ ├── base-profile.js │ │ ├── claude.js │ │ ├── cline.js │ │ ├── codex.js │ │ ├── cursor.js │ │ ├── gemini.js │ │ ├── index.js │ │ ├── kilo.js │ │ ├── kiro.js │ │ ├── opencode.js │ │ ├── roo.js │ │ ├── trae.js │ │ ├── vscode.js │ │ ├── windsurf.js │ │ └── zed.js │ ├── progress │ │ ├── base-progress-tracker.js │ │ ├── cli-progress-factory.js │ │ ├── parse-prd-tracker.js │ │ ├── progress-tracker-builder.js │ │ └── tracker-ui.js │ ├── prompts │ │ ├── add-task.json │ │ ├── analyze-complexity.json │ │ ├── expand-task.json │ │ ├── parse-prd.json │ │ ├── README.md │ │ ├── research.json │ │ ├── schemas │ │ │ ├── parameter.schema.json │ │ │ ├── prompt-template.schema.json │ │ │ ├── README.md │ │ │ └── variant.schema.json │ │ ├── update-subtask.json │ │ ├── update-task.json │ │ └── update-tasks.json │ ├── provider-registry │ │ └── index.js │ ├── task-master.js │ ├── ui │ │ ├── confirm.js │ │ ├── indicators.js │ │ └── parse-prd.js │ └── utils │ ├── asset-resolver.js │ ├── create-mcp-config.js │ ├── format.js │ ├── getVersion.js │ ├── logger-utils.js │ ├── manage-gitignore.js │ ├── path-utils.js │ ├── profiles.js │ ├── rule-transformer.js │ ├── stream-parser.js │ └── timeout-manager.js ├── test-clean-tags.js ├── test-config-manager.js ├── test-prd.txt ├── test-tag-functions.js ├── test-version-check-full.js ├── test-version-check.js ├── tests │ ├── e2e │ │ ├── e2e_helpers.sh │ │ ├── parse_llm_output.cjs │ │ ├── run_e2e.sh │ │ ├── run_fallback_verification.sh │ │ └── test_llm_analysis.sh │ ├── fixture │ │ └── test-tasks.json │ ├── fixtures │ │ ├── .taskmasterconfig │ │ ├── sample-claude-response.js │ │ ├── sample-prd.txt │ │ └── sample-tasks.js │ ├── integration │ │ ├── claude-code-optional.test.js │ │ ├── cli │ │ │ ├── commands.test.js │ │ │ ├── complex-cross-tag-scenarios.test.js │ │ │ └── move-cross-tag.test.js │ │ ├── manage-gitignore.test.js │ │ ├── mcp-server │ │ │ └── direct-functions.test.js │ │ ├── move-task-cross-tag.integration.test.js │ │ ├── move-task-simple.integration.test.js │ │ └── profiles │ │ ├── amp-init-functionality.test.js │ │ ├── claude-init-functionality.test.js │ │ ├── cline-init-functionality.test.js │ │ ├── codex-init-functionality.test.js │ │ ├── cursor-init-functionality.test.js │ │ ├── gemini-init-functionality.test.js │ │ ├── opencode-init-functionality.test.js │ │ ├── roo-files-inclusion.test.js │ │ ├── roo-init-functionality.test.js │ │ ├── rules-files-inclusion.test.js │ │ ├── trae-init-functionality.test.js │ │ ├── vscode-init-functionality.test.js │ │ └── windsurf-init-functionality.test.js │ ├── manual │ │ ├── progress │ │ │ ├── parse-prd-analysis.js │ │ │ ├── test-parse-prd.js │ │ │ └── TESTING_GUIDE.md │ │ └── prompts │ │ ├── prompt-test.js │ │ └── README.md │ ├── README.md │ ├── setup.js │ └── unit │ ├── ai-providers │ │ ├── claude-code.test.js │ │ ├── custom-sdk │ │ │ └── claude-code │ │ │ └── language-model.test.js │ │ ├── gemini-cli.test.js │ │ ├── mcp-components.test.js │ │ └── openai.test.js │ ├── ai-services-unified.test.js │ ├── commands.test.js │ ├── config-manager.test.js │ ├── config-manager.test.mjs │ ├── dependency-manager.test.js │ ├── init.test.js │ ├── initialize-project.test.js │ ├── kebab-case-validation.test.js │ ├── manage-gitignore.test.js │ ├── mcp │ │ └── tools │ │ ├── __mocks__ │ │ │ └── move-task.js │ │ ├── add-task.test.js │ │ ├── analyze-complexity.test.js │ │ ├── expand-all.test.js │ │ ├── get-tasks.test.js │ │ ├── initialize-project.test.js │ │ ├── move-task-cross-tag-options.test.js │ │ ├── move-task-cross-tag.test.js │ │ └── remove-task.test.js │ ├── mcp-providers │ │ ├── mcp-components.test.js │ │ └── mcp-provider.test.js │ ├── parse-prd.test.js │ ├── profiles │ │ ├── amp-integration.test.js │ │ ├── claude-integration.test.js │ │ ├── cline-integration.test.js │ │ ├── codex-integration.test.js │ │ ├── cursor-integration.test.js │ │ ├── gemini-integration.test.js │ │ ├── kilo-integration.test.js │ │ ├── kiro-integration.test.js │ │ ├── mcp-config-validation.test.js │ │ ├── opencode-integration.test.js │ │ ├── profile-safety-check.test.js │ │ ├── roo-integration.test.js │ │ ├── rule-transformer-cline.test.js │ │ ├── rule-transformer-cursor.test.js │ │ ├── rule-transformer-gemini.test.js │ │ ├── rule-transformer-kilo.test.js │ │ ├── rule-transformer-kiro.test.js │ │ ├── rule-transformer-opencode.test.js │ │ ├── rule-transformer-roo.test.js │ │ ├── rule-transformer-trae.test.js │ │ ├── rule-transformer-vscode.test.js │ │ ├── rule-transformer-windsurf.test.js │ │ ├── rule-transformer-zed.test.js │ │ ├── rule-transformer.test.js │ │ ├── selective-profile-removal.test.js │ │ ├── subdirectory-support.test.js │ │ ├── trae-integration.test.js │ │ ├── vscode-integration.test.js │ │ ├── windsurf-integration.test.js │ │ └── zed-integration.test.js │ ├── progress │ │ └── base-progress-tracker.test.js │ ├── prompt-manager.test.js │ ├── prompts │ │ └── expand-task-prompt.test.js │ ├── providers │ │ └── provider-registry.test.js │ ├── scripts │ │ └── modules │ │ ├── commands │ │ │ ├── move-cross-tag.test.js │ │ │ └── README.md │ │ ├── dependency-manager │ │ │ ├── circular-dependencies.test.js │ │ │ ├── cross-tag-dependencies.test.js │ │ │ └── fix-dependencies-command.test.js │ │ ├── task-manager │ │ │ ├── add-subtask.test.js │ │ │ ├── add-task.test.js │ │ │ ├── analyze-task-complexity.test.js │ │ │ ├── clear-subtasks.test.js │ │ │ ├── complexity-report-tag-isolation.test.js │ │ │ ├── expand-all-tasks.test.js │ │ │ ├── expand-task.test.js │ │ │ ├── find-next-task.test.js │ │ │ ├── generate-task-files.test.js │ │ │ ├── list-tasks.test.js │ │ │ ├── move-task-cross-tag.test.js │ │ │ ├── move-task.test.js │ │ │ ├── parse-prd.test.js │ │ │ ├── remove-subtask.test.js │ │ │ ├── remove-task.test.js │ │ │ ├── research.test.js │ │ │ ├── scope-adjustment.test.js │ │ │ ├── set-task-status.test.js │ │ │ ├── setup.js │ │ │ ├── update-single-task-status.test.js │ │ │ ├── update-subtask-by-id.test.js │ │ │ ├── update-task-by-id.test.js │ │ │ └── update-tasks.test.js │ │ ├── ui │ │ │ └── cross-tag-error-display.test.js │ │ └── utils-tag-aware-paths.test.js │ ├── task-finder.test.js │ ├── task-manager │ │ ├── clear-subtasks.test.js │ │ ├── move-task.test.js │ │ ├── tag-boundary.test.js │ │ └── tag-management.test.js │ ├── task-master.test.js │ ├── ui │ │ └── indicators.test.js │ ├── ui.test.js │ ├── utils-strip-ansi.test.js │ └── utils.test.js ├── tsconfig.json ├── tsdown.config.ts └── turbo.json ``` # Files -------------------------------------------------------------------------------- /packages/tm-core/src/storage/index.ts: -------------------------------------------------------------------------------- ```typescript /** * @fileoverview Storage layer for the tm-core package * This file exports all storage-related classes and interfaces */ // Export storage implementations export { FileStorage } from './file-storage/index.js'; export { ApiStorage, type ApiStorageConfig } from './api-storage.js'; export { StorageFactory } from './storage-factory.js'; // Export storage interface and types export type { IStorage, StorageStats } from '../interfaces/storage.interface.js'; // Placeholder exports - these will be implemented in later tasks export interface StorageAdapter { read(path: string): Promise<string | null>; write(path: string, data: string): Promise<void>; exists(path: string): Promise<boolean>; delete(path: string): Promise<void>; } /** * @deprecated This is a placeholder class that will be properly implemented in later tasks */ export class PlaceholderStorage implements StorageAdapter { private data = new Map<string, string>(); async read(path: string): Promise<string | null> { return this.data.get(path) || null; } async write(path: string, data: string): Promise<void> { this.data.set(path, data); } async exists(path: string): Promise<boolean> { return this.data.has(path); } async delete(path: string): Promise<void> { this.data.delete(path); } } ``` -------------------------------------------------------------------------------- /src/prompts/schemas/parameter.schema.json: -------------------------------------------------------------------------------- ```json { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://github.com/eyaltoledano/claude-task-master/blob/main/src/prompts/schemas/parameter.schema.json", "version": "1.0.0", "title": "Task Master Prompt Parameter", "description": "Schema for individual prompt template parameters", "type": "object", "required": ["type", "description"], "properties": { "type": { "type": "string", "enum": ["string", "number", "boolean", "array", "object"], "description": "The expected data type for this parameter" }, "description": { "type": "string", "minLength": 1, "description": "Human-readable description of the parameter" }, "required": { "type": "boolean", "default": false, "description": "Whether this parameter is required" }, "default": { "description": "Default value for optional parameters" }, "enum": { "type": "array", "description": "Valid values for string parameters", "items": { "type": "string" } }, "pattern": { "type": "string", "description": "Regular expression pattern for string validation" }, "minimum": { "type": "number", "description": "Minimum value for number parameters" }, "maximum": { "type": "number", "description": "Maximum value for number parameters" } } } ``` -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/enhancements---feature-requests.md: -------------------------------------------------------------------------------- ```markdown --- name: Enhancements & feature requests about: Suggest an idea for this project title: 'feat: ' labels: enhancement assignees: '' --- > "Direct quote or clear summary of user request or need or user story." ### Motivation Detailed explanation of why this feature is important. Describe the problem it solves or the benefit it provides. ### Proposed Solution Clearly describe the proposed feature, including: - High-level overview of the feature - Relevant technologies or integrations - How it fits into the existing workflow or architecture ### High-Level Workflow 1. Step-by-step description of how the feature will be implemented 2. Include necessary intermediate milestones ### Key Elements - Bullet-point list of technical or UX/UI enhancements - Mention specific integrations or APIs - Highlight changes needed in existing data models or commands ### Example Workflow Provide a clear, concrete example demonstrating the feature: ```shell $ task-master [action] → Expected response/output ``` ### Implementation Considerations - Dependencies on external components or APIs - Backward compatibility requirements - Potential performance impacts or resource usage ### Out of Scope (Future Considerations) Clearly list any features or improvements not included but relevant for future iterations. ``` -------------------------------------------------------------------------------- /packages/tm-core/src/executors/types.ts: -------------------------------------------------------------------------------- ```typescript /** * Executor types and interfaces for Task Master */ import type { Task } from '../types/index.js'; /** * Supported executor types */ export type ExecutorType = 'claude' | 'shell' | 'custom'; /** * Options for executor creation */ export interface ExecutorOptions { type: ExecutorType; projectRoot: string; config?: Record<string, any>; } /** * Result from task execution */ export interface ExecutionResult { success: boolean; taskId: string; executorType: ExecutorType; output?: string; error?: string; startTime: string; endTime?: string; processId?: number; } /** * Base interface for all task executors */ export interface ITaskExecutor { /** * Execute a task */ execute(task: Task): Promise<ExecutionResult>; /** * Stop a running task execution */ stop?(): Promise<void>; /** * Get executor type */ getType(): ExecutorType; /** * Check if executor is available/configured */ isAvailable(): Promise<boolean>; } /** * Configuration for Claude executor */ export interface ClaudeExecutorConfig { command?: string; // Default: 'claude' systemPrompt?: string; additionalFlags?: string[]; } /** * Configuration for Shell executor */ export interface ShellExecutorConfig { shell?: string; // Default: '/bin/bash' env?: Record<string, string>; cwd?: string; } ``` -------------------------------------------------------------------------------- /src/ai-providers/ollama.js: -------------------------------------------------------------------------------- ```javascript /** * ollama.js * AI provider implementation for Ollama models using the ollama-ai-provider package. */ import { createOllama } from 'ollama-ai-provider'; import { BaseAIProvider } from './base-provider.js'; export class OllamaAIProvider extends BaseAIProvider { constructor() { super(); this.name = 'Ollama'; } /** * Override auth validation - Ollama doesn't require API keys * @param {object} params - Parameters to validate */ validateAuth(_params) { // Ollama runs locally and doesn't require API keys // No authentication validation needed } /** * Creates and returns an Ollama client instance. * @param {object} params - Parameters for client initialization * @param {string} [params.baseURL] - Optional Ollama base URL (defaults to http://localhost:11434) * @returns {Function} Ollama client function * @throws {Error} If initialization fails */ getClient(params) { try { const { baseURL } = params; return createOllama({ ...(baseURL && { baseURL }) }); } catch (error) { this.handleError('client initialization', error); } } isRequiredApiKey() { return false; } /** * Returns the required API key environment variable name for Ollama. * @returns {string} The environment variable name */ getRequiredApiKeyName() { return 'OLLAMA_API_KEY'; } } ``` -------------------------------------------------------------------------------- /.claude/commands/tm/remove-dependency/remove-dependency.md: -------------------------------------------------------------------------------- ```markdown Remove a dependency between tasks. Arguments: $ARGUMENTS Parse the task IDs to remove dependency relationship. ## Removing Dependencies Removes a dependency relationship, potentially unblocking tasks. ## Argument Parsing Parse natural language or IDs: - "remove dependency between 5 and 3" - "5 no longer needs 3" - "unblock 5 from 3" - "5 3" → remove dependency of 5 on 3 ## Execution ```bash task-master remove-dependency --id=<task-id> --depends-on=<dependency-id> ``` ## Pre-Removal Checks 1. **Verify dependency exists** 2. **Check impact on task flow** 3. **Warn if it breaks logical sequence** 4. **Show what will be unblocked** ## Smart Analysis Before removing: - Show why dependency might have existed - Check if removal makes tasks executable - Verify no critical path disruption - Suggest alternative dependencies ## Post-Removal After removing: 1. Show updated task status 2. List newly unblocked tasks 3. Update project timeline 4. Suggest next actions ## Safety Features - Confirm if removing critical dependency - Show tasks that become immediately actionable - Warn about potential issues - Keep removal history ## Example ``` /project:tm/remove-dependency 5 from 3 → Removed: Task #5 no longer depends on #3 → Task #5 is now UNBLOCKED and ready to start → Warning: Consider if #5 still needs #2 completed first ``` ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/remove-dependency/remove-dependency.md: -------------------------------------------------------------------------------- ```markdown Remove a dependency between tasks. Arguments: $ARGUMENTS Parse the task IDs to remove dependency relationship. ## Removing Dependencies Removes a dependency relationship, potentially unblocking tasks. ## Argument Parsing Parse natural language or IDs: - "remove dependency between 5 and 3" - "5 no longer needs 3" - "unblock 5 from 3" - "5 3" → remove dependency of 5 on 3 ## Execution ```bash task-master remove-dependency --id=<task-id> --depends-on=<dependency-id> ``` ## Pre-Removal Checks 1. **Verify dependency exists** 2. **Check impact on task flow** 3. **Warn if it breaks logical sequence** 4. **Show what will be unblocked** ## Smart Analysis Before removing: - Show why dependency might have existed - Check if removal makes tasks executable - Verify no critical path disruption - Suggest alternative dependencies ## Post-Removal After removing: 1. Show updated task status 2. List newly unblocked tasks 3. Update project timeline 4. Suggest next actions ## Safety Features - Confirm if removing critical dependency - Show tasks that become immediately actionable - Warn about potential issues - Keep removal history ## Example ``` /project:tm/remove-dependency 5 from 3 → Removed: Task #5 no longer depends on #3 → Task #5 is now UNBLOCKED and ready to start → Warning: Consider if #5 still needs #2 completed first ``` ``` -------------------------------------------------------------------------------- /.taskmaster/tasks/task_004_tm-start.txt: -------------------------------------------------------------------------------- ``` # Task ID: 4 # Title: Implement claude-code executor # Status: pending # Dependencies: 3 # Priority: high # Description: Add functionality to execute the claude-code command with the built prompt # Details: Implement the functionality to execute the claude command with the built prompt. This should use Node.js child_process.exec() to run the command directly in the terminal. ```typescript import { exec } from 'child_process'; // Inside execute method, after task validation private async executeClaude(prompt: string): Promise<void> { console.log('Starting claude-code to implement the task...'); try { // Execute claude with the prompt const claudeCommand = `claude "${prompt.replace(/"/g, '\\"')}"`; // Use execSync to wait for the command to complete const { execSync } = require('child_process'); execSync(claudeCommand, { stdio: 'inherit' }); console.log('Claude session completed.'); } catch (error) { console.error('Error executing claude-code:', error.message); process.exit(1); } } ``` Then call this method from the execute method after building the prompt. # Test Strategy: Test by running the command with a valid task ID and verifying that the claude command is executed with the correct prompt. Check that the command handles errors appropriately if claude-code is not available. ``` -------------------------------------------------------------------------------- /apps/extension/src/components/TaskDetails/PriorityBadge.tsx: -------------------------------------------------------------------------------- ```typescript import type React from 'react'; import type { TaskMasterTask } from '../../webview/types'; // Custom Priority Badge Component with theme-adaptive styling export const PriorityBadge: React.FC<{ priority: TaskMasterTask['priority']; }> = ({ priority }) => { const getPriorityColors = (priority: string) => { switch (priority) { case 'high': return { backgroundColor: 'rgba(239, 68, 68, 0.2)', // red-500 with opacity color: '#dc2626', // red-600 - works in both themes borderColor: 'rgba(239, 68, 68, 0.4)' }; case 'medium': return { backgroundColor: 'rgba(245, 158, 11, 0.2)', // amber-500 with opacity color: '#d97706', // amber-600 - works in both themes borderColor: 'rgba(245, 158, 11, 0.4)' }; case 'low': return { backgroundColor: 'rgba(34, 197, 94, 0.2)', // green-500 with opacity color: '#16a34a', // green-600 - works in both themes borderColor: 'rgba(34, 197, 94, 0.4)' }; default: return { backgroundColor: 'rgba(156, 163, 175, 0.2)', color: 'var(--vscode-foreground)', borderColor: 'rgba(156, 163, 175, 0.4)' }; } }; const colors = getPriorityColors(priority || ''); return ( <span className="inline-flex items-center px-2 py-1 text-xs font-medium rounded-md border" style={colors} > {priority || 'None'} </span> ); }; ``` -------------------------------------------------------------------------------- /.taskmaster/reports/task-complexity-report.json: -------------------------------------------------------------------------------- ```json { "meta": { "generatedAt": "2025-08-02T14:28:59.851Z", "tasksAnalyzed": 1, "totalTasks": 93, "analysisCount": 1, "thresholdScore": 5, "projectName": "Taskmaster", "usedResearch": false }, "complexityAnalysis": [ { "taskId": 24, "taskTitle": "Implement AI-Powered Test Generation Command", "complexityScore": 8, "recommendedSubtasks": 6, "expansionPrompt": "Expand task 24 'Implement AI-Powered Test Generation Command' into 6 subtasks, focusing on: 1) Command structure implementation, 2) AI prompt engineering for test generation, 3) Test file generation and output, 4) Framework-specific template implementation, 5) MCP tool integration, and 6) Documentation and help system integration. Include detailed implementation steps, dependencies, and testing approaches for each subtask.", "reasoning": "This task has high complexity due to several challenging aspects: 1) AI integration requiring sophisticated prompt engineering, 2) Test generation across multiple frameworks, 3) File system operations with proper error handling, 4) MCP tool integration, 5) Complex configuration requirements, and 6) Framework-specific template generation. The task already has 5 subtasks but could benefit from reorganization based on the updated implementation details in the info blocks, particularly around framework support and configuration." } ] } ``` -------------------------------------------------------------------------------- /mcp-server/src/custom-sdk/index.js: -------------------------------------------------------------------------------- ```javascript /** * src/ai-providers/custom-sdk/mcp/index.js * * AI SDK factory function for MCP provider. * Creates MCP language model instances with session-based AI operations. */ import { MCPLanguageModel } from './language-model.js'; /** * Create MCP provider factory function following AI SDK patterns * @param {object} options - Provider options * @param {object} options.session - MCP session object * @param {object} options.defaultSettings - Default settings for the provider * @returns {Function} Provider factory function */ export function createMCP(options = {}) { if (!options.session) { throw new Error('MCP provider requires session object'); } // Return the provider factory function that AI SDK expects const provider = function (modelId, settings = {}) { if (new.target) { throw new Error( 'The MCP model function cannot be called with the new keyword.' ); } return new MCPLanguageModel({ session: options.session, modelId: modelId || 'claude-3-5-sonnet-20241022', settings: { temperature: settings.temperature, maxTokens: settings.maxTokens, ...options.defaultSettings, ...settings } }); }; // Add required methods for AI SDK compatibility provider.languageModel = (modelId, settings) => provider(modelId, settings); provider.chat = (modelId, settings) => provider(modelId, settings); return provider; } ``` -------------------------------------------------------------------------------- /packages/tm-core/vitest.config.ts: -------------------------------------------------------------------------------- ```typescript import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { defineConfig } from 'vitest/config'; // __dirname in ESM const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export default defineConfig({ test: { globals: true, environment: 'node', include: [ 'tests/**/*.test.ts', 'tests/**/*.spec.ts', 'tests/{unit,integration,e2e}/**/*.{test,spec}.ts', 'src/**/*.test.ts', 'src/**/*.spec.ts' ], exclude: ['node_modules', 'dist', '.git', '.cache'], coverage: { provider: 'v8', reporter: ['text', 'json', 'html', 'lcov'], exclude: [ 'node_modules', 'dist', 'tests', '**/*.test.ts', '**/*.spec.ts', '**/*.d.ts', 'src/index.ts' ], thresholds: { branches: 80, functions: 80, lines: 80, statements: 80 } }, setupFiles: ['./tests/setup.ts'], testTimeout: 10000, clearMocks: true, restoreMocks: true, mockReset: true }, resolve: { alias: { '@': path.resolve(__dirname, './src'), '@/types': path.resolve(__dirname, './src/types'), '@/providers': path.resolve(__dirname, './src/providers'), '@/storage': path.resolve(__dirname, './src/storage'), '@/parser': path.resolve(__dirname, './src/parser'), '@/utils': path.resolve(__dirname, './src/utils'), '@/errors': path.resolve(__dirname, './src/errors') } } }); ``` -------------------------------------------------------------------------------- /.taskmaster/tasks/task_001_tm-start.txt: -------------------------------------------------------------------------------- ``` # Task ID: 1 # Title: Create start command class structure # Status: pending # Dependencies: None # Priority: high # Description: Create the basic structure for the start command following the Commander class pattern # Details: Create a new file `apps/cli/src/commands/start.command.ts` based on the existing list.command.ts pattern. Implement the command class with proper command registration, description, and argument handling for the task_id parameter. The class should extend the base Command class and implement the required methods. Example structure: ```typescript import { Command } from 'commander'; import { BaseCommand } from './base.command'; export class StartCommand extends BaseCommand { public register(program: Command): void { program .command('start') .alias('tm start') .description('Start implementing a task using claude-code') .argument('<task_id>', 'ID of the task to start') .action(async (taskId: string) => { await this.execute(taskId); }); } public async execute(taskId: string): Promise<void> { // Implementation will be added in subsequent tasks } } ``` # Test Strategy: Verify the command registers correctly by running the CLI with --help and checking that the start command appears with proper description and arguments. Test the basic structure by ensuring the command can be invoked without errors. ``` -------------------------------------------------------------------------------- /packages/tm-core/src/constants/index.ts: -------------------------------------------------------------------------------- ```typescript /** * @fileoverview Constants for Task Master Core * Single source of truth for all constant values */ import type { TaskStatus, TaskPriority, TaskComplexity } from '../types/index.js'; /** * Valid task status values */ export const TASK_STATUSES: readonly TaskStatus[] = [ 'pending', 'in-progress', 'done', 'deferred', 'cancelled', 'blocked', 'review' ] as const; /** * Valid task priority values */ export const TASK_PRIORITIES: readonly TaskPriority[] = [ 'low', 'medium', 'high', 'critical' ] as const; /** * Valid task complexity values */ export const TASK_COMPLEXITIES: readonly TaskComplexity[] = [ 'simple', 'moderate', 'complex', 'very-complex' ] as const; /** * Valid output formats for task display */ export const OUTPUT_FORMATS = ['text', 'json', 'compact'] as const; export type OutputFormat = (typeof OUTPUT_FORMATS)[number]; /** * Status icons for display */ export const STATUS_ICONS: Record<TaskStatus, string> = { done: '✓', completed: '✓', 'in-progress': '►', blocked: '⭕', pending: '○', deferred: '⏸', cancelled: '✗', review: '👁' } as const; /** * Status colors for display (using chalk color names) */ export const STATUS_COLORS: Record<TaskStatus, string> = { pending: 'yellow', 'in-progress': 'blue', done: 'green', deferred: 'gray', cancelled: 'red', blocked: 'magenta', review: 'cyan', completed: 'green' } as const; ``` -------------------------------------------------------------------------------- /.claude/commands/tm/workflows/smart-workflow.md: -------------------------------------------------------------------------------- ```markdown Execute an intelligent workflow based on current project state and recent commands. This command analyzes: 1. Recent commands you've run 2. Current project state 3. Time of day / day of week 4. Your working patterns Arguments: $ARGUMENTS ## Intelligent Workflow Selection Based on context, I'll determine the best workflow: ### Context Analysis - Previous command executed - Current task states - Unfinished work from last session - Your typical patterns ### Smart Execution If last command was: - `status` → Likely starting work → Run daily standup - `complete` → Task finished → Find next task - `list pending` → Planning → Suggest sprint planning - `expand` → Breaking down work → Show complexity analysis - `init` → New project → Show onboarding workflow If no recent commands: - Morning? → Daily standup workflow - Many pending tasks? → Sprint planning - Tasks blocked? → Dependency resolution - Friday? → Weekly review ### Workflow Composition I'll chain appropriate commands: 1. Analyze current state 2. Execute primary workflow 3. Suggest follow-up actions 4. Prepare environment for coding ### Learning Mode This command learns from your patterns: - Track command sequences - Note time preferences - Remember common workflows - Adapt to your style Example flows detected: - Morning: standup → next → start - After lunch: status → continue task - End of day: complete → commit → status ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/workflows/smart-workflow.md: -------------------------------------------------------------------------------- ```markdown Execute an intelligent workflow based on current project state and recent commands. This command analyzes: 1. Recent commands you've run 2. Current project state 3. Time of day / day of week 4. Your working patterns Arguments: $ARGUMENTS ## Intelligent Workflow Selection Based on context, I'll determine the best workflow: ### Context Analysis - Previous command executed - Current task states - Unfinished work from last session - Your typical patterns ### Smart Execution If last command was: - `status` → Likely starting work → Run daily standup - `complete` → Task finished → Find next task - `list pending` → Planning → Suggest sprint planning - `expand` → Breaking down work → Show complexity analysis - `init` → New project → Show onboarding workflow If no recent commands: - Morning? → Daily standup workflow - Many pending tasks? → Sprint planning - Tasks blocked? → Dependency resolution - Friday? → Weekly review ### Workflow Composition I'll chain appropriate commands: 1. Analyze current state 2. Execute primary workflow 3. Suggest follow-up actions 4. Prepare environment for coding ### Learning Mode This command learns from your patterns: - Track command sequences - Note time preferences - Remember common workflows - Adapt to your style Example flows detected: - Morning: standup → next → start - After lunch: status → continue task - End of day: complete → commit → status ``` -------------------------------------------------------------------------------- /.kiro/steering/kiro_rules.md: -------------------------------------------------------------------------------- ```markdown --- inclusion: always --- - **Required Rule Structure:** ```markdown --- description: Clear, one-line description of what the rule enforces globs: path/to/files/*.ext, other/path/**/* alwaysApply: boolean --- - **Main Points in Bold** - Sub-points with details - Examples and explanations ``` - **File References:** - Use `[filename](mdc:path/to/file)` ([filename](mdc:filename)) to reference files - Example: [prisma.md](.kiro/steering/prisma.md) for rule references - Example: [schema.prisma](mdc:prisma/schema.prisma) for code references - **Code Examples:** - Use language-specific code blocks ```typescript // ✅ DO: Show good examples const goodExample = true; // ❌ DON'T: Show anti-patterns const badExample = false; ``` - **Rule Content Guidelines:** - Start with high-level overview - Include specific, actionable requirements - Show examples of correct implementation - Reference existing code when possible - Keep rules DRY by referencing other rules - **Rule Maintenance:** - Update rules when new patterns emerge - Add examples from actual codebase - Remove outdated patterns - Cross-reference related rules - **Best Practices:** - Use bullet points for clarity - Keep descriptions concise - Include both DO and DON'T examples - Reference actual code over theoretical examples - Use consistent formatting across rules ``` -------------------------------------------------------------------------------- /scripts/modules/update-config-tokens.js: -------------------------------------------------------------------------------- ```javascript /** * update-config-tokens.js * Updates config.json with correct maxTokens values from supported-models.json */ import fs from 'fs'; import supportedModels from './supported-models.json' with { type: 'json' }; /** * Updates the config file with correct maxTokens values from supported-models.json * @param {string} configPath - Path to the config.json file to update * @returns {boolean} True if successful, false otherwise */ export function updateConfigMaxTokens(configPath) { try { // Load config const config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); // Update each role's maxTokens if the model exists in supported-models.json const roles = ['main', 'research', 'fallback']; for (const role of roles) { if (config.models && config.models[role]) { const provider = config.models[role].provider; const modelId = config.models[role].modelId; // Find the model in supported models if (supportedModels[provider]) { const modelData = supportedModels[provider].find( (m) => m.id === modelId ); if (modelData && modelData.max_tokens) { config.models[role].maxTokens = modelData.max_tokens; } } } } // Write back the updated config fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); return true; } catch (error) { console.error('Error updating config maxTokens:', error.message); return false; } } ``` -------------------------------------------------------------------------------- /tests/unit/task-manager/clear-subtasks.test.js: -------------------------------------------------------------------------------- ```javascript import fs from 'fs'; import path from 'path'; import clearSubtasks from '../../../scripts/modules/task-manager/clear-subtasks.js'; const TMP = path.join(process.cwd(), '.tmp_clear_subtasks'); const TASKS = path.join(TMP, 'tasks.json'); function seed() { fs.rmSync(TMP, { recursive: true, force: true }); fs.mkdirSync(path.join(TMP, '.taskmaster'), { recursive: true }); fs.writeFileSync( TASKS, JSON.stringify( { master: { tasks: [ { id: 1, title: 'Parent', subtasks: [ { id: 1, title: 'Sub1' }, { id: 2, title: 'Sub2' } ] }, { id: 2, title: 'Solo' } ], metadata: { created: new Date().toISOString() } } }, null, 2 ) ); } describe('clearSubtasks', () => { beforeEach(seed); afterAll(() => fs.rmSync(TMP, { recursive: true, force: true })); it('clears subtasks for given task id', () => { clearSubtasks(TASKS, '1', { projectRoot: TMP, tag: 'master' }); const data = JSON.parse(fs.readFileSync(TASKS, 'utf8')); const parent = data.master.tasks.find((t) => t.id === 1); expect(parent.subtasks.length).toBe(0); }); it('does nothing when task has no subtasks', () => { clearSubtasks(TASKS, '2', { projectRoot: TMP, tag: 'master' }); const data = JSON.parse(fs.readFileSync(TASKS, 'utf8')); const solo = data.master.tasks.find((t) => t.id === 2); expect(solo.subtasks).toBeUndefined(); }); }); ``` -------------------------------------------------------------------------------- /mcp-server/src/core/utils/env-utils.js: -------------------------------------------------------------------------------- ```javascript /** * Temporarily sets environment variables from session.env, executes an action, * and restores the original environment variables. * @param {object | undefined} sessionEnv - The environment object from the session. * @param {Function} actionFn - An async function to execute with the temporary environment. * @returns {Promise<any>} The result of the actionFn. */ export async function withSessionEnv(sessionEnv, actionFn) { if ( !sessionEnv || typeof sessionEnv !== 'object' || Object.keys(sessionEnv).length === 0 ) { // If no sessionEnv is provided, just run the action directly return await actionFn(); } const originalEnv = {}; const keysToRestore = []; // Set environment variables from sessionEnv for (const key in sessionEnv) { if (Object.prototype.hasOwnProperty.call(sessionEnv, key)) { // Store original value if it exists, otherwise mark for deletion if (process.env[key] !== undefined) { originalEnv[key] = process.env[key]; } keysToRestore.push(key); process.env[key] = sessionEnv[key]; } } try { // Execute the provided action function return await actionFn(); } finally { // Restore original environment variables for (const key of keysToRestore) { if (Object.prototype.hasOwnProperty.call(originalEnv, key)) { process.env[key] = originalEnv[key]; } else { // If the key didn't exist originally, delete it delete process.env[key]; } } } } ``` -------------------------------------------------------------------------------- /packages/tm-core/src/index.ts: -------------------------------------------------------------------------------- ```typescript /** * @fileoverview Main entry point for the tm-core package * This file exports all public APIs from the core Task Master library */ // Export main facade export { TaskMasterCore, createTaskMasterCore, type TaskMasterCoreOptions, type ListTasksResult, type StartTaskOptions, type StartTaskResult, type ConflictCheckResult } from './task-master-core.js'; // Re-export types export type * from './types/index.js'; // Re-export interfaces (types only to avoid conflicts) export type * from './interfaces/index.js'; // Re-export constants export * from './constants/index.js'; // Re-export providers export * from './providers/index.js'; // Re-export storage (selectively to avoid conflicts) export { FileStorage, ApiStorage, StorageFactory, type ApiStorageConfig } from './storage/index.js'; export { PlaceholderStorage, type StorageAdapter } from './storage/index.js'; // Re-export parser export * from './parser/index.js'; // Re-export utilities export * from './utils/index.js'; // Re-export errors export * from './errors/index.js'; // Re-export entities export { TaskEntity } from './entities/task.entity.js'; // Re-export authentication export { AuthManager, AuthenticationError, type AuthCredentials, type OAuthFlowOptions, type AuthConfig } from './auth/index.js'; // Re-export logger export { getLogger, createLogger, setGlobalLogger } from './logger/index.js'; // Re-export executors export * from './executors/index.js'; ``` -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- ```javascript export default { // Use Node.js environment for testing testEnvironment: 'node', // Automatically clear mock calls between every test clearMocks: true, // Indicates whether the coverage information should be collected while executing the test collectCoverage: false, // The directory where Jest should output its coverage files coverageDirectory: 'coverage', // A list of paths to directories that Jest should use to search for files in roots: ['<rootDir>/tests'], // The glob patterns Jest uses to detect test files testMatch: ['**/__tests__/**/*.js', '**/?(*.)+(spec|test).js'], // Transform files preset: 'ts-jest/presets/default-esm', extensionsToTreatAsEsm: ['.ts'], moduleFileExtensions: ['js', 'ts', 'json', 'node'], transform: { '^.+\\.ts$': [ 'ts-jest', { useESM: true } ] }, // Disable transformations for node_modules transformIgnorePatterns: ['/node_modules/'], // Set moduleNameMapper for absolute paths moduleNameMapper: { '^@/(.*)$': '<rootDir>/$1' }, resolver: '<rootDir>/jest.resolver.cjs', // Setup module aliases moduleDirectories: ['node_modules', '<rootDir>'], // Configure test coverage thresholds coverageThreshold: { global: { branches: 80, functions: 80, lines: 80, statements: 80 } }, // Generate coverage report in these formats coverageReporters: ['text', 'lcov'], // Verbose output verbose: true, // Setup file setupFilesAfterEnv: ['<rootDir>/tests/setup.js'] }; ``` -------------------------------------------------------------------------------- /.claude/commands/tm/validate-dependencies/validate-dependencies.md: -------------------------------------------------------------------------------- ```markdown Validate all task dependencies for issues. ## Dependency Validation Comprehensive check for dependency problems across the entire project. ## Execution ```bash task-master validate-dependencies ``` ## Validation Checks 1. **Circular Dependencies** - A depends on B, B depends on A - Complex circular chains - Self-dependencies 2. **Missing Dependencies** - References to non-existent tasks - Deleted task references - Invalid task IDs 3. **Logical Issues** - Completed tasks depending on pending - Cancelled tasks in dependency chains - Impossible sequences 4. **Complexity Warnings** - Over-complex dependency chains - Too many dependencies per task - Bottleneck tasks ## Smart Analysis The validation provides: - Visual dependency graph - Critical path analysis - Bottleneck identification - Suggested optimizations ## Report Format ``` Dependency Validation Report ━━━━━━━━━━━━━━━━━━━━━━━━━━ ✅ No circular dependencies found ⚠️ 2 warnings found: - Task #23 has 7 dependencies (consider breaking down) - Task #45 blocks 5 other tasks (potential bottleneck) ❌ 1 error found: - Task #67 depends on deleted task #66 Critical Path: #1 → #5 → #23 → #45 → #50 (15 days) ``` ## Actionable Output For each issue found: - Clear description - Impact assessment - Suggested fix - Command to resolve ## Next Steps After validation: - Run `/project:tm/fix-dependencies` to auto-fix - Manually adjust problematic dependencies - Rerun to verify fixes ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/validate-dependencies/validate-dependencies.md: -------------------------------------------------------------------------------- ```markdown Validate all task dependencies for issues. ## Dependency Validation Comprehensive check for dependency problems across the entire project. ## Execution ```bash task-master validate-dependencies ``` ## Validation Checks 1. **Circular Dependencies** - A depends on B, B depends on A - Complex circular chains - Self-dependencies 2. **Missing Dependencies** - References to non-existent tasks - Deleted task references - Invalid task IDs 3. **Logical Issues** - Completed tasks depending on pending - Cancelled tasks in dependency chains - Impossible sequences 4. **Complexity Warnings** - Over-complex dependency chains - Too many dependencies per task - Bottleneck tasks ## Smart Analysis The validation provides: - Visual dependency graph - Critical path analysis - Bottleneck identification - Suggested optimizations ## Report Format ``` Dependency Validation Report ━━━━━━━━━━━━━━━━━━━━━━━━━━ ✅ No circular dependencies found ⚠️ 2 warnings found: - Task #23 has 7 dependencies (consider breaking down) - Task #45 blocks 5 other tasks (potential bottleneck) ❌ 1 error found: - Task #67 depends on deleted task #66 Critical Path: #1 → #5 → #23 → #45 → #50 (15 days) ``` ## Actionable Output For each issue found: - Clear description - Impact assessment - Suggested fix - Command to resolve ## Next Steps After validation: - Run `/project:tm/fix-dependencies` to auto-fix - Manually adjust problematic dependencies - Rerun to verify fixes ``` -------------------------------------------------------------------------------- /packages/tm-core/package.json: -------------------------------------------------------------------------------- ```json { "name": "@tm/core", "private": true, "description": "Core library for Task Master - TypeScript task management system", "type": "module", "types": "./src/index.ts", "main": "./dist/index.js", "exports": { ".": "./src/index.ts", "./auth": "./src/auth/index.ts", "./storage": "./src/storage/index.ts", "./config": "./src/config/index.ts", "./providers": "./src/providers/index.ts", "./services": "./src/services/index.ts", "./errors": "./src/errors/index.ts", "./logger": "./src/logger/index.ts", "./types": "./src/types/index.ts", "./interfaces": "./src/interfaces/index.ts", "./utils": "./src/utils/index.ts" }, "scripts": { "test": "vitest run", "test:watch": "vitest", "test:coverage": "vitest run --coverage", "lint": "biome check --write", "lint:check": "biome check", "lint:fix": "biome check --fix --unsafe", "format": "biome format --write", "format:check": "biome format", "typecheck": "tsc --noEmit" }, "dependencies": { "@supabase/supabase-js": "^2.57.4", "zod": "^3.23.8" }, "devDependencies": { "@biomejs/biome": "^1.9.4", "@tm/build-config": "*", "@types/node": "^22.10.5", "@vitest/coverage-v8": "^2.0.5", "dotenv-mono": "^1.5.1", "ts-node": "^10.9.2", "tsup": "^8.5.0", "typescript": "^5.7.3", "vitest": "^2.1.8" }, "engines": { "node": ">=18.0.0" }, "files": ["src", "README.md", "CHANGELOG.md"], "keywords": ["task-management", "typescript", "ai", "prd", "parser"], "author": "Task Master AI", "license": "MIT" } ``` -------------------------------------------------------------------------------- /tests/unit/task-manager/move-task.test.js: -------------------------------------------------------------------------------- ```javascript import fs from 'fs'; import path from 'path'; import moveTask from '../../../scripts/modules/task-manager/move-task.js'; const TMP = path.join(process.cwd(), '.tmp_move_task'); const TASKS = path.join(TMP, 'tasks.json'); function seed(initialTasks) { fs.rmSync(TMP, { recursive: true, force: true }); fs.mkdirSync(path.join(TMP, '.taskmaster'), { recursive: true }); fs.writeFileSync( TASKS, JSON.stringify( { master: { tasks: initialTasks, metadata: { created: new Date().toISOString() } } }, null, 2 ) ); } describe('moveTask basic scenarios', () => { afterAll(() => fs.rmSync(TMP, { recursive: true, force: true })); it('moves a task to a new ID within same tag', async () => { seed([ { id: 1, title: 'A' }, { id: 2, title: 'B' } ]); await moveTask(TASKS, '1', '3', false, { projectRoot: TMP, tag: 'master' }); const data = JSON.parse(fs.readFileSync(TASKS, 'utf8')); const ids = data.master.tasks.map((t) => t.id); expect(ids).toEqual(expect.arrayContaining([2, 3])); expect(ids).not.toContain(1); }); it('refuses to move across tags', async () => { // build dual-tag structure seed([{ id: 1, title: 'task' }]); const raw = JSON.parse(fs.readFileSync(TASKS, 'utf8')); raw.other = { tasks: [], metadata: { created: new Date().toISOString() } }; fs.writeFileSync(TASKS, JSON.stringify(raw, null, 2)); await expect( moveTask(TASKS, '1', '2', false, { projectRoot: TMP, tag: 'other' }) ).rejects.toThrow(/Source task/); }); }); ``` -------------------------------------------------------------------------------- /.taskmaster/templates/example_prd.txt: -------------------------------------------------------------------------------- ``` <context> # Overview [Provide a high-level overview of your product here. Explain what problem it solves, who it's for, and why it's valuable.] # Core Features [List and describe the main features of your product. For each feature, include: - What it does - Why it's important - How it works at a high level] # User Experience [Describe the user journey and experience. Include: - User personas - Key user flows - UI/UX considerations] </context> <PRD> # Technical Architecture [Outline the technical implementation details: - System components - Data models - APIs and integrations - Infrastructure requirements] # Development Roadmap [Break down the development process into phases: - MVP requirements - Future enhancements - Do not think about timelines whatsoever -- all that matters is scope and detailing exactly what needs to be build in each phase so it can later be cut up into tasks] # Logical Dependency Chain [Define the logical order of development: - Which features need to be built first (foundation) - Getting as quickly as possible to something usable/visible front end that works - Properly pacing and scoping each feature so it is atomic but can also be built upon and improved as development approaches] # Risks and Mitigations [Identify potential risks and how they'll be addressed: - Technical challenges - Figuring out the MVP that we can build upon - Resource constraints] # Appendix [Include any additional information: - Research findings - Technical specifications] </PRD> ``` -------------------------------------------------------------------------------- /assets/example_prd.txt: -------------------------------------------------------------------------------- ``` <context> # Overview [Provide a high-level overview of your product here. Explain what problem it solves, who it's for, and why it's valuable.] # Core Features [List and describe the main features of your product. For each feature, include: - What it does - Why it's important - How it works at a high level] # User Experience [Describe the user journey and experience. Include: - User personas - Key user flows - UI/UX considerations] </context> <PRD> # Technical Architecture [Outline the technical implementation details: - System components - Data models - APIs and integrations - Infrastructure requirements] # Development Roadmap [Break down the development process into phases: - MVP requirements - Future enhancements - Do not think about timelines whatsoever -- all that matters is scope and detailing exactly what needs to be build in each phase so it can later be cut up into tasks] # Logical Dependency Chain [Define the logical order of development: - Which features need to be built first (foundation) - Getting as quickly as possible to something usable/visible front end that works - Properly pacing and scoping each feature so it is atomic but can also be built upon and improved as development approaches] # Risks and Mitigations [Identify potential risks and how they'll be addressed: - Technical challenges - Figuring out the MVP that we can build upon - Resource constraints] # Appendix [Include any additional information: - Research findings - Technical specifications] </PRD> ``` -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- ```yaml name: Release on: push: branches: - main concurrency: ${{ github.workflow }}-${{ github.ref }} permissions: contents: write pull-requests: write id-token: write jobs: release: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-node@v4 with: node-version: 20 cache: "npm" - name: Cache node_modules uses: actions/cache@v4 with: path: | node_modules */*/node_modules key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-node- - name: Install Dependencies run: npm ci timeout-minutes: 2 - name: Check pre-release mode run: node ./.github/scripts/check-pre-release-mode.mjs "main" - name: Build packages run: npm run turbo:build env: NODE_ENV: production FORCE_COLOR: 1 TM_PUBLIC_BASE_DOMAIN: ${{ secrets.TM_PUBLIC_BASE_DOMAIN }} TM_PUBLIC_SUPABASE_URL: ${{ secrets.TM_PUBLIC_SUPABASE_URL }} TM_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.TM_PUBLIC_SUPABASE_ANON_KEY }} - name: Create Release Pull Request or Publish to npm uses: changesets/action@v1 with: publish: node ./.github/scripts/release.mjs env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} ``` -------------------------------------------------------------------------------- /apps/extension/src/components/ui/CollapsibleSection.tsx: -------------------------------------------------------------------------------- ```typescript import type React from 'react'; import { useState } from 'react'; import { Button } from './button'; import { ChevronDown, ChevronRight } from 'lucide-react'; import type { LucideIcon } from 'lucide-react'; interface CollapsibleSectionProps { title: string; icon?: LucideIcon; defaultExpanded?: boolean; className?: string; headerClassName?: string; contentClassName?: string; buttonClassName?: string; children: React.ReactNode; rightElement?: React.ReactNode; } export const CollapsibleSection: React.FC<CollapsibleSectionProps> = ({ title, icon: Icon, defaultExpanded = false, className = '', headerClassName = '', contentClassName = '', buttonClassName = 'text-vscode-foreground/70 hover:text-vscode-foreground', children, rightElement }) => { const [isExpanded, setIsExpanded] = useState(defaultExpanded); return ( <div className={`mb-8 ${className}`}> <div className={`flex items-center gap-2 mb-4 ${headerClassName}`}> <Button variant="ghost" size="sm" className={`p-0 h-auto ${buttonClassName}`} onClick={() => setIsExpanded(!isExpanded)} > {isExpanded ? ( <ChevronDown className="w-4 h-4 mr-1" /> ) : ( <ChevronRight className="w-4 h-4 mr-1" /> )} {Icon && <Icon className="w-4 h-4 mr-1" />} {title} </Button> {rightElement} </div> {isExpanded && ( <div className={`bg-widget-background rounded-lg p-4 border border-widget-border ${contentClassName}`} > {children} </div> )} </div> ); }; ``` -------------------------------------------------------------------------------- /apps/extension/src/webview/components/SidebarView.tsx: -------------------------------------------------------------------------------- ```typescript import React, { useState, useEffect } from 'react'; import { TaskMasterLogo } from '../../components/TaskMasterLogo'; interface SidebarViewProps { initialConnectionStatus?: boolean; } // Acquire VS Code API only once globally to avoid "already acquired" error const vscode = window.acquireVsCodeApi ? window.acquireVsCodeApi() : null; export const SidebarView: React.FC<SidebarViewProps> = ({ initialConnectionStatus = false }) => { const [isConnected, setIsConnected] = useState(initialConnectionStatus); useEffect(() => { const handleMessage = (event: MessageEvent) => { const message = event.data; if (message.type === 'connectionStatus') { setIsConnected(message.data.isConnected); } }; window.addEventListener('message', handleMessage); return () => { window.removeEventListener('message', handleMessage); }; }, []); const handleOpenBoard = () => { vscode?.postMessage({ command: 'openBoard' }); }; return ( <div className="h-full flex items-center justify-center p-6"> <div className="text-center"> <TaskMasterLogo className="w-20 h-20 mx-auto mb-5 opacity-80 text-vscode-foreground" /> <h2 className="text-xl font-semibold mb-6 text-vscode-foreground"> TaskMaster </h2> <button onClick={handleOpenBoard} className="w-full px-4 py-2 bg-vscode-button-background text-vscode-button-foreground rounded hover:bg-vscode-button-hoverBackground transition-colors text-sm font-medium" > Open Kanban Board </button> </div> </div> ); }; ``` -------------------------------------------------------------------------------- /apps/docs/getting-started/quick-start/requirements.mdx: -------------------------------------------------------------------------------- ```markdown --- title: Requirements sidebarTitle: "Requirements" --- Before you can start using TaskMaster AI, you'll need to install Node.js and set up at least one model API Key. ## 1. Node.js TaskMaster AI is built with Node.js and requires it to run. npm (Node Package Manager) comes bundled with Node.js. <Accordion title="Install Node.js"> ### Installation **Option 1: Download from official website** 1. Visit [nodejs.org](https://nodejs.org) 2. Download the **LTS (Long Term Support)** version for your operating system 3. Run the installer and follow the setup wizard **Option 2: Use a package manager** <CodeGroup> ```bash Windows (Chocolatey) choco install nodejs ``` ```bash Windows (winget) winget install OpenJS.NodeJS ``` </CodeGroup> </Accordion> ## 2. Model API Key Taskmaster utilizes AI across several commands, and those require a separate API key. For the purpose of a Quick Start we recommend setting up an API Key with Anthropic for your main model and Perplexity for your research model (optional but recommended). <Tip>Task Master shows API costs per command used. Most users load $5-10 on their keys and don't have to top it off for a few months.</Tip> At least one (1) of the following is required: 1. Anthropic API key (Claude API) - **recommended for Quick Start** 2. OpenAI API key 3. Google Gemini API key 4. Perplexity API key (for research model) 5. xAI API Key (for research or main model) 6. OpenRouter API Key (for research or main model) 7. Claude Code (no API key required - requires Claude Code CLI) ``` -------------------------------------------------------------------------------- /src/ai-providers/claude-code.js: -------------------------------------------------------------------------------- ```javascript /** * src/ai-providers/claude-code.js * * Implementation for interacting with Claude models via Claude Code CLI * using a custom AI SDK implementation. */ import { createClaudeCode } from './custom-sdk/claude-code/index.js'; import { BaseAIProvider } from './base-provider.js'; import { getClaudeCodeSettingsForCommand } from '../../scripts/modules/config-manager.js'; export class ClaudeCodeProvider extends BaseAIProvider { constructor() { super(); this.name = 'Claude Code'; } getRequiredApiKeyName() { return 'CLAUDE_CODE_API_KEY'; } isRequiredApiKey() { return false; } /** * Override validateAuth to skip API key validation for Claude Code * @param {object} params - Parameters to validate */ validateAuth(params) { // Claude Code doesn't require an API key // No validation needed } /** * Creates and returns a Claude Code client instance. * @param {object} params - Parameters for client initialization * @param {string} [params.commandName] - Name of the command invoking the service * @param {string} [params.baseURL] - Optional custom API endpoint (not used by Claude Code) * @returns {Function} Claude Code client function * @throws {Error} If initialization fails */ getClient(params) { try { // Claude Code doesn't use API keys or base URLs // Just return the provider factory return createClaudeCode({ defaultSettings: getClaudeCodeSettingsForCommand(params?.commandName) }); } catch (error) { this.handleError('client initialization', error); } } } ``` -------------------------------------------------------------------------------- /src/ai-providers/openai.js: -------------------------------------------------------------------------------- ```javascript /** * openai.js * AI provider implementation for OpenAI models using Vercel AI SDK. */ import { createOpenAI } from '@ai-sdk/openai'; import { BaseAIProvider } from './base-provider.js'; export class OpenAIProvider extends BaseAIProvider { constructor() { super(); this.name = 'OpenAI'; } /** * Returns the environment variable name required for this provider's API key. * @returns {string} The environment variable name for the OpenAI API key */ getRequiredApiKeyName() { return 'OPENAI_API_KEY'; } /** * Determines if a model requires max_completion_tokens instead of maxTokens * GPT-5 models require max_completion_tokens parameter * @param {string} modelId - The model ID to check * @returns {boolean} True if the model requires max_completion_tokens */ requiresMaxCompletionTokens(modelId) { return modelId && modelId.startsWith('gpt-5'); } /** * Creates and returns an OpenAI client instance. * @param {object} params - Parameters for client initialization * @param {string} params.apiKey - OpenAI API key * @param {string} [params.baseURL] - Optional custom API endpoint * @returns {Function} OpenAI client function * @throws {Error} If API key is missing or initialization fails */ getClient(params) { try { const { apiKey, baseURL } = params; if (!apiKey) { throw new Error('OpenAI API key is required.'); } return createOpenAI({ apiKey, ...(baseURL && { baseURL }) }); } catch (error) { this.handleError('client initialization', error); } } } ``` -------------------------------------------------------------------------------- /.claude/commands/tm/add-subtask/convert-task-to-subtask.md: -------------------------------------------------------------------------------- ```markdown Convert an existing task into a subtask. Arguments: $ARGUMENTS Parse parent ID and task ID to convert. ## Task Conversion Converts an existing standalone task into a subtask of another task. ## Argument Parsing - "move task 8 under 5" - "make 8 a subtask of 5" - "nest 8 in 5" - "5 8" → make task 8 a subtask of task 5 ## Execution ```bash task-master add-subtask --parent=<parent-id> --task-id=<task-to-convert> ``` ## Pre-Conversion Checks 1. **Validation** - Both tasks exist and are valid - No circular parent relationships - Task isn't already a subtask - Logical hierarchy makes sense 2. **Impact Analysis** - Dependencies that will be affected - Tasks that depend on converting task - Priority alignment needed - Status compatibility ## Conversion Process 1. Change task ID from "8" to "5.1" (next available) 2. Update all dependency references 3. Inherit parent's context where appropriate 4. Adjust priorities if needed 5. Update time estimates ## Smart Features - Preserve task history - Maintain dependencies - Update all references - Create conversion log ## Example ``` /project:tm/add-subtask/from-task 5 8 → Converting: Task #8 becomes subtask #5.1 → Updated: 3 dependency references → Parent task #5 now has 1 subtask → Note: Subtask inherits parent's priority Before: #8 "Implement validation" (standalone) After: #5.1 "Implement validation" (subtask of #5) ``` ## Post-Conversion - Show new task hierarchy - List updated dependencies - Verify project integrity - Suggest related conversions ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/add-subtask/convert-task-to-subtask.md: -------------------------------------------------------------------------------- ```markdown Convert an existing task into a subtask. Arguments: $ARGUMENTS Parse parent ID and task ID to convert. ## Task Conversion Converts an existing standalone task into a subtask of another task. ## Argument Parsing - "move task 8 under 5" - "make 8 a subtask of 5" - "nest 8 in 5" - "5 8" → make task 8 a subtask of task 5 ## Execution ```bash task-master add-subtask --parent=<parent-id> --task-id=<task-to-convert> ``` ## Pre-Conversion Checks 1. **Validation** - Both tasks exist and are valid - No circular parent relationships - Task isn't already a subtask - Logical hierarchy makes sense 2. **Impact Analysis** - Dependencies that will be affected - Tasks that depend on converting task - Priority alignment needed - Status compatibility ## Conversion Process 1. Change task ID from "8" to "5.1" (next available) 2. Update all dependency references 3. Inherit parent's context where appropriate 4. Adjust priorities if needed 5. Update time estimates ## Smart Features - Preserve task history - Maintain dependencies - Update all references - Create conversion log ## Example ``` /project:tm/add-subtask/from-task 5 8 → Converting: Task #8 becomes subtask #5.1 → Updated: 3 dependency references → Parent task #5 now has 1 subtask → Note: Subtask inherits parent's priority Before: #8 "Implement validation" (standalone) After: #5.1 "Implement validation" (subtask of #5) ``` ## Post-Conversion - Show new task hierarchy - List updated dependencies - Verify project integrity - Suggest related conversions ``` -------------------------------------------------------------------------------- /apps/extension/src/components/ui/scroll-area.tsx: -------------------------------------------------------------------------------- ```typescript import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'; import type * as React from 'react'; import { cn } from '@/lib/utils'; function ScrollArea({ className, children, ...props }: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) { return ( <ScrollAreaPrimitive.Root data-slot="scroll-area" className={cn('relative overflow-hidden', className)} {...props} > <ScrollAreaPrimitive.Viewport data-slot="scroll-area-viewport" className="focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1 overflow-y-auto" > {children} </ScrollAreaPrimitive.Viewport> <ScrollBar /> <ScrollAreaPrimitive.Corner /> </ScrollAreaPrimitive.Root> ); } function ScrollBar({ className, orientation = 'vertical', ...props }: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) { return ( <ScrollAreaPrimitive.ScrollAreaScrollbar data-slot="scroll-area-scrollbar" orientation={orientation} className={cn( 'flex touch-none p-px transition-colors select-none', orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent', orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent', className )} {...props} > <ScrollAreaPrimitive.ScrollAreaThumb data-slot="scroll-area-thumb" className="bg-border relative flex-1 rounded-full" /> </ScrollAreaPrimitive.ScrollAreaScrollbar> ); } export { ScrollArea, ScrollBar }; ``` -------------------------------------------------------------------------------- /apps/extension/src/components/ui/badge.tsx: -------------------------------------------------------------------------------- ```typescript import { Slot } from '@radix-ui/react-slot'; import { type VariantProps, cva } from 'class-variance-authority'; import type * as React from 'react'; import { cn } from '@/lib/utils'; const badgeVariants = cva( 'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden', { variants: { variant: { default: 'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90', secondary: 'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90', destructive: 'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', outline: 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground' } }, defaultVariants: { variant: 'default' } } ); function Badge({ className, variant, asChild = false, ...props }: React.ComponentProps<'span'> & VariantProps<typeof badgeVariants> & { asChild?: boolean }) { const Comp = asChild ? Slot : 'span'; return ( <Comp data-slot="badge" className={cn(badgeVariants({ variant }), className)} {...props} /> ); } export { Badge, badgeVariants }; ``` -------------------------------------------------------------------------------- /apps/extension/src/services/polling-strategies.ts: -------------------------------------------------------------------------------- ```typescript /** * Polling Strategies - Simplified * Different algorithms for polling intervals */ import type { PollingStrategy } from './polling-service'; /** * Fixed interval polling */ export class FixedIntervalStrategy implements PollingStrategy { constructor(private interval = 10000) {} calculateNextInterval(): number { return this.interval; } getName(): string { return 'fixed'; } } /** * Adaptive polling based on activity */ export class AdaptivePollingStrategy implements PollingStrategy { private readonly MIN_INTERVAL = 5000; // 5 seconds private readonly MAX_INTERVAL = 60000; // 1 minute private readonly BASE_INTERVAL = 10000; // 10 seconds calculateNextInterval(consecutiveNoChanges: number): number { // Start with base interval let interval = this.BASE_INTERVAL; // If no changes for a while, slow down if (consecutiveNoChanges > 5) { interval = Math.min( this.MAX_INTERVAL, this.BASE_INTERVAL * 1.5 ** (consecutiveNoChanges - 5) ); } else if (consecutiveNoChanges === 0) { // Recent change, poll more frequently interval = this.MIN_INTERVAL; } return Math.round(interval); } getName(): string { return 'adaptive'; } } /** * Create polling strategy from configuration */ export function createPollingStrategy(config: any): PollingStrategy { const type = config.get('polling.strategy', 'adaptive'); const interval = config.get('polling.interval', 10000); switch (type) { case 'fixed': return new FixedIntervalStrategy(interval); default: return new AdaptivePollingStrategy(); } } ``` -------------------------------------------------------------------------------- /packages/tm-core/src/executors/executor-factory.ts: -------------------------------------------------------------------------------- ```typescript /** * Factory for creating task executors */ import type { ITaskExecutor, ExecutorOptions, ExecutorType } from './types.js'; import { ClaudeExecutor } from './claude-executor.js'; import { getLogger } from '../logger/index.js'; export class ExecutorFactory { private static logger = getLogger('ExecutorFactory'); /** * Create an executor based on the provided options */ static create(options: ExecutorOptions): ITaskExecutor { this.logger.debug(`Creating executor of type: ${options.type}`); switch (options.type) { case 'claude': return new ClaudeExecutor(options.projectRoot, options.config); case 'shell': // Placeholder for shell executor throw new Error('Shell executor not yet implemented'); case 'custom': // Placeholder for custom executor throw new Error('Custom executor not yet implemented'); default: throw new Error(`Unknown executor type: ${options.type}`); } } /** * Get the default executor type based on available tools */ static async getDefaultExecutor( projectRoot: string ): Promise<ExecutorType | null> { // Check for Claude first const claudeExecutor = new ClaudeExecutor(projectRoot); if (await claudeExecutor.isAvailable()) { this.logger.info('Claude CLI detected as default executor'); return 'claude'; } // Could check for other executors here this.logger.warn('No default executor available'); return null; } /** * Get list of available executor types */ static getAvailableTypes(): ExecutorType[] { return ['claude', 'shell', 'custom']; } } ``` -------------------------------------------------------------------------------- /.claude/commands/tm/workflows/command-pipeline.md: -------------------------------------------------------------------------------- ```markdown Execute a pipeline of commands based on a specification. Arguments: $ARGUMENTS ## Command Pipeline Execution Parse pipeline specification from arguments. Supported formats: ### Simple Pipeline `init → expand-all → sprint-plan` ### Conditional Pipeline `status → if:pending>10 → sprint-plan → else → next` ### Iterative Pipeline `for:pending-tasks → expand → complexity-check` ### Smart Pipeline Patterns **1. Project Setup Pipeline** ``` init [prd] → expand-all → complexity-report → sprint-plan → show first-sprint ``` **2. Daily Work Pipeline** ``` standup → if:in-progress → continue → else → next → start ``` **3. Task Completion Pipeline** ``` complete [id] → git-commit → if:blocked-tasks-freed → show-freed → next ``` **4. Quality Check Pipeline** ``` list in-progress → for:each → check-idle-time → if:idle>1day → prompt-update ``` ### Pipeline Features **Variables** - Store results: `status → $count=pending-count` - Use in conditions: `if:$count>10` - Pass between commands: `expand $high-priority-tasks` **Error Handling** - On failure: `try:complete → catch:show-blockers` - Skip on error: `optional:test-run` - Retry logic: `retry:3:commit` **Parallel Execution** - Parallel branches: `[analyze | test | lint]` - Join results: `parallel → join:report` ### Execution Flow 1. Parse pipeline specification 2. Validate command sequence 3. Execute with state passing 4. Handle conditions and loops 5. Aggregate results 6. Show summary This enables complex workflows like: `parse-prd → expand-all → filter:complex>70 → assign:senior → sprint-plan:weighted` ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/workflows/command-pipeline.md: -------------------------------------------------------------------------------- ```markdown Execute a pipeline of commands based on a specification. Arguments: $ARGUMENTS ## Command Pipeline Execution Parse pipeline specification from arguments. Supported formats: ### Simple Pipeline `init → expand-all → sprint-plan` ### Conditional Pipeline `status → if:pending>10 → sprint-plan → else → next` ### Iterative Pipeline `for:pending-tasks → expand → complexity-check` ### Smart Pipeline Patterns **1. Project Setup Pipeline** ``` init [prd] → expand-all → complexity-report → sprint-plan → show first-sprint ``` **2. Daily Work Pipeline** ``` standup → if:in-progress → continue → else → next → start ``` **3. Task Completion Pipeline** ``` complete [id] → git-commit → if:blocked-tasks-freed → show-freed → next ``` **4. Quality Check Pipeline** ``` list in-progress → for:each → check-idle-time → if:idle>1day → prompt-update ``` ### Pipeline Features **Variables** - Store results: `status → $count=pending-count` - Use in conditions: `if:$count>10` - Pass between commands: `expand $high-priority-tasks` **Error Handling** - On failure: `try:complete → catch:show-blockers` - Skip on error: `optional:test-run` - Retry logic: `retry:3:commit` **Parallel Execution** - Parallel branches: `[analyze | test | lint]` - Join results: `parallel → join:report` ### Execution Flow 1. Parse pipeline specification 2. Validate command sequence 3. Execute with state passing 4. Handle conditions and loops 5. Aggregate results 6. Show summary This enables complex workflows like: `parse-prd → expand-all → filter:complex>70 → assign:senior → sprint-plan:weighted` ``` -------------------------------------------------------------------------------- /mcp-server/src/tools/get-operation-status.js: -------------------------------------------------------------------------------- ```javascript // mcp-server/src/tools/get-operation-status.js import { z } from 'zod'; import { createErrorResponse, createContentResponse } from './utils.js'; // Assuming these utils exist /** * Register the get_operation_status tool. * @param {FastMCP} server - FastMCP server instance. * @param {AsyncOperationManager} asyncManager - The async operation manager. */ export function registerGetOperationStatusTool(server, asyncManager) { server.addTool({ name: 'get_operation_status', description: 'Retrieves the status and result/error of a background operation.', parameters: z.object({ operationId: z.string().describe('The ID of the operation to check.') }), execute: async (args, { log }) => { try { const { operationId } = args; log.info(`Checking status for operation ID: ${operationId}`); const status = asyncManager.getStatus(operationId); // Status will now always return an object, but it might have status='not_found' if (status.status === 'not_found') { log.warn(`Operation ID not found: ${operationId}`); return createErrorResponse( status.error?.message || `Operation ID not found: ${operationId}`, status.error?.code || 'OPERATION_NOT_FOUND' ); } log.info(`Status for ${operationId}: ${status.status}`); return createContentResponse(status); } catch (error) { log.error(`Error in get_operation_status tool: ${error.message}`, { stack: error.stack }); return createErrorResponse( `Failed to get operation status: ${error.message}`, 'GET_STATUS_ERROR' ); } } }); } ``` -------------------------------------------------------------------------------- /.claude/commands/tm/list/list-tasks.md: -------------------------------------------------------------------------------- ```markdown List tasks with intelligent argument parsing. Parse arguments to determine filters and display options: - Status: pending, in-progress, done, review, deferred, cancelled - Priority: high, medium, low (or priority:high) - Special: subtasks, tree, dependencies, blocked - IDs: Direct numbers (e.g., "1,3,5" or "1-5") - Complex: "pending high" = pending AND high priority Arguments: $ARGUMENTS Let me parse your request intelligently: 1. **Detect Filter Intent** - If arguments contain status keywords → filter by status - If arguments contain priority → filter by priority - If arguments contain "subtasks" → include subtasks - If arguments contain "tree" → hierarchical view - If arguments contain numbers → show specific tasks - If arguments contain "blocked" → show blocked tasks only 2. **Smart Combinations** Examples of what I understand: - "pending high" → pending tasks with high priority - "done today" → tasks completed today - "blocked" → tasks with unmet dependencies - "1-5" → tasks 1 through 5 - "subtasks tree" → hierarchical view with subtasks 3. **Execute Appropriate Query** Based on parsed intent, run the most specific task-master command 4. **Enhanced Display** - Group by relevant criteria - Show most important information first - Use visual indicators for quick scanning - Include relevant metrics 5. **Intelligent Suggestions** Based on what you're viewing, suggest next actions: - Many pending? → Suggest priority order - Many blocked? → Show dependency resolution - Looking at specific tasks? → Show related tasks ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/list/list-tasks.md: -------------------------------------------------------------------------------- ```markdown List tasks with intelligent argument parsing. Parse arguments to determine filters and display options: - Status: pending, in-progress, done, review, deferred, cancelled - Priority: high, medium, low (or priority:high) - Special: subtasks, tree, dependencies, blocked - IDs: Direct numbers (e.g., "1,3,5" or "1-5") - Complex: "pending high" = pending AND high priority Arguments: $ARGUMENTS Let me parse your request intelligently: 1. **Detect Filter Intent** - If arguments contain status keywords → filter by status - If arguments contain priority → filter by priority - If arguments contain "subtasks" → include subtasks - If arguments contain "tree" → hierarchical view - If arguments contain numbers → show specific tasks - If arguments contain "blocked" → show blocked tasks only 2. **Smart Combinations** Examples of what I understand: - "pending high" → pending tasks with high priority - "done today" → tasks completed today - "blocked" → tasks with unmet dependencies - "1-5" → tasks 1 through 5 - "subtasks tree" → hierarchical view with subtasks 3. **Execute Appropriate Query** Based on parsed intent, run the most specific task-master command 4. **Enhanced Display** - Group by relevant criteria - Show most important information first - Use visual indicators for quick scanning - Include relevant metrics 5. **Intelligent Suggestions** Based on what you're viewing, suggest next actions: - Many pending? → Suggest priority order - Many blocked? → Show dependency resolution - Looking at specific tasks? → Show related tasks ``` -------------------------------------------------------------------------------- /test-config-manager.js: -------------------------------------------------------------------------------- ```javascript // test-config-manager.js console.log('=== ENVIRONMENT TEST ==='); console.log('Working directory:', process.cwd()); console.log('NODE_PATH:', process.env.NODE_PATH); // Test basic imports try { console.log('Importing config-manager'); // Use dynamic import for ESM const configManagerModule = await import( './scripts/modules/config-manager.js' ); const configManager = configManagerModule.default || configManagerModule; console.log('Config manager loaded successfully'); console.log('Loading supported models'); // Add after line 14 (after "Config manager loaded successfully") console.log('Config manager exports:', Object.keys(configManager)); } catch (error) { console.error('Import error:', error.message); console.error(error.stack); } // Test file access try { console.log('Checking for .taskmasterconfig'); // Use dynamic import for ESM const { readFileSync, existsSync } = await import('fs'); const { resolve } = await import('path'); const configExists = existsSync('./.taskmasterconfig'); console.log('.taskmasterconfig exists:', configExists); if (configExists) { const config = JSON.parse(readFileSync('./.taskmasterconfig', 'utf-8')); console.log('Config keys:', Object.keys(config)); } console.log('Checking for supported-models.json'); const modelsPath = resolve('./scripts/modules/supported-models.json'); console.log('Models path:', modelsPath); const modelsExists = existsSync(modelsPath); console.log('supported-models.json exists:', modelsExists); } catch (error) { console.error('File access error:', error.message); } console.log('=== TEST COMPLETE ==='); ``` -------------------------------------------------------------------------------- /src/ai-providers/azure.js: -------------------------------------------------------------------------------- ```javascript /** * azure.js * AI provider implementation for Azure OpenAI models using Vercel AI SDK. */ import { createAzure } from '@ai-sdk/azure'; import { BaseAIProvider } from './base-provider.js'; export class AzureProvider extends BaseAIProvider { constructor() { super(); this.name = 'Azure OpenAI'; } /** * Returns the environment variable name required for this provider's API key. * @returns {string} The environment variable name for the Azure OpenAI API key */ getRequiredApiKeyName() { return 'AZURE_OPENAI_API_KEY'; } /** * Validates Azure-specific authentication parameters * @param {object} params - Parameters to validate * @throws {Error} If required parameters are missing */ validateAuth(params) { if (!params.apiKey) { throw new Error('Azure API key is required'); } if (!params.baseURL) { throw new Error( 'Azure endpoint URL is required. Set it in .taskmasterconfig global.azureBaseURL or models.[role].baseURL' ); } } /** * Creates and returns an Azure OpenAI client instance. * @param {object} params - Parameters for client initialization * @param {string} params.apiKey - Azure OpenAI API key * @param {string} params.baseURL - Azure OpenAI endpoint URL (from .taskmasterconfig global.azureBaseURL or models.[role].baseURL) * @returns {Function} Azure OpenAI client function * @throws {Error} If required parameters are missing or initialization fails */ getClient(params) { try { const { apiKey, baseURL } = params; return createAzure({ apiKey, baseURL }); } catch (error) { this.handleError('client initialization', error); } } } ``` -------------------------------------------------------------------------------- /tests/setup.js: -------------------------------------------------------------------------------- ```javascript /** * Jest setup file * * This file is run before each test suite to set up the test environment. */ import path from 'path'; import { fileURLToPath } from 'url'; // Capture the actual original working directory before any changes const originalWorkingDirectory = process.cwd(); // Store original working directory and project root const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const projectRoot = path.resolve(__dirname, '..'); // Ensure we're always starting from the project root if (process.cwd() !== projectRoot) { process.chdir(projectRoot); } // Mock environment variables process.env.MODEL = 'sonar-pro'; process.env.MAX_TOKENS = '64000'; process.env.TEMPERATURE = '0.2'; process.env.DEBUG = 'false'; process.env.TASKMASTER_LOG_LEVEL = 'error'; // Set to error to reduce noise in tests process.env.DEFAULT_SUBTASKS = '5'; process.env.DEFAULT_PRIORITY = 'medium'; process.env.PROJECT_NAME = 'Test Project'; process.env.PROJECT_VERSION = '1.0.0'; // Ensure tests don't make real API calls by setting mock API keys process.env.ANTHROPIC_API_KEY = 'test-mock-api-key-for-tests'; process.env.PERPLEXITY_API_KEY = 'test-mock-perplexity-key-for-tests'; // Add global test helpers if needed global.wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); // Store original working directory for tests that need it global.originalWorkingDirectory = originalWorkingDirectory; global.projectRoot = projectRoot; // If needed, silence console during tests if (process.env.SILENCE_CONSOLE === 'true') { global.console = { ...console, log: () => {}, info: () => {}, warn: () => {}, error: () => {} }; } ``` -------------------------------------------------------------------------------- /.claude/commands/tm/status/project-status.md: -------------------------------------------------------------------------------- ```markdown Enhanced status command with comprehensive project insights. Arguments: $ARGUMENTS ## Intelligent Status Overview ### 1. **Executive Summary** Quick dashboard view: - 🏃 Active work (in-progress tasks) - 📊 Progress metrics (% complete, velocity) - 🚧 Blockers and risks - ⏱️ Time analysis (estimated vs actual) - 🎯 Sprint/milestone progress ### 2. **Contextual Analysis** Based on $ARGUMENTS, focus on: - "sprint" → Current sprint progress and burndown - "blocked" → Dependency chains and resolution paths - "team" → Task distribution and workload - "timeline" → Schedule adherence and projections - "risk" → High complexity or overdue items ### 3. **Smart Insights** **Workflow Health:** - Idle tasks (in-progress > 24h without updates) - Bottlenecks (multiple tasks waiting on same dependency) - Quick wins (low complexity, high impact) **Predictive Analytics:** - Completion projections based on velocity - Risk of missing deadlines - Recommended task order for optimal flow ### 4. **Visual Intelligence** Dynamic visualization based on data: ``` Sprint Progress: ████████░░ 80% (16/20 tasks) Velocity Trend: ↗️ +15% this week Blocked Tasks: 🔴 3 critical path items Priority Distribution: High: ████████ 8 tasks (2 blocked) Medium: ████░░░░ 4 tasks Low: ██░░░░░░ 2 tasks ``` ### 5. **Actionable Recommendations** Based on analysis: 1. **Immediate actions** (unblock critical path) 2. **Today's focus** (optimal task sequence) 3. **Process improvements** (recurring patterns) 4. **Resource needs** (skills, time, dependencies) ### 6. **Historical Context** Compare to previous periods: - Velocity changes - Pattern recognition - Improvement areas - Success patterns to repeat ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/status/project-status.md: -------------------------------------------------------------------------------- ```markdown Enhanced status command with comprehensive project insights. Arguments: $ARGUMENTS ## Intelligent Status Overview ### 1. **Executive Summary** Quick dashboard view: - 🏃 Active work (in-progress tasks) - 📊 Progress metrics (% complete, velocity) - 🚧 Blockers and risks - ⏱️ Time analysis (estimated vs actual) - 🎯 Sprint/milestone progress ### 2. **Contextual Analysis** Based on $ARGUMENTS, focus on: - "sprint" → Current sprint progress and burndown - "blocked" → Dependency chains and resolution paths - "team" → Task distribution and workload - "timeline" → Schedule adherence and projections - "risk" → High complexity or overdue items ### 3. **Smart Insights** **Workflow Health:** - Idle tasks (in-progress > 24h without updates) - Bottlenecks (multiple tasks waiting on same dependency) - Quick wins (low complexity, high impact) **Predictive Analytics:** - Completion projections based on velocity - Risk of missing deadlines - Recommended task order for optimal flow ### 4. **Visual Intelligence** Dynamic visualization based on data: ``` Sprint Progress: ████████░░ 80% (16/20 tasks) Velocity Trend: ↗️ +15% this week Blocked Tasks: 🔴 3 critical path items Priority Distribution: High: ████████ 8 tasks (2 blocked) Medium: ████░░░░ 4 tasks Low: ██░░░░░░ 2 tasks ``` ### 5. **Actionable Recommendations** Based on analysis: 1. **Immediate actions** (unblock critical path) 2. **Today's focus** (optimal task sequence) 3. **Process improvements** (recurring patterns) 4. **Resource needs** (skills, time, dependencies) ### 6. **Historical Context** Compare to previous periods: - Velocity changes - Pattern recognition - Improvement areas - Success patterns to repeat ``` -------------------------------------------------------------------------------- /apps/docs/archive/examples.mdx: -------------------------------------------------------------------------------- ```markdown --- title: "Example Cursor AI Interactions" description: "Below are some common interactions with Cursor AI when using Task Master" --- <AccordionGroup> <Accordion title="Starting a new project"> ``` I've just initialized a new project with Claude Task Master. I have a PRD at scripts/prd.txt. Can you help me parse it and set up the initial tasks? ``` </Accordion> <Accordion title="Working on tasks"> ``` What's the next task I should work on? Please consider dependencies and priorities. ``` </Accordion> <Accordion title="Implementing a specific task"> ``` I'd like to implement task 4. Can you help me understand what needs to be done and how to approach it? ``` </Accordion> <Accordion title="Managing subtasks"> ``` I need to regenerate the subtasks for task 3 with a different approach. Can you help me clear and regenerate them? ``` </Accordion> <Accordion title="Handling changes"> ``` We've decided to use MongoDB instead of PostgreSQL. Can you update all future tasks to reflect this change? ``` </Accordion> <Accordion title="Completing work"> ``` I've finished implementing the authentication system described in task 2. All tests are passing. Please mark it as complete and tell me what I should work on next. ``` </Accordion> <Accordion title="Analyzing complexity"> ``` Can you analyze the complexity of our tasks to help me understand which ones need to be broken down further? ``` </Accordion> <Accordion title="Viewing complexity report"> ``` Can you show me the complexity report in a more readable format? ``` </Accordion> </AccordionGroup> ``` -------------------------------------------------------------------------------- /.taskmaster/tasks/task_007_tm-start.txt: -------------------------------------------------------------------------------- ``` # Task ID: 7 # Title: Integrate execution flow in start command # Status: pending # Dependencies: 3, 4 # Priority: high # Description: Connect all the components to implement the complete execution flow for the start command # Details: Update the execute method in the StartCommand class to integrate all the components and implement the complete execution flow as described in the PRD: 1. Validate task exists 2. Build standardized prompt 3. Execute claude-code 4. Check git status for changes 5. Auto-mark task as done if changes detected ```typescript public async execute(taskId: string): Promise<void> { // Validate task exists const core = await createTaskMasterCore(); const task = await core.tasks.getById(parseInt(taskId, 10)); if (!task) { console.error(`Task with ID ${taskId} not found`); process.exit(1); } // Build prompt const prompt = this.buildPrompt(taskId); // Execute claude-code await this.executeClaude(prompt); // Check git status const changedFiles = await this.checkGitChanges(); if (changedFiles.length > 0) { console.log('\nChanges detected in the following files:'); changedFiles.forEach(file => console.log(`- ${file}`)); // Auto-mark task as done await this.markTaskAsDone(taskId); console.log(`\nTask ${taskId} completed successfully and marked as done.`); } else { console.warn('\nNo changes detected after claude-code execution. Task not marked as done.'); } } ``` # Test Strategy: Test the complete execution flow by running the start command with a valid task ID and verifying that all steps are executed correctly. Test with both scenarios: when changes are detected and when no changes are detected. ``` -------------------------------------------------------------------------------- /mcp-server/src/tools/rules.js: -------------------------------------------------------------------------------- ```javascript /** * tools/rules.js * Tool to add or remove rules from a project (MCP server) */ import { z } from 'zod'; import { createErrorResponse, handleApiResult, withNormalizedProjectRoot } from './utils.js'; import { rulesDirect } from '../core/direct-functions/rules.js'; import { RULE_PROFILES } from '../../../src/constants/profiles.js'; /** * Register the rules tool with the MCP server * @param {Object} server - FastMCP server instance */ export function registerRulesTool(server) { server.addTool({ name: 'rules', description: 'Add or remove rule profiles from the project.', parameters: z.object({ action: z .enum(['add', 'remove']) .describe('Whether to add or remove rule profiles.'), profiles: z .array(z.enum(RULE_PROFILES)) .min(1) .describe( `List of rule profiles to add or remove (e.g., [\"cursor\", \"roo\"]). Available options: ${RULE_PROFILES.join(', ')}` ), projectRoot: z .string() .describe( 'The root directory of the project. Must be an absolute path.' ), force: z .boolean() .optional() .default(false) .describe( 'DANGEROUS: Force removal even if it would leave no rule profiles. Only use if you are absolutely certain.' ) }), execute: withNormalizedProjectRoot(async (args, { log, session }) => { try { log.info( `[rules tool] Executing action: ${args.action} for profiles: ${args.profiles.join(', ')} in ${args.projectRoot}` ); const result = await rulesDirect(args, log, { session }); return handleApiResult(result, log); } catch (error) { log.error(`[rules tool] Error: ${error.message}`); return createErrorResponse(error.message, { details: error.stack }); } }) }); } ``` -------------------------------------------------------------------------------- /test-clean-tags.js: -------------------------------------------------------------------------------- ```javascript import fs from 'fs'; import { createTag, listTags } from './scripts/modules/task-manager/tag-management.js'; console.log('=== Testing Tag Management with Clean File ==='); // Create a clean test tasks.json file const testTasksPath = './test-tasks.json'; const cleanData = { master: { tasks: [ { id: 1, title: 'Test Task 1', status: 'pending' }, { id: 2, title: 'Test Task 2', status: 'done' } ], metadata: { created: new Date().toISOString(), description: 'Master tag' } } }; // Write clean test file fs.writeFileSync(testTasksPath, JSON.stringify(cleanData, null, 2)); console.log('Created clean test file'); try { // Test creating a new tag console.log('\n--- Testing createTag ---'); await createTag( testTasksPath, 'test-branch', { copyFromCurrent: true, description: 'Test branch' }, { projectRoot: process.cwd() }, 'json' ); // Read the file and check for corruption const resultData = JSON.parse(fs.readFileSync(testTasksPath, 'utf8')); console.log('Keys in result file:', Object.keys(resultData)); console.log('Has _rawTaggedData in file:', !!resultData._rawTaggedData); if (resultData._rawTaggedData) { console.log('❌ CORRUPTION DETECTED: _rawTaggedData found in file!'); } else { console.log('✅ SUCCESS: No _rawTaggedData corruption in file'); } // Test listing tags console.log('\n--- Testing listTags ---'); const tagList = await listTags( testTasksPath, {}, { projectRoot: process.cwd() }, 'json' ); console.log( 'Found tags:', tagList.tags.map((t) => t.name) ); } catch (error) { console.error('Error during test:', error.message); } finally { // Clean up test file if (fs.existsSync(testTasksPath)) { fs.unlinkSync(testTasksPath); console.log('\nCleaned up test file'); } } ``` -------------------------------------------------------------------------------- /.claude/commands/tm/add-subtask/add-subtask.md: -------------------------------------------------------------------------------- ```markdown Add a subtask to a parent task. Arguments: $ARGUMENTS Parse arguments to create a new subtask or convert existing task. ## Adding Subtasks Creates subtasks to break down complex parent tasks into manageable pieces. ## Argument Parsing Flexible natural language: - "add subtask to 5: implement login form" - "break down 5 with: setup, implement, test" - "subtask for 5: handle edge cases" - "5: validate user input" → adds subtask to task 5 ## Execution Modes ### 1. Create New Subtask ```bash task-master add-subtask --parent=<id> --title="<title>" --description="<desc>" ``` ### 2. Convert Existing Task ```bash task-master add-subtask --parent=<id> --task-id=<existing-id> ``` ## Smart Features 1. **Automatic Subtask Generation** - If title contains "and" or commas, create multiple - Suggest common subtask patterns - Inherit parent's context 2. **Intelligent Defaults** - Priority based on parent - Appropriate time estimates - Logical dependencies between subtasks 3. **Validation** - Check parent task complexity - Warn if too many subtasks - Ensure subtask makes sense ## Creation Process 1. Parse parent task context 2. Generate subtask with ID like "5.1" 3. Set appropriate defaults 4. Link to parent task 5. Update parent's time estimate ## Example Flows ``` /project:tm/add-subtask to 5: implement user authentication → Created subtask #5.1: "implement user authentication" → Parent task #5 now has 1 subtask → Suggested next subtasks: tests, documentation /project:tm/add-subtask 5: setup, implement, test → Created 3 subtasks: #5.1: setup #5.2: implement #5.3: test ``` ## Post-Creation - Show updated task hierarchy - Suggest logical next subtasks - Update complexity estimates - Recommend subtask order ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/add-subtask/add-subtask.md: -------------------------------------------------------------------------------- ```markdown Add a subtask to a parent task. Arguments: $ARGUMENTS Parse arguments to create a new subtask or convert existing task. ## Adding Subtasks Creates subtasks to break down complex parent tasks into manageable pieces. ## Argument Parsing Flexible natural language: - "add subtask to 5: implement login form" - "break down 5 with: setup, implement, test" - "subtask for 5: handle edge cases" - "5: validate user input" → adds subtask to task 5 ## Execution Modes ### 1. Create New Subtask ```bash task-master add-subtask --parent=<id> --title="<title>" --description="<desc>" ``` ### 2. Convert Existing Task ```bash task-master add-subtask --parent=<id> --task-id=<existing-id> ``` ## Smart Features 1. **Automatic Subtask Generation** - If title contains "and" or commas, create multiple - Suggest common subtask patterns - Inherit parent's context 2. **Intelligent Defaults** - Priority based on parent - Appropriate time estimates - Logical dependencies between subtasks 3. **Validation** - Check parent task complexity - Warn if too many subtasks - Ensure subtask makes sense ## Creation Process 1. Parse parent task context 2. Generate subtask with ID like "5.1" 3. Set appropriate defaults 4. Link to parent task 5. Update parent's time estimate ## Example Flows ``` /project:tm/add-subtask to 5: implement user authentication → Created subtask #5.1: "implement user authentication" → Parent task #5 now has 1 subtask → Suggested next subtasks: tests, documentation /project:tm/add-subtask 5: setup, implement, test → Created 3 subtasks: #5.1: setup #5.2: implement #5.3: test ``` ## Post-Creation - Show updated task hierarchy - Suggest logical next subtasks - Update complexity estimates - Recommend subtask order ``` -------------------------------------------------------------------------------- /.claude/commands/tm/remove-subtasks/remove-subtasks.md: -------------------------------------------------------------------------------- ```markdown Clear all subtasks from a specific task. Arguments: $ARGUMENTS (task ID) Remove all subtasks from a parent task at once. ## Clearing Subtasks Bulk removal of all subtasks from a parent task. ## Execution ```bash task-master clear-subtasks --id=<task-id> ``` ## Pre-Clear Analysis 1. **Subtask Summary** - Number of subtasks - Completion status of each - Work already done - Dependencies affected 2. **Impact Assessment** - Data that will be lost - Dependencies to be removed - Effect on project timeline - Parent task implications ## Confirmation Required ``` Clear Subtasks Confirmation ━━━━━━━━━━━━━━━━━━━━━━━━━ Parent Task: #5 "Implement user authentication" Subtasks to remove: 4 - #5.1 "Setup auth framework" (done) - #5.2 "Create login form" (in-progress) - #5.3 "Add validation" (pending) - #5.4 "Write tests" (pending) ⚠️ This will permanently delete all subtask data Continue? (y/n) ``` ## Smart Features - Option to convert to standalone tasks - Backup task data before clearing - Preserve completed work history - Update parent task appropriately ## Process 1. List all subtasks for confirmation 2. Check for in-progress work 3. Remove all subtasks 4. Update parent task 5. Clean up dependencies ## Alternative Options Suggest alternatives: - Convert important subtasks to tasks - Keep completed subtasks - Archive instead of delete - Export subtask data first ## Post-Clear - Show updated parent task - Recalculate time estimates - Update task complexity - Suggest next steps ## Example ``` /project:tm/clear-subtasks 5 → Found 4 subtasks to remove → Warning: Subtask #5.2 is in-progress → Cleared all subtasks from task #5 → Updated parent task estimates → Suggestion: Consider re-expanding with better breakdown ``` ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/clear-subtasks/clear-subtasks.md: -------------------------------------------------------------------------------- ```markdown Clear all subtasks from a specific task. Arguments: $ARGUMENTS (task ID) Remove all subtasks from a parent task at once. ## Clearing Subtasks Bulk removal of all subtasks from a parent task. ## Execution ```bash task-master clear-subtasks --id=<task-id> ``` ## Pre-Clear Analysis 1. **Subtask Summary** - Number of subtasks - Completion status of each - Work already done - Dependencies affected 2. **Impact Assessment** - Data that will be lost - Dependencies to be removed - Effect on project timeline - Parent task implications ## Confirmation Required ``` Clear Subtasks Confirmation ━━━━━━━━━━━━━━━━━━━━━━━━━ Parent Task: #5 "Implement user authentication" Subtasks to remove: 4 - #5.1 "Setup auth framework" (done) - #5.2 "Create login form" (in-progress) - #5.3 "Add validation" (pending) - #5.4 "Write tests" (pending) ⚠️ This will permanently delete all subtask data Continue? (y/n) ``` ## Smart Features - Option to convert to standalone tasks - Backup task data before clearing - Preserve completed work history - Update parent task appropriately ## Process 1. List all subtasks for confirmation 2. Check for in-progress work 3. Remove all subtasks 4. Update parent task 5. Clean up dependencies ## Alternative Options Suggest alternatives: - Convert important subtasks to tasks - Keep completed subtasks - Archive instead of delete - Export subtask data first ## Post-Clear - Show updated parent task - Recalculate time estimates - Update task complexity - Suggest next steps ## Example ``` /project:tm/clear-subtasks 5 → Found 4 subtasks to remove → Warning: Subtask #5.2 is in-progress → Cleared all subtasks from task #5 → Updated parent task estimates → Suggestion: Consider re-expanding with better breakdown ``` ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/remove-subtasks/remove-subtasks.md: -------------------------------------------------------------------------------- ```markdown Clear all subtasks from a specific task. Arguments: $ARGUMENTS (task ID) Remove all subtasks from a parent task at once. ## Clearing Subtasks Bulk removal of all subtasks from a parent task. ## Execution ```bash task-master clear-subtasks --id=<task-id> ``` ## Pre-Clear Analysis 1. **Subtask Summary** - Number of subtasks - Completion status of each - Work already done - Dependencies affected 2. **Impact Assessment** - Data that will be lost - Dependencies to be removed - Effect on project timeline - Parent task implications ## Confirmation Required ``` Clear Subtasks Confirmation ━━━━━━━━━━━━━━━━━━━━━━━━━ Parent Task: #5 "Implement user authentication" Subtasks to remove: 4 - #5.1 "Setup auth framework" (done) - #5.2 "Create login form" (in-progress) - #5.3 "Add validation" (pending) - #5.4 "Write tests" (pending) ⚠️ This will permanently delete all subtask data Continue? (y/n) ``` ## Smart Features - Option to convert to standalone tasks - Backup task data before clearing - Preserve completed work history - Update parent task appropriately ## Process 1. List all subtasks for confirmation 2. Check for in-progress work 3. Remove all subtasks 4. Update parent task 5. Clean up dependencies ## Alternative Options Suggest alternatives: - Convert important subtasks to tasks - Keep completed subtasks - Archive instead of delete - Export subtask data first ## Post-Clear - Show updated parent task - Recalculate time estimates - Update task complexity - Suggest next steps ## Example ``` /project:tm/clear-subtasks 5 → Found 4 subtasks to remove → Warning: Subtask #5.2 is in-progress → Cleared all subtasks from task #5 → Updated parent task estimates → Suggestion: Consider re-expanding with better breakdown ``` ``` -------------------------------------------------------------------------------- /.claude/commands/tm/remove-subtask/remove-subtask.md: -------------------------------------------------------------------------------- ```markdown Remove a subtask from its parent task. Arguments: $ARGUMENTS Parse subtask ID to remove, with option to convert to standalone task. ## Removing Subtasks Remove a subtask and optionally convert it back to a standalone task. ## Argument Parsing - "remove subtask 5.1" - "delete 5.1" - "convert 5.1 to task" → remove and convert - "5.1 standalone" → convert to standalone ## Execution Options ### 1. Delete Subtask ```bash task-master remove-subtask --id=<parentId.subtaskId> ``` ### 2. Convert to Standalone ```bash task-master remove-subtask --id=<parentId.subtaskId> --convert ``` ## Pre-Removal Checks 1. **Validate Subtask** - Verify subtask exists - Check completion status - Review dependencies 2. **Impact Analysis** - Other subtasks that depend on it - Parent task implications - Data that will be lost ## Removal Process ### For Deletion: 1. Confirm if subtask has work done 2. Update parent task estimates 3. Remove subtask and its data 4. Clean up dependencies ### For Conversion: 1. Assign new standalone task ID 2. Preserve all task data 3. Update dependency references 4. Maintain task history ## Smart Features - Warn if subtask is in-progress - Show impact on parent task - Preserve important data - Update related estimates ## Example Flows ``` /project:tm/remove-subtask 5.1 → Warning: Subtask #5.1 is in-progress → This will delete all subtask data → Parent task #5 will be updated Confirm deletion? (y/n) /project:tm/remove-subtask 5.1 convert → Converting subtask #5.1 to standalone task #89 → Preserved: All task data and history → Updated: 2 dependency references → New task #89 is now independent ``` ## Post-Removal - Update parent task status - Recalculate estimates - Show updated hierarchy - Suggest next actions ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/remove-subtask/remove-subtask.md: -------------------------------------------------------------------------------- ```markdown Remove a subtask from its parent task. Arguments: $ARGUMENTS Parse subtask ID to remove, with option to convert to standalone task. ## Removing Subtasks Remove a subtask and optionally convert it back to a standalone task. ## Argument Parsing - "remove subtask 5.1" - "delete 5.1" - "convert 5.1 to task" → remove and convert - "5.1 standalone" → convert to standalone ## Execution Options ### 1. Delete Subtask ```bash task-master remove-subtask --id=<parentId.subtaskId> ``` ### 2. Convert to Standalone ```bash task-master remove-subtask --id=<parentId.subtaskId> --convert ``` ## Pre-Removal Checks 1. **Validate Subtask** - Verify subtask exists - Check completion status - Review dependencies 2. **Impact Analysis** - Other subtasks that depend on it - Parent task implications - Data that will be lost ## Removal Process ### For Deletion: 1. Confirm if subtask has work done 2. Update parent task estimates 3. Remove subtask and its data 4. Clean up dependencies ### For Conversion: 1. Assign new standalone task ID 2. Preserve all task data 3. Update dependency references 4. Maintain task history ## Smart Features - Warn if subtask is in-progress - Show impact on parent task - Preserve important data - Update related estimates ## Example Flows ``` /project:tm/remove-subtask 5.1 → Warning: Subtask #5.1 is in-progress → This will delete all subtask data → Parent task #5 will be updated Confirm deletion? (y/n) /project:tm/remove-subtask 5.1 convert → Converting subtask #5.1 to standalone task #89 → Preserved: All task data and history → Updated: 2 dependency references → New task #89 is now independent ``` ## Post-Removal - Update parent task status - Recalculate estimates - Show updated hierarchy - Suggest next actions ``` -------------------------------------------------------------------------------- /.claude/commands/tm/next/next-task.md: -------------------------------------------------------------------------------- ```markdown Intelligently determine and prepare the next action based on comprehensive context. This enhanced version of 'next' considers: - Current task states - Recent activity - Time constraints - Dependencies - Your working patterns Arguments: $ARGUMENTS ## Intelligent Next Action ### 1. **Context Gathering** Let me analyze the current situation: - Active tasks (in-progress) - Recently completed tasks - Blocked tasks - Time since last activity - Arguments provided: $ARGUMENTS ### 2. **Smart Decision Tree** **If you have an in-progress task:** - Has it been idle > 2 hours? → Suggest resuming or switching - Near completion? → Show remaining steps - Blocked? → Find alternative task **If no in-progress tasks:** - Unblocked high-priority tasks? → Start highest - Complex tasks need breakdown? → Suggest expansion - All tasks blocked? → Show dependency resolution **Special arguments handling:** - "quick" → Find task < 2 hours - "easy" → Find low complexity task - "important" → Find high priority regardless of complexity - "continue" → Resume last worked task ### 3. **Preparation Workflow** Based on selected task: 1. Show full context and history 2. Set up development environment 3. Run relevant tests 4. Open related files 5. Show similar completed tasks 6. Estimate completion time ### 4. **Alternative Suggestions** Always provide options: - Primary recommendation - Quick alternative (< 1 hour) - Strategic option (unblocks most tasks) - Learning option (new technology/skill) ### 5. **Workflow Integration** Seamlessly connect to: - `/project:task-master:start [selected]` - `/project:workflows:auto-implement` - `/project:task-master:expand` (if complex) - `/project:utils:complexity-report` (if unsure) The goal: Zero friction from decision to implementation. ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/next/next-task.md: -------------------------------------------------------------------------------- ```markdown Intelligently determine and prepare the next action based on comprehensive context. This enhanced version of 'next' considers: - Current task states - Recent activity - Time constraints - Dependencies - Your working patterns Arguments: $ARGUMENTS ## Intelligent Next Action ### 1. **Context Gathering** Let me analyze the current situation: - Active tasks (in-progress) - Recently completed tasks - Blocked tasks - Time since last activity - Arguments provided: $ARGUMENTS ### 2. **Smart Decision Tree** **If you have an in-progress task:** - Has it been idle > 2 hours? → Suggest resuming or switching - Near completion? → Show remaining steps - Blocked? → Find alternative task **If no in-progress tasks:** - Unblocked high-priority tasks? → Start highest - Complex tasks need breakdown? → Suggest expansion - All tasks blocked? → Show dependency resolution **Special arguments handling:** - "quick" → Find task < 2 hours - "easy" → Find low complexity task - "important" → Find high priority regardless of complexity - "continue" → Resume last worked task ### 3. **Preparation Workflow** Based on selected task: 1. Show full context and history 2. Set up development environment 3. Run relevant tests 4. Open related files 5. Show similar completed tasks 6. Estimate completion time ### 4. **Alternative Suggestions** Always provide options: - Primary recommendation - Quick alternative (< 1 hour) - Strategic option (unblocks most tasks) - Learning option (new technology/skill) ### 5. **Workflow Integration** Seamlessly connect to: - `/project:task-master:start [selected]` - `/project:workflows:auto-implement` - `/project:task-master:expand` (if complex) - `/project:utils:complexity-report` (if unsure) The goal: Zero friction from decision to implementation. ``` -------------------------------------------------------------------------------- /.claude/commands/tm/fix-dependencies/fix-dependencies.md: -------------------------------------------------------------------------------- ```markdown Automatically fix dependency issues found during validation. ## Automatic Dependency Repair Intelligently fixes common dependency problems while preserving project logic. ## Execution ```bash task-master fix-dependencies ``` ## What Gets Fixed ### 1. **Auto-Fixable Issues** - Remove references to deleted tasks - Break simple circular dependencies - Remove self-dependencies - Clean up duplicate dependencies ### 2. **Smart Resolutions** - Reorder dependencies to maintain logic - Suggest task merging for over-dependent tasks - Flatten unnecessary dependency chains - Remove redundant transitive dependencies ### 3. **Manual Review Required** - Complex circular dependencies - Critical path modifications - Business logic dependencies - High-impact changes ## Fix Process 1. **Analysis Phase** - Run validation check - Categorize issues by type - Determine fix strategy 2. **Execution Phase** - Apply automatic fixes - Log all changes made - Preserve task relationships 3. **Verification Phase** - Re-validate after fixes - Show before/after comparison - Highlight manual fixes needed ## Smart Features - Preserves intended task flow - Minimal disruption approach - Creates fix history/log - Suggests manual interventions ## Output Example ``` Dependency Auto-Fix Report ━━━━━━━━━━━━━━━━━━━━━━━━ Fixed Automatically: ✅ Removed 2 references to deleted tasks ✅ Resolved 1 self-dependency ✅ Cleaned 3 redundant dependencies Manual Review Needed: ⚠️ Complex circular dependency: #12 → #15 → #18 → #12 Suggestion: Make #15 not depend on #12 ⚠️ Task #45 has 8 dependencies Suggestion: Break into subtasks Run '/project:tm/validate-dependencies' to verify fixes ``` ## Safety - Preview mode available - Rollback capability - Change logging - No data loss ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/fix-dependencies/fix-dependencies.md: -------------------------------------------------------------------------------- ```markdown Automatically fix dependency issues found during validation. ## Automatic Dependency Repair Intelligently fixes common dependency problems while preserving project logic. ## Execution ```bash task-master fix-dependencies ``` ## What Gets Fixed ### 1. **Auto-Fixable Issues** - Remove references to deleted tasks - Break simple circular dependencies - Remove self-dependencies - Clean up duplicate dependencies ### 2. **Smart Resolutions** - Reorder dependencies to maintain logic - Suggest task merging for over-dependent tasks - Flatten unnecessary dependency chains - Remove redundant transitive dependencies ### 3. **Manual Review Required** - Complex circular dependencies - Critical path modifications - Business logic dependencies - High-impact changes ## Fix Process 1. **Analysis Phase** - Run validation check - Categorize issues by type - Determine fix strategy 2. **Execution Phase** - Apply automatic fixes - Log all changes made - Preserve task relationships 3. **Verification Phase** - Re-validate after fixes - Show before/after comparison - Highlight manual fixes needed ## Smart Features - Preserves intended task flow - Minimal disruption approach - Creates fix history/log - Suggests manual interventions ## Output Example ``` Dependency Auto-Fix Report ━━━━━━━━━━━━━━━━━━━━━━━━ Fixed Automatically: ✅ Removed 2 references to deleted tasks ✅ Resolved 1 self-dependency ✅ Cleaned 3 redundant dependencies Manual Review Needed: ⚠️ Complex circular dependency: #12 → #15 → #18 → #12 Suggestion: Make #15 not depend on #12 ⚠️ Task #45 has 8 dependencies Suggestion: Break into subtasks Run '/project:tm/validate-dependencies' to verify fixes ``` ## Safety - Preview mode available - Rollback capability - Change logging - No data loss ``` -------------------------------------------------------------------------------- /src/ai-providers/custom-sdk/grok-cli/types.js: -------------------------------------------------------------------------------- ```javascript /** * @fileoverview Type definitions for Grok CLI provider */ /** * @typedef {Object} GrokCliSettings * @property {string} [apiKey] - API key for Grok CLI * @property {string} [baseURL] - Base URL for Grok API * @property {string} [model] - Default model to use * @property {number} [timeout] - Timeout in milliseconds * @property {string} [workingDirectory] - Working directory for CLI commands */ /** * @typedef {string} GrokCliModelId * Model identifiers supported by Grok CLI */ /** * @typedef {Object} GrokCliErrorMetadata * @property {string} [code] - Error code * @property {number} [exitCode] - Process exit code * @property {string} [stderr] - Standard error output * @property {string} [stdout] - Standard output * @property {string} [promptExcerpt] - Excerpt of the prompt that caused the error * @property {number} [timeoutMs] - Timeout value in milliseconds */ /** * @typedef {Function} GrokCliProvider * @property {Function} languageModel - Create a language model * @property {Function} chat - Alias for languageModel * @property {Function} textEmbeddingModel - Text embedding model (throws error) */ /** * @typedef {Object} GrokCliProviderSettings * @property {GrokCliSettings} [defaultSettings] - Default settings for all models */ /** * @typedef {Object} GrokCliMessage * @property {string} role - Message role (user, assistant, system) * @property {string} content - Message content */ /** * @typedef {Object} GrokCliResponse * @property {string} content - Response content * @property {Object} [usage] - Token usage information * @property {number} [usage.prompt_tokens] - Input tokens used * @property {number} [usage.completion_tokens] - Output tokens used * @property {number} [usage.total_tokens] - Total tokens used */ export {}; ``` -------------------------------------------------------------------------------- /packages/tm-core/src/errors/index.ts: -------------------------------------------------------------------------------- ```typescript /** * @fileoverview Custom error classes for the tm-core package * This file exports all custom error types and error handling utilities */ // Export the main TaskMasterError class export { TaskMasterError, ERROR_CODES, type ErrorCode, type ErrorContext, type SerializableError } from './task-master-error.js'; // Error implementations will be defined here // export * from './task-errors.js'; // export * from './storage-errors.js'; // export * from './provider-errors.js'; // export * from './validation-errors.js'; // Placeholder exports - these will be implemented in later tasks /** * Base error class for all tm-core errors * @deprecated This is a placeholder class that will be properly implemented in later tasks */ export class TmCoreError extends Error { constructor( message: string, public code?: string ) { super(message); this.name = 'TmCoreError'; } } /** * Error thrown when a task is not found * @deprecated This is a placeholder class that will be properly implemented in later tasks */ export class TaskNotFoundError extends TmCoreError { constructor(taskId: string) { super(`Task not found: ${taskId}`, 'TASK_NOT_FOUND'); this.name = 'TaskNotFoundError'; } } /** * Error thrown when validation fails * @deprecated This is a placeholder class that will be properly implemented in later tasks */ export class ValidationError extends TmCoreError { constructor(message: string) { super(message, 'VALIDATION_ERROR'); this.name = 'ValidationError'; } } /** * Error thrown when storage operations fail * @deprecated This is a placeholder class that will be properly implemented in later tasks */ export class StorageError extends TmCoreError { constructor(message: string) { super(message, 'STORAGE_ERROR'); this.name = 'StorageError'; } } ``` -------------------------------------------------------------------------------- /src/ai-providers/perplexity.js: -------------------------------------------------------------------------------- ```javascript /** * perplexity.js * AI provider implementation for Perplexity models using Vercel AI SDK. */ import { createPerplexity } from '@ai-sdk/perplexity'; import { BaseAIProvider } from './base-provider.js'; export class PerplexityAIProvider extends BaseAIProvider { constructor() { super(); this.name = 'Perplexity'; } /** * Returns the environment variable name required for this provider's API key. * @returns {string} The environment variable name for the Perplexity API key */ getRequiredApiKeyName() { return 'PERPLEXITY_API_KEY'; } /** * Creates and returns a Perplexity client instance. * @param {object} params - Parameters for client initialization * @param {string} params.apiKey - Perplexity API key * @param {string} [params.baseURL] - Optional custom API endpoint * @returns {Function} Perplexity client function * @throws {Error} If API key is missing or initialization fails */ getClient(params) { try { const { apiKey, baseURL } = params; if (!apiKey) { throw new Error('Perplexity API key is required.'); } return createPerplexity({ apiKey, baseURL: baseURL || 'https://api.perplexity.ai' }); } catch (error) { this.handleError('client initialization', error); } } /** * Override generateObject to use JSON mode for Perplexity * * NOTE: Perplexity models (especially sonar models) have known issues * generating valid JSON, particularly with array fields. They often * generate malformed JSON like "dependencies": , instead of "dependencies": [] * * The base provider now handles JSON repair automatically for all providers. */ async generateObject(params) { // Force JSON mode for Perplexity as it may help with reliability return super.generateObject({ ...params, mode: 'json' }); } } ``` -------------------------------------------------------------------------------- /.claude/commands/tm/add-task/add-task.md: -------------------------------------------------------------------------------- ```markdown Add new tasks with intelligent parsing and context awareness. Arguments: $ARGUMENTS ## Smart Task Addition Parse natural language to create well-structured tasks. ### 1. **Input Understanding** I'll intelligently parse your request: - Natural language → Structured task - Detect priority from keywords (urgent, ASAP, important) - Infer dependencies from context - Suggest complexity based on description - Determine task type (feature, bug, refactor, test, docs) ### 2. **Smart Parsing Examples** **"Add urgent task to fix login bug"** → Title: Fix login bug → Priority: high → Type: bug → Suggested complexity: medium **"Create task for API documentation after task 23 is done"** → Title: API documentation → Dependencies: [23] → Type: documentation → Priority: medium **"Need to refactor auth module - depends on 12 and 15, high complexity"** → Title: Refactor auth module → Dependencies: [12, 15] → Complexity: high → Type: refactor ### 3. **Context Enhancement** Based on current project state: - Suggest related existing tasks - Warn about potential conflicts - Recommend dependencies - Propose subtasks if complex ### 4. **Interactive Refinement** ```yaml Task Preview: ───────────── Title: [Extracted title] Priority: [Inferred priority] Dependencies: [Detected dependencies] Complexity: [Estimated complexity] Suggestions: - Similar task #34 exists, consider as dependency? - This seems complex, break into subtasks? - Tasks #45-47 work on same module ``` ### 5. **Validation & Creation** Before creating: - Validate dependencies exist - Check for duplicates - Ensure logical ordering - Verify task completeness ### 6. **Smart Defaults** Intelligent defaults based on: - Task type patterns - Team conventions - Historical data - Current sprint/phase Result: High-quality tasks from minimal input. ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/add-task/add-task.md: -------------------------------------------------------------------------------- ```markdown Add new tasks with intelligent parsing and context awareness. Arguments: $ARGUMENTS ## Smart Task Addition Parse natural language to create well-structured tasks. ### 1. **Input Understanding** I'll intelligently parse your request: - Natural language → Structured task - Detect priority from keywords (urgent, ASAP, important) - Infer dependencies from context - Suggest complexity based on description - Determine task type (feature, bug, refactor, test, docs) ### 2. **Smart Parsing Examples** **"Add urgent task to fix login bug"** → Title: Fix login bug → Priority: high → Type: bug → Suggested complexity: medium **"Create task for API documentation after task 23 is done"** → Title: API documentation → Dependencies: [23] → Type: documentation → Priority: medium **"Need to refactor auth module - depends on 12 and 15, high complexity"** → Title: Refactor auth module → Dependencies: [12, 15] → Complexity: high → Type: refactor ### 3. **Context Enhancement** Based on current project state: - Suggest related existing tasks - Warn about potential conflicts - Recommend dependencies - Propose subtasks if complex ### 4. **Interactive Refinement** ```yaml Task Preview: ───────────── Title: [Extracted title] Priority: [Inferred priority] Dependencies: [Detected dependencies] Complexity: [Estimated complexity] Suggestions: - Similar task #34 exists, consider as dependency? - This seems complex, break into subtasks? - Tasks #45-47 work on same module ``` ### 5. **Validation & Creation** Before creating: - Validate dependencies exist - Check for duplicates - Ensure logical ordering - Verify task completeness ### 6. **Smart Defaults** Intelligent defaults based on: - Task type patterns - Team conventions - Historical data - Current sprint/phase Result: High-quality tasks from minimal input. ``` -------------------------------------------------------------------------------- /.claude/commands/dedupe.md: -------------------------------------------------------------------------------- ```markdown --- allowed-tools: Bash(gh issue view:*), Bash(gh search:*), Bash(gh issue list:*), Bash(gh api:*), Bash(gh issue comment:*) description: Find duplicate GitHub issues --- Find up to 3 likely duplicate issues for a given GitHub issue. To do this, follow these steps precisely: 1. Use an agent to check if the Github issue (a) is closed, (b) does not need to be deduped (eg. because it is broad product feedback without a specific solution, or positive feedback), or (c) already has a duplicates comment that you made earlier. If so, do not proceed. 2. Use an agent to view a Github issue, and ask the agent to return a summary of the issue 3. Then, launch 5 parallel agents to search Github for duplicates of this issue, using diverse keywords and search approaches, using the summary from #1 4. Next, feed the results from #1 and #2 into another agent, so that it can filter out false positives, that are likely not actually duplicates of the original issue. If there are no duplicates remaining, do not proceed. 5. Finally, comment back on the issue with a list of up to three duplicate issues (or zero, if there are no likely duplicates) Notes (be sure to tell this to your agents, too): - Use `gh` to interact with Github, rather than web fetch - Do not use other tools, beyond `gh` (eg. don't use other MCP servers, file edit, etc.) - Make a todo list first - For your comment, follow the following format precisely (assuming for this example that you found 3 suspected duplicates): --- Found 3 possible duplicate issues: 1. <link to issue> 2. <link to issue> 3. <link to issue> This issue will be automatically closed as a duplicate in 3 days. - If your issue is a duplicate, please close it and 👍 the existing issue instead - To prevent auto-closure, add a comment or 👎 this comment 🤖 Generated with \[Task Master Bot\] --- ``` -------------------------------------------------------------------------------- /apps/extension/src/components/ui/card.tsx: -------------------------------------------------------------------------------- ```typescript import type * as React from 'react'; import { cn } from '@/lib/utils'; function Card({ className, ...props }: React.ComponentProps<'div'>) { return ( <div data-slot="card" className={cn( 'bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm', className )} {...props} /> ); } function CardHeader({ className, ...props }: React.ComponentProps<'div'>) { return ( <div data-slot="card-header" className={cn( '@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6', className )} {...props} /> ); } function CardTitle({ className, ...props }: React.ComponentProps<'div'>) { return ( <div data-slot="card-title" className={cn('leading-none font-semibold', className)} {...props} /> ); } function CardDescription({ className, ...props }: React.ComponentProps<'div'>) { return ( <div data-slot="card-description" className={cn('text-muted-foreground text-sm', className)} {...props} /> ); } function CardAction({ className, ...props }: React.ComponentProps<'div'>) { return ( <div data-slot="card-action" className={cn( 'col-start-2 row-span-2 row-start-1 self-start justify-self-end', className )} {...props} /> ); } function CardContent({ className, ...props }: React.ComponentProps<'div'>) { return ( <div data-slot="card-content" className={cn('px-6', className)} {...props} /> ); } function CardFooter({ className, ...props }: React.ComponentProps<'div'>) { return ( <div data-slot="card-footer" className={cn('flex items-center px-6 [.border-t]:pt-6', className)} {...props} /> ); } export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent }; ``` -------------------------------------------------------------------------------- /apps/docs/docs.json: -------------------------------------------------------------------------------- ```json { "$schema": "https://mintlify.com/docs.json", "theme": "mint", "name": "Task Master", "colors": { "primary": "#3366CC", "light": "#6699FF", "dark": "#24478F" }, "favicon": "/favicon.svg", "navigation": { "tabs": [ { "tab": "Task Master Documentation", "groups": [ { "group": "Welcome", "pages": ["introduction"] }, { "group": "Getting Started", "pages": [ { "group": "Quick Start", "pages": [ "getting-started/quick-start/quick-start", "getting-started/quick-start/requirements", "getting-started/quick-start/installation", "getting-started/quick-start/configuration-quick", "getting-started/quick-start/prd-quick", "getting-started/quick-start/tasks-quick", "getting-started/quick-start/execute-quick" ] }, "getting-started/faq", "getting-started/contribute" ] }, { "group": "Best Practices", "pages": [ "best-practices/index", "best-practices/configuration-advanced", "best-practices/advanced-tasks" ] }, { "group": "Technical Capabilities", "pages": [ "capabilities/mcp", "capabilities/cli-root-commands", "capabilities/task-structure" ] } ] } ], "global": { "anchors": [ { "anchor": "Github", "href": "https://github.com/eyaltoledano/claude-task-master", "icon": "github" }, { "anchor": "Discord", "href": "https://discord.gg/fWJkU7rf", "icon": "discord" } ] } }, "logo": { "light": "/logo/task-master-logo.png", "dark": "/logo/task-master-logo.png" }, "footer": { "socials": { "x": "https://x.com/TaskmasterAI", "github": "https://github.com/eyaltoledano/claude-task-master" } } } ``` -------------------------------------------------------------------------------- /apps/extension/src/webview/components/PollingStatus.tsx: -------------------------------------------------------------------------------- ```typescript /** * Polling Status Indicator Component */ import React from 'react'; import type { AppState } from '../types'; interface PollingStatusProps { polling: AppState['polling']; onRetry?: () => void; } export const PollingStatus: React.FC<PollingStatusProps> = ({ polling, onRetry }) => { const { isActive, errorCount, isOfflineMode, connectionStatus, reconnectAttempts, maxReconnectAttempts } = polling; if (isOfflineMode || connectionStatus === 'offline') { return ( <div className="flex items-center gap-2"> <div className="flex items-center gap-1 text-red-400" title="Offline mode - using cached data" > <div className="w-2 h-2 rounded-full bg-red-400" /> <span className="text-xs">Offline</span> </div> <button onClick={onRetry} className="text-xs text-blue-400 hover:underline" title="Attempt to reconnect" > Retry </button> </div> ); } if (connectionStatus === 'reconnecting') { return ( <div className="flex items-center gap-1 text-yellow-400" title={`Reconnecting... (${reconnectAttempts}/${maxReconnectAttempts})`} > <div className="w-2 h-2 rounded-full bg-yellow-400 animate-pulse" /> <span className="text-xs">Reconnecting</span> </div> ); } if (errorCount > 0) { return ( <div className="flex items-center gap-1 text-yellow-400" title={`${errorCount} polling error${errorCount > 1 ? 's' : ''}`} > <div className="w-2 h-2 rounded-full bg-yellow-400" /> <span className="text-xs">Live (errors)</span> </div> ); } if (isActive) { return ( <div className="flex items-center gap-1 text-green-400" title="Live updates active" > <div className="w-2 h-2 rounded-full bg-green-400 animate-pulse" /> <span className="text-xs">Live</span> </div> ); } return null; }; ``` -------------------------------------------------------------------------------- /src/ai-providers/custom-sdk/grok-cli/json-extractor.js: -------------------------------------------------------------------------------- ```javascript /** * @fileoverview Extract JSON from Grok's response, handling markdown blocks and other formatting */ /** * Extract JSON from Grok's response * @param {string} text - The text to extract JSON from * @returns {string} - The extracted JSON string */ export function extractJson(text) { // Remove markdown code blocks if present let jsonText = text.trim(); // Remove ```json blocks jsonText = jsonText.replace(/^```json\s*/gm, ''); jsonText = jsonText.replace(/^```\s*/gm, ''); jsonText = jsonText.replace(/```\s*$/gm, ''); // Remove common TypeScript/JavaScript patterns jsonText = jsonText.replace(/^const\s+\w+\s*=\s*/, ''); // Remove "const varName = " jsonText = jsonText.replace(/^let\s+\w+\s*=\s*/, ''); // Remove "let varName = " jsonText = jsonText.replace(/^var\s+\w+\s*=\s*/, ''); // Remove "var varName = " jsonText = jsonText.replace(/;?\s*$/, ''); // Remove trailing semicolons // Try to extract JSON object or array const objectMatch = jsonText.match(/{[\s\S]*}/); const arrayMatch = jsonText.match(/\[[\s\S]*\]/); if (objectMatch) { jsonText = objectMatch[0]; } else if (arrayMatch) { jsonText = arrayMatch[0]; } // First try to parse as valid JSON try { JSON.parse(jsonText); return jsonText; } catch { // If it's not valid JSON, it might be a JavaScript object literal // Try to convert it to valid JSON try { // This is a simple conversion that handles basic cases // Replace unquoted keys with quoted keys const converted = jsonText .replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g, '$1"$2":') // Replace single quotes with double quotes .replace(/'/g, '"'); // Validate the converted JSON JSON.parse(converted); return converted; } catch { // If all else fails, return the original text // The AI SDK will handle the error appropriately return text; } } } ``` -------------------------------------------------------------------------------- /src/constants/profiles.js: -------------------------------------------------------------------------------- ```javascript /** * @typedef {'amp' | 'claude' | 'cline' | 'codex' | 'cursor' | 'gemini' | 'kiro' | 'opencode' | 'kilo' | 'roo' | 'trae' | 'windsurf' | 'vscode' | 'zed'} RulesProfile */ /** * Available rule profiles for project initialization and rules command * * ⚠️ SINGLE SOURCE OF TRUTH: This is the authoritative list of all supported rule profiles. * This constant is used directly throughout the codebase (previously aliased as PROFILE_NAMES). * * @type {RulesProfile[]} * @description Defines possible rule profile sets: * - amp: Amp Code integration * - claude: Claude Code integration * - cline: Cline IDE rules * - codex: Codex integration * - cursor: Cursor IDE rules * - gemini: Gemini integration * - kiro: Kiro IDE rules * - opencode: OpenCode integration * - kilo: Kilo Code integration * - roo: Roo Code IDE rules * - trae: Trae IDE rules * - vscode: VS Code with GitHub Copilot integration * - windsurf: Windsurf IDE rules * - zed: Zed IDE rules * * To add a new rule profile: * 1. Add the profile name to this array * 2. Create a profile file in src/profiles/{profile}.js * 3. Export it as {profile}Profile in src/profiles/index.js */ export const RULE_PROFILES = [ 'amp', 'claude', 'cline', 'codex', 'cursor', 'gemini', 'kiro', 'opencode', 'kilo', 'roo', 'trae', 'vscode', 'windsurf', 'zed' ]; /** * Centralized enum for all supported Roo agent modes * @type {string[]} * @description Available Roo Code IDE modes for rule generation */ export const ROO_MODES = [ 'architect', 'ask', 'orchestrator', 'code', 'debug', 'test' ]; /** * Check if a given rule profile is valid * @param {string} rulesProfile - The rule profile to check * @returns {boolean} True if the rule profile is valid, false otherwise */ export function isValidRulesProfile(rulesProfile) { return RULE_PROFILES.includes(rulesProfile); } ``` -------------------------------------------------------------------------------- /src/ai-providers/custom-sdk/claude-code/json-extractor.js: -------------------------------------------------------------------------------- ```javascript /** * @fileoverview Extract JSON from Claude's response, handling markdown blocks and other formatting */ /** * Extract JSON from Claude's response * @param {string} text - The text to extract JSON from * @returns {string} - The extracted JSON string */ export function extractJson(text) { // Remove markdown code blocks if present let jsonText = text.trim(); // Remove ```json blocks jsonText = jsonText.replace(/^```json\s*/gm, ''); jsonText = jsonText.replace(/^```\s*/gm, ''); jsonText = jsonText.replace(/```\s*$/gm, ''); // Remove common TypeScript/JavaScript patterns jsonText = jsonText.replace(/^const\s+\w+\s*=\s*/, ''); // Remove "const varName = " jsonText = jsonText.replace(/^let\s+\w+\s*=\s*/, ''); // Remove "let varName = " jsonText = jsonText.replace(/^var\s+\w+\s*=\s*/, ''); // Remove "var varName = " jsonText = jsonText.replace(/;?\s*$/, ''); // Remove trailing semicolons // Try to extract JSON object or array const objectMatch = jsonText.match(/{[\s\S]*}/); const arrayMatch = jsonText.match(/\[[\s\S]*\]/); if (objectMatch) { jsonText = objectMatch[0]; } else if (arrayMatch) { jsonText = arrayMatch[0]; } // First try to parse as valid JSON try { JSON.parse(jsonText); return jsonText; } catch { // If it's not valid JSON, it might be a JavaScript object literal // Try to convert it to valid JSON try { // This is a simple conversion that handles basic cases // Replace unquoted keys with quoted keys const converted = jsonText .replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g, '$1"$2":') // Replace single quotes with double quotes .replace(/'/g, '"'); // Validate the converted JSON JSON.parse(converted); return converted; } catch { // If all else fails, return the original text // The AI SDK will handle the error appropriately return text; } } } ``` -------------------------------------------------------------------------------- /apps/docs/getting-started/quick-start/execute-quick.mdx: -------------------------------------------------------------------------------- ```markdown --- title: Executing Tasks sidebarTitle: "Executing Tasks" --- Now that your tasks are generated and reviewed you are ready to begin executing. ## Select the Task to Work on: Next Task Task Master has the "next" command to find the next task to work on. You can access it with the following request: ``` What's the next task I should work on? Please consider dependencies and priorities. ``` Alternatively you can use the CLI to show the next task ```bash task-master next ``` ## Discuss Task When you know what task to work on next you can then start chatting with the agent to make sure it understands the plan of action. You can tag relevant files and folders so it knows what context to pull up as it generates its plan. For example: ``` Please review Task 5 and confirm you understand how to execute before beginning. Refer to @models @api and @schema ``` The agent will begin analyzing the task and files and respond with the steps to complete the task. ## Agent Task execution If you agree with the plan of action, tell the agent to get started. ``` You may begin. I believe in you. ``` ## Review and Test Once the agent is finished with the task you can refer to the task testing strategy to make sure it was completed correctly. ## Update Task Status If the task was completed correctly you can update the status to done ``` Please mark Task 5 as done ``` The agent will execute ```bash task-master set-status --id=5 --status=done ``` ## Rules and Context If you ran into problems and had to debug errors you can create new rules as you go. This helps build context on your codebase that helps the creation and execution of future tasks. ## On to the Next Task! By now you have all you need to get started executing code faster and smarter with Task Master. If you have any questions please check out [Frequently Asked Questions](/docs/getting-started/faq) ``` -------------------------------------------------------------------------------- /.taskmaster/tasks/task_003_tm-start.txt: -------------------------------------------------------------------------------- ``` # Task ID: 3 # Title: Create standardized prompt builder # Status: pending # Dependencies: 1 # Priority: medium # Description: Implement a function to build the standardized prompt for claude-code based on the task details # Details: Create a function in the StartCommand class that builds the standardized prompt according to the template provided in the PRD. The prompt should include instructions for Claude to first run `tm show <task_id>` to get task details, and then implement the required changes. ```typescript private buildPrompt(taskId: string): string { return `You are an AI coding assistant with access to this repository's codebase. First, run this command to get the task details: tm show ${taskId} Then implement the task with these requirements: - Make the SMALLEST number of code changes possible - Follow ALL existing patterns in the codebase (you have access to analyze the code) - Do NOT over-engineer the solution - Use existing files/functions/patterns wherever possible - When complete, print: COMPLETED: <brief summary of changes> Begin by running tm show ${taskId} to understand what needs to be implemented.`; } ``` <info added on 2025-09-12T02:40:01.812Z> The prompt builder function will handle task context retrieval by instructing Claude to use the task-master show command. This approach ensures Claude has access to all necessary task details before implementation begins. The command syntax "tm show ${taskId}" embedded in the prompt will direct Claude to first gather the complete task context, including description, requirements, and any existing implementation details, before proceeding with code changes. </info added on 2025-09-12T02:40:01.812Z> # Test Strategy: Verify the prompt is correctly formatted by calling the function with a sample task ID and checking that the output matches the expected template with the task ID properly inserted. ``` -------------------------------------------------------------------------------- /.claude/commands/tm/update/update-task.md: -------------------------------------------------------------------------------- ```markdown Update tasks with intelligent field detection and bulk operations. Arguments: $ARGUMENTS ## Intelligent Task Updates Parse arguments to determine update intent and execute smartly. ### 1. **Natural Language Processing** Understand update requests like: - "mark 23 as done" → Update status to done - "increase priority of 45" → Set priority to high - "add dependency on 12 to task 34" → Add dependency - "tasks 20-25 need review" → Bulk status update - "all API tasks high priority" → Pattern-based update ### 2. **Smart Field Detection** Automatically detect what to update: - Status keywords: done, complete, start, pause, review - Priority changes: urgent, high, low, deprioritize - Dependency updates: depends on, blocks, after - Assignment: assign to, owner, responsible - Time: estimate, spent, deadline ### 3. **Bulk Operations** Support for multiple task updates: ``` Examples: - "complete tasks 12, 15, 18" - "all pending auth tasks to in-progress" - "increase priority for tasks blocking 45" - "defer all documentation tasks" ``` ### 4. **Contextual Validation** Before updating, check: - Status transitions are valid - Dependencies don't create cycles - Priority changes make sense - Bulk updates won't break project flow Show preview: ``` Update Preview: ───────────────── Tasks to update: #23, #24, #25 Change: status → in-progress Impact: Will unblock tasks #30, #31 Warning: Task #24 has unmet dependencies ``` ### 5. **Smart Suggestions** Based on update: - Completing task? → Show newly unblocked tasks - Changing priority? → Show impact on sprint - Adding dependency? → Check for conflicts - Bulk update? → Show summary of changes ### 6. **Workflow Integration** After updates: - Auto-update dependent task states - Trigger status recalculation - Update sprint/milestone progress - Log changes with context Result: Flexible, intelligent task updates with safety checks. ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/update/update-task.md: -------------------------------------------------------------------------------- ```markdown Update tasks with intelligent field detection and bulk operations. Arguments: $ARGUMENTS ## Intelligent Task Updates Parse arguments to determine update intent and execute smartly. ### 1. **Natural Language Processing** Understand update requests like: - "mark 23 as done" → Update status to done - "increase priority of 45" → Set priority to high - "add dependency on 12 to task 34" → Add dependency - "tasks 20-25 need review" → Bulk status update - "all API tasks high priority" → Pattern-based update ### 2. **Smart Field Detection** Automatically detect what to update: - Status keywords: done, complete, start, pause, review - Priority changes: urgent, high, low, deprioritize - Dependency updates: depends on, blocks, after - Assignment: assign to, owner, responsible - Time: estimate, spent, deadline ### 3. **Bulk Operations** Support for multiple task updates: ``` Examples: - "complete tasks 12, 15, 18" - "all pending auth tasks to in-progress" - "increase priority for tasks blocking 45" - "defer all documentation tasks" ``` ### 4. **Contextual Validation** Before updating, check: - Status transitions are valid - Dependencies don't create cycles - Priority changes make sense - Bulk updates won't break project flow Show preview: ``` Update Preview: ───────────────── Tasks to update: #23, #24, #25 Change: status → in-progress Impact: Will unblock tasks #30, #31 Warning: Task #24 has unmet dependencies ``` ### 5. **Smart Suggestions** Based on update: - Completing task? → Show newly unblocked tasks - Changing priority? → Show impact on sprint - Adding dependency? → Check for conflicts - Bulk update? → Show summary of changes ### 6. **Workflow Integration** After updates: - Auto-update dependent task states - Trigger status recalculation - Update sprint/milestone progress - Log changes with context Result: Flexible, intelligent task updates with safety checks. ``` -------------------------------------------------------------------------------- /tests/fixtures/sample-claude-response.js: -------------------------------------------------------------------------------- ```javascript /** * Sample Claude API response for testing */ export const sampleClaudeResponse = { tasks: [ { id: 1, title: 'Setup Task Data Structure', description: 'Implement the core task data structure and file operations', status: 'pending', dependencies: [], priority: 'high', details: 'Create the tasks.json file structure with support for task properties including ID, title, description, status, dependencies, priority, details, and test strategy. Implement file system operations for reading and writing task data.', testStrategy: 'Verify tasks.json is created with the correct structure and that task data can be read from and written to the file.' }, { id: 2, title: 'Implement CLI Foundation', description: 'Create the command-line interface foundation with basic commands', status: 'pending', dependencies: [1], priority: 'high', details: 'Set up Commander.js for handling CLI commands. Implement the basic command structure including help documentation. Create the foundational command parsing logic.', testStrategy: 'Test each command to ensure it properly parses arguments and options. Verify help documentation is displayed correctly.' }, { id: 3, title: 'Develop Task Management Operations', description: 'Implement core operations for creating, reading, updating, and deleting tasks', status: 'pending', dependencies: [1], priority: 'medium', details: 'Implement functions for listing tasks, adding new tasks, updating task status, and removing tasks. Include support for filtering tasks by status and other properties.', testStrategy: 'Create unit tests for each CRUD operation to verify they correctly modify the task data.' } ], metadata: { projectName: 'Task Management CLI', totalTasks: 3, sourceFile: 'tests/fixtures/sample-prd.txt', generatedAt: '2023-12-15' } }; ``` -------------------------------------------------------------------------------- /src/ai-providers/anthropic.js: -------------------------------------------------------------------------------- ```javascript /** * src/ai-providers/anthropic.js * * Implementation for interacting with Anthropic models (e.g., Claude) * using the Vercel AI SDK. */ import { createAnthropic } from '@ai-sdk/anthropic'; import { BaseAIProvider } from './base-provider.js'; // TODO: Implement standardized functions for generateText, streamText, generateObject // --- Client Instantiation --- // Note: API key resolution should ideally happen closer to the call site // using the config manager/resolver which checks process.env and session.env. // This is a placeholder for basic functionality. // Remove the global variable and caching logic // let anthropicClient; export class AnthropicAIProvider extends BaseAIProvider { constructor() { super(); this.name = 'Anthropic'; } /** * Returns the environment variable name required for this provider's API key. * @returns {string} The environment variable name for the Anthropic API key */ getRequiredApiKeyName() { return 'ANTHROPIC_API_KEY'; } /** * Creates and returns an Anthropic client instance. * @param {object} params - Parameters for client initialization * @param {string} params.apiKey - Anthropic API key * @param {string} [params.baseURL] - Optional custom API endpoint * @returns {Function} Anthropic client function * @throws {Error} If API key is missing or initialization fails */ getClient(params) { try { const { apiKey, baseURL } = params; if (!apiKey) { throw new Error('Anthropic API key is required.'); } return createAnthropic({ apiKey, ...(baseURL && { baseURL }), headers: { 'anthropic-beta': 'output-128k-2025-02-19' } }); } catch (error) { this.handleError('client initialization', error); } } } // TODO: Implement streamAnthropicObject if needed and supported well by the SDK for Anthropic. // The basic structure would be similar to generateAnthropicObject but using streamObject. ``` -------------------------------------------------------------------------------- /mcp-server/src/tools/use-tag.js: -------------------------------------------------------------------------------- ```javascript /** * tools/use-tag.js * Tool to switch to a different tag context */ import { z } from 'zod'; import { createErrorResponse, handleApiResult, withNormalizedProjectRoot } from './utils.js'; import { useTagDirect } from '../core/task-master-core.js'; import { findTasksPath } from '../core/utils/path-utils.js'; /** * Register the useTag tool with the MCP server * @param {Object} server - FastMCP server instance */ export function registerUseTagTool(server) { server.addTool({ name: 'use_tag', description: 'Switch to a different tag context for task operations', parameters: z.object({ name: z.string().describe('Name of the tag to switch to'), file: z .string() .optional() .describe('Path to the tasks file (default: tasks/tasks.json)'), projectRoot: z .string() .describe('The directory of the project. Must be an absolute path.') }), execute: withNormalizedProjectRoot(async (args, { log, session }) => { try { log.info(`Starting use-tag with args: ${JSON.stringify(args)}`); // Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot) let tasksJsonPath; try { tasksJsonPath = findTasksPath( { projectRoot: args.projectRoot, file: args.file }, log ); } catch (error) { log.error(`Error finding tasks.json: ${error.message}`); return createErrorResponse( `Failed to find tasks.json: ${error.message}` ); } // Call the direct function const result = await useTagDirect( { tasksJsonPath: tasksJsonPath, name: args.name, projectRoot: args.projectRoot }, log, { session } ); return handleApiResult( result, log, 'Error switching tag', undefined, args.projectRoot ); } catch (error) { log.error(`Error in use-tag tool: ${error.message}`); return createErrorResponse(error.message); } }) }); } ``` -------------------------------------------------------------------------------- /tests/unit/utils-strip-ansi.test.js: -------------------------------------------------------------------------------- ```javascript /** * Tests for the stripAnsiCodes utility function */ import { jest } from '@jest/globals'; // Import the module under test const { stripAnsiCodes } = await import('../../scripts/modules/utils.js'); describe('stripAnsiCodes', () => { test('should remove ANSI color codes from text', () => { const textWithColors = '\x1b[31mRed text\x1b[0m \x1b[32mGreen text\x1b[0m'; const result = stripAnsiCodes(textWithColors); expect(result).toBe('Red text Green text'); }); test('should handle text without ANSI codes', () => { const plainText = 'This is plain text'; const result = stripAnsiCodes(plainText); expect(result).toBe('This is plain text'); }); test('should handle empty string', () => { const result = stripAnsiCodes(''); expect(result).toBe(''); }); test('should handle complex ANSI sequences', () => { // Test with various ANSI escape sequences const complexText = '\x1b[1;31mBold red\x1b[0m \x1b[4;32mUnderlined green\x1b[0m \x1b[33;46mYellow on cyan\x1b[0m'; const result = stripAnsiCodes(complexText); expect(result).toBe('Bold red Underlined green Yellow on cyan'); }); test('should handle non-string input gracefully', () => { expect(stripAnsiCodes(null)).toBe(null); expect(stripAnsiCodes(undefined)).toBe(undefined); expect(stripAnsiCodes(123)).toBe(123); expect(stripAnsiCodes({})).toEqual({}); }); test('should handle real chalk output patterns', () => { // Test patterns similar to what chalk produces const chalkLikeText = '1 \x1b[32m✓ done\x1b[39m Setup Project \x1b[31m(high)\x1b[39m'; const result = stripAnsiCodes(chalkLikeText); expect(result).toBe('1 ✓ done Setup Project (high)'); }); test('should handle multiline text with ANSI codes', () => { const multilineText = '\x1b[31mLine 1\x1b[0m\n\x1b[32mLine 2\x1b[0m\n\x1b[33mLine 3\x1b[0m'; const result = stripAnsiCodes(multilineText); expect(result).toBe('Line 1\nLine 2\nLine 3'); }); }); ``` -------------------------------------------------------------------------------- /mcp-test.js: -------------------------------------------------------------------------------- ```javascript #!/usr/bin/env node import { Config } from 'fastmcp'; import path from 'path'; import fs from 'fs'; // Log the current directory console.error(`Current working directory: ${process.cwd()}`); try { console.error('Attempting to load FastMCP Config...'); // Check if .cursor/mcp.json exists const mcpPath = path.join(process.cwd(), '.cursor', 'mcp.json'); console.error(`Checking if mcp.json exists at: ${mcpPath}`); if (fs.existsSync(mcpPath)) { console.error('mcp.json file found'); console.error( `File content: ${JSON.stringify(JSON.parse(fs.readFileSync(mcpPath, 'utf8')), null, 2)}` ); } else { console.error('mcp.json file not found'); } // Try to create Config const config = new Config(); console.error('Config created successfully'); // Check if env property exists if (config.env) { console.error( `Config.env exists with keys: ${Object.keys(config.env).join(', ')}` ); // Print each env var value (careful with sensitive values) for (const [key, value] of Object.entries(config.env)) { if (key.includes('KEY')) { console.error(`${key}: [value hidden]`); } else { console.error(`${key}: ${value}`); } } } else { console.error('Config.env does not exist'); } } catch (error) { console.error(`Error loading Config: ${error.message}`); console.error(`Stack trace: ${error.stack}`); } // Log process.env to see if values from mcp.json were loaded automatically console.error('\nChecking if process.env already has values from mcp.json:'); const envVars = [ 'ANTHROPIC_API_KEY', 'PERPLEXITY_API_KEY', 'MODEL', 'PERPLEXITY_MODEL', 'MAX_TOKENS', 'TEMPERATURE', 'DEFAULT_SUBTASKS', 'DEFAULT_PRIORITY' ]; for (const varName of envVars) { if (process.env[varName]) { if (varName.includes('KEY')) { console.error(`${varName}: [value hidden]`); } else { console.error(`${varName}: ${process.env[varName]}`); } } else { console.error(`${varName}: not set`); } } ``` -------------------------------------------------------------------------------- /tests/unit/profiles/cursor-integration.test.js: -------------------------------------------------------------------------------- ```javascript import { jest } from '@jest/globals'; import fs from 'fs'; import path from 'path'; import os from 'os'; // Mock external modules jest.mock('child_process', () => ({ execSync: jest.fn() })); // Mock console methods jest.mock('console', () => ({ log: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn(), clear: jest.fn() })); describe('Cursor Integration', () => { let tempDir; beforeEach(() => { jest.clearAllMocks(); // Create a temporary directory for testing tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'task-master-test-')); // Spy on fs methods jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {}); jest.spyOn(fs, 'readFileSync').mockImplementation((filePath) => { if (filePath.toString().includes('mcp.json')) { return JSON.stringify({ mcpServers: {} }, null, 2); } return '{}'; }); jest.spyOn(fs, 'existsSync').mockImplementation(() => false); jest.spyOn(fs, 'mkdirSync').mockImplementation(() => {}); }); afterEach(() => { // Clean up the temporary directory try { fs.rmSync(tempDir, { recursive: true, force: true }); } catch (err) { console.error(`Error cleaning up: ${err.message}`); } }); // Test function that simulates the createProjectStructure behavior for Cursor files function mockCreateCursorStructure() { // Create main .cursor directory fs.mkdirSync(path.join(tempDir, '.cursor'), { recursive: true }); // Create rules directory fs.mkdirSync(path.join(tempDir, '.cursor', 'rules'), { recursive: true }); // Create MCP config file fs.writeFileSync( path.join(tempDir, '.cursor', 'mcp.json'), JSON.stringify({ mcpServers: {} }, null, 2) ); } test('creates all required .cursor directories', () => { // Act mockCreateCursorStructure(); // Assert expect(fs.mkdirSync).toHaveBeenCalledWith(path.join(tempDir, '.cursor'), { recursive: true }); expect(fs.mkdirSync).toHaveBeenCalledWith( path.join(tempDir, '.cursor', 'rules'), { recursive: true } ); }); }); ``` -------------------------------------------------------------------------------- /mcp-server/src/tools/rename-tag.js: -------------------------------------------------------------------------------- ```javascript /** * tools/rename-tag.js * Tool to rename an existing tag */ import { z } from 'zod'; import { createErrorResponse, handleApiResult, withNormalizedProjectRoot } from './utils.js'; import { renameTagDirect } from '../core/task-master-core.js'; import { findTasksPath } from '../core/utils/path-utils.js'; /** * Register the renameTag tool with the MCP server * @param {Object} server - FastMCP server instance */ export function registerRenameTagTool(server) { server.addTool({ name: 'rename_tag', description: 'Rename an existing tag', parameters: z.object({ oldName: z.string().describe('Current name of the tag to rename'), newName: z.string().describe('New name for the tag'), file: z .string() .optional() .describe('Path to the tasks file (default: tasks/tasks.json)'), projectRoot: z .string() .describe('The directory of the project. Must be an absolute path.') }), execute: withNormalizedProjectRoot(async (args, { log, session }) => { try { log.info(`Starting rename-tag with args: ${JSON.stringify(args)}`); // Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot) let tasksJsonPath; try { tasksJsonPath = findTasksPath( { projectRoot: args.projectRoot, file: args.file }, log ); } catch (error) { log.error(`Error finding tasks.json: ${error.message}`); return createErrorResponse( `Failed to find tasks.json: ${error.message}` ); } // Call the direct function const result = await renameTagDirect( { tasksJsonPath: tasksJsonPath, oldName: args.oldName, newName: args.newName, projectRoot: args.projectRoot }, log, { session } ); return handleApiResult( result, log, 'Error renaming tag', undefined, args.projectRoot ); } catch (error) { log.error(`Error in rename-tag tool: ${error.message}`); return createErrorResponse(error.message); } }) }); } ```