Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 27 additions & 0 deletions plugins/ai-memory/skills/browser/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
name: browser
description: Use browser automation (screenshots, navigate, interact). Requires browser MCP.
type: skill
status: active
requires:
capabilities: [browser]
permission: read # read | edit | write — only request what the task needs
---

# browser — Browser Automation Skill

## When to use

- Take screenshots of web pages
- Navigate, fill forms, click elements
- Verify visual changes or UI state

## Setup

Ensure browser capability is enabled for your environment. See `.ai/reference/capability-specs.json` or run `ai-memory install --capability browser` when available.

## Usage patterns

- **Failures** → write to `debugging.md` via `commit_memory` with symptom, screenshot path, root cause
- **Screenshots** → reference path in memory entries; include URL and viewport
- **Visual regression** → `search_memory` for known changes; create debugging entry if unexpected
25 changes: 25 additions & 0 deletions plugins/ai-memory/skills/screen-capture/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
name: screen-capture
description: Capture desktop or app window for vision analysis. Platform-dependent (e.g. Peekaboo on macOS).
type: skill
status: active
requires:
capabilities: [screen_capture]
---

# screen-capture — Desktop/App Screenshot Skill

## When to use

- Read another app's screen (e.g. IDE, browser window)
- Capture for vision analysis or handoff
- Save to `.ai/temp/` for cross-tool handoff

## Setup

See `.ai/reference/capability-specs.json` for platform-specific install (e.g. Peekaboo on macOS). Manual fallback: screenshot to `.ai/temp/screen.png`.

## Usage

- Capture → save to `.ai/temp/` → agent reads via file or `get_memory`
- Handoff: write path to `.ai/temp/request-for-*.md` for another agent
27 changes: 14 additions & 13 deletions src/cli/adapters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,7 @@ Only request the permission the task requires.

## Setup

- **Cursor/Claude Code/Windsurf/Cline:** Run \`ai-memory install --capability desktop_automation\`
- **Antigravity:** Add ai-memory-desktop-automation to \`~/.gemini/antigravity/mcp_config.json\` manually. Config: \`{ "command": "uvx", "args": ["--python", "3.13", "computer-control-mcp@latest"] }\`
- **Python 3.14 users:** onnxruntime has no wheels for 3.14 yet. The config pins \`--python 3.13\` so uv uses a compatible version. If you see "No solution found when resolving tool dependencies", ensure uv can access Python 3.13 (\`uv python install 3.13\`).
Run \`ai-memory install --capability desktop_automation\` or see \`.ai/reference/capability-specs.json\` for tool-specific config.

## Usage

Expand Down Expand Up @@ -440,6 +438,8 @@ export interface ToolAdapter {
mcpPath?: string;
/** Additional files to write (path relative to project root → content) */
extraFiles?: Record<string, string>;
/** Message to show after install (tool-specific notes) */
postInstallNote?: string;
}

export const TOOL_ADAPTERS: Record<string, ToolAdapter> = {
Expand All @@ -460,16 +460,16 @@ export const TOOL_ADAPTERS: Record<string, ToolAdapter> = {
...skillStubsForDir(".agents/skills"),
},
},
windsurf: {
dest: ".windsurfrules",
content: BOOTSTRAP_INSTRUCTION,
mcp: true,
},
cline: {
dest: ".clinerules",
content: BOOTSTRAP_INSTRUCTION,
mcp: true,
},
// windsurf: {
// dest: ".windsurfrules",
// content: BOOTSTRAP_INSTRUCTION,
// mcp: true,
// },
// cline: {
// dest: ".clinerules",
// content: BOOTSTRAP_INSTRUCTION,
// mcp: true,
// },
copilot: {
dest: ".github/copilot-instructions.md",
content: `# Copilot Instructions\n\n${BOOTSTRAP_INSTRUCTION}\n\n> Note: GitHub Copilot does not support MCP. Skills must be run by pasting content from \`.ai/skills/\`.\n`,
Expand All @@ -479,6 +479,7 @@ export const TOOL_ADAPTERS: Record<string, ToolAdapter> = {
dest: "CLAUDE.md",
content: `# Claude Code — Project Memory\n\n${BOOTSTRAP_INSTRUCTION}`,
mcp: true,
postInstallNote: "Hooks installed: SessionStart (context injection), PreCompact (state preservation)\n Note: Restart Claude Code for hooks to take effect.",
extraFiles: {
...skillStubsForDir(".claude/skills"),
".claude/hooks/SessionStart.js": SESSION_START_HOOK,
Expand Down
9 changes: 6 additions & 3 deletions src/cli/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ export function getCapabilityManualInstructions(
const ENV_MCP_PATHS: Record<string, string> = {
cursor: ".cursor/mcp.json",
"claude-code": ".mcp.json",
windsurf: ".mcp.json",
cline: ".mcp.json",
// windsurf: ".mcp.json",
// cline: ".mcp.json",
antigravity: ".mcp.json", // Antigravity uses global config; project path unused for injection
};

Expand Down Expand Up @@ -158,12 +158,15 @@ function mcpEntryFromCapConfig(capability: string, config: Record<string, unknow
if (type === "stdio") {
const command = mcp.command as string;
const args = mcp.args as string[] | undefined;
const env = mcp.env as Record<string, string> | undefined;
if (!command) return null;
return {
const entry: Record<string, unknown> = {
type: "stdio",
command,
args: args ?? ["-y", "@anthropic-ai/cursor-ide-browser"],
};
if (env && typeof env === "object") entry.env = env;
return entry;
}
return null;
}
Expand Down
29 changes: 17 additions & 12 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ program
console.log(` Or manually edit .ai/IDENTITY.md and .ai/PROJECT_STATUS.md.`);
console.log(``);
console.log(` Connect your tool: npx @radix-ai/ai-memory install --to <tool>`);
console.log(` Supported tools: cursor, claude-code, antigravity, windsurf, cline, copilot`);
console.log(` Supported tools: cursor, claude-code, antigravity, copilot`);
});

async function scaffoldAiDir(aiDir: string, full: boolean): Promise<void> {
Expand Down Expand Up @@ -208,9 +208,8 @@ program
console.log(`✓ Wrote .ai/skills/${skillName}/SKILL.md (canonical)`);
}

if (tool === "claude-code") {
console.log(`\n Hooks installed: SessionStart (context injection), PreCompact (state preservation)`);
console.log(` Note: Restart Claude Code for hooks to take effect.`);
if (adapter.postInstallNote) {
console.log(`\n ${adapter.postInstallNote}`);
}

if (adapter.mcp) {
Expand Down Expand Up @@ -267,13 +266,20 @@ program
}
}

// Post-install steps from tool-specific config (plugins/adapters/<tool>/INSTALL.md)
const pkgRoot = join(__dirname_cli, "..", "..");
const toolInstallPath = join(pkgRoot, "plugins", "adapters", tool, "INSTALL.md");
const genericInstallPath = join(pkgRoot, "plugins", "adapters", "generic", "INSTALL.md");
const installPath = existsSync(toolInstallPath) ? toolInstallPath : genericInstallPath;
const installContent = existsSync(installPath) ? readFileSync(installPath, "utf-8") : null;

console.log(`\nDone. Before starting:`);
if (tool === "antigravity") {
console.log(` 1. Add ai-memory MCP to ~/.gemini/antigravity/mcp_config.json (Antigravity uses global MCP config)`);
console.log(` 2. Start a new session and verify with: "What does .ai/IDENTITY.md say about this project?"`);
} else if (adapter.mcp) {
console.log(` 1. Enable the ai-memory MCP server in your tool's settings (it's disabled by default)`);
console.log(` 2. Start a new session and verify with: "What does .ai/IDENTITY.md say about this project?"`);
if (installContent) {
const lines = installContent.split("\n").filter((l) => l.trim());
for (const line of lines) {
if (line.startsWith("#")) continue; // Skip headers
console.log(` ${line.trimStart()}`);
}
} else {
console.log(` 1. Start a new session and verify with: "What does .ai/IDENTITY.md say about this project?"`);
}
Expand Down Expand Up @@ -462,7 +468,6 @@ program
.option("--paths <paths>", "Comma-separated paths to check (default: from git diff --name-only)")
.action(async (opts: { dir?: string; paths?: string }) => {
const projectRoot = resolve(opts.dir ?? process.cwd());
const aiDir = join(projectRoot, ".ai");
const { loadDocsSchema, validateDocPlacement } = await import("../docs-schema.js");

const schema = await loadDocsSchema(projectRoot);
Expand Down Expand Up @@ -605,7 +610,7 @@ program
checks.push({ name: "MCP config", status: mcpLocations.length > 0 ? "pass" : "warn", detail: mcpLocations.length > 0 ? mcpLocations.join(", ") : "None found — MCP tools won't be available" });

// 3. Bootstrap installed for at least one tool
const bootstrapMap: Record<string, string> = { "claude-code": "CLAUDE.md", cursor: ".cursor/rules/00-load-ai-memory.mdc", windsurf: ".windsurfrules", cline: ".clinerules", copilot: ".github/copilot-instructions.md" };
const bootstrapMap: Record<string, string> = { "claude-code": "CLAUDE.md", cursor: ".cursor/rules/00-load-ai-memory.mdc", antigravity: ".agents/rules/00-load-ai-memory.md", copilot: ".github/copilot-instructions.md" };
const installed = Object.entries(bootstrapMap).filter(([, p]) => existsSync(join(projectRoot, p))).map(([t]) => t);
checks.push({ name: "Bootstrap", status: installed.length > 0 ? "pass" : "warn", detail: installed.length > 0 ? `Installed for: ${installed.join(", ")}` : "None — run `ai-memory install --to <tool>`" });

Expand Down
2 changes: 1 addition & 1 deletion src/mcp-server/tools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ export function registerTools(server: Server, aiDir: string): void {
inputSchema: {
type: "object",
properties: {
tool_id: { type: "string", description: "Tool ID (cursor, claude-code, antigravity, windsurf, cline)" },
tool_id: { type: "string", description: "Tool ID (cursor, claude-code, antigravity)" },
project_root: { type: "string", description: "Project root (default: parent of .ai/)" },
},
required: ["tool_id"],
Expand Down
24 changes: 12 additions & 12 deletions src/mcp-server/tools/tool-inspect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,18 @@ export const TOOL_PATH_MAPPINGS: Record<
skillsDir: ".agents/skills",
mcpPath: ".mcp.json",
},
windsurf: {
rulesDir: null,
rulesPath: ".windsurfrules",
skillsDir: null,
mcpPath: ".mcp.json",
},
cline: {
rulesDir: null,
rulesPath: ".clinerules",
skillsDir: null,
mcpPath: ".mcp.json",
},
// windsurf: {
// rulesDir: null,
// rulesPath: ".windsurfrules",
// skillsDir: null,
// mcpPath: ".mcp.json",
// },
// cline: {
// rulesDir: null,
// rulesPath: ".clinerules",
// skillsDir: null,
// mcpPath: ".mcp.json",
// },
};

// ─── Internal helpers ─────────────────────────────────────────────────────
Expand Down
28 changes: 28 additions & 0 deletions templates/.ai/reference/capability-specs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"capabilities": {
"browser": {
"description": "Browser automation (screenshots, navigate, interact)",
"environments": {
"cursor": { "native": true },
"claude-code": { "mcp": { "type": "stdio", "command": "npx", "args": ["-y", "@anthropic-ai/cursor-ide-browser"] } },
"antigravity": { "manual": "Add browser MCP to your global mcp_config.json. See docs/reference/antigravity-agent-setup.md." }
}
},
"screen_capture": {
"description": "Desktop/app window screenshot",
"environments": {
"cursor": { "manual": "Platform tools (e.g. Peekaboo on macOS). Fallback: screenshot to .ai/temp/screen.png" },
"claude-code": { "manual": "Platform tools (e.g. Peekaboo on macOS). Fallback: screenshot to .ai/temp/screen.png" },
"antigravity": { "manual": "Platform tools (e.g. Peekaboo on macOS). Fallback: screenshot to .ai/temp/screen.png" }
}
},
"desktop_automation": {
"description": "Desktop UI automation — mouse, keyboard, OCR",
"environments": {
"cursor": { "mcp": { "type": "stdio", "command": "uvx", "args": ["--python", "3.13", "computer-control-mcp@latest"], "env": { "PYTHONIOENCODING": "utf-8" } } },
"claude-code": { "mcp": { "type": "stdio", "command": "uvx", "args": ["--python", "3.13", "computer-control-mcp@latest"], "env": { "PYTHONIOENCODING": "utf-8" } } },
"antigravity": { "manual": "Add ai-memory-desktop-automation to %APPDATA%\\antigravity\\mcp_config.json (Windows) or ~/.antigravity/mcp_config.json (macOS/Linux). Config: { \"command\": \"uvx\", \"args\": [\"--python\", \"3.13\", \"computer-control-mcp@latest\"], \"env\": { \"PYTHONIOENCODING\": \"utf-8\" } }. See docs/reference/antigravity-agent-setup.md." }
}
}
}
}
24 changes: 24 additions & 0 deletions templates/.ai/reference/environment-specs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"environments": [
{
"id": "cursor",
"name": "Cursor",
"detect": { "paths": [".cursor/mcp.json", ".cursor/rules"] }
},
{
"id": "antigravity",
"name": "Antigravity",
"detect": { "paths": [".agents/rules", ".agents/skills"] }
},
{
"id": "claude-code",
"name": "Claude Code",
"detect": { "paths": [".claude/hooks", "CLAUDE.md"] }
},
{
"id": "copilot",
"name": "GitHub Copilot",
"detect": { "paths": [".github/copilot-instructions.md"] }
}
]
}
Loading