Skip to content

Commit 9e51f32

Browse files
committed
Added IDE integration
1 parent 77902ef commit 9e51f32

9 files changed

Lines changed: 400 additions & 0 deletions

File tree

IDE/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Integrating OpenMemory with AI Coding Environments
2+
3+
This directory holds lightweight SDK shims that let popular AI-assisted IDEs talk to your OpenMemory server without additional backend plumbing. Every integration exposes the same small surface:
4+
5+
| Function | Description |
6+
|----------|-------------|
7+
| `remember(content, tags?)` | Persists a memory via `POST /memory/add`. |
8+
| `recall(query)` | Retrieves related memories via `POST /memory/query`. |
9+
| `forget(id)` | Removes a memory via `DELETE /memory/{id}`. |
10+
11+
All clients auto-detect `OPENMEMORY_URL` from the environment (`process.env.OPENMEMORY_URL`), falling back to `http://localhost:8080` so you can plug them into existing workflows instantly.
12+
13+
## Quick Example
14+
15+
```ts
16+
import { remember, recall } from './IDE/claude/claude'
17+
18+
await remember('User prefers dark mode.', ['preferences'])
19+
const theme = await recall('What theme does user like?')
20+
```
21+
22+
## Supported IDEs
23+
24+
- **Claude Code (Anthropic)**`/IDE/claude/claude.ts`
25+
- **GitHub Copilot / Codex**`/IDE/codex/codex.js`
26+
- **Cursor IDE**`/IDE/cursor/cursor.ts`
27+
- **Windsurf**`/IDE/windsurf/windsurf.ts`
28+
29+
Each subdirectory contains:
30+
31+
- The minimal client file (`claude.ts`, `codex.js`, `cursor.ts`, `windsurf.ts`).
32+
- A dedicated README with installation instructions, environment configuration, and usage snippets tailored to that IDE.
33+
34+
Use these clients as-is or adapt them to your project’s structure—they’re intentionally dependency-free and ESM-friendly so that IDE agents (Claude, Copilot, Cursor, Windsurf) can introspect and start storing context instantly.

IDE/claude/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
## OpenMemory + Claude Code
2+
3+
This helper lets Claude persist and recall context between coding sessions by talking directly to your local OpenMemory API.
4+
5+
### Setup
6+
7+
1. Ensure OpenMemory is running (default `http://localhost:8080`).
8+
2. Copy `claude.ts` into your repo (e.g., `project/IDE/claude/claude.ts`).
9+
3. Optionally set `OPENMEMORY_URL` in your workspace `.env` or shell:
10+
```bash
11+
OPENMEMORY_URL=http://localhost:8080
12+
```
13+
14+
### Usage Inside Claude
15+
16+
```ts
17+
import { remember, recall, forget } from './IDE/claude/claude'
18+
19+
await remember('User prefers dark mode.', ['preferences'])
20+
const matches = await recall('What theme does user like?')
21+
await forget(matches.matches[0].id)
22+
```
23+
24+
Claude inspects project files; once it sees these helpers it understands you’ve wired persistent memory and will offer them in completions when you ask things like “Integrate OpenMemory for memory recall.”
25+
26+
### API
27+
28+
| Function | Description |
29+
|----------|-------------|
30+
| `remember(content, tags?)` | Stores a memory node. |
31+
| `recall(query, k=8)` | Retrieves relevant memories. |
32+
| `forget(id)` | Deletes a memory by identifier. |
33+
34+
All functions use `fetch` and modern ESM exports so they work in Node-based Claude environments without extra dependencies.

IDE/claude/claude.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const DEFAULT_URL = 'http://localhost:8080'
2+
3+
type MemoryAddResponse = {
4+
id: string
5+
primary_sector: string
6+
sectors: string[]
7+
}
8+
9+
type MemoryMatch = {
10+
id: string
11+
content: string
12+
score: number
13+
sectors: string[]
14+
primary_sector: string
15+
}
16+
17+
type MemoryQueryResponse = {
18+
query: string
19+
matches: MemoryMatch[]
20+
}
21+
22+
const baseUrl = () => process.env.OPENMEMORY_URL?.trim() || DEFAULT_URL
23+
24+
async function request<T>(path: string, init: RequestInit): Promise<T> {
25+
const url = `${baseUrl()}${path}`
26+
const headers = {
27+
'content-type': 'application/json',
28+
...(init.headers || {})
29+
}
30+
const response = await fetch(url, { ...init, headers })
31+
if (!response.ok) {
32+
const text = await response.text().catch(() => '')
33+
throw new Error(`OpenMemory request failed (${response.status}): ${text || response.statusText}`)
34+
}
35+
if (response.status === 204) return undefined as T
36+
return response.json() as Promise<T>
37+
}
38+
39+
export async function remember(content: string, tags?: string[]): Promise<MemoryAddResponse> {
40+
if (!content || !content.trim()) {
41+
throw new Error('remember() requires non-empty content')
42+
}
43+
return request<MemoryAddResponse>('/memory/add', {
44+
method: 'POST',
45+
body: JSON.stringify({ content, tags })
46+
})
47+
}
48+
49+
export async function recall(query: string, k = 8): Promise<MemoryQueryResponse> {
50+
if (!query || !query.trim()) {
51+
throw new Error('recall() requires a query string')
52+
}
53+
return request<MemoryQueryResponse>('/memory/query', {
54+
method: 'POST',
55+
body: JSON.stringify({ query, k })
56+
})
57+
}
58+
59+
export async function forget(id: string): Promise<void> {
60+
if (!id) throw new Error('forget() requires a memory id')
61+
await request<void>(`/memory/${encodeURIComponent(id)}`, { method: 'DELETE' })
62+
}
63+
64+
export default { remember, recall, forget }

IDE/codex/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
## OpenMemory + GitHub Copilot / Codex
2+
3+
Use these helpers inside VSCode or JetBrains so Copilot can store and recall long-term context from OpenMemory.
4+
5+
### Setup
6+
7+
1. Run OpenMemory locally (default `http://localhost:8080`).
8+
2. Save `codex.js` somewhere public to your project (e.g., `IDE/codex/codex.js`).
9+
3. Export `OPENMEMORY_URL` if you’re not on localhost.
10+
11+
### Usage Example
12+
13+
```js
14+
import { memoryAdd, memoryQuery } from '../IDE/codex/codex.js'
15+
16+
await memoryAdd('Refactor added dark mode support.', ['ui'])
17+
const recall = await memoryQuery('What theme does the user prefer?')
18+
```
19+
20+
When Copilot sees `memoryAdd` / `memoryQuery` invocations it understands that persistent context is available and will weave it into suggestions.
21+
22+
### API Surface
23+
24+
| Function | Description |
25+
|----------|-------------|
26+
| `memoryAdd(content, tags?)` | Calls `POST /memory/add`. |
27+
| `memoryQuery(query, k)` | Calls `POST /memory/query`. |
28+
| `memoryDelete(id)` | Calls `DELETE /memory/{id}`. |
29+
30+
All exported functions use native `fetch` (Node 18+ / browsers) and modern ESM exports.

IDE/codex/codex.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
const DEFAULT_URL = 'http://localhost:8080'
2+
3+
const baseUrl = () => (process.env.OPENMEMORY_URL || DEFAULT_URL).trim()
4+
5+
async function http(path, init) {
6+
const url = `${baseUrl()}${path}`
7+
const headers = { 'content-type': 'application/json', ...(init.headers || {}) }
8+
const res = await fetch(url, { ...init, headers })
9+
if (!res.ok) {
10+
const body = await res.text().catch(() => '')
11+
throw new Error(`OpenMemory request failed (${res.status}): ${body || res.statusText}`)
12+
}
13+
if (res.status === 204) return undefined
14+
return res.json()
15+
}
16+
17+
export async function memoryAdd(content, tags) {
18+
if (!content || !content.trim()) {
19+
throw new Error('memoryAdd() requires non-empty content')
20+
}
21+
return http('/memory/add', {
22+
method: 'POST',
23+
body: JSON.stringify({ content, tags })
24+
})
25+
}
26+
27+
export async function memoryQuery(query, k = 8) {
28+
if (!query || !query.trim()) {
29+
throw new Error('memoryQuery() requires a query string')
30+
}
31+
return http('/memory/query', {
32+
method: 'POST',
33+
body: JSON.stringify({ query, k })
34+
})
35+
}
36+
37+
export async function memoryDelete(id) {
38+
if (!id) throw new Error('memoryDelete() requires a memory id')
39+
await http(`/memory/${encodeURIComponent(id)}`, { method: 'DELETE' })
40+
}
41+
42+
export default { memoryAdd, memoryQuery, memoryDelete }

IDE/cursor/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
## OpenMemory + Cursor IDE
2+
3+
This helper lets Cursor’s AI agent persist and recall OpenMemory context while you work.
4+
5+
### Setup
6+
7+
1. Run OpenMemory (default `http://localhost:8080`).
8+
2. Drop `cursor.ts` into your project (e.g., `IDE/cursor/cursor.ts`).
9+
3. Configure `OPENMEMORY_URL` if you’re targeting a remote server.
10+
11+
### Usage Inside Cursor
12+
13+
```ts
14+
import { om } from '../IDE/cursor/cursor'
15+
16+
await om.add('Cursor project linked to OpenMemory.')
17+
const memories = await om.search('integration progress')
18+
```
19+
20+
Cursor automatically inspects local code; once it sees `om.add` / `om.search` it will suggest them when you ask “Enable long-term memory.”
21+
22+
### API
23+
24+
| Method | Description |
25+
|--------|-------------|
26+
| `om.add(content, tags?)` | Persists a memory entry. |
27+
| `om.search(query, k)` | Retrieves matching memories. |
28+
| `om.remove(id)` | Deletes a specific memory node. |
29+
30+
`cursor.ts` exports both the named `om` object and `default om`, making it convenient in either ESM or auto-import scenarios.

IDE/cursor/cursor.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const DEFAULT_URL = 'http://localhost:8080'
2+
3+
interface MemoryAddResponse {
4+
id: string
5+
primary_sector: string
6+
sectors: string[]
7+
}
8+
9+
interface MemoryQueryResponse {
10+
query: string
11+
matches: Array<{
12+
id: string
13+
content: string
14+
score: number
15+
primary_sector: string
16+
sectors: string[]
17+
}>
18+
}
19+
20+
const baseUrl = () => process.env.OPENMEMORY_URL?.trim() || DEFAULT_URL
21+
22+
async function request<T>(path: string, init: RequestInit): Promise<T> {
23+
const url = `${baseUrl()}${path}`
24+
const headers = {
25+
'content-type': 'application/json',
26+
...(init.headers || {})
27+
}
28+
const res = await fetch(url, { ...init, headers })
29+
if (!res.ok) {
30+
const body = await res.text().catch(() => '')
31+
throw new Error(`OpenMemory request failed (${res.status}): ${body || res.statusText}`)
32+
}
33+
if (res.status === 204) return undefined as T
34+
return res.json() as Promise<T>
35+
}
36+
37+
async function add(content: string, tags?: string[]): Promise<MemoryAddResponse> {
38+
if (!content?.trim()) throw new Error('om.add() requires non-empty content')
39+
return request<MemoryAddResponse>('/memory/add', {
40+
method: 'POST',
41+
body: JSON.stringify({ content, tags })
42+
})
43+
}
44+
45+
async function search(query: string, k = 8): Promise<MemoryQueryResponse> {
46+
if (!query?.trim()) throw new Error('om.search() requires a query string')
47+
return request<MemoryQueryResponse>('/memory/query', {
48+
method: 'POST',
49+
body: JSON.stringify({ query, k })
50+
})
51+
}
52+
53+
async function remove(id: string): Promise<void> {
54+
if (!id) throw new Error('om.remove() requires a memory id')
55+
await request<void>(`/memory/${encodeURIComponent(id)}`, { method: 'DELETE' })
56+
}
57+
58+
export const om = {
59+
add,
60+
search,
61+
remove
62+
}
63+
64+
export default om

IDE/windsurf/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
## OpenMemory + Windsurf
2+
3+
Register OpenMemory as a Windsurf plugin so every agent can persist and recall context seamlessly.
4+
5+
### Setup
6+
7+
1. Run OpenMemory locally (`http://localhost:8080` by default) or expose it remotely and set `OPENMEMORY_URL`.
8+
2. Place `windsurf.ts` somewhere accessible, e.g., `IDE/windsurf/windsurf.ts`.
9+
3. Reference the plugin inside `windsurf.config.json`:
10+
11+
```json
12+
{
13+
"plugins": ["./IDE/windsurf/windsurf.ts"]
14+
}
15+
```
16+
17+
Windsurf loads the module and executes the default export during startup.
18+
19+
### Usage
20+
21+
```ts
22+
import { integrateWithWindsurf } from './IDE/windsurf/windsurf'
23+
24+
const om = await integrateWithWindsurf()
25+
await om.remember('Documented Windsurf integration.', ['docs'])
26+
const context = await om.recall('integration status')
27+
await om.forget(context.matches[0].id)
28+
```
29+
30+
### API
31+
32+
| Method | Description |
33+
|--------|-------------|
34+
| `remember(content, tags?)` | Adds a memory via `POST /memory/add`. |
35+
| `recall(query, k?)` | Searches memories via `POST /memory/query`. |
36+
| `forget(id)` | Deletes a memory via `DELETE /memory/{id}`. |
37+
38+
All network calls use native `fetch` with ESM exports so Windsurf’s runtime can load them without additional tooling.

0 commit comments

Comments
 (0)