things_add_items_to_project
Add structured todos and headings to an existing project in Things 3. Organize tasks under visual separators to group related items within your project workflow.
Instructions
Add todos and headings to an existing project. Items are added as a flat array where headings act as visual separators for the todos that follow them.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Unique system-generated ID of the project (alphanumeric like "pRj123aBc456dEf789gHi", 20-24 chars). NOT the project title! You MUST use things_get_projects to find the correct ID first. Common mistake: using project name like "My Vacation Planning" instead of its ID. | |
| items | Yes | Add structured todos and headings to an existing project. Items are added as a flat array where headings act as visual separators. Todos that follow a heading will appear grouped under it. Example: [{type: 'heading', title: 'Phase 2'}, {type: 'todo', title: 'Task 1'}, {type: 'todo', title: 'Task 2'}]. | |
| operation | No |
Implementation Reference
- src/lib/json-builder.ts:70-124 (handler)The implementation of addItemsToProject logic, which iterates over project items and uses executeThingsJSON to add them to a project.
async addItemsToProject(params: AddItemsToProjectParams): Promise<string> { const results = { todos: 0, headings: 0, errors: [] as string[] }; // Create each item as a new to-do assigned to the project for (const item of params.items) { if (item.type === 'heading') { results.headings++; // Headings cannot be added to existing projects via JSON API // Skip them with a warning (they can only be added during project creation) continue; } try { // Create to-do and assign it to the project const todoAttributes = this.buildFullTodo(item).attributes as Record<string, unknown>; todoAttributes['list-id'] = params.id; // Assign to the project await executeThingsJSON([{ type: 'to-do', attributes: todoAttributes }]); results.todos++; } catch { results.errors.push(`"${item.title}"`); } } // Build detailed response message let message = ''; if (results.todos > 0) { message = `✅ Added ${results.todos} todo(s) to project`; } if (results.headings > 0) { if (message) message += '\n'; message += `⚠️ Skipped ${results.headings} heading(s) - headings cannot be added to existing projects`; } if (results.errors.length > 0) { if (message) message += '\n'; message += `❌ Failed to add: ${results.errors.join(', ')}`; } if (!message) { message = '⚠️ No items were processed'; } return message; } - src/tools/update-json.ts:24-29 (registration)Registration of the things_add_items_to_project tool definition.
{ name: 'things_add_items_to_project', description: 'Add todos and headings to an existing project. Items are added as a flat array where headings act as visual separators for the todos that follow them.', schema: AddItemsToProjectSchema as any } ]; - src/tools/update-json.ts:38-41 (handler)Handler routing logic for things_add_items_to_project within the UpdateJSONToolHandler class.
} else if (toolName === 'things_add_items_to_project') { const addItemsParams = params as z.infer<typeof AddItemsToProjectSchema>; return jsonBuilder.addItemsToProject(addItemsParams); }