mem-search · git:20261020.826811e · 2026-10-20 · sha256 29dce09590fda3f3

mem-search git:20261020.826811eA

Immutable. This exact content never changes and is served at /api/v1/blob/29dce09590fda3f3.

---
name: mem-search
description: Smart search (default). Search claude-mem's persistent cross-session memory database in three steps: search, timeline, then selected get_observations. Use when user asks "did we already solve this?", "how did we do X last time?", or needs work from previous sessions.
---

# Smart Search (Default)

Search past work across all sessions. Use the original three-step mem-search workflow by default: search → timeline → selected get_observations. Reason about the index and context before choosing details. Do not use auto or guided modes.

## Runtime and Tool Names

The examples below use the local worker tools. Native Pi and DSH integrations
name the same three steps `mem_search`, `mem_timeline`, and
`mem_get_observations`. Native OpenCode uses `claude_mem_search`,
`claude_mem_timeline`, and `claude_mem_get_observations`. CMEM Pro uses `memory_search`, `timeline`, and
`get_observations`; use the parameter names advertised by that connection.

A self-hosted server runtime uses the same three steps: `search`, `timeline`,
and `get_observations`, scoped to the configured server project. Server
observation IDs are strings. Set `projectId` only when selecting another
authorized server project. Dumb search is unavailable in server runtime. A direct self-hosted `/v1/mcp`
connection instead requires `projectId` on each call and `anchorId` for its
timeline. CMEM Pro also uses `anchorId` for timeline context, and uses
`get_summaries` when the selected index rows are session summaries. Follow the
active connection’s advertised schema.

## When to Use

Use when users ask about PREVIOUS sessions (not current conversation):

- "Did we already fix this?"
- "How did we solve X last time?"
- "What happened last week?"

## Layered Workflow (ALWAYS Follow)

**NEVER fetch full details without filtering first. 10x token savings.**

### Step 1: Search - Get Index with IDs

Use the `search` MCP tool:

```
search(query="authentication", limit=20, project="my-project")
```

**Returns:** Table with IDs, timestamps, types, titles (~50-100 tokens/result)

```
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #11131 | 3:48 PM | 🟣 | Added JWT authentication | ~75 |
| #10942 | 2:15 PM | 🔴 | Fixed auth token expiration | ~50 |
```

**Parameters:**

- `query` (string) - Search term
- `limit` (number) - Max results, default 20, max 100
- `project` (string) - Project name filter
- `type` (string, optional) - "observations", "sessions", or "prompts"
- `obs_type` (string, optional) - Comma-separated: bugfix, feature, decision, discovery, change
- `dateStart` (string, optional) - YYYY-MM-DD or epoch ms
- `dateEnd` (string, optional) - YYYY-MM-DD or epoch ms
- `offset` (number, optional) - Skip N results
- `orderBy` (string, optional) - "date_desc" (default), "date_asc", "relevance"

### Step 2: Timeline - Get Context Around Interesting Results

Use the `timeline` MCP tool:

```
timeline(anchor=11131, depth_before=3, depth_after=3, project="my-project")
```

Or find anchor automatically from query:

```
timeline(query="authentication", depth_before=3, depth_after=3, project="my-project")
```

**Returns:** `depth_before + 1 + depth_after` items in chronological order with observations, sessions, and prompts interleaved around the anchor.

**Parameters:**

- `anchor` (number, optional) - Observation ID to center around
- `query` (string, optional) - Find anchor automatically if anchor not provided
- `depth_before` (number, optional) - Items before anchor, default 5, max 20
- `depth_after` (number, optional) - Items after anchor, default 5, max 20
- `project` (string) - Project name filter

### Step 3: Fetch - Get Full Details ONLY for Filtered IDs

Review titles from Step 1 and context from Step 2. Pick relevant IDs. Discard the rest.

Use the `get_observations` MCP tool:

```
get_observations(ids=[11131, 10942])
```

**ALWAYS use `get_observations` for 2+ observations - single request vs N requests.**

**Parameters:**

- `ids` (array of numbers, required) - Observation IDs to fetch
- `orderBy` (string, optional) - "date_desc" (default), "date_asc"
- `limit` (number, optional) - Max observations to return
- `project` (string, optional) - Project name filter

**Returns:** Complete observation objects with title, subtitle, narrative, facts, concepts, files (~500-1000 tokens each)

### Exceptional Follow-up: Raw Tool I/O - Only When Step 3 Was Not Enough

Observations are *summaries*. When the answer needs the literal bytes a tool
returned — the exact diff, the exact command output, the exact API response —
use the `get_tool_uses` MCP tool:

```
get_tool_uses(ids=["toolu_01ABC..."], project="my-project")
```

**Do not start here.** Raw tool bodies are unsummarized and can run to thousands
of tokens each; that is the whole reason claude-mem compresses them into
observations in the first place. Reach for this layer only after search /
timeline / get_observations pointed you at specific tool calls.

**Parameters:**

- `ids` (array, required) - Numeric `tool_uses` ids OR opaque `tool_use_id` strings
- `limit` (number, optional) - Max rows to return
- `project` (string, optional) - Project name filter
- `contentSessionId` (string, optional) - Restrict to one session

**Returns:** The stored `tool_input` / `tool_response` for those calls, plus the
tool name, session ids, and the observation each was folded into. Payloads over
64 KB were truncated on write and carry a `…[truncated: N bytes]` marker.

## Examples

**Find recent bug fixes:**

```
search(query="bug", type="observations", obs_type="bugfix", limit=20, project="my-project")
```

**Find what happened last week:**

```
search(type="observations", dateStart="2025-11-11", limit=20, project="my-project")
```

**Understand context around a discovery:**

```
timeline(anchor=11131, depth_before=5, depth_after=5, project="my-project")
```

**Batch fetch details:**

```
get_observations(ids=[11131, 10942, 10855], orderBy="date_desc")
```

**Recover the exact output of a command we ran last week:**

```
search(query="migration failed", limit=20, project="my-project")
timeline(anchor=11131, project="my-project")
get_observations(ids=[11131])            # read the summary first
get_tool_uses(ids=["toolu_01ABC..."])    # only if the summary omitted the detail
```

## Why This Workflow?

- **Search index:** ~50-100 tokens per result
- **Full observation:** ~500-1000 tokens each
- **Raw tool body:** up to 64 KB each — the layer you skip 95% of the time
- **Batch fetch:** 1 HTTP request vs N individual requests
- **10x token savings** by filtering before fetching

## Knowledge Agents

Want synthesized answers instead of raw records? Use `/knowledge-agent` to build a queryable corpus from your observation history. The knowledge agent reads all matching observations and answers questions conversationally.

## Dumb Search (Optional)

**Doesn’t reason about the results. Fast, but shallow. Use Smart for reliable recall.**

```
dumb_search(query="authentication token expiry", project="my-project")
```

This one-call lookup picks records whose titles share the most query words,
adds nearby context, and returns up to `maxDetails` (default 3, max 5) records.
Matching words from unrelated projects can crowd out useful results, and
conflicting records are not reconciled. Use only for a quick, direct lookup;
use Smart search by default.

## Durable Note Taking

Search for related decisions before saving a new note. Save useful decisions,
corrections, resolved failures, and handoff facts through
`save_memory(text="...", title="...", project="...")` for local-worker notes when
that tool is available. In server runtime, use `observation_add` for the selected
server project when available; `save_memory` never writes server notes. Keep the
note factual, concise, and tied to evidence. Do not save secrets or copy whole
transcripts.