diff --git a/apps/docs/docs.json b/apps/docs/docs.json index c385883f..82691bc1 100644 --- a/apps/docs/docs.json +++ b/apps/docs/docs.json @@ -152,7 +152,17 @@ "smfs/overview", "smfs/install", "smfs/mount", - "smfs/bash-tool" + "smfs/bash-tool", + { + "group": "Providers", + "icon": "cloud", + "pages": [ + "smfs/providers/daytona", + "smfs/providers/e2b", + "smfs/providers/vercel", + "smfs/providers/cloudflare" + ] + } ] } ], diff --git a/apps/docs/smfs/overview.mdx b/apps/docs/smfs/overview.mdx index da26a6c6..32b9606f 100644 --- a/apps/docs/smfs/overview.mdx +++ b/apps/docs/smfs/overview.mdx @@ -37,6 +37,25 @@ Pick by where your agent runs. +## Use SMFS with your sandbox provider + +Already using a sandbox or agent platform? Jump straight to the guide for your provider. + + + + Isolated Linux sandboxes with millisecond boot times. Mount SMFS inside or use the bash tool from your orchestrating code. + + + Firecracker microVMs for AI code execution. Install SMFS directly or use a custom template with it pre-installed. + + + The most popular TypeScript agent framework. Add memory as a tool with one function call. + + + Edge-first agents. Use the bash tool in Workers, or mount SMFS in Cloudflare Containers. + + + ## Next steps diff --git a/apps/docs/smfs/providers/cloudflare.mdx b/apps/docs/smfs/providers/cloudflare.mdx new file mode 100644 index 00000000..94de4742 --- /dev/null +++ b/apps/docs/smfs/providers/cloudflare.mdx @@ -0,0 +1,205 @@ +--- +title: "Cloudflare" +sidebarTitle: "Cloudflare" +description: "Add persistent memory to Cloudflare Workers agents with SMFS." +icon: "cloud" +--- + +[Cloudflare Workers](https://workers.cloudflare.com) run at the edge in V8 isolates — no filesystem, no shell. That's exactly what `@supermemory/bash` is built for. It gives your Worker a virtual bash environment backed by Supermemory, so your agent can `ls`, `cat`, `grep`, and write to a persistent memory container without needing a real filesystem. + +## Architecture + +Cloudflare Workers can't mount SMFS (no FUSE, no disk). Instead, use `@supermemory/bash` as a tool for your agent. The bash tool runs entirely in-process — no child processes, no disk I/O, no native dependencies. + +``` +Request → Worker → LLM → calls bash tool → @supermemory/bash → Supermemory API +``` + + + If you're using [Cloudflare Containers](https://developers.cloudflare.com/containers/) (full Linux containers at the edge), you can install the `smfs` binary directly. See [Alternative: Cloudflare Containers](#alternative-cloudflare-containers) below. + + +## Prerequisites + +- A [Supermemory](https://console.supermemory.ai) account and API key +- A [Cloudflare](https://dash.cloudflare.com) account +- Node.js 18+ and Wrangler CLI + +## 1. Set up a Worker + +```bash +npm create cloudflare@latest -- my-memory-agent +cd my-memory-agent +npm install @supermemory/bash +``` + +Add your Supermemory API key as a secret: + +```bash +npx wrangler secret put SUPERMEMORY_API_KEY +``` + +## 2. Build an agent with memory + +```typescript src/index.ts +import { createBash } from "@supermemory/bash"; + +export default { + async fetch(request: Request, env: Env): Promise { + const { bash, toolDescription } = await createBash({ + apiKey: env.SUPERMEMORY_API_KEY, + containerTag: "user_42", + }); + + // Read the user's profile + const profile = await bash.exec("cat /profile.md"); + + // Search memory semantically + const results = await bash.exec("sgrep 'project deadlines'"); + + // Write new memory + await bash.exec('echo "Met with client on April 27" >> /notes.md'); + + return new Response(JSON.stringify({ + profile: profile.stdout, + search: results.stdout, + })); + }, +}; +``` + +## 3. Full agent with tool calling + +Wire `@supermemory/bash` as a tool for an LLM. This example uses the OpenAI API, but any provider works: + +```typescript src/index.ts +import { createBash } from "@supermemory/bash"; + +interface Env { + SUPERMEMORY_API_KEY: string; + OPENAI_API_KEY: string; +} + +export default { + async fetch(request: Request, env: Env): Promise { + const { messages, userId } = await request.json() as { + messages: any[]; + userId: string; + }; + + const { bash, toolDescription } = await createBash({ + apiKey: env.SUPERMEMORY_API_KEY, + containerTag: `user_${userId}`, + }); + + // Call the LLM with the bash tool + const response = await fetch("https://api.openai.com/v1/chat/completions", { + method: "POST", + headers: { + "Authorization": `Bearer ${env.OPENAI_API_KEY}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + model: "gpt-4o", + messages: [ + { + role: "system", + content: `You have persistent memory via a bash tool. +Use it to remember things about the user. +Start by reading /profile.md for context.`, + }, + ...messages, + ], + tools: [{ + type: "function", + function: { + name: "bash", + description: toolDescription, + parameters: { + type: "object", + properties: { cmd: { type: "string" } }, + required: ["cmd"], + }, + }, + }], + }), + }); + + const data = await response.json() as any; + + // Handle tool calls + if (data.choices[0].message.tool_calls) { + const toolCall = data.choices[0].message.tool_calls[0]; + const cmd = JSON.parse(toolCall.function.arguments).cmd; + const result = await bash.exec(cmd); + + // Send the result back to the LLM + const followUp = await fetch("https://api.openai.com/v1/chat/completions", { + method: "POST", + headers: { + "Authorization": `Bearer ${env.OPENAI_API_KEY}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + model: "gpt-4o", + messages: [ + ...messages, + data.choices[0].message, + { + role: "tool", + tool_call_id: toolCall.id, + content: JSON.stringify(result), + }, + ], + }), + }); + + const followUpData = await followUp.json() as any; + return new Response(followUpData.choices[0].message.content); + } + + return new Response(data.choices[0].message.content); + }, +}; +``` + +## Alternative: Cloudflare Containers + +[Cloudflare Containers](https://developers.cloudflare.com/containers/) give you full Linux environments at the edge. Unlike Workers, containers have a real filesystem and shell — so you can install and mount SMFS directly. + +```dockerfile Dockerfile +FROM node:20-slim + +# Install SMFS +RUN curl -fsSL https://smfs.ai/install | sh + +# Your agent code +COPY . /app +WORKDIR /app +RUN npm install + +CMD ["node", "agent.js"] +``` + +Inside the container, mount SMFS as you would on any Linux machine: + +```bash +smfs login --key $SUPERMEMORY_API_KEY +smfs mount agent_memory --ephemeral --path /memory +``` + +Your agent can then use standard Unix commands to interact with memory. + +## Tips + +- **Workers have a 30-second CPU time limit.** Keep tool call chains short. If your agent needs many steps, consider using Durable Objects for longer-running workflows. +- **One container tag per user.** Use the user's ID as the container tag for isolated memory per user. +- **`sgrep` for semantic search.** Inside the bash tool, `sgrep "query"` searches by meaning. Regular `grep` does literal matching. +- **Cache-friendly.** `@supermemory/bash` warms its path index on `createBash`. For Workers that handle many requests, consider caching the instance in a Durable Object. + +## Resources + +- [Cloudflare Workers docs](https://developers.cloudflare.com/workers/) +- [Cloudflare Containers docs](https://developers.cloudflare.com/containers/) +- [SMFS Bash Tool reference](/smfs/bash-tool) +- [Supermemory quickstart](/quickstart) diff --git a/apps/docs/smfs/providers/daytona.mdx b/apps/docs/smfs/providers/daytona.mdx new file mode 100644 index 00000000..195cf14b --- /dev/null +++ b/apps/docs/smfs/providers/daytona.mdx @@ -0,0 +1,227 @@ +--- +title: "Daytona" +sidebarTitle: "Daytona" +description: "Give your Daytona sandboxes persistent memory with SMFS." +icon: "server" +--- + +[Daytona](https://www.daytona.io) gives AI agents isolated Linux sandboxes that boot in milliseconds. Pair it with SMFS and your agent gets both safe code execution **and** persistent memory it can `ls`, `cat`, and `grep`. + +## Architecture + +Daytona sandboxes run full Linux with shell access, filesystem, and network. There are two ways to wire SMFS in: + + + + Install the `smfs` binary inside the sandbox and mount a container directly. Best when the sandbox has unrestricted outbound HTTPS. + + + Use `@supermemory/bash` in the code that **orchestrates** the sandbox. The agent reads memory via the bash tool, then sends code to Daytona for execution. Best for most setups. + + + + + Daytona sandboxes may restrict outbound TLS to certain hosts. If `smfs mount` fails with connection errors, use the Bash Tool pattern instead — it runs in your orchestrating code, not inside the sandbox. + + +## Prerequisites + +- A [Supermemory](https://console.supermemory.ai) account and API key +- A [Daytona](https://app.daytona.io) account and API key +- Node.js 18+ or Python 3.10+ + +## 1. Get your API keys + +### Supermemory + +1. Go to [console.supermemory.ai](https://console.supermemory.ai) +2. Navigate to **Settings → API Keys** +3. Create a new key and copy it + +### Daytona + +1. Go to [app.daytona.io](https://app.daytona.io) +2. Sign up and verify your email +3. Set your default region (US or EU) +4. Navigate to **API Keys** in the sidebar +5. Click **Create Key**, give it a name, and copy the key + + + You can only view a Daytona API key once. Store it somewhere safe immediately after creation. + + +## 2. Install the SDKs + + + + ```bash + npm install @supermemory/bash @daytonaio/sdk + ``` + + + ```bash + pip install supermemory daytona-sdk + ``` + + + +## 3. Build an agent with memory + code execution + +The recommended pattern: your agent code uses `@supermemory/bash` for memory and the Daytona SDK for code execution. The LLM gets both as tools. + + + + ```typescript agent.ts + import { createBash } from "@supermemory/bash"; + import { Daytona } from "@daytonaio/sdk"; + import { generateText, tool } from "ai"; + import { openai } from "@ai-sdk/openai"; + import { z } from "zod"; + + async function main() { + // 1. Set up memory (SMFS bash tool) + const { bash, toolDescription } = await createBash({ + apiKey: process.env.SUPERMEMORY_API_KEY!, + containerTag: "agent_memory", + }); + + // 2. Set up code execution (Daytona sandbox) + const daytona = new Daytona({ + apiKey: process.env.DAYTONA_API_KEY!, + apiUrl: "https://app.daytona.io/api", + }); + const sandbox = await daytona.create(); + + // 3. Give the LLM both tools + const result = await generateText({ + model: openai("gpt-4o"), + tools: { + memory: tool({ + description: toolDescription, + parameters: z.object({ cmd: z.string() }), + execute: async ({ cmd }) => bash.exec(cmd), + }), + execute_code: tool({ + description: "Run code in an isolated sandbox", + parameters: z.object({ code: z.string() }), + execute: async ({ code }) => { + const res = await sandbox.process.exec(code); + return res.result; + }, + }), + }, + prompt: "Check my memory for the user's preferred language, then write and run a hello world in that language.", + }); + + console.log(result.text); + + // 4. Clean up + await daytona.delete(sandbox); + } + + main(); + ``` + + + ```python agent.py + import os + from daytona_sdk import Daytona, DaytonaConfig + + # 1. Set up code execution (Daytona sandbox) + config = DaytonaConfig( + api_key=os.environ["DAYTONA_API_KEY"], + api_url="https://app.daytona.io/api", + ) + daytona = Daytona(config) + sandbox = daytona.create() + + # 2. Install SMFS inside the sandbox + sandbox.process.exec( + "curl -fsSL https://smfs.ai/install | sh" + ) + + # 3. Log in and mount + sandbox.process.exec( + f"~/.local/bin/smfs login --key {os.environ['SUPERMEMORY_API_KEY']}" + ) + sandbox.process.exec( + "~/.local/bin/smfs mount agent_memory --ephemeral" + ) + + # 4. Your agent can now use the filesystem + sandbox.process.exec('echo "User prefers Python" > agent_memory/memory.md') + response = sandbox.process.exec("cat agent_memory/profile.md") + print(response.result) + + # 5. Semantic search + response = sandbox.process.exec( + "~/.local/bin/smfs grep 'preferred language'" + ) + print(response.result) + + # 6. Clean up + sandbox.process.exec("~/.local/bin/smfs unmount agent_memory") + daytona.delete(sandbox) + ``` + + + +## Alternative: Mount SMFS inside the sandbox + +If your Daytona sandbox has unrestricted network access, you can install and mount SMFS directly inside it. This gives the agent a real filesystem it can navigate with standard Unix commands. + +```python +from daytona_sdk import Daytona, DaytonaConfig +import os + +config = DaytonaConfig( + api_key=os.environ["DAYTONA_API_KEY"], + api_url="https://app.daytona.io/api", +) +daytona = Daytona(config) +sandbox = daytona.create() + +# Install SMFS +sandbox.process.exec("curl -fsSL https://smfs.ai/install | sh") + +# Log in +sandbox.process.exec( + f"~/.local/bin/smfs login --key {os.environ['SUPERMEMORY_API_KEY']}" +) + +# Mount with ephemeral mode (recommended for sandboxes) +sandbox.process.exec( + "~/.local/bin/smfs mount agent_memory --ephemeral --path /memory" +) + +# Now the agent can use standard Unix commands +sandbox.process.exec('echo "Meeting notes from standup" > /memory/notes.md') +result = sandbox.process.exec("cat /memory/profile.md") +print(result.result) + +# Semantic grep works inside the mount +result = sandbox.process.exec("cd /memory && grep 'standup'") +print(result.result) + +# Clean up +sandbox.process.exec("~/.local/bin/smfs unmount agent_memory") +daytona.delete(sandbox) +``` + + + Use `--ephemeral` when mounting inside sandboxes. It keeps the cache in memory only — nothing persists locally after unmount, but writes still push to Supermemory. + + +## Tips + +- **Use `--ephemeral` for sandboxes.** Sandbox filesystems are temporary. Ephemeral mode avoids writing a local SQLite cache that will be thrown away. +- **One container, many sandboxes.** Mount the same container tag from multiple sandboxes. Bidirectional sync keeps them in step. +- **Give each agent a subdirectory.** If multiple agents share a container, scope them to `/agent_a/`, `/agent_b/`, etc. They can still read across the whole mount. +- **Clean up sandboxes.** Call `daytona.delete(sandbox)` when done to avoid burning through free credits. + +## Resources + +- [Daytona docs](https://www.daytona.io/docs) +- [Daytona SDK reference](https://www.daytona.io/docs/en/tools/api/) +- [SMFS Mount reference](/smfs/mount) +- [SMFS Bash Tool reference](/smfs/bash-tool) diff --git a/apps/docs/smfs/providers/e2b.mdx b/apps/docs/smfs/providers/e2b.mdx new file mode 100644 index 00000000..922a0f22 --- /dev/null +++ b/apps/docs/smfs/providers/e2b.mdx @@ -0,0 +1,218 @@ +--- +title: "E2B" +sidebarTitle: "E2B" +description: "Give your E2B sandboxes persistent memory with SMFS." +icon: "cube" +--- + +[E2B](https://e2b.dev) runs AI-generated code in secure Firecracker microVMs. Pair it with SMFS and your agent gets both safe code execution **and** persistent memory it can `ls`, `cat`, and `grep`. + +## Architecture + +E2B sandboxes are ephemeral Linux microVMs with full shell access. Two ways to wire SMFS in: + + + + Install the `smfs` binary inside the sandbox and mount a container. The agent uses standard Unix commands to read and write memory. + + + Use `@supermemory/bash` in the code that **orchestrates** the sandbox. Memory lives in your agent code; code execution lives in E2B. + + + +## Prerequisites + +- A [Supermemory](https://console.supermemory.ai) account and API key +- An [E2B](https://e2b.dev) account and API key +- Node.js 18+ or Python 3.10+ + +## 1. Get your API keys + +### Supermemory + +1. Go to [console.supermemory.ai](https://console.supermemory.ai) +2. Navigate to **Settings → API Keys** +3. Create a new key and copy it + +### E2B + +1. Go to [e2b.dev](https://e2b.dev) and sign up +2. Open the [Dashboard](https://e2b.dev/dashboard) +3. Navigate to **API Keys** +4. Copy your API key + +## 2. Install the SDKs + + + + ```bash + npm install @supermemory/bash @e2b/code-interpreter + ``` + + + ```bash + pip install supermemory e2b-code-interpreter + ``` + + + +## 3. Build an agent with memory + code execution + + + + ```typescript agent.ts + import { createBash } from "@supermemory/bash"; + import { Sandbox } from "@e2b/code-interpreter"; + import { generateText, tool } from "ai"; + import { openai } from "@ai-sdk/openai"; + import { z } from "zod"; + + async function main() { + // 1. Set up memory (SMFS bash tool) + const { bash, toolDescription } = await createBash({ + apiKey: process.env.SUPERMEMORY_API_KEY!, + containerTag: "agent_memory", + }); + + // 2. Set up code execution (E2B sandbox) + const sandbox = await Sandbox.create({ + apiKey: process.env.E2B_API_KEY!, + }); + + // 3. Give the LLM both tools + const result = await generateText({ + model: openai("gpt-4o"), + tools: { + memory: tool({ + description: toolDescription, + parameters: z.object({ cmd: z.string() }), + execute: async ({ cmd }) => bash.exec(cmd), + }), + execute_code: tool({ + description: "Run Python code in an isolated sandbox", + parameters: z.object({ code: z.string() }), + execute: async ({ code }) => { + const execution = await sandbox.runCode(code); + return execution.text; + }, + }), + }, + prompt: "Check my memory for the user's preferences, then write a script that uses them.", + }); + + console.log(result.text); + + // 4. Clean up + await sandbox.kill(); + } + + main(); + ``` + + + ```python agent.py + import os + from e2b_code_interpreter import Sandbox + + # 1. Create an E2B sandbox + sandbox = Sandbox(api_key=os.environ["E2B_API_KEY"]) + + # 2. Install SMFS inside the sandbox + sandbox.commands.run("curl -fsSL https://smfs.ai/install | sh") + + # 3. Log in and mount + sandbox.commands.run( + f"~/.local/bin/smfs login --key {os.environ['SUPERMEMORY_API_KEY']}" + ) + sandbox.commands.run( + "~/.local/bin/smfs mount agent_memory --ephemeral --path /memory" + ) + + # 4. Your agent can now use the filesystem + sandbox.commands.run('echo "User prefers dark mode" > /memory/memory.md') + + result = sandbox.commands.run("cat /memory/profile.md") + print(result.stdout) + + # 5. Semantic search + result = sandbox.commands.run("cd /memory && grep 'preferences'") + print(result.stdout) + + # 6. Clean up + sandbox.commands.run("~/.local/bin/smfs unmount agent_memory") + sandbox.kill() + ``` + + + +## Alternative: Mount SMFS inside the sandbox + +E2B sandboxes have full network access, so you can install and mount SMFS directly. This gives the agent a real filesystem with semantic grep. + +```python +from e2b_code_interpreter import Sandbox +import os + +sandbox = Sandbox(api_key=os.environ["E2B_API_KEY"]) + +# Install SMFS +sandbox.commands.run("curl -fsSL https://smfs.ai/install | sh") + +# Log in and mount +sandbox.commands.run( + f"~/.local/bin/smfs login --key {os.environ['SUPERMEMORY_API_KEY']}" +) +sandbox.commands.run( + "~/.local/bin/smfs mount agent_memory --ephemeral --path /memory" +) + +# Write some memory +sandbox.commands.run('echo "Project deadline is March 15" > /memory/notes.md') + +# Read the auto-generated profile +result = sandbox.commands.run("cat /memory/profile.md") +print(result.stdout) + +# Semantic search across all memory +result = sandbox.commands.run("cd /memory && grep 'deadline'") +print(result.stdout) + +# Clean up +sandbox.commands.run("~/.local/bin/smfs unmount agent_memory") +sandbox.kill() +``` + +## Custom E2B template with SMFS pre-installed + +For faster startup, bake SMFS into a custom E2B template so you don't have to install it every time: + +```dockerfile e2b.Dockerfile +FROM e2b/code-interpreter:latest + +# Pre-install SMFS +RUN curl -fsSL https://smfs.ai/install | sh +``` + +```bash +e2b template build -d e2b.Dockerfile +``` + +Then use your custom template: + +```python +sandbox = Sandbox(template="your-custom-template") +``` + +## Tips + +- **Use `--ephemeral` for sandboxes.** E2B sandboxes are short-lived. Ephemeral mode avoids writing a local cache that will be thrown away. +- **Custom templates save time.** Pre-install SMFS in a template to skip the install step on every sandbox boot. +- **E2B sandboxes have a timeout.** Default is 5 minutes. Set `timeout` when creating the sandbox if your agent needs longer. +- **One container, many sandboxes.** Mount the same container tag from multiple E2B sandboxes. Bidirectional sync keeps them in step. + +## Resources + +- [E2B docs](https://e2b.dev/docs) +- [E2B SDK reference](https://e2b.dev/docs/sdk-reference) +- [SMFS Mount reference](/smfs/mount) +- [SMFS Bash Tool reference](/smfs/bash-tool) diff --git a/apps/docs/smfs/providers/vercel.mdx b/apps/docs/smfs/providers/vercel.mdx new file mode 100644 index 00000000..615ac953 --- /dev/null +++ b/apps/docs/smfs/providers/vercel.mdx @@ -0,0 +1,168 @@ +--- +title: "Vercel AI SDK" +sidebarTitle: "Vercel AI SDK" +description: "Add persistent memory to agents built with the Vercel AI SDK." +icon: "triangle" +--- + +The [Vercel AI SDK](https://sdk.vercel.ai) is the most popular framework for building AI agents in TypeScript. SMFS plugs in as a tool — give your agent a `bash` tool backed by `@supermemory/bash` and it can `ls`, `cat`, `grep`, and write to a Supermemory container without any filesystem to manage. + +## Architecture + +The Vercel AI SDK uses a tool-calling pattern: you define tools, the model decides when to call them. `@supermemory/bash` fits this perfectly — it's a single tool that exposes a virtual filesystem backed by Supermemory. + +``` +User → AI SDK → LLM → calls bash tool → @supermemory/bash → Supermemory API +``` + +No sandbox needed. The bash tool runs in your server process and handles all the memory operations. + +## Prerequisites + +- A [Supermemory](https://console.supermemory.ai) account and API key +- Node.js 18+ +- An LLM provider (OpenAI, Anthropic, Google, etc.) + +## 1. Install + +```bash +npm install @supermemory/bash ai @ai-sdk/openai zod +``` + +## 2. Create an agent with memory + +```typescript agent.ts +import { createBash } from "@supermemory/bash"; +import { generateText, tool } from "ai"; +import { openai } from "@ai-sdk/openai"; +import { z } from "zod"; + +async function main() { + // Set up the SMFS bash tool + const { bash, toolDescription } = await createBash({ + apiKey: process.env.SUPERMEMORY_API_KEY!, + containerTag: "user_42", + }); + + const result = await generateText({ + model: openai("gpt-4o"), + tools: { + bash: tool({ + description: toolDescription, + parameters: z.object({ cmd: z.string() }), + execute: async ({ cmd }) => bash.exec(cmd), + }), + }, + maxSteps: 10, + system: `You have access to a persistent memory filesystem via the bash tool. +Use it to remember things about the user across conversations. +Start by reading /profile.md to see what you already know.`, + prompt: "What do you remember about me?", + }); + + console.log(result.text); +} + +main(); +``` + +That's it. The model will call `bash({ cmd: "cat /profile.md" })` to read the user's profile, `bash({ cmd: "ls /" })` to browse memory, and `bash({ cmd: "grep 'preferences'" })` to search semantically. + +## 3. Multi-step agent with memory + +A more complete example with conversation history and memory persistence: + +```typescript chat.ts +import { createBash } from "@supermemory/bash"; +import { generateText, tool, CoreMessage } from "ai"; +import { openai } from "@ai-sdk/openai"; +import { z } from "zod"; + +// Create one bash instance per user (reuse across requests) +const userBashInstances = new Map(); + +async function getBash(userId: string) { + if (!userBashInstances.has(userId)) { + const instance = await createBash({ + apiKey: process.env.SUPERMEMORY_API_KEY!, + containerTag: `user_${userId}`, + }); + userBashInstances.set(userId, instance); + } + return userBashInstances.get(userId); +} + +export async function chat(userId: string, messages: CoreMessage[]) { + const { bash, toolDescription } = await getBash(userId); + + return generateText({ + model: openai("gpt-4o"), + tools: { + bash: tool({ + description: toolDescription, + parameters: z.object({ cmd: z.string() }), + execute: async ({ cmd }) => bash.exec(cmd), + }), + }, + maxSteps: 10, + system: `You are a helpful assistant with persistent memory. + +Use the bash tool to: +- Read /profile.md at the start of each conversation for context +- Save important facts to /memory.md +- Search with grep when looking for specific information +- Organize notes in subdirectories as needed`, + messages, + }); +} +``` + +## With Vercel AI SDK Streams + +For streaming responses in a Next.js app: + +```typescript app/api/chat/route.ts +import { createBash } from "@supermemory/bash"; +import { streamText, tool } from "ai"; +import { openai } from "@ai-sdk/openai"; +import { z } from "zod"; + +export async function POST(req: Request) { + const { messages, userId } = await req.json(); + + const { bash, toolDescription } = await createBash({ + apiKey: process.env.SUPERMEMORY_API_KEY!, + containerTag: `user_${userId}`, + }); + + const result = streamText({ + model: openai("gpt-4o"), + tools: { + bash: tool({ + description: toolDescription, + parameters: z.object({ cmd: z.string() }), + execute: async ({ cmd }) => bash.exec(cmd), + }), + }, + maxSteps: 10, + system: "You have persistent memory via the bash tool. Read /profile.md for context.", + messages, + }); + + return result.toDataStreamResponse(); +} +``` + +## Tips + +- **One `createBash` per user.** Use the user's ID as the container tag. Each user gets their own isolated memory. +- **Read `profile.md` first.** Tell the model to `cat /profile.md` at the start of each conversation. It's a live digest of everything in the container. +- **`sgrep` for semantic search.** Inside the bash tool, `sgrep "query"` searches by meaning, not just text. Regular `grep` does literal matching. +- **Cache the bash instance.** `createBash` warms the path index on startup. Reuse the instance across requests for the same user. +- **Works with any LLM provider.** Swap `openai("gpt-4o")` for `anthropic("claude-sonnet-4-20250514")`, `google("gemini-2.0-flash")`, or any AI SDK-compatible provider. + +## Resources + +- [Vercel AI SDK docs](https://sdk.vercel.ai/docs) +- [SMFS Bash Tool reference](/smfs/bash-tool) +- [Supermemory quickstart](/quickstart)