@hiveai/cli 0.2.7 → 0.2.9
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 +406 -0
- package/dist/Dashboard-SRPCHP7Z.js +0 -0
- package/dist/index.js +138 -5
- package/dist/index.js.map +1 -1
- package/package.json +12 -12
package/README.md
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
# @hiveai/cli
|
|
2
|
+
|
|
3
|
+
> **hAIve** — team-first persistent memory layer for AI coding agents.
|
|
4
|
+
|
|
5
|
+
Stop re-explaining your project to every AI session. hAIve stores your team's conventions, architectural decisions, gotchas, and discovered patterns as version-controlled Markdown files. Every AI tool on your team reads the same shared knowledge automatically — via the MCP server, bridge files (CLAUDE.md, .cursorrules, Copilot instructions), or the CLI directly.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install -g @hiveai/cli
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This installs the `haive` command globally.
|
|
16
|
+
|
|
17
|
+
> **MCP server**: also install `@hiveai/mcp` to expose memories to Claude Code, Cursor, Copilot, and any MCP-compatible AI client.
|
|
18
|
+
> **Semantic search** (optional): install `@hiveai/embeddings` for local embedding-based search (no data leaves your machine).
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# 1. Initialize hAIve in your project
|
|
26
|
+
cd my-project
|
|
27
|
+
haive init
|
|
28
|
+
|
|
29
|
+
# 2. Start the MCP server (in Claude Code / Cursor MCP config)
|
|
30
|
+
haive mcp --root /absolute/path/to/my-project
|
|
31
|
+
|
|
32
|
+
# 3. Add a team memory
|
|
33
|
+
haive memory add \
|
|
34
|
+
--type gotcha \
|
|
35
|
+
--slug "open-in-view-false" \
|
|
36
|
+
--scope team \
|
|
37
|
+
--paths src/main/resources/application.properties \
|
|
38
|
+
--body "spring.jpa.open-in-view=false is intentional — do not re-enable."
|
|
39
|
+
|
|
40
|
+
# 4. Browse memories
|
|
41
|
+
haive memory list --scope team
|
|
42
|
+
|
|
43
|
+
# 5. Get a briefing before a task
|
|
44
|
+
haive briefing --task "add a payment endpoint" --scope team
|
|
45
|
+
|
|
46
|
+
# 6. Sync after a git pull
|
|
47
|
+
haive sync
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Commands
|
|
53
|
+
|
|
54
|
+
### `haive init`
|
|
55
|
+
|
|
56
|
+
Initialize the `.ai/` structure in a project and generate bridge files for your AI tools.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
haive init # Creates .ai/, CLAUDE.md, .cursorrules, copilot-instructions.md
|
|
60
|
+
haive init --no-bridges # Skip bridge file generation
|
|
61
|
+
haive init --with-ci # Also write .github/workflows/haive-sync.yml
|
|
62
|
+
haive init --dir /other/path # Initialize in a specific directory
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**What it creates:**
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
your-project/
|
|
69
|
+
├── .ai/
|
|
70
|
+
│ ├── project-context.md # Shared project overview (fill via bootstrap_project MCP prompt)
|
|
71
|
+
│ ├── modules/ # Per-component context files
|
|
72
|
+
│ └── memories/
|
|
73
|
+
│ ├── personal/ # Private to one developer
|
|
74
|
+
│ ├── team/ # Shared with the whole team (git-committed)
|
|
75
|
+
│ └── module/<name>/ # Scoped to a specific module/component
|
|
76
|
+
├── CLAUDE.md # Bridge for Claude Code (auto-generated)
|
|
77
|
+
├── .cursorrules # Bridge for Cursor (auto-generated)
|
|
78
|
+
└── .github/
|
|
79
|
+
└── copilot-instructions.md # Bridge for GitHub Copilot (auto-generated)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Bridge files include mandatory rules that tell agents to call `post_task` and `mem_tried` before closing a session, so knowledge is captured automatically.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### `haive mcp`
|
|
87
|
+
|
|
88
|
+
Start the hAIve MCP server over stdio. Point your AI client at this binary.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
haive mcp # Auto-detect project root
|
|
92
|
+
haive mcp --root /path/to/project # Explicit project root
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Claude Code** (`~/.claude.json`):
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"mcpServers": {
|
|
99
|
+
"haive": {
|
|
100
|
+
"command": "haive-mcp",
|
|
101
|
+
"args": ["--root", "/absolute/path/to/your/project"]
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Cursor** (`~/.cursor/mcp.json`):
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"mcpServers": {
|
|
111
|
+
"haive": {
|
|
112
|
+
"command": "haive-mcp",
|
|
113
|
+
"args": ["--root", "/absolute/path/to/your/project"]
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**VS Code**:
|
|
120
|
+
```bash
|
|
121
|
+
code --add-mcp '{"name":"haive","command":"haive-mcp","args":["--root","/path/to/project"]}'
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### `haive memory`
|
|
127
|
+
|
|
128
|
+
Manage individual memory entries.
|
|
129
|
+
|
|
130
|
+
#### `haive memory add`
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
haive memory add \
|
|
134
|
+
--type <type> \ # convention | decision | gotcha | architecture | glossary | attempt
|
|
135
|
+
--slug <slug> \ # Short identifier used in the filename
|
|
136
|
+
--scope team \ # personal (default) | team | module
|
|
137
|
+
--title "My title" \ # Optional heading (auto-added to body)
|
|
138
|
+
--tags "auth,jwt" \ # Comma-separated tags
|
|
139
|
+
--domain payments \ # Business domain for relevance scoring
|
|
140
|
+
--paths src/auth.ts \ # Anchor to files (enables staleness detection)
|
|
141
|
+
--symbols JwtFilter \ # Anchor to symbols/functions
|
|
142
|
+
--body "The knowledge." # Memory content (Markdown)
|
|
143
|
+
|
|
144
|
+
# Read body from a file (useful for long memories):
|
|
145
|
+
haive memory add --type architecture --slug "payment-flow" \
|
|
146
|
+
--body-file docs/payment-architecture.md
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Memory types:**
|
|
150
|
+
|
|
151
|
+
| Type | When to use |
|
|
152
|
+
|---|---|
|
|
153
|
+
| `convention` | How things are done here: naming, patterns, workflow |
|
|
154
|
+
| `decision` | A choice that was made and WHY (tradeoffs, constraints) |
|
|
155
|
+
| `gotcha` | Non-obvious behavior, traps, things that surprise newcomers |
|
|
156
|
+
| `architecture` | Structural overview of a system or module |
|
|
157
|
+
| `glossary` | Domain terms and their meaning in this project |
|
|
158
|
+
| `attempt` | Failed approach — prevents the same mistake next session |
|
|
159
|
+
|
|
160
|
+
#### `haive memory list`
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
haive memory list # All memories
|
|
164
|
+
haive memory list --scope team # Team memories only
|
|
165
|
+
haive memory list --status validated # Only validated
|
|
166
|
+
haive memory list --type gotcha # Gotchas only
|
|
167
|
+
haive memory list --tags auth,jwt # By tags (AND match)
|
|
168
|
+
haive memory list --module payments # Module-scoped memories
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### `haive memory query`
|
|
172
|
+
|
|
173
|
+
Full-text search across id, tags, and body.
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
haive memory query "flyway migration" # AND search across all tokens
|
|
177
|
+
haive memory query "payment mobile wave" # Falls back to OR if no AND match
|
|
178
|
+
haive memory query "jwt" --scope team --limit 5
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### `haive memory show`
|
|
182
|
+
|
|
183
|
+
Print the full body, frontmatter, and usage stats of a memory.
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
haive memory show 2025-01-15-gotcha-flyway-strict
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### `haive memory update`
|
|
190
|
+
|
|
191
|
+
Update a memory's body, tags, or anchor without changing its id or history.
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
haive memory update <id> --body "Updated content."
|
|
195
|
+
haive memory update <id> --tags "auth,jwt,security"
|
|
196
|
+
haive memory update <id> --paths src/auth.ts,src/jwt.ts
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### `haive memory verify`
|
|
200
|
+
|
|
201
|
+
Check anchor freshness — detect stale memories when anchored files or symbols have moved.
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
haive memory verify # Check all memories
|
|
205
|
+
haive memory verify --id <id> # Check a specific one
|
|
206
|
+
haive memory verify --update # Write stale/validated status back to disk
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
When a file is missing, hAIve searches the project for files with the same basename and suggests possible renames.
|
|
210
|
+
|
|
211
|
+
#### `haive memory approve` / `promote` / `reject`
|
|
212
|
+
|
|
213
|
+
Control the memory lifecycle: `draft → proposed → validated` or `rejected`.
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
haive memory approve <id> # Mark as validated
|
|
217
|
+
haive memory approve --all # Bulk-approve all proposed/draft
|
|
218
|
+
haive memory promote <id> # Promote personal → team (status: proposed)
|
|
219
|
+
haive memory reject <id> --reason "Outdated after refactor"
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### `haive memory tried`
|
|
223
|
+
|
|
224
|
+
Record a failed approach — the most valuable type of negative knowledge.
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
haive memory tried \
|
|
228
|
+
--what "importing gray-matter with ESM dynamic import" \
|
|
229
|
+
--why-failed "gray-matter doesn't export a default; named import required" \
|
|
230
|
+
--instead "import matter from 'gray-matter'" \
|
|
231
|
+
--scope team \
|
|
232
|
+
--paths src/parser.ts
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Auto-validated (no approval cycle needed). Surfaced first in `get_briefing` so agents see it before making the same mistake.
|
|
236
|
+
|
|
237
|
+
#### `haive memory import`
|
|
238
|
+
|
|
239
|
+
Import documentation (README, ADR, wiki page) as memories via the `import_docs` MCP prompt.
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
haive memory import --from docs/architecture.md --scope team
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Prints the MCP `import_docs` invocation to run in your AI client.
|
|
246
|
+
|
|
247
|
+
#### `haive memory for-files`
|
|
248
|
+
|
|
249
|
+
Show memories relevant to specific files you're about to edit.
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
haive memory for-files src/payments/PaymentService.java src/payments/PaymentController.java
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### `haive memory stats` / `hot` / `pending`
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
haive memory stats # Usage stats and confidence levels for all memories
|
|
259
|
+
haive memory hot # Most-read unvalidated memories (good promotion candidates)
|
|
260
|
+
haive memory pending # Proposed memories awaiting review
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### `haive briefing`
|
|
266
|
+
|
|
267
|
+
Print the full project briefing — project context + relevant memories — in one shot. Use before starting a task.
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
haive briefing # Full briefing, team scope
|
|
271
|
+
haive briefing --task "add a Stripe payment" # Filter by task relevance
|
|
272
|
+
haive briefing --files src/payments/PaymentService.java # Filter by files
|
|
273
|
+
haive briefing --scope all # Include personal memories
|
|
274
|
+
haive briefing --include-stale # Include stale memories
|
|
275
|
+
haive briefing --max-memories 15 # Show more memories
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
### `haive sync`
|
|
281
|
+
|
|
282
|
+
Refresh memory state after a `git pull` or merge.
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
haive sync # Verify anchors + auto-promote eligible memories
|
|
286
|
+
haive sync --since main # Report memories changed since main
|
|
287
|
+
haive sync --inject-bridge # Inject top memories into CLAUDE.md
|
|
288
|
+
haive sync --embed # Rebuild embeddings index after sync
|
|
289
|
+
haive sync --quiet # Minimal output (for git hooks)
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
**What sync does:**
|
|
293
|
+
1. Checks every anchored memory: does the file/symbol still exist? → marks `stale` if not
|
|
294
|
+
2. Re-validates previously stale memories that are now fresh again
|
|
295
|
+
3. Auto-promotes `proposed` memories that have been read enough times
|
|
296
|
+
4. Reports a decay warning for memories not read in >90 days
|
|
297
|
+
5. Optionally injects the top validated memories into your CLAUDE.md
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
### `haive install-hooks`
|
|
302
|
+
|
|
303
|
+
Install git hooks so `haive sync` runs automatically after every pull/merge.
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
haive install-hooks # Install post-merge and post-rewrite hooks
|
|
307
|
+
haive install-hooks --dir /path/to/project
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
### `haive embeddings`
|
|
313
|
+
|
|
314
|
+
Manage the local semantic search index (requires `@hiveai/embeddings` to be installed).
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
haive embeddings index # Build or refresh the embeddings index
|
|
318
|
+
haive embeddings status # Show index stats (count, last updated, model)
|
|
319
|
+
haive embeddings query "how do we handle retries on payment failures"
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
The model (`bge-small-en-v1.5`, ~110MB) is downloaded on first use and cached locally. **No data leaves your machine.**
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
### `haive index`
|
|
327
|
+
|
|
328
|
+
Build code navigation indexes.
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
haive index code # Build .ai/code-map.json (file → exports + 1-line descriptions)
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
The code map lets AI agents find where a function lives without grepping — dramatically reducing tool calls at the start of a task.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
### `haive tui`
|
|
339
|
+
|
|
340
|
+
Interactive terminal dashboard to browse, filter, and manage memories.
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
haive tui # Open the TUI (q to quit, arrow keys to navigate)
|
|
344
|
+
haive tui --dir /path/to/project
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Memory lifecycle
|
|
350
|
+
|
|
351
|
+
```
|
|
352
|
+
haive memory add → status: draft
|
|
353
|
+
haive memory promote → status: proposed (personal → team)
|
|
354
|
+
haive memory approve → status: validated
|
|
355
|
+
haive sync → status: stale (if anchor broken)
|
|
356
|
+
haive memory reject → status: rejected
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Validated team memories are loaded into every `get_briefing` call and injected into bridge files.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Multi-component projects
|
|
364
|
+
|
|
365
|
+
For projects with frontend + backend (or microservices), create one module context per component:
|
|
366
|
+
|
|
367
|
+
```bash
|
|
368
|
+
# After haive init, create module context files:
|
|
369
|
+
mkdir -p .ai/modules/backend .ai/modules/frontend
|
|
370
|
+
|
|
371
|
+
cat > .ai/modules/backend/context.md << 'EOF'
|
|
372
|
+
# Module: backend
|
|
373
|
+
- Spring Boot, Java 17, PostgreSQL
|
|
374
|
+
- Always filter by tenantId in every query
|
|
375
|
+
- Never modify existing Flyway migrations
|
|
376
|
+
EOF
|
|
377
|
+
|
|
378
|
+
cat > .ai/modules/frontend/context.md << 'EOF'
|
|
379
|
+
# Module: frontend
|
|
380
|
+
- React 19, TypeScript, TanStack Query
|
|
381
|
+
- All API calls go through hooks in features/<domain>/api/
|
|
382
|
+
- Env vars must be prefixed with VITE_
|
|
383
|
+
EOF
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
`get_briefing` auto-loads the relevant module context based on the files the agent is editing.
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Semantic search (optional)
|
|
391
|
+
|
|
392
|
+
Install `@hiveai/embeddings` for similarity-based memory retrieval:
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
npm install -g @hiveai/embeddings
|
|
396
|
+
haive embeddings index # First run downloads the model (~110MB)
|
|
397
|
+
haive embeddings query "payment retry logic"
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
From MCP: set `semantic: true` on `mem_search` or `get_briefing`.
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## License
|
|
405
|
+
|
|
406
|
+
MIT
|
|
File without changes
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command27 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/briefing.ts
|
|
7
7
|
import { existsSync } from "fs";
|
|
@@ -291,9 +291,49 @@ var BRIDGE_BODY = `<!-- hAIve bridge file \u2014 do not edit by hand. -->
|
|
|
291
291
|
|
|
292
292
|
See \`.ai/project-context.md\` for the full project context.
|
|
293
293
|
Memories live under \`.ai/memories/\` (personal/team/module).
|
|
294
|
+
|
|
295
|
+
## hAIve \u2014 mandatory rules for AI agents
|
|
296
|
+
- **Before** marking a task as done ("Done", "Finished", "C'est fait"), call the MCP prompt \`post_task\`.
|
|
297
|
+
- **Immediately** when an approach fails (wrong API, wrong pattern, wrong assumption), call \`mem_tried\` \u2014 do not wait until the end of the session.
|
|
298
|
+
- When starting a new task, call \`get_briefing\` with the task description to load relevant memories and avoid repeating past mistakes.
|
|
299
|
+
`;
|
|
300
|
+
var CI_WORKFLOW = `name: haive-sync
|
|
301
|
+
|
|
302
|
+
on:
|
|
303
|
+
push:
|
|
304
|
+
branches: [main, master]
|
|
305
|
+
pull_request:
|
|
306
|
+
paths:
|
|
307
|
+
- '.ai/**'
|
|
308
|
+
|
|
309
|
+
jobs:
|
|
310
|
+
sync:
|
|
311
|
+
runs-on: ubuntu-latest
|
|
312
|
+
steps:
|
|
313
|
+
- uses: actions/checkout@v4
|
|
314
|
+
with:
|
|
315
|
+
fetch-depth: 0
|
|
316
|
+
|
|
317
|
+
- uses: actions/setup-node@v4
|
|
318
|
+
with:
|
|
319
|
+
node-version: '20'
|
|
320
|
+
|
|
321
|
+
- name: Install hAIve CLI
|
|
322
|
+
run: npm install -g @haive/cli
|
|
323
|
+
|
|
324
|
+
- name: Sync memories (verify anchors + auto-promote)
|
|
325
|
+
run: haive sync --quiet
|
|
326
|
+
|
|
327
|
+
- name: Commit updated memories (if any)
|
|
328
|
+
run: |
|
|
329
|
+
git config user.name "github-actions[bot]"
|
|
330
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
331
|
+
git add .ai/
|
|
332
|
+
git diff --cached --quiet || git commit -m "chore: haive sync [skip ci]"
|
|
333
|
+
git push
|
|
294
334
|
`;
|
|
295
335
|
function registerInit(program2) {
|
|
296
|
-
program2.command("init").description("Initialize a hAIve project (.ai/ structure + bridge files)").option("-d, --dir <dir>", "project root", process.cwd()).option("--no-bridges", "do not generate CLAUDE.md / .cursorrules / copilot-instructions.md").action(async (opts) => {
|
|
336
|
+
program2.command("init").description("Initialize a hAIve project (.ai/ structure + bridge files)").option("-d, --dir <dir>", "project root", process.cwd()).option("--no-bridges", "do not generate CLAUDE.md / .cursorrules / copilot-instructions.md").option("--with-ci", "write a GitHub Actions workflow (.github/workflows/haive-sync.yml)").action(async (opts) => {
|
|
297
337
|
const root = path3.resolve(opts.dir);
|
|
298
338
|
const paths = resolveHaivePaths4(root);
|
|
299
339
|
if (existsSync3(paths.haiveDir)) {
|
|
@@ -312,6 +352,16 @@ function registerInit(program2) {
|
|
|
312
352
|
await writeBridge(root, ".cursorrules");
|
|
313
353
|
await writeBridge(root, path3.join(".github", "copilot-instructions.md"));
|
|
314
354
|
}
|
|
355
|
+
if (opts.withCi) {
|
|
356
|
+
const ciPath = path3.join(root, ".github", "workflows", "haive-sync.yml");
|
|
357
|
+
if (existsSync3(ciPath)) {
|
|
358
|
+
ui.info("CI workflow already exists \u2014 skipped");
|
|
359
|
+
} else {
|
|
360
|
+
await mkdir(path3.dirname(ciPath), { recursive: true });
|
|
361
|
+
await writeFile(ciPath, CI_WORKFLOW, "utf8");
|
|
362
|
+
ui.success(`Created ${path3.relative(root, ciPath)}`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
315
365
|
ui.success(`hAIve initialized at ${root}`);
|
|
316
366
|
ui.info("Next: " + ui.bold("haive memory add --type convention --slug <name>"));
|
|
317
367
|
});
|
|
@@ -429,6 +479,7 @@ import {
|
|
|
429
479
|
findProjectRoot as findProjectRoot8,
|
|
430
480
|
getUsage,
|
|
431
481
|
isAutoPromoteEligible,
|
|
482
|
+
isDecaying,
|
|
432
483
|
loadMemoriesFromDir as loadMemoriesFromDir2,
|
|
433
484
|
loadUsageIndex,
|
|
434
485
|
resolveHaivePaths as resolveHaivePaths5,
|
|
@@ -444,7 +495,7 @@ function registerSync(program2) {
|
|
|
444
495
|
).option("--no-verify", "skip the anchor verification step").option("--no-promote", "skip the auto-promotion step").option(
|
|
445
496
|
"--inject-bridge",
|
|
446
497
|
"inject top validated memories into CLAUDE.md (or --bridge-file) between <!-- haive:memories-start/end --> markers"
|
|
447
|
-
).option("--bridge-file <path>", "bridge file to inject into (default: CLAUDE.md)").option("--bridge-max-memories <n>", "max memories to inject into bridge file", "5").action(async (opts) => {
|
|
498
|
+
).option("--bridge-file <path>", "bridge file to inject into (default: CLAUDE.md)").option("--bridge-max-memories <n>", "max memories to inject into bridge file", "5").option("--embed", "rebuild embeddings index after sync (requires @haive/embeddings)").action(async (opts) => {
|
|
448
499
|
const root = findProjectRoot8(opts.dir);
|
|
449
500
|
const paths = resolveHaivePaths5(root);
|
|
450
501
|
if (!existsSync6(paths.memoriesDir)) {
|
|
@@ -555,6 +606,33 @@ function registerSync(program2) {
|
|
|
555
606
|
for (const f of sinceReport.removed) log(` - ${f}`);
|
|
556
607
|
}
|
|
557
608
|
}
|
|
609
|
+
if (!opts.quiet) {
|
|
610
|
+
const allForDecay = await loadMemoriesFromDir2(paths.memoriesDir);
|
|
611
|
+
const usageForDecay = await loadUsageIndex(paths);
|
|
612
|
+
const decaying = allForDecay.filter(({ memory: memory2 }) => {
|
|
613
|
+
const fm = memory2.frontmatter;
|
|
614
|
+
if (fm.status === "rejected" || fm.status === "deprecated" || fm.status === "stale") return false;
|
|
615
|
+
const u = getUsage(usageForDecay, fm.id);
|
|
616
|
+
return isDecaying(u, fm.created_at);
|
|
617
|
+
});
|
|
618
|
+
if (decaying.length > 0) {
|
|
619
|
+
log(ui.yellow(`
|
|
620
|
+
\u26A0 ${decaying.length} memor${decaying.length === 1 ? "y" : "ies"} not read in >90 days (consider reviewing or deprecating):`));
|
|
621
|
+
for (const { memory: memory2 } of decaying) {
|
|
622
|
+
log(ui.dim(` ${memory2.frontmatter.id}`));
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
if (opts.embed) {
|
|
627
|
+
try {
|
|
628
|
+
const emb = await import("@hiveai/embeddings");
|
|
629
|
+
log(ui.dim("embed: rebuilding index\u2026"));
|
|
630
|
+
const report = await emb.rebuildIndex(paths);
|
|
631
|
+
log(ui.dim(`embed: index rebuilt (${report.added} added, ${report.updated} updated, ${report.removed} removed)`));
|
|
632
|
+
} catch {
|
|
633
|
+
ui.warn("--embed: @hiveai/embeddings not available or index build failed. Run `haive embeddings index` manually.");
|
|
634
|
+
}
|
|
635
|
+
}
|
|
558
636
|
});
|
|
559
637
|
}
|
|
560
638
|
async function injectBridge(bridgeFile, memoriesDir, maxMemories, root, quiet) {
|
|
@@ -1698,6 +1776,9 @@ function registerMemoryVerify(memory2) {
|
|
|
1698
1776
|
console.log(`${ui.bold("STALE")} ${mem.frontmatter.id}`);
|
|
1699
1777
|
console.log(` ${ui.dim(rel)}`);
|
|
1700
1778
|
console.log(` ${result.reason}`);
|
|
1779
|
+
if (result.possibleRenames.length > 0) {
|
|
1780
|
+
console.log(` ${ui.yellow("Possible renames:")} ${result.possibleRenames.join(", ")}`);
|
|
1781
|
+
}
|
|
1701
1782
|
} else {
|
|
1702
1783
|
freshCount++;
|
|
1703
1784
|
console.log(`${ui.dim("fresh")} ${mem.frontmatter.id}`);
|
|
@@ -1751,9 +1832,60 @@ function applyVerification(mem, result) {
|
|
|
1751
1832
|
};
|
|
1752
1833
|
}
|
|
1753
1834
|
|
|
1835
|
+
// src/commands/memory-import.ts
|
|
1836
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
1837
|
+
import { existsSync as existsSync24 } from "fs";
|
|
1838
|
+
import "commander";
|
|
1839
|
+
import {
|
|
1840
|
+
findProjectRoot as findProjectRoot26,
|
|
1841
|
+
resolveHaivePaths as resolveHaivePaths23
|
|
1842
|
+
} from "@hiveai/core";
|
|
1843
|
+
function registerMemoryImport(memory2) {
|
|
1844
|
+
memory2.command("import").description(
|
|
1845
|
+
"Parse a Markdown file and suggest memories via the import_docs MCP prompt (prints a ready-to-use prompt invocation)"
|
|
1846
|
+
).requiredOption("--from <file>", "Markdown/text file to import from").option("--scope <scope>", "personal | team (default: team)", "team").option("-d, --dir <dir>", "project root").action(async (opts) => {
|
|
1847
|
+
const root = findProjectRoot26(opts.dir);
|
|
1848
|
+
const paths = resolveHaivePaths23(root);
|
|
1849
|
+
if (!existsSync24(paths.haiveDir)) {
|
|
1850
|
+
ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
|
|
1851
|
+
process.exitCode = 1;
|
|
1852
|
+
return;
|
|
1853
|
+
}
|
|
1854
|
+
if (!existsSync24(opts.from)) {
|
|
1855
|
+
ui.error(`File not found: ${opts.from}`);
|
|
1856
|
+
process.exitCode = 1;
|
|
1857
|
+
return;
|
|
1858
|
+
}
|
|
1859
|
+
const content = await readFile7(opts.from, "utf8");
|
|
1860
|
+
const scope = opts.scope ?? "team";
|
|
1861
|
+
ui.info(`Preparing import from: ${opts.from} (scope=${scope})`);
|
|
1862
|
+
ui.info(`Content length: ${content.length} chars`);
|
|
1863
|
+
console.log();
|
|
1864
|
+
console.log(ui.bold("To import via MCP, invoke the `import_docs` prompt with:"));
|
|
1865
|
+
console.log();
|
|
1866
|
+
console.log(
|
|
1867
|
+
ui.dim(
|
|
1868
|
+
JSON.stringify(
|
|
1869
|
+
{
|
|
1870
|
+
content: content.slice(0, 200) + (content.length > 200 ? "\u2026" : ""),
|
|
1871
|
+
source: opts.from,
|
|
1872
|
+
scope
|
|
1873
|
+
},
|
|
1874
|
+
null,
|
|
1875
|
+
2
|
|
1876
|
+
)
|
|
1877
|
+
)
|
|
1878
|
+
);
|
|
1879
|
+
console.log();
|
|
1880
|
+
ui.info(
|
|
1881
|
+
'Or use your AI client to call: import_docs({ content: <file contents>, source: "' + opts.from + '", scope: "' + scope + '" })'
|
|
1882
|
+
);
|
|
1883
|
+
});
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1754
1886
|
// src/index.ts
|
|
1755
|
-
var program = new
|
|
1756
|
-
program.name("haive").description("hAIve \u2014 team-first persistent memory layer for AI coding agents").version("0.2.
|
|
1887
|
+
var program = new Command27();
|
|
1888
|
+
program.name("haive").description("hAIve \u2014 team-first persistent memory layer for AI coding agents").version("0.2.9");
|
|
1757
1889
|
registerInit(program);
|
|
1758
1890
|
registerMcp(program);
|
|
1759
1891
|
registerBriefing(program);
|
|
@@ -1780,6 +1912,7 @@ registerMemoryApprove(memory);
|
|
|
1780
1912
|
registerMemoryUpdate(memory);
|
|
1781
1913
|
registerMemoryHot(memory);
|
|
1782
1914
|
registerMemoryTried(memory);
|
|
1915
|
+
registerMemoryImport(memory);
|
|
1783
1916
|
program.parseAsync(process.argv).catch((err) => {
|
|
1784
1917
|
if (isZodError(err)) {
|
|
1785
1918
|
for (const issue of err.issues) {
|