diff --git a/README.md b/README.md index 6aeec01b..39ae24c9 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,22 @@ Treat Engram as a curated project memory, not a transcript sink. Use this operat **Learned**: Reuse the request id as the idempotency key. ``` +| Agent | One-liner | +| --------------------------- | -------------------------------------------------------------------------------------------- | +| Claude Code | `claude plugin marketplace add Gentleman-Programming/engram && claude plugin install engram` | +| Pi | `engram setup pi` | +| OpenCode | `engram setup opencode` | +| Gemini CLI | `engram setup gemini-cli` | +| Codex | `engram setup codex` | +| Antigravity CLI | `engram setup antigravity-cli` | +| Windsurf | `engram setup windsurf` | +| Qwen Code | `engram setup qwen` | +| Kiro | `engram setup kiro` | +| Cursor | `engram setup cursor` | +| VS Code (Copilot) | `engram setup vscode-copilot` | +| Kilo Code | `engram setup kilocode` | +| Kimi Code | `engram setup kimi` | +| Any other MCP client | See [docs/AGENT-SETUP.md](docs/AGENT-SETUP.md) | Use a short, searchable title and a fitting type with that content. The full [Memory Protocol](DOCS.md#memory-protocol) defines the durable-save rules and session-summary shape. ### Choose MCP tools by intent diff --git a/cmd/engram/main.go b/cmd/engram/main.go index cb51c2fc..2eb7a797 100644 --- a/cmd/engram/main.go +++ b/cmd/engram/main.go @@ -3406,7 +3406,7 @@ Commands: --paths-only Limit pruning to project names containing / or \ setup [agent] Install/setup agent integration (opencode, pi, claude-code, gemini-cli, codex, antigravity-cli, windsurf, qwen, kiro, - cursor, vscode-copilot, kilocode) + cursor, vscode-copilot, kilocode, kimi) sync Export new memories as compressed chunk to .engram/ --import Import new chunks from .engram/ into local DB --status Show sync status diff --git a/cmd/engram/main_test.go b/cmd/engram/main_test.go index bce4735f..9edb65f0 100644 --- a/cmd/engram/main_test.go +++ b/cmd/engram/main_test.go @@ -309,7 +309,7 @@ func TestPrintUsage(t *testing.T) { if !strings.Contains(stdout, "search ") || !strings.Contains(stdout, "[--match all|any]") || !strings.Contains(stdout, "setup [agent]") { t.Fatalf("usage missing expected commands: %q", stdout) } - for _, agent := range []string{"opencode", "pi", "claude-code", "gemini-cli", "codex", "antigravity-cli", "windsurf", "qwen", "kiro", "cursor", "vscode-copilot", "kilocode"} { + for _, agent := range []string{"opencode", "pi", "claude-code", "gemini-cli", "codex", "antigravity-cli", "windsurf", "qwen", "kiro", "cursor", "vscode-copilot", "kilocode", "kimi"} { if !strings.Contains(stdout, agent) { t.Fatalf("usage missing setup agent %q: %q", agent, stdout) } @@ -427,6 +427,11 @@ func TestPrintPostInstall(t *testing.T) { result: &setup.Result{Agent: "kilocode"}, expects: []string{"Restart Kilo Code", "~/.config/kilo/opencode.json"}, }, + { + name: "kimi", + result: &setup.Result{Agent: "kimi"}, + expects: []string{"Restart Kimi Code", "~/.kimi-code/mcp.json", "~/.kimi-code/AGENTS.md"}, + }, { name: "unknown", result: &setup.Result{Agent: "unknown"}, diff --git a/docs/AGENT-SETUP.md b/docs/AGENT-SETUP.md index 1c84f8cb..fd78ad7d 100644 --- a/docs/AGENT-SETUP.md +++ b/docs/AGENT-SETUP.md @@ -28,6 +28,7 @@ Engram works with **any MCP-compatible agent**. Pick your agent below. | Cursor | `engram setup cursor` | [Details](#cursor) | | VS Code Copilot | `engram setup vscode-copilot` | [Details](#vs-code-copilot--claude-code-extension) | | Kilo Code | `engram setup kilocode` | [Details](#kilo-code) | +| Kimi Code | `engram setup kimi` | [Details](#kimi-code) | | Any MCP agent | `engram mcp` (stdio) | [Details](#any-other-mcp-agent) | > **Native setup for all agents above.** `engram setup ` writes the right @@ -723,6 +724,18 @@ Registers the engram server under the OpenCode-style `mcp` object in `~/.config/ --- +## Kimi Code + +**Automated:** + +```bash +engram setup kimi +``` + +Registers `mcpServers.engram` in `~/.kimi-code/mcp.json` and writes the Memory Protocol as a marker block in `~/.kimi-code/AGENTS.md`. Both files live under the Kimi Code data root, so when `KIMI_CODE_HOME` is set the setup honors it and writes there instead. + +--- + ## Any other MCP agent The pattern is always the same — point your agent's MCP config to `engram mcp` via stdio transport. diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index 629c62ed..84098546 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -227,4 +227,5 @@ When using `engram setup`, config files are written to platform-appropriate loca | Cursor | `~/.cursor/mcp.json` + `~/.cursor/rules/engram.mdc` | `%USERPROFILE%\.cursor\...` | | VS Code Copilot | `~/.config/Code/User/mcp.json` + `.../prompts/engram.instructions.md` (macOS: `~/Library/Application Support/Code/User/`) | `%APPDATA%\Code\User\...` | | Kilo Code | `~/.config/kilo/opencode.json` + `~/.config/kilo/AGENTS.md` | `%USERPROFILE%\.config\kilo\...` | +| Kimi Code | `~/.kimi-code/mcp.json` + `~/.kimi-code/AGENTS.md` | `%USERPROFILE%\.kimi-code\...` | | Data directory | `~/.engram/` | `%USERPROFILE%\.engram\` | diff --git a/docs/codebase/integrations.md b/docs/codebase/integrations.md index ba3a4c23..3898c15a 100644 --- a/docs/codebase/integrations.md +++ b/docs/codebase/integrations.md @@ -39,7 +39,7 @@ is either: - **declarative** — just an MCP path + format (`mcpServers` / `servers` / OpenCode's `mcp` object) and instruction surfaces; the generic `injectMCP` / `writeInstruction` driver in `registry.go` does the writes. Antigravity CLI, Windsurf, Qwen, Kiro, - Cursor, VS Code Copilot, and Kilo Code are all declarative. + Cursor, VS Code Copilot, Kilo Code, and Kimi Code are all declarative. Adding a declarative agent is normally just a new entry in `agentAdapters()` plus its path helpers — no new install code path. Agents not in the registry remain diff --git a/internal/setup/agents.go b/internal/setup/agents.go index a035696d..e34ebfa6 100644 --- a/internal/setup/agents.go +++ b/internal/setup/agents.go @@ -160,6 +160,20 @@ func agentAdapters() []agentAdapter { "Verify ~/.config/kilo/AGENTS.md has the Memory Protocol block", }, }, + { + slug: "kimi", + description: "Kimi Code CLI — MCP registration in ~/.kimi-code/mcp.json plus AGENTS.md Memory Protocol", + mcpPath: kimiMCPPath, + mcpFormat: mcpServersObject, + instructions: []instrSurface{ + {path: kimiAgentsPath, style: markerBlock, body: memoryProtocolMarkdown}, + }, + postInstall: []string{ + "Restart Kimi Code so MCP config is reloaded", + "Verify ~/.kimi-code/mcp.json includes mcpServers.engram", + "Verify ~/.kimi-code/AGENTS.md has the Memory Protocol block", + }, + }, } } @@ -291,3 +305,26 @@ func kilocodeConfigPath() string { func kilocodeAgentsPath() string { return filepath.Join(kilocodeConfigDir(), "AGENTS.md") } + +// ─── Kimi Code paths ───────────────────────────────────────────────────────── +// +// Kimi Code keeps all user-level data under KIMI_CODE_HOME (default +// ~/.kimi-code on every platform, including Windows). MCP servers are declared +// in mcp.json (top-level "mcpServers") and global agent instructions in +// AGENTS.md; both live directly under the data root. + +func kimiCodeHome() string { + if dir := os.Getenv("KIMI_CODE_HOME"); dir != "" && filepath.IsAbs(dir) { + return dir + } + home, _ := userHome() + return filepath.Join(home, ".kimi-code") +} + +func kimiMCPPath() string { + return filepath.Join(kimiCodeHome(), "mcp.json") +} + +func kimiAgentsPath() string { + return filepath.Join(kimiCodeHome(), "AGENTS.md") +} diff --git a/internal/setup/registry_test.go b/internal/setup/registry_test.go index 8138cfa4..162ae834 100644 --- a/internal/setup/registry_test.go +++ b/internal/setup/registry_test.go @@ -31,6 +31,7 @@ func declarativeAgents() []declarativeAgent { {"cursor", cursorMCPPath, "mcpServers", mcpServersObject, cursorMemoryProtocolPath, wholeFile}, {"vscode-copilot", vscodeMCPPath, "servers", serversObject, vscodePromptPath, wholeFile}, {"kilocode", kilocodeConfigPath, "mcp", opencodeObject, kilocodeAgentsPath, markerBlock}, + {"kimi", kimiMCPPath, "mcpServers", mcpServersObject, kimiAgentsPath, markerBlock}, } } @@ -44,6 +45,7 @@ func stubRegistryEnv(t *testing.T) string { osExecutable = func() (string, error) { return testEngramBin, nil } t.Setenv("XDG_CONFIG_HOME", "") t.Setenv("APPDATA", "") + t.Setenv("KIMI_CODE_HOME", "") return home } @@ -58,7 +60,7 @@ func TestSupportedAgentsIncludesAllRegistryAgents(t *testing.T) { want := []string{ "opencode", "pi", "claude-code", "gemini-cli", "codex", "antigravity-cli", "windsurf", "qwen", "kiro", "cursor", - "vscode-copilot", "kilocode", + "vscode-copilot", "kilocode", "kimi", } for _, slug := range want { if !got[slug] { @@ -450,4 +452,31 @@ func TestConfigDirsIgnoreRelativeConfigHome(t *testing.T) { t.Errorf("vscodeUserDir with relative APPDATA = %q, want %q", got, want) } }) + + t.Run("relative KIMI_CODE_HOME ignored", func(t *testing.T) { + t.Setenv("KIMI_CODE_HOME", "relative/kimi") + if got, want := kimiCodeHome(), filepath.Join(home, ".kimi-code"); got != want { + t.Errorf("kimiCodeHome with relative KIMI_CODE_HOME = %q, want %q", got, want) + } + }) +} + +// TestKimiCodeHomeHonorsAbsoluteEnv verifies an absolute KIMI_CODE_HOME +// relocates both the MCP config and the AGENTS.md instruction surface. +func TestKimiCodeHomeHonorsAbsoluteEnv(t *testing.T) { + resetSetupSeams(t) + useTestHome(t) + + custom := filepath.Join(t.TempDir(), "kimi-home") + t.Setenv("KIMI_CODE_HOME", custom) + + if got := kimiCodeHome(); got != custom { + t.Errorf("kimiCodeHome = %q, want %q", got, custom) + } + if got, want := kimiMCPPath(), filepath.Join(custom, "mcp.json"); got != want { + t.Errorf("kimiMCPPath = %q, want %q", got, want) + } + if got, want := kimiAgentsPath(), filepath.Join(custom, "AGENTS.md"); got != want { + t.Errorf("kimiAgentsPath = %q, want %q", got, want) + } }