clawvault 2.3.0 → 2.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.
Files changed (55) hide show
  1. package/bin/clawvault.js +6 -0
  2. package/bin/register-core-commands.js +25 -2
  3. package/bin/register-tailscale-commands.js +106 -0
  4. package/bin/register-task-commands.js +18 -2
  5. package/bin/register-task-commands.test.js +24 -0
  6. package/dist/{chunk-SOTWYGH7.js → chunk-33GW63WK.js} +4 -35
  7. package/dist/chunk-4GBPTBFJ.js +628 -0
  8. package/dist/{chunk-GQVYQCY5.js → chunk-AHGUJG76.js} +3 -3
  9. package/dist/{chunk-GJEGPO7U.js → chunk-BI6SGGZP.js} +1 -1
  10. package/dist/chunk-CLE2HHNT.js +513 -0
  11. package/dist/{chunk-NGVAEFT2.js → chunk-DEFBIVQ3.js} +21 -0
  12. package/dist/{chunk-DPS7NYIU.js → chunk-DHJPXGC7.js} +2 -2
  13. package/dist/{chunk-2HM7ZI4X.js → chunk-FEFPBHH4.js} +287 -12
  14. package/dist/{chunk-K6XHCUFL.js → chunk-FHFUXL6G.js} +8 -1
  15. package/dist/{chunk-6BBTI7NV.js → chunk-GBIDDDSL.js} +2 -2
  16. package/dist/{chunk-VR5NE7PZ.js → chunk-HVTTYDCJ.js} +1 -1
  17. package/dist/chunk-IFTEGE4D.js +361 -0
  18. package/dist/{chunk-5WR6RRPX.js → chunk-JXY6T5R7.js} +2 -2
  19. package/dist/chunk-L3DJ36BZ.js +40 -0
  20. package/dist/{chunk-Z2XBWN7A.js → chunk-NAMFB7ZA.js} +2 -0
  21. package/dist/chunk-NZ4ZZNSR.js +373 -0
  22. package/dist/{chunk-OTQW3OMC.js → chunk-Q3WBH4P4.js} +97 -0
  23. package/dist/{chunk-MQUJNOHK.js → chunk-QALB2V3E.js} +1 -1
  24. package/dist/{chunk-PTSEIWXZ.js → chunk-SNEMCQP7.js} +13 -6
  25. package/dist/commands/archive.js +3 -3
  26. package/dist/commands/backlog.js +9 -2
  27. package/dist/commands/blocked.js +9 -2
  28. package/dist/commands/canvas.d.ts +11 -3
  29. package/dist/commands/canvas.js +1333 -25
  30. package/dist/commands/context.js +5 -4
  31. package/dist/commands/doctor.js +1 -1
  32. package/dist/commands/migrate-observations.js +3 -3
  33. package/dist/commands/observe.d.ts +1 -0
  34. package/dist/commands/observe.js +5 -4
  35. package/dist/commands/rebuild.js +5 -4
  36. package/dist/commands/reflect.js +5 -5
  37. package/dist/commands/replay.js +7 -6
  38. package/dist/commands/setup.d.ts +10 -2
  39. package/dist/commands/setup.js +1 -1
  40. package/dist/commands/sleep.js +7 -6
  41. package/dist/commands/status.js +1 -1
  42. package/dist/commands/tailscale.d.ts +52 -0
  43. package/dist/commands/tailscale.js +25 -0
  44. package/dist/commands/task.js +1 -1
  45. package/dist/commands/wake.js +4 -4
  46. package/dist/index.d.ts +9 -0
  47. package/dist/index.js +79 -15
  48. package/dist/lib/tailscale.d.ts +225 -0
  49. package/dist/lib/tailscale.js +49 -0
  50. package/dist/lib/task-utils.d.ts +13 -1
  51. package/dist/lib/task-utils.js +3 -1
  52. package/dist/lib/webdav.d.ts +109 -0
  53. package/dist/lib/webdav.js +34 -0
  54. package/package.json +2 -2
  55. package/dist/chunk-W463YRED.js +0 -97
package/bin/clawvault.js CHANGED
@@ -16,7 +16,10 @@ import { registerResilienceCommands } from './register-resilience-commands.js';
16
16
  import { registerSessionLifecycleCommands } from './register-session-lifecycle-commands.js';
17
17
  import { registerTemplateCommands } from './register-template-commands.js';
18
18
  import { registerVaultOperationsCommands } from './register-vault-operations-commands.js';
19
+
19
20
  import { registerTaskCommands } from './register-task-commands.js';
21
+
22
+ import { registerTailscaleCommands } from './register-tailscale-commands.js';
20
23
  import {
21
24
  getVault,
22
25
  resolveVaultPath,
@@ -83,10 +86,13 @@ registerVaultOperationsCommands(program, {
83
86
  path
84
87
  });
85
88
 
89
+
86
90
  registerTaskCommands(program, {
87
91
  chalk,
88
92
  resolveVaultPath
89
93
  });
90
94
 
95
+ registerTailscaleCommands(program, { chalk });
96
+
91
97
  // Parse and run
92
98
  program.parse();
@@ -13,6 +13,13 @@ export function registerCoreCommands(
13
13
  .option('-n, --name <name>', 'Vault name')
14
14
  .option('--qmd', 'Set up qmd semantic search collection')
15
15
  .option('--qmd-collection <name>', 'qmd collection name (defaults to vault name)')
16
+ .option('--no-bases', 'Skip Obsidian Bases file generation')
17
+ .option('--no-tasks', 'Skip tasks/ and backlog/ directories')
18
+ .option('--no-graph', 'Skip initial graph build')
19
+ .option('--categories <list>', 'Comma-separated list of custom categories to create')
20
+ .option('--canvas <template>', 'Generate a canvas dashboard on init (default, brain, project-board, sprint)')
21
+ .option('--theme <style>', 'Graph color theme to apply (neural, minimal, none)', 'none')
22
+ .option('--minimal', 'Create minimal vault (memory categories only, no tasks/bases/graph)')
16
23
  .action(async (vaultPath, options) => {
17
24
  const targetPath = vaultPath || '.';
18
25
  console.log(chalk.cyan(`\n🐘 Initializing ClawVault at ${path.resolve(targetPath)}...\n`));
@@ -67,10 +74,26 @@ export function registerCoreCommands(
67
74
  program
68
75
  .command('setup')
69
76
  .description('Auto-discover and configure a ClawVault')
70
- .action(async () => {
77
+ .option('--graph-colors', 'Set up graph color scheme for Obsidian')
78
+ .option('--no-graph-colors', 'Skip graph color configuration')
79
+ .option('--bases', 'Generate Obsidian Bases views for task management')
80
+ .option('--no-bases', 'Skip Bases file generation')
81
+ .option('--canvas [template]', 'Generate canvas dashboard (default, brain, project-board, sprint)')
82
+ .option('--no-canvas', 'Skip canvas generation')
83
+ .option('--theme <style>', 'Graph color theme (neural, minimal, none)', 'neural')
84
+ .option('--force', 'Overwrite existing configuration files')
85
+ .option('-v, --vault <path>', 'Vault path')
86
+ .action(async (options) => {
71
87
  try {
72
88
  const { setupCommand } = await import('../dist/commands/setup.js');
73
- await setupCommand();
89
+ await setupCommand({
90
+ graphColors: options.graphColors,
91
+ bases: options.bases,
92
+ canvas: options.canvas,
93
+ theme: options.theme,
94
+ force: options.force,
95
+ vault: options.vault
96
+ });
74
97
  } catch (err) {
75
98
  console.error(chalk.red(`Error: ${err.message}`));
76
99
  process.exit(1);
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Tailscale networking command registrations.
3
+ * Provides vault synchronization over Tailscale networks.
4
+ */
5
+
6
+ export function registerTailscaleCommands(program, { chalk }) {
7
+ // === TAILSCALE-STATUS ===
8
+ program
9
+ .command('tailscale-status')
10
+ .alias('ts-status')
11
+ .description('Show Tailscale connection status and peers')
12
+ .option('--json', 'Output as JSON')
13
+ .option('--peers', 'Show all peers including offline')
14
+ .action(async (options) => {
15
+ try {
16
+ const { tailscaleStatusCommand } = await import('../dist/commands/tailscale.js');
17
+ await tailscaleStatusCommand({
18
+ json: options.json,
19
+ peers: options.peers
20
+ });
21
+ } catch (err) {
22
+ console.error(chalk.red(`Error: ${err.message}`));
23
+ process.exit(1);
24
+ }
25
+ });
26
+
27
+ // === TAILSCALE-SYNC ===
28
+ program
29
+ .command('tailscale-sync')
30
+ .alias('ts-sync')
31
+ .description('Sync vault with a peer on the Tailscale network')
32
+ .requiredOption('--peer <hostname>', 'Peer hostname or IP to sync with')
33
+ .option('-v, --vault <path>', 'Vault path')
34
+ .option('--port <number>', 'Port on the peer (default: 8384)', parseInt)
35
+ .option('--direction <dir>', 'Sync direction: push, pull, or bidirectional', 'bidirectional')
36
+ .option('--dry-run', 'Show what would be synced without making changes')
37
+ .option('--delete-orphans', 'Delete files that exist locally but not on peer (pull only)')
38
+ .option('--categories <list>', 'Comma-separated list of categories to sync')
39
+ .option('--https', 'Use HTTPS for connection')
40
+ .option('--json', 'Output as JSON')
41
+ .action(async (options) => {
42
+ try {
43
+ const { tailscaleSyncCommand } = await import('../dist/commands/tailscale.js');
44
+ await tailscaleSyncCommand({
45
+ peer: options.peer,
46
+ vaultPath: options.vault,
47
+ port: options.port,
48
+ direction: options.direction,
49
+ dryRun: options.dryRun,
50
+ deleteOrphans: options.deleteOrphans,
51
+ categories: options.categories?.split(',').map(c => c.trim()),
52
+ https: options.https,
53
+ json: options.json
54
+ });
55
+ } catch (err) {
56
+ console.error(chalk.red(`Error: ${err.message}`));
57
+ process.exit(1);
58
+ }
59
+ });
60
+
61
+ // === TAILSCALE-SERVE ===
62
+ program
63
+ .command('tailscale-serve')
64
+ .alias('ts-serve')
65
+ .description('Serve vault for sync over Tailscale')
66
+ .option('-v, --vault <path>', 'Vault path')
67
+ .option('--port <number>', 'Port to serve on (default: 8384)', parseInt)
68
+ .option('--funnel', 'Expose via Tailscale Funnel (public internet)')
69
+ .option('--background', 'Run in background')
70
+ .option('--stop', 'Stop serving')
71
+ .action(async (options) => {
72
+ try {
73
+ const { tailscaleServeCommand } = await import('../dist/commands/tailscale.js');
74
+ await tailscaleServeCommand({
75
+ vaultPath: options.vault,
76
+ port: options.port,
77
+ funnel: options.funnel,
78
+ background: options.background,
79
+ stop: options.stop
80
+ });
81
+ } catch (err) {
82
+ console.error(chalk.red(`Error: ${err.message}`));
83
+ process.exit(1);
84
+ }
85
+ });
86
+
87
+ // === TAILSCALE-DISCOVER ===
88
+ program
89
+ .command('tailscale-discover')
90
+ .alias('ts-discover')
91
+ .description('Discover ClawVault peers on the Tailscale network')
92
+ .option('--port <number>', 'Port to check (default: 8384)', parseInt)
93
+ .option('--json', 'Output as JSON')
94
+ .action(async (options) => {
95
+ try {
96
+ const { tailscaleDiscoverCommand } = await import('../dist/commands/tailscale.js');
97
+ await tailscaleDiscoverCommand({
98
+ port: options.port,
99
+ json: options.json
100
+ });
101
+ } catch (err) {
102
+ console.error(chalk.red(`Error: ${err.message}`));
103
+ process.exit(1);
104
+ }
105
+ });
106
+ }
@@ -242,12 +242,28 @@ export function registerTaskCommands(
242
242
  .description('Generate Obsidian canvas dashboard')
243
243
  .option('-v, --vault <path>', 'Vault path')
244
244
  .option('--output <path>', 'Output file path (default: dashboard.canvas)')
245
+ .option('--template <id>', 'Canvas template ID (default, project-board, brain, sprint)')
246
+ .option('--project <project>', 'Project filter for template-aware canvases')
247
+ .option('--owner <owner>', 'Filter tasks by owner (agent name or human)')
248
+ .option('--width <pixels>', 'Canvas width in pixels', parseInt)
249
+ .option('--height <pixels>', 'Canvas height in pixels', parseInt)
250
+ .option('--include-done', 'Include completed tasks (default: limited)')
251
+ .option('--list-templates', 'List available canvas templates and exit')
245
252
  .action(async (options) => {
246
253
  try {
247
- const vaultPath = resolveVaultPath(options.vault);
254
+ const vaultPath = options.listTemplates
255
+ ? (options.vault || '.')
256
+ : resolveVaultPath(options.vault);
248
257
  const { canvasCommand } = await import('../dist/commands/canvas.js');
249
258
  await canvasCommand(vaultPath, {
250
- output: options.output
259
+ output: options.output,
260
+ template: options.template,
261
+ project: options.project,
262
+ owner: options.owner,
263
+ width: options.width,
264
+ height: options.height,
265
+ includeDone: options.includeDone,
266
+ listTemplates: options.listTemplates
251
267
  });
252
268
  } catch (err) {
253
269
  console.error(chalk.red(`Error: ${err.message}`));
@@ -0,0 +1,24 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { Command } from 'commander';
3
+ import { registerTaskCommands } from './register-task-commands.js';
4
+ import { chalkStub, stubResolveVaultPath } from './test-helpers/cli-command-fixtures.js';
5
+
6
+ describe('register-task-commands', () => {
7
+ it('adds canvas template and listing flags', () => {
8
+ const program = new Command();
9
+ registerTaskCommands(program, {
10
+ chalk: chalkStub,
11
+ resolveVaultPath: stubResolveVaultPath
12
+ });
13
+
14
+ const canvasCommand = program.commands.find((command) => command.name() === 'canvas');
15
+ expect(canvasCommand).toBeDefined();
16
+
17
+ const optionFlags = canvasCommand?.options.map((option) => option.flags) ?? [];
18
+ expect(optionFlags).toEqual(expect.arrayContaining([
19
+ '--template <id>',
20
+ '--list-templates',
21
+ '--project <project>'
22
+ ]));
23
+ });
24
+ });
@@ -1,48 +1,17 @@
1
1
  import {
2
2
  ClawVault
3
- } from "./chunk-OTQW3OMC.js";
3
+ } from "./chunk-Q3WBH4P4.js";
4
4
  import {
5
- parseObservationMarkdown
6
- } from "./chunk-K6XHCUFL.js";
5
+ parseObservationLines,
6
+ readObservations
7
+ } from "./chunk-L3DJ36BZ.js";
7
8
  import {
8
9
  getMemoryGraph
9
10
  } from "./chunk-ZZA73MFY.js";
10
- import {
11
- listObservationFiles
12
- } from "./chunk-Z2XBWN7A.js";
13
11
 
14
12
  // src/commands/context.ts
15
13
  import * as path from "path";
16
14
 
17
- // src/lib/observation-reader.ts
18
- import * as fs from "fs";
19
- function readObservations(vaultPath, days = 7) {
20
- const normalizedDays = Number.isFinite(days) ? Math.max(0, Math.floor(days)) : 0;
21
- if (normalizedDays === 0) {
22
- return "";
23
- }
24
- const files = listObservationFiles(vaultPath, {
25
- includeLegacy: true,
26
- includeArchive: false,
27
- dedupeByDate: true
28
- }).sort((left, right) => right.date.localeCompare(left.date)).slice(0, normalizedDays);
29
- if (files.length === 0) {
30
- return "";
31
- }
32
- return files.map((entry) => fs.readFileSync(entry.path, "utf-8").trim()).filter(Boolean).join("\n\n").trim();
33
- }
34
- function parseObservationLines(markdown) {
35
- return parseObservationMarkdown(markdown).map((record) => ({
36
- type: record.type,
37
- confidence: record.confidence,
38
- importance: record.importance,
39
- content: record.content,
40
- date: record.date,
41
- format: record.format,
42
- priority: record.priority
43
- }));
44
- }
45
-
46
15
  // src/lib/token-counter.ts
47
16
  function estimateTokens(text) {
48
17
  if (!text) {