groove-dev 0.27.139 → 0.27.141

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 (75) hide show
  1. package/node_modules/@groove-dev/cli/package.json +1 -1
  2. package/node_modules/@groove-dev/daemon/integrations-registry.json +12 -44
  3. package/node_modules/@groove-dev/daemon/package.json +1 -1
  4. package/node_modules/@groove-dev/daemon/src/api.js +225 -16
  5. package/node_modules/@groove-dev/daemon/src/index.js +2 -0
  6. package/node_modules/@groove-dev/daemon/src/integrations.js +10 -0
  7. package/node_modules/@groove-dev/daemon/src/introducer.js +17 -1
  8. package/node_modules/@groove-dev/daemon/src/journalist.js +169 -0
  9. package/node_modules/@groove-dev/daemon/src/keeper.js +277 -0
  10. package/node_modules/@groove-dev/daemon/src/model-lab.js +11 -0
  11. package/node_modules/@groove-dev/daemon/src/process.js +76 -0
  12. package/node_modules/@groove-dev/daemon/src/validate.js +9 -0
  13. package/node_modules/@groove-dev/gui/dist/assets/index-A4e1gIDh.css +1 -0
  14. package/node_modules/@groove-dev/gui/dist/assets/index-P1hsM27-.js +8696 -0
  15. package/node_modules/@groove-dev/gui/dist/index.html +2 -2
  16. package/node_modules/@groove-dev/gui/package.json +1 -1
  17. package/node_modules/@groove-dev/gui/src/app.jsx +4 -0
  18. package/node_modules/@groove-dev/gui/src/components/agents/agent-chat.jsx +41 -17
  19. package/node_modules/@groove-dev/gui/src/components/agents/agent-file-tree.jsx +10 -3
  20. package/node_modules/@groove-dev/gui/src/components/agents/code-review.jsx +5 -4
  21. package/node_modules/@groove-dev/gui/src/components/agents/workspace-mode.jsx +160 -12
  22. package/node_modules/@groove-dev/gui/src/components/editor/ai-panel.jsx +77 -6
  23. package/node_modules/@groove-dev/gui/src/components/editor/file-tree.jsx +2 -86
  24. package/node_modules/@groove-dev/gui/src/components/editor/terminal.jsx +15 -4
  25. package/node_modules/@groove-dev/gui/src/components/keeper/global-modals.jsx +177 -0
  26. package/node_modules/@groove-dev/gui/src/components/layout/activity-bar.jsx +11 -6
  27. package/node_modules/@groove-dev/gui/src/components/layout/terminal-panel.jsx +152 -3
  28. package/node_modules/@groove-dev/gui/src/components/marketplace/integration-wizard.jsx +223 -18
  29. package/node_modules/@groove-dev/gui/src/stores/groove.js +302 -20
  30. package/node_modules/@groove-dev/gui/src/views/agents.jsx +118 -60
  31. package/node_modules/@groove-dev/gui/src/views/editor.jsx +67 -219
  32. package/node_modules/@groove-dev/gui/src/views/memory.jsx +460 -0
  33. package/node_modules/@groove-dev/gui/src/views/model-lab.jsx +1 -6
  34. package/node_modules/@groove-dev/gui/src/views/models.jsx +658 -565
  35. package/package.json +1 -1
  36. package/packages/cli/package.json +1 -1
  37. package/packages/daemon/integrations-registry.json +12 -44
  38. package/packages/daemon/package.json +1 -1
  39. package/packages/daemon/src/api.js +225 -16
  40. package/packages/daemon/src/index.js +2 -0
  41. package/packages/daemon/src/integrations.js +10 -0
  42. package/packages/daemon/src/introducer.js +17 -1
  43. package/packages/daemon/src/journalist.js +169 -0
  44. package/packages/daemon/src/keeper.js +277 -0
  45. package/packages/daemon/src/model-lab.js +11 -0
  46. package/packages/daemon/src/process.js +76 -0
  47. package/packages/daemon/src/validate.js +9 -0
  48. package/packages/gui/dist/assets/index-A4e1gIDh.css +1 -0
  49. package/packages/gui/dist/assets/index-P1hsM27-.js +8696 -0
  50. package/packages/gui/dist/index.html +2 -2
  51. package/packages/gui/package.json +1 -1
  52. package/packages/gui/src/app.jsx +4 -0
  53. package/packages/gui/src/components/agents/agent-chat.jsx +41 -17
  54. package/packages/gui/src/components/agents/agent-file-tree.jsx +10 -3
  55. package/packages/gui/src/components/agents/code-review.jsx +5 -4
  56. package/packages/gui/src/components/agents/workspace-mode.jsx +160 -12
  57. package/packages/gui/src/components/editor/ai-panel.jsx +77 -6
  58. package/packages/gui/src/components/editor/file-tree.jsx +2 -86
  59. package/packages/gui/src/components/editor/terminal.jsx +15 -4
  60. package/packages/gui/src/components/keeper/global-modals.jsx +177 -0
  61. package/packages/gui/src/components/layout/activity-bar.jsx +11 -6
  62. package/packages/gui/src/components/layout/terminal-panel.jsx +152 -3
  63. package/packages/gui/src/components/marketplace/integration-wizard.jsx +223 -18
  64. package/packages/gui/src/stores/groove.js +302 -20
  65. package/packages/gui/src/views/agents.jsx +118 -60
  66. package/packages/gui/src/views/editor.jsx +67 -219
  67. package/packages/gui/src/views/memory.jsx +460 -0
  68. package/packages/gui/src/views/model-lab.jsx +1 -6
  69. package/packages/gui/src/views/models.jsx +658 -565
  70. package/plan_files/keeper-manual.md +295 -0
  71. package/plan_files/keeper-memory-system.md +223 -0
  72. package/node_modules/@groove-dev/gui/dist/assets/index-AkOtskHS.css +0 -1
  73. package/node_modules/@groove-dev/gui/dist/assets/index-B4uYLR57.js +0 -8694
  74. package/packages/gui/dist/assets/index-AkOtskHS.css +0 -1
  75. package/packages/gui/dist/assets/index-B4uYLR57.js +0 -8694
@@ -0,0 +1,295 @@
1
+ # Keeper — Instruction Manual
2
+
3
+ ## What It Is
4
+
5
+ Keeper is your personal tagged notebook inside GROOVE. Save ideas, context, and decisions from agent conversations and pull them into new sessions with a single command. No AI decides what's important — you control every word.
6
+
7
+ Two types of content:
8
+ - **Manual** — you write it via `[save]`, `[append]`, `[update]`
9
+ - **Doc** — AI writes it via `[doc]`, synthesizing your conversation into a structured document
10
+
11
+ ---
12
+
13
+ ## Commands
14
+
15
+ All commands work in any agent chat. Brackets are optional — `save #tag` and `[save] #tag` both work. The command and tag are stripped out; your message still gets sent to the agent.
16
+
17
+ ### Saving
18
+
19
+ **`save #tag`** — Save the message content under a tag and send the message to the agent. Creates or overwrites.
20
+
21
+ ```
22
+ the sky is blue save #thought
23
+ → Saves "the sky is blue" to #thought
24
+ → Agent receives "the sky is blue" and responds normally
25
+
26
+ we're going with REST over GraphQL because of team familiarity save #design-decision
27
+ → Saves to #design-decision AND the agent gets your message
28
+
29
+ this routing approach works well for our use case save #groove/routing
30
+ → Saves to #groove/routing (nested under groove)
31
+ ```
32
+
33
+ The command can appear anywhere in your message. Everything except the command word and `#tag` becomes the saved content, and the agent gets it too.
34
+
35
+ **`append #tag`** — Add content to an existing memory with a `---` separator. Also sends to the agent. Same syntax as save.
36
+
37
+ ```
38
+ actually we should also consider WebSockets append #design-decision
39
+ → Adds "actually we should also consider WebSockets" to the bottom of #design-decision
40
+ → Agent receives the message too
41
+ ```
42
+
43
+ If the tag doesn't exist yet, `append` creates it (same as `save`).
44
+
45
+ ### Editing
46
+
47
+ **`update #tag`** — Opens the editor modal with the current content for in-place editing. Full textarea, Cmd+S to save.
48
+
49
+ ```
50
+ update #design-decision
51
+ → Opens editor with the current content of #design-decision
52
+ ```
53
+
54
+ If the tag doesn't exist, opens a blank editor to create it. This command is intercepted — not sent to the agent.
55
+
56
+ ### Viewing
57
+
58
+ **`view #tag`** — Opens a read-only modal to review content without risk of editing.
59
+
60
+ ```
61
+ view #design-decision
62
+ → Opens read-only viewer showing the full content
63
+ ```
64
+
65
+ Intercepted — not sent to the agent.
66
+
67
+ ### Reading
68
+
69
+ **`read #tag1 #tag2 ...`** — Sends the memory content to the agent behind the scenes. The agent reads it alongside whatever else you type, but the raw content doesn't flood your chat. You just see a confirmation.
70
+
71
+ ```
72
+ read #memory-system
73
+ → "Sent #memory-system to agent"
74
+ → Agent has the full content and can work with it
75
+
76
+ read #design-decision #groove/routing
77
+ → Agent receives both memories
78
+ ```
79
+
80
+ Reading a parent tag pulls all children automatically. `read #groove` sends `#groove/routing`, `#groove/memory-system`, and anything else under `#groove`.
81
+
82
+ Intercepted — not sent to the agent as your message (the content goes as context).
83
+
84
+ ### AI Doc Generation
85
+
86
+ **`doc #tag`** — AI reads the full chat history of the current agent conversation and generates a comprehensive document. The result opens in the editor for your review and editing.
87
+
88
+ ```
89
+ doc #memory-system
90
+ → AI synthesizes the conversation into a structured doc
91
+ → Opens in editor so you can review/edit before it's final
92
+ ```
93
+
94
+ The generated doc includes:
95
+ - Core idea and motivation
96
+ - Key decisions from the discussion
97
+ - Architecture / design choices
98
+ - Implementation plan (if discussed)
99
+ - Open questions / next steps
100
+
101
+ If the journalist headless mode isn't available (no API key), falls back to a raw transcript.
102
+
103
+ ### Linking
104
+
105
+ **`link #tag path/to/doc`** — Links a memory tag to a NORTHSTAR or external document for cross-referencing.
106
+
107
+ ```
108
+ link #design-decision plan_files/NORTHSTAR.md
109
+ → Links #design-decision to the NORTHSTAR doc
110
+ ```
111
+
112
+ Links show up as badges on memory cards in the Memory view.
113
+
114
+ ### Help
115
+
116
+ **`[instruct]`** — Opens the command reference modal with all commands, tag hierarchy guide, and memory types. (This one needs brackets since it has no `#tag` to disambiguate.)
117
+
118
+ ### Deleting
119
+
120
+ **`delete #tag`** — Permanently removes a memory.
121
+
122
+ ```
123
+ delete #old-idea
124
+ → Gone
125
+ ```
126
+
127
+ ---
128
+
129
+ ## Tag Hierarchy
130
+
131
+ Tags use `/` for namespacing. This creates a folder structure:
132
+
133
+ ```
134
+ #groove → top-level
135
+ #groove/routing → child of groove
136
+ #groove/memory-system → child of groove
137
+ #design/frontend → child of design
138
+ #design/backend → child of design
139
+ ```
140
+
141
+ When you `[pull] #groove`, you get all children too — `#groove/routing` and `#groove/memory-system` are included automatically.
142
+
143
+ In the Memory view, tree mode shows this as collapsible folders.
144
+
145
+ ### Tag Rules
146
+ - Lowercase only (auto-converted)
147
+ - Letters, numbers, `/`, `-`, `_` allowed
148
+ - No spaces, no special characters
149
+ - Max 20 tags per agent when spawning with `keeperTags`
150
+
151
+ ---
152
+
153
+ ## Memory View
154
+
155
+ Access from the activity bar (BookOpen icon, between Dashboard and Teams).
156
+
157
+ ### List View
158
+ - Cards with content preview (first 3 lines)
159
+ - Relative timestamps ("5m ago", "2d ago")
160
+ - Size indicator
161
+ - Type badge: purple "AI" sparkle for doc-generated memories
162
+ - Link count badges
163
+ - Hover to reveal edit/delete buttons
164
+
165
+ ### Tree View
166
+ - Collapsible folder hierarchy following tag namespacing
167
+ - Click a tag to open the editor
168
+ - Virtual folders appear for parent paths that don't have their own content
169
+
170
+ ### Search
171
+ - Filters by tag name in real-time
172
+
173
+ ### New Button
174
+ - Opens editor modal with tag input + content textarea
175
+ - Tag input auto-sanitizes (lowercase, valid chars only)
176
+
177
+ ---
178
+
179
+ ## Syntax Highlighting
180
+
181
+ In agent chat, Keeper syntax highlights in real-time:
182
+ - `[save]`, `[pull]`, etc. — teal accent pills
183
+ - `#tag-name` — accent-colored text
184
+
185
+ This works in both sent messages and the input textarea (via a transparent overlay).
186
+
187
+ ---
188
+
189
+ ## Spawning Agents with Context
190
+
191
+ When spawning a new agent, you can pre-load memories via `keeperTags` in the agent config:
192
+
193
+ ```json
194
+ {
195
+ "role": "frontend",
196
+ "keeperTags": ["design-decision", "groove/routing"]
197
+ }
198
+ ```
199
+
200
+ The introducer pulls those memories and injects them as a "Keeper Context" section in the agent's intro prompt. Budget: 5KB max.
201
+
202
+ ---
203
+
204
+ ## How It Works Under the Hood
205
+
206
+ ### Storage
207
+ ```
208
+ .groove/keeper/
209
+ ├── index.json — tag metadata (type, links, timestamps, size)
210
+ ├── thought.md — flat tag: #thought
211
+ ├── design-decision.md — flat tag: #design-decision
212
+ └── groove/
213
+ ├── routing.md — nested: #groove/routing
214
+ └── memory-system.md — nested: #groove/memory-system
215
+ ```
216
+
217
+ Each tag = one `.md` file. `index.json` stores metadata only.
218
+
219
+ ### API Endpoints
220
+
221
+ 14 endpoints under `/api/keeper/`:
222
+
223
+ | Method | Path | What It Does |
224
+ |--------|------|--------------|
225
+ | GET | `/api/keeper` | List all memories (metadata only) |
226
+ | GET | `/api/keeper/tree` | Hierarchical tree structure |
227
+ | GET | `/api/keeper/search?q=` | Search tags and content |
228
+ | GET | `/api/keeper/commands` | Command reference data |
229
+ | GET | `/api/keeper/:tag` | Read single memory with content |
230
+ | POST | `/api/keeper` | Save `{ tag, content }` |
231
+ | POST | `/api/keeper/append` | Append `{ tag, content }` |
232
+ | POST | `/api/keeper/pull` | Assemble brief from `{ tags: [...] }` |
233
+ | POST | `/api/keeper/doc` | AI synthesis from `{ tag, chatHistory, agentId }` |
234
+ | POST | `/api/keeper/link` | Link `{ tag, docPath }` |
235
+ | POST | `/api/keeper/parse` | Parse command text |
236
+ | PATCH | `/api/keeper/:tag` | Update content |
237
+ | DELETE | `/api/keeper/link/:tag` | Unlink a document |
238
+ | DELETE | `/api/keeper/:tag` | Delete memory |
239
+
240
+ ### Real-Time Sync
241
+
242
+ All mutations broadcast via WebSocket (`keeper:saved`, `keeper:updated`, `keeper:deleted`). Multiple browser tabs stay in sync.
243
+
244
+ ---
245
+
246
+ ## Testing Checklist
247
+
248
+ ### Basic Flow
249
+ - [ ] Type `hello world save #test` in agent chat → saves "hello world", agent also receives "hello world"
250
+ - [ ] Type `the sky is blue save #test2` → saves "the sky is blue" to #test2, agent gets the message
251
+ - [ ] `save` and `#test` highlight teal as you type in the input
252
+ - [ ] Navigate to Memory view → both #test and #test2 appear
253
+ - [ ] Click edit icon on #test → editor opens with "hello world"
254
+ - [ ] Modify content, Cmd+S → saves, card updates
255
+
256
+ ### All Commands (brackets optional)
257
+ - [ ] `more thoughts append #test` → adds with separator, agent gets "more thoughts"
258
+ - [ ] `update #test` → opens editor modal (intercepted, not sent to agent)
259
+ - [ ] `view #test` → opens read-only modal (intercepted)
260
+ - [ ] `read #test` → "Sent #test to agent", agent receives content, chat stays clean
261
+ - [ ] `doc #test` → "Generating doc..." message, editor opens with result
262
+ - [ ] `link #test plan_files/keeper-manual.md` → links successfully
263
+ - [ ] `[instruct]` → command reference modal opens (brackets required for this one)
264
+ - [ ] `delete #test` → memory removed
265
+
266
+ ### Brackets Still Work
267
+ - [ ] `[save] #test hello` → same behavior as `hello save #test`
268
+ - [ ] `[update] #test` → same as `update #test`
269
+
270
+ ### Hierarchy
271
+ - [ ] `[save] #project/frontend layout decisions here` → creates nested tag
272
+ - [ ] `[save] #project/backend api design here` → second child
273
+ - [ ] Memory view tree mode shows "project" folder with both children
274
+ - [ ] `[pull] #project` → injects both children
275
+
276
+ ### Edge Cases
277
+ - [ ] `save #tag` with no content → shows usage hint
278
+ - [ ] `save` with no tag → not intercepted (no `#tag` to match), sent to agent normally
279
+ - [ ] `view #nonexistent` → "not found" message
280
+ - [ ] `read #nonexistent` → "no memories found" message
281
+ - [ ] Very long content (5KB+) → saves and displays correctly
282
+
283
+ ### Memory View
284
+ - [ ] Empty state shows onboarding text + "Create first memory" button
285
+ - [ ] List/Tree toggle works
286
+ - [ ] Search filters by tag name
287
+ - [ ] "New" button opens editor with tag input
288
+ - [ ] Delete from card hover button works
289
+ - [ ] Instruct button (?) opens command reference
290
+
291
+ ### Cross-View
292
+ - [ ] Save from agent chat → Memory view updates
293
+ - [ ] Edit in Memory view → reflected when pulled in chat
294
+ - [ ] Global modals work from non-memory views (agents view, dashboard, etc.)
295
+ - [ ] Global modals don't duplicate when ON memory view
@@ -0,0 +1,223 @@
1
+ # Keeper — Tagged Memory System
2
+
3
+ ## What This Is
4
+
5
+ Keeper is a lightweight tagged memory system for GROOVE that gives users direct, explicit control over saving and retrieving context across agent sessions. It solves the problem of context loss when spawning new agents — instead of manually pointing each agent to scattered docs, users tag ideas inline and pull them into new sessions with a single command.
6
+
7
+ ## Why We're Building It
8
+
9
+ When working with multiple agents across sessions, the user repeatedly has to explain the same context: "read NORTHSTAR.md, read this doc, read that doc." This is inefficient for both the user and the agent. The user also loses nuanced ideas — the small decisions, adjustments, and explorations that happen during conversations but never make it into formal docs.
10
+
11
+ Keeper is the user's personal notebook. Not an AI brain that decides what's important — a notebook where the user controls every word. Two types of content:
12
+
13
+ 1. **Manual memories** — the user writes exactly what they want saved. No synthesis, no interpretation. "Write that down."
14
+ 2. **Doc memories** — for longer explorations, AI reads the full conversation and generates a comprehensive document. The user still reviews and edits.
15
+
16
+ This complements NORTHSTAR (formal strategy docs) rather than replacing it. NORTHSTAR is the plan. Keeper is the working notes, ideas, and context that feed into the plan.
17
+
18
+ ## Design Principles
19
+
20
+ - **One tag = one document.** No versioning, no stacking, no timestamps cluttering things up. `#memory-system` is a single block of text.
21
+ - **User owns every word.** `[save]` creates it, `[update]` lets you edit it, `[append]` adds to the bottom. Nothing goes in that the user didn't approve.
22
+ - **Hierarchy is just namespacing.** `#groove/memory-system` and `#groove/routing` live under `#groove`. Not a graph database — just folders.
23
+ - **The modal is the source of truth.** Every mutation goes through an editor modal or explicit chat command. No background magic.
24
+ - **Sidecar pattern.** Commands are intercepted before they reach the agent. The agent never sees `[save]` or `[pull]` — Keeper handles it silently.
25
+
26
+ ## Command Grammar
27
+
28
+ All commands are typed in agent chat. Keeper intercepts them before the agent sees the message.
29
+
30
+ | Command | Syntax | Behavior |
31
+ |---------|--------|----------|
32
+ | `[save]` | `[save] #tag content...` | Save the message content under the tag. Creates or overwrites. |
33
+ | `[append]` | `[append] #tag content...` | Add content to an existing memory with a `---` separator. |
34
+ | `[update]` | `[update] #tag` | Opens editor modal with current content for in-place editing. |
35
+ | `[delete]` | `[delete] #tag` | Permanently removes the memory. |
36
+ | `[view]` | `[view] #tag` | Opens read-only modal to review content. |
37
+ | `[pull]` | `[pull] #tag1 #tag2 ...` | Injects memory content into the active agent's context as an instruction. |
38
+ | `[read]` | `[read] #tag` | Alias for `[pull]`. |
39
+ | `[doc]` | `[doc] #tag` | AI reads the full chat history and generates a comprehensive document. Opens result in editor for review. |
40
+ | `[link]` | `[link] #tag path/to/doc` | Links a memory tag to a NORTHSTAR or external document for cross-referencing. |
41
+ | `[instruct]` | `[instruct]` | Opens the command reference modal. |
42
+
43
+ ## Architecture
44
+
45
+ ### Storage
46
+
47
+ ```
48
+ .groove/keeper/
49
+ ├── index.json — tag metadata (type, links, timestamps, size)
50
+ ├── memory-system.md — flat tag
51
+ ├── groove/
52
+ │ ├── routing.md — nested: groove/routing
53
+ │ └── memory-system.md — nested: groove/memory-system
54
+ └── northstar.md
55
+ ```
56
+
57
+ - Each tag is a single `.md` file. The filename mirrors the tag path.
58
+ - `index.json` stores metadata only — the content lives in the `.md` files.
59
+ - Hierarchy is filesystem directories. `#groove/routing` → `groove/routing.md`.
60
+
61
+ ### Daemon Module: `keeper.js`
62
+
63
+ **Location:** `packages/daemon/src/keeper.js`
64
+
65
+ The `Keeper` class handles all file I/O and tag management:
66
+
67
+ - **Constructor** — creates `.groove/keeper/` directory, loads `index.json`
68
+ - **CRUD** — `save()`, `append()`, `update()`, `get()`, `delete()`
69
+ - **Doc** — `saveDoc()` stores content with `type: 'doc'` metadata
70
+ - **Links** — `link()` / `unlink()` associate tags with external doc paths
71
+ - **Query** — `list()`, `tree()`, `children()`, `search()`
72
+ - **Parser** — static `parseCommand(text)` extracts command + tags from chat input
73
+
74
+ Exports `KEEPER_COMMANDS` — a reference object of all 10 commands with syntax and descriptions.
75
+
76
+ ### Daemon Wiring
77
+
78
+ **`index.js`** — `this.keeper = new Keeper(this.grooveDir)` instantiated alongside other modules.
79
+
80
+ **`api.js`** — 14 REST endpoints under `/api/keeper/`:
81
+
82
+ | Method | Path | Purpose |
83
+ |--------|------|---------|
84
+ | GET | `/api/keeper` | List all memories |
85
+ | GET | `/api/keeper/tree` | Hierarchical tree structure |
86
+ | GET | `/api/keeper/search?q=` | Search tags and content |
87
+ | GET | `/api/keeper/commands` | Command reference data |
88
+ | GET | `/api/keeper/:tag(*)` | Read single memory (wildcard for nested tags) |
89
+ | POST | `/api/keeper` | Save `{ tag, content }` |
90
+ | POST | `/api/keeper/append` | Append `{ tag, content }` |
91
+ | POST | `/api/keeper/pull` | Assemble brief from `{ tags: [...] }` |
92
+ | POST | `/api/keeper/doc` | AI synthesis — sends chat history to journalist.callHeadless |
93
+ | POST | `/api/keeper/link` | Link `{ tag, docPath }` |
94
+ | POST | `/api/keeper/parse` | Parse command text |
95
+ | PATCH | `/api/keeper/:tag(*)` | Update content |
96
+ | DELETE | `/api/keeper/:tag(*)` | Delete memory |
97
+ | DELETE | `/api/keeper/link/:tag(*)` | Unlink document |
98
+
99
+ All mutations call `daemon.audit.log()` and `daemon.broadcast()` for real-time sync.
100
+
101
+ **Route order matters:** Static paths (`/tree`, `/search`, `/commands`) are registered before the wildcard `/:tag(*)` so Express matches them first.
102
+
103
+ ### Context Injection on Spawn
104
+
105
+ **`introducer.js`** — After the existing Layer 7 memory injection, a new "Keeper Context" section is appended if the agent config includes `keeperTags`:
106
+
107
+ ```javascript
108
+ if (this.daemon.keeper && newAgent.keeperTags?.length > 0) {
109
+ const brief = this.daemon.keeper.pull(newAgent.keeperTags);
110
+ // Injected as "## Keeper Context (user-tagged memories)" section
111
+ // Hard budget: 5KB
112
+ }
113
+ ```
114
+
115
+ **`validate.js`** — `keeperTags` added to the validated agent config output. Array of strings, max 20 tags, sanitized.
116
+
117
+ ### GUI: Chat Command Interception
118
+
119
+ **`stores/groove.js`** — `instructAgent()` checks every message for bracket commands before sending to the daemon:
120
+
121
+ ```
122
+ User types: [save] #memory-system This is my idea
123
+ → Keeper intercepts, saves to .groove/keeper/memory-system.md
124
+ → System message: "Saved to #memory-system"
125
+ → Agent never sees the message
126
+ ```
127
+
128
+ The `_handleKeeperCommand()` method handles all 10 commands:
129
+ - `[save]`, `[append]`, `[delete]` — immediate API call + confirmation
130
+ - `[update]`, `[view]` — opens editor modal via `keeperEditing` store state
131
+ - `[pull]`, `[read]` — fetches brief from API, sends as agent instruction
132
+ - `[doc]` — sends chat history to `/api/keeper/doc`, opens result in editor
133
+ - `[link]` — parses tag + path, calls link API
134
+ - `[instruct]` — sets `keeperInstructOpen: true`
135
+
136
+ ### GUI: Syntax Highlighting
137
+
138
+ **`agent-chat.jsx`** — `highlightKeeper()` function splits text on bracket commands and hashtags:
139
+
140
+ - `[save]`, `[pull]`, etc. render as teal accent pills (`bg-accent/15 text-accent font-mono`)
141
+ - `#tag-name` renders in accent color (`text-accent font-medium`)
142
+ - Applied in `FormattedText` (message display) and as a transparent overlay on the textarea input
143
+
144
+ **Input overlay approach:** When the input contains keeper syntax, the textarea text becomes transparent (`text-transparent caret-text-0`) while a mirrored overlay div renders the highlighted version. This lets the cursor and selection work normally while commands light up in real-time.
145
+
146
+ ### GUI: Memory View
147
+
148
+ **`views/memory.jsx`** — Full view accessible from the activity bar (BookOpen icon, between Dashboard and Teams).
149
+
150
+ Features:
151
+ - **List view** — cards with content preview, relative timestamps, size, type badge (AI sparkle for docs), link count
152
+ - **Tree view** — collapsible folder hierarchy following tag namespacing
153
+ - **Search** — filters by tag name
154
+ - **Editor modal** — tag input (new only), full-height textarea, Cmd+S save, read-only mode
155
+ - **Instruct modal** — all 10 commands with descriptions, tag hierarchy guide, memory types explanation
156
+ - **Empty state** — onboarding text explaining the system + quick action buttons
157
+
158
+ ### GUI: Global Modals
159
+
160
+ **`components/keeper/global-modals.jsx`** — `KeeperGlobalModals` rendered at App.jsx level.
161
+
162
+ Two modals that respond to store state (`keeperEditing`, `keeperInstructOpen`):
163
+ - **KeeperEditorModal** — same editor as the memory view, triggered from chat commands
164
+ - **KeeperInstructModal** — command reference, triggered by `[instruct]`
165
+
166
+ Both skip rendering when `activeView === 'memory'` to avoid duplicate modals (the memory view renders its own copies).
167
+
168
+ ### GUI: Store State
169
+
170
+ New state in Zustand store:
171
+ - `keeperItems: []` — list of all memory metadata
172
+ - `keeperTree: []` — hierarchical tree structure
173
+ - `keeperEditing: null` — `{ tag, content, isNew, readOnly }` drives the editor modal
174
+ - `keeperInstructOpen: false` — drives the instruct modal
175
+
176
+ New actions:
177
+ - `fetchKeeperItems()` — loads items + tree from API
178
+ - `saveKeeperItem()`, `appendKeeperItem()`, `updateKeeperItem()`, `deleteKeeperItem()` — CRUD
179
+ - `getKeeperItem()` — fetch single item with content
180
+ - `searchKeeper()` — search API wrapper
181
+ - `setKeeperEditing()` — open/close editor modal
182
+ - `_handleKeeperCommand()` — chat command interception logic
183
+
184
+ WebSocket handlers for `keeper:saved`, `keeper:updated`, `keeper:deleted` — trigger `fetchKeeperItems()` for real-time sync.
185
+
186
+ ## Files Changed
187
+
188
+ ### New Files
189
+ - `packages/daemon/src/keeper.js` — Keeper module
190
+ - `packages/gui/src/views/memory.jsx` — Memory view
191
+ - `packages/gui/src/components/keeper/global-modals.jsx` — Global editor + instruct modals
192
+
193
+ ### Modified Files
194
+ - `packages/daemon/src/index.js` — import + instantiate Keeper
195
+ - `packages/daemon/src/api.js` — 14 Keeper endpoints + import
196
+ - `packages/daemon/src/introducer.js` — Keeper context injection on spawn
197
+ - `packages/daemon/src/validate.js` — `keeperTags` in agent config
198
+ - `packages/gui/src/stores/groove.js` — Keeper state, actions, WebSocket handlers, command interception
199
+ - `packages/gui/src/components/layout/activity-bar.jsx` — BookOpen icon for Memory
200
+ - `packages/gui/src/components/agents/agent-chat.jsx` — syntax highlighting + input overlay
201
+ - `packages/gui/src/App.jsx` — MemoryView route + KeeperGlobalModals
202
+
203
+ ## Review Checklist
204
+
205
+ - [ ] Daemon starts without errors after adding keeper.js
206
+ - [ ] All 14 API endpoints respond correctly (save, get, update, delete, append, pull, doc, link, search, tree, list, commands, parse, unlink)
207
+ - [ ] Tag hierarchy works: saving `#groove/routing` creates directory structure
208
+ - [ ] `[save] #test hello world` in agent chat saves without reaching the agent
209
+ - [ ] `[pull] #test` injects the memory into the agent's context
210
+ - [ ] `[update] #test` opens the editor modal with existing content
211
+ - [ ] `[view] #test` opens read-only modal
212
+ - [ ] `[doc] #test` generates a doc from chat history (requires a provider for headless calls)
213
+ - [ ] `[link] #test plan_files/NORTHSTAR.md` links successfully
214
+ - [ ] `[instruct]` opens command reference
215
+ - [ ] `[delete] #test` removes the memory
216
+ - [ ] Syntax highlighting: `[save]` and `#tag` render in teal in both messages and input
217
+ - [ ] Memory view: list/tree toggle, search, new/edit/delete all work
218
+ - [ ] Global modals: editor opens from chat commands when not on memory view
219
+ - [ ] Agent spawn with `keeperTags` gets memory content in intro context
220
+ - [ ] WebSocket: saving from one client updates another
221
+ - [ ] Route order: `GET /api/keeper/commands` doesn't get caught by wildcard
222
+ - [ ] 265 existing tests still pass
223
+ - [ ] GUI build succeeds