add-mnemon
Add persistent graph-based memory via mnemon. Agents recall past context before responding and remember insights after each turn.
Install
npx skills add https://github.com/nanocoai/nanoclaw/tree/main/.claude/skills/add-mnemon
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install nanocoai-nanoclaw@llmmart
git clone https://github.com/nanocoai/nanoclaw.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole nanocoai/nanoclaw collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Add Mnemon — Persistent Memory
Installs mnemon in the agent container image. On each container start, mnemon setup registers Claude Code hooks that surface relevant memory before the agent responds and store new insights after each turn. Memory is written to the per-agent-group .claude/ mount and survives container restarts.
Provider Compatibility
mnemon hooks fire only under --target claude-code. Use this skill on agent groups that run the default Claude provider. The provider is the materialized provider key in each group's container.json (absent or claude = default Claude provider). Confirm it before applying:
grep -H '"provider"' groups/*/container.json 2>/dev/null # no match, or "provider": "claude" = Claude
If a group sets a different provider (e.g. "provider": "opencode"), it spawns its own process and never invokes the claude CLI, so the hooks registered by mnemon setup do not run for that group.
Phase 1: Pre-flight
Check if already applied
grep -q 'MNEMON_VERSION' container/Dockerfile && echo "Already applied" || echo "Not applied"
If already applied, re-run Phase 2 anyway — every step is idempotent and skips work that is already in place — then continue to Phase 3 (Verify).
Check latest mnemon version
curl -fsSL https://api.github.com/repos/mnemon-dev/mnemon/releases/latest | grep '"tag_name"'
Note the version (e.g. v0.1.1) — use it as MNEMON_VERSION in the next step.
Phase 2: Apply Changes
1. Dockerfile — install mnemon binary
Insert the mnemon block immediately above the # ---- Bun runtime section of container/Dockerfile (skip if grep -q 'MNEMON_VERSION' container/Dockerfile already matches):
# ---- mnemon — persistent agent memory ----------------------------------------
ARG MNEMON_VERSION=0.1.1
RUN ARCH=$(dpkg --print-architecture) && \
curl -fsSL "https://github.com/mnemon-dev/mnemon/releases/download/v${MNEMON_VERSION}/mnemon_${MNEMON_VERSION}_linux_${ARCH}.tar.gz" \
| tar -xz -C /usr/local/bin mnemon && \
chmod +x /usr/local/bin/mnemon
ENV MNEMON_DATA_DIR=/home/node/.claude/mnemon
MNEMON_DATA_DIR points into the per-agent-group .claude/ mount, so memory persists across container restarts.
2. Entrypoint — run mnemon setup on each container start
mnemon setup is idempotent. Run it once per container/entrypoint.sh. First check whether the line is already present:
grep -q 'mnemon setup' container/entrypoint.sh && echo "Already wired" || echo "Wire it"
If it prints Wire it, add the setup call right after set -e, before the cat that captures stdin, so the result looks like:
#!/bin/bash
# NanoClaw agent container entrypoint.
#
# ...existing header comment...
set -e
mnemon setup --target claude-code --yes --global >/dev/stderr 2>&1
cat > /tmp/input.json
exec bun run /app/src/index.ts < /tmp/input.json
>/dev/stderr 2>&1 routes all mnemon output to stderr (docker logs) so it doesn't interfere with the JSON stdin handshake between host and agent-runner.
3. Copy the integration tests
Both reach-ins are into container build/runtime files that aren't importable or typed (a GitHub-release binary in the Dockerfile, a shell line in the entrypoint), so structural tests guard them. Copy them into the host test tree:
cp .claude/skills/add-mnemon/mnemon-dockerfile.test.ts src/mnemon-dockerfile.test.ts
cp .claude/skills/add-mnemon/mnemon-entrypoint.test.ts src/mnemon-entrypoint.test.ts
pnpm exec vitest run src/mnemon-dockerfile.test.ts src/mnemon-entrypoint.test.ts
mnemon-dockerfile.test.ts asserts the MNEMON_VERSION ARG and MNEMON_DATA_DIR ENV are present (red if the install layer is dropped on an upgrade). mnemon-entrypoint.test.ts asserts the entrypoint invokes mnemon setup --target claude-code (red if the wiring is removed).
4. Rebuild and smoke-test the image
./container/build.sh
docker run --rm --entrypoint mnemon nanoclaw-agent:latest --version
Phase 3: Restart and Verify
Restart the service
Run from your NanoClaw project root:
source setup/lib/install-slug.sh
systemctl --user restart $(systemd_unit) # Linux
# launchctl kickstart -k gui/$(id -u)/$(launchd_label) # macOS
Confirm mnemon hooks are registered
After the next container starts, check that setup ran:
docker logs $(docker ps --filter label=nanoclaw-session --format "{{.Names}}" | head -1) 2>&1 | grep -i mnemon
Then inspect the hooks inside the running container:
docker exec $(docker ps --filter label=nanoclaw-session --format "{{.Names}}" | head -1) \
cat /home/node/.claude/settings.json | grep -A5 mnemon
Test memory recall
Have a conversation with the agent, then start a new session and reference something from the earlier one. Mnemon should surface the relevant context automatically without you restating it.
Memory Storage
Mnemon writes to /home/node/.claude/mnemon/ inside the container, which maps to the per-agent-group .claude/ directory on the host. To find the exact host path:
docker inspect $(docker ps --filter label=nanoclaw-session --format "{{.Names}}" | head -1) \
--format '{{range .Mounts}}{{if eq .Destination "/home/node/.claude"}}{{.Source}}{{end}}{{end}}'
To reset all memory for an agent, stop the container and delete the mnemon/ subdirectory from that host path.
Troubleshooting
mnemon: command not found in container
The image wasn't rebuilt after adding the Dockerfile layer. Run ./container/build.sh and restart.
Memory not persisting across restarts
Verify MNEMON_DATA_DIR resolves to a mounted path (not an in-container ephemeral directory):
docker exec <container> sh -c 'ls -la $MNEMON_DATA_DIR'
If the directory is empty after conversations, the mount is missing or the path is wrong. Check the host mount with the docker inspect command above.
Agent not using past memory
mnemon setup writes hooks into /home/node/.claude/settings.json. Verify:
docker exec <container> cat /home/node/.claude/settings.json
If the hooks are absent, mnemon setup may have failed silently. Check container startup logs for errors from mnemon.
Setup fails at container start
Run setup manually inside a running container to see the full error:
docker exec -it <container> mnemon setup --target claude-code --yes --global
Files (nanoclaw)
-
mnemon-dockerfile.test.ts 1.2 KB
/** * Structural guard for the mnemon Dockerfile reach-in (the dependency install). * * mnemon ships as a GitHub-release binary, not an npm package, so it can't be * imported or typechecked. The only red-on-drift guard is asserting the install * layer is present in container/Dockerfile: drop the layer on an upgrade and the * container starts with "mnemon: command not found", but nothing else fails. * This test reads the Dockerfile and asserts the MNEMON_VERSION ARG and the * MNEMON_DATA_DIR ENV are both present. */ import fs from 'fs'; import path from 'path'; import { describe, it, expect } from 'vitest'; function dockerfile(): string { // From src/ up to repo root, then into container/. const p = path.resolve(__dirname, '..', 'container', 'Dockerfile'); return fs.readFileSync(p, 'utf8'); } describe('container/Dockerfile installs the mnemon binary', () => { const text = dockerfile(); it('declares the MNEMON_VERSION build arg', () => { expect(text).toMatch(/ARG\s+MNEMON_VERSION/); }); it('downloads the mnemon release binary', () => { expect(text).toContain('mnemon-dev/mnemon/releases/download'); }); it('sets MNEMON_DATA_DIR into the .claude mount', () => { expect(text).toMatch(/ENV\s+MNEMON_DATA_DIR=/); }); }); -
mnemon-entrypoint.test.ts 985 B
/** * Structural guard for the mnemon entrypoint reach-in. * * container/entrypoint.sh runs on every container start; the inserted * `mnemon setup --target claude-code` line is what registers the Claude Code * memory hooks. The entrypoint is a shell script, not an invocable function, so * the guard is structural: assert the setup invocation is present. Drop it on an * upgrade and the hooks silently never register — this test goes red. */ import fs from 'fs'; import path from 'path'; import { describe, it, expect } from 'vitest'; function entrypoint(): string { // From src/ up to repo root, then into container/. const p = path.resolve(__dirname, '..', 'container', 'entrypoint.sh'); return fs.readFileSync(p, 'utf8'); } describe('container/entrypoint.sh runs mnemon setup on start', () => { const text = entrypoint(); it('invokes mnemon setup targeting claude-code', () => { expect(text).toMatch(/mnemon\s+setup\s+--target\s+claude-code/); }); }); -
REMOVE.md 1.9 KB
# Remove Mnemon Every step is idempotent — safe to run even if some steps were never applied. ## 1. Strip the Dockerfile install layer Open `container/Dockerfile` and delete the mnemon block (the `# ---- mnemon` comment, the `ARG MNEMON_VERSION`, the `RUN` that downloads the binary, and the `ENV MNEMON_DATA_DIR` line): ```dockerfile # ---- mnemon — persistent agent memory ---------------------------------------- ARG MNEMON_VERSION=0.1.1 RUN ARCH=$(dpkg --print-architecture) && \ curl -fsSL "https://github.com/mnemon-dev/mnemon/releases/download/v${MNEMON_VERSION}/mnemon_${MNEMON_VERSION}_linux_${ARCH}.tar.gz" \ | tar -xz -C /usr/local/bin mnemon && \ chmod +x /usr/local/bin/mnemon ENV MNEMON_DATA_DIR=/home/node/.claude/mnemon ``` If the block is already gone, skip this step. ## 2. Strip the entrypoint setup line Open `container/entrypoint.sh` and delete the `mnemon setup` line that follows `set -e`: ```bash mnemon setup --target claude-code --yes --global >/dev/stderr 2>&1 ``` If the line is already gone, skip this step. ## 3. Delete the copied test files ```bash rm -f src/mnemon-dockerfile.test.ts src/mnemon-entrypoint.test.ts ``` ## 4. Rebuild and restart ```bash pnpm run build && ./container/build.sh source setup/lib/install-slug.sh # macOS launchctl kickstart -k gui/$(id -u)/$(launchd_label) # Linux systemctl --user restart $(systemd_unit) ``` ## 5. Delete stored memory (optional) Mnemon's graph lives at `/home/node/.claude/mnemon/` in each container, which maps to the per-agent-group `.claude/` directory on the host. To find the host path and clear it: ```bash docker inspect $(docker ps --filter label=nanoclaw-session --format "{{.Names}}" | head -1) \ --format '{{range .Mounts}}{{if eq .Destination "/home/node/.claude"}}{{.Source}}{{end}}{{end}}' ``` Stop the container, then delete the `mnemon/` subdirectory from that path. -
SKILL.md 6.6 KB
--- name: add-mnemon description: Add persistent graph-based memory via mnemon. Agents recall past context before responding and remember insights after each turn. --- # Add Mnemon — Persistent Memory Installs [mnemon](https://github.com/mnemon-dev/mnemon) in the agent container image. On each container start, `mnemon setup` registers Claude Code hooks that surface relevant memory before the agent responds and store new insights after each turn. Memory is written to the per-agent-group `.claude/` mount and survives container restarts. ## Provider Compatibility mnemon hooks fire only under `--target claude-code`. Use this skill on agent groups that run the default Claude provider. The provider is the materialized `provider` key in each group's `container.json` (absent or `claude` = default Claude provider). Confirm it before applying: ```bash grep -H '"provider"' groups/*/container.json 2>/dev/null # no match, or "provider": "claude" = Claude ``` If a group sets a different provider (e.g. `"provider": "opencode"`), it spawns its own process and never invokes the `claude` CLI, so the hooks registered by `mnemon setup` do not run for that group. ## Phase 1: Pre-flight ### Check if already applied ```bash grep -q 'MNEMON_VERSION' container/Dockerfile && echo "Already applied" || echo "Not applied" ``` If already applied, re-run Phase 2 anyway — every step is idempotent and skips work that is already in place — then continue to Phase 3 (Verify). ### Check latest mnemon version ```bash curl -fsSL https://api.github.com/repos/mnemon-dev/mnemon/releases/latest | grep '"tag_name"' ``` Note the version (e.g. `v0.1.1`) — use it as `MNEMON_VERSION` in the next step. ## Phase 2: Apply Changes ### 1. Dockerfile — install mnemon binary Insert the mnemon block immediately above the `# ---- Bun runtime` section of `container/Dockerfile` (skip if `grep -q 'MNEMON_VERSION' container/Dockerfile` already matches): ```dockerfile # ---- mnemon — persistent agent memory ---------------------------------------- ARG MNEMON_VERSION=0.1.1 RUN ARCH=$(dpkg --print-architecture) && \ curl -fsSL "https://github.com/mnemon-dev/mnemon/releases/download/v${MNEMON_VERSION}/mnemon_${MNEMON_VERSION}_linux_${ARCH}.tar.gz" \ | tar -xz -C /usr/local/bin mnemon && \ chmod +x /usr/local/bin/mnemon ENV MNEMON_DATA_DIR=/home/node/.claude/mnemon ``` `MNEMON_DATA_DIR` points into the per-agent-group `.claude/` mount, so memory persists across container restarts. ### 2. Entrypoint — run mnemon setup on each container start `mnemon setup` is idempotent. Run it once per `container/entrypoint.sh`. First check whether the line is already present: ```bash grep -q 'mnemon setup' container/entrypoint.sh && echo "Already wired" || echo "Wire it" ``` If it prints `Wire it`, add the setup call right after `set -e`, before the `cat` that captures stdin, so the result looks like: ```bash #!/bin/bash # NanoClaw agent container entrypoint. # # ...existing header comment... set -e mnemon setup --target claude-code --yes --global >/dev/stderr 2>&1 cat > /tmp/input.json exec bun run /app/src/index.ts < /tmp/input.json ``` `>/dev/stderr 2>&1` routes all mnemon output to stderr (docker logs) so it doesn't interfere with the JSON stdin handshake between host and agent-runner. ### 3. Copy the integration tests Both reach-ins are into container build/runtime files that aren't importable or typed (a GitHub-release binary in the Dockerfile, a shell line in the entrypoint), so structural tests guard them. Copy them into the host test tree: ```bash cp .claude/skills/add-mnemon/mnemon-dockerfile.test.ts src/mnemon-dockerfile.test.ts cp .claude/skills/add-mnemon/mnemon-entrypoint.test.ts src/mnemon-entrypoint.test.ts pnpm exec vitest run src/mnemon-dockerfile.test.ts src/mnemon-entrypoint.test.ts ``` `mnemon-dockerfile.test.ts` asserts the `MNEMON_VERSION` ARG and `MNEMON_DATA_DIR` ENV are present (red if the install layer is dropped on an upgrade). `mnemon-entrypoint.test.ts` asserts the entrypoint invokes `mnemon setup --target claude-code` (red if the wiring is removed). ### 4. Rebuild and smoke-test the image ```bash ./container/build.sh docker run --rm --entrypoint mnemon nanoclaw-agent:latest --version ``` ## Phase 3: Restart and Verify ### Restart the service Run from your NanoClaw project root: ```bash source setup/lib/install-slug.sh systemctl --user restart $(systemd_unit) # Linux # launchctl kickstart -k gui/$(id -u)/$(launchd_label) # macOS ``` ### Confirm mnemon hooks are registered After the next container starts, check that setup ran: ```bash docker logs $(docker ps --filter label=nanoclaw-session --format "{{.Names}}" | head -1) 2>&1 | grep -i mnemon ``` Then inspect the hooks inside the running container: ```bash docker exec $(docker ps --filter label=nanoclaw-session --format "{{.Names}}" | head -1) \ cat /home/node/.claude/settings.json | grep -A5 mnemon ``` ### Test memory recall Have a conversation with the agent, then start a new session and reference something from the earlier one. Mnemon should surface the relevant context automatically without you restating it. ## Memory Storage Mnemon writes to `/home/node/.claude/mnemon/` inside the container, which maps to the per-agent-group `.claude/` directory on the host. To find the exact host path: ```bash docker inspect $(docker ps --filter label=nanoclaw-session --format "{{.Names}}" | head -1) \ --format '{{range .Mounts}}{{if eq .Destination "/home/node/.claude"}}{{.Source}}{{end}}{{end}}' ``` To reset all memory for an agent, stop the container and delete the `mnemon/` subdirectory from that host path. ## Troubleshooting ### `mnemon: command not found` in container The image wasn't rebuilt after adding the Dockerfile layer. Run `./container/build.sh` and restart. ### Memory not persisting across restarts Verify `MNEMON_DATA_DIR` resolves to a mounted path (not an in-container ephemeral directory): ```bash docker exec <container> sh -c 'ls -la $MNEMON_DATA_DIR' ``` If the directory is empty after conversations, the mount is missing or the path is wrong. Check the host mount with the `docker inspect` command above. ### Agent not using past memory `mnemon setup` writes hooks into `/home/node/.claude/settings.json`. Verify: ```bash docker exec <container> cat /home/node/.claude/settings.json ``` If the hooks are absent, `mnemon setup` may have failed silently. Check container startup logs for errors from mnemon. ### Setup fails at container start Run setup manually inside a running container to see the full error: ```bash docker exec -it <container> mnemon setup --target claude-code --yes --global ```
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.