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 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> --notes "Waiting for approval" --when upcoming
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 notes |
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 notes = task.description?.toLowerCase() ?? "";
7399
- return title.includes(query) || notes.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, `notes: ${task.description}`);
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 resolveNotes = async (_context, flagNotes) => {
7492
- if (typeof flagNotes === "string") {
7493
- const trimmed = flagNotes.trim();
7494
- return trimmed.length > 0 ? trimmed : null;
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 stdinContent = await readStdin();
7497
- if (stdinContent) return stdinContent;
7498
- return null;
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 notes = await resolveNotes(context, options.notes);
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: notes,
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.clearNotes && typeof options.notes === "string") throw new Error("Use either --notes or --clear-notes, not both.");
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.clearNotes) updates.description = null;
7659
- else if (typeof options.notes === "string") {
7660
- const notes = options.notes.trim();
7661
- updates.description = notes.length > 0 ? notes : null;
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, --notes, --clear-notes, --when, --deadline, --clear-deadline, --project, --clear-project, --team, or --clear-team.");
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, `notes: ${task.description}`);
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 notes").option("-v, --view <view>", "Filter by view (inbox|anytime|today|upcoming|someday|logbook|trash)").addHelpText("after", `
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 (notes) 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) => {
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("-n, --notes <text>", "Task notes (or pipe via 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", `
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 --notes "Check for XSS" --json
7905
- echo "Multi-line notes" | donebear task add "My task"
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("--notes <text>", "Replace task notes (empty string clears)").option("--clear-notes", "Clear task notes").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) => {
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 notes").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", `
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 --notes \"Triage for bugs\" --json",
8781
- "echo \"Multi-line notes\" | donebear task add \"My task\"",
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. Notes can be piped via stdin. Task id accepts full UUID or prefix of >= 4 chars in all other task subcommands.",
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
- "--idempotency-key": {
8803
- description: "Stable key making retries safe (repeated calls create only one task)",
8813
+ "--description": {
8814
+ description: "Body / description text. Pass --description - to read from piped stdin.",
8804
8815
  type: "string"
8805
8816
  },
8806
- "--notes": {
8807
- description: "Body / description text (or pipe via stdin)",
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 notes",
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-notes": {
8912
- description: "Clear notes/description",
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
- "--notes": {
8929
- description: "Replace notes/description",
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 notes",
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/notes as plain text",
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 notes",
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 notes",
9236
+ prepend: "Prepend text to a task's description",
9226
9237
  random: "Pick a random task (--state to filter)",
9227
- read: "Print task notes as plain text",
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"