Memory
A folder of markdown files the agent writes and reads to carry context across conversations — plus optional sync between Chrome profiles.
Agent memory is a folder tree of plain markdown files. The agent authors and maintains it directly with the normal file tools — Read, Write, Edit, Move, LS, Glob, Grep — plus a searchMemory tool for retrieval. Writing a memory is just writing a file.
The files are the source of truth. IndexedDB holds a keyword + backlink index derived from them, and it is rebuilt from disk on startup, so hand edits and repairs are picked up automatically rather than fighting a hidden database.
No server, no account
Memory files live in your browser's origin-private filesystem (OPFS), local to
the Chrome profile. OpenBrowse has no backend: nothing is uploaded, and
nothing is used for training. Three honest caveats. Memory reaches your
model provider the way the rest of a conversation does — a compact index
of titles and descriptions goes into the system prompt each turn, and any note
the agent reads becomes part of that request, sent from your browser to the
provider you configured with your own key. If you turn on
sync and put the folder somewhere a cloud client
watches, that provider gets the files. And linking a folder writes a small
hint to chrome.storage.sync — the vault's random id, the folder's name,
and your profile label — so your other profiles can find it; with Chrome Sync
on, that rides your Google account the way a bookmark does. No absolute path
and no memory content is ever in it. Stop syncing withdraws the hint.
Where memory lives
| Path | Scope |
|---|---|
memory/** | Global — durable knowledge about you and your world. Visible in every conversation and every Space. |
spaces/<spaceId>/memory/** | Space-scoped — knowledge about that Space's project. Visible only inside it (globals stay visible too). |
Organization inside those roots is emergent, not prescribed. There is no required folder structure and no fixed taxonomy: the default is a flat, descriptively named file per topic, with a folder created only once a natural cluster appears. The [[link]] graph does the organizing, not deep nesting.
What a memory file looks like
YAML frontmatter plus a body split into a compiled-truth section and a timeline:
---
title: Garry Tan
description: President & CEO of Y Combinator
type: reference
domain: ycombinator.com
aliases: [gt]
created: 2026-08-05
updated: 2026-08-06
---
# Compiled truth
Current best understanding — read first. Works with [[jessica-livingston]]
at [[y-combinator]].
# Timeline
- 2026-08-06 — Met at the YC dinner. [Source: [[chat]]]The compiled-truth block is the current summary; timeline entries are appended rather than overwriting history, so the note keeps a record of how the agent's understanding changed.
The format is a convention, not a schema. Every field is optional and a plain markdown note with no frontmatter at all still parses and stays searchable — the whole file is simply treated as compiled truth. [Source: …] markers render as clickable links in the viewer, either back to the conversation a fact came from or out to the page it was read from.
Links and the graph
Notes reference each other with bare-basename [[wikilinks]]: [[garry-tan]] resolves to any …/garry-tan.md in scope, regardless of which folder it sits in. That makes links survive a Move, which is what allows the agent to reorganize memory without breaking anything.
Links are parsed on every write — no model calls involved — into a link/backlink table. Two things fall out of that:
- Linked-to notes rank higher in
searchMemory, and a search also returns a one-hop "related via links" set. - Settings → Memory has a graph view. A force-directed view of the whole link graph: node size by backlink count, color by scope, and hollow "dangling" nodes for links whose note doesn't exist yet — a useful signal for entities the agent referenced but never wrote up.
How the agent works with memory
There are no dedicated save/recall/update/delete memory tools. Recall is searchMemory or Read; save and update are Write and Edit; reorganizing is Move; forgetting is Delete. See the Tools Reference for signatures.
Only Delete asks
Writing, editing, and moving memory are ungated — the agent captures and
reorganizes as it goes, without a prompt. Deleting is the one memory
action that requires your approval. Move refuses to cross the memory
boundary in either direction, so it can't be used to smuggle a workspace file
into memory or to turn a delete into an unapproved one.
The agent decides when to write, but you can be explicit:
- "Remember that I prefer TypeScript over JavaScript."
- "Make a note about the people on the platform team."
- "Forget what you know about my old staging URL."
Managing memory yourself
Settings → Memory is a file tree on the left and the note on the right. The viewer parses frontmatter into a header, offers a Rendered ⟷ Source toggle, renders [[wikilinks]] as links you can click to navigate between notes, and has Delete behind a confirmation. In a Space, memory files open in the same rail viewer as Space files.
Sync across profiles
OPFS is partitioned per Chrome profile and Chrome never replicates it, so by default separate Work and Personal profiles mean two agents that know nothing about each other. Sync is the opt-in fix: point each profile at one shared folder — the vault — and their global memory converges.
Only memory/** syncs. Space-scoped memory does not: a Space's id is a per-profile UUID with no portable identity, so there is no honest way to tell that "Work" in one profile is the same Space as "Work" in another.
Turning it on
Open Settings → Memory and click the sync icon in the Memory header, then Choose folder…. Repeat in each Chrome profile, choosing the same folder every time. The icon shows an amber dot when sync needs a click — a lapsed grant, a moved folder, or unresolved conflicts — so you don't have to open the panel to notice.
If you don't have a folder yet, the panel suggests Documents/OpenBrowse and the picker opens in Documents, so you can create it right there. It isn't a dotfolder like ~/.openbrowse for one blunt reason: dotfolders are hidden in the OS file picker, and this is a folder you have to pick by hand in every profile. On macOS with iCloud Drive's "Desktop & Documents" option enabled, ~/Documents is already replicated — so that default gets you cross-machine sync without doing anything else. Any folder works; this is only a suggestion.
Linking never deletes anything. The first pass has no history to compare against, so the two trees are simply unioned.
Give each profile a label ("Work", "Personal") in the same panel. It's what conflicts are attributed to, so you can tell which profile made a change.
Finding the folder in your other profiles
Chrome won't let an extension preselect a path, and the picker's remembered directory is per-profile, so the second profile normally gets no help. Once one profile has linked a folder, the others stop guessing: an unlinked profile says "Your Work profile syncs memory to a folder named OpenBrowse. Choose that same folder here to join it." Pick a different folder anyway and you get told outright that the two profiles won't share anything — previously that mistake was silent and only surfaced later as memory that never converged.
The hint travels through chrome.storage.sync, so it only appears when the profiles are signed into the same Google account with Chrome Sync on. When they aren't, there is simply no suggestion and setup works exactly as before — you pick the same folder in each profile from memory. Nothing breaks; you just don't get the hint.
Across machines
Put the vault in Dropbox, iCloud Drive, or Google Drive — or git init it — and memory follows you between machines. OpenBrowse has no server and no account, so there is nothing for it to sync through; a folder your existing tools already replicate is the whole mechanism. The tradeoff is that whatever guarantees you get across machines are your cloud client's or git's, not ours.
The folder is a real markdown vault
The vault mirrors what Settings → Memory shows, one file at a time:
<vault>/
├── memory/ # mirrors memory/** 1:1
│ ├── garry-tan.md
│ └── projects/
│ └── openbrowse.md
└── .openbrowse/ # sync metadata; hidden in Obsidian
├── vault.json # vault id + schema version
├── tombstones/ # one file per deleted note
├── conflicts/ # copies that lost a conflict
└── lock # advisory cross-profile lockSo the vault is not an export format. Open it in Obsidian, read it, edit a note by hand, commit it and diff it in git — the next sync picks the change up as an ordinary edit. Metadata hides in a dotfolder, and paths beginning with . are rejected as memory notes, so sync bookkeeping can never be mistaken for something the agent should read.
Non-markdown files are ignored rather than imported, and a pass caps out at 1,000 files and 1 MB per file. Anything skipped is reported in the status line instead of being silently dropped.
When sync runs
Sync happens while an OpenBrowse surface is open — the side panel, the Alt+Space global chat popup, the home tab, or the Chrome new tab page. The new tab page counts deliberately: a Cmd-T quick chat is a normal way to use OpenBrowse, and memory written there would be a surprising thing to drop.
A pass fires:
- when a surface mounts, and each time one comes back to the foreground
- after an agent run finishes, in whichever surface is open
- about three seconds after memory changes on disk, debounced
- when you press Sync now
Automatic passes have a shared floor of roughly 10 seconds between attempts, counted across every tab in the profile rather than per tab — otherwise eight open new tab pages would turn each tab switch into another permission query and directory probe. Sync now ignores the floor. Automatic passes also skip silently when the folder grant has lapsed; only Sync now reports problems, because that's the one you asked for.
It is a checkpoint operation, not a live channel — and that is a constraint, not a preference. Chrome does not reliably keep folder permission across browser sessions, and the permission can only be restored by requestPermission() under a user gesture, which a background service worker with no open window cannot produce (crbug.com/1359786). So the sync engine has to live in a page, and the service worker can only ask whichever surface is open to run a pass.
That has one real gap, and it follows directly from the same constraint: a run driven by an external MCP host has no OpenBrowse page open, so nothing is listening for the request, and memory that run writes stays local until you next open a surface. It isn't lost — the next pass picks it up as an ordinary local edit. Scheduled runs don't have this problem, because the scheduler opens a pinned home tab to host the run, which brings the sync triggers with it.
The other visible consequence: near the start of a browser session you may see "Reconnect the folder to resume syncing" with a Reconnect button. That is routine, not an error — one click supplies the gesture Chrome wants.
Conflicts
If the same note changed in two profiles since they last agreed, the newer version wins — by the note's updated frontmatter date, falling back to file modification time when the dates match. Frontmatter is preferred because copying a vault between machines, restoring a backup, or a cloud client rewriting timestamps all disturb mtime while leaving the note's own record of when it last meaningfully changed intact.
The version that lost is never discarded. It is archived under .openbrowse/conflicts/ and listed in the sync panel with Restore and Dismiss. Restore makes that copy the live note again; Dismiss throws it away. Archives sit outside memory/ deliberately — the agent reads everything under memory/, so a second copy of a note parked there would surface the same fact twice and quietly corrupt the graph.
Deletes
Deleting a note in one profile removes it in the others. Two deliberate biases both favor keeping data:
- An edit beats a concurrent delete. Edit a note in one profile while deleting it in another and the edit wins — the note comes back, and the sync result says so rather than hiding it. Losing something you just wrote is worse than seeing something you deleted return.
- A note that simply vanished from the vault is restored, not deleted. Deletes made through OpenBrowse always leave a tombstone. A file that is just missing is far more likely to be a half-synced cloud folder or an interrupted copy than an instruction to erase memory, so it gets pushed back.
Tombstones are garbage-collected after 90 days. A profile that hasn't synced in longer than that can resurrect a note deleted elsewhere; that shows up in the status line as a restored note.
Stop syncing
Stop syncing unlinks the folder and deletes nothing. The memory in this profile and the files in the vault both stay exactly as they are. It also withdraws this profile's discovery hint, so it stops suggesting the folder to your other profiles.
Pick a folder only you control
Anything you put in the vault's memory/ directory becomes readable by the
agent, which makes a shared or world-writable folder a prompt-injection
vector. Do not point sync at a folder other people can write to. The vault is
also plaintext markdown on your disk — that is what makes it inspectable and
Obsidian- and git-compatible, and it is not encrypted at rest.
What tends to end up in memory
- You and your world — role, preferences, the people you work with, recurring projects, decisions.
- Project context — where things live, relevant URLs, active work, carried across sessions.
- References — facts worth keeping, with a
[Source: …]marker you can click to check.
Per-site knowledge — navigation patterns, selectors, page quirks — goes into that domain's site skill instead of memory. Ephemeral things (current page contents, open tab URLs, one-off task details) are deliberately not written at all.