ai-memory: install persistent memory for agents on Linux

Mascote LinuxPro programando com IA em uma cadeira gamer, entre IDE, terminal Linux e memória persistente

Switching from Claude Code to Codex, OpenCode, Cursor, or Grok mid-task usually costs context: you have to re-explain the architecture, the attempts that failed, and the next step. The ai-memory solves this problem with persistent memory shared between agents. This guide installs the native version on Linux, creates a service systemd --user, enables MCP and hooks in the supported clients and shows where the data is stored. Version 2.0 also made memory more portable and ready for concurrent use.

What ai-memory stores — and what it doesn't store

ai-memory is a long-term memory server for programming agents. Hooks record session events; the server consolidates this material into Markdown pages and allows retrieving context and handoffs via MCP. The source of truth is a file-based wiki .md; SQLite is a derived index. This makes memory inspectable, versionable, and recoverable without depending on an opaque vector database.

The default path requires no API key or LLM calls: capture, text search, and handoff remain available. On the first server run, ai-memory downloads a local model all-MiniLM-L6-v2 for embeddings; it does not need an API key. An LLM is optional for consolidation and recovery features. To disable local embeddings, set embedding_provider = "none" in the configuration. Before enabling hooks, evaluate what can enter the project history. For sensitive areas, use a capture policy and keep the instance on loopback only.

What changed in line 2.x

The announcement of the ai-memory 2.0 helps understand why this is not just a summary manager. The wiki now uses the Open Knowledge Format (OKF): Markdown pages with standardized metadata. In other words, the memory remains readable outside the server — you can inspect it, version it in Git, or take it to another compatible tool.

When migrating a 1.x installation, 2.0 creates and verifies a backup of the data directory before changing the format. Don't discard this backup until you've verified the wiki and queries after the update. Local embeddings continue to be the default path: they don't require an API key or send the memory content to an external provider.

The other practical change is concurrency. Claude Code, Codex, OpenCode and other harnesses can work on the same checkout without sharing a global “current project” pointer. Writes go through a single queue and pages receive versions, so a later update won't silently erase the previous one. In a shared installation, pages can serve the entire team; however, handoffs remain personal and can only be accepted once by the session owner.

This doesn't mean an already open conversation is interrupted to receive a new annotation: it will see it on the next query or in a following session. For teams, keep authentication and HTTPS enabled before exposing the service outside the local machine.

Prerequisites and choosing the installation method

The project offers Linux binaries for x86_64 and aarch64. The recommended alternative by the project itself for native installations is mise use -g github:akitaonrails/ai-memory; below we'll use the release tarball to make version, checksum, binary and hooks explicit.

Don't use cargo install ai-memory: that name already belongs to another crate on crates.io. To build, use the repository workspace; for normal operation, prefer a binary from the release v2.1.1.

command -v curl sha256sum tar systemctl
uname -m
mkdir -p ~/.local/bin ~/.config/ai-memory ~/.local/share/ai-memory

Downloading and verifying the native binary

Always download the file .sha256 published alongside the tarball and abort the installation if the checksum does not match. The block below selects the architecture, uses release v2.1.1 and preserves the hooks that come with the package.

set -euo pipefail

VER=2.1.1
case "$(uname -m)" in
  x86_64)  ARQ=ai-memory-linux-x86_64.tar.gz ;;
  aarch64|arm64) ARQ=ai-memory-linux-aarch64.tar.gz ;;
  *) echo "Arquitetura sem binário publicado: $(uname -m)" >&2; exit 1 ;;
esac

BASE="https://github.com/akitaonrails/ai-memory/releases/download/v${VER}"
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT

curl -fL "$BASE/$ARQ" -o "$TMP/$ARQ"
curl -fL "$BASE/$ARQ.sha256" -o "$TMP/$ARQ.sha256"
(
  cd "$TMP"
  sha256sum -c "$ARQ.sha256"
  mkdir release
  tar -xzf "$ARQ" -C release
)

install -m 0755 "$TMP/release/ai-memory" "$HOME/.local/bin/ai-memory"
install -d "$HOME/.local/share/ai-memory/release-$VER"
cp -a "$TMP/release/hooks" "$HOME/.local/share/ai-memory/release-$VER/"

export PATH="$HOME/.local/bin:$PATH"
ai-memory --version

If ai-memory does not appear in a new terminal, add export PATH="$HOME/.local/bin:$PATH" to the shell initialization file, such as ~/.bashrc or ~/.zshrc.

Initializing the local database

Let's keep the configuration in ~/.config/ai-memory/config.toml and the data in ~/.local/share/ai-memory, the expected default in a Linux user installation.

ai-memory 
  --data-dir "$HOME/.local/share/ai-memory" 
  --config "$HOME/.config/ai-memory/config.toml" 
  init

After first use, the wiki is in ~/.local/share/ai-memory/wiki/, the SQLite index in ~/.local/share/ai-memory/db/memory.sqlite and the local templates in ~/.local/share/ai-memory/models/. The wiki is the source of truth for pages, but sessions, observations, handoffs, and audit also live in the database. For a complete backup, use the ai-memory backup command itself:

mkdir -p "$HOME/backups/ai-memory"
ai-memory backup --to "$HOME/backups/ai-memory/ai-memory-$(date +%Y%m%d-%H%M).tar.gz"

Starting the server with user systemd

The MCP server needs to stay running so CLIs and hooks can talk to it. This user service listens only on 127.0.0.1:49374: do not expose this port to the network.

cat > ~/.config/systemd/user/ai-memory.service <<'UNIT'
[Unit]
Description=ai-memory local MCP and lifecycle server
After=network.target

[Service]
Type=simple
WorkingDirectory=%h
ExecStart=%h/.local/bin/ai-memory --data-dir %h/.local/share/ai-memory --config %h/.config/ai-memory/config.toml serve --transport http --bind 127.0.0.1:49374
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=default.target
UNIT

systemctl --user daemon-reload
systemctl --user enable --now ai-memory.service
systemctl --user status ai-memory.service --no-pager

On a machine that should keep the service running even without a graphical login, enable linger once:

loginctl enable-linger "$USER"

Check the process and logs when something doesn't respond:

systemctl --user is-active ai-memory.service
journalctl --user -u ai-memory.service -n 80 --no-pager
ai-memory status

Using ChatGPT/Codex as the LLM provider

Without a provider, ai-memory continues capturing sessions, searching the wiki, and creating deterministic summaries. An LLM adds richer consolidation, lint, and background improvements. To use the ChatGPT Plus, Pro, or Codex subscription, select openai-oauth: it uses the ChatGPT/Codex backend via OAuth, no need for OPENAI_API_KEY and stores the renewable token in ~/.local/share/ai-memory/auth.json.

For consolidation, an economical model is sufficient. The example sets gpt-5.6-luna with medium: it is the most balanced starting point when sessions involve technical decisions, failed attempts, and next steps. Create a systemd drop-in instead of editing the main unit:

mkdir -p ~/.config/systemd/user/ai-memory.service.d

cat > ~/.config/systemd/user/ai-memory.service.d/llm-openai-oauth.conf <<'EOF'
[Service]
Environment=AI_MEMORY_LLM_PROVIDER=openai-oauth
Environment=AI_MEMORY_LLM_MODEL=gpt-5.6-luna
Environment=AI_MEMORY_LLM_REASONING_EFFORT=medium
Environment=AI_MEMORY_CONSOLIDATE_ON_SESSION_END=true
EOF

systemctl --user daemon-reload

The last parameter schedules LLM consolidation after session shutdown; capture and handoff are not blocked waiting for the model's response. The GPT-5.6 Luna is aimed at high-volume, cost-sensitive workloads and accepts none, low, medium, high, xhigh and max. Therefore, none is a valid configuration — but it's not the only option, nor the best default choice for consolidating technical sessions.

Which effort to choose for ai-memory?

Start with medium if the goal is to preserve decisions, failure causes, and pending items from a session. It tends to produce a more useful consolidation than a simple summary, without increasing cost and latency as much as the higher levels.

Effort When to use in ai-memory
none Very simple extraction or summary, when the lowest latency is the priority.
low Good option to balance speed and quality in routine sessions.
medium Recommended as a starting point for consolidating technical sessions and handoffs.
high Test only for exceptionally complex sessions, if medium is leaving important decisions out.
xhigh and max Rarely needed for automatic consolidation; increase only after evaluating real quality gain.

In other words: use low when you want to prioritize speed; use medium for daily use of projects with code, infrastructure and troubleshooting. Only move up to high if the consolidated handoffs and pages are proven to still be superficial.

OAuth login and testing

Do interactive login as the same user running the service. The command shows a URL and a temporary code: open the URL, log into your ChatGPT/Codex account and enter the code. Do not copy the file auth.json, nor paste tokens into configuration files.

ai-memory auth login openai-oauth

# depois de autorizar no navegador:
systemctl --user restart ai-memory.service
ai-memory auth status
ai-memory llm-test 
  --provider openai-oauth 
  --model gpt-5.6-luna 
  --prompt 'Responda somente: OK'

The test should return OK. If the login expires or is revoked, repeat ai-memory auth login openai-oauth; to switch accounts, run first ai-memory auth logout openai-oauth. Consult the documentation of ai-memory providers for Anthropic, OpenAI via API, Gemini, Copilot, and OpenAI-compatible endpoints.

Registering MCP and hooks in agents

MCP gives the agent tools like memory query and handoff acceptance. Hooks handle lifecycle capture automatically. Both are required for the full experience. The commands below merge ai-memory entries without requiring manual editing of client JSON and TOML files.

Set the extracted hooks directory during installation and run the command pair for each installed client:

export PATH="$HOME/.local/bin:$PATH"
HOOKS_DIR="$HOME/.local/share/ai-memory/release-2.1.1/hooks"

# Claude Code
ai-memory install-mcp --client claude-code --apply
ai-memory install-hooks --agent claude-code --hooks-dir "$HOOKS_DIR" --apply --project-strategy repo-root

# OpenAI Codex
ai-memory install-mcp --client codex --apply
ai-memory install-hooks --agent codex --hooks-dir "$HOOKS_DIR" --apply --project-strategy repo-root

# OpenCode
ai-memory install-mcp --client open-code --apply
ai-memory install-hooks --agent open-code --apply --project-strategy repo-root

# Cursor Agent CLI
ai-memory install-mcp --client cursor --apply
ai-memory install-hooks --agent cursor --hooks-dir "$HOOKS_DIR" --apply --project-strategy repo-root

# Grok Build CLI
ai-memory install-mcp --client grok --apply
ai-memory install-hooks --agent grok --hooks-dir "$HOOKS_DIR" --apply --project-strategy repo-root

Restart clients after merging. In Codex, approve hooks when the client requests confirmation. OpenCode loads hooks as a TypeScript plugin in ~/.config/opencode/plugins/, so it also needs to be restarted. In Grok, the event's stdout SessionStart is not inserted into the context; when resuming work, ask the agent to call memory_handoff_accept. In Codex CLI 0.145.0 or newer, the event SessionEnd delivers the handoff automatically. In older versions — or when this event is not available — the Stop event doesn't end the session: run ai-memory finalize-session --agent codex when finishing an important task.

Scope per repository and privacy rules

Without configuration, the project is identified by the current directory name. The parameter --project-strategy repo-root used above prevents a cd from creating a separate memory for a subdirectory. To declare the scope in the repository itself, create .ai-memory.toml at the root:

workspace = "pessoal"
project = "site-linuxpro"

[briefing]
inject_on_session_start = "true"
max_chars = 4000

[capture]
ignore_paths = ["private/**", "~/.ssh/**"]

The values of workspace and project accept lowercase ASCII letters, digits, period, hyphen and underscore. The section capture avoids logging recognized events from archive tools under the indicated paths; it is not a complete DLP solution for shell commands or content you write yourself in the prompt. For maximum caution, install the hooks in allowlist mode and place the marker only on repositories that should be captured:

ai-memory install-hooks --agent claude-code --hooks-dir "$HOOKS_DIR" --apply --capture-mode allowlist

Querying memory and delivering context

After working normally through the agent, use MCP to request a search about decisions, files, or previous attempts. When ending, finalize the session when necessary; the next agent should accept the pending handoff instead of starting from scratch.

# Útil principalmente após uma sessão do Codex:
ai-memory finalize-session

# Diagnóstico e manutenção local
ai-memory status
ai-memory lint

Inside Claude, Codex, OpenCode, Cursor Agent CLI or Grok, a simple instruction is enough: “search memory for decisions about this project's authentication” or “accept the pending handoff”. The agent uses the registered MCP tools; there's no need to copy the wiki into the conversation.

Remote access: do not expose the raw port

This article's example is local and doesn't use authentication because the bind is loopback-only. To serve another machine, configure bearer token, allowed_hosts and HTTPS through a reverse proxy before changing the bind. Authentication doesn't encrypt traffic. The project maintains an HTTPS proxy guide with examples for Caddy and Cloudflare Tunnel.

Updates and recovery

To update a tarball installation, download the new release, validate the checksum, replace the binary, update the hooks directory, and restart the service. Then, run again install-hooks --apply for each agent. When crossing the border to the 2.x line, let the migration create and verify your backup before touching the data. Don't delete wiki/ neither db/ during this process.

systemctl --user restart ai-memory.service
systemctl --user status ai-memory.service --no-pager

If there's a problem after an update, restore the file generated by ai-memory backup and examine journalctl --user -u ai-memory.service. This backup includes the wiki and the SQLite state needed to also preserve sessions, observations, and handoffs.

Author credit and license

The ai-memory is created and maintained by Fábio Akita, author of the repository akitaonrails/ai-memory. The file LICENSE from the release identifies “Copyright (c) 2026 Fabio Akita” and makes the project available under the MIT license. Thank you to Fábio for making available an open, local, and interoperable alternative for agent memory.

With the local service, MCP and hooks installed, you can switch agents without abandoning the project's technical history. To compare other options, see also the alternatives to Claude-Mem in Go, Rust, and C and the article about persistent memory for agents on Linux.