@empirical-gauzza/cli 1.0.28 → 1.0.30
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.
- package/bin/empirical.js +1 -1
- package/lib/alertBanner.js +17 -0
- package/lib/constants.js +657 -640
- package/lib/http.js +2 -2
- package/lib/installers/hooks.js +321 -61
- package/lib/installers/skill-variants/SKILL.both.md +21 -0
- package/lib/installers/skill-variants/SKILL.cli.md +21 -0
- package/lib/installers/skill-variants/SKILL.mcp.md +21 -0
- package/lib/memoryCommands.js +88 -4
- package/package.json +1 -1
package/lib/constants.js
CHANGED
|
@@ -1,640 +1,657 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
|
|
6
|
-
const EMPIRICAL_MCP_NAME = 'empirical';
|
|
7
|
-
const EMPIRICAL_MCP_LEGACY_NAMES = ['empirical-live'];
|
|
8
|
-
const EMPIRICAL_MCP_URL = process.env.EMPIRICAL_MCP_URL || 'https://empirical.gauzza.com/mcp';
|
|
9
|
-
const COPILOT_OAUTH_CLIENT_ID = process.env.EMPIRICAL_COPILOT_OAUTH_CLIENT_ID || 'copilot-cli-empirical';
|
|
10
|
-
|
|
11
|
-
// These two lists mirror the schema-level enums in packages/shared/src/memoryGraph.ts.
|
|
12
|
-
// They are duplicated rather than imported on purpose: this CLI publishes to npm as
|
|
13
|
-
// @empirical-gauzza/cli, and @empirical/shared is a private workspace package, so depending
|
|
14
|
-
// on it would break `npm install` for end users. tests/unit/cliMemoryEnumParity.test.js
|
|
15
|
-
// fails CI if the copies ever diverge.
|
|
16
|
-
const MEMORY_CATEGORIES = [
|
|
17
|
-
'health', 'fitness', 'food', 'supplement', 'mood', 'idea', 'business',
|
|
18
|
-
'build', 'growth', 'learning', 'leadership', 'operations', 'workflow',
|
|
19
|
-
'lead', 'project', 'recipe', 'preference', 'reflection', 'relationship', 'heartbeat'
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
const NODE_TYPES = [
|
|
23
|
-
'event', 'entity', 'observation', 'reflection', 'goal', 'concept'
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
const DOC_TOPICS = {
|
|
27
|
-
memory: `# Empirical Memory Commands
|
|
28
|
-
|
|
29
|
-
Use the \`empirical memory\` subcommands to query and manage memories via the REST API.
|
|
30
|
-
All commands require a valid access token (see \`empirical doc auth\`).
|
|
31
|
-
Errors are written to stderr as JSON. Successful output is written to stdout as JSON.
|
|
32
|
-
|
|
33
|
-
## Subcommands
|
|
34
|
-
|
|
35
|
-
### query
|
|
36
|
-
Search memories by natural language.
|
|
37
|
-
|
|
38
|
-
empirical memory query --match "coding style preferences" [--top-k 3] [--category build] [--tags ts,node] [--pretty] [--format table]
|
|
39
|
-
|
|
40
|
-
Flags:
|
|
41
|
-
- \`--match\` (required): natural language search string
|
|
42
|
-
- \`--top-k\`: number of results, 1–100, default 3
|
|
43
|
-
- \`--category\`: filter by category
|
|
44
|
-
- \`--tags\`: comma-separated tags filter
|
|
45
|
-
- \`--tags-all\`: comma-separated tags that must ALL be present (AND match)
|
|
46
|
-
- \`--status\`: comma-separated status values to keep (for example open,in_progress)
|
|
47
|
-
- \`--
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
- \`--
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
- \`--
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
- \`--path
|
|
59
|
-
when
|
|
60
|
-
- \`--path
|
|
61
|
-
Use it when you want
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
- \`--
|
|
81
|
-
- \`--
|
|
82
|
-
- \`--
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
empirical memory record --category build --summary
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
\`--category
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
empirical workspace
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
##
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
##
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
empirical
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
empirical
|
|
453
|
-
empirical
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
##
|
|
466
|
-
|
|
467
|
-
empirical skill
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
##
|
|
483
|
-
|
|
484
|
-
empirical
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
\`
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
##
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const EMPIRICAL_MCP_NAME = 'empirical';
|
|
7
|
+
const EMPIRICAL_MCP_LEGACY_NAMES = ['empirical-live'];
|
|
8
|
+
const EMPIRICAL_MCP_URL = process.env.EMPIRICAL_MCP_URL || 'https://empirical.gauzza.com/mcp';
|
|
9
|
+
const COPILOT_OAUTH_CLIENT_ID = process.env.EMPIRICAL_COPILOT_OAUTH_CLIENT_ID || 'copilot-cli-empirical';
|
|
10
|
+
|
|
11
|
+
// These two lists mirror the schema-level enums in packages/shared/src/memoryGraph.ts.
|
|
12
|
+
// They are duplicated rather than imported on purpose: this CLI publishes to npm as
|
|
13
|
+
// @empirical-gauzza/cli, and @empirical/shared is a private workspace package, so depending
|
|
14
|
+
// on it would break `npm install` for end users. tests/unit/cliMemoryEnumParity.test.js
|
|
15
|
+
// fails CI if the copies ever diverge.
|
|
16
|
+
const MEMORY_CATEGORIES = [
|
|
17
|
+
'health', 'fitness', 'food', 'supplement', 'mood', 'idea', 'business',
|
|
18
|
+
'build', 'growth', 'learning', 'leadership', 'operations', 'workflow',
|
|
19
|
+
'lead', 'project', 'recipe', 'preference', 'reflection', 'relationship', 'heartbeat'
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const NODE_TYPES = [
|
|
23
|
+
'event', 'entity', 'observation', 'reflection', 'goal', 'concept'
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
const DOC_TOPICS = {
|
|
27
|
+
memory: `# Empirical Memory Commands
|
|
28
|
+
|
|
29
|
+
Use the \`empirical memory\` subcommands to query and manage memories via the REST API.
|
|
30
|
+
All commands require a valid access token (see \`empirical doc auth\`).
|
|
31
|
+
Errors are written to stderr as JSON. Successful output is written to stdout as JSON.
|
|
32
|
+
|
|
33
|
+
## Subcommands
|
|
34
|
+
|
|
35
|
+
### query
|
|
36
|
+
Search memories by natural language.
|
|
37
|
+
|
|
38
|
+
empirical memory query --match "coding style preferences" [--top-k 3] [--category build] [--tags ts,node] [--pretty] [--format table]
|
|
39
|
+
|
|
40
|
+
Flags:
|
|
41
|
+
- \`--match\` (required): natural language search string
|
|
42
|
+
- \`--top-k\`: number of results, 1–100, default 3
|
|
43
|
+
- \`--category\`: filter by category
|
|
44
|
+
- \`--tags\`: comma-separated tags filter
|
|
45
|
+
- \`--tags-all\`: comma-separated tags that must ALL be present (AND match)
|
|
46
|
+
- \`--status\`: comma-separated status values to keep (for example open,in_progress)
|
|
47
|
+
- \`--due-before\`, \`--due-after\`: keep only reminders due in that window (ISO 8601 dates).
|
|
48
|
+
"What is due?" is \`--due-before <now> --remind-state pending\`; dueness is a filter, never
|
|
49
|
+
something semantic ranking finds on its own
|
|
50
|
+
- \`--remind-state\`: comma-separated reminder states to keep: pending, notified, acknowledged, cancelled
|
|
51
|
+
- \`--path\`: pin one retrieval pathway (see below)
|
|
52
|
+
- \`--hops\`: 1 or 2, graph depth; only valid with \`--path graph\` or \`--path hebbian\`
|
|
53
|
+
- \`--pretty\`: pretty-print JSON output
|
|
54
|
+
- \`--format table\`: render results as a table instead of JSON (JSON stays the default)
|
|
55
|
+
|
|
56
|
+
#### Retrieval pathways
|
|
57
|
+
|
|
58
|
+
- \`--path semantic\`: ranked meaning match. Runs the embedding search and scores candidates.
|
|
59
|
+
Use it when you are asking a question and want the closest few answers.
|
|
60
|
+
- \`--path list\`: filtered browse. Skips ranking and returns the matching set in order, with
|
|
61
|
+
paging. Use it when you want everything carrying a tag, status, or category, not a top few.
|
|
62
|
+
- \`--path graph\`: relationship walk from the best entry points, out \`--hops\` steps. Use it
|
|
63
|
+
when what you want is connected to what you can name rather than worded like it.
|
|
64
|
+
- \`--path hebbian\`: co-recall walk, following the links that repeated retrieval strengthened.
|
|
65
|
+
Use it when you want what usually comes up alongside this, not what merely resembles it.
|
|
66
|
+
|
|
67
|
+
Omitting \`--path\` keeps the default, where the classifier decides which pathway answers.
|
|
68
|
+
|
|
69
|
+
### get
|
|
70
|
+
Retrieve one memory by exact ID.
|
|
71
|
+
|
|
72
|
+
empirical memory get --memory-id <id> [--pretty]
|
|
73
|
+
|
|
74
|
+
### list
|
|
75
|
+
Browse memories deterministically. Use \`--cursor\` from the previous response while \`pagination.hasMore\` is true.
|
|
76
|
+
|
|
77
|
+
empirical memory list [--category project] [--tags canonical,launch] [--start-date <ISO>] [--end-date <ISO>] [--limit 20] [--cursor <cursor>] [--oldest] [--pretty] [--format table]
|
|
78
|
+
|
|
79
|
+
Flags:
|
|
80
|
+
- \`--category\`, \`--tags\`: optional filters
|
|
81
|
+
- \`--start-date\`, \`--end-date\`: createdAt bounds
|
|
82
|
+
- \`--limit\`: page size, 1–100, default 20
|
|
83
|
+
- \`--cursor\`: continuation cursor from a previous page
|
|
84
|
+
- \`--oldest\`: sort oldest first; default is newest first
|
|
85
|
+
- \`--pretty\`: pretty-print JSON output
|
|
86
|
+
- \`--format table\`: render results as a table instead of JSON (JSON stays the default)
|
|
87
|
+
|
|
88
|
+
### acknowledge
|
|
89
|
+
Close a due reminder from the terminal.
|
|
90
|
+
|
|
91
|
+
empirical memory acknowledge --memory-id <id> [--cancel]
|
|
92
|
+
|
|
93
|
+
Marks the reminder done (or dropped, with \`--cancel\`), frees its slot on your plan, and clears
|
|
94
|
+
its alert on every surface so no agent keeps relaying it. The id is in the reminder banner.
|
|
95
|
+
|
|
96
|
+
### record
|
|
97
|
+
Save a new memory.
|
|
98
|
+
|
|
99
|
+
empirical memory record --category build --summary "Use ESM modules for all new packages" [--tags ts,node] [--node-type observation] [--author-type user|agent] [--due <ISO date>]
|
|
100
|
+
|
|
101
|
+
\`--due <ISO date>\` turns the memory into a REMINDER: at that time you get one email with a
|
|
102
|
+
calendar entry attached. Accepts 2026-10-14 or a full timestamp like 2026-10-14T09:00:00Z.
|
|
103
|
+
Any memory can carry one. Plans cap CONCURRENT pending reminders rather than how many you
|
|
104
|
+
create per month, so acknowledging or cancelling one frees a slot.
|
|
105
|
+
|
|
106
|
+
\`--author-type\` records WHO the fact belongs to, which the transport cannot know. Use
|
|
107
|
+
\`user\` for something the user said, decided or prefers; \`agent\` for your own session notes
|
|
108
|
+
and findings. Omitted, it is left unresolved rather than guessed. Retrieval reads it to keep
|
|
109
|
+
agent notes out of answers about the user's own life and work.
|
|
110
|
+
|
|
111
|
+
Passing text that contains code (backticks, \${...}, $(...)): do NOT put it in a double-quoted
|
|
112
|
+
\`--summary "..."\` -- the shell substitutes those away before the CLI runs and the write still
|
|
113
|
+
succeeds with the code silently missing. Use one of:
|
|
114
|
+
|
|
115
|
+
empirical memory record --category build --summary-file ./note.md --tags ts
|
|
116
|
+
empirical memory record --category build --summary - --tags ts <<'EOF'
|
|
117
|
+
Use \`createChat()\`; raw calls leak \${stage} and 400.
|
|
118
|
+
EOF
|
|
119
|
+
|
|
120
|
+
(a single-quoted heredoc delimiter, 'EOF', disables substitution). From an MCP-connected agent,
|
|
121
|
+
prefer the record_graph_memory tool, which takes JSON and never touches a shell.
|
|
122
|
+
|
|
123
|
+
Flags:
|
|
124
|
+
- \`--category\` (required unless --json-file): memory category
|
|
125
|
+
- \`--summary\` (required unless --summary-file/--json-file): memory summary text; \`-\` reads stdin
|
|
126
|
+
- \`--summary-file\`: path to a file whose contents become the summary (safe for code)
|
|
127
|
+
- \`--tags\`: comma-separated tags
|
|
128
|
+
- \`--node-type\`: node type, default \`observation\`
|
|
129
|
+
- \`--json-file\`: path to JSON file with full memory payload
|
|
130
|
+
|
|
131
|
+
Both \`--category\` and \`--node-type\` are closed sets. Do not guess a value: anything outside
|
|
132
|
+
these lists is rejected and the write does not happen.
|
|
133
|
+
|
|
134
|
+
Valid categories (20): health, fitness, food, supplement, mood, idea, business, build, growth,
|
|
135
|
+
learning, leadership, operations, workflow, lead, project, recipe, preference, reflection,
|
|
136
|
+
relationship, heartbeat.
|
|
137
|
+
|
|
138
|
+
Valid node types (6): event, entity, observation, reflection, goal, concept.
|
|
139
|
+
|
|
140
|
+
There is no \`product\` category and no \`decision\` node type. Record a decision as
|
|
141
|
+
\`--category project --node-type event\`.
|
|
142
|
+
|
|
143
|
+
### note
|
|
144
|
+
Add a note to an existing memory.
|
|
145
|
+
|
|
146
|
+
empirical memory note --match "ESM modules" --text "confirmed in monorepo migration" [--min-score 0.35]
|
|
147
|
+
|
|
148
|
+
Flags:
|
|
149
|
+
- \`--match\` (required unless --memory-id): search string to find the memory
|
|
150
|
+
- \`--text\` (required): note text to append
|
|
151
|
+
- \`--memory-id\`: use exact memory ID (skips fuzzy search)
|
|
152
|
+
- \`--min-score\`: minimum similarity score, default 0.35
|
|
153
|
+
|
|
154
|
+
### update
|
|
155
|
+
Update an existing memory.
|
|
156
|
+
|
|
157
|
+
empirical memory update --match "ESM modules" --patch-json '{"summary":"Updated summary"}' [--min-score 0.35]
|
|
158
|
+
|
|
159
|
+
Flags:
|
|
160
|
+
- \`--match\` (required unless --memory-id): search string
|
|
161
|
+
- \`--patch-json\`: JSON string with fields to update
|
|
162
|
+
- \`--json-file\`: path to JSON patch file
|
|
163
|
+
- \`--memory-id\`: use exact memory ID
|
|
164
|
+
- \`--min-score\`: minimum similarity score, default 0.35
|
|
165
|
+
|
|
166
|
+
### delete
|
|
167
|
+
Delete a memory. Without --confirm, runs a dry-run and prints what would be deleted.
|
|
168
|
+
|
|
169
|
+
empirical memory delete --match "old preference" --confirm [--min-score 0.35]
|
|
170
|
+
|
|
171
|
+
Flags:
|
|
172
|
+
- \`--match\` (required unless --memory-id): search string
|
|
173
|
+
- \`--confirm\`: actually delete (without this, dry-run only)
|
|
174
|
+
- \`--memory-id\`: use exact memory ID
|
|
175
|
+
- \`--min-score\`: minimum similarity score, default 0.35
|
|
176
|
+
|
|
177
|
+
Bulk delete by tag, category, or everything (exactly one selector):
|
|
178
|
+
|
|
179
|
+
empirical memory delete --tag old-preference --confirm
|
|
180
|
+
empirical memory delete --category recipe --confirm
|
|
181
|
+
empirical memory delete --all --confirm
|
|
182
|
+
|
|
183
|
+
Without \`--confirm\`, always a dry-run that prints the count that would be deleted; no writes
|
|
184
|
+
happen. Re-run with \`--confirm\` to actually delete.
|
|
185
|
+
|
|
186
|
+
### export / import
|
|
187
|
+
Export memories to a versioned, round-trippable JSON document and re-import them later.
|
|
188
|
+
|
|
189
|
+
empirical memory export --scope <personal|workspace> [--out <path>] [--workspace-id <id>]
|
|
190
|
+
empirical memory import <file> [--dry-run]
|
|
191
|
+
|
|
192
|
+
Export writes \`{ schemaVersion: 1, exportedAt, memories: [...] }\`. Import reads that same
|
|
193
|
+
shape and POSTs each row through the normal create endpoint, so imported memories get the same
|
|
194
|
+
dedupe and auto-link treatment as any other write. \`--dry-run\` on import prints the count that
|
|
195
|
+
would be imported without writing anything.
|
|
196
|
+
|
|
197
|
+
### stats
|
|
198
|
+
Aggregated counts, scoped to the caller.
|
|
199
|
+
|
|
200
|
+
empirical memory stats [--format table]
|
|
201
|
+
|
|
202
|
+
Returns total count, counts by category, counts by tag, and oldest/newest memory timestamps.
|
|
203
|
+
|
|
204
|
+
### compact
|
|
205
|
+
On-demand near-duplicate scan (the same logic the nightly compaction job runs), scoped to the
|
|
206
|
+
caller only. Dry-run by default, matching a terraform plan/apply model.
|
|
207
|
+
|
|
208
|
+
empirical memory compact [--category <cat>]
|
|
209
|
+
empirical memory compact --apply [--category <cat>]
|
|
210
|
+
|
|
211
|
+
Without \`--apply\`, reports proposed merge/link candidate pairs and counts with no writes.
|
|
212
|
+
With \`--apply\`, executes the merges and links for real and reports what was applied.
|
|
213
|
+
|
|
214
|
+
## Error output contract
|
|
215
|
+
- Errors → stderr as JSON: \`{ "error": true, "code": "...", "message": "..." }\`
|
|
216
|
+
- Success → stdout as JSON (compact by default)
|
|
217
|
+
`,
|
|
218
|
+
|
|
219
|
+
install: `# Empirical Install
|
|
220
|
+
|
|
221
|
+
empirical install
|
|
222
|
+
|
|
223
|
+
Runs the interactive installer to connect Empirical memory to your AI coding CLI(s).
|
|
224
|
+
|
|
225
|
+
## What it does
|
|
226
|
+
1. Detects installed CLIs: Codex, GitHub Copilot, Claude Code
|
|
227
|
+
2. Prompts for CLI target selection
|
|
228
|
+
3. Asks how agents should interact with Empirical:
|
|
229
|
+
- Mode 1: Via MCP tool (recommended) — registers Empirical as an MCP server
|
|
230
|
+
- Mode 2: Via CLI commands — writes CLI-direct instruction block, no MCP registration
|
|
231
|
+
- Mode 3: Both — MCP primary with CLI fallback
|
|
232
|
+
4. Stores the personalized behavior policy for the native Empirical Memory Skill; global
|
|
233
|
+
instruction files are left unchanged
|
|
234
|
+
5. Offers optional browser OAuth login for CLI use, optional headless/API-key bootstrap for
|
|
235
|
+
automation, containers, and external runtimes, and optional work-history/scar-tissue guidance
|
|
236
|
+
6. Installs a \`SessionStart\` hook for each selected client that calls the \`empirical\` CLI
|
|
237
|
+
directly once per session — deterministic baseline context that doesn't depend on the model
|
|
238
|
+
deciding to call a tool. Claude: \`~/.claude/settings.json\`. Codex: \`<CODEX_HOME>/hooks.json\`
|
|
239
|
+
(defaults to \`~/.codex\`). Copilot: \`~/.copilot/hooks/empirical-session-start.json\`.
|
|
240
|
+
7. Installs the native \`empirical-memory\` plugin for each selected client. The plugin owns
|
|
241
|
+
the Empirical MCP connection and all agent-facing Skills; the CLI does not generate duplicate
|
|
242
|
+
\`SKILL.md\` or \`EMPIRICAL_SKILL.md\` files.
|
|
243
|
+
|
|
244
|
+
## Native plugin only
|
|
245
|
+
|
|
246
|
+
empirical plugin install <codex|copilot|claude|all> [--all-optional]
|
|
247
|
+
|
|
248
|
+
empirical plugin check [--force]
|
|
249
|
+
|
|
250
|
+
Installs or refreshes only the native marketplace plugin. It does not run the MCP/auth questionnaire
|
|
251
|
+
or modify global instruction files. With no target, the command installs for detected CLIs.
|
|
252
|
+
|
|
253
|
+
The CLI performs a best-effort native plugin version check during interactive use (at most once per
|
|
254
|
+
day). It is silent for noninteractive/headless commands. Use \`empirical plugin check --force\` to
|
|
255
|
+
check immediately.
|
|
256
|
+
|
|
257
|
+
Use \`empirical policy show\` to inspect the current native-skill behavior policy and
|
|
258
|
+
\`empirical policy set --json '{"allowDiscretionaryUse":false}'\` to change it without rerunning
|
|
259
|
+
the installer. The policy is cached locally and refreshed when stale.
|
|
260
|
+
`,
|
|
261
|
+
|
|
262
|
+
workspace: `# Empirical Workspace Commands
|
|
263
|
+
|
|
264
|
+
Manage disposable team workspaces and which Empirical workspace is active for this OAuth client.
|
|
265
|
+
|
|
266
|
+
## Commands
|
|
267
|
+
|
|
268
|
+
### List workspaces
|
|
269
|
+
|
|
270
|
+
empirical workspace list
|
|
271
|
+
|
|
272
|
+
Shows all available workspaces and which one is currently selected.
|
|
273
|
+
|
|
274
|
+
### Show current workspace
|
|
275
|
+
|
|
276
|
+
empirical workspace current
|
|
277
|
+
|
|
278
|
+
Prints the currently selected workspace name.
|
|
279
|
+
|
|
280
|
+
### Select a workspace
|
|
281
|
+
|
|
282
|
+
empirical workspace select [<number|name>]
|
|
283
|
+
|
|
284
|
+
Interactive workspace selector (prompts if no argument given).
|
|
285
|
+
Pass a number (from \`list\`) or an exact workspace name.
|
|
286
|
+
|
|
287
|
+
empirical workspace select 2
|
|
288
|
+
empirical workspace select "My Workspace"
|
|
289
|
+
|
|
290
|
+
Note: workspace selection may be admin-locked for some OAuth clients.
|
|
291
|
+
|
|
292
|
+
### Create a demo workspace
|
|
293
|
+
|
|
294
|
+
empirical workspace create "Demo Workspace" --description "Temporary shared context"
|
|
295
|
+
|
|
296
|
+
Creates a team workspace using your existing plan quota and prints its workspace ID.
|
|
297
|
+
|
|
298
|
+
### Use a workspace
|
|
299
|
+
|
|
300
|
+
empirical workspace use <number|name|id>
|
|
301
|
+
|
|
302
|
+
Friendly alias for \`workspace select\`. It accepts the list number, exact case-insensitive name, or workspace ID.
|
|
303
|
+
|
|
304
|
+
### Share an active workspace
|
|
305
|
+
|
|
306
|
+
empirical workspace invite create --role writer --expires-in-days 7 --max-uses 3
|
|
307
|
+
empirical workspace invite list
|
|
308
|
+
empirical workspace invite revoke <token>
|
|
309
|
+
|
|
310
|
+
Invite commands operate on the active team workspace. Create prints a shareable URL.
|
|
311
|
+
|
|
312
|
+
### Soft-delete a demo workspace
|
|
313
|
+
|
|
314
|
+
empirical workspace delete <number|name|id>
|
|
315
|
+
empirical workspace delete <number|name|id> --confirm
|
|
316
|
+
|
|
317
|
+
Deletion dry-runs by default. \`--confirm\` calls the existing soft-delete endpoint; the Default Workspace cannot be deleted. If the active workspace is deleted, the CLI selects the Default Workspace.
|
|
318
|
+
`,
|
|
319
|
+
|
|
320
|
+
doctor: `# Empirical Doctor
|
|
321
|
+
|
|
322
|
+
empirical doctor [--output json] [--deep]
|
|
323
|
+
|
|
324
|
+
Checks the health of your Empirical CLI setup, including why MCP tools might not be showing up
|
|
325
|
+
in a host CLI (the most common failure report).
|
|
326
|
+
|
|
327
|
+
## Checks performed
|
|
328
|
+
|
|
329
|
+
1. **Token presence** — verifies a token exists via EMPIRICAL_ACCESS_TOKEN env, apiKey field,
|
|
330
|
+
or accessToken field in the token file
|
|
331
|
+
2. **Token type** — detects API key (long alphanumeric, no dots) vs JWT (3 dot-separated parts)
|
|
332
|
+
3. **Token expiry** — if JWT, decodes the payload and checks the \`exp\` field; warns if no \`exp\`
|
|
333
|
+
4. **API connectivity** — calls GET /api/v1/users/me; 200 = OK, anything else = FAIL
|
|
334
|
+
5. **Workspace** — reads workspaceId from the /api/v1/users/me response; warns if null
|
|
335
|
+
6. **MCP hosts detected** — which of codex/claude/copilot were found on this machine
|
|
336
|
+
7. **MCP config registration (per detected host)** — reads that host's own config file
|
|
337
|
+
(\`~/.claude.json\`, \`<CODEX_HOME>/config.toml\`, \`~/.copilot/mcp-config.json\`) and confirms
|
|
338
|
+
the Empirical MCP server is actually registered there with the current URL
|
|
339
|
+
8. **MCP reachability** — POSTs a real MCP \`initialize\` request to the MCP endpoint with the
|
|
340
|
+
resolved access token and confirms a valid JSON-RPC response comes back
|
|
341
|
+
9. **Native plugin presence/version (per detected host)** — runs \`<host> plugin list\` and
|
|
342
|
+
reports the installed empirical-memory (and optional) plugin versions
|
|
343
|
+
10. **Hooks presence (per detected host)** — confirms the SessionStart/UserPromptSubmit/Stop
|
|
344
|
+
hook scripts exist on disk and are registered in that host's hook manifest
|
|
345
|
+
|
|
346
|
+
## --deep
|
|
347
|
+
|
|
348
|
+
Adds a live write/query/delete round trip: records a \`doctor-probe-<timestamp>\` memory, queries
|
|
349
|
+
it back, deletes it, and reports elapsed time for each leg. Requires a valid token; writes and
|
|
350
|
+
deletes exactly one throwaway memory tagged \`doctor-probe\`.
|
|
351
|
+
|
|
352
|
+
## Output format
|
|
353
|
+
|
|
354
|
+
Default: human-readable lines prefixed with [OK], [WARN], or [FAIL].
|
|
355
|
+
|
|
356
|
+
empirical doctor --output json
|
|
357
|
+
|
|
358
|
+
JSON output: \`{ "checks": [{ "name", "status", "message" }], "overall": "ok"|"warn"|"fail" }\`
|
|
359
|
+
Useful for agent/automation use.
|
|
360
|
+
|
|
361
|
+
## Exit codes
|
|
362
|
+
- 0: all checks passed (ok or warn)
|
|
363
|
+
- 1: one or more checks failed
|
|
364
|
+
`,
|
|
365
|
+
|
|
366
|
+
agents: `# Empirical Agent Integration
|
|
367
|
+
|
|
368
|
+
Empirical memory integrates with three AI coding CLIs.
|
|
369
|
+
|
|
370
|
+
## Supported agents
|
|
371
|
+
|
|
372
|
+
| Agent | Config dir | Instruction file | MCP config |
|
|
373
|
+
|-------------|---------------------|-------------------------------|-------------------------------------|
|
|
374
|
+
| Claude Code | ~/.claude/ | CLAUDE.md | ~/.claude.json (mcpServers) |
|
|
375
|
+
| Codex CLI | ~/.codex/ | AGENTS.md | codex mcp add |
|
|
376
|
+
| Copilot CLI | ~/.copilot/ | copilot-instructions.md | ~/.copilot/mcp-config.json |
|
|
377
|
+
|
|
378
|
+
## Integration modes
|
|
379
|
+
|
|
380
|
+
**Mode 1: MCP tool (recommended)**
|
|
381
|
+
Empirical is registered as an MCP server. Agents call memory tools (query_memories,
|
|
382
|
+
record_graph_memory, etc.) directly via the MCP protocol. Best for interactive sessions.
|
|
383
|
+
|
|
384
|
+
**Mode 2: CLI commands**
|
|
385
|
+
Agents run \`empirical memory <subcommand>\` shell commands. No MCP registration required.
|
|
386
|
+
Suitable for headless/scripted environments or when MCP is unavailable.
|
|
387
|
+
|
|
388
|
+
**Mode 3: Both**
|
|
389
|
+
MCP is primary; CLI commands are available as fallback. Maximizes reliability.
|
|
390
|
+
|
|
391
|
+
## Inventory commands
|
|
392
|
+
|
|
393
|
+
empirical skill list
|
|
394
|
+
empirical device list
|
|
395
|
+
empirical device show <deviceId>
|
|
396
|
+
|
|
397
|
+
Use these to inspect Skills across Kits and the effective Skills installed for a device.
|
|
398
|
+
|
|
399
|
+
The native \`empirical-memory\` plugin owns its Skills and MCP connection. Run
|
|
400
|
+
\`empirical install\` to install it and configure detected agents.
|
|
401
|
+
`,
|
|
402
|
+
|
|
403
|
+
kit: `# Empirical Skills Kits
|
|
404
|
+
|
|
405
|
+
Kits are named collections of agent Skills. A Kit can contain Skills authored in Empirical
|
|
406
|
+
or discovered from a git repository, then sync the resolved set to your local agents.
|
|
407
|
+
|
|
408
|
+
## Commands
|
|
409
|
+
|
|
410
|
+
### Create and list Kits
|
|
411
|
+
|
|
412
|
+
empirical kit create "My Team Kit"
|
|
413
|
+
empirical kit list
|
|
414
|
+
|
|
415
|
+
### Add or remove a git source
|
|
416
|
+
|
|
417
|
+
empirical kit add-source "My Team Kit" https://github.com/example/skills.git
|
|
418
|
+
empirical kit add-source "My Team Kit" https://github.com/example/skills.git --ref main --path skills
|
|
419
|
+
empirical kit remove-source "My Team Kit" <source-id>
|
|
420
|
+
|
|
421
|
+
Each source is scanned for valid \`SKILL.md\` files. A Skill file must begin with YAML
|
|
422
|
+
frontmatter containing both \`name\` and \`description\`, for example:
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
name: my-skill
|
|
426
|
+
description: Explain when this skill should be used.
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
### Activate and sync
|
|
430
|
+
|
|
431
|
+
empirical kit use "My Team Kit"
|
|
432
|
+
empirical kit sync
|
|
433
|
+
empirical kit sync --dry-run
|
|
434
|
+
|
|
435
|
+
\`kit use\` activates a Kit on this device and syncs its Skills into detected agent
|
|
436
|
+
directories. \`kit sync\` refreshes the active Kit. Use \`--quiet\` for unattended syncs
|
|
437
|
+
and \`--force\` only when you intentionally want to bypass the local-edit guard.
|
|
438
|
+
|
|
439
|
+
### Inventory
|
|
440
|
+
|
|
441
|
+
empirical skill list
|
|
442
|
+
empirical kit list
|
|
443
|
+
empirical kit devices "My Team Kit"
|
|
444
|
+
empirical device list
|
|
445
|
+
empirical device show <deviceId>
|
|
446
|
+
|
|
447
|
+
\`skill list\` shows Skills resolved from owned Kits. \`device list\` shows registered devices and
|
|
448
|
+
their active Kits; \`device show\` shows the effective resolved Skills for one device.
|
|
449
|
+
|
|
450
|
+
### Manage devices and autosync
|
|
451
|
+
|
|
452
|
+
empirical kit autosync "My Team Kit" on
|
|
453
|
+
empirical kit devices "My Team Kit"
|
|
454
|
+
empirical kit deactivate "My Team Kit" <device-id>
|
|
455
|
+
|
|
456
|
+
Autosync keeps a registered device current. Interactive syncs review new or changed external
|
|
457
|
+
Skills; unattended syncs apply them and leave a review marker for the next interactive sync.
|
|
458
|
+
`,
|
|
459
|
+
|
|
460
|
+
skill: `# Empirical Skills
|
|
461
|
+
|
|
462
|
+
Skills are agent-facing \`SKILL.md\` instruction files. Authored Skills can be pushed into a
|
|
463
|
+
Kit so they follow you across machines and projects.
|
|
464
|
+
|
|
465
|
+
## Push an authored Skill
|
|
466
|
+
|
|
467
|
+
empirical skill list
|
|
468
|
+
|
|
469
|
+
empirical skill push path/to/SKILL.md
|
|
470
|
+
empirical skill push path/to/SKILL.md --kit "My Team Kit"
|
|
471
|
+
|
|
472
|
+
The file must contain YAML frontmatter at the top with both required fields:
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
name: my-skill
|
|
476
|
+
description: Explain when this skill should be used.
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
The remainder of the file is the Skill body. The CLI validates the frontmatter before upload.
|
|
480
|
+
After pushing, activate or sync the target Kit with \`empirical kit use\` or \`empirical kit sync\`.
|
|
481
|
+
|
|
482
|
+
## Review and rollback
|
|
483
|
+
|
|
484
|
+
empirical skill history <authored-skill-id>
|
|
485
|
+
empirical skill rollback <authored-skill-id> --to-version 2
|
|
486
|
+
|
|
487
|
+
Use history to inspect versions and rollback to a known-good version when a Skill needs to be
|
|
488
|
+
reverted. External git-sourced Skills are reviewed during Kit sync and are not authored with
|
|
489
|
+
this command.
|
|
490
|
+
`,
|
|
491
|
+
|
|
492
|
+
auth: `# Empirical Auth
|
|
493
|
+
|
|
494
|
+
## Token types
|
|
495
|
+
|
|
496
|
+
**API key**: Long alphanumeric string, no dots. Never expires. Preferred for automation.
|
|
497
|
+
**JWT**: Three dot-separated base64 parts. Has an expiry (\`exp\` claim). Used for browser OAuth flows.
|
|
498
|
+
|
|
499
|
+
## Browser OAuth login
|
|
500
|
+
|
|
501
|
+
empirical auth login
|
|
502
|
+
|
|
503
|
+
Opens the browser, completes OAuth with the Empirical account, and saves a CLI session at
|
|
504
|
+
\`~/.empirical/oauth-session.json\`. Use this for normal interactive CLI use when you do not
|
|
505
|
+
want to provision a permanent API key.
|
|
506
|
+
|
|
507
|
+
## Logging out (and actually revoking)
|
|
508
|
+
|
|
509
|
+
empirical auth logout # revoke refresh tokens server-side, then clear locally
|
|
510
|
+
empirical auth logout --local-only # forget this machine only, leave other clients signed in
|
|
511
|
+
empirical auth logout --client-id <id> # revoke just one client's refresh tokens
|
|
512
|
+
|
|
513
|
+
Plain \`logout\` calls \`DELETE /api/v1/users/me/refresh-tokens\`, so the session ends on the
|
|
514
|
+
server and not merely on disk. This matters because refresh tokens are written without an
|
|
515
|
+
expiry: before this existed, a leaked refresh token stayed redeemable forever and no command,
|
|
516
|
+
endpoint or portal screen could revoke it.
|
|
517
|
+
|
|
518
|
+
## Managing API keys
|
|
519
|
+
|
|
520
|
+
empirical auth list-keys # ids, labels, created dates
|
|
521
|
+
empirical auth rotate-key [--label <name>] # mint an ADDITIONAL key, others keep working
|
|
522
|
+
empirical auth rotate-key --replace-all # destructive: wipe every key, mint exactly one
|
|
523
|
+
empirical auth revoke-key --key-id <id> # revoke one key
|
|
524
|
+
empirical auth revoke-key --all # revoke every key on the account
|
|
525
|
+
|
|
526
|
+
Rotating without \`--replace-all\` is the safe cutover: mint the new key, move your integrations
|
|
527
|
+
over, then \`revoke-key --key-id\` the old one. A key is displayed once at mint time; only its
|
|
528
|
+
hash is stored, so there is no way to read it back later.
|
|
529
|
+
|
|
530
|
+
Minting requires a signed-in session (browser login or a fresh OAuth session), because a
|
|
531
|
+
permanent API key must not be able to mint more credentials. Revoking does not: it only ever
|
|
532
|
+
reduces access, and the CLI needs to be able to revoke with the credential it already holds.
|
|
533
|
+
|
|
534
|
+
## Bootstrap command (headless / non-interactive)
|
|
535
|
+
|
|
536
|
+
empirical oauth bootstrap headless --write-env
|
|
537
|
+
|
|
538
|
+
Exchanges account credentials (client ID + secret, i.e. your userId + API key) for an access
|
|
539
|
+
token via \`grant_type=client_credentials\` — this is NOT a dynamically-registered OAuth client;
|
|
540
|
+
the server treats client_id/client_secret as userId/apiKey directly.
|
|
541
|
+
Writes token to \`.empirical/headless-token.json\` and \`.empirical/headless.env\`.
|
|
542
|
+
|
|
543
|
+
No portal visit or manual copy/paste needed: if no client ID/secret is found via
|
|
544
|
+
\`EMPIRICAL_CLIENT_ID\`/\`EMPIRICAL_CLIENT_SECRET\` env vars or \`~/.empirical/oauth-client.json\`
|
|
545
|
+
(set via \`empirical oauth client set\`), the CLI self-provisions your account's API key via
|
|
546
|
+
\`POST /api/v1/users/me/credentials\`, authenticated with whatever bearer token it already has
|
|
547
|
+
(existing token file, or — only if nothing exists yet — one browser login). If you already have
|
|
548
|
+
an API key on the account, the CLI will never silently rotate it (that would break other
|
|
549
|
+
integrations using it); it asks for explicit confirmation in a TTY, or gives up quietly in
|
|
550
|
+
non-interactive contexts. If a stored client is rejected by the server ("Invalid client
|
|
551
|
+
credentials"), the CLI discards it and re-provisions automatically on the same run — unless
|
|
552
|
+
\`--client-id\`/\`--client-secret\` was passed explicitly, in which case the error is surfaced
|
|
553
|
+
as-is.
|
|
554
|
+
|
|
555
|
+
## Refresh command
|
|
556
|
+
|
|
557
|
+
empirical oauth refresh headless
|
|
558
|
+
|
|
559
|
+
Exchanges a stored refresh token for a new access token. Token file must exist.
|
|
560
|
+
|
|
561
|
+
## Token resolution priority (resolveAccessToken)
|
|
562
|
+
|
|
563
|
+
1. \`EMPIRICAL_ACCESS_TOKEN\` environment variable (skipped if it's an expired JWT, so a
|
|
564
|
+
stale session token can never permanently shadow a valid credential below it)
|
|
565
|
+
2. \`apiKey\` field in token file
|
|
566
|
+
3. \`accessToken\` field in token file
|
|
567
|
+
4. \`~/.empirical/oauth-session.json\` browser OAuth session
|
|
568
|
+
5. \`EMPIRICAL_API_KEY\` or \`EMPIRICAL_CLIENT_SECRET\` environment variable, used directly
|
|
569
|
+
as a permanent Bearer credential — lets a stateless agent environment authenticate from
|
|
570
|
+
client_id/secret alone with no token file and no bootstrap step
|
|
571
|
+
|
|
572
|
+
Token file lookup order:
|
|
573
|
+
1. Path in \`EMPIRICAL_TOKEN_OUTPUT\` env var
|
|
574
|
+
2. \`.empirical/headless-token.json\` (current working directory)
|
|
575
|
+
3. \`~/.empirical/headless-token.json\` (home directory)
|
|
576
|
+
|
|
577
|
+
The browser OAuth session is stored separately at \`~/.empirical/oauth-session.json\`.
|
|
578
|
+
|
|
579
|
+
## Verify auth status
|
|
580
|
+
|
|
581
|
+
empirical auth status
|
|
582
|
+
empirical whoami
|
|
583
|
+
|
|
584
|
+
Prints a single JSON object: \`{ authenticated, tokenPresent, tokenType, tokenExpiresAt,
|
|
585
|
+
tokenExpired, user: { id, email } | null, workspaceId, error }\`. \`whoami\` is an alias for
|
|
586
|
+
\`auth status\`. Exits 1 if not authenticated.
|
|
587
|
+
|
|
588
|
+
empirical doctor
|
|
589
|
+
|
|
590
|
+
Checks token presence, type, expiry, and API connectivity across a broader set of checks
|
|
591
|
+
(host MCP config registration, hooks, plugin versions).
|
|
592
|
+
`,
|
|
593
|
+
|
|
594
|
+
user: `# Empirical User Identity
|
|
595
|
+
|
|
596
|
+
## Via MCP (when Empirical MCP server is connected)
|
|
597
|
+
|
|
598
|
+
Use the \`get_user\` MCP tool. Returns: id, email, name, workspaceId, tier, and plan details.
|
|
599
|
+
|
|
600
|
+
## Via CLI
|
|
601
|
+
|
|
602
|
+
empirical doctor --output json
|
|
603
|
+
|
|
604
|
+
Returns a JSON object with a \`checks\` array. The connectivity check (name: "api")
|
|
605
|
+
includes the user record from /api/users/me when successful.
|
|
606
|
+
|
|
607
|
+
empirical workspace current
|
|
608
|
+
|
|
609
|
+
Prints the active workspace name.
|
|
610
|
+
|
|
611
|
+
## Notes
|
|
612
|
+
|
|
613
|
+
- \`get_user\` has no standalone CLI subcommand; use \`empirical doctor --output json\` to
|
|
614
|
+
inspect identity from the shell.
|
|
615
|
+
- If MCP is unavailable, parse the \`api\` check from doctor JSON output for user context.
|
|
616
|
+
`
|
|
617
|
+
};
|
|
618
|
+
|
|
619
|
+
let cachedCliVersion = null;
|
|
620
|
+
|
|
621
|
+
function getCliVersion() {
|
|
622
|
+
if (cachedCliVersion) return cachedCliVersion;
|
|
623
|
+
try {
|
|
624
|
+
const cliPackagePath = path.join(__dirname, '..', 'package.json');
|
|
625
|
+
const parsed = JSON.parse(fs.readFileSync(cliPackagePath, 'utf8'));
|
|
626
|
+
if (parsed && typeof parsed.version === 'string' && parsed.version.trim()) {
|
|
627
|
+
cachedCliVersion = parsed.version.trim();
|
|
628
|
+
return cachedCliVersion;
|
|
629
|
+
}
|
|
630
|
+
} catch (_error) {
|
|
631
|
+
// ignore and use fallback
|
|
632
|
+
}
|
|
633
|
+
cachedCliVersion = 'unknown';
|
|
634
|
+
return cachedCliVersion;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
function deriveBaseUrlFromMcpUrl() {
|
|
638
|
+
try {
|
|
639
|
+
const parsed = new URL(EMPIRICAL_MCP_URL);
|
|
640
|
+
parsed.pathname = parsed.pathname.replace(/\/mcp\/?$/, '');
|
|
641
|
+
return parsed.origin + parsed.pathname.replace(/\/$/, '');
|
|
642
|
+
} catch (_error) {
|
|
643
|
+
return '';
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
module.exports = {
|
|
648
|
+
EMPIRICAL_MCP_NAME,
|
|
649
|
+
EMPIRICAL_MCP_LEGACY_NAMES,
|
|
650
|
+
EMPIRICAL_MCP_URL,
|
|
651
|
+
COPILOT_OAUTH_CLIENT_ID,
|
|
652
|
+
MEMORY_CATEGORIES,
|
|
653
|
+
NODE_TYPES,
|
|
654
|
+
DOC_TOPICS,
|
|
655
|
+
getCliVersion,
|
|
656
|
+
deriveBaseUrlFromMcpUrl
|
|
657
|
+
};
|