Import and export use the same memory structure across all formats. This page is the canonical reference for the JSON, YAML, Markdown, and NDJSON schemas used by both the CLI (me import memories — alias me memory import — / me memory export) and MCP tools (me_memory_import / me_memory_export).
Every memory has one required field (content) and several optional fields:
| Field | Type | Required | Description |
|---|---|---|---|
id |
string |
no | UUIDv7. Preserves identity across import/export and makes re-import idempotent -- a record whose id (or (tree, name) slot) already exists is skipped. Must match ^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$. |
content |
string |
yes | The memory text. Must be non-empty. |
name |
string |
no | Optional filename-like leaf slug, unique within its tree (e.g. jwt-rotation). Matches ^[A-Za-z0-9][A-Za-z0-9._-]*$, ≤128 chars -- dots allowed, no slashes. Lets the memory be addressed as tree/name. |
meta |
object |
no | Arbitrary key-value metadata. Any valid JSON object. |
tree |
string |
no | Hierarchical path, /-separated with a leading slash (e.g. /share/work/projects/api); a leading ~ expands to your private home. The leading slash is optional on input. Each label matches [A-Za-z0-9_-]. When omitted, the file importers (me import memories, me_memory_import) default the record to the shared root /share. |
temporal |
varies | no | Time range for the memory. Accepted shapes depend on format -- see below. |
The temporal field normalizes to {start: string, end?: string} where timestamps are ISO 8601 with timezone offset (e.g. 2024-01-15T10:30:00Z).
Different formats accept different input shapes:
| Input shape | JSON | YAML | Markdown |
|---|---|---|---|
| String -- interpreted as start | yes | yes | yes |
Array of 1-2 strings -- [start] or [start, end] |
yes | yes | yes |
Object -- {start, end?} |
yes | yes | yes |
Examples:
"temporal": "2024-01-15T00:00:00Z"
"temporal": ["2024-01-01T00:00:00Z", "2024-12-31T23:59:59Z"]
"temporal": {"start": "2024-01-01T00:00:00Z", "end": "2024-12-31T23:59:59Z"}YAML and Markdown exports use the object form, so exported files can be re-imported without conversion.
A JSON array of memory objects. This is the default export format.
[
{
"id": "0194a000-0001-7000-8000-000000000001",
"content": "Project started with three engineers",
"tree": "/work/projects/api",
"name": "kickoff",
"meta": { "source": "import", "author": "jane" },
"temporal": { "start": "2024-01-15T00:00:00Z" }
},
{
"content": "Switched to PostgreSQL for the queue",
"tree": "/work/projects/api",
"meta": { "type": "decision" }
}
]A single object (not wrapped in an array) is also accepted:
{
"content": "Single memory import",
"tree": "/notes"
}File extensions: .json
Newline-delimited JSON -- one JSON object per line. Useful for streaming or large datasets.
{"content": "First memory", "tree": "/notes"}
{"content": "Second memory", "tree": "/notes", "name": "second", "meta": {"priority": "high"}}
{"content": "Third memory", "tree": "/notes"}
NDJSON is auto-detected when the content contains multiple lines that each start with {. It is parsed using the JSON parser internally.
File extensions: .ndjson, .jsonl
NDJSON is supported for import only. Export always produces a JSON array.
A YAML array of memory objects.
- id: "0194a000-0001-7000-8000-000000000001"
content: Project started with three engineers
tree: /work/projects/api
name: kickoff
meta:
source: import
author: jane
temporal:
start: "2024-01-15T00:00:00Z"
end: "2024-12-31T23:59:59Z"
- content: Switched to PostgreSQL for the queue
tree: /work/projects/api
meta:
type: decisionA single object (not wrapped in an array) is also accepted:
content: Single memory import
tree: /notesFile extensions: .yaml, .yml
A Markdown file with optional YAML frontmatter. The frontmatter carries the metadata fields; the body after the closing --- is the memory content.
---
id: 0194a000-0001-7000-8000-000000000001
tree: /work/projects/api
name: queue-backend
meta:
source: import
type: decision
temporal:
start: "2024-01-01T00:00:00Z"
end: "2024-06-30T23:59:59Z"
---
We decided to use PostgreSQL as the task queue backend instead of Redis.
The main reasons were transactional guarantees and operational simplicity.A file with no frontmatter is treated as a single memory with the entire file as content:
This entire file becomes the memory content.
No metadata, tree, or temporal information.One memory per file. Each .md file produces exactly one memory. To import multiple memories, use a directory with --recursive (CLI) or use JSON/YAML format instead.
File extensions: .md, .markdown
When exporting to Markdown, the directory mirrors the tree: each memory is written to <dir>/<tree-as-directories>/<name-or-id>.md. A named memory uses its name as the filename (.../share/auth/jwt-rotation.md); an unnamed one falls back to its {id}.md. Frontmatter includes name (when set) and created_at (CLI only) in addition to the standard fields. The created_at field is informational and is ignored on re-import.
- CLI: requires a directory path when exporting multiple memories. Single-memory export to stdout is allowed.
- MCP: when
pathis provided, creates or uses it as a directory tree of.mdfiles. Whenpathis null (inline), only single-memory export is allowed -- multiple memories will return an error asking for a directory path.
When no explicit format is specified, the format is detected automatically.
| Extension | Format |
|---|---|
.json |
JSON |
.ndjson |
NDJSON (parsed as JSON) |
.jsonl |
NDJSON (parsed as JSON) |
.yaml |
YAML |
.yml |
YAML |
.md |
Markdown |
.markdown |
Markdown |
When reading from stdin or a content string with no file extension, the format is detected from the content:
| Content starts with | Detected format |
|---|---|
--- |
Markdown |
{ or [ |
JSON |
| Anything else | YAML |
An explicit --format (CLI) or format parameter (MCP) always takes precedence over auto-detection.
| Limit | Value | Applies to |
|---|---|---|
| Batch size | 1,000 memories | Per import request |
| Request body | 1 MB | API request size (import via content / MCP inline) |
When importing from a file path, the file is read server-side and the 1 MB request limit does not apply. Use path instead of content for large imports.
Exported files can be re-imported directly. The export output uses the same field names and structure as the import schema; tree is written in the canonical /-prefixed form, which re-imports cleanly (input is lenient).
The id and name fields are preserved in exports, so re-importing is idempotent: the file importers submit with onConflict: 'ignore', and a record whose idempotency key -- a named record's (tree, name) slot (name takes precedence), else its id -- already exists is skipped rather than duplicated.
Fields that appear in exports but are not part of the import schema (like created_at in Markdown frontmatter) are silently ignored on re-import.