# MemPalace — Antigravity hook scripts Lifecycle hooks for the [Antigravity IDE](https://antigravity.google/). This is the third sibling of the Claude Code and Codex integrations (see `hooks/mempal_save_hook.sh` and `.codex-plugin/hooks/`). The overall shape is the same — a Stop event triggers a background save, a startup-time event injects memory into the agent — but the wire format and STDOUT contract are Antigravity-specific (see [STDIN_SHAPE.md](STDIN_SHAPE.md)). ## Quick start From the repo root: ```bash bash hooks/antigravity/install.sh ``` This installs the plugin to `~/.gemini/config/plugins/mempalace/`. Restart Antigravity and the MCP server, skill, and hooks all register automatically. To dry-run first: ```bash bash hooks/antigravity/install.sh --dry-run ``` To uninstall: ```bash bash hooks/antigravity/install.sh --uninstall ``` ## What gets installed ``` ~/.gemini/config/plugins/mempalace/ ├── plugin.json # marker manifest ├── mcp_config.json # registers mempalace-mcp ├── hooks.json # rendered from hooks.json.tmpl ├── README.md ├── skills/ │ └── mempalace/ │ └── SKILL.md └── hooks/ ├── lib/ │ └── common.sh ├── mempal_save_hook_antigravity.sh # Stop event handler └── mempal_wake_hook_antigravity.sh # PreInvocation handler ``` `hooks.json` carries absolute paths to the two hook scripts (resolved from `__PLUGIN_DIR__` at install time). ## What the hooks do ### `mempal_save_hook_antigravity.sh` (Stop event) Fires every time the agent's execution loop terminates. Increments a per-conversation counter; every `MEMPAL_SAVE_INTERVAL` fires (default 15), spawns `mempalace mine --mode convos --wing ` in the background. The hook itself returns `{}` to stdout in under a few milliseconds — the actual mining runs detached and does not block the user. Defers when: - `fullyIdle == false` (background tasks still running) - `terminationReason == "error"` (transcript may be corrupt) - A previous save for this conversation is still running - Any kill switch is set ### `mempal_wake_hook_antigravity.sh` (PreInvocation event, gated) Fires before every model invocation. Gated to `invocationNum == 1` (first invocation of the conversation only) — beyond that we'd be re-injecting on every turn. Calls `mempalace wake-up --wing ` with a 500ms hard timeout and emits the verbatim output as an `ephemeralMessage` so the agent sees relevant memory on its first response without polluting the persistent transcript. Skips when: - `invocationNum != 1` - Already woke this conversation (atomic `mkdir` loop guard) - `mempalace wake-up` exits non-zero, times out, or produces empty output - Any kill switch is set ## Kill switches Any one of these disables both hooks (silent passthrough, exit 0): | Knob | Value | |------------------------------------------|--------------------------------| | `MEMPAL_DISABLE_HOOK` | `1`, `true`, `yes` | | `MEMPALACE_HOOKS_AUTO_SAVE` | `false`, `0`, `no` | | `~/.mempalace/config.json` | `{"hooks": {"auto_save": false}}` | | Removing `~/.mempalace/` entirely | (palace nuke) | ## Workspace-scoped install (advanced) If you want MemPalace to load only inside a specific workspace, manually copy the rendered plugin into your workspace's `.agents/plugins/`: ```bash bash hooks/antigravity/install.sh --install-dir /tmp/render-stage mkdir -p /.agents/plugins/ cp -r /tmp/render-stage /.agents/plugins/mempalace rm -rf /tmp/render-stage ``` The global install at `~/.gemini/config/plugins/mempalace/` is the canonical UX and what we recommend. ## Troubleshooting ### Hooks aren't firing 1. Confirm Antigravity sees the plugin: open the IDE, navigate to the Customizations page; `mempalace` should appear in the global plugins list. 2. Check `~/.mempalace/hook_state/antigravity_hook.log` — every fire logs a line. No log lines = the hook is not being invoked. 3. Verify `mempalace-mcp` is on `$PATH`: `mempalace-mcp --version`. 4. Inspect the rendered `hooks.json` paths point at executable files: `bash -n ~/.gemini/config/plugins/mempalace/hooks/*.sh`. ### Save fires but no mining happens 1. Look for the most recent `[event=stop]` lines in `antigravity_hook.log` — `count` and `interval` should both be visible. Mining only triggers when `count % interval == 0`. 2. Ensure a Python that can import `mempalace` is reachable. The hook runs `"$MEMPAL_PYTHON_BIN" -m mempalace`, where `MEMPAL_PYTHON_BIN` is resolved (in order) from `$MEMPAL_PYTHON`, the `mempalace-mcp` / `mempalace` console-script shebang on `$PATH`, then `python3`. A failed probe logs: ``` ERROR: mempalace is not runnable via -m mempalace; install mempalace or set MEMPAL_PYTHON ``` On a GUI-launched Antigravity the harness `PATH` may differ from your shell `PATH`; if the shebang heuristic can't find the right interpreter, export `MEMPAL_PYTHON=/abs/path/python` (e.g. `"$(uv tool dir)/mempalace/bin/python"`) and restart. ### Wake injection isn't appearing 1. The wake hook only injects on `invocationNum == 1`. Subsequent invocations are gated. 2. The atomic `mkdir` marker `~/.mempalace/hook_state/antigravity_woke_` exists after a successful injection. Remove it to re-inject (rare). 3. `mempalace wake-up --wing ` may be returning empty output if the wing doesn't exist yet. Run `mempalace status` to verify wing presence. ## See also - [INVESTIGATION.md](INVESTIGATION.md) — every Antigravity surface we investigated, with verbatim quotes and source URLs. - [STDIN_SHAPE.md](STDIN_SHAPE.md) — the exact wire format Antigravity uses, with worked examples. - [../mempal_save_hook.sh](../mempal_save_hook.sh) — Claude Code equivalent. - [../../.codex-plugin/hooks/](../../.codex-plugin/hooks/) — Codex equivalent. - [../../website/guide/antigravity.md](../../website/guide/antigravity.md) — full user-facing guide.