mempalace/hooks/antigravity/README.md

173 lines
6.2 KiB
Markdown

# 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 <transcript-dir> --mode convos --wing
<inferred>` 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 <inferred>`
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 <workspace>/.agents/plugins/
cp -r /tmp/render-stage <workspace>/.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 <python> -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_<conversationId>` exists
after a successful injection. Remove it to re-inject (rare).
3. `mempalace wake-up --wing <inferred>` 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.