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,
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It implies a destructive action ('Clear') but doesn't specify if this is permanent, reversible, or requires specific permissions. No information on side effects, error handling, or output format is given, which is inadequate for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that directly states the tool's function without unnecessary words. It's front-loaded and wastes no space, making it highly concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of a destructive operation with 5 parameters and no annotations or output schema, the description is insufficient. It lacks details on behavior, error cases, and what 'clearing' entails (e.g., deletion vs. archiving), making it incomplete for safe and effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, so parameters like 'all', 'file', 'id', 'projectRoot', and 'tag' are well-documented in the schema. The description adds no additional meaning beyond implying task specification, which is already covered, resulting in a baseline score.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Clear') and resource ('subtasks from specified tasks'), making the purpose understandable. However, it doesn't differentiate from sibling tools like 'remove_subtask' or 'update_subtask', which could handle similar operations, so it's not fully specific about its unique scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives such as 'remove_subtask' or 'update_subtask'. It mentions 'specified tasks' but doesn't clarify selection criteria or exclusions, leaving usage context vague.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

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