donebear 0.3.9 → 0.4.0
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/README.md +2 -2
- package/dist/cli.mjs +54 -43
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -81,7 +81,7 @@ Edit:
|
|
|
81
81
|
|
|
82
82
|
```bash
|
|
83
83
|
npx donebear task edit <id> --title "Pay vendor invoice"
|
|
84
|
-
npx donebear task edit <id> --
|
|
84
|
+
npx donebear task edit <id> --description "Waiting for approval" --when upcoming
|
|
85
85
|
npx donebear task edit <id> --clear-deadline
|
|
86
86
|
npx donebear task append <id> "Added follow-up note"
|
|
87
87
|
```
|
|
@@ -161,7 +161,7 @@ npx donebear task list --total # count only
|
|
|
161
161
|
| `label` | list | list, show |
|
|
162
162
|
| `team` | list | list, show |
|
|
163
163
|
| `today` | — | List today's tasks |
|
|
164
|
-
| `search` | — | Search tasks by title or
|
|
164
|
+
| `search` | — | Search tasks by title or description |
|
|
165
165
|
| `history` | — | Workspace audit log |
|
|
166
166
|
| `context` | — | Workspace state snapshot (--markdown for prompts) |
|
|
167
167
|
| `spec` | — | CLI spec for agent discovery (no auth required) |
|
package/dist/cli.mjs
CHANGED
|
@@ -7395,8 +7395,8 @@ const filterTasks = (tasks, options) => {
|
|
|
7395
7395
|
if (query.length === 0) return viewFiltered;
|
|
7396
7396
|
return viewFiltered.filter((task) => {
|
|
7397
7397
|
const title = task.title.toLowerCase();
|
|
7398
|
-
const
|
|
7399
|
-
return title.includes(query) ||
|
|
7398
|
+
const description = task.description?.toLowerCase() ?? "";
|
|
7399
|
+
return title.includes(query) || description.includes(query);
|
|
7400
7400
|
});
|
|
7401
7401
|
};
|
|
7402
7402
|
const loadTasksForScope = (context, scope, apiOptions) => {
|
|
@@ -7477,7 +7477,7 @@ const runTaskShow = async (context, taskRef, options, workspaceOverride) => {
|
|
|
7477
7477
|
if (task.projectId) writeInfo(context, `projectId: ${task.projectId}`);
|
|
7478
7478
|
if (task.teamId) writeInfo(context, `teamId: ${task.teamId}`);
|
|
7479
7479
|
if (task.assigneeId) writeInfo(context, `assigneeId: ${task.assigneeId}`);
|
|
7480
|
-
if (task.description) writeInfo(context, `
|
|
7480
|
+
if (task.description) writeInfo(context, `description: ${task.description}`);
|
|
7481
7481
|
};
|
|
7482
7482
|
const resolveTitle = async (context, rawTitle) => {
|
|
7483
7483
|
if (rawTitle) {
|
|
@@ -7488,20 +7488,28 @@ const resolveTitle = async (context, rawTitle) => {
|
|
|
7488
7488
|
if (prompted) return prompted;
|
|
7489
7489
|
throw new CliError("Task title is required.", EXIT_CODES.VALIDATION, "Provide a title as an argument: donebear task add \"My task\"");
|
|
7490
7490
|
};
|
|
7491
|
-
const
|
|
7492
|
-
if (typeof
|
|
7493
|
-
|
|
7494
|
-
|
|
7491
|
+
const resolveDescription = async (context, flagDescription) => {
|
|
7492
|
+
if (typeof flagDescription !== "string") return null;
|
|
7493
|
+
if (flagDescription === "-") {
|
|
7494
|
+
const piped = await readStdin();
|
|
7495
|
+
if (!piped) {
|
|
7496
|
+
writeWarning(context, "No description received on stdin (--description -); task created without a description.");
|
|
7497
|
+
return null;
|
|
7498
|
+
}
|
|
7499
|
+
return piped;
|
|
7495
7500
|
}
|
|
7496
|
-
const
|
|
7497
|
-
if (
|
|
7498
|
-
|
|
7501
|
+
const trimmed = flagDescription.trim();
|
|
7502
|
+
if (trimmed.length === 0) {
|
|
7503
|
+
writeWarning(context, "Empty --description value; task created without a description.");
|
|
7504
|
+
return null;
|
|
7505
|
+
}
|
|
7506
|
+
return trimmed;
|
|
7499
7507
|
};
|
|
7500
7508
|
const runTaskAdd = async (context, title, options, workspaceOverride) => {
|
|
7501
7509
|
const commandContext = await resolveCommandContext(context);
|
|
7502
7510
|
const userId = await requireUserId(context, commandContext);
|
|
7503
7511
|
const normalizedTitle = await resolveTitle(context, title);
|
|
7504
|
-
const
|
|
7512
|
+
const description = await resolveDescription(context, options.description);
|
|
7505
7513
|
const { workspace, autoSelected } = await resolveWorkspace(context, {
|
|
7506
7514
|
apiBaseUrl: commandContext.apiBaseUrl,
|
|
7507
7515
|
storedWorkspaceId: commandContext.localContext.workspaceId,
|
|
@@ -7544,7 +7552,7 @@ const runTaskAdd = async (context, title, options, workspaceOverride) => {
|
|
|
7544
7552
|
createdAt: now,
|
|
7545
7553
|
creatorId: userId,
|
|
7546
7554
|
deadlineAt: deadlineEpoch,
|
|
7547
|
-
description
|
|
7555
|
+
description,
|
|
7548
7556
|
key: taskId.replaceAll("-", "").slice(0, 8),
|
|
7549
7557
|
projectId,
|
|
7550
7558
|
sortOrder: 0,
|
|
@@ -7564,6 +7572,7 @@ const runTaskAdd = async (context, title, options, workspaceOverride) => {
|
|
|
7564
7572
|
autoSelected,
|
|
7565
7573
|
created: true,
|
|
7566
7574
|
deadlineAt: deadlineEpoch,
|
|
7575
|
+
description,
|
|
7567
7576
|
id: taskId,
|
|
7568
7577
|
projectId,
|
|
7569
7578
|
teamId,
|
|
@@ -7577,6 +7586,7 @@ const runTaskAdd = async (context, title, options, workspaceOverride) => {
|
|
|
7577
7586
|
if (autoSelected) writeInfo(context, `Auto-selected workspace: ${workspace.name}`);
|
|
7578
7587
|
writeSuccess(context, `Added task: ${normalizedTitle}`);
|
|
7579
7588
|
writeInfo(context, `id: ${taskId}`);
|
|
7589
|
+
if (description) writeInfo(context, `description: ${description}`);
|
|
7580
7590
|
};
|
|
7581
7591
|
const runTaskMutation = async (context, taskRef, payload) => {
|
|
7582
7592
|
const commandContext = await resolveCommandContext(context);
|
|
@@ -7644,7 +7654,7 @@ const resolveTeamId = async (context, commandContext, teamRef, workspaceRef) =>
|
|
|
7644
7654
|
}), teamRef, "Team");
|
|
7645
7655
|
};
|
|
7646
7656
|
const validateTaskEditOptions = (options) => {
|
|
7647
|
-
if (options.
|
|
7657
|
+
if (options.clearDescription && typeof options.description === "string") throw new Error("Use either --description or --clear-description, not both.");
|
|
7648
7658
|
if (options.clearDeadline && typeof options.deadline === "string") throw new Error("Use either --deadline or --clear-deadline, not both.");
|
|
7649
7659
|
if (options.clearProject && typeof options.project === "string") throw new Error("Use either --project or --clear-project, not both.");
|
|
7650
7660
|
if (options.clearTeam && typeof options.team === "string") throw new Error("Use either --team or --clear-team, not both.");
|
|
@@ -7655,10 +7665,10 @@ const applyScalarEdits = (updates, options) => {
|
|
|
7655
7665
|
if (title.length === 0) throw new Error("Task title cannot be empty.");
|
|
7656
7666
|
updates.title = title;
|
|
7657
7667
|
}
|
|
7658
|
-
if (options.
|
|
7659
|
-
else if (typeof options.
|
|
7660
|
-
const
|
|
7661
|
-
updates.description =
|
|
7668
|
+
if (options.clearDescription) updates.description = null;
|
|
7669
|
+
else if (typeof options.description === "string") {
|
|
7670
|
+
const description = options.description.trim();
|
|
7671
|
+
updates.description = description.length > 0 ? description : null;
|
|
7662
7672
|
}
|
|
7663
7673
|
if (typeof options.when === "string") Object.assign(updates, buildTaskStartFields(parseTaskView(options.when)));
|
|
7664
7674
|
if (options.clearDeadline) updates.deadlineAt = null;
|
|
@@ -7674,7 +7684,7 @@ const runTaskEdit = async (context, taskRef, options, workspaceOverride) => {
|
|
|
7674
7684
|
else if (typeof options.project === "string") updates.projectId = await resolveProjectId(context, commandContext, options.project, wsRef);
|
|
7675
7685
|
if (options.clearTeam) updates.teamId = null;
|
|
7676
7686
|
else if (typeof options.team === "string") updates.teamId = await resolveTeamId(context, commandContext, options.team, wsRef);
|
|
7677
|
-
if (Object.keys(updates).length === 0) throw new Error("No updates provided. Use --title, --
|
|
7687
|
+
if (Object.keys(updates).length === 0) throw new Error("No updates provided. Use --title, --description, --clear-description, --when, --deadline, --clear-deadline, --project, --clear-project, --team, or --clear-team.");
|
|
7678
7688
|
updates.updatedAt = Date.now();
|
|
7679
7689
|
await runTaskMutation(context, taskRef, {
|
|
7680
7690
|
action: "UPDATE",
|
|
@@ -7781,7 +7791,7 @@ const runTaskRandom = async (context, options, workspaceOverride) => {
|
|
|
7781
7791
|
writeInfo(context, `start: ${task.start}`);
|
|
7782
7792
|
writeInfo(context, `startBucket: ${task.startBucket}`);
|
|
7783
7793
|
writeInfo(context, `deadline: ${formatDateOnlyEpoch(task.deadlineAt) ?? "(none)"}`);
|
|
7784
|
-
if (task.description) writeInfo(context, `
|
|
7794
|
+
if (task.description) writeInfo(context, `description: ${task.description}`);
|
|
7785
7795
|
};
|
|
7786
7796
|
const resolveChecklistItemReference = async (context, commandContext, taskId, itemRef) => {
|
|
7787
7797
|
const trimmed = itemRef.trim();
|
|
@@ -7852,7 +7862,7 @@ Agent tip: run "donebear spec task add" for full option reference
|
|
|
7852
7862
|
}, workspaceOverride);
|
|
7853
7863
|
});
|
|
7854
7864
|
});
|
|
7855
|
-
task.command("list").alias("ls").description("List tasks").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").option("-s, --state <state>", "open|done|archived|all", "open").option("-n, --limit <count>", "Maximum number of tasks", (value) => parsePositiveInteger(value, "Limit"), DEFAULT_TASK_LIST_LIMIT).option("-q, --search <query>", "Filter by title or
|
|
7865
|
+
task.command("list").alias("ls").description("List tasks").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").option("-s, --state <state>", "open|done|archived|all", "open").option("-n, --limit <count>", "Maximum number of tasks", (value) => parsePositiveInteger(value, "Limit"), DEFAULT_TASK_LIST_LIMIT).option("-q, --search <query>", "Filter by title or description").option("-v, --view <view>", "Filter by view (inbox|anytime|today|upcoming|someday|logbook|trash)").addHelpText("after", `
|
|
7856
7866
|
Examples:
|
|
7857
7867
|
donebear task list --json
|
|
7858
7868
|
donebear task list --state done --json
|
|
@@ -7873,7 +7883,7 @@ Views: inbox | anytime | today | upcoming | someday | logbook | trash
|
|
|
7873
7883
|
await runTaskShow(context, taskId, options, workspaceOverride);
|
|
7874
7884
|
});
|
|
7875
7885
|
});
|
|
7876
|
-
task.command("read").description("Print the description
|
|
7886
|
+
task.command("read").description("Print the description of a task").argument("<id>", "Task id or unique prefix").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").action(async (taskId, options, command) => {
|
|
7877
7887
|
const context = contextFromCommand(command);
|
|
7878
7888
|
await runWithErrorHandling(context, async () => {
|
|
7879
7889
|
await runTaskRead(context, taskId, options, workspaceOverride);
|
|
@@ -7897,12 +7907,12 @@ Views: inbox | anytime | today | upcoming | someday | logbook | trash
|
|
|
7897
7907
|
await runTaskRandom(context, options, workspaceOverride);
|
|
7898
7908
|
});
|
|
7899
7909
|
});
|
|
7900
|
-
task.command("add").alias("create").description("Create a task").argument("[title]", "Task title (prompted interactively if omitted)").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").option("-
|
|
7910
|
+
task.command("add").alias("create").description("Create a task").argument("[title]", "Task title (prompted interactively if omitted)").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").option("-d, --description <text>", "Task description (use --description - to read from piped stdin)").option("--when <view>", "inbox|anytime|today|upcoming|someday", "inbox").option("--deadline <date>", "Deadline (YYYY-MM-DD or ISO datetime)").option("--project <key-or-id>", "Project key or id").option("--team <key-or-id>", "Team key or id").option("--idempotency-key <key>", "Stable key making retries safe (repeated calls create only one task)").addHelpText("after", `
|
|
7901
7911
|
Examples:
|
|
7902
7912
|
donebear task add "Fix login bug" --when today --json
|
|
7903
7913
|
donebear task add "Write tests" --deadline 2030-03-15 --project PROJ --json
|
|
7904
|
-
donebear task add "Review PR" --when anytime --
|
|
7905
|
-
echo "Multi-line
|
|
7914
|
+
donebear task add "Review PR" --when anytime --description "Check for XSS" --json
|
|
7915
|
+
echo "Multi-line description" | donebear task add "My task" --description -
|
|
7906
7916
|
donebear task add # prompts for title interactively
|
|
7907
7917
|
|
|
7908
7918
|
Date format: YYYY-MM-DD (e.g. 2030-03-15)
|
|
@@ -7913,7 +7923,7 @@ View (--when): inbox | anytime | today | upcoming | someday
|
|
|
7913
7923
|
await runTaskAdd(context, title, options, workspaceOverride);
|
|
7914
7924
|
});
|
|
7915
7925
|
});
|
|
7916
|
-
task.command("edit").description("Update task fields").argument("<id>", "Task id or unique prefix").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").option("--title <title>", "Replace task title").option("--
|
|
7926
|
+
task.command("edit").description("Update task fields").argument("<id>", "Task id or unique prefix").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").option("--title <title>", "Replace task title").option("--description <text>", "Replace task description (empty string clears)").option("--clear-description", "Clear task description").option("--when <view>", "Set view bucket (inbox|anytime|today|upcoming|someday)").option("--deadline <date>", "Set deadline (YYYY-MM-DD or ISO datetime)").option("--clear-deadline", "Clear deadline").option("--project <key-or-id>", "Set project (key or id)").option("--clear-project", "Remove project assignment").option("--team <key-or-id>", "Set team (key or id)").option("--clear-team", "Remove team assignment").action(async (taskId, options, command) => {
|
|
7917
7927
|
const context = contextFromCommand(command);
|
|
7918
7928
|
await runWithErrorHandling(context, async () => {
|
|
7919
7929
|
await runTaskEdit(context, taskId, options, workspaceOverride);
|
|
@@ -8230,7 +8240,7 @@ const runSearch = async (context, query, options, workspaceOverride) => {
|
|
|
8230
8240
|
if (context.copy) copyToClipboard(taskListLines(limited).join("\n"));
|
|
8231
8241
|
};
|
|
8232
8242
|
const registerSearchCommand = (program, workspaceOverride) => {
|
|
8233
|
-
program.command("search").description("Search tasks by title or
|
|
8243
|
+
program.command("search").description("Search tasks by title or description").argument("[query]", "Search query (prompted interactively if omitted)").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").option("-s, --state <state>", "open|done|archived|all", "all").option("-n, --limit <count>", "Maximum number of results", (value) => parsePositiveInteger(value, "Limit"), DEFAULT_SEARCH_LIMIT).addHelpText("after", `
|
|
8234
8244
|
Examples:
|
|
8235
8245
|
donebear search "meeting"
|
|
8236
8246
|
donebear search "launch" --state open
|
|
@@ -8777,13 +8787,14 @@ const COMMAND_SPECS = {
|
|
|
8777
8787
|
examples: [
|
|
8778
8788
|
"donebear task add \"Fix login bug\" --when today --json",
|
|
8779
8789
|
"donebear task add \"Write tests\" --deadline 2026-03-15 --project PROJ --json",
|
|
8780
|
-
"donebear task add \"Review PR\" --when anytime --
|
|
8781
|
-
"echo \"Multi-line
|
|
8790
|
+
"donebear task add \"Review PR\" --when anytime --description \"Triage for bugs\" --json",
|
|
8791
|
+
"echo \"Multi-line description\" | donebear task add \"My task\" --description -",
|
|
8782
8792
|
"donebear task add # prompts for title interactively in TTY"
|
|
8783
8793
|
],
|
|
8784
8794
|
json_output: {
|
|
8785
8795
|
created: "boolean",
|
|
8786
8796
|
deadlineAt: "number | null",
|
|
8797
|
+
description: "string | null",
|
|
8787
8798
|
id: "string (UUID)",
|
|
8788
8799
|
projectId: "string | null",
|
|
8789
8800
|
teamId: "string | null",
|
|
@@ -8792,19 +8803,19 @@ const COMMAND_SPECS = {
|
|
|
8792
8803
|
workspaceId: "string",
|
|
8793
8804
|
workspaceName: "string"
|
|
8794
8805
|
},
|
|
8795
|
-
notes: "Title is prompted interactively when omitted in TTY.
|
|
8806
|
+
notes: "Title is prompted interactively when omitted in TTY. The description is NOT read from stdin unless you pass --description - explicitly; without --description the task is created with no description (and the saved description is echoed back in the output). Task id accepts full UUID or prefix of >= 4 chars in all other task subcommands.",
|
|
8796
8807
|
options: {
|
|
8797
8808
|
"--deadline": {
|
|
8798
8809
|
description: "Due date",
|
|
8799
8810
|
format: "YYYY-MM-DD",
|
|
8800
8811
|
type: "string"
|
|
8801
8812
|
},
|
|
8802
|
-
"--
|
|
8803
|
-
description: "
|
|
8813
|
+
"--description": {
|
|
8814
|
+
description: "Body / description text. Pass --description - to read from piped stdin.",
|
|
8804
8815
|
type: "string"
|
|
8805
8816
|
},
|
|
8806
|
-
"--
|
|
8807
|
-
description: "
|
|
8817
|
+
"--idempotency-key": {
|
|
8818
|
+
description: "Stable key making retries safe (repeated calls create only one task)",
|
|
8808
8819
|
type: "string"
|
|
8809
8820
|
},
|
|
8810
8821
|
"--project": {
|
|
@@ -8847,7 +8858,7 @@ const COMMAND_SPECS = {
|
|
|
8847
8858
|
}
|
|
8848
8859
|
},
|
|
8849
8860
|
command: "task append",
|
|
8850
|
-
description: "Append text to task
|
|
8861
|
+
description: "Append text to a task's description",
|
|
8851
8862
|
examples: ["donebear task append abc1 \"Additional context\" --json"],
|
|
8852
8863
|
json_output: {
|
|
8853
8864
|
id: "string",
|
|
@@ -8908,8 +8919,8 @@ const COMMAND_SPECS = {
|
|
|
8908
8919
|
description: "Clear the due date",
|
|
8909
8920
|
type: "boolean"
|
|
8910
8921
|
},
|
|
8911
|
-
"--clear-
|
|
8912
|
-
description: "Clear
|
|
8922
|
+
"--clear-description": {
|
|
8923
|
+
description: "Clear the description",
|
|
8913
8924
|
type: "boolean"
|
|
8914
8925
|
},
|
|
8915
8926
|
"--clear-project": {
|
|
@@ -8925,8 +8936,8 @@ const COMMAND_SPECS = {
|
|
|
8925
8936
|
format: "YYYY-MM-DD",
|
|
8926
8937
|
type: "string"
|
|
8927
8938
|
},
|
|
8928
|
-
"--
|
|
8929
|
-
description: "Replace
|
|
8939
|
+
"--description": {
|
|
8940
|
+
description: "Replace the task description",
|
|
8930
8941
|
type: "string"
|
|
8931
8942
|
},
|
|
8932
8943
|
"--project": {
|
|
@@ -9024,7 +9035,7 @@ const COMMAND_SPECS = {
|
|
|
9024
9035
|
}
|
|
9025
9036
|
},
|
|
9026
9037
|
command: "task prepend",
|
|
9027
|
-
description: "Prepend text to task
|
|
9038
|
+
description: "Prepend text to a task's description",
|
|
9028
9039
|
examples: ["donebear task prepend abc1 \"URGENT: \" --json"],
|
|
9029
9040
|
json_output: {
|
|
9030
9041
|
id: "string",
|
|
@@ -9040,7 +9051,7 @@ const COMMAND_SPECS = {
|
|
|
9040
9051
|
type: "string"
|
|
9041
9052
|
} },
|
|
9042
9053
|
command: "task read",
|
|
9043
|
-
description: "Print task description
|
|
9054
|
+
description: "Print task description as plain text",
|
|
9044
9055
|
examples: ["donebear task read abc1"],
|
|
9045
9056
|
options: { "--workspace": { type: "string" } },
|
|
9046
9057
|
usage: "donebear task read <id> [options]"
|
|
@@ -9216,15 +9227,15 @@ const TOP_LEVEL_SPECS = {
|
|
|
9216
9227
|
notes: "Task id accepts full UUID or a prefix of >= 4 chars.",
|
|
9217
9228
|
subcommands: {
|
|
9218
9229
|
add: "Create a new task",
|
|
9219
|
-
append: "Append text to task
|
|
9230
|
+
append: "Append text to a task's description",
|
|
9220
9231
|
archive: "Archive a task",
|
|
9221
9232
|
checklist: "Manage task checklist items",
|
|
9222
9233
|
done: "Mark a task as complete",
|
|
9223
9234
|
edit: "Update task fields",
|
|
9224
9235
|
list: "List tasks (--state, --view, --search, --limit)",
|
|
9225
|
-
prepend: "Prepend text to task
|
|
9236
|
+
prepend: "Prepend text to a task's description",
|
|
9226
9237
|
random: "Pick a random task (--state to filter)",
|
|
9227
|
-
read: "Print task
|
|
9238
|
+
read: "Print task description as plain text",
|
|
9228
9239
|
reopen: "Reopen a completed task",
|
|
9229
9240
|
show: "Get task details by id",
|
|
9230
9241
|
unarchive: "Restore an archived task"
|