Files
mempalace-toolkit/AGENTS.md
T
joakimp 16915f0e55 refactor: split pi-generic config into pi-toolkit repo
Parallel to the opencode-toolkit split earlier today. Pi's own config
(keybindings, shell env loader, settings template) moves to a new
sibling repo so opencode-devbox's mempalace opt-out can build slim
containers that include pi without dragging in chromadb + embedding
models (~300 MB).

What moved to pi-toolkit (https://gitea.jordbo.se/joakimp/pi-toolkit):
- extensions/pi/keybindings.json          (mosh/tmux newline fix)
- extensions/pi/pi-env.zsh                (sources ~/.config/pi/.env)
- extensions/pi/settings.example.json     (Bedrock template)
- install.sh::install_pi_keybindings      (symlink step)
- install.sh::install_pi_env_loader       (cp step + bash fallback)
- install.sh::check_pi_settings           (probe)
- install.sh::check_aws_env               (probe)

What stays here (this is the pi\u2194mempalace bridge, mempalace-side):
- extensions/pi/mempalace.ts              (the MCP extension)
- install.sh::install_pi_extension        (symlink step)
- NEW: install.sh::check_pi_toolkit       (probe: warns if pi is
                                           installed but pi-toolkit's
                                           artifacts are missing, with
                                           git-clone pointer)

install.sh shrank from 520 to 403 lines. Uninstall mirror correctly
does NOT touch pi-toolkit-owned files (explicit comment).

Docs updated:
- extensions/pi/README.md: rewritten as 'pi\u2194MemPalace MCP bridge',
  recipe becomes 'Deploying pi with mempalace' (pi-toolkit step 3,
  this repo step 5).
- AGENTS.md: Structure block + 'What install.sh does' section reflect
  the narrower scope and list the four things that moved out.
- README.md: repo-contents line + Setup section's deploy summary.

Verified on tor-ms22: full install\u2192uninstall\u2192reinstall lifecycle clean.
After mempalace-toolkit uninstall, pi-toolkit artifacts
(~/.pi/agent/keybindings.json, ~/.oh-my-zsh/custom/pi-env.zsh) remain
intact \u2014 correctly untouched. check_pi_toolkit probe fires green when
both exist.
2026-05-05 17:26:53 +02:00

10 KiB

AGENTS.md

What this is

Producer-side tooling for MemPalace. Three thin wrappers in bin/ (opencode + pi session feeders, a docs miner), a companion agent skill, and an extensions/ tree with per-harness bridges (currently pi/). Pairs with the consumer-side mempalace skill.

Read ARCHITECTURE.md first — it's the canonical spec for what this repo does and why.

Structure

install.sh              # Idempotent installer — see "What install.sh does" below
ARCHITECTURE.md         # Canonical spec: diagrams, setup recipe, ops notes, upstream roadmap
README.md               # Human-facing quickstart + per-tool usage reference
SKILL.md                # Agent skill (symlinked into ~/.agents/skills/ on install)
bin/
  mempalace-docs        # Docs-only MemPalace miner (bash wrapper)
  mempalace-session     # Opencode session → MemPalace bridge (bash + inline Python)
  mempalace-pi-session  # pi session → MemPalace bridge (bash + inline Python)
contrib/                # systemd / launchd / cron templates for scheduling feeders
extensions/
  pi/                   # pi↔mempalace MCP bridge (bridge-only; pi's own config is in the pi-toolkit repo)
    mempalace.ts        # Symlinked into ~/.pi/agent/extensions/ (MCP <→ pi glue)
    README.md           # Bridge internals, Type.Unsafe gotcha, pi+mempalace deploy recipe

What install.sh does

Idempotent, safe to re-run. Always:

  • Symlinks bin/* into ~/.local/bin/.
  • Creates ~/.agents/skills/opencode-mempalace-bridge/ with a SKILL.md symlink and a .skill-source marker.

Gated on pi being installed (~/.pi/agent/extensions/ exists):

  • Symlinks extensions/pi/mempalace.ts into ~/.pi/agent/extensions/. Backs up any real file in the way.

Probes (never halt, warn + return 0):

  • ~/.local/bin is on $PATH.
  • ~/.config/opencode/instructions/mempalace.md exists (opencode wake-up protocol).
  • mempalace is registered as an MCP server in ~/.config/opencode/opencode.json.
  • If pi is installed: pi-toolkit artifacts (~/.pi/agent/keybindings.json symlink, ~/.oh-my-zsh/custom/pi-env.zsh) exist. Warns with a git clone ssh://...pi-toolkit.git pointer if missing.

All non-destructive: if something is already in place and points into this repo, prints "already linked" and moves on. If a non-symlink real file is in the way, backs it up with a timestamp.

Not handled here any more (split to pi-toolkit on 2026-05-05):

  • keybindings.json symlink into ~/.pi/agent/
  • pi-env.zsh cp into ~/.oh-my-zsh/custom/
  • settings.example.json template + check_pi_settings probe
  • check_aws_env probe

Those are pi-generic concerns. This toolkit installs only the pi↔mempalace MCP bridge on top of whatever pi-toolkit set up.

Conventions

  • Standalone executables in bin/ with #!/usr/bin/env bash shebang, no extension, chmod +x. Must work in non-interactive contexts (agent processes, cron, CI).
  • Thin wrappers only. Neither tool reimplements the mempalace miner. Both follow the stage-to-cache-then-mine idiom: curate input to ~/.cache/…/<wing>/, then delegate to mempalace mine.
  • Idempotent + dry-runnable. Every tool supports --dry-run. Second invocation on unchanged input is a no-op (dedup via source_file path, optionally + mtime).
  • No external Python deps. Stdlib only (sqlite3, json, pathlib). Inline in the bash wrapper via heredoc.
  • Argument parsing: --help/-h first, then mode flags, then positional args.
  • Comment sections use # ── Section Name ────── style (matches sibling cli_utils repo).

Adding a new wrapper

Three wrappers live happily as standalone scripts — no shared helper library yet, because each one's stage-to-cache logic differs enough that the common surface is thin (arg parsing + mempalace mine invocation). A fourth wrapper might tip the balance; re-evaluate then. Until then, copy the pattern from mempalace-session (richest example):

  1. Create bin/<name> with #!/usr/bin/env bash + chmod +x.
  2. Implement --help, --dry-run, --repair flags (repair is opt-in; --no-repair kept as deprecated alias).
  3. Stage to ~/.cache/<name>/<wing>/ with deterministic filenames.
  4. Invoke mempalace mine ... (choose --mode convos if input is chat-like).
  5. Do NOT end with mempalace repair unless --repair was explicitly passed. Repair is a destructive in-place HNSW rebuild and must never run on an unattended schedule.
  6. Update README.md with usage + rationale.
  7. Update install.sh? No — bin/* is auto-linked.
  8. Update ARCHITECTURE.md if the wrapper fills a new architectural gap.
  9. Update SKILL.md if agents should know when to invoke it.

Adding a new harness extension

extensions/<harness>/ is the home for per-agent-harness bridges — code that lives inside an agent runtime (pi, claude-code, kiro, …) and talks to the mempalace MCP server. Currently only extensions/pi/ exists. If you add a second one (e.g. extensions/claude-code/), follow the same shape:

  1. One directory per harness. Never mix harnesses in one dir.
  2. A README.md covering: what it does, harness-specific install path, debug knobs, and any gotchas (e.g. the pi Type.Unsafe schema passthrough).
  3. Symlink what's safe to symlink, template what the harness rewrites. Pi rewrites ~/.pi/agent/settings.json at runtime — shipped as settings.example.json with a cp instruction, not a symlink, to avoid dirtying the repo. Whereas mempalace.ts and keybindings.json are pure config, safe to symlink.
  4. Gate install.sh steps on the harness being present. Detect via a well-known path (pi uses ~/.pi/agent/extensions/). Skip silently on machines without that harness. Never force-install.
  5. Back up real files, never clobber. If a destination exists and isn't our symlink, mv it to <path>.bak.YYYYMMDD-HHMMSS before linking.
  6. Probe, don't halt. Any harness-specific env / config checks use warn + return 0, never exit non-zero. Gate on evidence the user actually opted into the affected path (e.g. AWS probe only fires if settings.json selects amazon-bedrock).
  7. Mirror in --uninstall. Every symlink this repo creates must have a matching removal step guarded by link_if_into_repo.
  8. Update the root README.md — add to the "What this repo contains" list and to Setup with a one-line pointer to the extension's own README.
  9. Update this file's Structure block to list the new extensions/<harness>/ contents.

See extensions/pi/README.md and the install_pi_extension / install_pi_keybindings / check_pi_settings / check_aws_env functions in install.sh for a full worked example.

Testing

Manual only. Integration-shaped:

# Smoke test — does it parse args and list what would happen?
./bin/mempalace-session --help
./bin/mempalace-session --dry-run

# Real test on a single session (safe, deterministic)
./bin/mempalace-session --session ses_<id> --dry-run
./bin/mempalace-session --session ses_<id>     # file into palace
mempalace_search "a phrase from that session"   # verify visibility
./bin/mempalace-session --session ses_<id>     # re-run → should skip

For mempalace-docs, test on a small repo (e.g. this one) first:

./bin/mempalace-docs "$PWD" --dry-run

Gotchas

  • install.sh is idempotent but interactive — use --yes in non-interactive contexts.
  • ~/.local/bin must be on $PATH. The installer warns if not.
  • The companion skill lives at ~/.agents/skills/opencode-mempalace-bridge/SKILL.md and is a symlink into this repo. Editing that file edits SKILL.md here. To propagate to Claude Code / Kiro, run agents-sync from cli_utils.
  • The opencode DB path defaults to ~/.local/share/opencode/opencode.db. Override via $OPENCODE_DB or --db.
  • The mempalace miner skips symlinks (as of v3.3.3 — miner.py line ~828). That's why the wrappers use cp -p / explicit file writes for staging, not symlinks.
  • The convos miner dedups on source_file path only (no mtime check). Staging filenames must be stable per session; deleting a staged JSONL forces a re-mine.
  • The docs miner dedups on source_file path + mtime. That's why staging uses cp -p (preserves mtime).

Colocated skill pattern

This repo owns an agent skill (SKILL.md) that lives alongside the code it documents, rather than in a central skills repo like skillset. The advantages: the skill moves in lockstep with the wrappers it explains, one git clone gets you the full producer-side setup, and retirement (when upstream gaps close) removes skill + code + docs in one commit.

The convention for making this coexist cleanly with sibling tooling:

  1. install.sh creates ~/.agents/skills/<name>/ as a real directory containing a SKILL.md symlink back into this repo. It does not create a dir-symlink, because real dirs are the signal that sibling reconcilers (skillset's deploy-skills.sh, cli_utils's agents-sync.zsh) should leave the dir alone.
  2. install.sh drops a .skill-source marker file at the root of the skill dir:
    # skill-source: mempalace-toolkit
    # repo: <absolute path>
    # url: ssh://git@gitea.jordbo.se:2222/joakimp/mempalace-toolkit.git
    
    This is a breadcrumb for humans and future tooling — it answers "who owns this skill dir?" at a glance. deploy-skills.sh and agents-sync.zsh don't read it today (their existing logic already handles external dirs correctly) but may surface it in status reports later.
  3. install.sh --uninstall removes the marker (only if it still says mempalace-toolkit) and the now-empty skill dir.

If you add a third colocated skill from a new repo, follow the same convention. The marker format is shared; only the repo name changes.

History

Split out from cli_utils on 2026-04-30. The wrappers originated there but the conceptual fit was weak (cli_utils is interactive shell tools; these are agent memory infrastructure). Some older diary entries and KG facts in the palace reference the original paths.