* fix(ci): resolve all CI failures — unversioned integrations, test retries - Move integration docs to separate unversioned docs plugin (docs-integrations/) so new integrations don't need to be duplicated across versioned_docs - Remove integration pages from versioned_docs (v0.3, v0.4) — sidebar entries now use links instead of doc refs - Add missing title/description SEO frontmatter to autogen.md - Add retry logic (2 attempts) to test-doc-examples.sh for transient LLM timeouts - Add pytest-rerunfailures to test-api with --reruns 2 for flaky Gemini-dependent integration tests * ci: retrigger * fix: graph entity inheritance, SyncTaskBackend error propagation, fact_type test regressions - Fix observation entity inheritance in get_graph_data: the unit_entities query only fetched entities for visible observation IDs, not their source memory IDs, so the inheritance loop always found an empty entity_map - Remove error swallowing in SyncTaskBackend._execute_task so test failures surface instead of being silently logged - Wrap remaining consolidation submission call sites with try/except since consolidation is non-critical for those operations - Fix test_sync_backend test to expect errors to propagate - Remove fact_type=["world"] filter from test_document_upsert_behavior and test_mentioned_at_from_context_string (same PR #848 regression) - Remove flaky marker from consolidation test (now deterministic)
216 lines
13 KiB
Markdown
216 lines
13 KiB
Markdown
---
|
|
sidebar_position: 5
|
|
title: "Claude Code Persistent Memory with Hindsight | Integration"
|
|
description: "Add long-term memory to Claude Code with Hindsight. Automatically captures conversations and recalls relevant context across sessions using Claude Code's hook-based architecture."
|
|
---
|
|
|
|
# Claude Code
|
|
|
|
Biomimetic long-term memory for [Claude Code](https://docs.anthropic.com/en/docs/claude-code) using [Hindsight](https://vectorize.io/hindsight). Automatically captures conversations and intelligently recalls relevant context — a complete port of [`hindsight-openclaw`](./openclaw) adapted to Claude Code's hook-based plugin architecture.
|
|
|
|
[View Changelog →](/changelog/integrations/claude-code)
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# 1. Add the Hindsight marketplace and install the plugin
|
|
claude plugin marketplace add vectorize-io/hindsight
|
|
claude plugin install hindsight-memory
|
|
|
|
# 2. Configure your LLM provider for memory extraction
|
|
# Option A: OpenAI (auto-detected)
|
|
export OPENAI_API_KEY="sk-your-key"
|
|
|
|
# Option B: Anthropic (auto-detected)
|
|
export ANTHROPIC_API_KEY="your-key"
|
|
|
|
# Option C: No API key needed (uses Claude Code's own model — personal/local use only)
|
|
export HINDSIGHT_LLM_PROVIDER=claude-code
|
|
|
|
# Option D: Connect to an external Hindsight server instead of running locally
|
|
mkdir -p ~/.hindsight
|
|
echo '{"hindsightApiUrl": "https://your-hindsight-server.com"}' > ~/.hindsight/claude-code.json
|
|
|
|
# 3. Start Claude Code — the plugin activates automatically
|
|
claude
|
|
```
|
|
|
|
That's it! The plugin will automatically start capturing and recalling memories.
|
|
|
|
## Features
|
|
|
|
- **Auto-recall** — on every user prompt, queries Hindsight for relevant memories and injects them as context (invisible to the chat transcript, visible to Claude)
|
|
- **Auto-retain** — after every response (or every N turns), extracts and retains conversation content to Hindsight for long-term storage
|
|
- **Daemon management** — can auto-start/stop `hindsight-embed` locally or connect to an external Hindsight server
|
|
- **Dynamic bank IDs** — supports per-agent, per-project, or per-session memory isolation
|
|
- **Channel-agnostic** — works with Claude Code Channels (Telegram, Discord, Slack) or interactive sessions
|
|
- **Zero dependencies** — pure Python stdlib, no pip install required
|
|
|
|
## Architecture
|
|
|
|
The plugin uses all four Claude Code hook events:
|
|
|
|
| Hook | Event | Purpose |
|
|
|------|-------|---------|
|
|
| `session_start.py` | `SessionStart` | Health check — verify Hindsight is reachable |
|
|
| `recall.py` | `UserPromptSubmit` | **Auto-recall** — query memories, inject as `additionalContext` |
|
|
| `retain.py` | `Stop` | **Auto-retain** — extract transcript, POST to Hindsight (async) |
|
|
| `session_end.py` | `SessionEnd` | Cleanup — stop auto-managed daemon if started |
|
|
|
|
## Connection Modes
|
|
|
|
### 1. External API (recommended for production)
|
|
|
|
Connect to a running Hindsight server (cloud or self-hosted). No local LLM needed — the server handles fact extraction.
|
|
|
|
```json
|
|
{
|
|
"hindsightApiUrl": "https://your-hindsight-server.com",
|
|
"hindsightApiToken": "your-token"
|
|
}
|
|
```
|
|
|
|
### 2. Local Daemon (auto-managed)
|
|
|
|
The plugin automatically starts and stops `hindsight-embed` via `uvx`. Requires an LLM provider API key for local fact extraction.
|
|
|
|
Set an LLM provider:
|
|
```bash
|
|
export OPENAI_API_KEY="sk-your-key"
|
|
# or
|
|
export ANTHROPIC_API_KEY="your-key"
|
|
# or
|
|
export HINDSIGHT_LLM_PROVIDER=claude-code # No API key needed
|
|
```
|
|
|
|
The model is selected automatically by the Hindsight API. To override, set `HINDSIGHT_LLM_MODEL`.
|
|
|
|
### 3. Existing Local Server
|
|
|
|
If you already have `hindsight-embed` running, leave `hindsightApiUrl` empty and set `apiPort` to match your server's port. The plugin will detect it automatically.
|
|
|
|
## Configuration
|
|
|
|
All settings live in `~/.hindsight/claude-code.json`. Every setting can also be overridden via environment variables. The plugin ships with sensible defaults — you only need to configure what you want to change.
|
|
|
|
**Loading order** (later entries win):
|
|
1. Built-in defaults (hardcoded in the plugin)
|
|
2. Plugin `settings.json` (ships with the plugin, at `CLAUDE_PLUGIN_ROOT/settings.json`)
|
|
3. User config (`~/.hindsight/claude-code.json` — recommended for your overrides)
|
|
4. Environment variables
|
|
|
|
---
|
|
|
|
### Connection & Daemon
|
|
|
|
These settings control how the plugin connects to the Hindsight API.
|
|
|
|
| Setting | Env Var | Default | Description |
|
|
|---------|---------|---------|-------------|
|
|
| `hindsightApiUrl` | `HINDSIGHT_API_URL` | `""` (empty) | URL of an external Hindsight API server. When empty, the plugin uses a local daemon instead. |
|
|
| `hindsightApiToken` | `HINDSIGHT_API_TOKEN` | `null` | Authentication token for the external API. Only needed when `hindsightApiUrl` is set. |
|
|
| `apiPort` | `HINDSIGHT_API_PORT` | `9077` | Port used by the local `hindsight-embed` daemon. Change this if you run multiple instances or have a port conflict. |
|
|
| `daemonIdleTimeout` | `HINDSIGHT_DAEMON_IDLE_TIMEOUT` | `0` | Seconds of inactivity before the local daemon shuts itself down. `0` means the daemon stays running until the session ends. |
|
|
| `embedVersion` | `HINDSIGHT_EMBED_VERSION` | `"latest"` | Which version of `hindsight-embed` to install via `uvx`. Pin to a specific version (e.g. `"0.5.2"`) for reproducibility. |
|
|
| `embedPackagePath` | `HINDSIGHT_EMBED_PACKAGE_PATH` | `null` | Local filesystem path to a `hindsight-embed` checkout. When set, the plugin runs from this path instead of installing via `uvx`. Useful for development. |
|
|
|
|
---
|
|
|
|
### LLM Provider (local daemon only)
|
|
|
|
These settings configure which LLM the local daemon uses for fact extraction. They are **ignored** when connecting to an external API (the server uses its own LLM configuration).
|
|
|
|
| Setting | Env Var | Default | Description |
|
|
|---------|---------|---------|-------------|
|
|
| `llmProvider` | `HINDSIGHT_LLM_PROVIDER` | auto-detect | Which LLM provider to use. Supported values: `openai`, `anthropic`, `gemini`, `groq`, `ollama`, `openai-codex`, `claude-code`. When omitted, the plugin auto-detects by checking for API key env vars in order: `OPENAI_API_KEY` → `ANTHROPIC_API_KEY` → `GEMINI_API_KEY` → `GROQ_API_KEY`. |
|
|
| `llmModel` | `HINDSIGHT_LLM_MODEL` | provider default | Override the default model for the chosen provider (e.g. `"gpt-4o"`, `"claude-sonnet-4-20250514"`). When omitted, the Hindsight API picks a sensible default for each provider. |
|
|
| `llmApiKeyEnv` | — | provider standard | Name of the environment variable that holds the API key. Normally auto-detected (e.g. `OPENAI_API_KEY` for the `openai` provider). Set this only if your key is in a non-standard env var. |
|
|
|
|
---
|
|
|
|
### Memory Bank
|
|
|
|
A **bank** is an isolated memory store — like a separate "brain." These settings control which bank the plugin reads from and writes to.
|
|
|
|
| Setting | Env Var | Default | Description |
|
|
|---------|---------|---------|-------------|
|
|
| `bankId` | `HINDSIGHT_BANK_ID` | `"claude_code"` | The bank ID to use when `dynamicBankId` is `false`. All sessions share this single bank. |
|
|
| `bankMission` | `HINDSIGHT_BANK_MISSION` | generic assistant prompt | A short description of the agent's identity and purpose. Sent to Hindsight when creating or updating the bank, and used during recall to contextualize results. |
|
|
| `retainMission` | — | extraction prompt | Instructions for the fact extraction LLM — tells it *what* to extract from conversations (e.g. "Extract technical decisions and user preferences"). |
|
|
| `dynamicBankId` | `HINDSIGHT_DYNAMIC_BANK_ID` | `false` | When `true`, the plugin derives a unique bank ID from context fields (see `dynamicBankGranularity`), giving each combination its own isolated memory. |
|
|
| `dynamicBankGranularity` | — | `["agent", "project"]` | Which context fields to combine when building a dynamic bank ID. Available fields: `agent` (agent name), `project` (working directory), `session` (session ID), `channel` (channel ID), `user` (user ID). |
|
|
| `bankIdPrefix` | — | `""` | A string prepended to all bank IDs — both static and dynamic. Useful for namespacing (e.g. `"prod"` or `"staging"`). |
|
|
| `agentName` | `HINDSIGHT_AGENT_NAME` | `"claude-code"` | Name used for the `agent` field in dynamic bank ID derivation. |
|
|
|
|
---
|
|
|
|
### Auto-Recall
|
|
|
|
Auto-recall runs on every user prompt. It queries Hindsight for relevant memories and injects them into Claude's context as invisible `additionalContext` (the user doesn't see them in the chat transcript).
|
|
|
|
| Setting | Env Var | Default | Description |
|
|
|---------|---------|---------|-------------|
|
|
| `autoRecall` | `HINDSIGHT_AUTO_RECALL` | `true` | Master switch for auto-recall. Set to `false` to disable memory retrieval entirely. |
|
|
| `recallBudget` | `HINDSIGHT_RECALL_BUDGET` | `"mid"` | Controls how hard Hindsight searches for memories. `"low"` = fast, fewer strategies; `"mid"` = balanced; `"high"` = thorough, slower. Affects latency directly. |
|
|
| `recallMaxTokens` | `HINDSIGHT_RECALL_MAX_TOKENS` | `1024` | Maximum number of tokens in the recalled memory block. Lower values reduce context usage but may truncate relevant memories. |
|
|
| `recallTypes` | — | `["world", "experience"]` | Which memory types to retrieve. `"world"` = general facts; `"experience"` = personal experiences; `"observation"` = raw observations. |
|
|
| `recallContextTurns` | `HINDSIGHT_RECALL_CONTEXT_TURNS` | `1` | How many prior conversation turns to include when composing the recall query. `1` = only the latest user message; higher values give more context but may dilute the query. |
|
|
| `recallMaxQueryChars` | `HINDSIGHT_RECALL_MAX_QUERY_CHARS` | `800` | Maximum character length of the query sent to Hindsight. Longer queries are truncated. |
|
|
| `recallRoles` | — | `["user", "assistant"]` | Which message roles to include when building the recall query from prior turns. |
|
|
| `recallPromptPreamble` | — | built-in string | Text placed above the recalled memories in the injected context block. Customize this to change how Claude interprets the memories. |
|
|
|
|
---
|
|
|
|
### Auto-Retain
|
|
|
|
Auto-retain runs after Claude responds. It extracts the conversation transcript and sends it to Hindsight for long-term storage and fact extraction.
|
|
|
|
| Setting | Env Var | Default | Description |
|
|
|---------|---------|---------|-------------|
|
|
| `autoRetain` | `HINDSIGHT_AUTO_RETAIN` | `true` | Master switch for auto-retain. Set to `false` to disable memory storage entirely. |
|
|
| `retainMode` | `HINDSIGHT_RETAIN_MODE` | `"full-session"` | Retention strategy. `"full-session"` sends the full conversation transcript (with chunking). |
|
|
| `retainEveryNTurns` | — | `10` | How often to retain. `1` = every turn; `10` = every 10th turn. Higher values reduce API calls but delay memory capture. Values > 1 enable **chunked retention** with a sliding window. |
|
|
| `retainOverlapTurns` | — | `2` | When chunked retention fires, this many extra turns from the previous chunk are included for continuity. Total window size = `retainEveryNTurns + retainOverlapTurns`. |
|
|
| `retainRoles` | — | `["user", "assistant"]` | Which message roles to include in the retained transcript. |
|
|
| `retainToolCalls` | — | `true` | Whether to include tool calls (function invocations and results) in the retained transcript. Captures structured actions like file reads, searches, and code edits. |
|
|
| `retainTags` | — | `["{session_id}"]` | Tags attached to the retained document. Supports `{session_id}` placeholder which is replaced with the current session ID at runtime. |
|
|
| `retainMetadata` | — | `{}` | Arbitrary key-value metadata attached to the retained document. |
|
|
| `retainContext` | — | `"claude-code"` | A label attached to retained memories identifying their source. Useful when multiple integrations write to the same bank. |
|
|
|
|
---
|
|
|
|
### Debug
|
|
|
|
| Setting | Env Var | Default | Description |
|
|
|---------|---------|---------|-------------|
|
|
| `debug` | `HINDSIGHT_DEBUG` | `false` | Enable verbose logging to stderr. All log lines are prefixed with `[Hindsight]`. Useful for diagnosing connection issues, recall/retain behavior, and bank ID derivation. |
|
|
|
|
## Claude Code Channels
|
|
|
|
With [Claude Code Channels](https://docs.anthropic.com/en/docs/claude-code), Claude Code can operate as a persistent background agent connected to Telegram, Discord, Slack, and other messaging platforms. This plugin gives Channel-based agents the same long-term memory that `hindsight-openclaw` provides for Openclaw agents.
|
|
|
|
For Channel agents, enable dynamic bank IDs for per-channel/per-user memory isolation:
|
|
|
|
```json
|
|
{
|
|
"dynamicBankId": true,
|
|
"dynamicBankGranularity": ["agent", "channel", "user"]
|
|
}
|
|
```
|
|
|
|
And set channel context via environment variables:
|
|
|
|
```bash
|
|
export HINDSIGHT_CHANNEL_ID="telegram-group-12345"
|
|
export HINDSIGHT_USER_ID="user-67890"
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
**Plugin not activating**: Check Claude Code logs for `[Hindsight]` messages. Enable `"debug": true` in `~/.hindsight/claude-code.json`.
|
|
|
|
**Recall returning no memories**: Verify the Hindsight server is reachable (`curl http://localhost:9077/health`). Memories need at least one retain cycle before they're available.
|
|
|
|
**Daemon not starting**: Ensure an LLM API key is set (or use `HINDSIGHT_LLM_PROVIDER=claude-code`). Review daemon logs at `~/.hindsight/profiles/claude-code.log`.
|
|
|
|
**High latency on recall**: The recall hook has a 12-second timeout. Use `recallBudget: "low"` or reduce `recallMaxTokens` for faster responses.
|