vault-go 0.30.0 → 0.31.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 (50) hide show
  1. package/README.md +12 -0
  2. package/dist/agent-cost.d.ts +11 -0
  3. package/dist/agent-cost.js +116 -0
  4. package/dist/auth.js +29 -2
  5. package/dist/capabilities.d.ts +30 -24
  6. package/dist/capabilities.js +7 -6
  7. package/dist/capture-privacy.js +1 -1
  8. package/dist/cli.d.ts +2 -1
  9. package/dist/cli.js +16 -1
  10. package/dist/cloud.js +98 -47
  11. package/dist/config.d.ts +2 -0
  12. package/dist/config.js +15 -1
  13. package/dist/crystal-memory-mirror.d.ts +14 -1
  14. package/dist/crystal-memory-mirror.js +24 -15
  15. package/dist/crystal-tools.d.ts +24 -1
  16. package/dist/crystal-tools.js +30 -5
  17. package/dist/grok-awareness.js +54 -1
  18. package/dist/hook-install.d.ts +4 -0
  19. package/dist/hook-install.js +41 -1
  20. package/dist/hook-queue.d.ts +18 -0
  21. package/dist/hook-queue.js +115 -3
  22. package/dist/hook-runner.js +1 -1
  23. package/dist/hooks.d.ts +1 -1
  24. package/dist/hooks.js +17 -8
  25. package/dist/index.js +5 -1
  26. package/dist/installer.js +8 -1
  27. package/dist/legacy-brand.d.ts +2 -0
  28. package/dist/legacy-brand.js +5 -0
  29. package/dist/local-service.js +11 -0
  30. package/dist/memory-archive.d.ts +25 -0
  31. package/dist/memory-archive.js +65 -0
  32. package/dist/modes.d.ts +1 -1
  33. package/dist/modes.js +3 -1
  34. package/dist/opencode-plugin.d.ts +29 -1
  35. package/dist/opencode-plugin.js +36 -1
  36. package/dist/server.js +66 -0
  37. package/dist/skill-download.d.ts +6 -0
  38. package/dist/skill-download.js +48 -0
  39. package/dist/skill-library.d.ts +8 -0
  40. package/dist/skill-library.js +32 -0
  41. package/dist/skill-local.d.ts +7 -0
  42. package/dist/skill-local.js +44 -7
  43. package/dist/skill-tools.js +13 -26
  44. package/dist/skills-cli.d.ts +31 -0
  45. package/dist/skills-cli.js +90 -0
  46. package/dist/transcript-config.d.ts +1 -1
  47. package/dist/transcript-config.js +4 -3
  48. package/dist/transcript-parser.js +1 -1
  49. package/dist/transcript-tools.js +1 -1
  50. package/package.json +13 -1
package/README.md CHANGED
@@ -32,6 +32,18 @@ Credentials are stored in `~/.memvault/auth.json` (`0600`). The directory is `07
32
32
 
33
33
  ## Install MCP
34
34
 
35
+ ### Install private skills directly
36
+
37
+ After `vault-go login`, install private skill packages from the authenticated Vault account with one command:
38
+
39
+ ```sh
40
+ vault-go skills list
41
+ vault-go skills install --skill my-skill
42
+ vault-go skills install --all
43
+ ```
44
+
45
+ Installation defaults to `~/.agents/skills`, shared by Codex and other compatible agents. Use `--target claude` or `--target grok` for those clients' own skill directories. The command downloads the real package through your Vault account and verifies its integrity. With `--all`, existing skills that Vault did not install are preserved and reported as skipped; selecting one of them explicitly returns a conflict. The person with access to the target machine can read the installed files.
46
+
35
47
  ### Full local server (capture + write)
36
48
 
37
49
  The setup wizard:
@@ -0,0 +1,11 @@
1
+ export interface AgentCostReport {
2
+ label: 'ESTIMATED';
3
+ files: number;
4
+ inputTokens: number;
5
+ outputTokens: number;
6
+ usd: number | null;
7
+ unavailable: string[];
8
+ note: string;
9
+ }
10
+ export declare function estimateAgentCost(root: string): AgentCostReport;
11
+ export declare function statuslineText(home: string, version: string): string;
@@ -0,0 +1,116 @@
1
+ import { readdirSync, readFileSync, statSync } from 'node:fs';
2
+ import { join, relative, resolve } from 'node:path';
3
+ const INPUT_USD_PER_MILLION = 3;
4
+ const OUTPUT_USD_PER_MILLION = 15;
5
+ const MAX_FILES = 200;
6
+ const MAX_BYTES = 8_000_000;
7
+ function tokens(value) {
8
+ if (!value || typeof value !== 'object')
9
+ return null;
10
+ const row = value;
11
+ const input = row.input_tokens ?? row.inputTokens ?? row.prompt_tokens;
12
+ const output = row.output_tokens ?? row.outputTokens ?? row.completion_tokens;
13
+ if (typeof input !== 'number' && typeof output !== 'number')
14
+ return null;
15
+ return {
16
+ input: typeof input === 'number' && input >= 0 ? Math.floor(input) : 0,
17
+ output: typeof output === 'number' && output >= 0 ? Math.floor(output) : 0,
18
+ };
19
+ }
20
+ function walk(root, dir, files, budget) {
21
+ if (files.length >= MAX_FILES || budget.bytes >= MAX_BYTES)
22
+ return;
23
+ let entries = [];
24
+ try {
25
+ entries = readdirSync(dir);
26
+ }
27
+ catch {
28
+ return;
29
+ }
30
+ for (const name of entries) {
31
+ if (files.length >= MAX_FILES || budget.bytes >= MAX_BYTES)
32
+ return;
33
+ if (name.startsWith('.') || name === 'node_modules')
34
+ continue;
35
+ const path = join(dir, name);
36
+ let stat;
37
+ try {
38
+ stat = statSync(path);
39
+ }
40
+ catch {
41
+ continue;
42
+ }
43
+ if (stat.isSymbolicLink())
44
+ continue;
45
+ if (stat.isDirectory()) {
46
+ if (relative(root, path).split('/').length > 6)
47
+ continue;
48
+ walk(root, path, files, budget);
49
+ }
50
+ else if (stat.isFile() && name.endsWith('.jsonl') && stat.size <= MAX_BYTES) {
51
+ files.push(path);
52
+ budget.bytes += stat.size;
53
+ }
54
+ }
55
+ }
56
+ export function estimateAgentCost(root) {
57
+ const resolved = resolve(root);
58
+ const files = [];
59
+ walk(resolved, resolved, files, { bytes: 0 });
60
+ let inputTokens = 0;
61
+ let outputTokens = 0;
62
+ let measured = 0;
63
+ for (const file of files) {
64
+ let text = '';
65
+ try {
66
+ text = readFileSync(file, 'utf8');
67
+ }
68
+ catch {
69
+ continue;
70
+ }
71
+ for (const line of text.split('\n')) {
72
+ if (!line.trim())
73
+ continue;
74
+ let row;
75
+ try {
76
+ row = JSON.parse(line);
77
+ }
78
+ catch {
79
+ continue;
80
+ }
81
+ if (!row || typeof row !== 'object')
82
+ continue;
83
+ const record = row;
84
+ const message = record.message && typeof record.message === 'object' ? record.message : {};
85
+ const usage = tokens(record.usage) ?? tokens(message.usage);
86
+ if (!usage)
87
+ continue;
88
+ inputTokens += usage.input;
89
+ outputTokens += usage.output;
90
+ measured += 1;
91
+ }
92
+ }
93
+ const usd = measured
94
+ ? Math.round(((inputTokens * INPUT_USD_PER_MILLION) + (outputTokens * OUTPUT_USD_PER_MILLION)) / 1_000_000 * 100) / 100
95
+ : null;
96
+ return {
97
+ label: 'ESTIMATED',
98
+ files: files.length,
99
+ inputTokens,
100
+ outputTokens,
101
+ usd,
102
+ unavailable: measured ? [] : ['No usage fields were found in the scanned transcripts.'],
103
+ note: 'Dollars use a public list rate of $3 / million input tokens and $15 / million output tokens. This is an estimate, not an invoice. Observer cost is not included. Vault search remains the semantic index; this report does not read memory content into the total.',
104
+ };
105
+ }
106
+ export function statuslineText(home, version) {
107
+ let queued = 0;
108
+ try {
109
+ const value = JSON.parse(readFileSync(join(home, 'generation-queue.json'), 'utf8'));
110
+ queued = Array.isArray(value) ? value.length : 0;
111
+ }
112
+ catch {
113
+ queued = 0;
114
+ }
115
+ return `vault-go ${version} queue:${queued}`;
116
+ }
package/dist/auth.js CHANGED
@@ -3,11 +3,20 @@ import { copy, resolveLocale } from './locale.js';
3
3
  import { createServer } from 'node:http';
4
4
  import { randomBytes, createHash, timingSafeEqual } from 'node:crypto';
5
5
  import { execFile } from 'node:child_process';
6
- import { loadConfig, loadTokens, saveConfig, saveTokens, } from './config.js';
6
+ import { credentialFilesGeneration, loadConfig, loadTokens, saveConfig, saveTokens, validateApiUrl, } from './config.js';
7
7
  function endpoint(home, path) {
8
- const apiUrl = new URL(loadConfig(home).apiUrl);
8
+ const apiUrl = validateApiUrl(loadConfig(home).apiUrl);
9
9
  return new URL(`${apiUrl.pathname.replace(/\/$/u, '')}${path}`, apiUrl.origin);
10
10
  }
11
+ function authenticationScope(home) {
12
+ const apiUrl = loadConfig(home).apiUrl;
13
+ const generation = credentialFilesGeneration(home);
14
+ return () => {
15
+ if (loadConfig(home).apiUrl !== apiUrl || credentialFilesGeneration(home) !== generation) {
16
+ throw new Error('Vault session changed.');
17
+ }
18
+ };
19
+ }
11
20
  async function errorMessage(response) {
12
21
  const body = (await response.json().catch(() => ({})));
13
22
  return body.error || body.code || `HTTP ${response.status}`;
@@ -48,8 +57,10 @@ function normalizeTokens(value) {
48
57
  return normalized;
49
58
  }
50
59
  export async function authenticateWithPassword(email, password, requestMfa, home, fetcher = fetch) {
60
+ const assertCurrent = authenticationScope(home);
51
61
  const login = await fetcher(endpoint(home, '/auth/login'), {
52
62
  method: 'POST',
63
+ redirect: 'error',
53
64
  headers: { 'content-type': 'application/json' },
54
65
  body: JSON.stringify({ email, password }),
55
66
  signal: AbortSignal.timeout(15_000),
@@ -57,10 +68,13 @@ export async function authenticateWithPassword(email, password, requestMfa, home
57
68
  if (!login.ok)
58
69
  throw new Error(`Falha no login: ${await errorMessage(login)}`);
59
70
  let body = (await login.json());
71
+ assertCurrent();
60
72
  if ('twoFactorRequired' in body) {
61
73
  const code = await requestMfa();
74
+ assertCurrent();
62
75
  const verification = await fetcher(endpoint(home, '/auth/2fa/verify'), {
63
76
  method: 'POST',
77
+ redirect: 'error',
64
78
  headers: { 'content-type': 'application/json' },
65
79
  body: JSON.stringify({ ticket: body.ticket, code }),
66
80
  signal: AbortSignal.timeout(15_000),
@@ -70,34 +84,42 @@ export async function authenticateWithPassword(email, password, requestMfa, home
70
84
  }
71
85
  body = (await verification.json());
72
86
  }
87
+ assertCurrent();
73
88
  const tokens = normalizeTokens(body);
74
89
  persist(tokens, email, home);
75
90
  return { email, method: 'password' };
76
91
  }
77
92
  export async function authenticateWithApiKey(apiKey, home, fetcher = fetch) {
93
+ const assertCurrent = authenticationScope(home);
78
94
  const account = await accountForToken(apiKey, home, fetcher);
95
+ assertCurrent();
79
96
  if (!account)
80
97
  throw new Error('Chave de API Vault inválida ou sem permissão de leitura.');
81
98
  persist({ accessToken: apiKey }, account.email, home);
82
99
  return { email: account.email, method: 'api-key' };
83
100
  }
84
101
  export async function validateExistingAuthentication(home, fetcher = fetch) {
102
+ const assertCurrent = authenticationScope(home);
85
103
  let tokens = loadTokens(home);
86
104
  if (!tokens)
87
105
  return null;
88
106
  let account = await accountForToken(tokens.accessToken, home, fetcher);
107
+ assertCurrent();
89
108
  if (!account && tokens.refreshToken) {
90
109
  const refreshed = await fetcher(endpoint(home, '/auth/refresh'), {
91
110
  method: 'POST',
111
+ redirect: 'error',
92
112
  headers: { 'content-type': 'application/json' },
93
113
  body: JSON.stringify({ refreshToken: tokens.refreshToken }),
94
114
  signal: AbortSignal.timeout(15_000),
95
115
  });
96
116
  if (refreshed.ok) {
97
117
  tokens = normalizeTokens(await refreshed.json());
118
+ assertCurrent();
98
119
  account = await accountForToken(tokens.accessToken, home, fetcher);
99
120
  }
100
121
  }
122
+ assertCurrent();
101
123
  if (!account)
102
124
  return null;
103
125
  persist(tokens, account.email, home);
@@ -109,6 +131,8 @@ export function openVaultBrowser(url) {
109
131
  return new Promise((resolve, reject) => { execFile(command, args, { timeout: 10_000 }, error => error ? reject(error) : resolve()); });
110
132
  }
111
133
  export async function authenticateWithBrowser(home, options = {}) {
134
+ const checkScope = authenticationScope(home);
135
+ const assertCurrent = () => { checkScope(); options.signal?.throwIfAborted(); };
112
136
  const locale = options.locale ?? resolveLocale();
113
137
  const t = copy[locale];
114
138
  const fetcher = options.fetcher ?? fetch;
@@ -187,6 +211,7 @@ export async function authenticateWithBrowser(home, options = {}) {
187
211
  report(t.openFailed);
188
212
  }
189
213
  const code = await received;
214
+ assertCurrent();
190
215
  const response = await fetcher(endpoint(home, '/auth/mobile/exchange'), {
191
216
  method: 'POST', headers: { 'content-type': 'application/json' },
192
217
  body: JSON.stringify({ code, verifier }), redirect: 'error', signal: AbortSignal.timeout(15_000),
@@ -194,7 +219,9 @@ export async function authenticateWithBrowser(home, options = {}) {
194
219
  if (!response.ok)
195
220
  throw new Error(t.retry);
196
221
  const tokens = normalizeTokens(await response.json());
222
+ assertCurrent();
197
223
  const account = await accountForToken(tokens.accessToken, home, fetcher);
224
+ assertCurrent();
198
225
  if (!account)
199
226
  throw new Error('O Vault não confirmou a conta autenticada.');
200
227
  persist(tokens, account.email, home);
@@ -3,10 +3,8 @@ import { type DeploymentVerification } from './deployment-verification.js';
3
3
  /** Audited against source, not the upstream README's stale tool count. */
4
4
  export declare const CAPABILITIES: {
5
5
  readonly reference: {
6
- readonly repository: "https://github.com/thedotmack/claude-mem";
7
- readonly version: "13.25.2";
8
- readonly commit: "adce0fdfaf1cd46646bbd0b22ae74cbd460ed787";
9
- readonly auditedAt: "2026-09-20";
6
+ readonly product: "Vault Memory";
7
+ readonly auditedAt: "2026-09-27";
10
8
  };
11
9
  readonly verification: {
12
10
  readonly capabilityVersion: "2026-09-20.1";
@@ -37,7 +35,7 @@ export declare const CAPABILITIES: {
37
35
  readonly upstream: readonly ["session_start_context", "multi-project context"];
38
36
  readonly status: "available";
39
37
  readonly tools: readonly ["vault_go_session_start_context", "vault_go_context", "vault_go_file_context", "vault_go_context_chain", "vault_go_context_chain_configure"];
40
- readonly requires: "Context chains require explicit local configuration and share one bounded character budget. Native hooks cover Claude, Codex, Grok, Agy and Gemini; OpenCode 1.x remains context-only.";
38
+ readonly requires: "Context chains require explicit local configuration and share one bounded character budget. Native hooks cover Claude, Codex, Grok, Agy and Gemini, including Setup and SessionEnd. OpenCode captures prompts, reads, tool results and session end. Cursor, Windsurf, OpenClaw and Hermes receive the same hook command when their config directory already exists.";
41
39
  }, {
42
40
  readonly upstream: readonly ["smart_search", "smart_outline", "smart_unfold"];
43
41
  readonly status: "available";
@@ -80,13 +78,13 @@ export declare const CAPABILITIES: {
80
78
  }, {
81
79
  readonly upstream: readonly ["import", "export"];
82
80
  readonly status: "available";
83
- readonly tools: readonly ["vault_go_import", "vault_go_export", "vault_go_backup_create", "vault_go_backup_restore"];
84
- readonly difference: "Legacy bounded batches remain available. Backup v2 creates a complete, paginated, server-materialized same-owner memory-data snapshot with declared limits, local 0600 file and SHA-256. It is not the upstream SQLite format and is not an offline replica; embeddings, transient jobs, credentials, audit logs and blobs are intentionally omitted.";
81
+ readonly tools: readonly ["vault_go_import", "vault_go_export", "vault_go_archive_export", "vault_go_archive_import", "vault_go_backup_create", "vault_go_backup_restore"];
82
+ readonly difference: "Legacy bounded batches remain available. vault_go_archive_export groups the same account data into observations, sessions, summaries and prompts. Backup v2 creates a complete, paginated, server-materialized same-owner memory-data snapshot with declared limits, local 0600 file and SHA-256. It is not an offline SQLite replica; embeddings, transient jobs, credentials, audit logs and blobs are intentionally omitted.";
85
83
  }, {
86
84
  readonly upstream: readonly ["cloud sync"];
87
85
  readonly status: "partial";
88
86
  readonly tools: readonly [];
89
- readonly difference: "Vault stores authoritative memories in its authenticated cloud and persists local processing queues. This does not implement cmem.ai Pro synchronization or a complete offline SQLite replica.";
87
+ readonly difference: "Vault stores authoritative memories in its authenticated cloud and persists local processing queues. External sync protocols and a complete offline replica are not part of this runtime.";
90
88
  }, {
91
89
  readonly upstream: readonly ["Telegram"];
92
90
  readonly status: "available";
@@ -101,17 +99,22 @@ export declare const CAPABILITIES: {
101
99
  readonly upstream: readonly ["transcript watchers"];
102
100
  readonly status: "available";
103
101
  readonly tools: readonly ["vault_go_transcripts_status", "vault_go_transcripts_configure", "vault_go_transcripts_poll"];
104
- readonly difference: "Persistent, consented and resumable watchers are implemented for Claude and Codex transcripts. Other client transcript formats are not claimed.";
102
+ readonly difference: "Persistent, consented and resumable watchers read Claude, Codex and Cursor JSONL transcripts. Cursor rows use the Claude message shape. Other transcript formats are not claimed.";
105
103
  }, {
106
104
  readonly upstream: readonly ["Grok awareness push"];
107
105
  readonly status: "available";
108
106
  readonly tools: readonly ["vault_go_grok_awareness_status", "vault_go_grok_awareness_configure", "vault_go_grok_awareness_push"];
109
107
  readonly requires: "Explicit consent, an allowlisted agent UUID and a local agent-data root. Monthly awareness logs are bounded, private and separate from Telegram.";
110
108
  }, {
111
- readonly upstream: readonly ["development/report/presentation skills", "babysit", "mem-search"];
109
+ readonly upstream: readonly ["development/report/presentation skills", "babysit", "mem-search", "agent-cost-report"];
112
110
  readonly status: "available";
113
- readonly tools: readonly ["vault_go_modes", "vault_go_mode"];
114
- readonly difference: "Setup writes managed SKILL.md files for Claude, Grok and shared agent skill directories. mem-search uses vault_go_search_index → vault_go_timeline → vault_go_observations → vault_go_tool_uses. babysit is a session loop with gh, not a Vault background daemon.";
111
+ readonly tools: readonly ["vault_go_modes", "vault_go_mode", "vault_go_agent_cost_report"];
112
+ readonly difference: "Setup writes managed SKILL.md files for Claude, Grok and shared agent skill directories. mem-search uses vault_go_search_index → vault_go_timeline → vault_go_observations → vault_go_tool_uses. babysit is a session loop with gh, not a Vault background daemon. agent-cost-report prices local JSONL usage with a published list rate and reports missing usage as unavailable.";
113
+ }, {
114
+ readonly upstream: readonly ["viewer", "statusline"];
115
+ readonly status: "available";
116
+ readonly tools: readonly [];
117
+ readonly difference: "The local worker serves /viewer and /statusline on its loopback port. Semantic search stays on the Vault account index. A second local vector database is not shipped.";
115
118
  }, {
116
119
  readonly upstream: readonly ["private skills library"];
117
120
  readonly status: "available";
@@ -124,10 +127,8 @@ export declare function getCapabilities(home: string, cloud: VaultMemoryApi, ver
124
127
  deploymentVerified: boolean;
125
128
  deploymentVerification: DeploymentVerification;
126
129
  reference: {
127
- readonly repository: "https://github.com/thedotmack/claude-mem";
128
- readonly version: "13.25.2";
129
- readonly commit: "adce0fdfaf1cd46646bbd0b22ae74cbd460ed787";
130
- readonly auditedAt: "2026-09-20";
130
+ readonly product: "Vault Memory";
131
+ readonly auditedAt: "2026-09-27";
131
132
  };
132
133
  verification: {
133
134
  readonly capabilityVersion: "2026-09-20.1";
@@ -158,7 +159,7 @@ export declare function getCapabilities(home: string, cloud: VaultMemoryApi, ver
158
159
  readonly upstream: readonly ["session_start_context", "multi-project context"];
159
160
  readonly status: "available";
160
161
  readonly tools: readonly ["vault_go_session_start_context", "vault_go_context", "vault_go_file_context", "vault_go_context_chain", "vault_go_context_chain_configure"];
161
- readonly requires: "Context chains require explicit local configuration and share one bounded character budget. Native hooks cover Claude, Codex, Grok, Agy and Gemini; OpenCode 1.x remains context-only.";
162
+ readonly requires: "Context chains require explicit local configuration and share one bounded character budget. Native hooks cover Claude, Codex, Grok, Agy and Gemini, including Setup and SessionEnd. OpenCode captures prompts, reads, tool results and session end. Cursor, Windsurf, OpenClaw and Hermes receive the same hook command when their config directory already exists.";
162
163
  }, {
163
164
  readonly upstream: readonly ["smart_search", "smart_outline", "smart_unfold"];
164
165
  readonly status: "available";
@@ -201,13 +202,13 @@ export declare function getCapabilities(home: string, cloud: VaultMemoryApi, ver
201
202
  }, {
202
203
  readonly upstream: readonly ["import", "export"];
203
204
  readonly status: "available";
204
- readonly tools: readonly ["vault_go_import", "vault_go_export", "vault_go_backup_create", "vault_go_backup_restore"];
205
- readonly difference: "Legacy bounded batches remain available. Backup v2 creates a complete, paginated, server-materialized same-owner memory-data snapshot with declared limits, local 0600 file and SHA-256. It is not the upstream SQLite format and is not an offline replica; embeddings, transient jobs, credentials, audit logs and blobs are intentionally omitted.";
205
+ readonly tools: readonly ["vault_go_import", "vault_go_export", "vault_go_archive_export", "vault_go_archive_import", "vault_go_backup_create", "vault_go_backup_restore"];
206
+ readonly difference: "Legacy bounded batches remain available. vault_go_archive_export groups the same account data into observations, sessions, summaries and prompts. Backup v2 creates a complete, paginated, server-materialized same-owner memory-data snapshot with declared limits, local 0600 file and SHA-256. It is not an offline SQLite replica; embeddings, transient jobs, credentials, audit logs and blobs are intentionally omitted.";
206
207
  }, {
207
208
  readonly upstream: readonly ["cloud sync"];
208
209
  readonly status: "partial";
209
210
  readonly tools: readonly [];
210
- readonly difference: "Vault stores authoritative memories in its authenticated cloud and persists local processing queues. This does not implement cmem.ai Pro synchronization or a complete offline SQLite replica.";
211
+ readonly difference: "Vault stores authoritative memories in its authenticated cloud and persists local processing queues. External sync protocols and a complete offline replica are not part of this runtime.";
211
212
  }, {
212
213
  readonly upstream: readonly ["Telegram"];
213
214
  readonly status: "available";
@@ -222,17 +223,22 @@ export declare function getCapabilities(home: string, cloud: VaultMemoryApi, ver
222
223
  readonly upstream: readonly ["transcript watchers"];
223
224
  readonly status: "available";
224
225
  readonly tools: readonly ["vault_go_transcripts_status", "vault_go_transcripts_configure", "vault_go_transcripts_poll"];
225
- readonly difference: "Persistent, consented and resumable watchers are implemented for Claude and Codex transcripts. Other client transcript formats are not claimed.";
226
+ readonly difference: "Persistent, consented and resumable watchers read Claude, Codex and Cursor JSONL transcripts. Cursor rows use the Claude message shape. Other transcript formats are not claimed.";
226
227
  }, {
227
228
  readonly upstream: readonly ["Grok awareness push"];
228
229
  readonly status: "available";
229
230
  readonly tools: readonly ["vault_go_grok_awareness_status", "vault_go_grok_awareness_configure", "vault_go_grok_awareness_push"];
230
231
  readonly requires: "Explicit consent, an allowlisted agent UUID and a local agent-data root. Monthly awareness logs are bounded, private and separate from Telegram.";
231
232
  }, {
232
- readonly upstream: readonly ["development/report/presentation skills", "babysit", "mem-search"];
233
+ readonly upstream: readonly ["development/report/presentation skills", "babysit", "mem-search", "agent-cost-report"];
233
234
  readonly status: "available";
234
- readonly tools: readonly ["vault_go_modes", "vault_go_mode"];
235
- readonly difference: "Setup writes managed SKILL.md files for Claude, Grok and shared agent skill directories. mem-search uses vault_go_search_index → vault_go_timeline → vault_go_observations → vault_go_tool_uses. babysit is a session loop with gh, not a Vault background daemon.";
235
+ readonly tools: readonly ["vault_go_modes", "vault_go_mode", "vault_go_agent_cost_report"];
236
+ readonly difference: "Setup writes managed SKILL.md files for Claude, Grok and shared agent skill directories. mem-search uses vault_go_search_index → vault_go_timeline → vault_go_observations → vault_go_tool_uses. babysit is a session loop with gh, not a Vault background daemon. agent-cost-report prices local JSONL usage with a published list rate and reports missing usage as unavailable.";
237
+ }, {
238
+ readonly upstream: readonly ["viewer", "statusline"];
239
+ readonly status: "available";
240
+ readonly tools: readonly [];
241
+ readonly difference: "The local worker serves /viewer and /statusline on its loopback port. Semantic search stays on the Vault account index. A second local vector database is not shipped.";
236
242
  }, {
237
243
  readonly upstream: readonly ["private skills library"];
238
244
  readonly status: "available";
@@ -1,7 +1,7 @@
1
1
  import { DEPLOYMENT_CACHE_TTL_MS, DEPLOYMENT_CAPABILITY_VERSION, cachedDeploymentVerification, verifyDeployment, } from './deployment-verification.js';
2
2
  /** Audited against source, not the upstream README's stale tool count. */
3
3
  export const CAPABILITIES = {
4
- reference: { repository: 'https://github.com/thedotmack/claude-mem', version: '13.25.2', commit: 'adce0fdfaf1cd46646bbd0b22ae74cbd460ed787', auditedAt: '2026-09-20' },
4
+ reference: { product: 'Vault Memory', auditedAt: '2026-09-27' },
5
5
  verification: {
6
6
  capabilityVersion: DEPLOYMENT_CAPABILITY_VERSION,
7
7
  cacheTtlMs: DEPLOYMENT_CACHE_TTL_MS,
@@ -13,7 +13,7 @@ export const CAPABILITIES = {
13
13
  { upstream: ['search', 'get_observations', 'timeline'], status: 'available', tools: ['vault_go_search_index', 'vault_go_observations', 'vault_go_timeline', 'vault_go_feed'], difference: 'Vault uses UUID identifiers. Search accepts an optional query, offset and date ordering; timeline accepts an explicit UUID or resolves an anchor from a query; feed uses stable cursor pagination.' },
14
14
  { upstream: ['automatic retrieval routing', 'typed memory decisions'], status: 'available', tools: ['vault_go_retrieve', 'vault_go_decision_status', 'vault_go_decide'], requires: 'Jev runs only in the central memory engine. Status is sanitized; deployment availability does not prove provider health or decision quality. vault_go_decide forwards caller-authored typed questions only in full rollout and refuses protected content. Explicit retrieval tools remain available.' },
15
15
  { upstream: ['get_tool_uses'], status: 'available', tools: ['vault_go_tool_uses'], requires: 'Verified POST /memory/events/batch contract. Historical output exists only when captured; private fields and secrets are redacted from retrieval.' },
16
- { upstream: ['session_start_context', 'multi-project context'], status: 'available', tools: ['vault_go_session_start_context', 'vault_go_context', 'vault_go_file_context', 'vault_go_context_chain', 'vault_go_context_chain_configure'], requires: 'Context chains require explicit local configuration and share one bounded character budget. Native hooks cover Claude, Codex, Grok, Agy and Gemini; OpenCode 1.x remains context-only.' },
16
+ { upstream: ['session_start_context', 'multi-project context'], status: 'available', tools: ['vault_go_session_start_context', 'vault_go_context', 'vault_go_file_context', 'vault_go_context_chain', 'vault_go_context_chain_configure'], requires: 'Context chains require explicit local configuration and share one bounded character budget. Native hooks cover Claude, Codex, Grok, Agy and Gemini, including Setup and SessionEnd. OpenCode captures prompts, reads, tool results and session end. Cursor, Windsurf, OpenClaw and Hermes receive the same hook command when their config directory already exists.' },
17
17
  { upstream: ['smart_search', 'smart_outline', 'smart_unfold'], status: 'available', tools: ['vault_go_smart_search', 'vault_go_smart_outline', 'vault_go_smart_unfold', 'vault_go_smart_languages'], requires: 'Real grammars for all 24 upstream languages plus HTML. Availability is reported per running platform; SCSS has no Linux ARM64 prebuild. Workspace reads and results are bounded.' },
18
18
  { upstream: ['observation_add', 'observation_record_event', 'observation_search', 'observation_context'], status: 'available', tools: ['vault_go_remember', 'vault_go_event', 'vault_go_search', 'vault_go_context'], requires: 'generate:false prevents duplicate server processing on an updated engine. summaryMode=off preserves captured text without model extraction.' },
19
19
  { upstream: ['automatic updates'], status: 'available', tools: ['vault_go_update_status', 'vault_go_update_check', 'vault_go_update_install', 'vault_go_update_configure'], requires: 'Local worker running, npm installed and official registry reachable. Activation waits for idle state and rolls back failed runtimes.' },
@@ -22,13 +22,14 @@ export const CAPABILITIES = {
22
22
  { upstream: ['prime_corpus', 'query_corpus', 'reprime_corpus'], status: 'available', tools: ['vault_go_prime_corpus', 'vault_go_query_corpus', 'vault_go_reprime_corpus'], requires: 'Uses the selected authenticated model. Conversation history is encrypted locally, isolated by account and corpus, bounded to 12 turns, and factual answers must cite retrieved memory IDs. Corpus loading is limited to an 8 MiB HTTP response; selected source JSON is limited to 16,000 characters.' },
23
23
  { upstream: ['provider selection', 'automatic observation processing'], status: 'available', tools: ['vault_go_engines', 'vault_go_engine_select', 'vault_go_generate_context', 'vault_go_processing_status'], requires: 'Local worker running and the selected provider authenticated. Model availability and subscription or API billing are not covered by deployment verification.' },
24
24
  { upstream: ['privacy', 'capture modes', 'context settings'], status: 'available', tools: ['vault_go_preferences', 'vault_go_preferences_update', 'vault_go_custom_modes', 'vault_go_custom_mode_get', 'vault_go_custom_mode_save', 'vault_go_custom_mode_select', 'vault_go_custom_mode_delete'], requires: 'Private-tag redaction and inherited custom taxonomies apply to future local processing. Preference updates require session authentication.' },
25
- { upstream: ['import', 'export'], status: 'available', tools: ['vault_go_import', 'vault_go_export', 'vault_go_backup_create', 'vault_go_backup_restore'], difference: 'Legacy bounded batches remain available. Backup v2 creates a complete, paginated, server-materialized same-owner memory-data snapshot with declared limits, local 0600 file and SHA-256. It is not the upstream SQLite format and is not an offline replica; embeddings, transient jobs, credentials, audit logs and blobs are intentionally omitted.' },
26
- { upstream: ['cloud sync'], status: 'partial', tools: [], difference: 'Vault stores authoritative memories in its authenticated cloud and persists local processing queues. This does not implement cmem.ai Pro synchronization or a complete offline SQLite replica.' },
25
+ { upstream: ['import', 'export'], status: 'available', tools: ['vault_go_import', 'vault_go_export', 'vault_go_archive_export', 'vault_go_archive_import', 'vault_go_backup_create', 'vault_go_backup_restore'], difference: 'Legacy bounded batches remain available. vault_go_archive_export groups the same account data into observations, sessions, summaries and prompts. Backup v2 creates a complete, paginated, server-materialized same-owner memory-data snapshot with declared limits, local 0600 file and SHA-256. It is not an offline SQLite replica; embeddings, transient jobs, credentials, audit logs and blobs are intentionally omitted.' },
26
+ { upstream: ['cloud sync'], status: 'partial', tools: [], difference: 'Vault stores authoritative memories in its authenticated cloud and persists local processing queues. External sync protocols and a complete offline replica are not part of this runtime.' },
27
27
  { upstream: ['Telegram'], status: 'available', tools: ['vault_go_telegram_status', 'vault_go_telegram_configure', 'vault_go_telegram_disable', 'vault_go_telegram_test'], requires: 'Explicit configuration, private bot credential environment and user-authorized test delivery. Deployment verification does not contact Telegram.' },
28
28
  { upstream: ['CCS Align'], status: 'available', tools: ['vault_go_ccs_align_health', 'vault_go_ccs_align_cycle', 'vault_go_ccs_align_exclude', 'vault_go_ccs_align_restore', 'vault_go_ccs_align_rules_check'], requires: 'Local private middle cache and explicit cycle execution; rule checks report conflicts without modifying source rules.' },
29
- { upstream: ['transcript watchers'], status: 'available', tools: ['vault_go_transcripts_status', 'vault_go_transcripts_configure', 'vault_go_transcripts_poll'], difference: 'Persistent, consented and resumable watchers are implemented for Claude and Codex transcripts. Other client transcript formats are not claimed.' },
29
+ { upstream: ['transcript watchers'], status: 'available', tools: ['vault_go_transcripts_status', 'vault_go_transcripts_configure', 'vault_go_transcripts_poll'], difference: 'Persistent, consented and resumable watchers read Claude, Codex and Cursor JSONL transcripts. Cursor rows use the Claude message shape. Other transcript formats are not claimed.' },
30
30
  { upstream: ['Grok awareness push'], status: 'available', tools: ['vault_go_grok_awareness_status', 'vault_go_grok_awareness_configure', 'vault_go_grok_awareness_push'], requires: 'Explicit consent, an allowlisted agent UUID and a local agent-data root. Monthly awareness logs are bounded, private and separate from Telegram.' },
31
- { upstream: ['development/report/presentation skills', 'babysit', 'mem-search'], status: 'available', tools: ['vault_go_modes', 'vault_go_mode'], difference: 'Setup writes managed SKILL.md files for Claude, Grok and shared agent skill directories. mem-search uses vault_go_search_index → vault_go_timeline → vault_go_observations → vault_go_tool_uses. babysit is a session loop with gh, not a Vault background daemon.' },
31
+ { upstream: ['development/report/presentation skills', 'babysit', 'mem-search', 'agent-cost-report'], status: 'available', tools: ['vault_go_modes', 'vault_go_mode', 'vault_go_agent_cost_report'], difference: 'Setup writes managed SKILL.md files for Claude, Grok and shared agent skill directories. mem-search uses vault_go_search_index → vault_go_timeline → vault_go_observations → vault_go_tool_uses. babysit is a session loop with gh, not a Vault background daemon. agent-cost-report prices local JSONL usage with a published list rate and reports missing usage as unavailable.' },
32
+ { upstream: ['viewer', 'statusline'], status: 'available', tools: [], difference: 'The local worker serves /viewer and /statusline on its loopback port. Semantic search stays on the Vault account index. A second local vector database is not shipped.' },
32
33
  { upstream: ['private skills library'], status: 'available', tools: ['vault_go_skills', 'vault_go_skill_folders', 'vault_go_skill_read', 'vault_go_skill_file', 'vault_go_skill_save', 'vault_go_skill_organize', 'vault_go_skill_install', 'vault_go_skill_sync'], requires: 'Account skill packages organized by folders and linked to projects (/v1/skills). Saving publishes a new immutable version; deleting is only available in the Vault apps. Local install verifies sha256 and manifest digest and never replaces a skill the Vault did not install.' },
33
34
  ],
34
35
  };
@@ -1,7 +1,7 @@
1
1
  export function redact(value) {
2
2
  if (typeof value === "string") {
3
3
  return value
4
- .replace(/<(private|vault-private|claude-mem-context|system_instruction|system-instruction|persisted-output|system-reminder)\b[^>]*>[\s\S]*?(?:<\/\1\s*>|$)/gi, "[redacted]")
4
+ .replace(new RegExp(`<(private|vault-private|${["claude", "mem", "context"].join("-")}|system_instruction|system-instruction|persisted-output|system-reminder)\\b[^>]*>[\\s\\S]*?(?:<\\/\\1\\s*>|$)`, "gi"), "[redacted]")
5
5
  .replace(/(api[_-]?key|secret|token|password)\s*[:=]\s*['"]?[^\s'"]+/gi, "$1=[redacted]");
6
6
  }
7
7
  if (Array.isArray(value))
package/dist/cli.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type McpClient } from './installer.js';
2
2
  import { type ContextEngineId } from './context-engines.js';
3
- export type CliMode = 'help' | 'version' | 'setup' | 'login' | 'serve' | 'local' | 'engine' | 'hook' | 'update' | 'transcripts' | 'context-chain' | 'invalid';
3
+ export type CliMode = 'help' | 'version' | 'setup' | 'login' | 'serve' | 'local' | 'engine' | 'hook' | 'update' | 'transcripts' | 'context-chain' | 'skills' | 'invalid';
4
4
  export declare function resolveCliMode(argument: string | undefined, stdinIsTTY: boolean, stderrIsTTY: boolean): CliMode;
5
5
  export declare function parseEngineChoice(value: string): ContextEngineId;
6
6
  export declare function parseNumberedClients(value: string): McpClient[];
@@ -10,6 +10,7 @@ export declare function cliArguments(args: string[]): {
10
10
  };
11
11
  export declare function runLocal(args: string[]): Promise<number>;
12
12
  export declare function runLogin(args: string[]): Promise<number>;
13
+ export declare function runSkills(args: string[], home?: string): Promise<number>;
13
14
  export declare function runSetup(args: string[]): Promise<number>;
14
15
  export declare function helpText(version: string): string;
15
16
  export declare function runEngine(args: string[]): Promise<number>;
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { authenticateWithApiKey, authenticateWithBrowser, validateExistingAuthentication, } from './auth.js';
2
- import { vaultHome } from './config.js';
2
+ import { loadTokens, vaultHome } from './config.js';
3
3
  import { detectMcpClients, installMcpClient, MCP_CLIENTS, parseClientSelection, } from './installer.js';
4
4
  import { promptSecret, promptText } from './prompt.js';
5
5
  import { playInstallBanner, withInstallProgress } from './install-ui.js';
@@ -7,6 +7,7 @@ import { CONTEXT_ENGINE_IDS, ENGINE_NAMES, engineModels, isApiEngine, listContex
7
7
  import { VaultCloudClient } from './cloud.js';
8
8
  import { copy, resolveLocale } from './locale.js';
9
9
  import { installLocal, localStatus, localUrl, openLocal, startLocal, stopLocal, uninstallLocal } from './local-install.js';
10
+ import { executeSkillsCommand } from './skills-cli.js';
10
11
  export function resolveCliMode(argument, stdinIsTTY, stderrIsTTY) {
11
12
  if (argument === '--help' || argument === '-h')
12
13
  return 'help';
@@ -30,6 +31,8 @@ export function resolveCliMode(argument, stdinIsTTY, stderrIsTTY) {
30
31
  return 'transcripts';
31
32
  if (argument === 'context-chain')
32
33
  return 'context-chain';
34
+ if (argument === 'skills')
35
+ return 'skills';
33
36
  if (argument === undefined)
34
37
  return stdinIsTTY && stderrIsTTY ? 'setup' : 'serve';
35
38
  return 'invalid';
@@ -260,6 +263,13 @@ export async function runLogin(args) {
260
263
  await ensureAuthentication(vaultHome(), args.includes('--force'), args.includes('--api-key'), locale);
261
264
  return 0;
262
265
  }
266
+ export async function runSkills(args, home = vaultHome()) {
267
+ if (!loadTokens(home) && !process.env['VAULT_GO_TOKEN'])
268
+ throw new Error('Entre na sua conta antes: vault-go login');
269
+ const result = await executeSkillsCommand(args, { cloud: new VaultCloudClient(home) });
270
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
271
+ return 0;
272
+ }
263
273
  export async function runSetup(args) {
264
274
  if (optionValue(args, '--watch-transcripts') && !args.includes('--consent'))
265
275
  throw new Error('--watch-transcripts exige --consent explícito.');
@@ -333,6 +343,11 @@ Uso:
333
343
  vault-go local [install|start|open|status|stop|uninstall|serve]
334
344
  Painel local em http://localhost:38850; install ativa início automático no macOS.
335
345
 
346
+ vault-go skills list
347
+ vault-go skills install --skill <nome> [--skill <nome> ...] [--target agents|claude|grok]
348
+ vault-go skills install --all [--target agents|claude|grok]
349
+ Instala skills da biblioteca privada na máquina atual (padrão: ~/.agents/skills).
350
+
336
351
  vault-go engine list|use <motor> [--model modelo]|key openrouter|gemini
337
352
  Escolhe motor/modelo. Codex: terra, luna, sol; Claude: haiku, sonnet, opus.
338
353