clawvault 2.5.2 → 2.5.4

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 (71) hide show
  1. package/README.md +159 -200
  2. package/bin/clawvault.js +111 -111
  3. package/bin/command-registration.test.js +166 -166
  4. package/bin/command-runtime.js +93 -93
  5. package/bin/command-runtime.test.js +154 -154
  6. package/bin/help-contract.test.js +39 -39
  7. package/bin/register-config-commands.js +153 -153
  8. package/bin/register-config-route-commands.test.js +121 -121
  9. package/bin/register-core-commands.js +237 -237
  10. package/bin/register-kanban-commands.js +56 -56
  11. package/bin/register-kanban-commands.test.js +83 -83
  12. package/bin/register-maintenance-commands.js +282 -282
  13. package/bin/register-project-commands.js +209 -209
  14. package/bin/register-project-commands.test.js +206 -206
  15. package/bin/register-query-commands.js +317 -317
  16. package/bin/register-query-commands.test.js +65 -65
  17. package/bin/register-resilience-commands.js +182 -182
  18. package/bin/register-resilience-commands.test.js +81 -81
  19. package/bin/register-route-commands.js +114 -114
  20. package/bin/register-session-lifecycle-commands.js +206 -206
  21. package/bin/register-tailscale-commands.js +106 -106
  22. package/bin/register-task-commands.js +348 -348
  23. package/bin/register-task-commands.test.js +69 -69
  24. package/bin/register-template-commands.js +72 -72
  25. package/bin/register-vault-operations-commands.js +300 -300
  26. package/bin/test-helpers/cli-command-fixtures.js +119 -119
  27. package/dashboard/lib/graph-diff.js +104 -104
  28. package/dashboard/lib/graph-diff.test.js +75 -75
  29. package/dashboard/lib/vault-parser.js +556 -556
  30. package/dashboard/lib/vault-parser.test.js +254 -254
  31. package/dashboard/public/app.js +796 -796
  32. package/dashboard/public/index.html +52 -52
  33. package/dashboard/public/styles.css +221 -221
  34. package/dashboard/server.js +374 -374
  35. package/dist/{chunk-3FP5BJ42.js → chunk-4QYGFWRM.js} +1 -1
  36. package/dist/{chunk-M25QVSJM.js → chunk-AXKYDCNN.js} +1 -1
  37. package/dist/{chunk-CLE2HHNT.js → chunk-IVRIKYFE.js} +18 -11
  38. package/dist/{chunk-HRTPQQF2.js → chunk-IZEY5S74.js} +1 -1
  39. package/dist/{chunk-HWUNREDJ.js → chunk-JDLOL2PL.js} +4 -4
  40. package/dist/{chunk-AY4PGUVL.js → chunk-KL4NAOMO.js} +1 -1
  41. package/dist/{chunk-O7XHXF7F.js → chunk-MAKNAHAW.js} +4 -4
  42. package/dist/{chunk-PLZKZW4I.js → chunk-OSMS7QIG.js} +1 -1
  43. package/dist/{chunk-NZ4ZZNSR.js → chunk-THRJVD4L.js} +1 -1
  44. package/dist/{chunk-4GBPTBFJ.js → chunk-TIGW564L.js} +1 -1
  45. package/dist/{chunk-BHO7WSAY.js → chunk-W2HNZC22.js} +3 -3
  46. package/dist/{chunk-GFJ3LIIB.js → chunk-XAVB4GB4.js} +1 -1
  47. package/dist/cli/index.js +10 -10
  48. package/dist/commands/context.js +3 -3
  49. package/dist/commands/doctor.js +4 -4
  50. package/dist/commands/embed.js +2 -2
  51. package/dist/commands/observe.js +2 -2
  52. package/dist/commands/setup.js +2 -2
  53. package/dist/commands/sleep.js +2 -2
  54. package/dist/commands/status.js +3 -3
  55. package/dist/commands/tailscale.js +3 -3
  56. package/dist/commands/wake.js +2 -2
  57. package/dist/index.js +12 -12
  58. package/dist/lib/tailscale.js +2 -2
  59. package/dist/lib/webdav.js +1 -1
  60. package/hooks/clawvault/HOOK.md +83 -74
  61. package/hooks/clawvault/handler.js +816 -816
  62. package/hooks/clawvault/handler.test.js +263 -263
  63. package/package.json +94 -125
  64. package/templates/checkpoint.md +19 -19
  65. package/templates/daily-note.md +19 -19
  66. package/templates/daily.md +19 -19
  67. package/templates/decision.md +17 -17
  68. package/templates/handoff.md +19 -19
  69. package/templates/lesson.md +16 -16
  70. package/templates/person.md +19 -19
  71. package/templates/project.md +23 -23
@@ -1,237 +1,237 @@
1
- /**
2
- * Core vault lifecycle and write command registrations.
3
- */
4
-
5
- import { validatePathWithinBase } from './command-runtime.js';
6
-
7
- export function registerCoreCommands(
8
- program,
9
- { chalk, path, fs, createVault, getVault, runQmd }
10
- ) {
11
- // === INIT ===
12
- program
13
- .command('init [path]')
14
- .description('Initialize a new ClawVault vault')
15
- .option('-n, --name <name>', 'Vault name (default: target directory name)')
16
- .option('--qmd', 'Set up qmd semantic search collection')
17
- .option('--qmd-collection <name>', 'qmd collection name (defaults to vault name)')
18
- .option('--no-bases', 'Skip Obsidian Bases file generation')
19
- .option('--no-tasks', 'Skip tasks/ and backlog/ directories')
20
- .option('--no-graph', 'Skip initial graph build')
21
- .option('--categories <list>', 'Comma-separated list of custom categories to create')
22
- .option('--canvas', 'Generate a vault status canvas dashboard on init')
23
- .option('--theme <style>', 'Graph color theme to apply (neural, minimal, none) (default: none)', 'none')
24
- .option('--minimal', 'Create minimal vault (memory categories only, no tasks/bases/graph)')
25
- .action(async (vaultPath, options) => {
26
- const targetPath = vaultPath || '.';
27
- const resolvedPath = path.resolve(targetPath);
28
- console.log(chalk.cyan(`\n🐘 Initializing ClawVault at ${resolvedPath}...\n`));
29
-
30
- // Check for existing vault
31
- const existingConfig = path.join(resolvedPath, '.clawvault.json');
32
- if (fs.existsSync(existingConfig)) {
33
- console.error(chalk.red(`Error: A ClawVault already exists at ${resolvedPath}`));
34
- console.error(chalk.dim(' Use --force to reinitialize (not yet supported) or choose a different path.'));
35
- process.exit(1);
36
- }
37
-
38
- try {
39
- // Resolve --minimal shorthand
40
- const isMinimal = !!options.minimal;
41
- const skipBases = isMinimal || options.bases === false;
42
- const skipTasks = isMinimal || !!options.noTasks;
43
- const skipGraph = isMinimal || !!options.noGraph;
44
-
45
- // Resolve custom categories
46
- const { DEFAULT_CATEGORIES } = await import('../dist/index.js');
47
- let categories = [...DEFAULT_CATEGORIES];
48
- if (options.categories) {
49
- const customCats = options.categories.split(',').map(c => c.trim()).filter(Boolean);
50
- categories = customCats;
51
- }
52
-
53
- const vault = await createVault(targetPath, {
54
- name: options.name || path.basename(resolvedPath),
55
- qmdCollection: options.qmdCollection,
56
- categories
57
- }, { skipBases, skipTasks, skipGraph });
58
-
59
- const vaultCategories = vault.getCategories();
60
- const memoryCategories = vaultCategories.filter(c => !['templates', 'tasks', 'backlog'].includes(c));
61
- const workCategories = vaultCategories.filter(c => ['tasks', 'backlog'].includes(c));
62
-
63
- console.log(chalk.green('✓ Vault created'));
64
- console.log(chalk.dim(` Memory: ${memoryCategories.join(', ')}`));
65
- if (workCategories.length > 0) {
66
- console.log(chalk.dim(` Work: ${workCategories.join(', ')}`));
67
- }
68
- console.log(chalk.dim(` Ledger: ledger/raw, ledger/observations, ledger/reflections`));
69
- if (skipBases) console.log(chalk.dim(' Bases: skipped'));
70
- if (skipGraph) console.log(chalk.dim(' Graph: skipped'));
71
-
72
- console.log(chalk.cyan('\nSetting up qmd collection...'));
73
- try {
74
- await runQmd([
75
- 'collection',
76
- 'add',
77
- vault.getQmdRoot(),
78
- '--name',
79
- vault.getQmdCollection(),
80
- '--mask',
81
- '**/*.md'
82
- ]);
83
- console.log(chalk.green('✓ qmd collection created'));
84
- } catch {
85
- console.log(chalk.yellow('⚠ qmd collection may already exist'));
86
- }
87
-
88
- // Apply theme if requested
89
- if (options.theme && options.theme !== 'none') {
90
- try {
91
- const { setupCommand } = await import('../dist/commands/setup.js');
92
- await setupCommand({
93
- graphColors: true,
94
- bases: false,
95
- canvas: false,
96
- theme: options.theme,
97
- vault: resolvedPath
98
- });
99
- } catch {
100
- console.log(chalk.yellow(`⚠ Could not apply ${options.theme} theme`));
101
- }
102
- }
103
-
104
- // Generate canvas if requested
105
- if (options.canvas) {
106
- try {
107
- const { setupCommand } = await import('../dist/commands/setup.js');
108
- await setupCommand({
109
- graphColors: false,
110
- bases: false,
111
- canvas: true,
112
- theme: 'none',
113
- vault: resolvedPath
114
- });
115
- } catch {
116
- console.log(chalk.yellow(`⚠ Could not generate canvas`));
117
- }
118
- }
119
-
120
- console.log(chalk.green('\n✅ ClawVault ready!\n'));
121
- console.log(' ' + chalk.bold('Try these:'));
122
- console.log(chalk.dim(' clawvault capture "my first thought" # quick capture'));
123
- console.log(chalk.dim(' clawvault graph # see your knowledge graph'));
124
- console.log(chalk.dim(' clawvault context "topic" # graph-aware context'));
125
- console.log(chalk.dim(' clawvault checkpoint --working-on "task" # save progress'));
126
- console.log();
127
- console.log(chalk.dim(' Full docs: https://docs.clawvault.dev'));
128
- console.log();
129
- } catch (err) {
130
- console.error(chalk.red(`Error: ${err.message}`));
131
- process.exit(1);
132
- }
133
- });
134
-
135
- // === SETUP ===
136
- program
137
- .command('setup')
138
- .description('Auto-discover and configure an existing ClawVault vault')
139
- .option('--graph-colors', 'Set up graph color scheme for Obsidian')
140
- .option('--no-graph-colors', 'Skip graph color configuration')
141
- .option('--bases', 'Generate Obsidian Bases views for task management')
142
- .option('--no-bases', 'Skip Bases file generation')
143
- .option('--canvas', 'Generate vault status canvas dashboard')
144
- .option('--no-canvas', 'Skip canvas generation')
145
- .option('--theme <style>', 'Graph color theme (neural, minimal, none) (default: neural)', 'neural')
146
- .option('--force', 'Overwrite existing configuration files')
147
- .option('-v, --vault <path>', 'Vault path')
148
- .action(async (options) => {
149
- try {
150
- const { setupCommand } = await import('../dist/commands/setup.js');
151
- await setupCommand({
152
- graphColors: options.graphColors,
153
- bases: options.bases,
154
- canvas: options.canvas,
155
- theme: options.theme,
156
- force: options.force,
157
- vault: options.vault
158
- });
159
- } catch (err) {
160
- console.error(chalk.red(`Error: ${err.message}`));
161
- process.exit(1);
162
- }
163
- });
164
-
165
- // === STORE ===
166
- program
167
- .command('store')
168
- .description('Store a new memory document')
169
- .requiredOption('-c, --category <category>', 'Category (preferences, decisions, patterns, people, projects, goals, transcripts, inbox)')
170
- .requiredOption('-t, --title <title>', 'Document title')
171
- .option('--content <content>', 'Content body')
172
- .option('-f, --file <file>', 'Read content from file (validated against current working directory)')
173
- .option('--stdin', 'Read content from stdin')
174
- .option('--overwrite', 'Overwrite if exists')
175
- .option('--no-index', 'Skip qmd index update (auto-updates by default)')
176
- .option('--embed', 'Also update qmd embeddings for vector search')
177
- .option('-v, --vault <path>', 'Vault path (default: find nearest)')
178
- .action(async (options) => {
179
- try {
180
- const vault = await getVault(options.vault);
181
- let content = options.content || '';
182
-
183
- if (options.file) {
184
- // Validate file path is within current working directory to prevent path traversal
185
- const cwd = process.cwd();
186
- const resolvedFilePath = validatePathWithinBase(options.file, cwd);
187
- content = fs.readFileSync(resolvedFilePath, 'utf-8');
188
- } else if (options.stdin) {
189
- content = fs.readFileSync(0, 'utf-8');
190
- }
191
-
192
- const doc = await vault.store({
193
- category: options.category,
194
- title: options.title,
195
- content,
196
- overwrite: options.overwrite
197
- });
198
-
199
- console.log(chalk.green(`✓ Stored: ${doc.id}`));
200
- console.log(chalk.dim(` Path: ${doc.path}`));
201
-
202
- if (options.index !== false) {
203
- const collection = vault.getQmdCollection();
204
- await runQmd(collection ? ['update', '-c', collection] : ['update']);
205
- if (options.embed) {
206
- await runQmd(collection ? ['embed', '-c', collection] : ['embed']);
207
- }
208
- }
209
- } catch (err) {
210
- console.error(chalk.red(`Error: ${err.message}`));
211
- process.exit(1);
212
- }
213
- });
214
-
215
- // === CAPTURE ===
216
- program
217
- .command('capture <note>')
218
- .description('Quick-capture a note to inbox')
219
- .option('-t, --title <title>', 'Note title')
220
- .option('-v, --vault <path>', 'Vault path')
221
- .option('--no-index', 'Skip qmd index update (auto-updates by default)')
222
- .action(async (note, options) => {
223
- try {
224
- const vault = await getVault(options.vault);
225
- const doc = await vault.capture(note, options.title);
226
- console.log(chalk.green(`✓ Captured: ${doc.id}`));
227
-
228
- if (options.index !== false) {
229
- const collection = vault.getQmdCollection();
230
- await runQmd(collection ? ['update', '-c', collection] : ['update']);
231
- }
232
- } catch (err) {
233
- console.error(chalk.red(`Error: ${err.message}`));
234
- process.exit(1);
235
- }
236
- });
237
- }
1
+ /**
2
+ * Core vault lifecycle and write command registrations.
3
+ */
4
+
5
+ import { validatePathWithinBase } from './command-runtime.js';
6
+
7
+ export function registerCoreCommands(
8
+ program,
9
+ { chalk, path, fs, createVault, getVault, runQmd }
10
+ ) {
11
+ // === INIT ===
12
+ program
13
+ .command('init [path]')
14
+ .description('Initialize a new ClawVault vault')
15
+ .option('-n, --name <name>', 'Vault name (default: target directory name)')
16
+ .option('--qmd', 'Set up qmd semantic search collection')
17
+ .option('--qmd-collection <name>', 'qmd collection name (defaults to vault name)')
18
+ .option('--no-bases', 'Skip Obsidian Bases file generation')
19
+ .option('--no-tasks', 'Skip tasks/ and backlog/ directories')
20
+ .option('--no-graph', 'Skip initial graph build')
21
+ .option('--categories <list>', 'Comma-separated list of custom categories to create')
22
+ .option('--canvas', 'Generate a vault status canvas dashboard on init')
23
+ .option('--theme <style>', 'Graph color theme to apply (neural, minimal, none) (default: none)', 'none')
24
+ .option('--minimal', 'Create minimal vault (memory categories only, no tasks/bases/graph)')
25
+ .action(async (vaultPath, options) => {
26
+ const targetPath = vaultPath || '.';
27
+ const resolvedPath = path.resolve(targetPath);
28
+ console.log(chalk.cyan(`\n🐘 Initializing ClawVault at ${resolvedPath}...\n`));
29
+
30
+ // Check for existing vault
31
+ const existingConfig = path.join(resolvedPath, '.clawvault.json');
32
+ if (fs.existsSync(existingConfig)) {
33
+ console.error(chalk.red(`Error: A ClawVault already exists at ${resolvedPath}`));
34
+ console.error(chalk.dim(' Use --force to reinitialize (not yet supported) or choose a different path.'));
35
+ process.exit(1);
36
+ }
37
+
38
+ try {
39
+ // Resolve --minimal shorthand
40
+ const isMinimal = !!options.minimal;
41
+ const skipBases = isMinimal || options.bases === false;
42
+ const skipTasks = isMinimal || !!options.noTasks;
43
+ const skipGraph = isMinimal || !!options.noGraph;
44
+
45
+ // Resolve custom categories
46
+ const { DEFAULT_CATEGORIES } = await import('../dist/index.js');
47
+ let categories = [...DEFAULT_CATEGORIES];
48
+ if (options.categories) {
49
+ const customCats = options.categories.split(',').map(c => c.trim()).filter(Boolean);
50
+ categories = customCats;
51
+ }
52
+
53
+ const vault = await createVault(targetPath, {
54
+ name: options.name || path.basename(resolvedPath),
55
+ qmdCollection: options.qmdCollection,
56
+ categories
57
+ }, { skipBases, skipTasks, skipGraph });
58
+
59
+ const vaultCategories = vault.getCategories();
60
+ const memoryCategories = vaultCategories.filter(c => !['templates', 'tasks', 'backlog'].includes(c));
61
+ const workCategories = vaultCategories.filter(c => ['tasks', 'backlog'].includes(c));
62
+
63
+ console.log(chalk.green('✓ Vault created'));
64
+ console.log(chalk.dim(` Memory: ${memoryCategories.join(', ')}`));
65
+ if (workCategories.length > 0) {
66
+ console.log(chalk.dim(` Work: ${workCategories.join(', ')}`));
67
+ }
68
+ console.log(chalk.dim(` Ledger: ledger/raw, ledger/observations, ledger/reflections`));
69
+ if (skipBases) console.log(chalk.dim(' Bases: skipped'));
70
+ if (skipGraph) console.log(chalk.dim(' Graph: skipped'));
71
+
72
+ console.log(chalk.cyan('\nSetting up qmd collection...'));
73
+ try {
74
+ await runQmd([
75
+ 'collection',
76
+ 'add',
77
+ vault.getQmdRoot(),
78
+ '--name',
79
+ vault.getQmdCollection(),
80
+ '--mask',
81
+ '**/*.md'
82
+ ]);
83
+ console.log(chalk.green('✓ qmd collection created'));
84
+ } catch {
85
+ console.log(chalk.yellow('⚠ qmd collection may already exist'));
86
+ }
87
+
88
+ // Apply theme if requested
89
+ if (options.theme && options.theme !== 'none') {
90
+ try {
91
+ const { setupCommand } = await import('../dist/commands/setup.js');
92
+ await setupCommand({
93
+ graphColors: true,
94
+ bases: false,
95
+ canvas: false,
96
+ theme: options.theme,
97
+ vault: resolvedPath
98
+ });
99
+ } catch {
100
+ console.log(chalk.yellow(`⚠ Could not apply ${options.theme} theme`));
101
+ }
102
+ }
103
+
104
+ // Generate canvas if requested
105
+ if (options.canvas) {
106
+ try {
107
+ const { setupCommand } = await import('../dist/commands/setup.js');
108
+ await setupCommand({
109
+ graphColors: false,
110
+ bases: false,
111
+ canvas: true,
112
+ theme: 'none',
113
+ vault: resolvedPath
114
+ });
115
+ } catch {
116
+ console.log(chalk.yellow(`⚠ Could not generate canvas`));
117
+ }
118
+ }
119
+
120
+ console.log(chalk.green('\n✅ ClawVault ready!\n'));
121
+ console.log(' ' + chalk.bold('Try these:'));
122
+ console.log(chalk.dim(' clawvault capture "my first thought" # quick capture'));
123
+ console.log(chalk.dim(' clawvault graph # see your knowledge graph'));
124
+ console.log(chalk.dim(' clawvault context "topic" # graph-aware context'));
125
+ console.log(chalk.dim(' clawvault checkpoint --working-on "task" # save progress'));
126
+ console.log();
127
+ console.log(chalk.dim(' Full docs: https://docs.clawvault.dev'));
128
+ console.log();
129
+ } catch (err) {
130
+ console.error(chalk.red(`Error: ${err.message}`));
131
+ process.exit(1);
132
+ }
133
+ });
134
+
135
+ // === SETUP ===
136
+ program
137
+ .command('setup')
138
+ .description('Auto-discover and configure an existing ClawVault vault')
139
+ .option('--graph-colors', 'Set up graph color scheme for Obsidian')
140
+ .option('--no-graph-colors', 'Skip graph color configuration')
141
+ .option('--bases', 'Generate Obsidian Bases views for task management')
142
+ .option('--no-bases', 'Skip Bases file generation')
143
+ .option('--canvas', 'Generate vault status canvas dashboard')
144
+ .option('--no-canvas', 'Skip canvas generation')
145
+ .option('--theme <style>', 'Graph color theme (neural, minimal, none) (default: neural)', 'neural')
146
+ .option('--force', 'Overwrite existing configuration files')
147
+ .option('-v, --vault <path>', 'Vault path')
148
+ .action(async (options) => {
149
+ try {
150
+ const { setupCommand } = await import('../dist/commands/setup.js');
151
+ await setupCommand({
152
+ graphColors: options.graphColors,
153
+ bases: options.bases,
154
+ canvas: options.canvas,
155
+ theme: options.theme,
156
+ force: options.force,
157
+ vault: options.vault
158
+ });
159
+ } catch (err) {
160
+ console.error(chalk.red(`Error: ${err.message}`));
161
+ process.exit(1);
162
+ }
163
+ });
164
+
165
+ // === STORE ===
166
+ program
167
+ .command('store')
168
+ .description('Store a new memory document')
169
+ .requiredOption('-c, --category <category>', 'Category (preferences, decisions, patterns, people, projects, goals, transcripts, inbox)')
170
+ .requiredOption('-t, --title <title>', 'Document title')
171
+ .option('--content <content>', 'Content body')
172
+ .option('-f, --file <file>', 'Read content from file (validated against current working directory)')
173
+ .option('--stdin', 'Read content from stdin')
174
+ .option('--overwrite', 'Overwrite if exists')
175
+ .option('--no-index', 'Skip qmd index update (auto-updates by default)')
176
+ .option('--embed', 'Also update qmd embeddings for vector search')
177
+ .option('-v, --vault <path>', 'Vault path (default: find nearest)')
178
+ .action(async (options) => {
179
+ try {
180
+ const vault = await getVault(options.vault);
181
+ let content = options.content || '';
182
+
183
+ if (options.file) {
184
+ // Validate file path is within current working directory to prevent path traversal
185
+ const cwd = process.cwd();
186
+ const resolvedFilePath = validatePathWithinBase(options.file, cwd);
187
+ content = fs.readFileSync(resolvedFilePath, 'utf-8');
188
+ } else if (options.stdin) {
189
+ content = fs.readFileSync(0, 'utf-8');
190
+ }
191
+
192
+ const doc = await vault.store({
193
+ category: options.category,
194
+ title: options.title,
195
+ content,
196
+ overwrite: options.overwrite
197
+ });
198
+
199
+ console.log(chalk.green(`✓ Stored: ${doc.id}`));
200
+ console.log(chalk.dim(` Path: ${doc.path}`));
201
+
202
+ if (options.index !== false) {
203
+ const collection = vault.getQmdCollection();
204
+ await runQmd(collection ? ['update', '-c', collection] : ['update']);
205
+ if (options.embed) {
206
+ await runQmd(collection ? ['embed', '-c', collection] : ['embed']);
207
+ }
208
+ }
209
+ } catch (err) {
210
+ console.error(chalk.red(`Error: ${err.message}`));
211
+ process.exit(1);
212
+ }
213
+ });
214
+
215
+ // === CAPTURE ===
216
+ program
217
+ .command('capture <note>')
218
+ .description('Quick-capture a note to inbox')
219
+ .option('-t, --title <title>', 'Note title')
220
+ .option('-v, --vault <path>', 'Vault path')
221
+ .option('--no-index', 'Skip qmd index update (auto-updates by default)')
222
+ .action(async (note, options) => {
223
+ try {
224
+ const vault = await getVault(options.vault);
225
+ const doc = await vault.capture(note, options.title);
226
+ console.log(chalk.green(`✓ Captured: ${doc.id}`));
227
+
228
+ if (options.index !== false) {
229
+ const collection = vault.getQmdCollection();
230
+ await runQmd(collection ? ['update', '-c', collection] : ['update']);
231
+ }
232
+ } catch (err) {
233
+ console.error(chalk.red(`Error: ${err.message}`));
234
+ process.exit(1);
235
+ }
236
+ });
237
+ }
@@ -1,56 +1,56 @@
1
- /**
2
- * Kanban command registrations for ClawVault.
3
- */
4
-
5
- export function registerKanbanCommands(
6
- program,
7
- { chalk, resolveVaultPath }
8
- ) {
9
- const kanbanCmd = program
10
- .command('kanban')
11
- .description('Manage Obsidian Kanban sync for task frontmatter');
12
-
13
- kanbanCmd
14
- .command('sync')
15
- .description('Generate and sync an Obsidian Kanban board from tasks')
16
- .option('-v, --vault <path>', 'Vault path (default: find nearest)')
17
- .option('--output <path>', 'Board markdown path (default: Board.md)')
18
- .option('--group-by <field>', 'Grouping field (status, priority, project, owner) (default: status)')
19
- .option('--filter-project <project>', 'Only include tasks from a project')
20
- .option('--filter-owner <owner>', 'Only include tasks for an owner')
21
- .option('--include-done', 'Include done tasks (default: hidden)')
22
- .action(async (options) => {
23
- try {
24
- const vaultPath = resolveVaultPath(options.vault);
25
- const { kanbanCommand } = await import('../dist/commands/kanban.js');
26
- await kanbanCommand(vaultPath, 'sync', {
27
- output: options.output,
28
- groupBy: options.groupBy,
29
- filterProject: options.filterProject,
30
- filterOwner: options.filterOwner,
31
- includeDone: options.includeDone
32
- });
33
- } catch (err) {
34
- console.error(chalk.red(`Error: ${err.message}`));
35
- process.exit(1);
36
- }
37
- });
38
-
39
- kanbanCmd
40
- .command('import')
41
- .description('Import lane state from an Obsidian Kanban board into tasks')
42
- .option('-v, --vault <path>', 'Vault path (default: find nearest)')
43
- .option('--output <path>', 'Board markdown path (default: Board.md)')
44
- .action(async (options) => {
45
- try {
46
- const vaultPath = resolveVaultPath(options.vault);
47
- const { kanbanCommand } = await import('../dist/commands/kanban.js');
48
- await kanbanCommand(vaultPath, 'import', {
49
- output: options.output
50
- });
51
- } catch (err) {
52
- console.error(chalk.red(`Error: ${err.message}`));
53
- process.exit(1);
54
- }
55
- });
56
- }
1
+ /**
2
+ * Kanban command registrations for ClawVault.
3
+ */
4
+
5
+ export function registerKanbanCommands(
6
+ program,
7
+ { chalk, resolveVaultPath }
8
+ ) {
9
+ const kanbanCmd = program
10
+ .command('kanban')
11
+ .description('Manage Obsidian Kanban sync for task frontmatter');
12
+
13
+ kanbanCmd
14
+ .command('sync')
15
+ .description('Generate and sync an Obsidian Kanban board from tasks')
16
+ .option('-v, --vault <path>', 'Vault path (default: find nearest)')
17
+ .option('--output <path>', 'Board markdown path (default: Board.md)')
18
+ .option('--group-by <field>', 'Grouping field (status, priority, project, owner) (default: status)')
19
+ .option('--filter-project <project>', 'Only include tasks from a project')
20
+ .option('--filter-owner <owner>', 'Only include tasks for an owner')
21
+ .option('--include-done', 'Include done tasks (default: hidden)')
22
+ .action(async (options) => {
23
+ try {
24
+ const vaultPath = resolveVaultPath(options.vault);
25
+ const { kanbanCommand } = await import('../dist/commands/kanban.js');
26
+ await kanbanCommand(vaultPath, 'sync', {
27
+ output: options.output,
28
+ groupBy: options.groupBy,
29
+ filterProject: options.filterProject,
30
+ filterOwner: options.filterOwner,
31
+ includeDone: options.includeDone
32
+ });
33
+ } catch (err) {
34
+ console.error(chalk.red(`Error: ${err.message}`));
35
+ process.exit(1);
36
+ }
37
+ });
38
+
39
+ kanbanCmd
40
+ .command('import')
41
+ .description('Import lane state from an Obsidian Kanban board into tasks')
42
+ .option('-v, --vault <path>', 'Vault path (default: find nearest)')
43
+ .option('--output <path>', 'Board markdown path (default: Board.md)')
44
+ .action(async (options) => {
45
+ try {
46
+ const vaultPath = resolveVaultPath(options.vault);
47
+ const { kanbanCommand } = await import('../dist/commands/kanban.js');
48
+ await kanbanCommand(vaultPath, 'import', {
49
+ output: options.output
50
+ });
51
+ } catch (err) {
52
+ console.error(chalk.red(`Error: ${err.message}`));
53
+ process.exit(1);
54
+ }
55
+ });
56
+ }