From ae8108adbedb9e354aee9e7becf91ba86d4a4347 Mon Sep 17 00:00:00 2001 From: Dhravya <63950637+Dhravya@users.noreply.github.com> Date: Mon, 27 Apr 2026 23:19:39 +0000 Subject: [PATCH] docs: replace ASCII diagrams with Mermaid, add both agent patterns --- apps/docs/smfs/providers/cloudflare.mdx | 133 ++++++++++++++---- apps/docs/smfs/providers/daytona.mdx | 172 ++++++++++++++++++++---- apps/docs/smfs/providers/e2b.mdx | 154 +++++++++++++++++---- apps/docs/smfs/providers/vercel.mdx | 78 +++++++---- 4 files changed, 431 insertions(+), 106 deletions(-) diff --git a/apps/docs/smfs/providers/cloudflare.mdx b/apps/docs/smfs/providers/cloudflare.mdx index f6e04d0b..127a719c 100644 --- a/apps/docs/smfs/providers/cloudflare.mdx +++ b/apps/docs/smfs/providers/cloudflare.mdx @@ -9,24 +9,35 @@ agent can read and write memory using standard filesystem commands. ## How it works -``` -┌──────────────────────────────────────────┐ -│ Cloudflare Container │ -│ │ -│ ┌──────────┐ ┌────────────────────┐ │ -│ │ Claude │───▶│ /memory │ │ -│ │ Agent │ │ (SMFS mount) │ │ -│ └──────────┘ └────────┬───────────┘ │ -│ │ │ -└───────────────────────────┼──────────────┘ - │ - ┌───────▼───────┐ - │ Supermemory │ - └───────────────┘ +There are two ways to wire SMFS into a Cloudflare Container — pick the one that +fits your architecture. + +### Agent inside the container + +The agent process runs inside the container with direct access to the SMFS +mount. The entrypoint sets up the mount and starts the agent. + +```mermaid +graph LR + subgraph Cloudflare Container + Agent["Claude Agent"] -->|"cat, ls, echo"| Mount["/memory\n(SMFS mount)"] + end + Mount -->|sync| SM["Supermemory"] ``` -SMFS and the Claude Agent SDK are baked into the container image. On startup, -the entrypoint mounts memory and runs the agent. +### Agent outside the container + +The agent runs in a Cloudflare Worker and sends commands to the container over +HTTP. The container exposes a simple exec endpoint. + +```mermaid +graph LR + Agent["Worker\n(agent logic)"] -->|"fetch('/exec')"| Container + subgraph Container ["Cloudflare Container"] + Mount["/memory\n(SMFS mount)"] + end + Mount -->|sync| SM["Supermemory"] +``` ## Prerequisites @@ -35,7 +46,14 @@ the entrypoint mounts memory and runs the agent. - A [Cloudflare account](https://dash.cloudflare.com) with Containers enabled - [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/install-and-update/) -## 1. Dockerfile +--- + +## Pattern A: Agent inside the container + +SMFS and the Claude Agent SDK are baked into the container image. On startup, +the entrypoint mounts memory and runs the agent. + +### Dockerfile ```dockerfile Dockerfile FROM python:3.12-slim @@ -54,7 +72,7 @@ RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] ``` -## 2. Entrypoint +### Entrypoint ```bash entrypoint.sh #!/bin/bash @@ -67,20 +85,22 @@ sleep 3 exec python3 /app/agent.py ``` -## 3. Agent +### Agent code ```python agent.py import asyncio from claude_agent_sdk import query, ClaudeAgentOptions +MEMORY = "/memory" + async def main(): async for message in query( - prompt="You have a persistent memory filesystem at /memory. " + prompt=f"You have a persistent memory filesystem at {MEMORY}. " "Read profile.md to learn about the user, then create " "session_notes.md summarizing what you found.", options=ClaudeAgentOptions( allowed_tools=["Bash", "Read", "Write"], - cwd="/memory", + cwd=MEMORY, ), ): print(message) @@ -88,7 +108,7 @@ async def main(): asyncio.run(main()) ``` -## 4. Deploy +### Deploy ```toml wrangler.toml name = "memory-agent" @@ -106,19 +126,82 @@ wrangler secret put ANTHROPIC_API_KEY wrangler deploy ``` -## Worker frontend (optional) +--- -Use a Worker as the HTTP frontend that triggers the container: +## Pattern B: Agent outside the container + +The agent logic lives in a Worker. The container just runs SMFS and exposes an +HTTP endpoint for executing commands against the mount. + +### Container (exec server) + +```dockerfile Dockerfile +FROM python:3.12-slim + +RUN apt-get update && apt-get install -y fuse3 curl bash && rm -rf /var/lib/apt/lists/* +RUN echo 'user_allow_other' >> /etc/fuse.conf + +RUN curl -fsSL https://smfs.ai/install | bash -s -- 0.0.1-rc2 +ENV PATH="/root/.local/bin:$PATH" +RUN pip install flask + +COPY server.py /app/server.py +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] +``` + +```bash entrypoint.sh +#!/bin/bash +set -e + +smfs login --key "$SUPERMEMORY_API_KEY" +smfs mount my_agent --ephemeral --path /memory --foreground & +sleep 3 + +exec python3 /app/server.py +``` + +```python server.py +import subprocess +from flask import Flask, request, jsonify + +app = Flask(__name__) + +@app.route("/exec", methods=["POST"]) +def exec_command(): + cmd = request.json["command"] + result = subprocess.run( + cmd, shell=True, capture_output=True, text=True, cwd="/memory", timeout=10 + ) + return jsonify(stdout=result.stdout, stderr=result.stderr, code=result.returncode) + +app.run(host="0.0.0.0", port=8080) +``` + +### Worker (agent logic) ```typescript worker.ts export default { async fetch(request: Request, env: any) { const container = await env.MY_CONTAINER.start(); - return container.fetch("/result"); + + const profile = await container + .fetch("/exec", { + method: "POST", + body: JSON.stringify({ command: "cat /memory/profile.md" }), + headers: { "Content-Type": "application/json" }, + }) + .then((r: Response) => r.json()); + + return Response.json({ profile: profile.stdout }); }, }; ``` +--- + ## Tips - Use `--ephemeral` for container mounts — keeps the cache in memory only, but diff --git a/apps/docs/smfs/providers/daytona.mdx b/apps/docs/smfs/providers/daytona.mdx index 482061b0..a81dc77e 100644 --- a/apps/docs/smfs/providers/daytona.mdx +++ b/apps/docs/smfs/providers/daytona.mdx @@ -14,23 +14,35 @@ your agent can read and write memory using standard filesystem commands. [local mount](/smfs/providers/vercel) instead. -## How it works (once network is resolved) +## How it works +There are two ways to wire SMFS into a Daytona sandbox — pick the one that fits +your architecture. + +### Agent inside the sandbox + +The agent process runs inside the sandbox and accesses the SMFS mount directly. + +```mermaid +graph LR + subgraph Daytona Sandbox + Agent["Claude Agent"] -->|"cat, ls, echo"| Mount["/home/daytona/memory\n(SMFS mount)"] + end + Mount -->|sync| SM["Supermemory"] ``` -┌──────────────────────────────────────────┐ -│ Daytona Sandbox │ -│ │ -│ ┌──────────┐ ┌────────────────────┐ │ -│ │ Claude │───▶│ /home/daytona/ │ │ -│ │ Agent │ │ memory │ │ -│ │ │ │ (SMFS mount) │ │ -│ └──────────┘ └────────┬───────────┘ │ -│ │ │ -└───────────────────────────┼──────────────┘ - │ - ┌───────▼───────┐ - │ Supermemory │ - └───────────────┘ + +### Agent outside the sandbox + +The agent runs in your orchestrating code and executes commands inside the +sandbox remotely. + +```mermaid +graph LR + Agent["Claude Agent\n(your server)"] -->|"sandbox.process.exec()"| Sandbox + subgraph Sandbox ["Daytona Sandbox"] + Mount["/home/daytona/memory\n(SMFS mount)"] + end + Mount -->|sync| SM["Supermemory"] ``` ## Prerequisites @@ -39,7 +51,11 @@ your agent can read and write memory using standard filesystem commands. - A [Daytona API key](https://app.daytona.io) — go to **API Keys** in the sidebar - An [Anthropic API key](https://console.anthropic.com) -## 1. Write your agent +--- + +## Pattern A: Agent inside the sandbox + +### Agent code ```python agent.py import asyncio @@ -62,7 +78,7 @@ async def main(): asyncio.run(main()) ``` -## 2. Run it +### Orchestration @@ -80,17 +96,19 @@ asyncio.run(main()) }, ) - # Install SMFS + # Install SMFS (from GitHub releases — smfs.ai is unreachable from Daytona) sandbox.process.exec( + "mkdir -p $HOME/.local/bin && " "curl -sL https://github.com/supermemoryai/smfs/releases/download/" "v0.0.1-rc2/smfs-linux-x64 -o $HOME/.local/bin/smfs && " "chmod +x $HOME/.local/bin/smfs" ) - # Fix FUSE config + # Fix FUSE config and install agent SDK sandbox.process.exec( "echo 'user_allow_other' | sudo tee -a /etc/fuse.conf > /dev/null" ) + sandbox.process.exec("pip install claude-agent-sdk") # Mount memory sandbox.process.exec("$HOME/.local/bin/smfs login --key $SUPERMEMORY_API_KEY") @@ -128,10 +146,11 @@ asyncio.run(main()) "chmod +x $HOME/.local/bin/smfs" ); - // Fix FUSE config + // Fix FUSE config and install agent SDK await sandbox.process.exec( "echo 'user_allow_other' | sudo tee -a /etc/fuse.conf > /dev/null" ); + await sandbox.process.exec("pip install claude-agent-sdk"); // Mount memory await sandbox.process.exec( @@ -142,7 +161,7 @@ asyncio.run(main()) "--path /home/daytona/memory --foreground &' && sleep 3" ); - // Run the agent + // Upload and run the agent const result = await sandbox.process.exec("python3 agent.py"); console.log(result.result); @@ -151,11 +170,106 @@ asyncio.run(main()) - - Daytona sandboxes can't reach `smfs.ai`, so the install downloads the binary - directly from GitHub releases. The SMFS binary and Claude Agent SDK both - install successfully — only the Supermemory API connection is blocked. - +--- + +## Pattern B: Agent outside the sandbox + +The agent runs in your server process and executes commands inside the sandbox +remotely via `sandbox.process.exec()`. + + + + ```python run.py + import os + from daytona_sdk import Daytona, DaytonaConfig + + daytona = Daytona(DaytonaConfig( + api_key=os.environ["DAYTONA_API_KEY"], + )) + sandbox = daytona.create( + env_vars={ + "SUPERMEMORY_API_KEY": os.environ["SUPERMEMORY_API_KEY"], + }, + ) + + # Install and mount SMFS + sandbox.process.exec( + "mkdir -p $HOME/.local/bin && " + "curl -sL https://github.com/supermemoryai/smfs/releases/download/" + "v0.0.1-rc2/smfs-linux-x64 -o $HOME/.local/bin/smfs && " + "chmod +x $HOME/.local/bin/smfs" + ) + sandbox.process.exec( + "echo 'user_allow_other' | sudo tee -a /etc/fuse.conf > /dev/null" + ) + sandbox.process.exec("$HOME/.local/bin/smfs login --key $SUPERMEMORY_API_KEY") + sandbox.process.exec( + "bash -c '$HOME/.local/bin/smfs mount my_agent --ephemeral" + " --path /home/daytona/memory --foreground &' && sleep 3" + ) + + # Agent runs here — executes commands in the sandbox + profile = sandbox.process.exec("cat /home/daytona/memory/profile.md") + print("Profile:", profile.result) + + sandbox.process.exec( + "bash -c 'echo \"Session started at $(date)\" > /home/daytona/memory/session_notes.md'" + ) + + files = sandbox.process.exec("ls /home/daytona/memory") + print("Files:", files.result) + + daytona.delete(sandbox) + ``` + + + ```typescript run.ts + import { Daytona } from "@daytonaio/sdk"; + + const daytona = new Daytona({ + apiKey: process.env.DAYTONA_API_KEY!, + }); + const sandbox = await daytona.create({ + envVars: { + SUPERMEMORY_API_KEY: process.env.SUPERMEMORY_API_KEY!, + }, + }); + + // Install and mount SMFS + await sandbox.process.exec( + "mkdir -p $HOME/.local/bin && " + + "curl -sL https://github.com/supermemoryai/smfs/releases/download/" + + "v0.0.1-rc2/smfs-linux-x64 -o $HOME/.local/bin/smfs && " + + "chmod +x $HOME/.local/bin/smfs" + ); + await sandbox.process.exec( + "echo 'user_allow_other' | sudo tee -a /etc/fuse.conf > /dev/null" + ); + await sandbox.process.exec( + "$HOME/.local/bin/smfs login --key $SUPERMEMORY_API_KEY" + ); + await sandbox.process.exec( + "bash -c '$HOME/.local/bin/smfs mount my_agent --ephemeral " + + "--path /home/daytona/memory --foreground &' && sleep 3" + ); + + // Agent runs here — executes commands in the sandbox + const profile = await sandbox.process.exec("cat /home/daytona/memory/profile.md"); + console.log("Profile:", profile.result); + + await sandbox.process.exec( + `bash -c 'echo "Session started at $(date)" > /home/daytona/memory/session_notes.md'` + ); + + const files = await sandbox.process.exec("ls /home/daytona/memory"); + console.log("Files:", files.result); + + await daytona.delete(sandbox); + ``` + + + +--- ## Tips @@ -164,3 +278,9 @@ asyncio.run(main()) - The binary installs to `~/.local/bin/` which isn't on PATH by default in Daytona's zsh — use the full path or `export PATH=$HOME/.local/bin:$PATH` - Use `pip install claude-agent-sdk` to install the agent SDK (PyPI is reachable) + + + Daytona sandboxes can't reach `smfs.ai`, so the install downloads the binary + directly from GitHub releases. The SMFS binary and Claude Agent SDK both + install successfully — only the Supermemory API connection is blocked. + diff --git a/apps/docs/smfs/providers/e2b.mdx b/apps/docs/smfs/providers/e2b.mdx index 3c719686..8bf0a7d5 100644 --- a/apps/docs/smfs/providers/e2b.mdx +++ b/apps/docs/smfs/providers/e2b.mdx @@ -8,25 +8,36 @@ agent can read and write memory using standard filesystem commands. ## How it works -``` -┌─────────────────────────────────────────┐ -│ E2B Sandbox │ -│ │ -│ ┌──────────┐ ┌───────────────────┐ │ -│ │ Claude │───▶│ /home/user/memory │ │ -│ │ Agent │ │ (SMFS mount) │ │ -│ └──────────┘ └────────┬──────────┘ │ -│ │ │ -└───────────────────────────┼──────────────┘ - │ - ┌───────▼───────┐ - │ Supermemory │ - └───────────────┘ +There are two ways to wire SMFS into an E2B sandbox — pick the one that fits +your architecture. + +### Agent inside the sandbox + +The agent process runs inside the sandbox and accesses the SMFS mount directly. +Your orchestrating code just boots the sandbox and kicks off the agent. + +```mermaid +graph LR + subgraph E2B Sandbox + Agent["Claude Agent"] -->|"cat, ls, echo"| Mount["/home/user/memory\n(SMFS mount)"] + end + Mount -->|sync| SM["Supermemory"] ``` -The agent runs inside the sandbox. SMFS mounts a Supermemory container as a -regular directory. The agent uses `cat`, `ls`, `echo` — standard bash. Writes -sync to Supermemory automatically. +### Agent outside the sandbox + +The agent runs in your orchestrating code and executes commands inside the +sandbox remotely. Useful when you want to keep the agent loop in your own +infra. + +```mermaid +graph LR + Agent["Claude Agent\n(your server)"] -->|"sbx.commands.run()"| Sandbox + subgraph Sandbox ["E2B Sandbox"] + Mount["/home/user/memory\n(SMFS mount)"] + end + Mount -->|sync| SM["Supermemory"] +``` ## Prerequisites @@ -52,10 +63,14 @@ RUN pip install claude-agent-sdk e2b template build -d e2b.Dockerfile ``` -## 2. Write your agent +--- -This is the code that runs inside the sandbox. It's just normal Python — -nothing sandbox-specific: +## Pattern A: Agent inside the sandbox + +The agent runs inside the sandbox as a Python script. Your orchestrating code +just sets up the mount and starts it. + +### Agent code ```python agent.py import asyncio @@ -78,7 +93,7 @@ async def main(): asyncio.run(main()) ``` -## 3. Run it +### Orchestration @@ -105,8 +120,9 @@ asyncio.run(main()) " --path /home/user/memory --foreground &' && sleep 3" ) - # Run the agent - result = sbx.commands.run("python3 agent.py", timeout=120) + # Upload and run the agent + sbx.files.write("/home/user/agent.py", open("agent.py").read()) + result = sbx.commands.run("python3 /home/user/agent.py", timeout=120) print(result.stdout) sbx.kill() @@ -115,6 +131,7 @@ asyncio.run(main()) ```typescript run.ts import { Sandbox } from "@e2b/code-interpreter"; + import { readFileSync } from "fs"; const sbx = await Sandbox.create({ template: "your-template-id", @@ -134,8 +151,9 @@ asyncio.run(main()) "bash -c 'smfs mount my_agent --ephemeral --path /home/user/memory --foreground &' && sleep 3" ); - // Run the agent - const result = await sbx.commands.run("python3 agent.py", { + // Upload and run the agent + await sbx.files.write("/home/user/agent.py", readFileSync("agent.py", "utf-8")); + const result = await sbx.commands.run("python3 /home/user/agent.py", { timeoutMs: 120_000, }); console.log(result.stdout); @@ -145,12 +163,92 @@ asyncio.run(main()) +--- + +## Pattern B: Agent outside the sandbox + +The agent runs in your server process and executes commands inside the sandbox +remotely via `sbx.commands.run()`. The SMFS mount lives inside the sandbox — +the agent never touches the filesystem directly. + + + + ```python run.py + import os + from e2b_code_interpreter import Sandbox + + sbx = Sandbox.create( + template="your-template-id", + timeout=300, + envs={ + "SUPERMEMORY_API_KEY": os.environ["SUPERMEMORY_API_KEY"], + }, + ) + + # Set up SMFS inside the sandbox + sbx.commands.run("sudo chmod 666 /dev/fuse") + sbx.commands.run("smfs login --key $SUPERMEMORY_API_KEY") + sbx.commands.run( + "bash -c 'smfs mount my_agent --ephemeral" + " --path /home/user/memory --foreground &' && sleep 3" + ) + + # Agent runs here — executes commands in the sandbox + profile = sbx.commands.run("cat /home/user/memory/profile.md").stdout + print("Profile:", profile) + + sbx.commands.run( + "sudo bash -c 'echo \"Session started at $(date)\" > /home/user/memory/session_notes.md'" + ) + + files = sbx.commands.run("ls /home/user/memory").stdout + print("Files:", files) + + sbx.kill() + ``` + + + ```typescript run.ts + import { Sandbox } from "@e2b/code-interpreter"; + + const sbx = await Sandbox.create({ + template: "your-template-id", + timeoutMs: 300_000, + envs: { + SUPERMEMORY_API_KEY: process.env.SUPERMEMORY_API_KEY!, + }, + }); + + // Set up SMFS inside the sandbox + await sbx.commands.run("sudo chmod 666 /dev/fuse"); + await sbx.commands.run("smfs login --key $SUPERMEMORY_API_KEY"); + await sbx.commands.run( + "bash -c 'smfs mount my_agent --ephemeral --path /home/user/memory --foreground &' && sleep 3" + ); + + // Agent runs here — executes commands in the sandbox + const profile = await sbx.commands.run("cat /home/user/memory/profile.md"); + console.log("Profile:", profile.stdout); + + await sbx.commands.run( + `sudo bash -c 'echo "Session started at $(date)" > /home/user/memory/session_notes.md'` + ); + + const files = await sbx.commands.run("ls /home/user/memory"); + console.log("Files:", files.stdout); + + await sbx.kill(); + ``` + + + - The FUSE mount is owned by root. The Claude agent handles this automatically - with the Bash tool (it uses `sudo` when needed). If you're writing files - manually, use `sudo bash -c 'echo "..." > /path/file'`. + The FUSE mount is owned by root. When writing files from outside the agent, + use `sudo bash -c 'echo "..." > /path/file'`. +--- + ## Tips - Use `--ephemeral` for sandbox mounts — keeps the cache in memory only, but diff --git a/apps/docs/smfs/providers/vercel.mdx b/apps/docs/smfs/providers/vercel.mdx index b1c7daab..0158fad5 100644 --- a/apps/docs/smfs/providers/vercel.mdx +++ b/apps/docs/smfs/providers/vercel.mdx @@ -8,24 +8,35 @@ write memory using standard filesystem commands. ## How it works -``` -┌──────────────────────────────────────┐ -│ Your Server │ -│ │ -│ ┌──────────┐ ┌────────────────┐ │ -│ │ Claude │───▶│ ./memory │ │ -│ │ Agent │ │ (SMFS mount) │ │ -│ └──────────┘ └───────┬────────┘ │ -│ │ │ -└──────────────────────────┼───────────┘ - │ - ┌───────▼───────┐ - │ Supermemory │ - └───────────────┘ +There are two ways to wire SMFS into a Vercel-based agent — pick the one that +fits your architecture. + +### Claude Agent SDK (agent has full filesystem access) + +The agent runs as a separate process with direct access to the SMFS mount. +Best when you want the agent to have full bash, read, and write capabilities. + +```mermaid +graph LR + subgraph Your Server + Agent["Claude Agent"] -->|"cat, ls, echo"| Mount["./memory\n(SMFS mount)"] + end + Mount -->|sync| SM["Supermemory"] ``` -SMFS mounts directly on the host. No sandbox needed — the agent runs in your -server process and accesses memory through the filesystem. +### Vercel AI SDK (agent uses a tool) + +The agent runs inside `generateText` and accesses memory through a bash tool +you define. Best when you're building an API route and want to keep everything +in one TypeScript process. + +```mermaid +graph LR + subgraph Your Server + AI["generateText()"] -->|"bash tool"| Mount["./memory\n(SMFS mount)"] + end + Mount -->|sync| SM["Supermemory"] +``` ## Prerequisites @@ -33,27 +44,36 @@ server process and accesses memory through the filesystem. - An [Anthropic API key](https://console.anthropic.com) - SMFS installed: `curl -fsSL https://smfs.ai/install | bash` -## 1. Mount memory +## Mount memory + +Start the mount once when your server boots — not per-request: ```bash smfs login --key $SUPERMEMORY_API_KEY smfs mount my_agent --path ./memory ``` -## 2. Write your agent +--- + +## Pattern A: Claude Agent SDK + +Write a standalone agent script. Nothing server-specific — just Python that +reads and writes files. ```python agent.py import asyncio from claude_agent_sdk import query, ClaudeAgentOptions +MEMORY = "./memory" + async def main(): async for message in query( - prompt="You have a persistent memory filesystem at ./memory. " + prompt=f"You have a persistent memory filesystem at {MEMORY}. " "Read profile.md to learn about the user, then create " "session_notes.md summarizing what you found.", options=ClaudeAgentOptions( allowed_tools=["Bash", "Read", "Write"], - cwd="./memory", + cwd=MEMORY, ), ): print(message) @@ -65,13 +85,12 @@ asyncio.run(main()) python3 agent.py ``` -That's it. The agent reads and writes files in `./memory` using standard bash -commands. Everything syncs to Supermemory automatically. +--- -## Using with the Vercel AI SDK +## Pattern B: Vercel AI SDK -If you're building an API route with the Vercel AI SDK, expose the memory -filesystem as a tool: +Expose the memory filesystem as a bash tool inside an API route. The agent +calls the tool to run commands against the mount. ```typescript api/agent.ts import { generateText, tool } from "ai"; @@ -79,7 +98,6 @@ import { anthropic } from "@ai-sdk/anthropic"; import { z } from "zod"; import { execSync } from "child_process"; -// SMFS is mounted at ./memory (started when the server boots) const MEMORY = "./memory"; export async function POST(req: Request) { @@ -93,7 +111,11 @@ export async function POST(req: Request) { parameters: z.object({ command: z.string() }), execute: async ({ command }) => { try { - return execSync(command, { cwd: MEMORY, encoding: "utf-8", timeout: 10_000 }); + return execSync(command, { + cwd: MEMORY, + encoding: "utf-8", + timeout: 10_000, + }); } catch (e: any) { return e.stderr || e.message; } @@ -108,6 +130,8 @@ export async function POST(req: Request) { } ``` +--- + ## Tips - Mount SMFS once when your server starts, not per-request