/** * /add-task command implementation * * Creates a new task file in .takt/tasks/ with YAML format. * Supports worktree and branch options. */ import * as fs from 'node:fs'; import * as path from 'node:path'; import { stringify as stringifyYaml } from 'yaml'; import { promptInput, confirm } from '../prompt/index.js'; import { success, info, error } from '../utils/ui.js'; import { slugify } from '../utils/slug.js'; import { createLogger } from '../utils/debug.js'; import type { TaskFileData } from '../task/schema.js'; const log = createLogger('add-task'); /** * Generate a unique task filename */ function generateFilename(tasksDir: string, taskContent: string): string { const slug = slugify(taskContent); const base = slug || 'task'; let filename = `${base}.yaml`; let counter = 1; while (fs.existsSync(path.join(tasksDir, filename))) { filename = `${base}-${counter}.yaml`; counter++; } return filename; } /** * /add-task command handler * * Usage: * takt /add-task "タスク内容" # Quick add (no worktree) * takt /add-task # Interactive mode */ export async function addTask(cwd: string, args: string[]): Promise { const tasksDir = path.join(cwd, '.takt', 'tasks'); fs.mkdirSync(tasksDir, { recursive: true }); let taskContent: string; let worktree: boolean | string | undefined; let branch: string | undefined; let workflow: string | undefined; if (args.length > 0) { // Argument mode: task content provided directly taskContent = args.join(' '); } else { // Interactive mode const input = await promptInput('Task content'); if (!input) { info('Cancelled.'); return; } taskContent = input; } // Ask about worktree const useWorktree = await confirm('Create worktree?', false); if (useWorktree) { const customPath = await promptInput('Worktree path (Enter for auto)'); worktree = customPath || true; // Ask about branch const customBranch = await promptInput('Branch name (Enter for auto)'); if (customBranch) { branch = customBranch; } } // Ask about workflow const customWorkflow = await promptInput('Workflow name (Enter for default)'); if (customWorkflow) { workflow = customWorkflow; } // Build task data const taskData: TaskFileData = { task: taskContent }; if (worktree !== undefined) { taskData.worktree = worktree; } if (branch) { taskData.branch = branch; } if (workflow) { taskData.workflow = workflow; } // Write YAML filea const filename = generateFilename(tasksDir, taskContent); const filePath = path.join(tasksDir, filename); const yamlContent = stringifyYaml(taskData); fs.writeFileSync(filePath, yamlContent, 'utf-8'); log.info('Task created', { filePath, taskData }); success(`Task created: ${filename}`); info(` Path: ${filePath}`); if (worktree) { info(` Worktree: ${typeof worktree === 'string' ? worktree : 'auto'}`); } if (branch) { info(` Branch: ${branch}`); } if (workflow) { info(` Workflow: ${workflow}`); } }