Bring your memory
Beta
The console page described here is in beta: it is new and may fail. Every import can be undone from the page for 7 days. If something looks wrong, tell us at support@mnemoverse.com. The REST path on this page is the same memory and works regardless.
The console's import page reads memories you keep elsewhere, shows you what it would write before anything is sent, writes it in batches, and lets you undo the whole run. It is not an import endpoint: there is none in the API. The page composes two calls the API already has, POST /memory/write-batch to store and DELETE /memory/domain/{domain} to undo, so a script can do the same thing (Import from a script).
Open Dashboard → Memory → Import in the console. The page states what it does with your files: "Your files are read in this browser; only the memories you confirm are sent."
Before you import
In the preview, before you confirm, the page shows this text word for word:
Imported memories arrive as flat records. They keep their original date, so they show up on the day they happened, and that date also stays at the start of the text; Mnemoverse learns how they connect as you use them. There is no other way yet. If that does not suit you, do not import. You can undo this import for 7 days.
What each part means:
- Flat records. Each imported item becomes one memory. Its concepts come only from the source's own structure (a chat title, Pieces tags, a Claude Code memory type, a category header in a pasted list); no model reads your files to invent any. Links between memories are learned the way they are for any memory, as you use them.
- Original date. Each imported memory carries the date its source gave it as
occurred_at, sosince,until, newest-first ordering and the recent feed place it on the day it happened, whilecreated_atstill records the day of the import. The date is also kept at the start of the text, as2025-03-14 —followed by the memory, and inmetadata.original_created_at(see Dates). An item whose source gives no date gets the import date. - Undo for 7 days. Every run goes into a domain of its own, and the page can delete that domain for 7 days (Undo).
- Plan limits apply. Each batch is one request against your daily quota (1,000 a day on Free), and each saved memory counts toward your plan's memory limit (10,000 on Free). See Quota and plan limits.
What you can import
| Source | What to give the page | What becomes a memory | Date it keeps |
|---|---|---|---|
| ChatGPT export | The ZIP from ChatGPT's Settings → Data controls → Export data → Export, or the conversations.json inside it | The visible thread of each chat you pick: your messages and ChatGPT's, written as User: and ChatGPT: paragraphs and packed into parts of 1,500 characters or fewer. Abandoned branches (edited prompts, regenerated answers), hidden messages, system, tool and reasoning messages, and images are left out. The chat's title becomes a concept, unless it is the default "New chat" | The first message of each part |
| Pieces export | The folder that the official Pieces export tool writes, with or without its top folder, or zipped | One memory per workstream summary: its title and narrative. Tags, people, source applications and website names become concepts. Other Pieces material (events, people, tags, profile histories) is not imported | The summary's creation time |
| Claude Code memory folder | A project's ~/.claude/projects/<project>/memory/ folder | One memory per Markdown file: its description and body, with its type and name as concepts. MEMORY.md, the folder's index, is skipped | The file's modified time, when its frontmatter has one |
| A pasted list | Text with one memory per line, such as the list another assistant writes when you run Claude's or Gemini's memory-import prompt in it: [2025-03-14] - Prefers short answers | One memory per line. A header line such as ## Projects becomes a concept for the lines below it; Instructions, Identity and Preferences headers mark them as that kind. When the paste holds a code block, only the lines inside it are read | The bracketed date; [unknown] and [date saved, if available] count as no date |
| Mnemoverse export | The .jsonl file from Export your memory or GET /memory/export | Current versions of your memories, with their concepts and metadata. Replaced versions only when you tick "Also bring replaced versions of corrected memories", and then each arrives as a memory of its own. Vault entries and shared-room rows are never imported | occurred_at, otherwise created_at |
| Mnemoverse import format | JSONL in the format below, uploaded or pasted | One memory per line. A line that does not fit the format is reported with its line number, and the rest go on | occurred_at |
For a ChatGPT export, OpenAI's help article Exporting your ChatGPT history and data (read 2026-10-24) gives the steps and two timings worth knowing: "Exports can take up to 7 days to arrive", and "The download link expires 24 hours after you receive it." Self-service export is "Not available for ChatGPT Business, Enterprise, or ChatGPT for Healthcare workspaces."
How an import runs
- Choose. Drop files, a folder or a ZIP on the page, pick them, or paste text.
- Detect. The page names the source it recognised and how sure it is (high, medium or low confidence); you can change it. For a ChatGPT export it lists the chats with their date, message count and size, and you pick which ones to import.
- Preview. A dry run: the files are read and every item is prepared exactly as it would be sent, and nothing is sent yet. What the preview counts is below, with the first memories exactly as they will be saved.
- Import. After you confirm, the page sends batches of up to 100 memories, one request at a time, with a progress bar. Stop takes effect between batches, so nothing is left unaccounted for. A dropped connection, a timeout or a busy server is retried in place with the same
Idempotency-Key, so a batch that did arrive is not written twice; an interrupted run resumes from the first batch that got no answer. - Report. How many were saved, how many were not saved because they repeat a memory already there, how many failed with an error, and how many were not sent yet, with each item that was not saved and the reason. Read back then shows your account's memory count before and after, and whether the run's domain is listed.
- Undo. "Undo this import" deletes the run's domain, for 7 days (Undo).
What the preview counts
- Memories to import, by kind: memories, summaries, parts of chats, instructions, preferences, facts about you.
- Read from your files, and what was passed over and why: chats not picked, Vault entries, memories of shared rooms, replaced versions, empty or repeated entries,
MEMORY.mdindex files, Pieces items that are not summaries. - Split into parts: text longer than 1,500 characters is split at paragraph breaks, and each part becomes a memory that records its place (
chunk_index,chunk_totalin metadata). - Secrets left out: a line that holds an API key, a token, a private key or a payment card number is dropped, and so is a concept or metadata value that holds one. The preview shows those lines with the secret itself replaced by a label. The check works by pattern, so a secret with no recognisable shape gets through: read the preview.
- Lines that read like instructions to an assistant are listed. In the page's words, "They are imported as your notes and never followed."
- Links: a Markdown link keeps its text and a bare address becomes its site name. "Nothing was opened."
- Also: repeated items skipped, empty items skipped, dates that could not be read or lay in the future left out (the memory is kept without a date), and extra metadata left out where a memory's metadata would pass 64 KB.
- Requests: how many requests the run takes and how much of your daily quota they use.
- Undo: the domain everything goes into.
When an item is not saved
The report gives each item that was not saved with its reason:
- "Too close to another memory in this import." The write gate refused it: the item's novelty score against the nearest memory already stored in the same domain fell below the threshold.
POST /memory/writeexplains the gate under "Whenstoredisfalse". Every item of a run is written into the run's own domain, so the comparison is with what this import has already saved, not with the rest of your memory. - "Already in your memory: an earlier import brought in this item." Each item carries an
external_refbuilt from its source and its id in that source, and the API refuses a second memory with a reference your account already uses. Importing the same file twice does not duplicate it. After an undo those references are free again. - An error. Mnemoverse could not save that item; importing the same file again retries it, and the items already saved are recognised as above.
Undo
Every run writes into one domain of its own, import:<source>:<run>, where <run> is the UTC date and 8 random hexadecimal digits, for example import:chatgpt:20261024-1a2b3c4d. A domain the source carries itself, such as a Claude Code project's project:<name>, is kept in metadata.target_domain.
"Undo this import" deletes that domain through DELETE /memory/domain/{domain}, after a confirmation that names it. The dialog says what it does and does not do: "It removes the memories, not links Mnemoverse has already learned from using them. Vault entries are never deleted here."
The console offers the undo for 7 days from the run's first batch. It remembers runs in this browser, so the button survives a reload or a closed tab, and the page lists "Imports from this browser in the last 7 days"; another browser does not show them. The 7 days are the console's window. The domain itself stays an ordinary domain, and you can delete it with the REST call below at any time.
Quota and plan limits
- One request per batch. The console sends at most 100 memories per request; that is the console's choice, to keep each request well inside the time limit at the network edge. The API accepts up to 500 items in one
POST /memory/write-batch. - Daily quota. Each request counts once toward your plan's daily quota (1,000 a day on Free), so 2,000 memories take 20 requests. When an import needs more than the day has left, the page says the import "stops at the limit and can continue the next day while this tab stays open."
- Memory limit. Every saved memory counts toward your plan's memory limit (10,000 on Free). The preview warns when an import would take the account past it.
- Writes paused. While writes are refused on the account (a suspended subscription, an account past its memory limit after the grace date, or writes stopped by an administrator), the page says so before you choose anything, and nothing can be imported. Reads and export keep working. Subscription / atom limit lists the refusals.
Pricing has the limits of every plan.
Dates
Each imported item carries its original date as occurred_at, and time-based reads (since, until, newest-first ordering, the recent feed) place the memory on that date; created_at keeps the moment of the import. The date also opens the text (2025-03-14 — Prefers short answers) and is in metadata.original_created_at, so a plain read shows it too. An item with no date in its source is placed on the day of the import.
Import from a script
A script does what the page does with two REST calls and an API key. Pick a run id, write every item into one domain with a stable external_ref, and send each batch with its own Idempotency-Key, so a retry after a dropped connection returns the first answer instead of writing twice:
curl -X POST https://core.mnemoverse.com/api/v1/memory/write-batch \
-H "X-Api-Key: mk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 20261024-1a2b3c4d:0" \
-d '{
"items": [
{
"content": "2025-03-14 — Prefers short answers with the code first",
"concepts": ["preference"],
"domain": "import:text:20261024-1a2b3c4d",
"external_ref": "text:pref-short-answers",
"metadata": {
"source": "text",
"source_id": "pref-short-answers",
"import_run": "20261024-1a2b3c4d",
"original_created_at": "2025-03-14"
}
}
]
}'The response has one result per item (stored, atom_id, reason, error), as POST /memory/write-batch describes. Use the hyphenated route: the underscore spelling has no Idempotency-Key. Do not send occurred_at until the server has it: until then the API refuses it as an unknown field, and the whole batch fails with 400 VALIDATION_ERROR.
To undo the run:
curl -X DELETE https://core.mnemoverse.com/api/v1/memory/domain/import:text:20261024-1a2b3c4d \
-H "X-Api-Key: mk_live_YOUR_KEY"The import: prefix is the console's convention, not something the API reserves: to the API it is a domain like any other, which is why deleting it removes exactly that run.
The Mnemoverse import format
Every source above is first read into the same record, and the same record can be uploaded directly as JSONL (one JSON object per line, UTF-8), so any dataset shaped this way imports. Keys outside the format are ignored.
| Field | Type | Required | Meaning |
|---|---|---|---|
content | string | Yes | The memory text, self-contained. Text longer than 1,500 characters is split at paragraph breaks into parts, each its own memory |
occurred_at | string | No | When it happened, ISO 8601: a date (2025-03-14) or a date and time; without a UTC offset it is read as UTC. A line whose value is not such a date is reported as unreadable; a date before 1970 or in the future is left out, the memory is kept, and the preview counts it |
source | string | Yes | One of pieces, chatgpt, claude-code, text, mnemoverse, generic. It is the first part of the memory's external_ref |
source_id | string | Yes | The item's stable id in its source. external_ref is <source>:<source_id> (a longer one is shortened with a hash), so the same item imported twice is recognised |
concepts | string[] | No | Labels from the source's own structure. The console trims them, drops repeats regardless of case and keeps the first twelve |
domain | string | No | Your own domain for this item, such as project:api, at most 100 characters. Items are always written into the run's import: domain; this one is kept in metadata.target_domain |
metadata | object | No | Extra details, kept as the memory's metadata, beside the keys the console adds: source, source_id, import_run, original_created_at, kind, target_domain, and the part keys of a split item. If the whole would pass 64 KB, your keys are left out and the console's are kept |
kind | string | No | One of memory, summary, conversation-chunk, instruction, preference, identity. Kept in metadata; instruction, preference and identity are also written as the memory's first concept |
Three records:
{"content": "Prefers short answers with the code first", "occurred_at": "2025-03-14", "source": "generic", "source_id": "pref-1", "kind": "preference"}
{"content": "Staging deploys need REDIS_URL set in the staging env group", "occurred_at": "2026-08-02T09:30:00Z", "source": "generic", "source_id": "notes/deploys#1", "concepts": ["staging", "redis"], "domain": "project:api"}
{"content": "Works as a data engineer", "source": "generic", "source_id": "profile-1", "kind": "identity"}From each record the console makes one write item, or one per part of a split record: content with the date in front when the record has one (2025-03-14 — Prefers short answers with the code first), the run's import: domain, external_ref <source>:<source_id>, the concepts, the metadata, and occurred_at once the server has it.
Related
- Export your memory: the four download formats, and the JSONL this page reads back
- API Reference:
POST /memory/write-batch: the batch call an import is made of - API Reference:
DELETE /memory/domain/{domain}: the call behind the undo - API Reference:
occurred_at: dating a memory by when it happened - Claude Code and ChatGPT: connect the tools whose memories you just brought over
- Pricing: daily quotas and memory limits per plan