# Keeper — Instruction Manual

## What It Is

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.

Two types of content:
- **Manual** — you write it via `[save]`, `[append]`, `[update]`
- **Doc** — AI writes it via `[doc]`, synthesizing your conversation into a structured document

---

## Commands

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.

### Saving

**`save #tag`** — Save the message content under a tag and send the message to the agent. Creates or overwrites.

```
the sky is blue save #thought
→ Saves "the sky is blue" to #thought
→ Agent receives "the sky is blue" and responds normally

we're going with REST over GraphQL because of team familiarity save #design-decision
→ Saves to #design-decision AND the agent gets your message

this routing approach works well for our use case save #groove/routing
→ Saves to #groove/routing (nested under groove)
```

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.

**`append #tag`** — Add content to an existing memory with a `---` separator. Also sends to the agent. Same syntax as save.

```
actually we should also consider WebSockets append #design-decision
→ Adds "actually we should also consider WebSockets" to the bottom of #design-decision
→ Agent receives the message too
```

If the tag doesn't exist yet, `append` creates it (same as `save`).

### Editing

**`update #tag`** — Opens the editor modal with the current content for in-place editing. Full textarea, Cmd+S to save.

```
update #design-decision
→ Opens editor with the current content of #design-decision
```

If the tag doesn't exist, opens a blank editor to create it. This command is intercepted — not sent to the agent.

### Viewing

**`view #tag`** — Opens a read-only modal to review content without risk of editing.

```
view #design-decision
→ Opens read-only viewer showing the full content
```

Intercepted — not sent to the agent.

### Reading

**`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.

```
read #memory-system
→ "Sent #memory-system to agent"
→ Agent has the full content and can work with it

read #design-decision #groove/routing
→ Agent receives both memories
```

Reading a parent tag pulls all children automatically. `read #groove` sends `#groove/routing`, `#groove/memory-system`, and anything else under `#groove`.

Intercepted — not sent to the agent as your message (the content goes as context).

### AI Doc Generation

**`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.

```
doc #memory-system
→ AI synthesizes the conversation into a structured doc
→ Opens in editor so you can review/edit before it's final
```

The generated doc includes:
- Core idea and motivation
- Key decisions from the discussion
- Architecture / design choices
- Implementation plan (if discussed)
- Open questions / next steps

If the journalist headless mode isn't available (no API key), falls back to a raw transcript.

### Linking

**`link #tag path/to/doc`** — Links a memory tag to a NORTHSTAR or external document for cross-referencing.

```
link #design-decision plan_files/NORTHSTAR.md
→ Links #design-decision to the NORTHSTAR doc
```

Links show up as badges on memory cards in the Memory view.

### Help

**`[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.)

### Deleting

**`delete #tag`** — Permanently removes a memory.

```
delete #old-idea
→ Gone
```

---

## Tag Hierarchy

Tags use `/` for namespacing. This creates a folder structure:

```
#groove                     → top-level
#groove/routing             → child of groove
#groove/memory-system       → child of groove
#design/frontend            → child of design
#design/backend             → child of design
```

When you `[pull] #groove`, you get all children too — `#groove/routing` and `#groove/memory-system` are included automatically.

In the Memory view, tree mode shows this as collapsible folders.

### Tag Rules
- Lowercase only (auto-converted)
- Letters, numbers, `/`, `-`, `_` allowed
- No spaces, no special characters
- Max 20 tags per agent when spawning with `keeperTags`

---

## Memory View

Access from the activity bar (BookOpen icon, between Dashboard and Teams).

### List View
- Cards with content preview (first 3 lines)
- Relative timestamps ("5m ago", "2d ago")
- Size indicator
- Type badge: purple "AI" sparkle for doc-generated memories
- Link count badges
- Hover to reveal edit/delete buttons

### Tree View
- Collapsible folder hierarchy following tag namespacing
- Click a tag to open the editor
- Virtual folders appear for parent paths that don't have their own content

### Search
- Filters by tag name in real-time

### New Button
- Opens editor modal with tag input + content textarea
- Tag input auto-sanitizes (lowercase, valid chars only)

---

## Syntax Highlighting

In agent chat, Keeper syntax highlights in real-time:
- `[save]`, `[pull]`, etc. — teal accent pills
- `#tag-name` — accent-colored text

This works in both sent messages and the input textarea (via a transparent overlay).

---

## Spawning Agents with Context

When spawning a new agent, you can pre-load memories via `keeperTags` in the agent config:

```json
{
  "role": "frontend",
  "keeperTags": ["design-decision", "groove/routing"]
}
```

The introducer pulls those memories and injects them as a "Keeper Context" section in the agent's intro prompt. Budget: 5KB max.

---

## How It Works Under the Hood

### Storage
```
.groove/keeper/
├── index.json              — tag metadata (type, links, timestamps, size)
├── thought.md              — flat tag: #thought
├── design-decision.md      — flat tag: #design-decision
└── groove/
    ├── routing.md           — nested: #groove/routing
    └── memory-system.md     — nested: #groove/memory-system
```

Each tag = one `.md` file. `index.json` stores metadata only.

### API Endpoints

14 endpoints under `/api/keeper/`:

| Method | Path | What It Does |
|--------|------|--------------|
| GET | `/api/keeper` | List all memories (metadata only) |
| GET | `/api/keeper/tree` | Hierarchical tree structure |
| GET | `/api/keeper/search?q=` | Search tags and content |
| GET | `/api/keeper/commands` | Command reference data |
| GET | `/api/keeper/:tag` | Read single memory with content |
| POST | `/api/keeper` | Save `{ tag, content }` |
| POST | `/api/keeper/append` | Append `{ tag, content }` |
| POST | `/api/keeper/pull` | Assemble brief from `{ tags: [...] }` |
| POST | `/api/keeper/doc` | AI synthesis from `{ tag, chatHistory, agentId }` |
| POST | `/api/keeper/link` | Link `{ tag, docPath }` |
| POST | `/api/keeper/parse` | Parse command text |
| PATCH | `/api/keeper/:tag` | Update content |
| DELETE | `/api/keeper/link/:tag` | Unlink a document |
| DELETE | `/api/keeper/:tag` | Delete memory |

### Real-Time Sync

All mutations broadcast via WebSocket (`keeper:saved`, `keeper:updated`, `keeper:deleted`). Multiple browser tabs stay in sync.

---

## Testing Checklist

### Basic Flow
- [ ] Type `hello world save #test` in agent chat → saves "hello world", agent also receives "hello world"
- [ ] Type `the sky is blue save #test2` → saves "the sky is blue" to #test2, agent gets the message
- [ ] `save` and `#test` highlight teal as you type in the input
- [ ] Navigate to Memory view → both #test and #test2 appear
- [ ] Click edit icon on #test → editor opens with "hello world"
- [ ] Modify content, Cmd+S → saves, card updates

### All Commands (brackets optional)
- [ ] `more thoughts append #test` → adds with separator, agent gets "more thoughts"
- [ ] `update #test` → opens editor modal (intercepted, not sent to agent)
- [ ] `view #test` → opens read-only modal (intercepted)
- [ ] `read #test` → "Sent #test to agent", agent receives content, chat stays clean
- [ ] `doc #test` → "Generating doc..." message, editor opens with result
- [ ] `link #test plan_files/keeper-manual.md` → links successfully
- [ ] `[instruct]` → command reference modal opens (brackets required for this one)
- [ ] `delete #test` → memory removed

### Brackets Still Work
- [ ] `[save] #test hello` → same behavior as `hello save #test`
- [ ] `[update] #test` → same as `update #test`

### Hierarchy
- [ ] `[save] #project/frontend layout decisions here` → creates nested tag
- [ ] `[save] #project/backend api design here` → second child
- [ ] Memory view tree mode shows "project" folder with both children
- [ ] `[pull] #project` → injects both children

### Edge Cases
- [ ] `save #tag` with no content → shows usage hint
- [ ] `save` with no tag → not intercepted (no `#tag` to match), sent to agent normally
- [ ] `view #nonexistent` → "not found" message
- [ ] `read #nonexistent` → "no memories found" message
- [ ] Very long content (5KB+) → saves and displays correctly

### Memory View
- [ ] Empty state shows onboarding text + "Create first memory" button
- [ ] List/Tree toggle works
- [ ] Search filters by tag name
- [ ] "New" button opens editor with tag input
- [ ] Delete from card hover button works
- [ ] Instruct button (?) opens command reference

### Cross-View
- [ ] Save from agent chat → Memory view updates
- [ ] Edit in Memory view → reflected when pulled in chat
- [ ] Global modals work from non-memory views (agents view, dashboard, etc.)
- [ ] Global modals don't duplicate when ON memory view
