engrm 0.1.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 (82) hide show
  1. package/.mcp.json +9 -0
  2. package/AUTH-DESIGN.md +436 -0
  3. package/BRIEF.md +197 -0
  4. package/CLAUDE.md +44 -0
  5. package/COMPETITIVE.md +174 -0
  6. package/CONTEXT-OPTIMIZATION.md +305 -0
  7. package/INFRASTRUCTURE.md +252 -0
  8. package/LICENSE +105 -0
  9. package/MARKET.md +230 -0
  10. package/PLAN.md +278 -0
  11. package/README.md +121 -0
  12. package/SENTINEL.md +293 -0
  13. package/SERVER-API-PLAN.md +553 -0
  14. package/SPEC.md +843 -0
  15. package/SWOT.md +148 -0
  16. package/SYNC-ARCHITECTURE.md +294 -0
  17. package/VIBE-CODER-STRATEGY.md +250 -0
  18. package/bun.lock +375 -0
  19. package/hooks/post-tool-use.ts +144 -0
  20. package/hooks/session-start.ts +64 -0
  21. package/hooks/stop.ts +131 -0
  22. package/mem-page.html +1305 -0
  23. package/package.json +30 -0
  24. package/src/capture/dedup.test.ts +103 -0
  25. package/src/capture/dedup.ts +76 -0
  26. package/src/capture/extractor.test.ts +245 -0
  27. package/src/capture/extractor.ts +330 -0
  28. package/src/capture/quality.test.ts +168 -0
  29. package/src/capture/quality.ts +104 -0
  30. package/src/capture/retrospective.test.ts +115 -0
  31. package/src/capture/retrospective.ts +121 -0
  32. package/src/capture/scanner.test.ts +131 -0
  33. package/src/capture/scanner.ts +100 -0
  34. package/src/capture/scrubber.test.ts +144 -0
  35. package/src/capture/scrubber.ts +181 -0
  36. package/src/cli.ts +517 -0
  37. package/src/config.ts +238 -0
  38. package/src/context/inject.test.ts +940 -0
  39. package/src/context/inject.ts +382 -0
  40. package/src/embeddings/backfill.ts +50 -0
  41. package/src/embeddings/embedder.test.ts +76 -0
  42. package/src/embeddings/embedder.ts +139 -0
  43. package/src/lifecycle/aging.test.ts +103 -0
  44. package/src/lifecycle/aging.ts +36 -0
  45. package/src/lifecycle/compaction.test.ts +264 -0
  46. package/src/lifecycle/compaction.ts +190 -0
  47. package/src/lifecycle/purge.test.ts +100 -0
  48. package/src/lifecycle/purge.ts +37 -0
  49. package/src/lifecycle/scheduler.test.ts +120 -0
  50. package/src/lifecycle/scheduler.ts +101 -0
  51. package/src/provisioning/browser-auth.ts +172 -0
  52. package/src/provisioning/provision.test.ts +198 -0
  53. package/src/provisioning/provision.ts +94 -0
  54. package/src/register.test.ts +167 -0
  55. package/src/register.ts +178 -0
  56. package/src/server.ts +436 -0
  57. package/src/storage/migrations.test.ts +244 -0
  58. package/src/storage/migrations.ts +261 -0
  59. package/src/storage/outbox.test.ts +229 -0
  60. package/src/storage/outbox.ts +131 -0
  61. package/src/storage/projects.test.ts +137 -0
  62. package/src/storage/projects.ts +184 -0
  63. package/src/storage/sqlite.test.ts +798 -0
  64. package/src/storage/sqlite.ts +934 -0
  65. package/src/storage/vec.test.ts +198 -0
  66. package/src/sync/auth.test.ts +76 -0
  67. package/src/sync/auth.ts +68 -0
  68. package/src/sync/client.ts +183 -0
  69. package/src/sync/engine.test.ts +94 -0
  70. package/src/sync/engine.ts +127 -0
  71. package/src/sync/pull.test.ts +279 -0
  72. package/src/sync/pull.ts +170 -0
  73. package/src/sync/push.test.ts +117 -0
  74. package/src/sync/push.ts +230 -0
  75. package/src/tools/get.ts +34 -0
  76. package/src/tools/pin.ts +47 -0
  77. package/src/tools/save.test.ts +301 -0
  78. package/src/tools/save.ts +231 -0
  79. package/src/tools/search.test.ts +69 -0
  80. package/src/tools/search.ts +181 -0
  81. package/src/tools/timeline.ts +64 -0
  82. package/tsconfig.json +22 -0
package/mem-page.html ADDED
@@ -0,0 +1,1305 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Engrm — AI Memory for Developers</title>
7
+ <meta name="description" content="Cross-device, team-shared memory for AI coding agents. Every discovery, decision, and bugfix — captured automatically, available everywhere.">
8
+
9
+ <!-- Open Graph -->
10
+ <meta property="og:type" content="website">
11
+ <meta property="og:title" content="Engrm — AI Memory for Developers">
12
+ <meta property="og:description" content="Cross-device, team-shared memory for AI coding agents. Every discovery, decision, and bugfix — captured automatically, available everywhere.">
13
+ <meta property="og:url" content="https://engrm.dev">
14
+ <meta property="og:site_name" content="Candengo">
15
+
16
+ <!-- Twitter Card -->
17
+ <meta name="twitter:card" content="summary_large_image">
18
+ <meta name="twitter:title" content="Engrm — AI Memory for Developers">
19
+ <meta name="twitter:description" content="Cross-device, team-shared memory for AI coding agents. Every discovery, decision, and bugfix — captured automatically, available everywhere.">
20
+
21
+ <!-- Structured Data -->
22
+ <script type="application/ld+json">
23
+ {
24
+ "@context": "https://schema.org",
25
+ "@type": "SoftwareApplication",
26
+ "name": "Engrm",
27
+ "applicationCategory": "DeveloperApplication",
28
+ "operatingSystem": "macOS, Linux, Windows",
29
+ "description": "Cross-device, team-shared memory for AI coding agents. Captures observations from AI-assisted coding sessions and syncs them via Candengo Vector.",
30
+ "offers": [
31
+ {
32
+ "@type": "Offer",
33
+ "price": "0",
34
+ "priceCurrency": "USD",
35
+ "name": "Free"
36
+ },
37
+ {
38
+ "@type": "Offer",
39
+ "price": "12",
40
+ "priceCurrency": "USD",
41
+ "name": "Pro",
42
+ "billingIncrement": "P1M"
43
+ },
44
+ {
45
+ "@type": "Offer",
46
+ "price": "8",
47
+ "priceCurrency": "USD",
48
+ "name": "Team",
49
+ "billingIncrement": "P1M"
50
+ }
51
+ ],
52
+ "provider": {
53
+ "@type": "Organization",
54
+ "name": "Candengo",
55
+ "url": "https://candengo.com"
56
+ }
57
+ }
58
+ </script>
59
+
60
+ <style>
61
+ :root {
62
+ --primary: #00d4ff;
63
+ --secondary: #7b2cbf;
64
+ --accent: #f59e0b;
65
+ --emerald: #10b981;
66
+ --bg-dark: #06060e;
67
+ --bg-mid: #0c0c1e;
68
+ --bg-card: rgba(255,255,255,0.025);
69
+ --text: #ffffff;
70
+ --text-muted: rgba(255,255,255,0.55);
71
+ --text-secondary: rgba(255,255,255,0.75);
72
+ --border: rgba(255,255,255,0.07);
73
+ --glow: rgba(0, 212, 255, 0.25);
74
+ --glow-purple: rgba(123, 44, 191, 0.25);
75
+ }
76
+
77
+ * {
78
+ margin: 0;
79
+ padding: 0;
80
+ box-sizing: border-box;
81
+ }
82
+
83
+ html {
84
+ scroll-behavior: smooth;
85
+ }
86
+
87
+ body {
88
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
89
+ background: var(--bg-dark);
90
+ color: var(--text);
91
+ line-height: 1.6;
92
+ overflow-x: hidden;
93
+ }
94
+
95
+ /* Grid overlay */
96
+ body::before {
97
+ content: '';
98
+ position: fixed;
99
+ inset: 0;
100
+ background-image:
101
+ linear-gradient(rgba(255,255,255,0.015) 1px, transparent 1px),
102
+ linear-gradient(90deg, rgba(255,255,255,0.015) 1px, transparent 1px);
103
+ background-size: 60px 60px;
104
+ pointer-events: none;
105
+ z-index: 0;
106
+ }
107
+
108
+ /* Sparkle/shimmer animation on logo text */
109
+ @keyframes sparkle {
110
+ 0% { background-position: -200% center; }
111
+ 100% { background-position: 200% center; }
112
+ }
113
+
114
+ @keyframes pulse-dot {
115
+ 0%, 100% { opacity: 1; transform: scale(1); }
116
+ 50% { opacity: 0.5; transform: scale(0.8); }
117
+ }
118
+
119
+ @keyframes float {
120
+ 0%, 100% { transform: translateY(0); }
121
+ 50% { transform: translateY(-6px); }
122
+ }
123
+
124
+ @keyframes gradient-rotate {
125
+ 0% { transform: rotate(0deg); }
126
+ 100% { transform: rotate(360deg); }
127
+ }
128
+
129
+ /* Layout */
130
+ .container {
131
+ max-width: 1200px;
132
+ margin: 0 auto;
133
+ padding: 0 24px;
134
+ position: relative;
135
+ z-index: 1;
136
+ }
137
+
138
+ /* Header */
139
+ header {
140
+ position: fixed;
141
+ top: 0;
142
+ left: 0;
143
+ right: 0;
144
+ z-index: 100;
145
+ padding: 16px 0;
146
+ background: rgba(6, 6, 14, 0.8);
147
+ backdrop-filter: blur(20px);
148
+ -webkit-backdrop-filter: blur(20px);
149
+ border-bottom: 1px solid var(--border);
150
+ }
151
+
152
+ header .container {
153
+ display: flex;
154
+ align-items: center;
155
+ justify-content: space-between;
156
+ }
157
+
158
+ .logo {
159
+ display: flex;
160
+ align-items: center;
161
+ gap: 10px;
162
+ text-decoration: none;
163
+ }
164
+
165
+ .logo-icon {
166
+ width: 32px;
167
+ height: 32px;
168
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
169
+ border-radius: 8px;
170
+ display: flex;
171
+ align-items: center;
172
+ justify-content: center;
173
+ font-weight: 700;
174
+ font-size: 14px;
175
+ color: #fff;
176
+ }
177
+
178
+ .logo-text {
179
+ font-size: 20px;
180
+ font-weight: 700;
181
+ letter-spacing: -0.02em;
182
+ background: linear-gradient(
183
+ 90deg,
184
+ var(--primary) 0%,
185
+ var(--secondary) 20%,
186
+ #fff 40%,
187
+ #fff 45%,
188
+ var(--secondary) 55%,
189
+ var(--primary) 100%
190
+ );
191
+ background-size: 200% auto;
192
+ -webkit-background-clip: text;
193
+ -webkit-text-fill-color: transparent;
194
+ background-clip: text;
195
+ animation: sparkle 4s linear infinite;
196
+ }
197
+
198
+ .logo-product {
199
+ font-size: 14px;
200
+ color: var(--text-muted);
201
+ font-weight: 500;
202
+ padding-left: 10px;
203
+ border-left: 1px solid var(--border);
204
+ }
205
+
206
+ nav {
207
+ display: flex;
208
+ align-items: center;
209
+ gap: 32px;
210
+ }
211
+
212
+ nav a {
213
+ color: var(--text-muted);
214
+ text-decoration: none;
215
+ font-size: 14px;
216
+ font-weight: 500;
217
+ transition: color 0.2s;
218
+ }
219
+
220
+ nav a:hover,
221
+ nav a.active {
222
+ color: var(--text);
223
+ }
224
+
225
+ nav a.active {
226
+ color: var(--primary);
227
+ }
228
+
229
+ .nav-cta {
230
+ padding: 8px 20px;
231
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
232
+ border: none;
233
+ border-radius: 8px;
234
+ color: #fff !important;
235
+ font-size: 14px;
236
+ font-weight: 600;
237
+ text-decoration: none;
238
+ transition: opacity 0.2s, transform 0.2s;
239
+ }
240
+
241
+ .nav-cta:hover {
242
+ opacity: 0.9;
243
+ transform: translateY(-1px);
244
+ }
245
+
246
+ .mobile-toggle {
247
+ display: none;
248
+ background: none;
249
+ border: none;
250
+ color: var(--text);
251
+ font-size: 24px;
252
+ cursor: pointer;
253
+ }
254
+
255
+ /* Buttons */
256
+ .btn-primary {
257
+ display: inline-flex;
258
+ align-items: center;
259
+ gap: 8px;
260
+ padding: 14px 32px;
261
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
262
+ border: none;
263
+ border-radius: 12px;
264
+ color: #fff;
265
+ font-size: 16px;
266
+ font-weight: 600;
267
+ text-decoration: none;
268
+ cursor: pointer;
269
+ transition: opacity 0.2s, transform 0.2s, box-shadow 0.2s;
270
+ }
271
+
272
+ .btn-primary:hover {
273
+ opacity: 0.9;
274
+ transform: translateY(-2px);
275
+ box-shadow: 0 8px 30px var(--glow);
276
+ }
277
+
278
+ .btn-secondary {
279
+ display: inline-flex;
280
+ align-items: center;
281
+ gap: 8px;
282
+ padding: 14px 32px;
283
+ background: transparent;
284
+ border: 1px solid var(--border);
285
+ border-radius: 12px;
286
+ color: var(--text-secondary);
287
+ font-size: 16px;
288
+ font-weight: 600;
289
+ text-decoration: none;
290
+ cursor: pointer;
291
+ transition: border-color 0.2s, color 0.2s, transform 0.2s;
292
+ }
293
+
294
+ .btn-secondary:hover {
295
+ border-color: var(--primary);
296
+ color: var(--text);
297
+ transform: translateY(-2px);
298
+ }
299
+
300
+ /* Section headers */
301
+ .section-header {
302
+ text-align: center;
303
+ max-width: 700px;
304
+ margin: 0 auto 60px;
305
+ }
306
+
307
+ .section-header h2 {
308
+ font-size: 40px;
309
+ font-weight: 700;
310
+ letter-spacing: -0.02em;
311
+ margin-bottom: 16px;
312
+ background: linear-gradient(135deg, var(--text), var(--text-secondary));
313
+ -webkit-background-clip: text;
314
+ -webkit-text-fill-color: transparent;
315
+ background-clip: text;
316
+ }
317
+
318
+ .section-header p {
319
+ font-size: 18px;
320
+ color: var(--text-muted);
321
+ line-height: 1.7;
322
+ }
323
+
324
+ /* Gradient text utility */
325
+ .gradient-text {
326
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
327
+ -webkit-background-clip: text;
328
+ -webkit-text-fill-color: transparent;
329
+ background-clip: text;
330
+ }
331
+
332
+ /* ================== HERO ================== */
333
+ .hero {
334
+ padding: 160px 0 80px;
335
+ text-align: center;
336
+ position: relative;
337
+ }
338
+
339
+ .hero::before {
340
+ content: '';
341
+ position: absolute;
342
+ top: 0;
343
+ left: 50%;
344
+ transform: translateX(-50%);
345
+ width: 800px;
346
+ height: 600px;
347
+ background: radial-gradient(ellipse, var(--glow-purple) 0%, transparent 70%);
348
+ pointer-events: none;
349
+ z-index: -1;
350
+ }
351
+
352
+ .hero-badge {
353
+ display: inline-flex;
354
+ align-items: center;
355
+ gap: 8px;
356
+ padding: 8px 20px;
357
+ background: rgba(16, 185, 129, 0.1);
358
+ border: 1px solid rgba(16, 185, 129, 0.2);
359
+ border-radius: 100px;
360
+ font-size: 14px;
361
+ font-weight: 500;
362
+ color: var(--emerald);
363
+ margin-bottom: 32px;
364
+ }
365
+
366
+ .hero-badge .pulse-dot {
367
+ width: 8px;
368
+ height: 8px;
369
+ border-radius: 50%;
370
+ background: var(--emerald);
371
+ animation: pulse-dot 2s ease-in-out infinite;
372
+ }
373
+
374
+ .hero h1 {
375
+ font-size: 72px;
376
+ font-weight: 800;
377
+ letter-spacing: -0.03em;
378
+ line-height: 1.05;
379
+ margin-bottom: 24px;
380
+ }
381
+
382
+ .hero h1 .line1 {
383
+ display: block;
384
+ background: linear-gradient(135deg, var(--primary), var(--secondary), var(--primary));
385
+ -webkit-background-clip: text;
386
+ -webkit-text-fill-color: transparent;
387
+ background-clip: text;
388
+ }
389
+
390
+ .hero h1 .line2 {
391
+ display: block;
392
+ font-weight: 300;
393
+ color: var(--text-muted);
394
+ -webkit-text-fill-color: var(--text-muted);
395
+ }
396
+
397
+ .hero-sub {
398
+ font-size: 20px;
399
+ color: var(--text-secondary);
400
+ max-width: 650px;
401
+ margin: 0 auto 16px;
402
+ line-height: 1.7;
403
+ }
404
+
405
+ .hero-detail {
406
+ font-size: 15px;
407
+ color: var(--text-muted);
408
+ max-width: 620px;
409
+ margin: 0 auto 40px;
410
+ line-height: 1.7;
411
+ }
412
+
413
+ .hero-ctas {
414
+ display: flex;
415
+ gap: 16px;
416
+ justify-content: center;
417
+ margin-bottom: 64px;
418
+ flex-wrap: wrap;
419
+ }
420
+
421
+ .metrics-bar {
422
+ display: flex;
423
+ justify-content: center;
424
+ gap: 48px;
425
+ flex-wrap: wrap;
426
+ }
427
+
428
+ .metric {
429
+ text-align: center;
430
+ }
431
+
432
+ .metric-value {
433
+ font-size: 28px;
434
+ font-weight: 700;
435
+ letter-spacing: -0.02em;
436
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
437
+ -webkit-background-clip: text;
438
+ -webkit-text-fill-color: transparent;
439
+ background-clip: text;
440
+ }
441
+
442
+ .metric-label {
443
+ font-size: 13px;
444
+ color: var(--text-muted);
445
+ margin-top: 4px;
446
+ }
447
+
448
+ /* ================== PIPELINE ================== */
449
+ .pipeline {
450
+ padding: 100px 0;
451
+ }
452
+
453
+ .pipeline-steps {
454
+ display: flex;
455
+ flex-direction: column;
456
+ gap: 0;
457
+ max-width: 800px;
458
+ margin: 0 auto;
459
+ position: relative;
460
+ }
461
+
462
+ .pipeline-steps::before {
463
+ content: '';
464
+ position: absolute;
465
+ left: 32px;
466
+ top: 32px;
467
+ bottom: 32px;
468
+ width: 2px;
469
+ background: linear-gradient(to bottom, var(--primary), var(--secondary));
470
+ opacity: 0.3;
471
+ }
472
+
473
+ .pipeline-step {
474
+ display: flex;
475
+ align-items: flex-start;
476
+ gap: 24px;
477
+ padding: 24px 0;
478
+ position: relative;
479
+ }
480
+
481
+ .step-number {
482
+ width: 64px;
483
+ height: 64px;
484
+ border-radius: 16px;
485
+ background: var(--bg-card);
486
+ border: 1px solid var(--border);
487
+ display: flex;
488
+ align-items: center;
489
+ justify-content: center;
490
+ font-size: 28px;
491
+ flex-shrink: 0;
492
+ position: relative;
493
+ z-index: 1;
494
+ }
495
+
496
+ .step-content h3 {
497
+ font-size: 20px;
498
+ font-weight: 700;
499
+ margin-bottom: 6px;
500
+ color: var(--text);
501
+ }
502
+
503
+ .step-content p {
504
+ font-size: 15px;
505
+ color: var(--text-muted);
506
+ line-height: 1.6;
507
+ }
508
+
509
+ /* ================== FEATURES ================== */
510
+ .features {
511
+ padding: 100px 0;
512
+ }
513
+
514
+ .features-grid {
515
+ display: grid;
516
+ grid-template-columns: repeat(3, 1fr);
517
+ gap: 24px;
518
+ }
519
+
520
+ .feature-card {
521
+ background: var(--bg-card);
522
+ border: 1px solid var(--border);
523
+ border-radius: 16px;
524
+ padding: 32px;
525
+ transition: transform 0.3s, box-shadow 0.3s, border-color 0.3s;
526
+ }
527
+
528
+ .feature-card:hover {
529
+ transform: translateY(-4px);
530
+ box-shadow: 0 12px 40px rgba(0, 212, 255, 0.08);
531
+ border-color: rgba(255,255,255,0.12);
532
+ }
533
+
534
+ .feature-icon {
535
+ font-size: 32px;
536
+ margin-bottom: 16px;
537
+ display: block;
538
+ }
539
+
540
+ .feature-card h3 {
541
+ font-size: 18px;
542
+ font-weight: 700;
543
+ margin-bottom: 10px;
544
+ color: var(--text);
545
+ }
546
+
547
+ .feature-card p {
548
+ font-size: 14px;
549
+ color: var(--text-muted);
550
+ line-height: 1.7;
551
+ }
552
+
553
+ /* ================== MOAT ================== */
554
+ .moat {
555
+ padding: 100px 0;
556
+ }
557
+
558
+ .moat-grid {
559
+ display: grid;
560
+ grid-template-columns: 1fr 1fr;
561
+ gap: 64px;
562
+ align-items: center;
563
+ }
564
+
565
+ .moat-text h2 {
566
+ font-size: 40px;
567
+ font-weight: 700;
568
+ letter-spacing: -0.02em;
569
+ margin-bottom: 12px;
570
+ background: linear-gradient(135deg, var(--text), var(--text-secondary));
571
+ -webkit-background-clip: text;
572
+ -webkit-text-fill-color: transparent;
573
+ background-clip: text;
574
+ }
575
+
576
+ .moat-text > p {
577
+ font-size: 17px;
578
+ color: var(--text-muted);
579
+ margin-bottom: 32px;
580
+ line-height: 1.7;
581
+ }
582
+
583
+ .moat-list {
584
+ list-style: none;
585
+ display: flex;
586
+ flex-direction: column;
587
+ gap: 16px;
588
+ }
589
+
590
+ .moat-list li {
591
+ font-size: 15px;
592
+ color: var(--text-secondary);
593
+ line-height: 1.6;
594
+ padding-left: 20px;
595
+ position: relative;
596
+ }
597
+
598
+ .moat-list li::before {
599
+ content: '';
600
+ position: absolute;
601
+ left: 0;
602
+ top: 10px;
603
+ width: 6px;
604
+ height: 6px;
605
+ border-radius: 50%;
606
+ background: var(--primary);
607
+ }
608
+
609
+ .moat-list li strong {
610
+ color: var(--text);
611
+ }
612
+
613
+ /* Code block with macOS chrome */
614
+ .code-window {
615
+ background: var(--bg-mid);
616
+ border: 1px solid var(--border);
617
+ border-radius: 12px;
618
+ overflow: hidden;
619
+ }
620
+
621
+ .code-titlebar {
622
+ display: flex;
623
+ align-items: center;
624
+ gap: 8px;
625
+ padding: 12px 16px;
626
+ background: rgba(255,255,255,0.03);
627
+ border-bottom: 1px solid var(--border);
628
+ }
629
+
630
+ .code-dot {
631
+ width: 12px;
632
+ height: 12px;
633
+ border-radius: 50%;
634
+ }
635
+
636
+ .code-dot.red { background: #ff5f57; }
637
+ .code-dot.yellow { background: #febc2e; }
638
+ .code-dot.green { background: #28c840; }
639
+
640
+ .code-titlebar span {
641
+ margin-left: 8px;
642
+ font-size: 12px;
643
+ color: var(--text-muted);
644
+ }
645
+
646
+ .code-body {
647
+ padding: 20px 24px;
648
+ font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace;
649
+ font-size: 13px;
650
+ line-height: 1.8;
651
+ overflow-x: auto;
652
+ }
653
+
654
+ .code-body .comment {
655
+ color: var(--text-muted);
656
+ }
657
+
658
+ .code-body .command {
659
+ color: var(--primary);
660
+ }
661
+
662
+ .code-body .output {
663
+ color: var(--emerald);
664
+ }
665
+
666
+ /* ================== PRICING ================== */
667
+ .pricing {
668
+ padding: 100px 0;
669
+ }
670
+
671
+ .pricing-grid {
672
+ display: grid;
673
+ grid-template-columns: repeat(3, 1fr);
674
+ gap: 24px;
675
+ }
676
+
677
+ .pricing-card {
678
+ background: var(--bg-card);
679
+ border: 1px solid var(--border);
680
+ border-radius: 16px;
681
+ padding: 40px 32px;
682
+ text-align: center;
683
+ transition: transform 0.3s, box-shadow 0.3s, border-color 0.3s;
684
+ display: flex;
685
+ flex-direction: column;
686
+ }
687
+
688
+ .pricing-card:hover {
689
+ transform: translateY(-4px);
690
+ box-shadow: 0 12px 40px rgba(0, 212, 255, 0.08);
691
+ border-color: rgba(255,255,255,0.12);
692
+ }
693
+
694
+ .pricing-card.featured {
695
+ border-color: var(--primary);
696
+ box-shadow: 0 0 40px var(--glow);
697
+ position: relative;
698
+ }
699
+
700
+ .pricing-card.featured::before {
701
+ content: 'Most Popular';
702
+ position: absolute;
703
+ top: -12px;
704
+ left: 50%;
705
+ transform: translateX(-50%);
706
+ padding: 4px 16px;
707
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
708
+ border-radius: 100px;
709
+ font-size: 12px;
710
+ font-weight: 600;
711
+ white-space: nowrap;
712
+ }
713
+
714
+ .pricing-name {
715
+ font-size: 20px;
716
+ font-weight: 700;
717
+ margin-bottom: 8px;
718
+ }
719
+
720
+ .pricing-price {
721
+ font-size: 48px;
722
+ font-weight: 800;
723
+ letter-spacing: -0.03em;
724
+ margin-bottom: 4px;
725
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
726
+ -webkit-background-clip: text;
727
+ -webkit-text-fill-color: transparent;
728
+ background-clip: text;
729
+ }
730
+
731
+ .pricing-price span {
732
+ font-size: 16px;
733
+ font-weight: 500;
734
+ -webkit-text-fill-color: var(--text-muted);
735
+ }
736
+
737
+ .pricing-period {
738
+ font-size: 14px;
739
+ color: var(--text-muted);
740
+ margin-bottom: 32px;
741
+ }
742
+
743
+ .pricing-features {
744
+ list-style: none;
745
+ display: flex;
746
+ flex-direction: column;
747
+ gap: 12px;
748
+ margin-bottom: 32px;
749
+ flex: 1;
750
+ text-align: left;
751
+ }
752
+
753
+ .pricing-features li {
754
+ font-size: 14px;
755
+ color: var(--text-secondary);
756
+ padding-left: 24px;
757
+ position: relative;
758
+ }
759
+
760
+ .pricing-features li::before {
761
+ content: '\2713';
762
+ position: absolute;
763
+ left: 0;
764
+ color: var(--emerald);
765
+ font-weight: 700;
766
+ }
767
+
768
+ .pricing-card .btn-primary,
769
+ .pricing-card .btn-secondary {
770
+ width: 100%;
771
+ justify-content: center;
772
+ padding: 12px 24px;
773
+ }
774
+
775
+ /* ================== CTA ================== */
776
+ .cta-section {
777
+ padding: 100px 0;
778
+ }
779
+
780
+ .cta-card {
781
+ position: relative;
782
+ border-radius: 24px;
783
+ padding: 80px 40px;
784
+ text-align: center;
785
+ overflow: hidden;
786
+ background: var(--bg-mid);
787
+ border: 1px solid var(--border);
788
+ }
789
+
790
+ .cta-card::before {
791
+ content: '';
792
+ position: absolute;
793
+ inset: -2px;
794
+ border-radius: 26px;
795
+ background: conic-gradient(from 0deg, var(--primary), var(--secondary), var(--accent), var(--emerald), var(--primary));
796
+ z-index: -1;
797
+ animation: gradient-rotate 6s linear infinite;
798
+ }
799
+
800
+ .cta-card::after {
801
+ content: '';
802
+ position: absolute;
803
+ inset: 2px;
804
+ border-radius: 22px;
805
+ background: var(--bg-mid);
806
+ z-index: -1;
807
+ }
808
+
809
+ .cta-card h2 {
810
+ font-size: 40px;
811
+ font-weight: 700;
812
+ letter-spacing: -0.02em;
813
+ margin-bottom: 16px;
814
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
815
+ -webkit-background-clip: text;
816
+ -webkit-text-fill-color: transparent;
817
+ background-clip: text;
818
+ }
819
+
820
+ .cta-card p {
821
+ font-size: 18px;
822
+ color: var(--text-muted);
823
+ margin-bottom: 32px;
824
+ }
825
+
826
+ .cta-card .btn-primary {
827
+ margin-bottom: 16px;
828
+ }
829
+
830
+ .cta-card .cta-note {
831
+ font-size: 13px;
832
+ color: var(--text-muted);
833
+ margin-bottom: 0;
834
+ }
835
+
836
+ /* ================== FOOTER ================== */
837
+ footer {
838
+ padding: 40px 0;
839
+ border-top: 1px solid var(--border);
840
+ }
841
+
842
+ footer .container {
843
+ display: flex;
844
+ align-items: center;
845
+ justify-content: space-between;
846
+ flex-wrap: wrap;
847
+ gap: 16px;
848
+ }
849
+
850
+ .footer-left {
851
+ display: flex;
852
+ align-items: center;
853
+ gap: 16px;
854
+ }
855
+
856
+ .footer-logo {
857
+ font-size: 16px;
858
+ font-weight: 700;
859
+ color: var(--text);
860
+ text-decoration: none;
861
+ }
862
+
863
+ .footer-copy {
864
+ font-size: 13px;
865
+ color: var(--text-muted);
866
+ }
867
+
868
+ .footer-links {
869
+ display: flex;
870
+ gap: 24px;
871
+ }
872
+
873
+ .footer-links a {
874
+ font-size: 13px;
875
+ color: var(--text-muted);
876
+ text-decoration: none;
877
+ transition: color 0.2s;
878
+ }
879
+
880
+ .footer-links a:hover {
881
+ color: var(--text);
882
+ }
883
+
884
+ /* ================== RESPONSIVE ================== */
885
+ @media (max-width: 900px) {
886
+ .hero h1 {
887
+ font-size: 48px;
888
+ }
889
+
890
+ .features-grid {
891
+ grid-template-columns: repeat(2, 1fr);
892
+ }
893
+
894
+ .pricing-grid {
895
+ grid-template-columns: repeat(2, 1fr);
896
+ }
897
+
898
+ .pricing-card:last-child {
899
+ grid-column: 1 / -1;
900
+ max-width: 400px;
901
+ margin: 0 auto;
902
+ width: 100%;
903
+ }
904
+
905
+ .moat-grid {
906
+ grid-template-columns: 1fr;
907
+ gap: 40px;
908
+ }
909
+
910
+ .metrics-bar {
911
+ gap: 32px;
912
+ }
913
+
914
+ nav {
915
+ gap: 20px;
916
+ }
917
+ }
918
+
919
+ @media (max-width: 640px) {
920
+ .hero h1 {
921
+ font-size: 36px;
922
+ }
923
+
924
+ .hero-sub {
925
+ font-size: 17px;
926
+ }
927
+
928
+ .section-header h2 {
929
+ font-size: 28px;
930
+ }
931
+
932
+ .features-grid {
933
+ grid-template-columns: 1fr;
934
+ }
935
+
936
+ .pricing-grid {
937
+ grid-template-columns: 1fr;
938
+ max-width: 400px;
939
+ margin: 0 auto;
940
+ }
941
+
942
+ .pricing-card:last-child {
943
+ max-width: none;
944
+ }
945
+
946
+ .hero-ctas {
947
+ flex-direction: column;
948
+ align-items: center;
949
+ }
950
+
951
+ .metrics-bar {
952
+ gap: 24px;
953
+ }
954
+
955
+ .metric {
956
+ min-width: 100px;
957
+ }
958
+
959
+ nav a:not(.nav-cta) {
960
+ display: none;
961
+ }
962
+
963
+ .mobile-toggle {
964
+ display: block;
965
+ }
966
+
967
+ nav.open a {
968
+ display: block;
969
+ }
970
+
971
+ .pipeline-steps::before {
972
+ left: 24px;
973
+ }
974
+
975
+ .step-number {
976
+ width: 48px;
977
+ height: 48px;
978
+ font-size: 22px;
979
+ border-radius: 12px;
980
+ }
981
+
982
+ .cta-card {
983
+ padding: 48px 24px;
984
+ }
985
+
986
+ .cta-card h2 {
987
+ font-size: 28px;
988
+ }
989
+
990
+ .moat-text h2 {
991
+ font-size: 28px;
992
+ }
993
+
994
+ footer .container {
995
+ flex-direction: column;
996
+ text-align: center;
997
+ }
998
+
999
+ .footer-left {
1000
+ flex-direction: column;
1001
+ }
1002
+ }
1003
+ </style>
1004
+ </head>
1005
+ <body>
1006
+
1007
+ <!-- Header -->
1008
+ <header>
1009
+ <div class="container">
1010
+ <a href="/mem" class="logo">
1011
+ <div class="logo-icon">M</div>
1012
+ <span class="logo-text">Candengo</span>
1013
+ <span class="logo-product">Mem</span>
1014
+ </a>
1015
+ <nav>
1016
+ <a href="/">Vector</a>
1017
+ <a href="/mem" class="active">Mem</a>
1018
+ <a href="#features">Features</a>
1019
+ <a href="#pricing">Pricing</a>
1020
+ <a href="/portal/signup" class="nav-cta">Sign Up</a>
1021
+ </nav>
1022
+ </div>
1023
+ </header>
1024
+
1025
+ <!-- Hero -->
1026
+ <section class="hero">
1027
+ <div class="container">
1028
+ <div class="hero-badge">
1029
+ <span class="pulse-dot"></span>
1030
+ AI Memory for Developers
1031
+ </div>
1032
+
1033
+ <h1>
1034
+ <span class="line1">Your AI Remembers.</span>
1035
+ <span class="line2">Across Every Session.</span>
1036
+ </h1>
1037
+
1038
+ <p class="hero-sub">Cross-device, team-shared memory for AI coding agents. Every discovery, decision, and bugfix &mdash; captured automatically, available everywhere.</p>
1039
+
1040
+ <p class="hero-detail">Engrm integrates with Claude Code, Codex CLI, Cursor, Windsurf, and any MCP-compatible agent. Your entire team shares context &mdash; no more repeating yourself to your AI.</p>
1041
+
1042
+ <div class="hero-ctas">
1043
+ <a href="/portal/signup" class="btn-primary">Get Started Free &rarr;</a>
1044
+ <a href="https://github.com/candengo/engrm" class="btn-secondary">View on GitHub</a>
1045
+ </div>
1046
+
1047
+ <div class="metrics-bar">
1048
+ <div class="metric">
1049
+ <div class="metric-value">&lt; 5ms</div>
1050
+ <div class="metric-label">Local Search</div>
1051
+ </div>
1052
+ <div class="metric">
1053
+ <div class="metric-value">Any</div>
1054
+ <div class="metric-label">MCP Agent</div>
1055
+ </div>
1056
+ <div class="metric">
1057
+ <div class="metric-value">10K</div>
1058
+ <div class="metric-label">Free Observations</div>
1059
+ </div>
1060
+ <div class="metric">
1061
+ <div class="metric-value">&infin;</div>
1062
+ <div class="metric-label">Offline-First</div>
1063
+ </div>
1064
+ </div>
1065
+ </div>
1066
+ </section>
1067
+
1068
+ <!-- How It Works -->
1069
+ <section class="pipeline">
1070
+ <div class="container">
1071
+ <div class="section-header">
1072
+ <h2>How It Works</h2>
1073
+ <p>From install to shared team memory in five steps. No config files, no boilerplate.</p>
1074
+ </div>
1075
+
1076
+ <div class="pipeline-steps">
1077
+ <div class="pipeline-step">
1078
+ <div class="step-number">&#x1F50C;</div>
1079
+ <div class="step-content">
1080
+ <h3>Connect</h3>
1081
+ <p>Install the MCP server, connect to your agent in one command. Zero config, instant setup.</p>
1082
+ </div>
1083
+ </div>
1084
+ <div class="pipeline-step">
1085
+ <div class="step-number">&#x1F4A1;</div>
1086
+ <div class="step-content">
1087
+ <h3>Capture</h3>
1088
+ <p>Observations captured automatically via hooks &mdash; bugfixes, decisions, patterns, and architectural insights.</p>
1089
+ </div>
1090
+ </div>
1091
+ <div class="pipeline-step">
1092
+ <div class="step-number">&#x1F9E0;</div>
1093
+ <div class="step-content">
1094
+ <h3>Remember</h3>
1095
+ <p>Smart context injection at session start with token-budgeted, tiered delivery. The most relevant knowledge first.</p>
1096
+ </div>
1097
+ </div>
1098
+ <div class="pipeline-step">
1099
+ <div class="step-number">&#x1F504;</div>
1100
+ <div class="step-content">
1101
+ <h3>Sync</h3>
1102
+ <p>Offline-first SQLite syncs to Candengo Vector for cross-device, cross-team access. Never miss a beat.</p>
1103
+ </div>
1104
+ </div>
1105
+ <div class="pipeline-step">
1106
+ <div class="step-number">&#x1F50D;</div>
1107
+ <div class="step-content">
1108
+ <h3>Search</h3>
1109
+ <p>Hybrid local FTS5 + remote vector search with intelligent reranking. Find anything in milliseconds.</p>
1110
+ </div>
1111
+ </div>
1112
+ </div>
1113
+ </div>
1114
+ </section>
1115
+
1116
+ <!-- Features -->
1117
+ <section class="features" id="features">
1118
+ <div class="container">
1119
+ <div class="section-header">
1120
+ <h2>Built for Real Developer Workflows</h2>
1121
+ <p>Every feature designed around how teams actually build software with AI.</p>
1122
+ </div>
1123
+
1124
+ <div class="features-grid">
1125
+ <div class="feature-card">
1126
+ <span class="feature-icon">&#x1F50C;</span>
1127
+ <h3>Zero-Config Setup</h3>
1128
+ <p><code>npx engrm init</code> opens your browser, authenticates, and configures everything. Working memory in under 2 minutes.</p>
1129
+ </div>
1130
+ <div class="feature-card">
1131
+ <span class="feature-icon">&#x1F9E0;</span>
1132
+ <h3>Smart Context Injection</h3>
1133
+ <p>Token-budgeted context with facts-first formatting. Top observations get detail, rest get titles. 50% denser than narrative prose.</p>
1134
+ </div>
1135
+ <div class="feature-card">
1136
+ <span class="feature-icon">&#x1F504;</span>
1137
+ <h3>Offline-First Sync</h3>
1138
+ <p>SQLite is always available. Sync outbox queues for Candengo Vector when online. Never lose work to connectivity issues.</p>
1139
+ </div>
1140
+ <div class="feature-card">
1141
+ <span class="feature-icon">&#x1F465;</span>
1142
+ <h3>Team Shared Memory</h3>
1143
+ <p>Your whole team's discoveries in one namespace. Debug a production issue? Everyone's AI knows about it next session.</p>
1144
+ </div>
1145
+ <div class="feature-card">
1146
+ <span class="feature-icon">&#x1F512;</span>
1147
+ <h3>Secret Scrubbing</h3>
1148
+ <p>API keys, passwords, connection strings &mdash; automatically scrubbed before storage. Custom patterns for org-specific secrets.</p>
1149
+ </div>
1150
+ <div class="feature-card">
1151
+ <span class="feature-icon">&#x1F916;</span>
1152
+ <h3>Multi-Agent Support</h3>
1153
+ <p>Works with Claude Code, Codex CLI, Cursor, Windsurf, Cline, and any MCP-compatible agent. Same memory, any tool.</p>
1154
+ </div>
1155
+ <div class="feature-card">
1156
+ <span class="feature-icon">&#x1F4CA;</span>
1157
+ <h3>Quality Scoring</h3>
1158
+ <p>Not all observations are equal. Quality scoring (0&ndash;1) surfaces the most valuable knowledge and filters noise automatically.</p>
1159
+ </div>
1160
+ <div class="feature-card">
1161
+ <span class="feature-icon">&#x1F4CC;</span>
1162
+ <h3>Knowledge Lifecycle</h3>
1163
+ <p>Active &rarr; Aging &rarr; Archived &rarr; Compacted. Pinned observations never age. Digests summarize old sessions into concise knowledge.</p>
1164
+ </div>
1165
+ <div class="feature-card">
1166
+ <span class="feature-icon">&#x1F517;</span>
1167
+ <h3>Knowledge Supersession</h3>
1168
+ <p>When understanding evolves, new observations supersede old ones. No stale knowledge polluting your context.</p>
1169
+ </div>
1170
+ </div>
1171
+ </div>
1172
+ </section>
1173
+
1174
+ <!-- MOAT Section -->
1175
+ <section class="moat">
1176
+ <div class="container">
1177
+ <div class="moat-grid">
1178
+ <div class="moat-text">
1179
+ <h2>The Unfair Advantage</h2>
1180
+ <p>Most AI memory tools are single-user, single-agent, single-machine. Engrm is none of those.</p>
1181
+
1182
+ <ul class="moat-list">
1183
+ <li><strong>Cross-device sync</strong> &mdash; Your laptop and desktop share the same memory via Candengo Vector</li>
1184
+ <li><strong>Team intelligence</strong> &mdash; When a teammate discovers a gotcha, every AI on the team knows about it</li>
1185
+ <li><strong>Multi-agent</strong> &mdash; Switch between Claude Code and Codex CLI? Your memory follows you</li>
1186
+ <li><strong>Offline-first</strong> &mdash; SQLite works without internet. Sync catches up when you're back online</li>
1187
+ <li><strong>Quality over quantity</strong> &mdash; Smart scoring, dedup, and compaction keep signal high and noise low</li>
1188
+ <li><strong>Enterprise-ready</strong> &mdash; Secret scrubbing, sensitivity levels, self-hosted option, team admin</li>
1189
+ </ul>
1190
+ </div>
1191
+
1192
+ <div class="code-window">
1193
+ <div class="code-titlebar">
1194
+ <div class="code-dot red"></div>
1195
+ <div class="code-dot yellow"></div>
1196
+ <div class="code-dot green"></div>
1197
+ <span>terminal</span>
1198
+ </div>
1199
+ <div class="code-body">
1200
+ <div class="comment"># Install in one command</div>
1201
+ <div class="command">$ npx engrm init</div>
1202
+ <br>
1203
+ <div class="comment"># Your AI now remembers everything</div>
1204
+ <div class="comment"># Session 1: "Fixed the auth bug in user.ts"</div>
1205
+ <div class="comment"># Session 2: "I see you fixed an auth bug yesterday..."</div>
1206
+ <br>
1207
+ <div class="comment"># Works across machines</div>
1208
+ <div class="command">$ ssh dev-server</div>
1209
+ <div class="comment"># Same memory, same context</div>
1210
+ <br>
1211
+ <div class="comment"># Works across agents</div>
1212
+ <div class="command">$ claude</div>
1213
+ <div class="output">&#10003; 12 observations loaded from Engrm</div>
1214
+ <div class="command">$ codex</div>
1215
+ <div class="output">&#10003; 12 observations loaded from Engrm</div>
1216
+ </div>
1217
+ </div>
1218
+ </div>
1219
+ </div>
1220
+ </section>
1221
+
1222
+ <!-- Pricing -->
1223
+ <section class="pricing" id="pricing">
1224
+ <div class="container">
1225
+ <div class="section-header">
1226
+ <h2>Simple, Transparent Pricing</h2>
1227
+ <p>Start free. Scale as your team grows.</p>
1228
+ </div>
1229
+
1230
+ <div class="pricing-grid">
1231
+ <div class="pricing-card">
1232
+ <div class="pricing-name">Free</div>
1233
+ <div class="pricing-price">$0</div>
1234
+ <div class="pricing-period">Free forever</div>
1235
+ <ul class="pricing-features">
1236
+ <li>10,000 observations</li>
1237
+ <li>1 user</li>
1238
+ <li>Local + cloud sync</li>
1239
+ <li>All MCP agents</li>
1240
+ <li>Community support</li>
1241
+ </ul>
1242
+ <a href="/portal/signup" class="btn-secondary">Get Started</a>
1243
+ </div>
1244
+
1245
+ <div class="pricing-card featured">
1246
+ <div class="pricing-name">Pro</div>
1247
+ <div class="pricing-price">$12<span>/mo</span></div>
1248
+ <div class="pricing-period">Per user, billed monthly</div>
1249
+ <ul class="pricing-features">
1250
+ <li>100,000 observations</li>
1251
+ <li>1 user</li>
1252
+ <li>Priority sync</li>
1253
+ <li>Advanced analytics</li>
1254
+ <li>Email support</li>
1255
+ </ul>
1256
+ <a href="/portal/signup" class="btn-primary">Start Free Trial</a>
1257
+ </div>
1258
+
1259
+ <div class="pricing-card">
1260
+ <div class="pricing-name">Team</div>
1261
+ <div class="pricing-price">$8<span>/user/mo</span></div>
1262
+ <div class="pricing-period">Billed monthly</div>
1263
+ <ul class="pricing-features">
1264
+ <li>Unlimited observations</li>
1265
+ <li>Shared team namespace</li>
1266
+ <li>Admin dashboard</li>
1267
+ <li>SSO / SAML</li>
1268
+ <li>Priority support</li>
1269
+ </ul>
1270
+ <a href="/portal/signup" class="btn-primary">Contact Sales</a>
1271
+ </div>
1272
+ </div>
1273
+ </div>
1274
+ </section>
1275
+
1276
+ <!-- CTA Section -->
1277
+ <section class="cta-section">
1278
+ <div class="container">
1279
+ <div class="cta-card">
1280
+ <h2>Give Your AI a Memory</h2>
1281
+ <p>Set up in 2 minutes. Free tier, no credit card required.</p>
1282
+ <a href="/portal/signup" class="btn-primary">Get Started Free &rarr;</a>
1283
+ <p class="cta-note">Works with Claude Code, Codex CLI, Cursor, Windsurf, and more</p>
1284
+ </div>
1285
+ </div>
1286
+ </section>
1287
+
1288
+ <!-- Footer -->
1289
+ <footer>
1290
+ <div class="container">
1291
+ <div class="footer-left">
1292
+ <a href="/" class="footer-logo">Candengo</a>
1293
+ <span class="footer-copy">&copy; 2025 Candengo. All rights reserved.</span>
1294
+ </div>
1295
+ <div class="footer-links">
1296
+ <a href="/">Vector</a>
1297
+ <a href="/mem">Mem</a>
1298
+ <a href="https://github.com/candengo/engrm">GitHub</a>
1299
+ <a href="mailto:sales@candengo.com">Contact Sales</a>
1300
+ </div>
1301
+ </div>
1302
+ </footer>
1303
+
1304
+ </body>
1305
+ </html>