clawvault 2.5.4 → 2.6.1

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 (89) hide show
  1. package/README.md +159 -159
  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 +75 -72
  25. package/bin/register-template-commands.test.js +87 -0
  26. package/bin/register-vault-operations-commands.js +300 -300
  27. package/bin/test-helpers/cli-command-fixtures.js +119 -119
  28. package/dashboard/lib/graph-diff.js +104 -104
  29. package/dashboard/lib/graph-diff.test.js +75 -75
  30. package/dashboard/lib/vault-parser.js +556 -556
  31. package/dashboard/lib/vault-parser.test.js +254 -254
  32. package/dashboard/public/app.js +796 -796
  33. package/dashboard/public/index.html +52 -52
  34. package/dashboard/public/styles.css +221 -221
  35. package/dashboard/server.js +374 -374
  36. package/dist/{chunk-2YDBJS7M.js → chunk-3BTHWPMB.js} +1 -1
  37. package/dist/{chunk-J5EMBUPK.js → chunk-4OXMU5S2.js} +1 -1
  38. package/dist/{chunk-GSD4ALSI.js → chunk-4VRIMU4O.js} +1 -1
  39. package/dist/{chunk-5GZFTAL7.js → chunk-AZYOKJYC.js} +128 -42
  40. package/dist/{chunk-K3CDT7IH.js → chunk-HIHOUSXS.js} +2 -2
  41. package/dist/{chunk-IZEY5S74.js → chunk-IEVLHNLU.js} +1 -1
  42. package/dist/{chunk-OSMS7QIG.js → chunk-ME37YNW3.js} +2 -2
  43. package/dist/chunk-MFAWT5O5.js +301 -0
  44. package/dist/{chunk-TPDH3JPP.js → chunk-PBEE567J.js} +1 -1
  45. package/dist/{chunk-S2IG7VNM.js → chunk-Q2J5YTUF.js} +2 -2
  46. package/dist/{chunk-IOALNTAN.js → chunk-QWQ3TIKS.js} +103 -29
  47. package/dist/{chunk-YCVDVI5B.js → chunk-R2MIW5G7.js} +1 -1
  48. package/dist/{chunk-4IV3R2F5.js → chunk-R6SXNSFD.js} +2 -2
  49. package/dist/{chunk-YOSEUUNB.js → chunk-T76H47ZS.js} +1 -1
  50. package/dist/{chunk-JDLOL2PL.js → chunk-TLGBDTYT.js} +3 -3
  51. package/dist/{chunk-W2HNZC22.js → chunk-UEOUADMO.js} +1 -1
  52. package/dist/cli/index.js +12 -10
  53. package/dist/commands/backlog.js +3 -1
  54. package/dist/commands/blocked.js +3 -1
  55. package/dist/commands/canvas.js +3 -1
  56. package/dist/commands/doctor.js +7 -5
  57. package/dist/commands/inject.js +2 -2
  58. package/dist/commands/kanban.js +4 -2
  59. package/dist/commands/observe.js +7 -5
  60. package/dist/commands/project.js +5 -3
  61. package/dist/commands/rebuild.js +6 -4
  62. package/dist/commands/reflect.js +3 -3
  63. package/dist/commands/replay.js +8 -6
  64. package/dist/commands/setup.js +1 -1
  65. package/dist/commands/sleep.js +7 -5
  66. package/dist/commands/status.js +6 -4
  67. package/dist/commands/task.js +4 -2
  68. package/dist/commands/template.d.ts +10 -1
  69. package/dist/commands/template.js +47 -55
  70. package/dist/commands/wake.js +2 -2
  71. package/dist/index.js +20 -19
  72. package/dist/lib/project-utils.js +4 -2
  73. package/dist/lib/task-utils.d.ts +14 -13
  74. package/dist/lib/task-utils.js +3 -1
  75. package/dist/lib/template-engine.d.ts +1 -0
  76. package/hooks/clawvault/HOOK.md +83 -83
  77. package/hooks/clawvault/handler.js +816 -816
  78. package/hooks/clawvault/handler.test.js +263 -263
  79. package/package.json +94 -94
  80. package/templates/checkpoint.md +34 -19
  81. package/templates/daily-note.md +34 -19
  82. package/templates/daily.md +34 -19
  83. package/templates/decision.md +39 -17
  84. package/templates/handoff.md +34 -19
  85. package/templates/lesson.md +31 -16
  86. package/templates/person.md +37 -19
  87. package/templates/project.md +84 -23
  88. package/templates/task.md +81 -0
  89. /package/dist/{chunk-AXKYDCNN.js → chunk-RVYA52PY.js} +0 -0
@@ -1,3 +1,11 @@
1
+ import {
2
+ TEMPLATE_EXTENSION,
3
+ buildTemplateIndex,
4
+ listTemplateDefinitions,
5
+ normalizeTemplateName,
6
+ parseTemplateDefinition,
7
+ renderDocumentFromTemplate
8
+ } from "../chunk-MFAWT5O5.js";
1
9
  import {
2
10
  buildTemplateVariables,
3
11
  renderTemplate
@@ -6,26 +14,8 @@ import {
6
14
  // src/commands/template.ts
7
15
  import * as fs from "fs";
8
16
  import * as path from "path";
9
- import { fileURLToPath } from "url";
10
17
  var VAULT_CONFIG_FILE = ".clawvault.json";
11
- var TEMPLATE_EXTENSION = ".md";
12
- function resolveBuiltinTemplatesDir(override) {
13
- if (override) {
14
- const resolved = path.resolve(override);
15
- return fs.existsSync(resolved) ? resolved : null;
16
- }
17
- const moduleDir = path.dirname(fileURLToPath(import.meta.url));
18
- const candidates = [
19
- path.resolve(moduleDir, "../templates"),
20
- path.resolve(moduleDir, "../../templates")
21
- ];
22
- for (const candidate of candidates) {
23
- if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
24
- return candidate;
25
- }
26
- }
27
- return null;
28
- }
18
+ var TEMPLATE_LIST_IGNORED_BUILTINS = /* @__PURE__ */ new Set(["daily"]);
29
19
  function findVaultRoot(start) {
30
20
  let current = path.resolve(start);
31
21
  while (true) {
@@ -48,53 +38,41 @@ function resolveVaultPath(options) {
48
38
  const cwd = options.cwd ?? process.cwd();
49
39
  return findVaultRoot(cwd);
50
40
  }
51
- function normalizeTemplateName(name) {
52
- const base = path.basename(name, path.extname(name));
53
- return base.trim();
54
- }
55
41
  function slugify(text) {
56
42
  return text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim();
57
43
  }
58
- function listTemplateFiles(dir, ignore) {
59
- const entries = /* @__PURE__ */ new Map();
60
- if (!fs.existsSync(dir)) return entries;
61
- for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
62
- if (!entry.isFile() || !entry.name.endsWith(TEMPLATE_EXTENSION)) continue;
63
- const name = normalizeTemplateName(entry.name);
64
- if (!name) continue;
65
- if (ignore?.has(name)) continue;
66
- entries.set(name, path.join(dir, entry.name));
67
- }
68
- return entries;
44
+ function buildTemplateIndexForContext(options) {
45
+ const vaultPath = resolveVaultPath(options) ?? void 0;
46
+ return buildTemplateIndex({
47
+ vaultPath,
48
+ builtinDir: options.builtinDir,
49
+ ignoreBuiltinNames: TEMPLATE_LIST_IGNORED_BUILTINS
50
+ });
69
51
  }
70
- function buildTemplateIndex(options) {
71
- const index = /* @__PURE__ */ new Map();
72
- const builtinDir = resolveBuiltinTemplatesDir(options.builtinDir);
73
- if (builtinDir) {
74
- const ignore = /* @__PURE__ */ new Set(["daily"]);
75
- for (const [name, filePath] of listTemplateFiles(builtinDir, ignore)) {
76
- index.set(name, filePath);
77
- }
78
- }
79
- const vaultPath = resolveVaultPath(options);
80
- if (vaultPath) {
81
- const vaultTemplatesDir = path.join(vaultPath, "templates");
82
- for (const [name, filePath] of listTemplateFiles(vaultTemplatesDir)) {
83
- index.set(name, filePath);
84
- }
85
- }
86
- return index;
52
+ function listTemplateDefinitions2(options = {}) {
53
+ const vaultPath = resolveVaultPath(options) ?? void 0;
54
+ return listTemplateDefinitions({
55
+ vaultPath,
56
+ builtinDir: options.builtinDir,
57
+ ignoreBuiltinNames: TEMPLATE_LIST_IGNORED_BUILTINS
58
+ }).map((definition) => ({
59
+ name: definition.name,
60
+ primitive: definition.primitive,
61
+ description: definition.description,
62
+ fields: Object.keys(definition.fields),
63
+ path: definition.path,
64
+ format: definition.format
65
+ }));
87
66
  }
88
67
  function listTemplates(options = {}) {
89
- const index = buildTemplateIndex(options);
90
- return [...index.keys()].sort();
68
+ return listTemplateDefinitions2(options).map((definition) => definition.name);
91
69
  }
92
70
  function createFromTemplate(name, options = {}) {
93
71
  const templateName = normalizeTemplateName(name);
94
72
  if (!templateName) {
95
73
  throw new Error("Template name is required.");
96
74
  }
97
- const index = buildTemplateIndex(options);
75
+ const index = buildTemplateIndexForContext(options);
98
76
  const templatePath = index.get(templateName);
99
77
  if (!templatePath) {
100
78
  const available = [...index.keys()].sort();
@@ -107,7 +85,20 @@ function createFromTemplate(name, options = {}) {
107
85
  const type = options.type ?? templateName;
108
86
  const title = options.title ?? `${type} ${date}`.trim();
109
87
  const variables = buildTemplateVariables({ title, type, date }, now);
110
- const rendered = renderTemplate(raw, variables);
88
+ const parsedTemplate = parseTemplateDefinition(raw, templateName, templatePath);
89
+ const rendered = parsedTemplate.format === "schema" ? renderDocumentFromTemplate(parsedTemplate, {
90
+ title,
91
+ type,
92
+ now,
93
+ variables: {
94
+ ...variables,
95
+ content: "",
96
+ links_line: "",
97
+ owner_link: "",
98
+ project_link: "",
99
+ team_links_line: ""
100
+ }
101
+ }).markdown : renderTemplate(raw, variables);
111
102
  const cwd = options.cwd ?? process.cwd();
112
103
  const slug = slugify(title) || slugify(templateName) || `template-${date}`;
113
104
  const outputPath = path.join(cwd, `${slug}${TEMPLATE_EXTENSION}`);
@@ -143,5 +134,6 @@ function addTemplate(file, options) {
143
134
  export {
144
135
  addTemplate,
145
136
  createFromTemplate,
137
+ listTemplateDefinitions2 as listTemplateDefinitions,
146
138
  listTemplates
147
139
  };
@@ -175,10 +175,10 @@ async function generateExecutiveSummary(recovery, recap, highlights) {
175
175
  if (process.env.GEMINI_API_KEY) {
176
176
  const model = "gemini-2.0-flash";
177
177
  const resp = await fetch(
178
- `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${process.env.GEMINI_API_KEY}`,
178
+ `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent`,
179
179
  {
180
180
  method: "POST",
181
- headers: { "content-type": "application/json" },
181
+ headers: { "content-type": "application/json", "x-goog-api-key": process.env.GEMINI_API_KEY },
182
182
  body: JSON.stringify({
183
183
  contents: [{ parts: [{ text: prompt }] }],
184
184
  generationConfig: { temperature: 0.3, maxOutputTokens: 300 }
package/dist/index.js CHANGED
@@ -1,7 +1,3 @@
1
- import {
2
- buildTemplateVariables,
3
- renderTemplate
4
- } from "./chunk-7766SIJP.js";
5
1
  import {
6
2
  buildSessionRecap,
7
3
  formatSessionRecapMarkdown,
@@ -9,7 +5,7 @@ import {
9
5
  } from "./chunk-ZKGY7WTT.js";
10
6
  import {
11
7
  setupCommand
12
- } from "./chunk-AXKYDCNN.js";
8
+ } from "./chunk-RVYA52PY.js";
13
9
  import {
14
10
  registerSyncBdCommand,
15
11
  syncBdCommand
@@ -22,14 +18,14 @@ import {
22
18
  import {
23
19
  rebuildCommand,
24
20
  registerRebuildCommand
25
- } from "./chunk-TPDH3JPP.js";
21
+ } from "./chunk-PBEE567J.js";
26
22
  import {
27
23
  registerReplayCommand,
28
24
  replayCommand
29
- } from "./chunk-4IV3R2F5.js";
25
+ } from "./chunk-R6SXNSFD.js";
30
26
  import {
31
27
  doctor
32
- } from "./chunk-W2HNZC22.js";
28
+ } from "./chunk-UEOUADMO.js";
33
29
  import "./chunk-7ZRP733D.js";
34
30
  import {
35
31
  graphCommand,
@@ -44,12 +40,12 @@ import {
44
40
  kanbanCommand,
45
41
  parseKanbanMarkdown,
46
42
  syncKanbanBoard
47
- } from "./chunk-J5EMBUPK.js";
43
+ } from "./chunk-4OXMU5S2.js";
48
44
  import "./chunk-4VQTUVH7.js";
49
45
  import "./chunk-J7ZWCI2C.js";
50
46
  import {
51
47
  registerCliCommands
52
- } from "./chunk-JDLOL2PL.js";
48
+ } from "./chunk-TLGBDTYT.js";
53
49
  import {
54
50
  registerTailscaleCommands,
55
51
  registerTailscaleDiscoverCommand,
@@ -87,17 +83,17 @@ import {
87
83
  SessionWatcher,
88
84
  observeCommand,
89
85
  registerObserveCommand
90
- } from "./chunk-OSMS7QIG.js";
86
+ } from "./chunk-ME37YNW3.js";
91
87
  import {
92
88
  parseSessionFile
93
89
  } from "./chunk-P5EPF6MB.js";
94
90
  import {
95
91
  reflectCommand,
96
92
  registerReflectCommand
97
- } from "./chunk-2YDBJS7M.js";
93
+ } from "./chunk-3BTHWPMB.js";
98
94
  import {
99
95
  runReflection
100
- } from "./chunk-YOSEUUNB.js";
96
+ } from "./chunk-T76H47ZS.js";
101
97
  import {
102
98
  buildContext,
103
99
  contextCommand,
@@ -112,13 +108,13 @@ import {
112
108
  getScaledObservationThresholdBytes,
113
109
  observeActiveSessions,
114
110
  parseSessionSourceLabel
115
- } from "./chunk-IZEY5S74.js";
111
+ } from "./chunk-IEVLHNLU.js";
116
112
  import "./chunk-HRLWZGMA.js";
117
113
  import {
118
114
  Compressor,
119
115
  Observer,
120
116
  Reflector
121
- } from "./chunk-S2IG7VNM.js";
117
+ } from "./chunk-Q2J5YTUF.js";
122
118
  import {
123
119
  archiveProject,
124
120
  createProject,
@@ -127,7 +123,7 @@ import {
127
123
  listProjects,
128
124
  readProject,
129
125
  updateProject
130
- } from "./chunk-5GZFTAL7.js";
126
+ } from "./chunk-AZYOKJYC.js";
131
127
  import {
132
128
  ClawVault,
133
129
  createVault,
@@ -156,11 +152,11 @@ import {
156
152
  injectCommand,
157
153
  registerInjectCommand,
158
154
  runPromptInjection
159
- } from "./chunk-GSD4ALSI.js";
155
+ } from "./chunk-4VRIMU4O.js";
160
156
  import {
161
157
  requestLlmCompletion,
162
158
  resolveLlmProvider
163
- } from "./chunk-K3CDT7IH.js";
159
+ } from "./chunk-HIHOUSXS.js";
164
160
  import {
165
161
  SUPPORTED_CONFIG_KEYS,
166
162
  addRouteRule,
@@ -211,7 +207,12 @@ import {
211
207
  queryTransitions,
212
208
  readAllTransitions,
213
209
  updateTask
214
- } from "./chunk-IOALNTAN.js";
210
+ } from "./chunk-QWQ3TIKS.js";
211
+ import "./chunk-MFAWT5O5.js";
212
+ import {
213
+ buildTemplateVariables,
214
+ renderTemplate
215
+ } from "./chunk-7766SIJP.js";
215
216
  import {
216
217
  checkOpenClawCompatibility,
217
218
  compatCommand,
@@ -6,8 +6,10 @@ import {
6
6
  listProjects,
7
7
  readProject,
8
8
  updateProject
9
- } from "../chunk-5GZFTAL7.js";
10
- import "../chunk-IOALNTAN.js";
9
+ } from "../chunk-AZYOKJYC.js";
10
+ import "../chunk-QWQ3TIKS.js";
11
+ import "../chunk-MFAWT5O5.js";
12
+ import "../chunk-7766SIJP.js";
11
13
  export {
12
14
  archiveProject,
13
15
  createProject,
@@ -63,6 +63,19 @@ interface TaskTransitionOptions {
63
63
  confidence?: number;
64
64
  reason?: string | null;
65
65
  }
66
+ type CreateTaskOptions = {
67
+ source?: string;
68
+ owner?: string;
69
+ project?: string;
70
+ priority?: TaskPriority;
71
+ due?: string;
72
+ content?: string;
73
+ tags?: string[];
74
+ description?: string;
75
+ estimate?: string;
76
+ parent?: string;
77
+ depends_on?: string[];
78
+ };
66
79
  /**
67
80
  * Slugify a title for use as filename
68
81
  * Deterministic: same title = same slug
@@ -111,19 +124,7 @@ declare function listBacklogItems(vaultPath: string, filters?: BacklogFilterOpti
111
124
  /**
112
125
  * Create a new task
113
126
  */
114
- declare function createTask(vaultPath: string, title: string, options?: {
115
- source?: string;
116
- owner?: string;
117
- project?: string;
118
- priority?: TaskPriority;
119
- due?: string;
120
- content?: string;
121
- tags?: string[];
122
- description?: string;
123
- estimate?: string;
124
- parent?: string;
125
- depends_on?: string[];
126
- }): Task;
127
+ declare function createTask(vaultPath: string, title: string, options?: CreateTaskOptions): Task;
127
128
  /**
128
129
  * Update an existing task
129
130
  */
@@ -23,7 +23,9 @@ import {
23
23
  slugify,
24
24
  updateBacklogItem,
25
25
  updateTask
26
- } from "../chunk-IOALNTAN.js";
26
+ } from "../chunk-QWQ3TIKS.js";
27
+ import "../chunk-MFAWT5O5.js";
28
+ import "../chunk-7766SIJP.js";
27
29
  export {
28
30
  completeTask,
29
31
  createBacklogItem,
@@ -3,6 +3,7 @@ interface TemplateVariables {
3
3
  date: string;
4
4
  datetime: string;
5
5
  type: string;
6
+ [key: string]: string | number | boolean | null | undefined;
6
7
  }
7
8
  declare function buildTemplateVariables(input?: Partial<TemplateVariables>, now?: Date): TemplateVariables;
8
9
  declare function renderTemplate(template: string, variables: TemplateVariables): string;
@@ -1,83 +1,83 @@
1
- ---
2
- name: clawvault
3
- description: "Context resilience - recovery detection, auto-checkpoint, and session context injection"
4
- metadata:
5
- openclaw:
6
- emoji: "🐘"
7
- events: ["gateway:startup", "gateway:heartbeat", "command:new", "session:start", "compaction:memoryFlush", "cron.weekly"]
8
- requires:
9
- bins: ["clawvault"]
10
- ---
11
-
12
- # ClawVault Hook
13
-
14
- Integrates ClawVault's context death resilience into OpenClaw:
15
-
16
- - **On gateway startup**: Checks for context death, alerts agent
17
- - **On heartbeat**: Runs cheap threshold checks and observes active sessions when needed
18
- - **On /new command**: Auto-checkpoints before session reset
19
- - **On context compaction**: Forces incremental observation flush before context is lost
20
- - **On session start**: Injects relevant vault context for the initial prompt
21
- - **On weekly cron**: Runs `clawvault reflect` every Sunday midnight (UTC)
22
-
23
- ## Installation
24
-
25
- ```bash
26
- npm install -g clawvault
27
- openclaw hooks install clawvault
28
- openclaw hooks enable clawvault
29
-
30
- # Verify
31
- openclaw hooks list --verbose
32
- openclaw hooks info clawvault
33
- openclaw hooks check
34
- ```
35
-
36
- After enabling, restart your OpenClaw gateway process so hook registration reloads.
37
-
38
- ## Requirements
39
-
40
- - ClawVault CLI installed globally
41
- - Vault initialized (`clawvault setup` or `CLAWVAULT_PATH` set)
42
-
43
- ## What It Does
44
-
45
- ### Gateway Startup
46
-
47
- 1. Runs `clawvault recover --clear`
48
- 2. If context death detected, injects warning into first agent turn
49
- 3. Clears dirty death flag for clean session start
50
-
51
- ### Command: /new
52
-
53
- 1. Creates automatic checkpoint with session info
54
- 2. Captures state even if agent forgot to handoff
55
- 3. Ensures continuity across session resets
56
-
57
- ### Session Start
58
-
59
- 1. Extracts the initial user prompt (`context.initialPrompt` or first user message)
60
- 2. Runs `clawvault context "<prompt>" --format json --profile auto -v <vaultPath>`
61
- - Delegates profile selection to the shared context intent policy (`incident`, `planning`, `handoff`, or `default`)
62
- 3. Injects up to 4 relevant context bullets into session messages
63
-
64
- Injection format:
65
-
66
- ```text
67
- [ClawVault] Relevant context for this task:
68
- - <title> (<age>): <snippet>
69
- - <title> (<age>): <snippet>
70
- ```
71
-
72
- ### Event Compatibility
73
-
74
- The hook accepts canonical OpenClaw events (`gateway:startup`, `gateway:heartbeat`, `command:new`, `session:start`, `compaction:memoryFlush`, `cron.weekly`) and tolerates alias payload shapes (`event`, `eventName`, `name`, `hook`, `trigger`) to remain robust across runtime wrappers.
75
-
76
- ## Configuration Notes
77
-
78
- The hook auto-detects vault path via:
79
-
80
- 1. `CLAWVAULT_PATH` environment variable
81
- 2. Walking up from cwd to find `.clawvault.json`
82
-
83
- If `openclaw hooks enable clawvault` fails with hook-not-found, run `openclaw hooks install clawvault` first and verify discovery with `openclaw hooks list --verbose`.
1
+ ---
2
+ name: clawvault
3
+ description: "Context resilience - recovery detection, auto-checkpoint, and session context injection"
4
+ metadata:
5
+ openclaw:
6
+ emoji: "🐘"
7
+ events: ["gateway:startup", "gateway:heartbeat", "command:new", "session:start", "compaction:memoryFlush", "cron.weekly"]
8
+ requires:
9
+ bins: ["clawvault"]
10
+ ---
11
+
12
+ # ClawVault Hook
13
+
14
+ Integrates ClawVault's context death resilience into OpenClaw:
15
+
16
+ - **On gateway startup**: Checks for context death, alerts agent
17
+ - **On heartbeat**: Runs cheap threshold checks and observes active sessions when needed
18
+ - **On /new command**: Auto-checkpoints before session reset
19
+ - **On context compaction**: Forces incremental observation flush before context is lost
20
+ - **On session start**: Injects relevant vault context for the initial prompt
21
+ - **On weekly cron**: Runs `clawvault reflect` every Sunday midnight (UTC)
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install -g clawvault
27
+ openclaw hooks install clawvault
28
+ openclaw hooks enable clawvault
29
+
30
+ # Verify
31
+ openclaw hooks list --verbose
32
+ openclaw hooks info clawvault
33
+ openclaw hooks check
34
+ ```
35
+
36
+ After enabling, restart your OpenClaw gateway process so hook registration reloads.
37
+
38
+ ## Requirements
39
+
40
+ - ClawVault CLI installed globally
41
+ - Vault initialized (`clawvault setup` or `CLAWVAULT_PATH` set)
42
+
43
+ ## What It Does
44
+
45
+ ### Gateway Startup
46
+
47
+ 1. Runs `clawvault recover --clear`
48
+ 2. If context death detected, injects warning into first agent turn
49
+ 3. Clears dirty death flag for clean session start
50
+
51
+ ### Command: /new
52
+
53
+ 1. Creates automatic checkpoint with session info
54
+ 2. Captures state even if agent forgot to handoff
55
+ 3. Ensures continuity across session resets
56
+
57
+ ### Session Start
58
+
59
+ 1. Extracts the initial user prompt (`context.initialPrompt` or first user message)
60
+ 2. Runs `clawvault context "<prompt>" --format json --profile auto -v <vaultPath>`
61
+ - Delegates profile selection to the shared context intent policy (`incident`, `planning`, `handoff`, or `default`)
62
+ 3. Injects up to 4 relevant context bullets into session messages
63
+
64
+ Injection format:
65
+
66
+ ```text
67
+ [ClawVault] Relevant context for this task:
68
+ - <title> (<age>): <snippet>
69
+ - <title> (<age>): <snippet>
70
+ ```
71
+
72
+ ### Event Compatibility
73
+
74
+ The hook accepts canonical OpenClaw events (`gateway:startup`, `gateway:heartbeat`, `command:new`, `session:start`, `compaction:memoryFlush`, `cron.weekly`) and tolerates alias payload shapes (`event`, `eventName`, `name`, `hook`, `trigger`) to remain robust across runtime wrappers.
75
+
76
+ ## Configuration Notes
77
+
78
+ The hook auto-detects vault path via:
79
+
80
+ 1. `CLAWVAULT_PATH` environment variable
81
+ 2. Walking up from cwd to find `.clawvault.json`
82
+
83
+ If `openclaw hooks enable clawvault` fails with hook-not-found, run `openclaw hooks install clawvault` first and verify discovery with `openclaw hooks list --verbose`.