---
title: KMS Vault Overview (searchable inventory table of every note)
---

# KMS Vault Overview (searchable inventory table of every note)

## What it is

The **Vault Overview** is a read-only, searchable, sortable table that shows every visible note in the active KMS vault on one screen: title, tags, AI summary state and text (when a summary marker is already present), estimated token count, byte size, and last-modified timestamp. It is the "bird's-eye" complement to the note-by-note editor — useful for auditing a large vault, finding notes by tag or summary content, and getting a rough sense of how much context each note would consume in an agent session.

The Overview never reads full note bodies and never generates summaries. Summary text is decoded from the first 800 characters of each note (where the `<!-- kms:summary … -->` marker lives), and size + token estimates come from the `body_bytes` column — so loading the table costs I/O proportional to row count, not total vault bytes. On a 10 000-note vault the query is still fast.

**Gating.** The panel is gated by the `nothariOverviewEnabled` setting (default **on**). With KMS itself off (`nothariEnabled: false`) the panel never loads.

## Where to find it

Inside the **KMS** panel, as the Vault Overview view of the active vault. It is a read-only table — there is no editing here — and it can be turned off in Settings if you would rather not see it.

## How it behaves

### How to use it

1. **Open the Overview.** In the KMS toolbar, click the **Vault Overview** button (a list/table icon). The panel is also reachable from the **command palette** (`Ctrl+Shift+P` → "Vault Overview").
2. **Search.** The filter input at the top narrows rows by title, tags, or summary text as you type.
3. **Sort.** Click any column header to sort by that field (title, tags, summary state, token estimate, size, updated-at). A second click reverses the order.
4. **Read the summary chip.** Each row shows a small chip for the note's summary state: **Up to date** (green), **Stale** (amber), **Locked** (grey), or no chip when the note has no summary marker. The summary text itself appears in the row when the note has a marker. See [kms-summaries.md](kms-summaries.md) for the full lifecycle.
5. **Open a note.** Clicking any row opens that note in the KMS editor, the same as clicking it in the file tree.
6. **Turn it off.** Settings → Features → KMS → uncheck **"Show Vault Overview"** (`nothariOverviewEnabled`).

### Known limitations

- **Token count is an estimate, not an exact count.** `tokenEstimate` uses `ceil(body_bytes / 4)` — a bytes-per-token heuristic, not a model tokenizer. For notes that are primarily ASCII prose the approximation is close; notes with many multi-byte characters (CJK, emoji, code) will have a higher real token count than the estimate shows.
- **Summaries shown only when already generated.** The Overview reads and displays whatever summary marker is already in a note — it never triggers summary generation. A note that has never been summarised shows `summary.state: 'none'` and `summary.text: null`. To populate summaries, use the in-editor chip or the opt-in auto-regen worker (see [kms-summaries.md](kms-summaries.md)).
- **Cross-vault note mixing in the agent tool.** `kms_inventory` returns notes from all registered vaults in one stream, with no per-vault label in the result beyond the `noteId`. Multi-vault users see a unified list; a `vaultId` filter is not yet available on the agent tool (the IPC handler does accept a `vaultId`).
- **No live refresh.** The panel data is a snapshot at load time. It does not auto-update as you edit notes — open a note, edit it, and come back to the Overview to see updated values.

## For agents

### The kms_inventory agent tool

Spawned Claude Code sessions can enumerate the vault through the **`kms_inventory`** MCP tool — the programmatic equivalent of the Vault Overview panel, exposed via the existing KMS agent-tools MCP server.

**Signature.** `kms_inventory(cursor?, limit?)` — both parameters are optional.

- `limit` — rows per page. Default **100**, max **500**. Pages are slim (no bodies) so even the max page stays well under the 100 KB payload cap.
- `cursor` — opaque pagination cursor. Omit on the first call; pass the returned `nextCursor` to fetch subsequent pages.

**Per-note fields returned.** For each visible note across every registered vault:

| Field | Type | Notes |
|---|---|---|
| `noteId` | string | Stable row id |
| `title` | string | Note title |
| `tags` | string[] | Hashtags, sorted |
| `updatedAt` | ISO string | Last modified |
| `summary.state` | string | `'current'` · `'stale'` · `'user_edited'` · `'cost_capped'` · `'none'` |
| `summary.text` | string\|null | AI summary text, or `null` when no marker exists |
| `tokenEstimate` | number | `ceil(body_bytes / 4)` — a rough size cue |
| `sizeBytes` | number | Stored byte count of the note body |

**Pagination.** When more rows remain beyond the current page, the result carries `nextCursor`. Re-call with that value to continue. Order is newest-first, stable at `(updatedAt DESC, noteId ASC)` so keyset pagination is deterministic even when many notes share a timestamp.

**Payload-cap edge case.** If an unusually large page of long summaries would exceed the 100 KB payload cap, the tool returns `{ truncated: true, cursor }` — the **same** cursor as the input, not an advanced one — so the agent re-calls the identical page start with a smaller `limit` without skipping any notes.

**Gating.** `kms_inventory` is gated by the same flags as every other read tool: `nothariEnabled` + `nothariAgentToolsEnabled`. Both must be on. Hidden notes (`hidden_at IS NOT NULL`) are never returned. Cost: **zero** (local SQLite only, no API spend).

**Cross-vault scope.** Like the other read tools, `kms_inventory` has no `vaultId` parameter — it returns notes from every registered vault in one stream. Single-vault users (the common case) are unaffected.

### How it works

### The inventory-core shared query

The main workhorse is [`src/main/services/kms/inventory-core.ts`](/src/main/services/kms/inventory-core.ts) — a dependency-free module shared by both the agent tool and the IPC handler. Sharing it ensures the panel and the tool always agree on which notes appear and how their fields are shaped.

**Freeze-safe top-of-body read.** A vault can hold thousands of notes, some over 100 KB. The query never fetches full bodies. Instead it uses `substr(body, 1, 800)` — just the leading 800 characters — because the `<!-- kms:summary … -->` marker always sits at the very top of the note body (frontmatter is a separate column). Size and token count come from the stored `body_bytes` column, which the indexer keeps current. Query cost scales with row count, not total vault bytes.

**Tag hydration without N+1.** Tags are fetched in a single batched `IN (?, …)` query over all the page's note ids (chunked at 500 per batch to stay within SQLite's variable limit), then mapped back to each row. No per-note tag query.

**Keyset cursor pagination.** The agent tool uses an opaque `<updatedAt>|<noteId>` cursor encoded by `encodeInventoryCursor` and decoded by `decodeInventoryCursor`. The SQL predicate `(updated_at < ? OR (updated_at = ? AND id > ?))` advances the page without skipping or re-emitting rows at timestamp boundaries.

**Token estimate.** `tokenEstimate` is `ceil(body_bytes / 4)` — the `BYTES_PER_TOKEN = 4` constant from `inventory-core.ts`. This is an intentional approximation for capacity-planning ("how big is this note?"), not an exact model tokenizer. The IPC handler and the agent tool use the same `estimateTokensFromBytes` export so both surfaces report the same number.

### The kms:list-inventory IPC channel

The Vault Overview panel loads its data via the **`kms:list-inventory`** IPC channel (`IPC.KMS_LIST_INVENTORY`), registered in [`src/main/ipc/kms-handlers.ts`](/src/main/ipc/kms-handlers.ts). The handler:

1. Validates input with `kmsListInventorySchema` (requires a `vaultId`).
2. Calls `listNotesWithInventory(db, vaultId)` from [`src/main/db/queries-kms/notes.ts`](/src/main/db/queries-kms/notes.ts), which delegates to `selectInventoryRows` from `inventory-core.ts`.
3. Returns `{ success: true, data: { notes } }` — the standard IPC envelope.

The handler is safety-capped at `INVENTORY_LIST_LIMIT` rows (100 000) and is gated by `withKmsEnabled`, so it is a no-op when KMS is off. The channel is in the mobile-safe WS baseline (`web-access-ws-invoke-baseline.json`) — the Vault Overview panel is reachable from a paired phone.

### The nothariOverviewEnabled off-switch

Setting `nothariOverviewEnabled: false` removes the Vault Overview toolbar button and command palette entry. The `kms:list-inventory` IPC channel itself remains registered (it is not gated by the toggle), so a caller that already has the channel name can still invoke it — the toggle is a UI-surface gate, not a data-access gate.

## Related

- [kms.md](kms.md) — the parent KMS vault editor (vault setup, the `nothariEnabled` master toggle, file structure)
- [kms-agent-tools.md](kms-agent-tools.md) — the full set of MCP read and write tools for spawned Claude sessions; `kms_inventory` is one of the read tools
- [kms-summaries.md](kms-summaries.md) — the AI summary marker lifecycle that the Overview's summary column and the `summary` field surface
