Skip to content
Local · Docker Compose · Manifest-driven

One local setup. Pick your agent memory backend.

personal-memory wires up indexing and compose for the memory API you pick. Agents use that provider’s plugin or MCP; this repo is plumbing, not a replacement memory product. Supported: Cognee, Hindsight, mem0.

Sources

  • Git repositories
  • Obsidian vaults
  • Notes · papers · bookmarks
  • Feed cache (RSS / OpenAlex)

Shared indexer

  • Tree-sitter code outlines
  • Poll repos · watch folders
  • Sink → active provider API

Memory provider

  • CogneeSupported
  • HindsightSupported
  • mem0Supported
  • GraphitiPlanned
  • LettaPlanned
  • ZepPlanned

MCP & plugins (host)

  • personal-memory MCP (memory_*)
  • Session hooks (all providers)
  • Provider MCP (mem0/Cognee, optional)
  • NotebookLM MCP (optional)

Coding agents

  • Claude Code
  • Codex
  • OpenCode
Indexing: repos, vaults, markdown trees, and feed cache → shared indexer → one active provider API (badges from manifests).Agents: unified memory_* MCP and session hooks on the host; optional provider-native MCP and NotebookLM MCP. LiteLLM is optional on Hindsight stacks (not shown). Optional upstream Hindsight plugin (@vectorize-io/hindsight-coding-agents) via --hindsight-plugin.Architecture.

What it does

Indexer, wizard, smoke tests, and MCP registration. Models and memory semantics stay with the provider you chose.

  • Pluggable providers

    Hindsight, mem0, Cognee, or the next manifest entry. One wizard and indexer; `npx personal-memory switch` rewires compose and MCP. Data stays on each backend until you export/import yourself.

  • Setup wizard

    Preflight, ports, index sources, compose up, health check, smoke retain/recall. Provider hooks in `providers/*/wizard.mjs` add only backend-specific steps.

  • Compose on loopback

    Hindsight publishes API and control on 127.0.0.1. LiteLLM stays on the Docker network as Hindsight’s model proxy.

  • Multi-source indexer

    Git repos (poll), Obsidian vaults, notes/papers/bookmarks folders, and RSS/OpenAlex feed cache (inotify). Tree-sitter outlines for code. One sink for the active provider.

  • Indexer secret masking

    Home is mounted read-only; generated compose overrides hide common credential paths. Writable storage is a named volume.

  • Smoke test

    Temporary bank retain/recall/delete after health passes. Idempotent reruns report changed=0 when nothing moved.

  • config.toml

    `~/.config/personal-memory/config.toml` for provider and ports. Day-2: up, down, doctor, install-mcp, switch.

  • Unified MCP

    `install-mcp` registers `personal-memory` with stable `memory_*` tools against the active API. Provider-native MCP (`--provider-only`) and NotebookLM MCP are separate servers.

  • Manifest-driven site

    Provider status badges and copy on this site are generated from `providers/*/manifest.json` at build time.

  • NotebookLM (opt-in)Opt-in

    Compose profile syncs into the active provider; optional MCP for list/search. Off until you enable sync.

How a run goes

  1. Pick a provider

    Run the wizard and choose a stack action and a memory provider. Defaults come from your config file.

  2. Configure

    The wizard checks Docker and ports, writes env files with mode 600 outside the repository, and wires the provider.

  3. Start the stack

    It builds the indexer only when its inputs changed, starts Compose, and waits for the health check.

  4. Index

    The indexer reads index.yml, finds repositories and vaults, and writes them to the active provider.

  5. Smoke test

    A retain and recall round trip in a temporary bank confirms the provider answers before you rely on it.

Architecture: indexing, MCP, and how memory updates

Providers

Status and ports come from providers/*/manifest.json at build time. Supported means the manifest says production-ready.

Memory providers with status, self-host story, and native documentation
ProviderIdStatusSelf-hostNative docs
CogneecogneeSupportedDocker Compose services: cognee, indexer. Default host port 8766 (COGNEE_PORT).Self-hosted graph/RAG memory run as a pinned cognee/cognee image (single container, SQLite + LanceDB + Ladybug) on a loopback port in single-user mode (no authentication). Ingestion is asynchronous: the indexer adds documents, then requests cognify once per changed dataset, so a document is searchable only after the graph is built (OpenAI-compatible LLM_API_KEY, or LLM_PROVIDER=ollama with matching ollama embeddings). No coding-agent plugin — agents use the REST API on the loopback port (/docs).docs.cognee.ai
HindsighthindsightSupportedDocker Compose services: litellm, hindsight, indexer. Default host port 8888 (HINDSIGHT_PORT).github.com
mem0mem0SupportedDocker Compose services: indexer. Default host port 18888 (MEM0_PORT).URL-only v1: the operator runs a mem0 REST server and this stack points the shared indexer at it; no mem0 container yet (docker mode is a follow-up). Operator runbook: providers/mem0/OPERATOR.md. Not api.mem0.ai. The API key lives in ~/.config/personal-memory/mem0.env (mode 600), never the stack .env. The wizard.* HTTP fields below are informational: the wizard's smoke hook replaces the generic HTTP smoke (it needs an X-API-Key header), and deletePath is admin-only upstream, so the hook deletes by memory id instead.none listed
GraphitigraphitiPlannedNot wired yet: no compose services declared.Placeholder for Zep Graphiti temporal knowledge graph backend.help.getzep.com
LettalettaPlannedNot wired yet: no compose services declared.Placeholder manifest. Letta (formerly MemGPT) server integration is not wired; track via issues before changing status.docs.letta.com
ZepzepPlannedNot wired yet: no compose services declared.Placeholder manifest. Zep Cloud/self-hosted API integration is not wired; track via issues before changing status.docs.getzep.com

Per-provider details

Works today. Up next.

Shipped features and manifest-driven gaps. No dates.

Works today

  • Interactive and non-interactive wizard: configure, start, stop, --yes, --dry-run
  • Provider manifests drive this site: supported today: Cognee, Hindsight, mem0
  • Hindsight stack through Docker Compose, with a LiteLLM proxy in front of lemond, Ollama, or a custom endpoint
  • mem0 (URL-only) and Cognee (pinned Docker image) compose profiles with provider wizard hooks and indexer sinks
  • Indexer for git repositories and Obsidian vaults, with tree-sitter outlines and secret-path masking
  • Smoke retain and recall, and an idempotent rerun that reports changed=N
  • Declarative config.toml and npx personal-memory tasks: up, down, doctor, install-mcp, switch
  • Unified personal-memory MCP (memory_add/search/recall/forget, PMM export/import) via install-mcp
  • Opt-in NotebookLM sync; install-mcp also registers the NotebookLM MCP when enabled
  • Provider-native MCP (mem0/Cognee) still available with install-mcp --provider-only

Up next

  • PMM import: mem0 duplicate detection; richer Cognee export (full document text)
  • Graphiti: manifest status is planned
  • Letta: manifest status is planned
  • Zep: manifest status is planned
  • Live end-to-end runs against real mem0 and Cognee servers (required before supported)
  • Further npm releases

Install

You need Docker with Compose v2, Node.js 20.12 or newer, and a model server for the provider you pick (for Hindsight: lemond, Ollama, or an OpenAI-compatible endpoint).

With npxPublished

Day-0 and day-2 commands. install-mcp registers the unified memory_* MCP; Hindsight session memory still uses the coding-agent plugin.

npx personal-memory
npx personal-memory up
npx personal-memory install-mcp --yes
npx personal-memory switch mem0 --yes

From sourceWorks today

Clone and use npx . for the same CLI. Add --dry-run first to see what setup would do without writing anything.

git clone https://github.com/bcmyguest/personal-memory.git
cd personal-memory
npm install && npx . setup

Security notes

  • Loopback binds

    The Hindsight API (127.0.0.1:8888) and control plane (127.0.0.1:9999) publish on loopback only. The LiteLLM proxy is on the internal Docker network and is not published.

  • Secret masking in the indexer

    The indexer sees your home directory read-only. A generated compose.override.yaml masks secret paths such as ~/.ssh and ~/.gnupg. Only paths that exist when it is generated are masked, so rerun the generator after adding a secret directory.

  • Secrets stay out of the repository

    Env files live under ~/.config/hindsight with mode 600. LiteLLM routes read keys from environment variables, so route YAML holds no secrets.

  • Nothing leaves the machine unless a provider says so

    Indexed text goes to the provider and the model server you configured. A hosted model route or the NotebookLM sync sends data to those services; a local route does not.

  • This site

    Static pages with self-hosted fonts: no analytics and no third-party requests. The build fails if the output contains home paths, private IPs, host aliases, or secret-style assignments.