Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,7 @@ The agentmemory entry is the **same MCP server block** across every host that us
| **Hermes Agent** | `~/.hermes/config.yaml` | Use the deeper [memory provider plugin](integrations/hermes/) with `memory.provider: agentmemory`. |
| **Qwen Code** | `~/.qwen/settings.json` | `agentmemory connect qwen` writes the standard `mcpServers` block. Hook payload is field-compatible with Claude Code, so the existing 12-hook scripts work without modification — wire them via the `hooks` section in the same `settings.json`. |
| **Antigravity** (replaces Gemini CLI) | `mcp_config.json` (in Antigravity's User dir) | `agentmemory connect antigravity` writes the standard `mcpServers` block. macOS: `~/Library/Application Support/Antigravity/User/`. Linux: `~/.config/Antigravity/User/`. Use after the 2026-06-18 Gemini CLI sunset. |
| **Antigravity CLI** (`agy`) | `~/.gemini/config/mcp_config.json` | `agentmemory connect antigravity-cli` — the `agy` CLI keeps its own config under `~/.gemini/`, separate from the Antigravity IDE above. Pass `--with-hooks` for native auto-capture via `~/.gemini/config/hooks.json`. |
| **Kiro** | `~/.kiro/settings/mcp.json` | `agentmemory connect kiro` writes the user-level config. Workspace overrides go in `.kiro/settings/mcp.json` next to your code. |
| **Warp** | `~/.warp/.mcp.json` | `agentmemory connect warp` writes the standard `mcpServers` block. Warp also auto-discovers skills from `.claude/skills/` — once the Claude Code plugin is installed the 8 agentmemory skills (`remember`, `recall`, `recap`, `handoff`, `forget`, `commit-context`, `commit-history`, `session-history`) appear natively in Warp's slash-command palette. |
| **Cline (CLI)** | `~/.cline/mcp.json` | `agentmemory connect cline` writes the standard `mcpServers` block. VS Code extension users: paste the same block via Cline Settings → MCP Servers → Edit JSON. |
Expand Down
51 changes: 51 additions & 0 deletions plugin/hooks/hooks.antigravity.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"agentmemory": {
"enabled": true,
"PreInvocation": [
{
"hooks": [
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/antigravity-bridge.mjs\" PreInvocation",
"timeout": 10
}
]
}
],
"PreToolUse": [
{
"matcher": "view_file|view_code_item|read_file|edit_file|replace_file_content|write_to_file|create_file|grep_search|codebase_search|find_by_name|list_dir",
"hooks": [
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/antigravity-bridge.mjs\" PreToolUse",
"timeout": 10
}
]
}
],
"PostToolUse": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/antigravity-bridge.mjs\" PostToolUse",
"timeout": 10
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/antigravity-bridge.mjs\" Stop",
"timeout": 10
}
]
}
]
}
}
124 changes: 124 additions & 0 deletions plugin/scripts/antigravity-bridge.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/usr/bin/env node
import { spawnSync } from "node:child_process";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
//#region src/hooks/antigravity-bridge.ts
const SCRIPTS_DIR = dirname(fileURLToPath(import.meta.url));
const TOOL_NAME_MAP = {
view_file: "read",
view_line_range: "read",
view_code_item: "read",
read_file: "read",
read_url_content: "read",
edit_file: "edit",
replace_file_content: "edit",
propose_code: "edit",
write_to_file: "write",
create_file: "write",
grep_search: "grep",
codebase_search: "grep",
find_by_name: "glob",
list_dir: "glob"
};
const ARG_KEY_MAP = {
AbsolutePath: "file_path",
TargetFile: "file_path",
DirectoryPath: "path",
SearchDirectory: "path",
Pattern: "pattern",
Query: "pattern",
CommandLine: "command"
};
function asObject(value) {
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
}
function firstString(...values) {
for (const v of values) if (typeof v === "string" && v.length > 0) return v;
}
function normalizeToolArgs(args) {
if (!args) return {};
const out = { ...args };
for (const [from, to] of Object.entries(ARG_KEY_MAP)) if (out[to] === void 0 && args[from] !== void 0) out[to] = args[from];
return out;
}
/**
* Translate one Antigravity hook payload into the flat, snake_case shape
* the bundled hooks consume. Unknown fields are passed through so future
* Antigravity additions stay visible to the capture pipeline.
*/
function normalizePayload(event, raw) {
const toolCall = asObject(raw["toolCall"]);
const workspacePaths = Array.isArray(raw["workspacePaths"]) ? raw["workspacePaths"] : [];
const sessionId = firstString(raw["conversationId"], raw["session_id"], raw["sessionId"]) ?? "unknown";
const cwd = firstString(raw["cwd"], workspacePaths[0]) ?? process.cwd();
const out = {
...raw,
session_id: sessionId,
cwd,
hook_event_name: event
};
const transcriptPath = firstString(raw["transcript_path"], raw["transcriptPath"]);
if (transcriptPath) out["transcript_path"] = transcriptPath;
if (toolCall) {
const args = normalizeToolArgs(asObject(toolCall["args"]) ?? asObject(toolCall["toolArgs"]));
const rawName = firstString(toolCall["name"], toolCall["toolName"], args["ToolName"], args["toolName"]);
if (rawName) {
out["tool_name"] = TOOL_NAME_MAP[rawName] ?? rawName;
out["native_tool_name"] = rawName;
}
out["tool_input"] = args;
const result = toolCall["result"] ?? raw["toolResult"] ?? raw["result"];
if (result !== void 0) out["tool_result"] = result;
}
return out;
}
/**
* Map an Antigravity event to the bundled scripts it should drive.
*
* PreInvocation stands in for both SessionStart and UserPromptSubmit: the
* first invocation of a conversation opens the session, every later one is
* a fresh user turn. PostInvocation is deliberately unmapped — PostToolUse
* already captures the work, and firing again would double-record it.
*/
function targetsFor(event, raw) {
switch (event) {
case "PreInvocation": {
const n = raw["invocationNum"];
return typeof n !== "number" || n <= 1 ? ["session-start.mjs", "prompt-submit.mjs"] : ["prompt-submit.mjs"];
}
case "PreToolUse": return ["pre-tool-use.mjs"];
case "PostToolUse": return ["post-tool-use.mjs"];
case "Stop": return ["stop.mjs", "session-end.mjs"];
default: return [];
}
}
async function main() {
const event = process.argv[2];
if (!event) return;
let input = "";
for await (const chunk of process.stdin) input += chunk;
let raw;
try {
raw = JSON.parse(input);
} catch {
return;
}
if (!raw || typeof raw !== "object") return;
const payload = JSON.stringify(normalizePayload(event, raw));
for (const script of targetsFor(event, raw)) spawnSync(process.execPath, [join(SCRIPTS_DIR, script)], {
input: payload,
stdio: [
"pipe",
"ignore",
"ignore"
]
});
}
if (process.argv[1] !== void 0 && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) main().catch(() => {}).finally(() => {
process.stdout.write("{}");
process.exit(0);
});
//#endregion
export { normalizePayload, targetsFor };

//# sourceMappingURL=antigravity-bridge.mjs.map
3 changes: 2 additions & 1 deletion plugin/skills/agentmemory-agents/REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
Generated from `src/cli/connect/index.ts`. Do not edit the block below by hand; run `npm run skills:gen` after adding or removing an adapter.

<!-- AUTOGEN:agents START - generated by scripts/skills/generate.ts, do not edit by hand -->
`agentmemory connect <agent>` wires the memory server into a host agent. 18 adapters:
`agentmemory connect <agent>` wires the memory server into a host agent. 19 adapters:

| Agent | Name | Protocol |
| --- | --- | --- |
| Antigravity | `antigravity` | Using MCP via mcp_config.json. Antigravity replaces Gemini CLI (sunset 2026-06-18). |
| Antigravity CLI (agy) | `antigravity-cli` | Using MCP via ~/.gemini/config/mcp_config.json (the agy CLI, not the Antigravity IDE, that one is `connect antigravity`). The `/mcp` slash command inside agy lists configured servers. Pass --with-hooks to also install the native ~/.gemini/config/hooks.json auto-capture hooks. |
| Claude Code | `claude-code` | Using MCP. Hooks are also available, see https://github.com/rohitg00/agentmemory#claude-code-one-block-paste-it. |
| Cline | `cline` | Using MCP via ~/.cline/mcp.json (CLI). VS Code users: add the same block via Cline Settings → MCP Servers → Edit JSON. |
| Codex CLI | `codex` | Using MCP. Hooks ship via the Codex plugin; on Codex Desktop, also pass --with-hooks to install the global hooks.json workaround for openai/codex#16430. |
Expand Down
2 changes: 1 addition & 1 deletion plugin/skills/agentmemory-rest-api/REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Generated from `src/triggers/api.ts`. Do not edit the block below by hand; run `
<!-- AUTOGEN:rest START - generated by scripts/skills/generate.ts, do not edit by hand -->
The REST API is the primary surface. All paths are under `http://localhost:3111` (override with `--port`). When `AGENTMEMORY_SECRET` is set, send `Authorization: Bearer $AGENTMEMORY_SECRET`; localhost is otherwise open.

118 registered endpoints:
119 registered endpoints:

| Method | Path |
| --- | --- |
Expand Down
100 changes: 100 additions & 0 deletions src/cli/connect/antigravity-cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { existsSync, mkdirSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
import * as p from "@clack/prompts";
import { createJsonMcpAdapter } from "./json-mcp-adapter.js";
import type { ConnectOptions, ConnectResult } from "./types.js";
import {
buildMergedAntigravityHooks,
type AntigravityHookManifest,
} from "./antigravity-hooks.js";
import { findPluginRoot } from "./codex-hooks.js";
import {
backupFile,
logBackup,
logInstalled,
readJsonSafe,
writeJsonAtomic,
} from "./util.js";

// Antigravity ships two products that do NOT share configuration:
//
// • the IDE, wired by `antigravity.ts` via the app-support directory
// (~/Library/Application Support/Antigravity/User/mcp_config.json);
// • the `agy` CLI, wired here, which reads its customizations out of
// ~/.gemini/ — MCP servers from ~/.gemini/config/mcp_config.json and
// hooks from ~/.gemini/config/hooks.json, with per-workspace overrides
// in <repo>/.agents/hooks.json.
//
// Detection keys off ~/.gemini/antigravity-cli/, which only the CLI
// creates — ~/.gemini/ alone would also match a Gemini CLI install.
//
// Unlike Claude Code, Codex and Droid, Antigravity's hooks.json is a map of
// *named* hook bundles and exposes only five events, so `--with-hooks`
// uses the dedicated merge engine in antigravity-hooks.ts and routes every
// event through the bridge in plugin/scripts/antigravity-bridge.mjs.
// Sources: antigravity.google/docs/hooks, antigravity.google/docs/cli/using
const GEMINI_DIR = join(homedir(), ".gemini");
const ANTIGRAVITY_CLI_DIR = join(GEMINI_DIR, "antigravity-cli");
const CUSTOMIZATION_DIR = join(GEMINI_DIR, "config");
const ANTIGRAVITY_CLI_HOOKS = join(CUSTOMIZATION_DIR, "hooks.json");

export const adapter = createJsonMcpAdapter({
name: "antigravity-cli",
displayName: "Antigravity CLI (agy)",
detectDir: ANTIGRAVITY_CLI_DIR,
configPath: join(CUSTOMIZATION_DIR, "mcp_config.json"),
docs: "https://github.com/rohitg00/agentmemory#other-agents",
protocolNote:
"→ Using MCP via ~/.gemini/config/mcp_config.json (the agy CLI, not the Antigravity IDE — that one is `connect antigravity`). The `/mcp` slash command inside agy lists configured servers. Pass --with-hooks to also install the native ~/.gemini/config/hooks.json auto-capture hooks.",
installHooks: installAntigravityCliHooks,
});

/**

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lot of similar comments

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trimmed in 3a095ba. The file header and the per-function block were stating the same things twice — kept one statement of each and dropped the rest. Comment lines: antigravity-cli.ts 26 → 12, antigravity-hooks.ts 65 → 46, antigravity-bridge.ts 70 → 41, which puts them in line with droid.ts.

What I deliberately kept is the agy behaviour I verified against a live 1.0.15 — the two event shapes, the no-quoting rule, the PreToolUse decision contract. That part isn't derivable from the code, and each of those was a real defect here, so a future reader changing the manifest needs the reason. Happy to cut further if you'd rather that lived only in the PR description.

* Merge the bundled `plugin/hooks/hooks.antigravity.json` into
* `~/.gemini/config/hooks.json`. Idempotent in the same way as the Codex
* and Droid installers: re-running replaces only the hook bundle
* agentmemory owns and leaves user-authored bundles alone.
*/
function installAntigravityCliHooks(opts: ConnectOptions): ConnectResult {
let pluginRoot: string;
try {
pluginRoot = findPluginRoot();
} catch (err) {
return {
kind: "skipped",
reason: err instanceof Error ? err.message : String(err),
};
}

const existing = readJsonSafe<AntigravityHookManifest>(ANTIGRAVITY_CLI_HOOKS);
const merged = buildMergedAntigravityHooks(existing, pluginRoot);

if (opts.dryRun) {
p.log.info(
`[dry-run] Would ${existing ? "merge" : "create"} ${ANTIGRAVITY_CLI_HOOKS} with ${Object.keys(merged).length} hook bundle(s)`,
);
return { kind: "installed", mutatedPath: ANTIGRAVITY_CLI_HOOKS };
}

let backupPath: string | undefined;
if (existsSync(ANTIGRAVITY_CLI_HOOKS)) {
backupPath = backupFile(ANTIGRAVITY_CLI_HOOKS, "antigravity-cli-hooks", "json");
logBackup(backupPath);
} else {
mkdirSync(CUSTOMIZATION_DIR, { recursive: true });
}

writeJsonAtomic(ANTIGRAVITY_CLI_HOOKS, merged);

logInstalled("Antigravity CLI hooks", ANTIGRAVITY_CLI_HOOKS);
p.log.info(
"User-scope hooks reference absolute paths under the bundled plugin/ dir. Re-run `agentmemory connect antigravity-cli --with-hooks` after upgrading agentmemory to refresh them.",
);

return {
kind: "installed",
mutatedPath: ANTIGRAVITY_CLI_HOOKS,
...(backupPath !== undefined && { backupPath }),
};
}
Loading
Loading