@vibetasks/cli 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/vibetasks.js +243 -2
- package/package.json +3 -3
package/dist/bin/vibetasks.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "../chunk-2KRLRG4G.js";
|
|
12
12
|
|
|
13
13
|
// bin/vibetasks.ts
|
|
14
|
-
import { Command as
|
|
14
|
+
import { Command as Command19 } from "commander";
|
|
15
15
|
import { createRequire } from "module";
|
|
16
16
|
|
|
17
17
|
// src/commands/login.ts
|
|
@@ -3239,10 +3239,250 @@ function formatDuration(start, end) {
|
|
|
3239
3239
|
return `${minutes}m`;
|
|
3240
3240
|
}
|
|
3241
3241
|
|
|
3242
|
+
// src/commands/subtask.ts
|
|
3243
|
+
import { Command as Command18 } from "commander";
|
|
3244
|
+
import ora13 from "ora";
|
|
3245
|
+
import chalk19 from "chalk";
|
|
3246
|
+
import { AuthManager as AuthManager16, TaskOperations as TaskOperations13 } from "@vibetasks/core";
|
|
3247
|
+
function parseIndices(args) {
|
|
3248
|
+
const indices = /* @__PURE__ */ new Set();
|
|
3249
|
+
for (const arg of args) {
|
|
3250
|
+
const parts = arg.split(",");
|
|
3251
|
+
for (const part of parts) {
|
|
3252
|
+
const trimmed = part.trim();
|
|
3253
|
+
if (trimmed.includes("-")) {
|
|
3254
|
+
const [startStr, endStr] = trimmed.split("-");
|
|
3255
|
+
const start = parseInt(startStr, 10);
|
|
3256
|
+
const end = parseInt(endStr, 10);
|
|
3257
|
+
if (!isNaN(start) && !isNaN(end) && start <= end) {
|
|
3258
|
+
for (let i = start; i <= end; i++) {
|
|
3259
|
+
indices.add(i);
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
} else {
|
|
3263
|
+
const num = parseInt(trimmed, 10);
|
|
3264
|
+
if (!isNaN(num)) {
|
|
3265
|
+
indices.add(num);
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
3270
|
+
return Array.from(indices).sort((a, b) => a - b);
|
|
3271
|
+
}
|
|
3272
|
+
function findSubtasksByTitle(subtasks, searchTerms) {
|
|
3273
|
+
const indices = [];
|
|
3274
|
+
for (const term of searchTerms) {
|
|
3275
|
+
const lowerTerm = term.toLowerCase();
|
|
3276
|
+
subtasks.forEach((subtask, index) => {
|
|
3277
|
+
if (subtask.title.toLowerCase().includes(lowerTerm)) {
|
|
3278
|
+
indices.push(index + 1);
|
|
3279
|
+
}
|
|
3280
|
+
});
|
|
3281
|
+
}
|
|
3282
|
+
return [...new Set(indices)].sort((a, b) => a - b);
|
|
3283
|
+
}
|
|
3284
|
+
var subtaskCommand = new Command18("subtask").description("Manage subtasks within a task");
|
|
3285
|
+
subtaskCommand.command("list").description("List subtasks for a task").argument("<task-id>", "Task ID, short # (1-99), or first 8 characters").action(async (taskIdArg) => {
|
|
3286
|
+
const spinner = ora13("Loading subtasks...").start();
|
|
3287
|
+
try {
|
|
3288
|
+
const authManager = new AuthManager16();
|
|
3289
|
+
const taskOps = await TaskOperations13.fromAuthManager(authManager);
|
|
3290
|
+
const shortIdManager = new ShortIdManager();
|
|
3291
|
+
let taskId = await shortIdManager.resolveId(taskIdArg);
|
|
3292
|
+
if (taskId.length < 32) {
|
|
3293
|
+
const allTasks = await taskOps.getTasks("all");
|
|
3294
|
+
const matchingTask = allTasks.find((t) => t.id.startsWith(taskId));
|
|
3295
|
+
if (!matchingTask) {
|
|
3296
|
+
spinner.fail(chalk19.red("Task not found"));
|
|
3297
|
+
console.error(chalk19.gray(`
|
|
3298
|
+
No task found with ID: ${taskIdArg}
|
|
3299
|
+
`));
|
|
3300
|
+
process.exit(1);
|
|
3301
|
+
}
|
|
3302
|
+
taskId = matchingTask.id;
|
|
3303
|
+
}
|
|
3304
|
+
const task = await taskOps.getTask(taskId);
|
|
3305
|
+
const subtasks = task.subtasks_json || [];
|
|
3306
|
+
spinner.stop();
|
|
3307
|
+
console.log();
|
|
3308
|
+
console.log(chalk19.white.bold(task.title));
|
|
3309
|
+
console.log(chalk19.gray(`ID: ${task.id.substring(0, 8)}`));
|
|
3310
|
+
console.log();
|
|
3311
|
+
if (subtasks.length === 0) {
|
|
3312
|
+
console.log(chalk19.gray(" No subtasks"));
|
|
3313
|
+
} else {
|
|
3314
|
+
const doneCount = subtasks.filter((s) => s.done).length;
|
|
3315
|
+
console.log(chalk19.gray(`Subtasks: ${doneCount}/${subtasks.length} completed`));
|
|
3316
|
+
console.log();
|
|
3317
|
+
subtasks.forEach((subtask, index) => {
|
|
3318
|
+
const checkbox = subtask.done ? chalk19.green("[x]") : chalk19.gray("[ ]");
|
|
3319
|
+
const title = subtask.done ? chalk19.strikethrough.gray(subtask.title) : chalk19.white(subtask.title);
|
|
3320
|
+
console.log(` ${chalk19.cyan(String(index + 1).padStart(2, " "))}. ${checkbox} ${title}`);
|
|
3321
|
+
});
|
|
3322
|
+
}
|
|
3323
|
+
console.log();
|
|
3324
|
+
process.exit(0);
|
|
3325
|
+
} catch (error) {
|
|
3326
|
+
spinner.fail(chalk19.red("Failed to load subtasks"));
|
|
3327
|
+
console.error(chalk19.red(`
|
|
3328
|
+
Error: ${error.message}
|
|
3329
|
+
`));
|
|
3330
|
+
process.exit(1);
|
|
3331
|
+
}
|
|
3332
|
+
});
|
|
3333
|
+
subtaskCommand.command("done").description("Mark subtasks as complete").argument("<task-id>", "Task ID, short # (1-99), or first 8 characters").argument("<indices...>", 'Subtask indices (1-based): "1 2 3", "1-5", "1,3,5", or partial title match').action(async (taskIdArg, indicesArgs) => {
|
|
3334
|
+
const spinner = ora13("Updating subtasks...").start();
|
|
3335
|
+
try {
|
|
3336
|
+
const authManager = new AuthManager16();
|
|
3337
|
+
const taskOps = await TaskOperations13.fromAuthManager(authManager);
|
|
3338
|
+
const shortIdManager = new ShortIdManager();
|
|
3339
|
+
let taskId = await shortIdManager.resolveId(taskIdArg);
|
|
3340
|
+
if (taskId.length < 32) {
|
|
3341
|
+
const allTasks = await taskOps.getTasks("all");
|
|
3342
|
+
const matchingTask = allTasks.find((t) => t.id.startsWith(taskId));
|
|
3343
|
+
if (!matchingTask) {
|
|
3344
|
+
spinner.fail(chalk19.red("Task not found"));
|
|
3345
|
+
console.error(chalk19.gray(`
|
|
3346
|
+
No task found with ID: ${taskIdArg}
|
|
3347
|
+
`));
|
|
3348
|
+
process.exit(1);
|
|
3349
|
+
}
|
|
3350
|
+
taskId = matchingTask.id;
|
|
3351
|
+
}
|
|
3352
|
+
const task = await taskOps.getTask(taskId);
|
|
3353
|
+
const subtasks = [...task.subtasks_json || []];
|
|
3354
|
+
if (subtasks.length === 0) {
|
|
3355
|
+
spinner.fail(chalk19.yellow("No subtasks to update"));
|
|
3356
|
+
process.exit(1);
|
|
3357
|
+
}
|
|
3358
|
+
let indices = parseIndices(indicesArgs);
|
|
3359
|
+
if (indices.length === 0) {
|
|
3360
|
+
indices = findSubtasksByTitle(subtasks, indicesArgs);
|
|
3361
|
+
}
|
|
3362
|
+
if (indices.length === 0) {
|
|
3363
|
+
spinner.fail(chalk19.yellow("No matching subtasks found"));
|
|
3364
|
+
console.error(chalk19.gray("\nProvide indices (1, 2, 3) or partial title matches.\n"));
|
|
3365
|
+
process.exit(1);
|
|
3366
|
+
}
|
|
3367
|
+
const outOfRange = indices.filter((i) => i < 1 || i > subtasks.length);
|
|
3368
|
+
if (outOfRange.length > 0) {
|
|
3369
|
+
spinner.fail(chalk19.red(`Invalid indices: ${outOfRange.join(", ")}`));
|
|
3370
|
+
console.error(chalk19.gray(`
|
|
3371
|
+
Valid range: 1-${subtasks.length}
|
|
3372
|
+
`));
|
|
3373
|
+
process.exit(1);
|
|
3374
|
+
}
|
|
3375
|
+
const updated = [];
|
|
3376
|
+
for (const idx of indices) {
|
|
3377
|
+
if (!subtasks[idx - 1].done) {
|
|
3378
|
+
subtasks[idx - 1].done = true;
|
|
3379
|
+
updated.push(subtasks[idx - 1].title);
|
|
3380
|
+
}
|
|
3381
|
+
}
|
|
3382
|
+
if (updated.length === 0) {
|
|
3383
|
+
spinner.succeed(chalk19.yellow("All specified subtasks were already done"));
|
|
3384
|
+
process.exit(0);
|
|
3385
|
+
}
|
|
3386
|
+
await taskOps.updateTask(taskId, { subtasks_json: subtasks });
|
|
3387
|
+
const doneCount = subtasks.filter((s) => s.done).length;
|
|
3388
|
+
spinner.succeed(chalk19.green(`Marked ${updated.length} subtask(s) as done`));
|
|
3389
|
+
console.log();
|
|
3390
|
+
updated.forEach((title) => {
|
|
3391
|
+
console.log(chalk19.green(` \u2713 ${title}`));
|
|
3392
|
+
});
|
|
3393
|
+
console.log();
|
|
3394
|
+
console.log(chalk19.gray(`Progress: ${doneCount}/${subtasks.length} completed`));
|
|
3395
|
+
if (doneCount === subtasks.length) {
|
|
3396
|
+
console.log();
|
|
3397
|
+
console.log(chalk19.cyan(`All subtasks complete! Run: vibetasks done ${taskId.substring(0, 8)}`));
|
|
3398
|
+
}
|
|
3399
|
+
console.log();
|
|
3400
|
+
process.exit(0);
|
|
3401
|
+
} catch (error) {
|
|
3402
|
+
spinner.fail(chalk19.red("Failed to update subtasks"));
|
|
3403
|
+
console.error(chalk19.red(`
|
|
3404
|
+
Error: ${error.message}
|
|
3405
|
+
`));
|
|
3406
|
+
process.exit(1);
|
|
3407
|
+
}
|
|
3408
|
+
});
|
|
3409
|
+
subtaskCommand.command("undo").description("Mark subtasks as incomplete").argument("<task-id>", "Task ID, short # (1-99), or first 8 characters").argument("<indices...>", 'Subtask indices (1-based): "1 2 3", "1-5", "1,3,5", or partial title match').action(async (taskIdArg, indicesArgs) => {
|
|
3410
|
+
const spinner = ora13("Updating subtasks...").start();
|
|
3411
|
+
try {
|
|
3412
|
+
const authManager = new AuthManager16();
|
|
3413
|
+
const taskOps = await TaskOperations13.fromAuthManager(authManager);
|
|
3414
|
+
const shortIdManager = new ShortIdManager();
|
|
3415
|
+
let taskId = await shortIdManager.resolveId(taskIdArg);
|
|
3416
|
+
if (taskId.length < 32) {
|
|
3417
|
+
const allTasks = await taskOps.getTasks("all");
|
|
3418
|
+
const matchingTask = allTasks.find((t) => t.id.startsWith(taskId));
|
|
3419
|
+
if (!matchingTask) {
|
|
3420
|
+
spinner.fail(chalk19.red("Task not found"));
|
|
3421
|
+
console.error(chalk19.gray(`
|
|
3422
|
+
No task found with ID: ${taskIdArg}
|
|
3423
|
+
`));
|
|
3424
|
+
process.exit(1);
|
|
3425
|
+
}
|
|
3426
|
+
taskId = matchingTask.id;
|
|
3427
|
+
}
|
|
3428
|
+
const task = await taskOps.getTask(taskId);
|
|
3429
|
+
const subtasks = [...task.subtasks_json || []];
|
|
3430
|
+
if (subtasks.length === 0) {
|
|
3431
|
+
spinner.fail(chalk19.yellow("No subtasks to update"));
|
|
3432
|
+
process.exit(1);
|
|
3433
|
+
}
|
|
3434
|
+
let indices = parseIndices(indicesArgs);
|
|
3435
|
+
if (indices.length === 0) {
|
|
3436
|
+
indices = findSubtasksByTitle(subtasks, indicesArgs);
|
|
3437
|
+
}
|
|
3438
|
+
if (indices.length === 0) {
|
|
3439
|
+
spinner.fail(chalk19.yellow("No matching subtasks found"));
|
|
3440
|
+
console.error(chalk19.gray("\nProvide indices (1, 2, 3) or partial title matches.\n"));
|
|
3441
|
+
process.exit(1);
|
|
3442
|
+
}
|
|
3443
|
+
const outOfRange = indices.filter((i) => i < 1 || i > subtasks.length);
|
|
3444
|
+
if (outOfRange.length > 0) {
|
|
3445
|
+
spinner.fail(chalk19.red(`Invalid indices: ${outOfRange.join(", ")}`));
|
|
3446
|
+
console.error(chalk19.gray(`
|
|
3447
|
+
Valid range: 1-${subtasks.length}
|
|
3448
|
+
`));
|
|
3449
|
+
process.exit(1);
|
|
3450
|
+
}
|
|
3451
|
+
const updated = [];
|
|
3452
|
+
for (const idx of indices) {
|
|
3453
|
+
if (subtasks[idx - 1].done) {
|
|
3454
|
+
subtasks[idx - 1].done = false;
|
|
3455
|
+
updated.push(subtasks[idx - 1].title);
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
if (updated.length === 0) {
|
|
3459
|
+
spinner.succeed(chalk19.yellow("All specified subtasks were already incomplete"));
|
|
3460
|
+
process.exit(0);
|
|
3461
|
+
}
|
|
3462
|
+
await taskOps.updateTask(taskId, { subtasks_json: subtasks });
|
|
3463
|
+
const doneCount = subtasks.filter((s) => s.done).length;
|
|
3464
|
+
spinner.succeed(chalk19.yellow(`Marked ${updated.length} subtask(s) as incomplete`));
|
|
3465
|
+
console.log();
|
|
3466
|
+
updated.forEach((title) => {
|
|
3467
|
+
console.log(chalk19.yellow(` \u25CB ${title}`));
|
|
3468
|
+
});
|
|
3469
|
+
console.log();
|
|
3470
|
+
console.log(chalk19.gray(`Progress: ${doneCount}/${subtasks.length} completed`));
|
|
3471
|
+
console.log();
|
|
3472
|
+
process.exit(0);
|
|
3473
|
+
} catch (error) {
|
|
3474
|
+
spinner.fail(chalk19.red("Failed to update subtasks"));
|
|
3475
|
+
console.error(chalk19.red(`
|
|
3476
|
+
Error: ${error.message}
|
|
3477
|
+
`));
|
|
3478
|
+
process.exit(1);
|
|
3479
|
+
}
|
|
3480
|
+
});
|
|
3481
|
+
|
|
3242
3482
|
// bin/vibetasks.ts
|
|
3243
3483
|
var require2 = createRequire(import.meta.url);
|
|
3244
3484
|
var pkg = require2("../../package.json");
|
|
3245
|
-
var program = new
|
|
3485
|
+
var program = new Command19();
|
|
3246
3486
|
program.name("vibetasks").description("VibeTasks CLI - Fast task management for vibers").version(pkg.version);
|
|
3247
3487
|
program.addCommand(setupCommand);
|
|
3248
3488
|
program.addCommand(loginCommand);
|
|
@@ -3262,4 +3502,5 @@ program.addCommand(archiveCommand);
|
|
|
3262
3502
|
program.addCommand(daemonCommand);
|
|
3263
3503
|
program.addCommand(nextCommand);
|
|
3264
3504
|
program.addCommand(sessionCommand);
|
|
3505
|
+
program.addCommand(subtaskCommand);
|
|
3265
3506
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibetasks/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "VibeTasks CLI - Lightning-fast task management from your terminal. Works with Claude Code, Cursor, and all AI coding tools.",
|
|
5
5
|
"author": "Vyas",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"typecheck": "tsc --noEmit"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@vibetasks/core": "^0.5.
|
|
49
|
-
"@vibetasks/shared": "^1.2.
|
|
48
|
+
"@vibetasks/core": "^0.5.3",
|
|
49
|
+
"@vibetasks/shared": "^1.2.3",
|
|
50
50
|
"commander": "^11.1.0",
|
|
51
51
|
"chalk": "^5.3.0",
|
|
52
52
|
"ora": "^8.0.1",
|