Skip to main content
Glama

clear_subtasks

Remove subtasks from specific or all tasks in a project, using task IDs, tags, or a tasks file, to streamline task management in AI-driven development workflows.

Instructions

Clear subtasks from specified tasks

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
allNoClear subtasks from all tasks
fileNoAbsolute path to the tasks file (default: tasks/tasks.json)
idNoTask IDs (comma-separated) to clear subtasks from
projectRootYesThe directory of the project. Must be an absolute path.
tagNoTag context to operate on

Implementation Reference

  • Registration function for the clear_subtasks MCP tool, including schema definition and execute handler that orchestrates the operation by calling clearSubtasksDirect
    export function registerClearSubtasksTool(server) { server.addTool({ name: 'clear_subtasks', description: 'Clear subtasks from specified tasks', parameters: z .object({ id: z .string() .optional() .describe('Task IDs (comma-separated) to clear subtasks from'), all: z.boolean().optional().describe('Clear subtasks from all tasks'), file: z .string() .optional() .describe( 'Absolute path to the tasks file (default: tasks/tasks.json)' ), projectRoot: z .string() .describe('The directory of the project. Must be an absolute path.'), tag: z.string().optional().describe('Tag context to operate on') }) .refine((data) => data.id || data.all, { message: "Either 'id' or 'all' parameter must be provided", path: ['id', 'all'] }), execute: withToolContext('clear-subtasks', async (args, context) => { try { context.log.info( `Clearing subtasks with args: ${JSON.stringify(args)}` ); const resolvedTag = resolveTag({ projectRoot: args.projectRoot, tag: args.tag }); // Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot) let tasksJsonPath; try { tasksJsonPath = findTasksPath( { projectRoot: args.projectRoot, file: args.file }, context.log ); } catch (error) { context.log.error(`Error finding tasks.json: ${error.message}`); return createErrorResponse( `Failed to find tasks.json: ${error.message}` ); } const result = await clearSubtasksDirect( { tasksJsonPath: tasksJsonPath, id: args.id, all: args.all, projectRoot: args.projectRoot, tag: resolvedTag }, context.log, { session: context.session } ); if (result.success) { context.log.info( `Subtasks cleared successfully: ${result.data.message}` ); } else { context.log.error( `Failed to clear subtasks: ${result.error.message}` ); } return handleApiResult({ result, log: context.log, errorPrefix: 'Error clearing subtasks', projectRoot: args.projectRoot }); } catch (error) { context.log.error(`Error in clearSubtasks tool: ${error.message}`); return createErrorResponse(error.message); } }) }); }
  • Direct function handler called by the MCP tool handler, performs validation, calls core clearSubtasks, and returns structured result
    export async function clearSubtasksDirect(args, log) { // Destructure expected args const { tasksJsonPath, id, all, tag, projectRoot } = args; try { log.info(`Clearing subtasks with args: ${JSON.stringify(args)}`); // Check if tasksJsonPath was provided if (!tasksJsonPath) { log.error('clearSubtasksDirect called without tasksJsonPath'); return { success: false, error: { code: 'MISSING_ARGUMENT', message: 'tasksJsonPath is required' } }; } // Either id or all must be provided if (!id && !all) { return { success: false, error: { code: 'INPUT_VALIDATION_ERROR', message: 'Either task IDs with id parameter or all parameter must be provided' } }; } // Use provided path const tasksPath = tasksJsonPath; // Check if tasks.json exists if (!fs.existsSync(tasksPath)) { return { success: false, error: { code: 'FILE_NOT_FOUND_ERROR', message: `Tasks file not found at ${tasksPath}` } }; } let taskIds; // Use readJSON which handles silent migration and tag resolution const data = readJSON(tasksPath, projectRoot, tag); if (!data || !data.tasks) { return { success: false, error: { code: 'INPUT_VALIDATION_ERROR', message: `No tasks found in tasks file: ${tasksPath}` } }; } const currentTag = data.tag || tag; const tasks = data.tasks; // If all is specified, get all task IDs if (all) { log.info(`Clearing subtasks from all tasks in tag '${currentTag}'`); if (tasks.length === 0) { return { success: false, error: { code: 'INPUT_VALIDATION_ERROR', message: `No tasks found in tag context '${currentTag}'` } }; } taskIds = tasks.map((t) => t.id).join(','); } else { // Use the provided task IDs taskIds = id; } log.info(`Clearing subtasks from tasks: ${taskIds} in tag '${currentTag}'`); // Enable silent mode to prevent console logs from interfering with JSON response enableSilentMode(); // Call the core function clearSubtasks(tasksPath, taskIds, { projectRoot, tag: currentTag }); // Restore normal logging disableSilentMode(); // Read the updated data to provide a summary const updatedData = readJSON(tasksPath, projectRoot, currentTag); const taskIdArray = taskIds.split(',').map((id) => parseInt(id.trim(), 10)); // Build a summary of what was done const clearedTasksCount = taskIdArray.length; const updatedTasks = updatedData.tasks || []; const taskSummary = taskIdArray.map((id) => { const task = updatedTasks.find((t) => t.id === id); return task ? { id, title: task.title } : { id, title: 'Task not found' }; }); return { success: true, data: { message: `Successfully cleared subtasks from ${clearedTasksCount} task(s) in tag '${currentTag}'`, tasksCleared: taskSummary, tag: currentTag } }; } catch (error) { // Make sure to restore normal logging even if there's an error disableSilentMode(); log.error(`Error in clearSubtasksDirect: ${error.message}`); return { success: false, error: { code: 'CORE_FUNCTION_ERROR', message: error.message } }; } }
  • Core implementation function that modifies the tasks.json by clearing subtasks arrays for specified tasks and handles CLI output
    function clearSubtasks(tasksPath, taskIds, context = {}) { const { projectRoot, tag } = context; log('info', `Reading tasks from ${tasksPath}...`); const data = readJSON(tasksPath, projectRoot, tag); if (!data || !data.tasks) { log('error', 'No valid tasks found.'); process.exit(1); } if (!isSilentMode()) { console.log( boxen(chalk.white.bold('Clearing Subtasks'), { padding: 1, borderColor: 'blue', borderStyle: 'round', margin: { top: 1, bottom: 1 } }) ); } // Handle multiple task IDs (comma-separated) const taskIdArray = taskIds.split(',').map((id) => id.trim()); let clearedCount = 0; // Create a summary table for the cleared subtasks const summaryTable = new Table({ head: [ chalk.cyan.bold('Task ID'), chalk.cyan.bold('Task Title'), chalk.cyan.bold('Subtasks Cleared') ], colWidths: [10, 50, 20], style: { head: [], border: [] } }); taskIdArray.forEach((taskId) => { const id = parseInt(taskId, 10); if (Number.isNaN(id)) { log('error', `Invalid task ID: ${taskId}`); return; } const task = data.tasks.find((t) => t.id === id); if (!task) { log('error', `Task ${id} not found`); return; } if (!task.subtasks || task.subtasks.length === 0) { log('info', `Task ${id} has no subtasks to clear`); summaryTable.push([ id.toString(), truncate(task.title, 47), chalk.yellow('No subtasks') ]); return; } const subtaskCount = task.subtasks.length; task.subtasks = []; clearedCount++; log('info', `Cleared ${subtaskCount} subtasks from task ${id}`); summaryTable.push([ id.toString(), truncate(task.title, 47), chalk.green(`${subtaskCount} subtasks cleared`) ]); }); if (clearedCount > 0) { writeJSON(tasksPath, data, projectRoot, tag); // Show summary table if (!isSilentMode()) { console.log( boxen(chalk.white.bold('Subtask Clearing Summary:'), { padding: { left: 2, right: 2, top: 0, bottom: 0 }, margin: { top: 1, bottom: 0 }, borderColor: 'blue', borderStyle: 'round' }) ); console.log(summaryTable.toString()); } // Success message if (!isSilentMode()) { console.log( boxen( chalk.green( `Successfully cleared subtasks from ${chalk.bold(clearedCount)} task(s)` ), { padding: 1, borderColor: 'green', borderStyle: 'round', margin: { top: 1 } } ) ); // Next steps suggestion console.log( boxen( chalk.white.bold('Next Steps:') + '\n\n' + `${chalk.cyan('1.')} Run ${chalk.yellow('task-master expand --id=<id>')} to generate new subtasks\n` + `${chalk.cyan('2.')} Run ${chalk.yellow('task-master list --with-subtasks')} to verify changes`, { padding: 1, borderColor: 'cyan', borderStyle: 'round', margin: { top: 1 } } ) ); } } else { if (!isSilentMode()) { console.log( boxen(chalk.yellow('No subtasks were cleared'), { padding: 1, borderColor: 'yellow', borderStyle: 'round', margin: { top: 1 } }) ); } } }
  • Tool registry mapping that includes clear_subtasks to its registration function
    import { registerClearSubtasksTool } from './clear-subtasks.js'; import { registerComplexityReportTool } from './complexity-report.js'; import { registerCopyTagTool } from './copy-tag.js'; import { registerDeleteTagTool } from './delete-tag.js'; import { registerExpandAllTool } from './expand-all.js'; import { registerExpandTaskTool } from './expand-task.js'; import { registerFixDependenciesTool } from './fix-dependencies.js'; import { registerInitializeProjectTool } from './initialize-project.js'; import { registerListTagsTool } from './list-tags.js'; import { registerModelsTool } from './models.js'; import { registerMoveTaskTool } from './move-task.js'; import { registerNextTaskTool } from './next-task.js'; import { registerParsePRDTool } from './parse-prd.js'; import { registerRemoveDependencyTool } from './remove-dependency.js'; import { registerRemoveSubtaskTool } from './remove-subtask.js'; import { registerRemoveTaskTool } from './remove-task.js'; import { registerRenameTagTool } from './rename-tag.js'; import { registerResearchTool } from './research.js'; import { registerResponseLanguageTool } from './response-language.js'; import { registerRulesTool } from './rules.js'; import { registerScopeDownTool } from './scope-down.js'; import { registerScopeUpTool } from './scope-up.js'; import { registerUpdateSubtaskTool } from './update-subtask.js'; import { registerUpdateTaskTool } from './update-task.js'; import { registerUpdateTool } from './update.js'; import { registerUseTagTool } from './use-tag.js'; import { registerValidateDependenciesTool } from './validate-dependencies.js'; // Import TypeScript tools from apps/mcp import { registerAutopilotAbortTool, registerAutopilotCommitTool, registerAutopilotCompleteTool, registerAutopilotFinalizeTool, registerAutopilotNextTool, registerAutopilotResumeTool, registerAutopilotStartTool, registerAutopilotStatusTool, registerGenerateTool, registerGetTaskTool, registerGetTasksTool, registerSetTaskStatusTool } from '@tm/mcp'; /** * Comprehensive tool registry mapping tool names to their registration functions * Used for dynamic tool registration and validation */ export const toolRegistry = { initialize_project: registerInitializeProjectTool, models: registerModelsTool, rules: registerRulesTool, parse_prd: registerParsePRDTool, 'response-language': registerResponseLanguageTool, analyze_project_complexity: registerAnalyzeProjectComplexityTool, expand_task: registerExpandTaskTool, expand_all: registerExpandAllTool, scope_up_task: registerScopeUpTool, scope_down_task: registerScopeDownTool, get_tasks: registerGetTasksTool, get_task: registerGetTaskTool, next_task: registerNextTaskTool, complexity_report: registerComplexityReportTool, set_task_status: registerSetTaskStatusTool, add_task: registerAddTaskTool, add_subtask: registerAddSubtaskTool, update: registerUpdateTool, update_task: registerUpdateTaskTool, update_subtask: registerUpdateSubtaskTool, remove_task: registerRemoveTaskTool, remove_subtask: registerRemoveSubtaskTool, clear_subtasks: registerClearSubtasksTool,

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/eyaltoledano/claude-task-master'

If you have feedback or need assistance with the MCP directory API, please join our Discord server