@basementuniverse/kanbn 1.1.1 → 2.1.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.
Files changed (182) hide show
  1. package/README.md +3 -0
  2. package/coverage/base.css +224 -0
  3. package/coverage/block-navigation.js +87 -0
  4. package/coverage/coverage-summary.json +31 -0
  5. package/coverage/favicon.png +0 -0
  6. package/coverage/index.html +146 -0
  7. package/coverage/kanbn/index.html +116 -0
  8. package/coverage/kanbn/index.js.html +217 -0
  9. package/coverage/kanbn/src/board.js.html +646 -0
  10. package/coverage/kanbn/src/controller/add.js.html +1729 -0
  11. package/coverage/kanbn/src/controller/archive.js.html +277 -0
  12. package/coverage/kanbn/src/controller/board.js.html +217 -0
  13. package/coverage/kanbn/src/controller/burndown.js.html +607 -0
  14. package/coverage/kanbn/src/controller/comment.js.html +397 -0
  15. package/coverage/kanbn/src/controller/edit.js.html +2920 -0
  16. package/coverage/kanbn/src/controller/find.js.html +1597 -0
  17. package/coverage/kanbn/src/controller/gantt.js.html +1342 -0
  18. package/coverage/kanbn/src/controller/help.js.html +115 -0
  19. package/coverage/kanbn/src/controller/history.js.html +400 -0
  20. package/coverage/kanbn/src/controller/index.html +431 -0
  21. package/coverage/kanbn/src/controller/init.js.html +511 -0
  22. package/coverage/kanbn/src/controller/move.js.html +514 -0
  23. package/coverage/kanbn/src/controller/remove-all.js.html +226 -0
  24. package/coverage/kanbn/src/controller/remove.js.html +307 -0
  25. package/coverage/kanbn/src/controller/rename.js.html +397 -0
  26. package/coverage/kanbn/src/controller/restore.js.html +268 -0
  27. package/coverage/kanbn/src/controller/sort.js.html +1318 -0
  28. package/coverage/kanbn/src/controller/sprint.js.html +361 -0
  29. package/coverage/kanbn/src/controller/status.js.html +310 -0
  30. package/coverage/kanbn/src/controller/task.js.html +244 -0
  31. package/coverage/kanbn/src/controller/validate.js.html +367 -0
  32. package/coverage/kanbn/src/controller/version.js.html +100 -0
  33. package/coverage/kanbn/src/index.html +191 -0
  34. package/coverage/kanbn/src/main.js.html +9787 -0
  35. package/coverage/kanbn/src/parse-index.js.html +1063 -0
  36. package/coverage/kanbn/src/parse-markdown.js.html +202 -0
  37. package/coverage/kanbn/src/parse-task.js.html +2191 -0
  38. package/coverage/kanbn/src/utility.js.html +616 -0
  39. package/coverage/lcov.info +11837 -0
  40. package/coverage/prettify.css +1 -0
  41. package/coverage/prettify.js +2 -0
  42. package/coverage/sort-arrow-sprite.png +0 -0
  43. package/coverage/sorter.js +210 -0
  44. package/coverage/tmp/coverage-214292-1787777191526-0.json +1 -0
  45. package/coverage/tmp/coverage-214293-1787777184569-0.json +1 -0
  46. package/docs/advanced-configuration.md +25 -0
  47. package/docs/commands/add.txt +19 -0
  48. package/docs/commands/archive.txt +5 -0
  49. package/docs/commands/board.txt +8 -1
  50. package/docs/commands/boards.txt +34 -0
  51. package/docs/commands/burndown.txt +8 -4
  52. package/docs/commands/comment.txt +5 -0
  53. package/docs/commands/edit.txt +27 -0
  54. package/docs/commands/find.txt +56 -1
  55. package/docs/commands/gantt.txt +5 -0
  56. package/docs/commands/help.txt +2 -0
  57. package/docs/commands/history.txt +5 -0
  58. package/docs/commands/init.txt +13 -0
  59. package/docs/commands/move.txt +10 -1
  60. package/docs/commands/remove.txt +12 -1
  61. package/docs/commands/rename.txt +5 -0
  62. package/docs/commands/restore.txt +6 -0
  63. package/docs/commands/sort.txt +18 -2
  64. package/docs/commands/sprint.txt +9 -0
  65. package/docs/commands/status.txt +10 -1
  66. package/docs/commands/task.txt +5 -0
  67. package/docs/commands/validate.txt +27 -0
  68. package/docs/filtering-and-sorting.md +218 -0
  69. package/docs/index-structure.md +94 -19
  70. package/docs/index.md +28 -2
  71. package/docs/migration-2.0.md +92 -0
  72. package/docs/multiple-boards.md +258 -0
  73. package/docs/quick-start.md +57 -1
  74. package/docs/task-structure.md +33 -3
  75. package/docs/views.md +229 -0
  76. package/example/README.md +93 -0
  77. package/example/advanced/.kanbn/index.md +26 -0
  78. package/example/advanced/.kanbn/tasks/add-rate-limiting.md +18 -0
  79. package/example/advanced/.kanbn/tasks/add-sso-support.md +15 -0
  80. package/example/advanced/.kanbn/tasks/migrate-to-new-cdn.md +14 -0
  81. package/example/advanced/.kanbn/tasks/refresh-marketing-site.md +14 -0
  82. package/example/advanced/.kanbn/tasks/rotate-api-keys.md +15 -0
  83. package/example/advanced/.kanbn/tasks/split-billing-service.md +17 -0
  84. package/example/advanced/.kanbn/tasks/upgrade-node-runtime.md +19 -0
  85. package/example/advanced/kanbn.yml +59 -0
  86. package/example/boards/.kanbn/design.md +31 -0
  87. package/example/boards/.kanbn/index.md +44 -0
  88. package/example/boards/.kanbn/tasks/add-usage-alert-emails.md +19 -0
  89. package/example/boards/.kanbn/tasks/build-tenant-settings-page.md +43 -0
  90. package/example/boards/.kanbn/tasks/create-organization-switcher.md +44 -0
  91. package/example/boards/.kanbn/tasks/design-onboarding-checklist.md +22 -0
  92. package/example/boards/.kanbn/tasks/refresh-marketing-site.md +28 -0
  93. package/example/boards/.kanbn/tasks/ship-billing-portal.md +29 -0
  94. package/example/views/.kanbn/index.md +140 -0
  95. package/example/views/.kanbn/tasks/add-audit-log-export.md +18 -0
  96. package/example/views/.kanbn/tasks/add-dark-mode-toggle.md +16 -0
  97. package/example/views/.kanbn/tasks/build-webhook-retry-queue.md +15 -0
  98. package/example/views/.kanbn/tasks/fix-avatar-upload-crash.md +13 -0
  99. package/example/views/.kanbn/tasks/fix-expired-session-redirect.md +15 -0
  100. package/example/views/.kanbn/tasks/investigate-offline-mode.md +12 -0
  101. package/example/views/.kanbn/tasks/rewrite-search-indexer.md +12 -0
  102. package/example/views/.kanbn/tasks/tidy-up-settings-copy.md +12 -0
  103. package/package.json +12 -9
  104. package/routes/add.json +35 -11
  105. package/routes/archive.json +10 -2
  106. package/routes/board.json +11 -3
  107. package/routes/boards.json +30 -0
  108. package/routes/burndown.json +23 -7
  109. package/routes/comment.json +14 -4
  110. package/routes/edit.json +33 -10
  111. package/routes/find.json +37 -12
  112. package/routes/gantt.json +20 -6
  113. package/routes/history.json +39 -25
  114. package/routes/init.json +3 -1
  115. package/routes/move.json +22 -6
  116. package/routes/remove.json +15 -4
  117. package/routes/rename.json +11 -3
  118. package/routes/restore.json +8 -2
  119. package/routes/sort.json +35 -11
  120. package/routes/sprint.json +14 -4
  121. package/routes/status.json +23 -7
  122. package/routes/task.json +10 -2
  123. package/routes/validate.json +19 -4
  124. package/skills/kanbn-plan/SKILL.md +10 -1
  125. package/skills/kanbn-plan/references/index-structure.md +1 -0
  126. package/skills/kanbn-plan/references/task-structure.md +2 -0
  127. package/skills/kanbn-replan/SKILL.md +6 -1
  128. package/src/board.js +2 -1
  129. package/src/controller/add.js +52 -46
  130. package/src/controller/archive.js +8 -4
  131. package/src/controller/board.js +9 -4
  132. package/src/controller/boards.js +140 -0
  133. package/src/controller/burndown.js +9 -5
  134. package/src/controller/comment.js +9 -5
  135. package/src/controller/edit.js +74 -17
  136. package/src/controller/find.js +12 -9
  137. package/src/controller/gantt.js +8 -4
  138. package/src/controller/history.js +8 -4
  139. package/src/controller/init.js +39 -4
  140. package/src/controller/move.js +69 -15
  141. package/src/controller/remove.js +34 -11
  142. package/src/controller/rename.js +8 -4
  143. package/src/controller/restore.js +23 -8
  144. package/src/controller/sort.js +19 -3
  145. package/src/controller/sprint.js +31 -7
  146. package/src/controller/status.js +20 -4
  147. package/src/controller/task.js +22 -9
  148. package/src/controller/validate.js +139 -23
  149. package/src/git-user-name.js +19 -0
  150. package/src/main.d.ts +184 -6
  151. package/src/main.js +1642 -221
  152. package/src/parse-index.js +17 -0
  153. package/src/parse-markdown.js +3 -1
  154. package/src/parse-task.js +44 -1
  155. package/src/utility.js +166 -1
  156. package/PLANS.md +0 -9
  157. /package/example/{.kanbn → basic/.kanbn}/index.md +0 -0
  158. /package/example/{.kanbn → basic/.kanbn}/tasks/add-basic-activity-feed.md +0 -0
  159. /package/example/{.kanbn → basic/.kanbn}/tasks/add-passwordless-login-option.md +0 -0
  160. /package/example/{.kanbn → basic/.kanbn}/tasks/add-usage-alert-email-thresholds.md +0 -0
  161. /package/example/{.kanbn → basic/.kanbn}/tasks/build-email-template-system.md +0 -0
  162. /package/example/{.kanbn → basic/.kanbn}/tasks/build-invoice-download-endpoint.md +0 -0
  163. /package/example/{.kanbn → basic/.kanbn}/tasks/build-tenant-settings-page.md +0 -0
  164. /package/example/{.kanbn → basic/.kanbn}/tasks/create-organization-switcher.md +0 -0
  165. /package/example/{.kanbn → basic/.kanbn}/tasks/create-sandbox-environment-provisioner.md +0 -0
  166. /package/example/{.kanbn → basic/.kanbn}/tasks/create-self-serve-cancellation-flow.md +0 -0
  167. /package/example/{.kanbn → basic/.kanbn}/tasks/define-product-pricing-strategy.md +0 -0
  168. /package/example/{.kanbn → basic/.kanbn}/tasks/design-onboarding-checklist.md +0 -0
  169. /package/example/{.kanbn → basic/.kanbn}/tasks/design-team-invite-expiry-flow.md +0 -0
  170. /package/example/{.kanbn → basic/.kanbn}/tasks/implement-data-retention-policy-jobs.md +0 -0
  171. /package/example/{.kanbn → basic/.kanbn}/tasks/implement-feature-flags-foundation.md +0 -0
  172. /package/example/{.kanbn → basic/.kanbn}/tasks/implement-project-creation-wizard.md +0 -0
  173. /package/example/{.kanbn → basic/.kanbn}/tasks/implement-stripe-webhook-signature-check.md +0 -0
  174. /package/example/{.kanbn → basic/.kanbn}/tasks/implement-team-permissions-ui.md +0 -0
  175. /package/example/{.kanbn → basic/.kanbn}/tasks/implement-user-signup-and-login.md +0 -0
  176. /package/example/{.kanbn → basic/.kanbn}/tasks/integrate-crm-lead-sync.md +0 -0
  177. /package/example/{.kanbn → basic/.kanbn}/tasks/legal-review-terms-and-privacy.md +0 -0
  178. /package/example/{.kanbn → basic/.kanbn}/tasks/migrate-legacy-events-to-new-schema.md +0 -0
  179. /package/example/{.kanbn → basic/.kanbn}/tasks/optimize-dashboard-first-load.md +0 -0
  180. /package/example/{.kanbn → basic/.kanbn}/tasks/prototype-report-export-scheduler.md +0 -0
  181. /package/example/{.kanbn → basic/.kanbn}/tasks/publish-internal-qa-checklist.md +0 -0
  182. /package/example/{.kanbn → basic/.kanbn}/tasks/setup-ci-pipeline.md +0 -0
@@ -4,10 +4,20 @@
4
4
  Search all tasks in the index and show search results. If no filters are specified, this command will list all tracked tasks.
5
5
 
6
6
  String search terms are treated as case-insensitive regular expressions.
7
+ Date filters match a single day, or a range if the option is repeated.
8
+ Numeric filters match a single value, or a range if the option is repeated.
7
9
 
8
10
  Only tasks that match all of the filters will be returned.
9
11
 
12
+ Filters ignore hidden columns - use --column to exclude them.
13
+
14
+ See docs/filtering-and-sorting.md for a full description of the filter model.
15
+
10
16
  Options:
17
+ {b}kanbn find --interactive{b}
18
+ {b}kanbn find -i{b}
19
+ Build search filters interactively.
20
+
11
21
  {b}kanbn find --quiet{b}
12
22
  {b}kanbn find -q{b}
13
23
  Only show task ids in the output.
@@ -16,6 +26,9 @@ Options:
16
26
  {b}kanbn find -j{b}
17
27
  Output results in JSON format. If used with the --quiet option, this will return an array of task ids.
18
28
 
29
+ {b}kanbn find --id "search term"{b}
30
+ Find tasks that have an id containing "search term".
31
+
19
32
  {b}kanbn find --name "search term"{b}
20
33
  {b}kanbn find -n "search term"{b}
21
34
  Find tasks that have a name containing "search term".
@@ -54,8 +67,26 @@ Options:
54
67
  This option can be repeated - if multiple dates are specified, find tasks that are due between the earliest and latest dates.
55
68
  The date can be in (almost) any format.
56
69
 
70
+ {b}kanbn find --plannedStart "date"{b}
71
+ Find tasks that have a planned start date that matches the specified date. The time part of the date will be ignored, unless searching between multiple dates.
72
+ This option can be repeated - if multiple dates are specified, find tasks with a planned start date between the earliest and latest dates.
73
+ The date can be in (almost) any format.
74
+
75
+ {b}kanbn find --plannedFinish "date"{b}
76
+ Find tasks that have a planned finish date that matches the specified date. The time part of the date will be ignored, unless searching between multiple dates.
77
+ This option can be repeated - if multiple dates are specified, find tasks with a planned finish date between the earliest and latest dates.
78
+ The date can be in (almost) any format.
79
+
57
80
  {b}kanbn find --assigned "name"{b}
58
- Find tasks assigned to a specific user.
81
+ Find tasks assigned to a specific user. Use "^$" to find unassigned tasks.
82
+
83
+ {b}kanbn find --workload N{b}
84
+ Find tasks with a specific calculated workload.
85
+ If multiple values are specified, find tasks with a workload between the lowest and highest inputs.
86
+
87
+ {b}kanbn find --progress N{b}
88
+ Find tasks with a specific progress value (between 0 and 1).
89
+ If multiple values are specified, find tasks with progress between the lowest and highest inputs.
59
90
 
60
91
  {b}kanbn find --sub-task "search term"{b}
61
92
  {b}kanbn find -s "search term"{b}
@@ -90,6 +121,30 @@ Options:
90
121
 
91
122
  {b}kanbn find --<custom field name> "search term"|N|date{b}
92
123
  Find tasks with a custom metadata field that matches the search filter.
124
+ The custom field must be declared in the customFields project option.
93
125
  If the custom field is a string and multiple filters are specified, find tasks with a value that matches one of the inputs.
94
126
  If the custom field is numeric and multiple filters are specified, find tasks with a value between the lowest and highest inputs.
95
127
  If the custom field is a date and multiple filters are specified, find tasks with a value between the earliest and latest dates.
128
+ If the custom field is a boolean, use {b}--<custom field name>{b} to match true and {b}--no-<custom field name>{b} to match false.
129
+
130
+ Examples:
131
+ {b}kanbn find --column Todo --column "In Progress" --assigned "^Ana$"{b}
132
+ Find tasks assigned to exactly "Ana" that are in either the "Todo" or "In Progress" column.
133
+
134
+ {b}kanbn find --tag "(^|\n)Bug($|\n)" --due "1 July 2026" --due "31 July 2026"{b}
135
+ Find tasks with the exact tag "Bug" that are due in July 2026.
136
+ Tags are matched against a newline-separated list, so anchoring on line breaks matches a whole tag.
137
+
138
+ {b}kanbn find --count-sub-tasks 1 --count-sub-tasks 99 --progress 0 -q{b}
139
+ List the ids of tasks that have sub-tasks but no progress yet.
140
+
141
+ {b}kanbn find --board "board-slug"{b}
142
+ {b}kanbn find -b "board-slug"{b}
143
+ Target a board other than the main one. Falls back to the KANBN_BOARD environment variable and
144
+ then to the defaultBoard option. See {b}kanbn boards{b} for the list of boards.
145
+
146
+ {b}kanbn find --all-boards{b}
147
+ Search every board in the workspace. A task on several boards appears once, annotated with the
148
+ board and column it occupies on each. Without this, the search is scoped to the target board.
149
+ This can't be combined with {b}--sprint{b}: sprint numbers and names are relative to one board's
150
+ list, so there is no sensible answer across several.
@@ -30,3 +30,8 @@ Options:
30
30
  {b}kanbn gantt --now "date"{b}
31
31
  {b}kanbn gantt -n "date"{b}
32
32
  Mock the current date used for the "now" line and single-date range filtering.
33
+
34
+ {b}kanbn gantt --board "board-slug"{b}
35
+ {b}kanbn gantt -b "board-slug"{b}
36
+ Target a board other than the main one. Falls back to the KANBN_BOARD environment variable and
37
+ then to the defaultBoard option. See {b}kanbn boards{b} for the list of boards.
@@ -7,6 +7,7 @@ Where {b}<command>{b} is one of:
7
7
  {b}version{b} {d}.......{d} Show package version
8
8
  {b}init{b} {d}..........{d} Initialise kanbn board
9
9
  {b}board{b} {d}.........{d} Show the kanbn board
10
+ {b}boards{b} {d}........{d} List the boards in this workspace
10
11
  {b}task{b} {d}..........{d} Show a kanbn task
11
12
  {b}add{b} {d}...........{d} Add a kanbn task
12
13
  {b}edit{b} {d}..........{d} Edit a kanbn task
@@ -24,6 +25,7 @@ Where {b}<command>{b} is one of:
24
25
  {b}archive{b} {d}.......{d} Archive a task
25
26
  {b}restore{b} {d}.......{d} Restore a task from the archive
26
27
  {b}remove-all{b} {d}....{d} Remove the kanbn board and all tasks
28
+ {b}history{b} {d}.......{d} Show task history
27
29
 
28
30
  For more help with commands, try:
29
31
 
@@ -27,3 +27,8 @@ Options:
27
27
  {b}kanbn history -t "task-id"{b}
28
28
  Filter for one or more task ids.
29
29
  This option can be repeated.
30
+
31
+ {b}kanbn history --board "board-slug"{b}
32
+ {b}kanbn history -b "board-slug"{b}
33
+ Target a board other than the main one. Falls back to the KANBN_BOARD environment variable and
34
+ then to the defaultBoard option. See {b}kanbn boards{b} for the list of boards.
@@ -19,3 +19,16 @@ Options:
19
19
  {b}kanbn init --column "column"{b}
20
20
  {b}kanbn init -c "column"{b}
21
21
  Initialise a kanbn board and add the specified column. This option can be repeated to add multiple columns.
22
+
23
+ {b}kanbn init --board "board-slug"{b}
24
+ {b}kanbn init -b "board-slug"{b}
25
+ Create a secondary board beside the main one, at {b}.kanbn/board-slug.md{b}. Secondary boards
26
+ share the main board's task folder, so a task can appear on several boards, in a different
27
+ column on each. Combine with {b}-n{b}, {b}-d{b} and {b}-c{b} to set the board's name,
28
+ description and columns:
29
+ {b}kanbn init -b design -n "Design Pipeline" -c Ideas -c Designing -c "Signed Off"{b}
30
+ Running it again on an existing board updates its name, description and columns, exactly as
31
+ {b}kanbn init{b} does for the main board. A new board only picks up the default started and
32
+ completed columns if it actually has columns by those names, so a board with its own workflow
33
+ doesn't silently inherit "In Progress" and "Done".
34
+ The workspace has to exist first - run {b}kanbn init{b} with no {b}-b{b} to create it.
@@ -5,7 +5,7 @@ Move an existing task to a different column or position. The task 'updated' date
5
5
 
6
6
  Options:
7
7
  {b}kanbn move "task-id" --interactive{b}
8
- {b}kanbn move "task-id" -n{b}
8
+ {b}kanbn move "task-id" -i{b}
9
9
  Move a task interactively.
10
10
 
11
11
  {b}kanbn move "task-id" --column "column"{b}
@@ -21,3 +21,12 @@ Options:
21
21
  Move the task to a position relative to its current position in the target column.
22
22
  When specifying a negative value for N, the negative sign can be escaped with '/' or '\\' to prevent the value being recognised as an option. For example:
23
23
  {b}kanbn mv "task-1" -p \\-1 --relative{b}
24
+
25
+ {b}kanbn move "task-id" --board "board-slug"{b}
26
+ {b}kanbn move "task-id" -b "board-slug"{b}
27
+ Move the task on a board other than the main one. If the task isn't on that board yet it is
28
+ added, with a notice - so pulling work onto a board is one command rather than two.
29
+
30
+ {b}kanbn move "task-id" -b "board-slug" --no-add{b}
31
+ Refuse to move a task that isn't on the target board, instead of adding it.
32
+ The main board never adds implicitly: moving an untracked task there is an error either way.
@@ -1,12 +1,23 @@
1
1
  {b}kanbn remove "task-id"{b}
2
2
  {b}kanbn rm "task-id"{b}
3
3
 
4
- Remove an existing task.
4
+ Remove an existing task. This deletes the task file and its index entry.
5
5
 
6
6
  Options:
7
7
  {b}kanbn remove "task-id" --index{b}
8
+ {b}kanbn remove "task-id" -x{b}
8
9
  Only remove the task from the index. The task file will not be deleted.
9
10
 
10
11
  {b}kanbn remove "task-id" --force{b}
11
12
  {b}kanbn remove "task-id" -f{b}
12
13
  Force remove the task without asking for confirmation.
14
+
15
+ {b}kanbn remove "task-id" --board "board-slug"{b}
16
+ {b}kanbn remove "task-id" -b "board-slug"{b}
17
+ Remove the task from that board. Combine this with {b}--index{b} to remove it from that board
18
+ only - boards own membership, so the task file and its entries on every other board are
19
+ untouched.
20
+
21
+ {b}kanbn remove "task-id" --all-boards{b}
22
+ Task files are shared between boards, so deleting one while another board still references it is
23
+ refused. This removes the task from every board that references it, then deletes the file.
@@ -11,3 +11,8 @@ Options:
11
11
  {b}kanbn rename "task-id" --name "name"{b}
12
12
  {b}kanbn rename "task-id" -n "name"{b}
13
13
  Rename the task with the specified name. This option is required if not renaming a task interactively.
14
+
15
+ {b}kanbn rename "task-id" --board "board-slug"{b}
16
+ {b}kanbn rename "task-id" -b "board-slug"{b}
17
+ Target a board other than the main one. Falls back to the KANBN_BOARD environment variable and
18
+ then to the defaultBoard option. See {b}kanbn boards{b} for the list of boards.
@@ -10,3 +10,9 @@ Options:
10
10
  {b}kanbn restore "task-id" --column "column"{b}
11
11
  {b}kanbn restore "task-id" -c "column"{b}
12
12
  Restore a task from the archive and place it in the specified column.
13
+
14
+ {b}kanbn restore "task-id" --board "board-slug"{b}
15
+ {b}kanbn restore "task-id" -b "board-slug"{b}
16
+ Restore the task to that board only. Without this, the task goes back to every board it was on
17
+ when it was archived, in the column it occupied on each. A board that has since been deleted is
18
+ reported and skipped rather than failing the restore.
@@ -9,14 +9,16 @@ If the filter regular expression has numbered capturing groups, the value of the
9
9
  If the filter regular expression has named capturing groups, the value of all named groups will be concatenated.
10
10
  If there are multiple matches, their values will be concatenated.
11
11
 
12
+ See docs/filtering-and-sorting.md for a full description of the sorting model.
13
+
12
14
  Options:
13
15
  {b}kanbn sort --interactive{b}
14
16
  {b}kanbn sort -i{b}
15
17
  Sort a column interactively.
16
18
 
17
19
  {b}kanbn sort --save{b}
18
- Save the column sort settings in the index file. This means that any tasks added to the column will be automatically sorted.
19
- If this option is not set, any saved sorting settings for the specified column will be removed.
20
+ Save the column sort settings in the index file (as a columnSorting option). This means that any tasks added to the column will be automatically sorted.
21
+ If this option is not set, the column is sorted once and any saved sorting settings for the specified column will be removed.
20
22
 
21
23
  {b}kanbn sort --ascending{b}
22
24
  {b}kanbn sort -a{b}
@@ -53,9 +55,18 @@ Options:
53
55
  {b}kanbn sort -e{b}
54
56
  Sort tasks by due date.
55
57
 
58
+ {b}kanbn sort --plannedStart{b}
59
+ Sort tasks by planned start date.
60
+
61
+ {b}kanbn sort --plannedFinish{b}
62
+ Sort tasks by planned finish date.
63
+
56
64
  {b}kanbn sort --assigned{b}
57
65
  Sort tasks by assigned user name.
58
66
 
67
+ {b}kanbn sort --progress{b}
68
+ Sort tasks by progress.
69
+
59
70
  {b}kanbn sort --sub-task "filter"{b}
60
71
  {b}kanbn sort -s "filter"{b}
61
72
  Sort tasks by sub-tasks.
@@ -96,3 +107,8 @@ Examples:
96
107
 
97
108
  {b}kanbn sort "Todo" -z -n --count-tags{b}
98
109
  Sort tasks in the "Todo" column first by name, then by the number of tags, all in descending order
110
+
111
+ {b}kanbn sort "column" --board "board-slug"{b}
112
+ {b}kanbn sort "column" -b "board-slug"{b}
113
+ Target a board other than the main one. Falls back to the KANBN_BOARD environment variable and
114
+ then to the defaultBoard option. See {b}kanbn boards{b} for the list of boards.
@@ -15,3 +15,12 @@ Options:
15
15
  {b}kanbn sprint --description "description"{b}
16
16
  {b}kanbn sprint -d "description"{b}
17
17
  Start a new sprint with the specified description.
18
+
19
+ {b}kanbn sprint --board "board-slug"{b}
20
+ {b}kanbn sprint -b "board-slug"{b}
21
+ Add a sprint from the context of another board. Sprints are workspace-level by default, so this
22
+ appends to the workspace list and says so. A board that declares its own {b}sprints{b} in its
23
+ front matter gets the sprint appended there instead, auto-named {b}{Board name} Sprint {n}{b} so
24
+ that two boards' sprints can't be confused.
25
+ A board with its own list can't see the workspace sprints at all - that's the cost of forking,
26
+ and it's why forking is a deliberate front-matter edit rather than a flag.
@@ -15,7 +15,11 @@ Options:
15
15
 
16
16
  {b}kanbn status --untracked{b}
17
17
  {b}kanbn status -u{b}
18
- Show a list of untracked task filenames.
18
+ Show a list of untracked task filenames. "Untracked" is workspace-scoped: a task is tracked if
19
+ any board references it, so this lists task files that are on no board at all.
20
+ When other boards track tasks that the target board doesn't, they're listed separately under
21
+ {b}tasksOnOtherBoards{b}, with the column each one occupies - the "what could I pull onto this
22
+ board" list.
19
23
 
20
24
  {b}kanbn status --due{b}
21
25
  {b}kanbn status -e{b}
@@ -33,3 +37,8 @@ Options:
33
37
  This option can be repeated - if multiple dates are specified, show task workloads for tasks between the earliest and latest dates.
34
38
  The date can be in (almost) any format.
35
39
  This option will be ignored if the --quiet or --sprint options are set.
40
+
41
+ {b}kanbn status --board "board-slug"{b}
42
+ {b}kanbn status -b "board-slug"{b}
43
+ Target a board other than the main one. Falls back to the KANBN_BOARD environment variable and
44
+ then to the defaultBoard option. See {b}kanbn boards{b} for the list of boards.
@@ -7,3 +7,8 @@ Options:
7
7
  {b}kanbn task "task-id" --json{b}
8
8
  {b}kanbn task "task-id" -j{b}
9
9
  Show task information in JSON format.
10
+
11
+ {b}kanbn task "task-id" --board "board-slug"{b}
12
+ {b}kanbn task "task-id" -b "board-slug"{b}
13
+ Target a board other than the main one. Falls back to the KANBN_BOARD environment variable and
14
+ then to the defaultBoard option. See {b}kanbn boards{b} for the list of boards.
@@ -2,10 +2,37 @@
2
2
 
3
3
  Validate kanbn index file and all task files, and report any formatting errors.
4
4
 
5
+ If the files are valid, this also reports tasks whose started/completed dates don't match the column
6
+ they're in - which usually means the task was moved by hand or by a merge, rather than through kanbn.
7
+
5
8
  Options:
6
9
  {b}kanbn validate --save{b}
7
10
  Re-save the index and task files. This will ensure that all index column sorting settings are applied and that all tasks are formatted correctly.
8
11
 
12
+ {b}kanbn validate --fix{b}
13
+ {b}kanbn validate -f{b}
14
+ Fill in missing started and completed dates for tasks that are sitting in a started or completed
15
+ column without one. Each date is taken from the task's history where the move was recorded,
16
+ falling back to the task's updated date and then its created date.
17
+ Tasks that have a completed date while sitting outside a completed column are reported but never
18
+ changed, because the date records something that actually happened. Use
19
+ {b}kanbn edit "task-id" --unset completed{b} to clear one deliberately.
20
+
9
21
  {b}kanbn validate --json{b}
10
22
  {b}kanbn validate -j{b}
11
23
  Output validation errors in JSON format.
24
+
25
+ {b}kanbn validate --board "board-slug"{b}
26
+ {b}kanbn validate -b "board-slug"{b}
27
+ Target a board other than the main one. Falls back to the KANBN_BOARD environment variable and
28
+ then to the defaultBoard option. See {b}kanbn boards{b} for the list of boards.
29
+
30
+ {b}kanbn validate --all-boards{b}
31
+ Validate every board in the workspace and the tasks each of them references, rather than just
32
+ the target board.
33
+
34
+ In a workspace with more than one board, {b}validate{b} also reports multi-board warnings - a
35
+ workspace-scoped option in a board file, several boards stamping the same shared date, sprints out
36
+ of order, a task on no board at all, history naming a board that has been deleted, and markdown
37
+ files beside the boards that don't parse as one. These are warnings, not errors: each describes a
38
+ workspace that still works, just not the way its author probably meant it to.
@@ -0,0 +1,218 @@
1
+ # Filtering and Sorting
2
+
3
+ Kanbn uses one shared filtering model and one shared sorting model. They are used by:
4
+
5
+ | Feature | Filters | Sorters |
6
+ | --- | --- | --- |
7
+ | `kanbn find` | yes (CLI options) | no |
8
+ | `kanbn sort` | no | yes (CLI options) |
9
+ | `columnSorting` project option | no | yes |
10
+ | [Views](views.md) (root, column and lane filters) | yes | yes (per view column) |
11
+
12
+ `kanbn status`, `kanbn burndown`, `kanbn gantt` and `kanbn history` have their own simpler `--column` / `--assigned` / `--date` / `--sprint` options and don't use this model.
13
+
14
+ ## Filters
15
+
16
+ A filter set is a map of field names to filter values. **A task must match every filter in the set** (filters are combined with AND). An empty filter set matches all tasks.
17
+
18
+ On the command line each `kanbn find` option is one filter. In the index options a filter set is a YAML object:
19
+
20
+ ```yaml
21
+ filters:
22
+ column: 'In Progress'
23
+ tag: Bug
24
+ workload:
25
+ - 3
26
+ - 8
27
+ ```
28
+
29
+ ### Filter fields
30
+
31
+ | Field | `kanbn find` option | Type | Matched against |
32
+ | --- | --- | --- | --- |
33
+ | `id` | `--id` | string | The task id (the task filename without `.md`) |
34
+ | `name` | `--name`, `-n` | string | The task name (level-1 heading) |
35
+ | `description` | `--description`, `-d` | string | The task description |
36
+ | `column` | `--column`, `-c` | string | The name of the column the task is currently in |
37
+ | `created` | `--created` | date | `created` metadata |
38
+ | `updated` | `--updated` | date | `updated` metadata |
39
+ | `started` | `--started` | date | `started` metadata |
40
+ | `completed` | `--completed` | date | `completed` metadata |
41
+ | `due` | `--due`, `-e` | date | `due` metadata |
42
+ | `plannedStart` | `--plannedStart` | date | `plannedStart` metadata |
43
+ | `plannedFinish` | `--plannedFinish` | date | `plannedFinish` metadata |
44
+ | `assigned` | `--assigned` | string | `assigned` metadata (empty string if unset) |
45
+ | `workload` | `--workload` | number | The task's [calculated workload](index-structure.md#taskworkloadtags) |
46
+ | `progress` | `--progress` | number | The task's [calculated progress](task-structure.md#progress) |
47
+ | `sub-task` | `--sub-task`, `-s` | string | All sub-tasks, one per line, as `[ ] text` or `[x] text` |
48
+ | `count-sub-tasks` | `--count-sub-tasks` | number | Number of sub-tasks |
49
+ | `tag` | `--tag`, `-t` | string | All tags, one per line |
50
+ | `count-tags` | `--count-tags` | number | Number of tags |
51
+ | `relation` | `--relation`, `-r` | string | All relations, one per line, as `type task-id` |
52
+ | `count-relations` | `--count-relations` | number | Number of relations |
53
+ | `comment` | `--comment` | string | All comments, one per line, as `author text` |
54
+ | `count-comments` | `--count-comments` | number | Number of comments |
55
+ | *custom field name* | `--<custom field name>` | declared type | The custom field value in the task metadata |
56
+
57
+ Custom fields must be declared in the [`customFields`](index-structure.md#customfields) project option before they can be filtered on.
58
+
59
+ A task that doesn't have the metadata field being filtered on never matches a date filter or a custom field filter. Missing `assigned` is treated as an empty string, missing `tags`/sub-tasks/relations/comments are treated as empty.
60
+
61
+ *Note: `hiddenColumns` only affects the board. `kanbn find` still returns tasks in hidden columns unless you filter them out with `column`.*
62
+
63
+ ### String filters
64
+
65
+ String filter values are **case-insensitive regular expressions**, matched anywhere in the value (not anchored). Passing an array (or repeating a CLI option) joins the values with `|`, so an array means "match any of these":
66
+
67
+ ```bash
68
+ kanbn find --column Todo --column "In Progress"
69
+ ```
70
+
71
+ ```yaml
72
+ filters:
73
+ column:
74
+ - Todo
75
+ - 'In Progress'
76
+ ```
77
+
78
+ Multi-value fields (`tag`, `sub-task`, `relation`, `comment`) are flattened into a single newline-separated string before matching. The regex is **not** built with the multiline flag, so `^` and `$` anchor to the start and end of that whole string, not to each line. To match a single value exactly, anchor on the line breaks instead:
79
+
80
+ ```bash
81
+ # Matches "Bug", but also "Debug" and "Bugfix"
82
+ kanbn find --tag Bug
83
+
84
+ # Matches only the exact tag "Bug"
85
+ kanbn find --tag '(^|\n)Bug($|\n)'
86
+ ```
87
+
88
+ ### Date filters
89
+
90
+ A single date matches any task whose date falls on **the same calendar day** — the time part is ignored:
91
+
92
+ ```bash
93
+ kanbn find --due "20 July 2026"
94
+ ```
95
+
96
+ Two or more dates match any task whose date falls **between the earliest and latest** of them (inclusive, times included):
97
+
98
+ ```bash
99
+ kanbn find --due "1 July 2026" --due "31 July 2026"
100
+ ```
101
+
102
+ On the command line dates are parsed with [chrono](https://github.com/wanasit/chrono), so almost any format works, including relative dates like `"yesterday"` or `"next friday"`. In YAML, write dates as plain YAML timestamps:
103
+
104
+ ```yaml
105
+ filters:
106
+ due:
107
+ - 2026-07-01
108
+ - 2026-07-31
109
+ ```
110
+
111
+ ### Number filters
112
+
113
+ A single number matches that number exactly. Two or more numbers match anything between the lowest and highest (inclusive):
114
+
115
+ ```bash
116
+ kanbn find --workload 5 # exactly 5
117
+ kanbn find --workload 3 --workload 8 # between 3 and 8
118
+ ```
119
+
120
+ ### Boolean filters
121
+
122
+ Boolean filters only apply to custom fields with type `boolean`, and are matched by exact equality. On the command line, `--<name>` matches `true` and `--no-<name>` matches `false`:
123
+
124
+ ```bash
125
+ kanbn find --needsDesign # tasks where needsDesign is true
126
+ kanbn find --no-needsDesign # tasks where needsDesign is false
127
+ ```
128
+
129
+ ## Sorters
130
+
131
+ A sorter list is an ordered array. Tasks are compared using the first sorter; ties are broken using the next one, and so on. Each sorter is an object:
132
+
133
+ ```yaml
134
+ sorters:
135
+ - field: workload
136
+ order: descending
137
+ - field: name
138
+ filter: ''
139
+ order: ascending
140
+ ```
141
+
142
+ | Property | Required | Description |
143
+ | --- | --- | --- |
144
+ | `field` | yes | The task field to sort by |
145
+ | `order` | no | `ascending` (default) or `descending` |
146
+ | `filter` | no | A regex used to transform values before comparing them (see below) |
147
+
148
+ Strings are compared with `localeCompare` (accent-sensitive, case-insensitive); dates and numbers are compared numerically.
149
+
150
+ ### Sort filters
151
+
152
+ The `filter` property is **not** a search filter — it extracts part of each value before comparing. The regex is applied globally and case-insensitively, and:
153
+
154
+ - if it has named capturing groups, the contents of all named groups are concatenated;
155
+ - otherwise, if it has numbered capturing groups, the contents of the first group are used;
156
+ - otherwise, the whole match is used;
157
+ - if there are multiple matches, their results are concatenated.
158
+
159
+ ```bash
160
+ # Sort by the number in task names like "Task 12", not by the whole name
161
+ kanbn sort "Todo" --name "Task (\d+)"
162
+ ```
163
+
164
+ ### Sortable fields
165
+
166
+ `kanbn sort` and `columnSorting` can sort by any of these. Note that the `field` value written in YAML is **not** always the same as the command line option:
167
+
168
+ | `field` value | `kanbn sort` option |
169
+ | --- | --- |
170
+ | `id` | `--id` |
171
+ | `name` | `--name`, `-n` |
172
+ | `description` | `--description`, `-d` |
173
+ | `created` | `--created` |
174
+ | `updated` | `--updated` |
175
+ | `started` | `--started` |
176
+ | `completed` | `--completed` |
177
+ | `due` | `--due`, `-e` |
178
+ | `plannedStart` | `--plannedStart` |
179
+ | `plannedFinish` | `--plannedFinish` |
180
+ | `assigned` | `--assigned` |
181
+ | `workload` | `--workload`, `-w` |
182
+ | `progress` | `--progress` |
183
+ | `subTasks` | `--sub-task`, `-s` |
184
+ | `countSubTasks` | `--count-sub-tasks` |
185
+ | `tags` | `--tag`, `-t` |
186
+ | `countTags` | `--count-tags` |
187
+ | `relations` | `--relation`, `-r` |
188
+ | `countRelations` | `--count-relations` |
189
+ | `comments` | `--comment` |
190
+ | `countComments` | `--count-comments` |
191
+ | *custom field name* | `--<custom field name>` |
192
+
193
+ [View](views.md) column `sorters` accept all of the same fields, plus `column` (the index column the task is currently in), which is useful in a view whose columns don't map onto index columns.
194
+
195
+ A view sorter only changes the order within that view. To order a column permanently, use `columnSorting` — that ordering is written to the index itself, and view columns with no `sorters` of their own inherit it.
196
+
197
+ ## Persistent column sorting
198
+
199
+ `columnSorting` keeps a column sorted in the index file itself, so the order survives `kanbn add`, `kanbn move` and `kanbn validate --save`:
200
+
201
+ ```yaml
202
+ columnSorting:
203
+ Backlog:
204
+ - field: workload
205
+ order: descending
206
+ - field: name
207
+ order: ascending
208
+ ```
209
+
210
+ You can also write this from the command line:
211
+
212
+ ```bash
213
+ kanbn sort "Backlog" --workload -z --name -a --save
214
+ ```
215
+
216
+ Running `kanbn sort "Backlog"` **without** `--save` removes any saved sorting settings for that column after applying the sort once.
217
+
218
+ See `kanbn find --help` and `kanbn sort --help` for the full list of command line options, and [Views](views.md) for filters and sorters inside board views.