SDKs

Claude Code plugin

Always-on memory for Claude Code — injects relevant context at every prompt and captures significant work automatically.

Claude Code plugin

The MemHQ plugin gives Claude Code a memory that persists across sessions. It runs entirely through Claude Code's hooks pipeline and does two things:

  • Injects relevant memories at session start and before every prompt, so Claude knows what you decided last week.
  • Captures significant work automatically — commits, deploys, config edits, completed todos — with no /remember command to forget.

The plugin and the MCP server are complementary, not alternatives. The MCP server gives Claude three tools it calls on purpose (memhq_add, memhq_search, memhq_ask). The plugin is the always-on background sync that runs whether or not Claude thinks to reach for a tool. Most people run both.

Install

The plugin is not on the Claude Code marketplace yet, so install it by symlinking the package into your local plugins directory:

mkdir -p ~/.claude/plugins
ln -s /absolute/path/to/memhq/packages/plugin-claude-code ~/.claude/plugins/memhq

Set your project API key in the shell Claude Code launches from — usually your login shell rc, not a project .env:

export MEMHQ_API_KEY="mem_..."

Restart Claude Code. The hooks resolve through ${CLAUDE_PLUGIN_ROOT}, so the symlink works with no further wiring.

Configuration

Everything is environment variables.

VariableDefaultPurpose
MEMHQ_API_KEYrequiredProject API key, starts with mem_.
MEMHQ_API_URLhttps://api.memhq.aiAPI base URL. Point at http://localhost:3000 for local dev.
MEMHQ_USER_ID(see below)Explicit identity override.
MEMHQ_USER_ID_FROM_KEY0Set 1 to derive the identity from the API key.
MEMHQ_ENABLEDtrueSet false to disable every hook without uninstalling.
MEMHQ_SESSION_START_LIMIT10Memories injected at session start.
MEMHQ_PROMPT_SEARCH_LIMIT5Memories injected per prompt.
MEMHQ_MIN_PROMPT_CHARS40Prompts shorter than this skip the search entirely.
MEMHQ_LOG/tmp/memhq-hook.outDebug log path.

MEMHQ_URL is still read as a legacy fallback for MEMHQ_API_URL, but prefer the latter — it matches the variable the SDKs and MCP server use.

Identity

Memories are stored against a user_id, which decides whose graph they land in. The plugin resolves it in this order:

  1. ExplicitMEMHQ_USER_ID=alice, used verbatim. Best when you want one identity across every machine you work on.
  2. Derived from the keyMEMHQ_USER_ID_FROM_KEY=1 computes sha256(MEMHQ_API_KEY)[:16], so identity follows the key rather than the machine.
  3. Per-machine defaultclaude-code-$(hostname -s), matching the MCP server's default.

Pick one and keep it stable. Changing identity mid-stream doesn't lose anything, but new memories land in a different graph than the old ones, so recall quietly gets worse.

What gets captured

HookFiresBehaviour
SessionStartNew sessionSearches for memories matching the project, injects them as markdown.
UserPromptSubmitEvery promptSearches using the prompt as the query, injects up to 5 matches.
PostToolUse (Bash)After a shell commandCaptures git commit/push/merge/rebase/tag, docker compose up/down, kubectl apply, terraform apply, and npm/pnpm/pip publish.
PostToolUse (Edit/Write)After a file editCaptures edits to Dockerfile, docker-compose*, pyproject*, requirements*, CLAUDE.md, .env*, tsconfig*, package.json.
PostToolUse (TodoWrite)After a todo updateCaptures the first 3 newly-completed todos.
PostCompactAfter compactionStores the compaction summary so the context survives being compacted away.
StopSession endsStores the final assistant message.

The capture lists are deliberately narrow. A hook that stored every Bash command would bury the signal — the filter targets actions that change the state of a system, because those are the ones you ask about later.

Failure behaviour

Every hook exits 0 no matter what, and every HTTP call is capped with --max-time 8. A network outage, an expired key, or a MemHQ incident slows a hook down at worst; it can never block or fail your Claude Code session. The cost of that guarantee is that failures are silent, which is what the log is for.

Troubleshooting

The plugin writes one line per HTTP call:

tail -f /tmp/memhq-hook.out

skip /v1/memhq/...: MEMHQ_API_KEY unset — the key isn't visible to the shell Claude Code launched from. Export it in your login shell rc and restart Claude Code; a project-local .env won't be picked up.

HTTP 401 or 403 — the key doesn't match the API URL you're pointing at, most often a local key against production or vice versa.

Nothing injected on a prompt — either the prompt is shorter than MEMHQ_MIN_PROMPT_CHARS (40 by default), or nothing matches yet. Memory compounds; the first few sessions in a project genuinely have nothing to recall.

Requirements

POSIX bash, jq, and curl. No Node, no Python. macOS ships all three; on Linux install jq from your package manager.