engrm 0.4.3 → 0.4.4

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Engrm
2
2
 
3
- **Cross-device memory for AI coding agents.** Every session remembers what you learned yesterday on any machine, for every team member.
3
+ **Shared memory and delivery review for AI coding agents.** Engrm keeps context, decisions, and project state moving across your machines, your team, and the agents you switch between.
4
4
 
5
5
  For npm users, Engrm runs on Node.js 18+ and does not require Bun to be installed.
6
6
 
@@ -8,17 +8,18 @@ For npm users, Engrm runs on Node.js 18+ and does not require Bun to be installe
8
8
  npx engrm init
9
9
  ```
10
10
 
11
- Public beta. The current source of truth for agent capability differences is [AGENT_SUPPORT.md](AGENT_SUPPORT.md).
11
+ Public beta. Engrm is built for Claude Code, Codex, OpenClaw skills, and other MCP-native coding workflows. The current source of truth for agent capability differences is [AGENT_SUPPORT.md](AGENT_SUPPORT.md).
12
12
 
13
13
  ---
14
14
 
15
15
  ## What It Does
16
16
 
17
- Your AI agent forgets everything between sessions. Engrm fixes that.
17
+ Your AI agent forgets everything between sessions. Engrm fixes that, and helps you check whether the work really matched the brief.
18
18
 
19
- - **Captures automatically** — hooks into Claude Code, and into Codex where its public hook surface allows
19
+ - **Works across agents** — Claude Code and Codex integrate directly, and OpenClaw can use Engrm through published skill bundles
20
20
  - **Remembers across devices** — fix a bug on your laptop, continue on your desktop with full context
21
21
  - **Shares with your team** — one developer's hard-won insight becomes everyone's knowledge
22
+ - **Reviews delivery** — tie plans, decisions, and sessions together so you can see what actually shipped
22
23
  - **Works offline** — local SQLite is the source of truth; syncs when connected
23
24
  - **Guards your code** — Sentinel audits changes in real-time before they land
24
25
 
@@ -34,7 +35,7 @@ Visit [engrm.dev](https://engrm.dev) and create an account.
34
35
  npx engrm init
35
36
  ```
36
37
 
37
- This opens your browser for authentication, writes config to `~/.engrm/`, and registers Engrm in both Claude Code and Codex when those configs are available. Takes about 30 seconds.
38
+ This opens your browser for authentication, writes config to `~/.engrm/`, and registers Engrm in Claude Code and Codex when those configs are available. OpenClaw support is provided through the packaged skills in [`openclaw/`](openclaw/). Takes about 30 seconds.
38
39
 
39
40
  **Alternative methods:**
40
41
  ```bash
@@ -54,7 +55,7 @@ That's it. Engrm works in the background:
54
55
 
55
56
  - **Session start** — injects relevant project memory into context
56
57
  - **While you work** — captures observations from tool use where the agent exposes that hook surface
57
- - **Session end** — generates a session digest, syncs to cloud, shows summary
58
+ - **Session end** — generates a session digest, syncs to cloud, and turns recent work into a denser project brief
58
59
 
59
60
  ```
60
61
  ━━━ Engrm Session Summary ━━━
@@ -80,7 +81,7 @@ Engrm Status
80
81
  User: david
81
82
  Email: david@example.com
82
83
  Device: macbook-a1b2c3d4
83
- Plan: Pro ($15/mo)
84
+ Plan: Pro (£9.99/mo)
84
85
  Candengo: https://www.candengo.com
85
86
  MCP server: registered
86
87
  Codex MCP: registered
@@ -135,19 +136,21 @@ Codex session
135
136
 
136
137
  ### Agent Support
137
138
 
138
- | Capability | Claude Code | Codex |
139
- |---|---|---|
140
- | MCP server tools | ✓ | ✓ |
141
- | Session-start context injection | ✓ | ✓ |
142
- | Stop/session summary hook | ✓ | ✓ |
143
- | Per-tool automatic capture | ✓ | Partial via MCP/manual flows only |
144
- | Pre-write Sentinel hook | ✓ | Not yet exposed by Codex public hooks |
145
- | Pre-compact reinjection | ✓ | Not exposed |
146
- | ElicitationResult capture | ✓ | Not exposed |
139
+ | Capability | Claude Code | Codex | OpenClaw |
140
+ |---|---|---|---|
141
+ | MCP server tools | ✓ | ✓ | Via skills / MCP |
142
+ | Session-start context injection | ✓ | ✓ | Via skill-guided workflow |
143
+ | Stop/session summary hook | ✓ | ✓ | Via skill-guided workflow |
144
+ | Per-tool automatic capture | ✓ | Partial via MCP/manual flows only | Manual / skill-guided |
145
+ | Pre-write Sentinel hook | ✓ | Not yet exposed by Codex public hooks | Not exposed |
146
+ | Pre-compact reinjection | ✓ | Not exposed | Not exposed |
147
+ | ElicitationResult capture | ✓ | Not exposed | Not exposed |
148
+
149
+ OpenClaw support is packaged in [`openclaw/`](openclaw/) as `engrm-memory`, `engrm-delivery-review`, and `engrm-sentinel` skills for ClawHub-style distribution.
147
150
 
148
151
  ### MCP Tools
149
152
 
150
- The MCP server exposes tools that Claude can call directly:
153
+ The MCP server exposes tools that supported agents can call directly:
151
154
 
152
155
  | Tool | Purpose |
153
156
  |------|---------|
@@ -217,9 +220,9 @@ Observations age gracefully: **active** (30 days, full weight) → **aging** (0.
217
220
 
218
221
  | | Free | Vibe | Pro | Team |
219
222
  |---|---|---|---|---|
220
- | **Price** | $0 | $9/mo | $15/mo | £19/seat/mo |
221
- | **Observations** | 5,000 | 25,000 | Unlimited | Unlimited |
222
- | **Devices** | 1 | 3 | Unlimited | Unlimited |
223
+ | **Price** | £0 | £5.99/mo | £9.99/mo | £12.99/seat/mo |
224
+ | **Observations** | 5,000 | 25,000 | 100,000 | Unlimited |
225
+ | **Devices** | 2 | 3 | 5 | Unlimited |
223
226
  | **Cloud sync** | ✓ | ✓ | ✓ | ✓ |
224
227
  | **Sentinel** | — | Advisory (50/day) | Advisory (200/day) | Blocking (unlimited) |
225
228
  | **Retention** | 30 days | 90 days | 1 year | Unlimited |
@@ -2413,7 +2413,8 @@ async function main() {
2413
2413
  available: remaining,
2414
2414
  securityFindings: context.securityFindings?.length ?? 0,
2415
2415
  unreadMessages: msgCount,
2416
- synced: syncedCount
2416
+ synced: syncedCount,
2417
+ context
2417
2418
  });
2418
2419
  let packLine = "";
2419
2420
  try {
@@ -2481,8 +2482,65 @@ function formatSplashScreen(data) {
2481
2482
  }
2482
2483
  lines.push("");
2483
2484
  lines.push(` ${c2.dim}Dashboard: https://engrm.dev/dashboard${c2.reset}`);
2485
+ const brief = formatVisibleStartupBrief(data.context);
2486
+ if (brief.length > 0) {
2487
+ lines.push("");
2488
+ lines.push(` ${c2.bold}Startup brief${c2.reset}`);
2489
+ for (const line of brief) {
2490
+ lines.push(` ${line}`);
2491
+ }
2492
+ }
2484
2493
  lines.push("");
2485
2494
  return lines.join(`
2486
2495
  `);
2487
2496
  }
2497
+ function formatVisibleStartupBrief(context) {
2498
+ const lines = [];
2499
+ const latest = context.summaries?.[0];
2500
+ if (latest) {
2501
+ const sections = [
2502
+ ["Investigated", latest.investigated],
2503
+ ["Learned", latest.learned],
2504
+ ["Completed", latest.completed],
2505
+ ["Next Steps", latest.next_steps]
2506
+ ];
2507
+ for (const [label, value] of sections) {
2508
+ const formatted = toSplashBullet(value, label === "Next Steps" ? 140 : 180);
2509
+ if (formatted) {
2510
+ lines.push(`${c2.cyan}${label}:${c2.reset} ${formatted}`);
2511
+ }
2512
+ }
2513
+ }
2514
+ if (context.staleDecisions && context.staleDecisions.length > 0) {
2515
+ const stale = context.staleDecisions[0];
2516
+ lines.push(`${c2.yellow}Watch:${c2.reset} ${truncateInline(`Decision still looks unfinished: ${stale.title}`, 170)}`);
2517
+ }
2518
+ if (lines.length === 0 && context.observations.length > 0) {
2519
+ const top = context.observations.slice(0, 2);
2520
+ for (const obs of top) {
2521
+ lines.push(`${c2.cyan}${capitalize(obs.type)}:${c2.reset} ${truncateInline(obs.title, 170)}`);
2522
+ }
2523
+ }
2524
+ return lines.slice(0, 5);
2525
+ }
2526
+ function toSplashBullet(value, maxLen) {
2527
+ if (!value)
2528
+ return null;
2529
+ const cleaned = value.split(`
2530
+ `).map((line) => line.trim().replace(/^[-*]\s*/, "")).filter(Boolean).join("; ");
2531
+ if (!cleaned)
2532
+ return null;
2533
+ return truncateInline(cleaned, maxLen);
2534
+ }
2535
+ function truncateInline(text, maxLen) {
2536
+ const compact = text.replace(/\s+/g, " ").trim();
2537
+ if (compact.length <= maxLen)
2538
+ return compact;
2539
+ return `${compact.slice(0, maxLen - 1).trimEnd()}\u2026`;
2540
+ }
2541
+ function capitalize(value) {
2542
+ if (!value)
2543
+ return value;
2544
+ return value.charAt(0).toUpperCase() + value.slice(1);
2545
+ }
2488
2546
  runHook("session-start", main);
@@ -1475,10 +1475,14 @@ function buildSummaryVectorDocument(summary, config, project) {
1475
1475
  const parts = [];
1476
1476
  if (summary.request)
1477
1477
  parts.push(`Request: ${summary.request}`);
1478
+ if (summary.investigated)
1479
+ parts.push(`Investigated: ${summary.investigated}`);
1478
1480
  if (summary.learned)
1479
1481
  parts.push(`Learned: ${summary.learned}`);
1480
1482
  if (summary.completed)
1481
1483
  parts.push(`Completed: ${summary.completed}`);
1484
+ if (summary.next_steps)
1485
+ parts.push(`Next Steps: ${summary.next_steps}`);
1482
1486
  return {
1483
1487
  site_id: config.site_id,
1484
1488
  namespace: config.namespace,
@@ -1492,6 +1496,11 @@ function buildSummaryVectorDocument(summary, config, project) {
1492
1496
  project_name: project.name,
1493
1497
  user_id: summary.user_id,
1494
1498
  session_id: summary.session_id,
1499
+ request: summary.request,
1500
+ investigated: summary.investigated,
1501
+ learned: summary.learned,
1502
+ completed: summary.completed,
1503
+ next_steps: summary.next_steps,
1495
1504
  created_at_epoch: summary.created_at_epoch,
1496
1505
  local_id: summary.id
1497
1506
  }
package/dist/server.js CHANGED
@@ -16508,10 +16508,14 @@ function buildSummaryVectorDocument(summary, config2, project) {
16508
16508
  const parts = [];
16509
16509
  if (summary.request)
16510
16510
  parts.push(`Request: ${summary.request}`);
16511
+ if (summary.investigated)
16512
+ parts.push(`Investigated: ${summary.investigated}`);
16511
16513
  if (summary.learned)
16512
16514
  parts.push(`Learned: ${summary.learned}`);
16513
16515
  if (summary.completed)
16514
16516
  parts.push(`Completed: ${summary.completed}`);
16517
+ if (summary.next_steps)
16518
+ parts.push(`Next Steps: ${summary.next_steps}`);
16515
16519
  return {
16516
16520
  site_id: config2.site_id,
16517
16521
  namespace: config2.namespace,
@@ -16525,6 +16529,11 @@ function buildSummaryVectorDocument(summary, config2, project) {
16525
16529
  project_name: project.name,
16526
16530
  user_id: summary.user_id,
16527
16531
  session_id: summary.session_id,
16532
+ request: summary.request,
16533
+ investigated: summary.investigated,
16534
+ learned: summary.learned,
16535
+ completed: summary.completed,
16536
+ next_steps: summary.next_steps,
16528
16537
  created_at_epoch: summary.created_at_epoch,
16529
16538
  local_id: summary.id
16530
16539
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "engrm",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Cross-device, team-shared memory layer for AI coding agents",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",