@braingrid/cli 0.2.17 → 0.2.19

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/CHANGELOG.md CHANGED
@@ -7,6 +7,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.19] - 2025-12-17
11
+
12
+ ### Added
13
+
14
+ - **Pagination options for task commands**
15
+ - Added `--page` and `--limit` options to `task list` and `task summary` commands
16
+ - Consistent with existing pagination options on `requirement list`
17
+
18
+ ### Changed
19
+
20
+ - **has_more pagination warnings**
21
+ - Task and requirement list commands now show a warning when more items exist beyond current page
22
+ - Warning message: "⚠️ More tasks/requirements exist. Use --limit to see more."
23
+ - `getCurrentTask` auto-detection warns if results may be incomplete due to pagination
24
+
25
+ - **Status line uses higher limit**
26
+ - Claude Code status line script now fetches up to 100 tasks for accurate counts
27
+ - Ensures task progress display `[completed/total]` is accurate for larger requirements
28
+
29
+ ## [0.2.18] - 2025-12-17
30
+
31
+ ### Added
32
+
33
+ - **Current task auto-detection**
34
+ - `task show` now works without a task ID - automatically detects the current task
35
+ - `task update` now works without a task ID - updates the current task
36
+ - Current task is determined by: first IN_PROGRESS task, or first PLANNED task if none in progress
37
+ - `task delete` still requires explicit task ID for safety
38
+
39
+ - **Status line shows current task**
40
+ - Claude Code status line now displays: `BrainGrid: PROJ-X > REQ-Y > TASK-Z [completed/total]`
41
+ - Shows the current task being worked on alongside progress count
42
+ - Automatically updates as tasks are completed
43
+
10
44
  ## [0.2.17] - 2025-12-17
11
45
 
12
46
  ### Added
package/dist/cli.js CHANGED
@@ -422,7 +422,7 @@ import axios3, { AxiosError as AxiosError2 } from "axios";
422
422
 
423
423
  // src/build-config.ts
424
424
  var BUILD_ENV = true ? "production" : process.env.NODE_ENV === "test" ? "development" : "production";
425
- var CLI_VERSION = true ? "0.2.17" : "0.0.0-test";
425
+ var CLI_VERSION = true ? "0.2.19" : "0.0.0-test";
426
426
  var PRODUCTION_CONFIG = {
427
427
  apiUrl: "https://app.braingrid.ai",
428
428
  workosAuthUrl: "https://auth.braingrid.ai",
@@ -3914,6 +3914,9 @@ async function handleRequirementList(opts) {
3914
3914
  break;
3915
3915
  }
3916
3916
  }
3917
+ if (response.pagination?.has_more) {
3918
+ output += "\n" + chalk7.yellow("\u26A0\uFE0F More requirements exist. Use --limit to see more.");
3919
+ }
3917
3920
  return {
3918
3921
  success: true,
3919
3922
  message: output,
@@ -4518,6 +4521,29 @@ function getServices3() {
4518
4521
  const taskService = new TaskService(config.apiUrl, auth);
4519
4522
  return { taskService, auth };
4520
4523
  }
4524
+ async function getCurrentTask(taskService, projectId, requirementId) {
4525
+ const response = await taskService.listTasks(projectId, requirementId);
4526
+ const inProgress = response.tasks.find((t) => t.status === "IN_PROGRESS");
4527
+ if (inProgress) {
4528
+ const warning = response.pagination?.has_more ? "Note: More tasks exist beyond current page." : void 0;
4529
+ return { success: true, taskId: inProgress.number, warning };
4530
+ }
4531
+ const planned = response.tasks.find((t) => t.status === "PLANNED");
4532
+ if (planned) {
4533
+ const warning = response.pagination?.has_more ? "Note: More tasks exist beyond current page." : void 0;
4534
+ return { success: true, taskId: planned.number, warning };
4535
+ }
4536
+ if (response.pagination?.has_more) {
4537
+ return {
4538
+ success: false,
4539
+ error: "No active task found in current page. More tasks exist - use --limit to fetch more."
4540
+ };
4541
+ }
4542
+ return {
4543
+ success: false,
4544
+ error: "No active task found. All tasks are completed or cancelled."
4545
+ };
4546
+ }
4521
4547
  async function handleTaskList(opts) {
4522
4548
  let stopSpinner = null;
4523
4549
  try {
@@ -4546,7 +4572,10 @@ async function handleTaskList(opts) {
4546
4572
  }
4547
4573
  const requirementId = requirementResult.requirementId;
4548
4574
  stopSpinner = showSpinner("Loading tasks", chalk8.gray);
4549
- const response = await taskService.listTasks(projectId, requirementId);
4575
+ const response = await taskService.listTasks(projectId, requirementId, {
4576
+ page: opts.page ? parseInt(opts.page, 10) : 1,
4577
+ limit: opts.limit ? parseInt(opts.limit, 10) : 20
4578
+ });
4550
4579
  stopSpinner();
4551
4580
  stopSpinner = null;
4552
4581
  if (response.tasks.length === 0) {
@@ -4560,12 +4589,15 @@ async function handleTaskList(opts) {
4560
4589
  const requirementShortId = opts.requirement || requirementId;
4561
4590
  const format = opts.format || "markdown";
4562
4591
  const config = getConfig();
4563
- const output = formatTasksListOutput(response.tasks, format, true, {
4592
+ let output = formatTasksListOutput(response.tasks, format, true, {
4564
4593
  requirementId,
4565
4594
  projectShortId,
4566
4595
  requirementShortId,
4567
4596
  apiUrl: config.apiUrl
4568
4597
  });
4598
+ if (response.pagination?.has_more) {
4599
+ output += "\n" + chalk8.yellow("\u26A0\uFE0F More tasks exist. Use --limit to see more.");
4600
+ }
4569
4601
  return {
4570
4602
  success: true,
4571
4603
  message: output,
@@ -4609,7 +4641,10 @@ async function handleTaskSummary(opts) {
4609
4641
  }
4610
4642
  const requirementId = requirementResult.requirementId;
4611
4643
  stopSpinner = showSpinner("Loading tasks", chalk8.gray);
4612
- const response = await taskService.listTasks(projectId, requirementId);
4644
+ const response = await taskService.listTasks(projectId, requirementId, {
4645
+ page: opts.page ? parseInt(opts.page, 10) : 1,
4646
+ limit: opts.limit ? parseInt(opts.limit, 10) : 20
4647
+ });
4613
4648
  stopSpinner();
4614
4649
  stopSpinner = null;
4615
4650
  if (response.tasks.length === 0) {
@@ -4622,12 +4657,15 @@ async function handleTaskSummary(opts) {
4622
4657
  const projectShortId = projectId;
4623
4658
  const requirementShortId = opts.requirement || requirementId;
4624
4659
  const config = getConfig();
4625
- const output = formatTasksListOutput(response.tasks, "table", false, {
4660
+ let output = formatTasksListOutput(response.tasks, "table", false, {
4626
4661
  requirementId,
4627
4662
  projectShortId,
4628
4663
  requirementShortId,
4629
4664
  apiUrl: config.apiUrl
4630
4665
  });
4666
+ if (response.pagination?.has_more) {
4667
+ output += "\n" + chalk8.yellow("\u26A0\uFE0F More tasks exist. Use --limit to see more.");
4668
+ }
4631
4669
  return {
4632
4670
  success: true,
4633
4671
  message: output,
@@ -4679,7 +4717,21 @@ async function handleTaskShow(id, opts) {
4679
4717
  };
4680
4718
  }
4681
4719
  const requirementId = requirementResult.requirementId;
4682
- const taskId = normalizeTaskId(id);
4720
+ let taskId;
4721
+ let taskWarning;
4722
+ if (id) {
4723
+ taskId = normalizeTaskId(id);
4724
+ } else {
4725
+ const currentTask = await getCurrentTask(taskService, projectId, requirementId);
4726
+ if (!currentTask.success) {
4727
+ return {
4728
+ success: false,
4729
+ message: chalk8.red(`\u274C ${currentTask.error}`)
4730
+ };
4731
+ }
4732
+ taskId = currentTask.taskId;
4733
+ taskWarning = currentTask.warning;
4734
+ }
4683
4735
  const config = getConfig();
4684
4736
  stopSpinner = showSpinner("Loading task", chalk8.gray);
4685
4737
  const task2 = await taskService.getTask(projectId, requirementId, taskId);
@@ -4713,6 +4765,9 @@ async function handleTaskShow(id, opts) {
4713
4765
  break;
4714
4766
  }
4715
4767
  }
4768
+ if (taskWarning) {
4769
+ output += "\n" + chalk8.yellow(`\u26A0\uFE0F ${taskWarning}`);
4770
+ }
4716
4771
  return {
4717
4772
  success: true,
4718
4773
  message: output,
@@ -4799,13 +4854,13 @@ async function handleTaskUpdate(id, opts) {
4799
4854
  message: chalk8.red("\u274C Not authenticated. Please run `braingrid login` first.")
4800
4855
  };
4801
4856
  }
4802
- if (!opts.status && !opts.title) {
4857
+ if (!opts?.status && !opts?.title) {
4803
4858
  return {
4804
4859
  success: false,
4805
4860
  message: chalk8.red("\u274C Please provide at least one field to update (--status or --title)")
4806
4861
  };
4807
4862
  }
4808
- const workspace = await workspaceManager.getProject(opts.project);
4863
+ const workspace = await workspaceManager.getProject(opts?.project);
4809
4864
  if (!workspace.success) {
4810
4865
  return {
4811
4866
  success: false,
@@ -4813,7 +4868,7 @@ async function handleTaskUpdate(id, opts) {
4813
4868
  };
4814
4869
  }
4815
4870
  const projectId = workspace.projectId;
4816
- const requirementResult = await workspaceManager.getRequirement(opts.requirement);
4871
+ const requirementResult = await workspaceManager.getRequirement(opts?.requirement);
4817
4872
  if (!requirementResult.success) {
4818
4873
  return {
4819
4874
  success: false,
@@ -4821,23 +4876,40 @@ async function handleTaskUpdate(id, opts) {
4821
4876
  };
4822
4877
  }
4823
4878
  const requirementId = requirementResult.requirementId;
4824
- const taskId = normalizeTaskId(id);
4879
+ let taskId;
4880
+ let taskWarning;
4881
+ if (id) {
4882
+ taskId = normalizeTaskId(id);
4883
+ } else {
4884
+ const currentTask = await getCurrentTask(taskService, projectId, requirementId);
4885
+ if (!currentTask.success) {
4886
+ return {
4887
+ success: false,
4888
+ message: chalk8.red(`\u274C ${currentTask.error}`)
4889
+ };
4890
+ }
4891
+ taskId = currentTask.taskId;
4892
+ taskWarning = currentTask.warning;
4893
+ }
4825
4894
  const config = getConfig();
4826
4895
  stopSpinner = showSpinner("Updating task", chalk8.gray);
4827
4896
  const task2 = await taskService.updateTask(projectId, requirementId, taskId, {
4828
- status: opts.status,
4829
- title: opts.title
4897
+ status: opts?.status,
4898
+ title: opts?.title
4830
4899
  });
4831
4900
  stopSpinner();
4832
4901
  stopSpinner = null;
4833
- const output = formatTaskOutput(task2, {
4902
+ let output = formatTaskOutput(task2, {
4834
4903
  showContent: true,
4835
4904
  successMessage: `Updated task ${task2.number}`,
4836
4905
  apiUrl: config.apiUrl,
4837
4906
  projectShortId: projectId,
4838
- requirementShortId: opts.requirement || requirementId,
4907
+ requirementShortId: opts?.requirement || requirementId,
4839
4908
  requirementId
4840
4909
  });
4910
+ if (taskWarning) {
4911
+ output += "\n" + chalk8.yellow(`\u26A0\uFE0F ${taskWarning}`);
4912
+ }
4841
4913
  return {
4842
4914
  success: true,
4843
4915
  message: output,
@@ -7168,21 +7240,21 @@ requirement.command("build [id]").description(
7168
7240
  }
7169
7241
  });
7170
7242
  var task = program.command("task").description("Manage tasks");
7171
- task.command("list").description("List tasks for a requirement").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").option("--format <format>", "output format (table, json, xml, markdown)", "markdown").action(async (opts) => {
7243
+ task.command("list").description("List tasks for a requirement").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").option("--format <format>", "output format (table, json, xml, markdown)", "markdown").option("--page <page>", "page number for pagination", "1").option("--limit <limit>", "number of tasks per page", "20").action(async (opts) => {
7172
7244
  const result = await handleTaskList(opts);
7173
7245
  console.log(result.message);
7174
7246
  if (!result.success) {
7175
7247
  process.exit(1);
7176
7248
  }
7177
7249
  });
7178
- task.command("summary").description("Show task summary table (quick overview without content)").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").action(async (opts) => {
7250
+ task.command("summary").description("Show task summary table (quick overview without content)").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").option("--page <page>", "page number for pagination", "1").option("--limit <limit>", "number of tasks per page", "20").action(async (opts) => {
7179
7251
  const result = await handleTaskSummary(opts);
7180
7252
  console.log(result.message);
7181
7253
  if (!result.success) {
7182
7254
  process.exit(1);
7183
7255
  }
7184
7256
  });
7185
- task.command("show <id>").description("Show task details").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").option("--format <format>", "output format (table, json, xml, markdown)", "table").action(async (id, opts) => {
7257
+ task.command("show [id]").description("Show task details (auto-detects current task if not provided)").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").option("--format <format>", "output format (table, json, xml, markdown)", "table").action(async (id, opts) => {
7186
7258
  const result = await handleTaskShow(id, opts);
7187
7259
  console.log(result.message);
7188
7260
  if (!result.success) {
@@ -7196,7 +7268,7 @@ task.command("create").description("Create a new task").option("-r, --requiremen
7196
7268
  process.exit(1);
7197
7269
  }
7198
7270
  });
7199
- task.command("update <id>").description("Update task information").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").option("--status <status>", "new status (PLANNED, IN_PROGRESS, COMPLETED, CANCELLED)").option("--title <title>", "new task title").action(async (id, opts) => {
7271
+ task.command("update [id]").description("Update task (auto-detects current task if not provided)").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").option("--status <status>", "new status (PLANNED, IN_PROGRESS, COMPLETED, CANCELLED)").option("--title <title>", "new task title").action(async (id, opts) => {
7200
7272
  const result = await handleTaskUpdate(id, opts);
7201
7273
  console.log(result.message);
7202
7274
  if (!result.success) {