engrm 0.1.0 → 0.2.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 (98) hide show
  1. package/README.md +214 -73
  2. package/bin/build.mjs +97 -0
  3. package/bin/engrm.mjs +13 -0
  4. package/dist/cli.js +2712 -0
  5. package/dist/hooks/elicitation-result.js +1786 -0
  6. package/dist/hooks/post-tool-use.js +2357 -0
  7. package/dist/hooks/pre-compact.js +1321 -0
  8. package/dist/hooks/sentinel.js +1168 -0
  9. package/dist/hooks/session-start.js +1473 -0
  10. package/dist/hooks/stop.js +1834 -0
  11. package/dist/server.js +16628 -0
  12. package/package.json +29 -4
  13. package/packs/api-best-practices.json +182 -0
  14. package/packs/nextjs-patterns.json +68 -0
  15. package/packs/node-security.json +68 -0
  16. package/packs/python-django.json +68 -0
  17. package/packs/react-gotchas.json +182 -0
  18. package/packs/typescript-patterns.json +67 -0
  19. package/packs/web-security.json +182 -0
  20. package/.mcp.json +0 -9
  21. package/AUTH-DESIGN.md +0 -436
  22. package/BRIEF.md +0 -197
  23. package/CLAUDE.md +0 -44
  24. package/COMPETITIVE.md +0 -174
  25. package/CONTEXT-OPTIMIZATION.md +0 -305
  26. package/INFRASTRUCTURE.md +0 -252
  27. package/MARKET.md +0 -230
  28. package/PLAN.md +0 -278
  29. package/SENTINEL.md +0 -293
  30. package/SERVER-API-PLAN.md +0 -553
  31. package/SPEC.md +0 -843
  32. package/SWOT.md +0 -148
  33. package/SYNC-ARCHITECTURE.md +0 -294
  34. package/VIBE-CODER-STRATEGY.md +0 -250
  35. package/bun.lock +0 -375
  36. package/hooks/post-tool-use.ts +0 -144
  37. package/hooks/session-start.ts +0 -64
  38. package/hooks/stop.ts +0 -131
  39. package/mem-page.html +0 -1305
  40. package/src/capture/dedup.test.ts +0 -103
  41. package/src/capture/dedup.ts +0 -76
  42. package/src/capture/extractor.test.ts +0 -245
  43. package/src/capture/extractor.ts +0 -330
  44. package/src/capture/quality.test.ts +0 -168
  45. package/src/capture/quality.ts +0 -104
  46. package/src/capture/retrospective.test.ts +0 -115
  47. package/src/capture/retrospective.ts +0 -121
  48. package/src/capture/scanner.test.ts +0 -131
  49. package/src/capture/scanner.ts +0 -100
  50. package/src/capture/scrubber.test.ts +0 -144
  51. package/src/capture/scrubber.ts +0 -181
  52. package/src/cli.ts +0 -517
  53. package/src/config.ts +0 -238
  54. package/src/context/inject.test.ts +0 -940
  55. package/src/context/inject.ts +0 -382
  56. package/src/embeddings/backfill.ts +0 -50
  57. package/src/embeddings/embedder.test.ts +0 -76
  58. package/src/embeddings/embedder.ts +0 -139
  59. package/src/lifecycle/aging.test.ts +0 -103
  60. package/src/lifecycle/aging.ts +0 -36
  61. package/src/lifecycle/compaction.test.ts +0 -264
  62. package/src/lifecycle/compaction.ts +0 -190
  63. package/src/lifecycle/purge.test.ts +0 -100
  64. package/src/lifecycle/purge.ts +0 -37
  65. package/src/lifecycle/scheduler.test.ts +0 -120
  66. package/src/lifecycle/scheduler.ts +0 -101
  67. package/src/provisioning/browser-auth.ts +0 -172
  68. package/src/provisioning/provision.test.ts +0 -198
  69. package/src/provisioning/provision.ts +0 -94
  70. package/src/register.test.ts +0 -167
  71. package/src/register.ts +0 -178
  72. package/src/server.ts +0 -436
  73. package/src/storage/migrations.test.ts +0 -244
  74. package/src/storage/migrations.ts +0 -261
  75. package/src/storage/outbox.test.ts +0 -229
  76. package/src/storage/outbox.ts +0 -131
  77. package/src/storage/projects.test.ts +0 -137
  78. package/src/storage/projects.ts +0 -184
  79. package/src/storage/sqlite.test.ts +0 -798
  80. package/src/storage/sqlite.ts +0 -934
  81. package/src/storage/vec.test.ts +0 -198
  82. package/src/sync/auth.test.ts +0 -76
  83. package/src/sync/auth.ts +0 -68
  84. package/src/sync/client.ts +0 -183
  85. package/src/sync/engine.test.ts +0 -94
  86. package/src/sync/engine.ts +0 -127
  87. package/src/sync/pull.test.ts +0 -279
  88. package/src/sync/pull.ts +0 -170
  89. package/src/sync/push.test.ts +0 -117
  90. package/src/sync/push.ts +0 -230
  91. package/src/tools/get.ts +0 -34
  92. package/src/tools/pin.ts +0 -47
  93. package/src/tools/save.test.ts +0 -301
  94. package/src/tools/save.ts +0 -231
  95. package/src/tools/search.test.ts +0 -69
  96. package/src/tools/search.ts +0 -181
  97. package/src/tools/timeline.ts +0 -64
  98. package/tsconfig.json +0 -22
package/README.md CHANGED
@@ -1,121 +1,262 @@
1
1
  # Engrm
2
2
 
3
- **Cross-device memory for AI coding agents**powered by [Candengo Vector](https://www.candengo.com).
3
+ **Cross-device memory for AI coding agents.** Every session remembers what you learned yesterday on any machine, for every team member.
4
4
 
5
- Engrm captures observations from AI-assisted coding sessions (discoveries, bugfixes, decisions, patterns) and syncs them to Candengo Vector so they're available on any machine, in any future session.
6
-
7
- Built from scratch. Inspired by [claude-mem](https://github.com/thedotmack/claude-mem)'s approach to hooking into Claude Code — but designed around cross-device sync from day one, with Candengo Vector as the backend.
5
+ ```
6
+ npx engrm init
7
+ ```
8
8
 
9
9
  ---
10
10
 
11
- ## The Problem
11
+ ## What It Does
12
+
13
+ Your AI agent forgets everything between sessions. Engrm fixes that.
14
+
15
+ - **Captures automatically** — hooks into Claude Code to record discoveries, bugfixes, decisions, and patterns as you work
16
+ - **Remembers across devices** — fix a bug on your laptop, continue on your desktop with full context
17
+ - **Shares with your team** — one developer's hard-won insight becomes everyone's knowledge
18
+ - **Works offline** — local SQLite is the source of truth; syncs when connected
19
+ - **Guards your code** — Sentinel audits changes in real-time before they land
20
+
21
+ ## Quick Start
22
+
23
+ ### 1. Sign up
24
+
25
+ Visit [engrm.dev](https://engrm.dev) and create an account.
12
26
 
13
- Our dev team works across multiple machines and projects (Candengo, Alchemy, AIMY). Every Claude Code session starts from zero — no memory of what was done yesterday, on another machine, or by another developer. The agent re-discovers the same patterns, hits the same gotchas, and asks the same questions that were already answered in a different session.
27
+ ### 2. Install
14
28
 
15
- ## The Solution
29
+ ```bash
30
+ npx engrm init
31
+ ```
32
+
33
+ This opens your browser for authentication, writes config to `~/.engrm/`, and registers the MCP server + hooks in Claude Code. Takes about 30 seconds.
34
+
35
+ **Alternative methods:**
36
+ ```bash
37
+ # From a provisioning token (shown on engrm.dev after signup)
38
+ npx engrm init --token=cmt_your_token
39
+
40
+ # Self-hosted Candengo Vector
41
+ npx engrm init --url=https://vector.internal.company.com
42
+
43
+ # Manual setup (air-gapped environments)
44
+ npx engrm init --manual
45
+ ```
16
46
 
17
- An MCP server + Claude Code hooks that:
47
+ ### 3. Use Claude Code normally
18
48
 
19
- 1. **Capture observations automatically** from coding sessions via Claude Code hooks (`PostToolUse`, `Stop`)
20
- 2. **Store locally** in SQLite (offline-first, always available)
21
- 3. **Sync to Candengo Vector** for cross-device, cross-developer search (BGE-M3 hybrid dense+sparse, cross-encoder reranking)
22
- 4. **Inject relevant context** on session start so the agent picks up where you (or a teammate) left off, on any machine
49
+ That's it. Engrm works in the background:
50
+
51
+ - **Session start** injects relevant project memory into context
52
+ - **While you work** — captures observations from tool use (edits, writes, commands)
53
+ - **Session end** — generates a session digest, syncs to cloud, shows summary
54
+
55
+ ```
56
+ ━━━ Engrm Session Summary ━━━
57
+
58
+ 📋 Request: Fix the OAuth redirect validation
59
+ 🔍 Investigated: redirect_uri handling in auth.py
60
+ 💡 Learned: scheme + host + port must all match registered URIs
61
+ ✅ Completed: Stricter redirect_uri validation (auth.py)
62
+
63
+ 🟢 Risk: Low (0.12)
64
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
65
+ ```
66
+
67
+ ### 4. Check status
68
+
69
+ ```bash
70
+ npx engrm status
71
+ ```
72
+
73
+ ```
74
+ Engrm Status
75
+
76
+ User: david
77
+ Email: david@example.com
78
+ Device: macbook-a1b2c3d4
79
+ Plan: Pro ($15/mo)
80
+ Candengo: https://www.candengo.com
81
+ MCP server: registered
82
+ Hooks: registered (6 hooks)
83
+
84
+ Observations: 1,247 active
85
+ By type: change: 412, discovery: 289, bugfix: 187, ...
86
+ Sentinel: enabled (advisory, 142/200 today)
87
+ Sync: push 2m ago, pull 5m ago
88
+ Security: 3 findings (1 high, 2 medium)
89
+ ```
23
90
 
24
91
  ---
25
92
 
26
- ## Architecture
27
-
28
- ```
29
- Developer's Machine (any device)
30
- +---------------------------------------------+
31
- | Claude Code |
32
- | | MCP (stdio) |
33
- | +-----------------------------------+ |
34
- | | Engrm MCP Server | |
35
- | | - Observation capture | |
36
- | | - Local SQLite + FTS5 | |
37
- | | - Sync outbox queue | |
38
- | | - Secret scrubbing | |
39
- | +--------------+--------------------+ |
40
- | | HTTPS (when available) |
41
- +-----------------+----------------------------+
42
- |
43
- v
44
- +---------------------------------------------+
45
- | Candengo Vector (self-hosted or cloud) |
46
- | - BGE-M3 hybrid dense+sparse search |
47
- | - Cross-encoder reranking |
48
- | - Multi-tenant (site_id / namespace) |
49
- +---------------------------------------------+
50
- ```
51
-
52
- **Key principle**: SQLite is the source of truth. Always available, always fast. Candengo Vector is the sync target that enables cross-device search. If the remote is unreachable, everything still works locally.
93
+ ## How It Works
94
+
95
+ ```
96
+ Claude Code session
97
+
98
+ ├─ SessionStart hook ──→ inject relevant memory into context
99
+
100
+ ├─ PreToolUse hook ────→ Sentinel audits Edit/Write (optional)
101
+
102
+ ├─ PostToolUse hook ───→ extract observations from tool results
103
+
104
+ ├─ PreCompact hook ────→ re-inject memory before context compression
105
+
106
+ ├─ ElicitationResult ──→ capture MCP form submissions
107
+
108
+ └─ Stop hook ──────────→ session digest + sync + summary
109
+
110
+
111
+ Local SQLite (FTS5 + sqlite-vec)
112
+
113
+ (sync every 30s)
114
+ Candengo Vector (cloud)
115
+
116
+
117
+ Available on all your devices + team members
118
+ ```
119
+
120
+ ### MCP Tools
121
+
122
+ The MCP server exposes tools that Claude can call directly:
123
+
124
+ | Tool | Purpose |
125
+ |------|---------|
126
+ | `search` | Find relevant observations from memory (hybrid FTS5 + vector) |
127
+ | `timeline` | Chronological context around an observation |
128
+ | `get_observations` | Fetch full details by ID |
129
+ | `save_observation` | Manually save something worth remembering |
130
+ | `install_pack` | Load a curated knowledge pack for your stack |
131
+
132
+ ### Observation Types
133
+
134
+ | Type | What it captures |
135
+ |------|-----------------|
136
+ | `discovery` | Learning about existing systems or codebases |
137
+ | `bugfix` | Something was broken, now fixed |
138
+ | `decision` | Architectural or design choice with rationale |
139
+ | `change` | Meaningful modification (feature, config, docs) |
140
+ | `feature` | New capability or functionality |
141
+ | `refactor` | Code restructured without behavior change |
142
+ | `pattern` | Recurring issue or technique |
143
+ | `digest` | Session summary (auto-generated) |
53
144
 
54
145
  ---
55
146
 
56
- ## Getting Started
147
+ ## Features
57
148
 
58
- Sign up at [engrm.dev](https://engrm.dev), then run the install command shown on the page:
149
+ ### Hybrid Search
150
+ Local FTS5 + sqlite-vec (all-MiniLM-L6-v2, 384 dims) combined with Candengo Vector's BGE-M3 semantic search. Results merged via Reciprocal Rank Fusion.
151
+
152
+ ### Sentinel — Real-Time Code Audit
153
+ LLM-powered review of every Edit/Write before it executes. Catches security issues, anti-patterns, and drift from team decisions.
154
+
155
+ ```
156
+ ⚠️ Sentinel: SQL query uses string concatenation instead of parameterized query
157
+ Rule: sql-injection
158
+ (Advisory mode — change allowed)
159
+ ```
160
+
161
+ 5 built-in rule packs: `security`, `auth`, `api`, `react`, `database`.
59
162
 
60
163
  ```bash
61
- npx engrm init --token=cmt_your_token_here
164
+ npx engrm sentinel init-rules # Install all rule packs
165
+ npx engrm sentinel rules # List available packs
62
166
  ```
63
167
 
64
- That's it. The command provisions your account, writes config, registers the MCP server and hooks in Claude Code. Your next Claude Code session has memory.
168
+ ### Starter Packs
169
+ Pre-loaded knowledge for your tech stack. Detected automatically on session start.
65
170
 
66
- **For teams**: Admin creates a team at [engrm.dev/team](https://engrm.dev/team), shares the invite link. Team members sign up via the link and are pre-configured for the shared namespace.
171
+ Available: `typescript-patterns`, `nextjs-patterns`, `node-security`, `python-django`, `react-gotchas`, `api-best-practices`, `web-security`
67
172
 
68
- **Self-hosted**: Point at your own Candengo Vector instance:
69
173
  ```bash
70
- npx engrm init --url=https://vector.internal.company.com --token=cmt_...
174
+ npx engrm install-pack typescript-patterns
71
175
  ```
72
176
 
177
+ ### Secret Scrubbing
178
+ Multi-layer regex scanning for API keys, passwords, tokens, and credentials. Sensitive content is redacted before storage and sync. Custom patterns configurable in `~/.engrm/settings.json`.
179
+
180
+ ### Observation Lifecycle
181
+ Observations age gracefully: **active** (30 days, full weight) → **aging** (0.7x search weight) → **archived** (compacted into digests) → **purged** (after 12 months). Pinned observations never age.
182
+
73
183
  ---
74
184
 
75
- ## How It Hooks Into Claude Code
185
+ ## Pricing
186
+
187
+ | | Free | Vibe | Pro | Team |
188
+ |---|---|---|---|---|
189
+ | **Price** | $0 | $9/mo | $15/mo | £19/seat/mo |
190
+ | **Observations** | 5,000 | 25,000 | Unlimited | Unlimited |
191
+ | **Devices** | 1 | 3 | Unlimited | Unlimited |
192
+ | **Cloud sync** | ✓ | ✓ | ✓ | ✓ |
193
+ | **Sentinel** | — | Advisory (50/day) | Advisory (200/day) | Blocking (unlimited) |
194
+ | **Retention** | 30 days | 90 days | 1 year | Unlimited |
195
+ | **Team namespace** | — | — | — | ✓ |
76
196
 
77
- Engrm integrates via two mechanisms:
197
+ Sign up at [engrm.dev](https://engrm.dev).
78
198
 
79
- ### MCP Server
80
- Registered in Claude Code's MCP config, exposes tools the agent can call:
81
- - `search` — find relevant observations from memory
82
- - `timeline` — chronological context around an observation
83
- - `get_observations` — fetch full details by ID
84
- - `save_observation` — manually save something worth remembering
199
+ ---
200
+
201
+ ## Self-Hosting
85
202
 
86
- ### Claude Code Hooks
87
- Shell scripts triggered by Claude Code lifecycle events:
88
- - `PostToolUse` — extract observations from tool results (the main capture path)
89
- - `Stop` generate session summary, flush sync queue
203
+ Point Engrm at your own [Candengo Vector](https://www.candengo.com) instance:
204
+
205
+ ```bash
206
+ npx engrm init --url=https://vector.internal.company.com --token=cmt_...
207
+ ```
90
208
 
91
- This is similar to how claude-mem hooks in, but our implementation is independent no shared code, no fork relationship.
209
+ Candengo Vector provides the backend: BGE-M3 hybrid search, multi-tenant namespaces, and team sync. See the [Candengo docs](https://www.candengo.com/docs) for deployment.
92
210
 
93
211
  ---
94
212
 
95
- ## Status
213
+ ## Configuration
214
+
215
+ ### User config: `~/.engrm/settings.json`
216
+
217
+ Created by `engrm init`. Contains API credentials, sync settings, search preferences, secret scrubbing patterns, and Sentinel configuration.
96
218
 
97
- **Building.** The product brief, technical spec, and implementation plan are complete. Implementation is starting with Phase 1: local MCP server with SQLite storage, observation capture, and secret scrubbing.
219
+ ### Project config: `.engrm.json` (optional)
220
+
221
+ Place in your project root to override project identity for non-git projects:
222
+
223
+ ```json
224
+ {
225
+ "project_id": "internal/design-system",
226
+ "name": "Design System"
227
+ }
228
+ ```
229
+
230
+ ### Claude Code integration
231
+
232
+ Engrm auto-registers in:
233
+ - `~/.claude.json` — MCP server (`engrm`)
234
+ - `~/.claude/settings.json` — 6 lifecycle hooks
98
235
 
99
236
  ---
100
237
 
101
- ## Project Documents
238
+ ## Tech Stack
102
239
 
103
- | Document | Contents |
104
- |---|---|
105
- | [BRIEF.md](BRIEF.md) | Product brief, target users, revenue model |
106
- | [SPEC.md](SPEC.md) | Technical specification: schemas, MCP tools, sync engine, search pipeline |
107
- | [PLAN.md](PLAN.md) | Phased implementation plan with effort estimates |
108
- | [SWOT.md](SWOT.md) | Strengths, weaknesses, opportunities, threats |
109
- | [COMPETITIVE.md](COMPETITIVE.md) | Competitive landscape analysis |
110
- | [MARKET.md](MARKET.md) | Market research, pricing, growth projections |
111
- | [INFRASTRUCTURE.md](INFRASTRUCTURE.md) | Scaling roadmap, capacity planning |
240
+ - **Runtime**: TypeScript, runs on Bun (dev) or Node.js 18+ (npm)
241
+ - **Local storage**: SQLite via better-sqlite3, FTS5 full-text search, sqlite-vec for embeddings
242
+ - **Embeddings**: all-MiniLM-L6-v2 via @xenova/transformers (384 dims, ~23MB)
243
+ - **Remote backend**: Candengo Vector (BGE-M3, Qdrant, hybrid dense+sparse search)
244
+ - **MCP**: @modelcontextprotocol/sdk (stdio transport)
245
+ - **AI extraction**: @anthropic-ai/claude-agent-sdk (optional, for richer observations)
112
246
 
113
247
  ---
114
248
 
115
249
  ## License
116
250
 
117
- Functional Source License v1.1 (FSL-1.1-ALv2) — source-available, part of the [Fair Source](https://fair.io) movement. Free to use, modify, and self-host for any non-competing purpose. You cannot offer this as a competing hosted service. Each version converts to Apache 2.0 after 2 years. Sentinel (real-time AI audit) is a separate proprietary product. See [LICENSE](LICENSE) for details.
251
+ **FSL-1.1-ALv2** (Functional Source License) — part of the [Fair Source](https://fair.io) movement.
252
+
253
+ - Free to use, modify, and self-host
254
+ - You cannot offer this as a competing hosted service
255
+ - Each version converts to Apache 2.0 after 2 years
256
+ - Sentinel is a separate proprietary product
257
+
258
+ See [LICENSE](LICENSE) for full terms.
118
259
 
119
260
  ---
120
261
 
121
- Built by [Unimpossible Consultants](https://unimpossible.com) — the team behind Candengo, Alchemy, and AIMY.
262
+ Built by [Unimpossible Consultants](https://unimpossible.com) — the team behind [Candengo](https://www.candengo.com), Alchemy, and AIMY.
package/bin/build.mjs ADDED
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Build script — compiles TypeScript to Node.js-compatible JavaScript.
4
+ *
5
+ * Uses Bun's bundler to produce self-contained .js files that run on Node.js.
6
+ * Output goes to dist/ and is what gets published to npm.
7
+ */
8
+
9
+ import { rmSync, mkdirSync, copyFileSync, writeFileSync } from "node:fs";
10
+ import { join, dirname } from "node:path";
11
+ import { fileURLToPath } from "node:url";
12
+
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
14
+ const root = join(__dirname, "..");
15
+ const dist = join(root, "dist");
16
+
17
+ // Clean
18
+ rmSync(dist, { recursive: true, force: true });
19
+ mkdirSync(dist, { recursive: true });
20
+ mkdirSync(join(dist, "hooks"), { recursive: true });
21
+
22
+ console.log("Building Engrm for Node.js...\n");
23
+
24
+ // Build CLI + MCP server
25
+ const mainResult = await Bun.build({
26
+ entrypoints: [
27
+ join(root, "src/cli.ts"),
28
+ join(root, "src/server.ts"),
29
+ ],
30
+ outdir: dist,
31
+ target: "node",
32
+ format: "esm",
33
+ external: [
34
+ "better-sqlite3",
35
+ "sqlite-vec",
36
+ "@xenova/transformers",
37
+ "@modelcontextprotocol/sdk",
38
+ "@anthropic-ai/claude-agent-sdk",
39
+ ],
40
+ });
41
+
42
+ if (!mainResult.success) {
43
+ console.error("Build failed (main):");
44
+ for (const msg of mainResult.logs) console.error(msg);
45
+ process.exit(1);
46
+ }
47
+ console.log(" dist/cli.js");
48
+ console.log(" dist/server.js");
49
+
50
+ // Build hooks
51
+ const hookResult = await Bun.build({
52
+ entrypoints: [
53
+ join(root, "hooks/session-start.ts"),
54
+ join(root, "hooks/pre-compact.ts"),
55
+ join(root, "hooks/post-tool-use.ts"),
56
+ join(root, "hooks/stop.ts"),
57
+ join(root, "hooks/sentinel.ts"),
58
+ join(root, "hooks/elicitation-result.ts"),
59
+ ],
60
+ outdir: join(dist, "hooks"),
61
+ target: "node",
62
+ format: "esm",
63
+ external: [
64
+ "better-sqlite3",
65
+ "sqlite-vec",
66
+ "@xenova/transformers",
67
+ "@modelcontextprotocol/sdk",
68
+ "@anthropic-ai/claude-agent-sdk",
69
+ ],
70
+ });
71
+
72
+ if (!hookResult.success) {
73
+ console.error("Build failed (hooks):");
74
+ for (const msg of hookResult.logs) console.error(msg);
75
+ process.exit(1);
76
+ }
77
+ console.log(" dist/hooks/session-start.js");
78
+ console.log(" dist/hooks/pre-compact.js");
79
+ console.log(" dist/hooks/post-tool-use.js");
80
+ console.log(" dist/hooks/stop.js");
81
+ console.log(" dist/hooks/sentinel.js");
82
+ console.log(" dist/hooks/elicitation-result.js");
83
+
84
+ // Add Node.js shebang to CLI and hooks (strip any existing shebangs first)
85
+ async function addShebang(filePath) {
86
+ const raw = await Bun.file(filePath).text();
87
+ const stripped = raw.replace(/^#!.*\n/gm, "");
88
+ writeFileSync(filePath, `#!/usr/bin/env node\n${stripped}`);
89
+ }
90
+
91
+ await addShebang(join(dist, "cli.js"));
92
+ await addShebang(join(dist, "server.js"));
93
+ for (const hook of ["session-start", "pre-compact", "post-tool-use", "stop", "sentinel", "elicitation-result"]) {
94
+ await addShebang(join(dist, "hooks", `${hook}.js`));
95
+ }
96
+
97
+ console.log("\nBuild complete.");
package/bin/engrm.mjs ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Engrm CLI entry point for npm/npx.
4
+ * Runs the pre-built dist/cli.js on Node.js — no Bun required.
5
+ */
6
+ import { fileURLToPath } from "node:url";
7
+ import { dirname, join } from "node:path";
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = dirname(__filename);
11
+
12
+ // Import and run the built CLI
13
+ await import(join(__dirname, "..", "dist", "cli.js"));