Branch-Aware Chat Example
Source: apps/memforks-chat on GitHub
apps/memforks-chat is a Next.js 15 reference app that demonstrates the full MemForks browser experience with the Vercel AI SDK.
What It Shows
| Feature | What to test |
|---|---|
| Persistent memory | Start a fresh chat and ask what the assistant remembers. |
| Branch isolation | Fork a reply and teach the fork a different fact. |
| Thread persistence | Switch branches and return to the previous visible thread. |
| Memory diff | Compare what a fork knows against main. |
| Merge | Promote recalled facts from a fork into main. |
Run It
cd apps/memforks-chat
npm install
cp .env.example .env
npm run devOpen http://localhost:3001.
Required environment:
OPENAI_API_KEY=sk-...
MEMFORK_TREE_ID=0x...
MEMFORK_PRIVATE_KEY=suiprivkey1...
MEMFORK_NETWORK=mainnet
MEMFORK_MEMWAL_ACCOUNT=0x...
MEMFORK_MEMWAL_KEY=...
MEMFORK_RELAYER_URL=https://relayer.memory.walrus.xyzRun memfork init --quick (mainnet, gas sponsored — no SUI needed) then memfork doctor --env to print all the MemForks values.
Architecture
Chat Flow
- User sends a message with the active branch in the request body.
- The route extracts the last user message as the recall query.
- The app calls
recallFacts(query, branch)manually so it can display recalled facts in the UI. - Recalled context is injected into the system prompt.
withMemForks(openai(...), { autoCommit: true })streams the answer.- The completed answer is committed to the active branch.
- Recalled facts are returned in a response header for UI display.
Branching Flow
On main, every assistant reply has Branch from here.
When clicked:
POST /api/branchcreates a new branch frommain.- The UI switches to the new
explore/<id>branch. - The visible thread is trimmed to the branch point.
- New memory commits go only to the fork.
Diff Flow
The diff panel calls the same query on both branches:
const [fromFacts, intoFacts] = await Promise.all([
recallFacts(query, from, 10),
recallFacts(query, into, 10),
]);The UI normalizes fact text and tags facts as shared or unique.
Merge Flow
The demo merge is a semantic cherry-pick:
- Recall broad queries from the source branch.
- Deduplicate fact text.
- Commit the result to
main.
This is intentionally simpler than full proposeMerge() governance. It is useful for app-level "Promote to main" interactions.
Multi-User Pattern
For production, do not share a naked main branch across users. Use a stable authenticated prefix:
function userBranch(userId: string, branch = "main") {
return `user/${userId}/${branch}`;
}See Multi-User Apps.