GREATMEMORY.

Getting started

Ingest, use, and remove data

Public examples for adding text and files, using memory in prompts, and deleting imported data by id.

The full data loop is small: ingest text into a space, use it through recall or context blocks, and remove it by id when it should no longer be available.

Use a space for each project, workspace, user, or environment. That keeps imports isolated and makes cleanup predictable.

1. Ingest text

For one-off memories, the CLI is the shortest path:

gmem add "The staging database runs Postgres 17 with pgvector." --space demo

For apps, jobs, and imports, use the REST API and keep the returned id:

MEMORY_ID=$(
  curl -s http://127.0.0.1:7437/v1/memories \
    -H 'Content-Type: application/json' \
    -d '{"space":"demo","content":"The staging database runs Postgres 17 with pgvector."}' |
  jq -r '.id'
)

echo "$MEMORY_ID"

Adds return quickly (202 Accepted): greatmemory chunks and embeds in the background through a bounded queue, so imports can stream data without waiting for each embedding operation.

2. Ingest files

greatmemory stores text. For plain-text files, read the file and POST it. Prefix the source path into the memory body so later retrieval has provenance.

export GM_URL=http://127.0.0.1:7437
export SPACE=docs-demo

mkdir -p .greatmemory-import
: > .greatmemory-import/ids.txt

find ./docs -type f \( -name '*.md' -o -name '*.txt' -o -name '*.json' -o -name '*.csv' \) -print0 |
while IFS= read -r -d '' file; do
  id=$(
    jq -n --rawfile content "$file" \
      --arg space "$SPACE" \
      --arg source "$file" \
      '{space:$space, content:("SOURCE: " + $source + "\n\n" + $content)}' |
    curl -sS "$GM_URL/v1/memories" \
      -H 'Content-Type: application/json' \
      -d @- |
    jq -r '.id'
  )
  printf '%s\t%s\n' "$id" "$file" >> .greatmemory-import/ids.txt
done

For PDF, DOCX, HTML, or slide decks, run an extractor first and POST the extracted text. Keep the source URI in the content prefix:

pdftotext ./contracts/acme-master-services.pdf - |
jq -Rs --arg space contracts \
  '{space:$space, content:("SOURCE: ./contracts/acme-master-services.pdf\n\n" + .)}' |
curl -sS "$GM_URL/v1/memories" \
  -H 'Content-Type: application/json' \
  -d @-

Cloud examples are in the provider guides:

3. Use the data

Use recall when you want scored chunks and facts:

gmem search "what does staging run?" --space demo

Use mode: "context" when you want a block ready to inject into an LLM prompt:

curl -s http://127.0.0.1:7437/v1/search \
  -H 'Content-Type: application/json' \
  -d '{"space":"demo","query":"staging database setup","mode":"context","max_tokens":1000}'

For an agent loop, the rhythm is:

  1. POST /v1/search with mode: "context" before the model call.
  2. Put the returned context block into the system or developer prompt.
  3. POST /v1/memories after the turn for durable facts, decisions, and outcomes.

With MCP, the equivalent tools are get_context, recall, and remember.

4. Remove data

Delete a memory by id when it should no longer be retrieved:

curl -s -X DELETE "$GM_URL/v1/memories/$MEMORY_ID"

If you imported many files, delete from the import manifest:

cut -f1 .greatmemory-import/ids.txt |
while read -r id; do
  curl -s -X DELETE "$GM_URL/v1/memories/$id" >/dev/null
done

With MCP, call forget with the memory_id returned by remember.

Facts already extracted from a deleted memory may remain as audited graph history but lose their source link. If you need a clean-room test, use a dedicated space or data directory for the import run.

Minimal TypeScript loop

const GM = "http://127.0.0.1:7437";
const SPACE = "demo";

async function remember(content: string) {
  const res = await fetch(`${GM}/v1/memories`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ space: SPACE, content }),
  });
  if (!res.ok) throw new Error(`remember failed: ${res.status}`);
  return (await res.json()).id as string;
}

async function context(query: string) {
  const res = await fetch(`${GM}/v1/search`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ space: SPACE, query, mode: "context", max_tokens: 1000 }),
  });
  if (!res.ok) throw new Error(`search failed: ${res.status}`);
  return (await res.json()).context as string;
}

async function forget(memoryId: string) {
  const res = await fetch(`${GM}/v1/memories/${memoryId}`, { method: "DELETE" });
  if (!res.ok) throw new Error(`delete failed: ${res.status}`);
}