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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ me memory search "how does authentication work"
me opencode install
me codex install
me gemini install
me claude install # MCP-only

# Claude Code uses the Memory Engine plugin
# Or, for the full Claude Code plugin (hooks + slash commands + MCP):
claude plugin marketplace add timescale/memory-engine
claude plugin install memory-engine@memory-engine
```
Expand Down
5 changes: 3 additions & 2 deletions docs/agents.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ mcp:
opencode: me opencode install
codex_cli: me codex install
gemini_cli: me gemini install
claude_code: claude plugin marketplace add timescale/memory-engine && claude plugin install memory-engine@memory-engine
description: Memory engine ships as an MCP server. OpenCode, Codex CLI, and Gemini CLI use agent-specific install commands. Claude Code uses the Memory Engine plugin.
claude_code: me claude install
claude_code_plugin: claude plugin marketplace add timescale/memory-engine && claude plugin install memory-engine@memory-engine
description: Memory engine ships as an MCP server. OpenCode, Codex CLI, Gemini CLI, and Claude Code all support MCP-only install via `me <agent> install`. Claude Code additionally supports a full plugin (hooks + slash commands + MCP) via Claude Code's plugin marketplace.
compatible_clients:
- Claude Code
- Codex CLI
Expand Down
33 changes: 32 additions & 1 deletion docs/cli/me-claude.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,40 @@ Claude Code integration commands.

## Commands

- [me claude install](#me-claude-install) -- register `me` as an MCP server with Claude Code (MCP-only)
- [me claude hook](#me-claude-hook) -- invoked by the Claude Code plugin to capture events as memories
- [me claude import](#me-claude-import) -- import Claude Code sessions from `~/.claude/projects`

---

## me claude install

Register `me` as an MCP server with Claude Code.

This is the **MCP-only** install path: it adds the `me` tools to Claude Code without installing the full Memory Engine plugin. If you want hooks (auto-capture of Claude Code events) and slash commands, install the plugin instead -- see [me claude hook](#me-claude-hook).

```
me claude install [options]
```

| Option | Description |
|--------|-------------|
| `--api-key <key>` | API key to embed in the MCP config. |
| `--server <url>` | Server URL to embed in the MCP config. |
| `-s, --scope <scope>` | Claude Code config scope: `local`, `user`, or `project`. Default: `user`. |

If no `--api-key` or `--server` is provided, values are resolved from `~/.config/me/credentials.yaml` (set by `me login` and `me engine use`).

The `--scope` flag mirrors `claude mcp add --scope`:

- `local` -- registration scoped to the current project on this machine only.
- `user` -- registration available to all projects for your user (default).
- `project` -- registration committed to the current project (e.g. checked into `.claude/`).

For manual MCP client configuration, see [MCP Integration](../mcp-integration.md).

---

## me claude hook

Invoked by the Claude Code plugin. Reads the event JSON from stdin, resolves config from `CLAUDE_PLUGIN_OPTION_*` env vars, and captures the event as a memory.
Expand All @@ -21,7 +50,7 @@ me claude hook --event <name>
|--------|-------------|
| `--event <name>` | Hook event name (required). |

This command is not run directly -- the Claude Code plugin calls it. The plugin is installed via Claude Code's native flow:
This command is not run directly -- the Claude Code plugin calls it. The plugin (which includes hooks, slash commands, and MCP) is installed via Claude Code's native flow:

```bash
claude plugin marketplace add timescale/memory-engine
Expand All @@ -30,6 +59,8 @@ claude plugin install memory-engine@memory-engine [--scope user|project|local]
/plugin # select memory-engine, Configure, fill api_key/server/tree_prefix
```

If you only want the MCP tools (no hooks, no slash commands), use [me claude install](#me-claude-install) instead.

Best-effort: logs failures to stderr but always exits 0 so that a hook failure never blocks a Claude Code session.

---
Expand Down
1 change: 1 addition & 0 deletions docs/cli/me-gemini.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ me gemini install [options]
|--------|-------------|
| `--api-key <key>` | API key to embed in the MCP config. |
| `--server <url>` | Server URL to embed in the MCP config. |
| `-s, --scope <scope>` | Gemini CLI config scope: `user` or `project`. Default: `user`. |

If no `--api-key` or `--server` is provided, values are resolved from `~/.config/me/credentials.yaml` (set by `me login` and `me engine use`).

Expand Down
73 changes: 64 additions & 9 deletions packages/cli/commands/claude.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
/**
* me claude — Claude Code integration commands.
*
* Just one subcommand: `me claude hook --event <name>`. The plugin itself
* is installed via Claude Code's native flow:
* Two integration paths:
*
* claude plugin marketplace add timescale/memory-engine
* claude plugin install memory-engine@memory-engine [--scope user|project|local]
* # then, in a Claude Code session:
* /plugin # select memory-engine, Configure, fill api_key/server/tree_prefix
* 1. Full plugin (hooks + slash commands + MCP) via Claude Code's native
* plugin marketplace:
*
* Claude Code delivers the configured values to our hook as
* CLAUDE_PLUGIN_OPTION_* env vars.
* claude plugin marketplace add timescale/memory-engine
* claude plugin install memory-engine@memory-engine [--scope user|project|local]
* # then, in a Claude Code session:
* /plugin # select memory-engine, Configure, fill api_key/server/tree_prefix
*
* Claude Code delivers the configured values to our hook (`me claude
* hook --event <name>`) via CLAUDE_PLUGIN_OPTION_* env vars.
*
* 2. MCP-only via `me claude install`. Registers `me` as an MCP server
* with Claude Code (no hooks, no slash commands — just the tools).
*/
import { Command } from "commander";
import { Command, InvalidArgumentError } from "commander";
import {
captureHookEvent,
HOOK_EVENT_NAMES,
Expand All @@ -21,8 +26,57 @@ import {
resolveHookConfigFromEnv,
} from "../claude/capture.ts";
import { claudeImporter } from "../importers/claude.ts";
import {
type AgentInstallOptions,
runAgentMcpInstall,
} from "../mcp/agent-install.ts";
import { buildAgentImportSubcommand } from "./import.ts";

const CLAUDE_SCOPES = ["local", "user", "project"] as const;
type ClaudeScope = (typeof CLAUDE_SCOPES)[number];

function parseClaudeScope(value: string): ClaudeScope {
if (!CLAUDE_SCOPES.includes(value as ClaudeScope)) {
throw new InvalidArgumentError(
`must be one of: ${CLAUDE_SCOPES.join(", ")}`,
);
}
return value as ClaudeScope;
}

/**
* me claude install — register me as an MCP server with Claude Code.
*
* MCP-only: leaves the full Claude Code plugin install flow alone. Use this
* if you want the `me` MCP tools available in Claude Code but don't want the
* plugin's hooks or slash commands.
*/
function createClaudeInstallCommand(): Command {
return new Command("install")
.description("register me as an MCP server with Claude Code")
.option("--api-key <key>", "API key to embed in MCP config")
.option("--server <url>", "server URL to embed in MCP config")
.option(
"-s, --scope <scope>",
`Claude Code config scope (${CLAUDE_SCOPES.join(", ")})`,
parseClaudeScope,
"user",
)
.action(
async (
opts: AgentInstallOptions & { scope: ClaudeScope },
cmd: Command,
) => {
const globalOpts = cmd.optsWithGlobals();
await runAgentMcpInstall("claude", {
apiKey: opts.apiKey,
server: globalOpts.server ?? opts.server,
scope: opts.scope,
});
},
);
}

/**
* me claude hook — invoked by the Claude Code plugin to capture events as
* memories.
Expand Down Expand Up @@ -101,6 +155,7 @@ function createClaudeHookCommand(): Command {

export function createClaudeCommand(): Command {
const claude = new Command("claude").description("Claude Code integration");
claude.addCommand(createClaudeInstallCommand());
claude.addCommand(createClaudeHookCommand());
claude.addCommand(
buildAgentImportSubcommand(
Expand Down
40 changes: 32 additions & 8 deletions packages/cli/commands/gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,48 @@
*
* - me gemini install: register me as an MCP server with Gemini CLI
*/
import { Command } from "commander";
import { Command, InvalidArgumentError } from "commander";
import {
type AgentInstallOptions,
runAgentMcpInstall,
} from "../mcp/agent-install.ts";

const GEMINI_SCOPES = ["user", "project"] as const;
type GeminiScope = (typeof GEMINI_SCOPES)[number];

function parseGeminiScope(value: string): GeminiScope {
if (!GEMINI_SCOPES.includes(value as GeminiScope)) {
throw new InvalidArgumentError(
`must be one of: ${GEMINI_SCOPES.join(", ")}`,
);
}
return value as GeminiScope;
}

function createGeminiInstallCommand(): Command {
return new Command("install")
.description("register me as an MCP server with Gemini CLI")
.option("--api-key <key>", "API key to embed in MCP config")
.option("--server <url>", "server URL to embed in MCP config")
.action(async (opts: AgentInstallOptions, cmd: Command) => {
const globalOpts = cmd.optsWithGlobals();
await runAgentMcpInstall("gemini", {
apiKey: opts.apiKey,
server: globalOpts.server ?? opts.server,
});
});
.option(
"-s, --scope <scope>",
`Gemini CLI config scope (${GEMINI_SCOPES.join(", ")})`,
parseGeminiScope,
"user",
)
.action(
async (
opts: AgentInstallOptions & { scope: GeminiScope },
cmd: Command,
) => {
const globalOpts = cmd.optsWithGlobals();
await runAgentMcpInstall("gemini", {
apiKey: opts.apiKey,
server: globalOpts.server ?? opts.server,
scope: opts.scope,
});
},
);
}

export function createGeminiCommand(): Command {
Expand Down
7 changes: 6 additions & 1 deletion packages/cli/mcp/agent-install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import { buildMeCommand, installMcpServer, MCP_TOOLS } from "./install.ts";
export interface AgentInstallOptions {
apiKey?: string;
server?: string;
/**
* Configuration scope for tools that support it (Claude Code, Gemini CLI).
* Ignored by tools without a scope concept (Codex, OpenCode).
*/
scope?: string;
}

/**
Expand Down Expand Up @@ -63,7 +68,7 @@ export async function runAgentMcpInstall(

const spin = clack.spinner();
spin.start(`Registering with ${tool.name}...`);
const result = await installMcpServer(tool, meCmd);
const result = await installMcpServer(tool, meCmd, { scope: opts.scope });

if (result.success) {
spin.stop(result.message);
Expand Down
Loading