Files
mempalace-toolkit/AGENTS.md
T
joakimp 5d8f523cb3 docs(AGENTS): unstale wrapper count + new 'Adding a new harness extension' section
Two stale lines from the 2-wrapper era (we have three now), plus a
missing convention doc for future harness extensions:

- 'What this is': two wrappers \u2192 three + extensions/ tree
- 'Adding a new wrapper': drop the 'third wrapper triggers helper lib'
  claim since three coexist fine as standalone scripts; keep the
  threshold at four, re-evaluate then.
- New 'Adding a new harness extension' section codifies the extensions/
  pattern so a future claude-code or kiro bridge follows the same shape
  (per-harness dir, symlink-vs-template rules, gated install steps,
  probe-don't-halt, uninstall mirror, README + Structure updates).
2026-05-05 15:29:15 +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 coding-agent bring-up: MCP bridge, keybindings, settings template
    mempalace.ts        # Symlinked into ~/.pi/agent/extensions/ (MCP <→ pi glue)
    keybindings.json    # Symlinked into ~/.pi/agent/ (mosh/tmux newline fix)
    settings.example.json # Template; user copies + edits (pi rewrites settings.json at runtime)
    README.md           # Extension internals, schema-passthrough gotcha, env setup

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.
  • Symlinks extensions/pi/keybindings.json into ~/.pi/agent/. Backs up any real file in the way.
  • settings.example.json is not symlinked — pi rewrites settings.json at runtime, so we'd dirty the repo. Installer warns if settings.json is missing and prints the cp command.

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.
  • ~/.pi/agent/settings.json exists (if pi is installed).
  • AWS_PROFILE/AWS_REGION set, but only if settings.json exists and selects amazon-bedrock. Silent otherwise.

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.

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.