container/skills/mk-memory-setup/SKILL.md
Set up memory-kernel for a NanoClaw agent — persistent memory across sessions. Use when user asks to set up memory, install memory-kernel, add persistent memory, or configure agent memory. Triggers on "setup memory", "memory-kernel", "mk-memory-setup", "add memory", "persistent memory".
npx skillsauth add mainion-ai/memory-kernel mk-memory-setupInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Set up persistent memory for a NanoClaw agent. This creates a file-based memory system (atoms, events, beliefs) that survives across sessions via CLAUDE.md rendering.
Important: This skill runs on the host machine via Claude Code, not inside a container. It configures mounts, databases, and cron jobs that require host-level access.
Principle: When something is broken or missing, fix it. Don't tell the user to go fix it themselves. Ask for permission when needed, then do the work.
UX Note: Use AskUserQuestion for all user-facing questions.
Before anything else, verify the environment. Run each check and report results:
node --version # Need >= 20.0.0
git --version # Need git
sqlite3 --version # Need sqlite3 (for NanoClaw DB config)
docker --version # Need Docker (NanoClaw container runtime)
If any missing:
node: Install via nvm or nodesource. Don't proceed without Node 20+.git: sudo apt install git (Linux) or brew install git (macOS)sqlite3: sudo apt install sqlite3 (Linux) or brew install sqlite3 (macOS)docker: Should already be running if NanoClaw works. Just verify.Optional checks (only if user wants GitHub backup):
gh auth status # GitHub CLI authenticated
Also verify NanoClaw is running:
# Check the NanoClaw process
pgrep -f nanoclaw || systemctl --user status nanoclaw 2>/dev/null || launchctl list | grep nanoclaw 2>/dev/null
If NanoClaw is not running, warn the user. Memory setup can proceed but the agent won't use it until NanoClaw restarts.
Use AskUserQuestion to gather setup details:
Question 1: Memory directory "Where should the memory data be stored?"
~/mk-memory (Recommended) — Simple, top-level~/repos/memory/kernel — If user prefers repos/ structureQuestion 2: Agent name "What is the agent's name? (used in commits, cron IDs, and identity)"
Question 3: Version control "Do you want to back up memory to GitHub?"
If yes to GitHub:
Question 3a: GitHub username "What GitHub username should own the memory repo? (e.g., nano-ai-agent)"
Question 4: Identity description "Describe this agent in 1-2 sentences (becomes the identity atom):"
Question 5: NanoClaw directory "Where is NanoClaw installed? I'll try to auto-detect first."
Run auto-detect:
NANOCLAW_DIR=$(for p in ~/nanoclaw ~/Documents/nanoclaw ~/projects/nanoclaw ~/repos/nanoclaw; do
[ -d "$p" ] && echo "$p" && break
done)
echo "Found: $NANOCLAW_DIR"
If found, confirm with user: "Found NanoClaw at $NANOCLAW_DIR — is this correct?"
If not found or user says no, ask: "Please enter the full path to your NanoClaw directory:" — free text input.
Store as {NANOCLAW_DIR} and use in all subsequent steps.
Store all values for use in subsequent steps.
npm install -g memory-kernel
Verify:
npx mk --version
If the install fails with EACCES, fix npm permissions:
mkdir -p ~/.npm-global && npm config set prefix '~/.npm-global'
export PATH=~/.npm-global/bin:$PATH
npm install -g memory-kernel
mkdir -p {MEMORY_DIR}
cd {MEMORY_DIR}
npx mk init .
This creates:
ENTITIES/ — canonical atom storage (beliefs, facts, decisions, etc.)CONFLICTS/ — merge conflict atomsARCHIVE/ — archived/superseded atomsEVIDENCE/ — supporting evidence filesEPISODES/ — long-form episode notesevents.ndjson — event log (source of truth for event sourcing).memory-index.db — SQLite index (derived, rebuildable)Verify the directory structure:
ls -la {MEMORY_DIR}
If any directories are missing, create them:
mkdir -p {MEMORY_DIR}/{ENTITIES,CONFLICTS,ARCHIVE,EVIDENCE,EPISODES}
Skip this step entirely if user chose "No" for version control.
cd {MEMORY_DIR}
git init
git add -A
git commit -m "Initial memory-kernel setup"
Create GitHub repo and push:
gh repo create {GITHUB_USER}/memory --private --source=. --remote=origin --push
If gh repo create fails with "remote origin already exists":
git remote set-url origin https://github.com/{GITHUB_USER}/memory.git
git push -u origin main
If repo already exists on GitHub:
git remote add origin https://github.com/{GITHUB_USER}/memory.git
git push -u origin main
Verify:
git remote -v
gh repo view {GITHUB_USER}/memory
NanoClaw silently blocks ALL additional container mounts unless an allowlist exists. This is the #1 gotcha in memory-kernel setup.
mkdir -p ~/.config/nanoclaw
Write the allowlist:
cat > ~/.config/nanoclaw/mount-allowlist.json << 'EOF'
{
"allowedRoots": [
{
"path": "{MEMORY_DIR_PARENT}",
"allowReadWrite": true,
"description": "Memory-kernel data"
}
],
"blockedPatterns": [],
"nonMainReadOnly": false
}
EOF
Where {MEMORY_DIR_PARENT} is the parent of the memory directory (e.g., ~ if memory is at ~/mk-memory, or ~/repos if at ~/repos/memory/kernel). Use the expanded absolute path, not ~.
Critical: Without this file, mounts silently fail. No error, no warning — the agent just can't see the memory files.
Locate the NanoClaw database (using {NANOCLAW_DIR} from Step 1):
NANOCLAW_DIR="{NANOCLAW_DIR}"
DB_PATH="$NANOCLAW_DIR/store/messages.db"
# Fallback for older versions
[ ! -f "$DB_PATH" ] && DB_PATH="$NANOCLAW_DIR/data/nanoclaw.db"
echo "DB: $DB_PATH"
Find the registered group:
sqlite3 "$DB_PATH" "SELECT name, folder, container_config FROM registered_groups;"
Update container_config with mount for memory data only. Container paths must be relative — NanoClaw prepends /workspace/extra/:
sqlite3 "$DB_PATH" "UPDATE registered_groups SET container_config = json('{
\"additionalMounts\": [
{
\"hostPath\": \"{MEMORY_DIR_ABSOLUTE}\",
\"containerPath\": \"memory\",
\"readonly\": false
}
]
}') WHERE is_main = 1;"
Important paths inside the container:
/workspace/extra/memory/workspace/group//workspace/group/CLAUDE.mdVerify the update:
sqlite3 "$DB_PATH" "SELECT container_config FROM registered_groups WHERE is_main = 1;"
Link conversation logs from NanoClaw into the memory directory so they're accessible to the kernel:
NANOCLAW_DIR="{NANOCLAW_DIR}"
GROUP_FOLDER=$(sqlite3 "$NANOCLAW_DIR/store/messages.db" "SELECT folder FROM registered_groups WHERE is_main = 1;")
# Conversation logs
ln -sf "$NANOCLAW_DIR/groups/$GROUP_FOLDER/logs" "{MEMORY_DIR}/conversations"
# Impulse queue (for capturing curiosity across sessions)
touch "$NANOCLAW_DIR/groups/$GROUP_FOLDER/impulses.ndjson"
ln -sf "$NANOCLAW_DIR/groups/$GROUP_FOLDER/impulses.ndjson" "{MEMORY_DIR}/impulses.ndjson"
Add identity and preference atoms so the agent knows who it is from the first session:
npx mk remember "{IDENTITY_DESCRIPTION}" \
-d {MEMORY_DIR} -t fact \
--tags identity agent-setup
npx mk remember "Created by {CREATOR_NAME}. Prefers direct communication, values agent autonomy." \
-d {MEMORY_DIR} -t preference \
--tags communication creator
Customize the preference atom based on what you know about the operator's preferences. Add more atoms as needed:
# Example: infrastructure facts
npx mk remember "Running on {hostname}, {OS}, IP {IP}" \
-d {MEMORY_DIR} -t fact \
--tags infrastructure
# Example: GitHub setup
npx mk remember "GitHub account: {GITHUB_USER}. Repos: {GITHUB_USER}/memory (private)" \
-d {MEMORY_DIR} -t fact \
--tags github setup
This is the critical step — render atoms into the CLAUDE.md file that NanoClaw loads at every session start:
NANOCLAW_DIR="{NANOCLAW_DIR}"
GROUP_FOLDER=$(sqlite3 "$NANOCLAW_DIR/store/messages.db" "SELECT folder FROM registered_groups WHERE is_main = 1;")
CLAUDE_MD="$NANOCLAW_DIR/groups/$GROUP_FOLDER/CLAUDE.md"
npx mk render "{MEMORY_DIR}" "$CLAUDE_MD"
Verify:
head -20 "$CLAUDE_MD"
# Should show: # Memory
# > Auto-generated from memory-kernel. X atoms, Y events.
If the render fails:
No atoms found → Check ls {MEMORY_DIR}/ENTITIES/ has .md filesCreate a nightly cron job that runs reflect → render → optionally git push:
With git backup:
NANOCLAW_DIR="{NANOCLAW_DIR}"
GROUP_FOLDER=$(sqlite3 "$NANOCLAW_DIR/store/messages.db" "SELECT folder FROM registered_groups WHERE is_main = 1;")
CLAUDE_MD="$NANOCLAW_DIR/groups/$GROUP_FOLDER/CLAUDE.md"
# Add to crontab (preserving existing entries)
(crontab -l 2>/dev/null; echo "0 23 * * * cd {MEMORY_DIR} && npx mk reflect -d . --agent-id {AGENT_NAME} --session-id nightly-\$(date +\%Y\%m\%d) && npx mk render {MEMORY_DIR} $CLAUDE_MD && git add -A && git commit -m \"nightly sync \$(date +\%Y-\%m-\%d)\" --allow-empty && git push 2>&1 | logger -t memory-sync") | crontab -
Without git (local only):
(crontab -l 2>/dev/null; echo "0 23 * * * cd {MEMORY_DIR} && npx mk reflect -d . --agent-id {AGENT_NAME} --session-id nightly-\$(date +\%Y\%m\%d) && npx mk render {MEMORY_DIR} $CLAUDE_MD 2>&1 | logger -t memory-sync") | crontab -
Verify:
crontab -l | grep memory
Restart so the new mounts and CLAUDE.md take effect:
# Linux (systemd)
systemctl --user restart nanoclaw
# macOS (launchd)
# launchctl kickstart -k gui/$(id -u)/com.nanoclaw
Wait a moment, then verify:
# Linux
systemctl --user status nanoclaw
# macOS
# launchctl list | grep nanoclaw
If using git:
cd {MEMORY_DIR}
git add -A
git commit -m "Memory-kernel setup complete"
git push
Run verification regardless:
npx mk status -d {MEMORY_DIR}
npx mk doctor -d {MEMORY_DIR}
Expected output:
mk status: shows atom counts by type, event countmk doctor: reports no issues (or only warnings)Print a summary of what was set up:
✅ Memory-Kernel Setup Complete
Agent: {AGENT_NAME}
Memory dir: {MEMORY_DIR}
GitHub repo: {GITHUB_USER}/memory (private) [or "Local only"]
CLAUDE.md: {CLAUDE_MD}
Mount allow: ~/.config/nanoclaw/mount-allowlist.json
Cron: Nightly sync at 23:00
Container paths:
/workspace/extra/memory (read-write)
/workspace/group/CLAUDE.md (auto-loaded)
The agent can now use these commands inside the container:
npx mk remember "text" -d /workspace/extra/memory -t fact
npx mk render /workspace/extra/memory /workspace/group/CLAUDE.md
If NanoClaw has drift enabled (DRIFT_ENABLED=true), you can add a cheap pre-filter that skips expensive LLM drift sessions when there's nothing interesting to explore. Add MEMORY_DIR to the NanoClaw .env file:
# In the NanoClaw .env file (NOT the memory directory — this tells NanoClaw where to find it)
MEMORY_DIR={MEMORY_DIR}
When set, NanoClaw runs mk wander --json (~30ms, no LLM) before each drift session. If no high-dissimilarity collisions are found, drift is skipped entirely. If collisions are found (atom pairs with Jaccard tag dissimilarity > 0.7), their context is injected into the drift prompt for directed exploration.
See the drift integration docs for details.
After setup, point the agent to these references:
/mk-doctor — self-diagnostic skill to verify setupOnce set up, the agent can use these commands inside the container (e.g. after a mid-session mk remember):
Primary (requires memory-kernel ≥ 1.1.0 published on npm):
npx mk render /workspace/extra/memory /workspace/group/CLAUDE.md
npx mk renderrequires memory-kernel ≥ 1.1.0 to be published on npm. Until then, use the legacy fallback if your agent has thememory-kernel-codemount.
Legacy fallback (works with mounted source at any version):
npx tsx /workspace/extra/memory-kernel-code/scripts/render-claude-md.ts \
/workspace/extra/memory /workspace/group/CLAUDE.md
If CLI behaviour doesn't match docs: Check npx mk --version against the latest release. Ask your operator to run npm update memory-kernel globally or update the mount source.
Mounts not working (agent can't see /workspace/extra/memory):
cat ~/.config/nanoclaw/mount-allowlist.jsonsqlite3 {DB_PATH} "SELECT container_config FROM registered_groups WHERE is_main = 1;"/). NanoClaw prepends /workspace/extra/.CLAUDE.md empty or not updating:
ls {MEMORY_DIR}/ENTITIES/npx mk render {MEMORY_DIR} {CLAUDE_MD}npm install -g fails with EACCES:
Fix npm prefix: mkdir -p ~/.npm-global && npm config set prefix '~/.npm-global'
Then add export PATH=~/.npm-global/bin:$PATH to your shell profile.
npx mk init -d . fails — The correct syntax is npx mk init . (positional argument, not -d flag).
npx mk retain unknown command — The CLI command is remember, not retain. (retain is the SDK API name.)
npx mk remember too many arguments — Memory dir is the -d flag: npx mk remember "text" -d {DIR} -t {TYPE}
Git push fails — Ensure gh repo create was run, or that the remote exists: git remote -v
Nightly cron not running — Check crontab -l, verify PATH includes node/npx. Add full paths if needed:
0 23 * * * PATH=/usr/local/bin:/usr/bin:$HOME/.nvm/versions/node/v22.*/bin cd {MEMORY_DIR} && ...
Agent uses npx tsx instead of mk (old setup):
If the agent was set up before mk render existed (pre-v1.1.0), update its memory-kernel-code mount and re-render, or just npm install -g memory-kernel on the host and update the cron to use mk render.
tools
Diagnose and fix memory-kernel setup issues for any agent host — NanoClaw, OpenClaw, MCP clients (Claude Desktop / Cursor), or a plain native install. Verifies the universal store (atoms, events, index, lifecycle atoms, semantic health, drift) and then runs host-specific checks (mounts, plugin doctrine, MCP wiring, cron). Use when atoms are missing, CLAUDE.md is empty, recall feels off, the agent doesn't seem to remember anything across sessions, or you want a health check before debugging further. Triggers on "mk doctor", "memory-kernel diagnose", "atoms missing", "CLAUDE.md empty", "memory-kernel broken", "agent memory not working", "mk-memory health", "diagnose mk", "memory-kernel check", "verify memory setup".
tools
Set up memory-kernel — persistent, file-based agent memory — for any host that needs it. Universal core (install CLI, init store, seed identity + lifecycle atoms, schedule reflect) plus host-specific plumbing for NanoClaw container agents (mounts, allowlist, restart), OpenClaw plugin-based agents (plugin install, isolation config, AGENTS.md / MEMORY.md doctrine), or any MCP-capable client (Claude Desktop, Cursor, Continue) that needs an `mk-mcp` server entry. Use when the user asks to "set up memory-kernel", "install mk", "configure agent memory", "add persistent memory to my agent", "wire up memory-kernel for NanoClaw / OpenClaw / Claude Desktop / Cursor", or anything similar where memory-kernel is being introduced to an agent host. Triggers on "mk-memory-setup", "memory-kernel setup", "set up agent memory", "install memory-kernel", "configure mk", "persistent memory across sessions", "add memory to my agent", "memory-kernel for NanoClaw", "memory-kernel for OpenClaw", "memory-kernel MCP server".
testing
Structured typed memory with event-log replay, confidence scoring, temporal decay, type-aware ranking, typed relation edges, and conflict detection. Use for facts, decisions, constraints, beliefs, and open questions — when structure matters more than fuzzy recall.
testing
Diagnose and fix memory-kernel setup issues. Use when memory isn't working, CLAUDE.md is empty, atoms aren't being retained, or you want to verify your memory setup is healthy. Triggers on "check memory", "memory broken", "mk doctor", "memory not working", "diagnose memory", "fix memory".