@takara-ai/miru-code 0.4.6 → 0.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,24 +33,44 @@ MCP loads your key from `credentials.json` automatically — no env block needed
33
33
  miru install
34
34
  ```
35
35
 
36
- Interactive — pick your agent and what to enable (MCP, instructions, sub-agent). Restart the IDE when done.
36
+ Interactive TUI — **↑↓** move, **space** toggle, **a** all, **enter** confirm. Pick agents and integrations:
37
+
38
+ | Integration | What it does |
39
+ |-------------|----------------|
40
+ | MCP server | `search` and `find_related` tools in the agent |
41
+ | Instructions | Search policy in `CLAUDE.md` / `AGENTS.md` / `GEMINI.md` |
42
+ | Sub-agent | Dedicated `miru-code` agent file |
43
+ | Cursor rules | Always-on `.cursor/rules/miru-code.mdc` (Cursor only) |
44
+ | Search hooks | Block built-in Grep/Glob and redirect to Miru MCP |
45
+
46
+ Restart the IDE when done.
37
47
 
38
48
  ```bash
39
49
  miru uninstall # remove miru config
40
50
  ```
41
51
 
42
- **Supported:** Cursor · Claude Code · Gemini CLI · Kiro · OpenCode · GitHub Copilot · Codex · VS Code · Visual Studio (Windows)
52
+ **Supported:** Cursor · Claude Code · Gemini CLI · Kiro · OpenCode · GitHub Copilot · Codex · VS Code · Visual Studio (Windows) · Windsurf / Devin Desktop
53
+
54
+ | IDE | MCP | Instructions / rules | Hooks |
55
+ |-----|-----|------------------------|-------|
56
+ | Cursor | `~/.cursor/mcp.json` | `~/.cursor/rules/miru-code.mdc` | `~/.cursor/hooks.json` |
57
+ | Claude Code | `~/.claude.json` | `~/.claude/CLAUDE.md` | `~/.claude/settings.json` |
58
+ | Gemini CLI | `~/.gemini/settings.json` | `~/.gemini/GEMINI.md` | `~/.gemini/settings.json` (`BeforeTool`) |
59
+ | Kiro | `~/.kiro/settings/mcp.json` | `~/.kiro/steering/miru.md` | `~/.kiro/settings/hooks.json` |
60
+ | OpenCode | `~/.config/opencode/opencode.json(c)` | `~/.config/opencode/AGENTS.md` | `~/.config/opencode/plugins/miru-search-guard.ts` |
61
+ | GitHub Copilot | `~/.copilot/mcp-config.json` | — | `~/.copilot/hooks/miru-search.json` |
62
+ | Codex | `~/.codex/config.toml` | `~/.codex/AGENTS.md` | `~/.codex/hooks.json` |
63
+ | VS Code | `…/Code/User/mcp.json` | — | `~/.copilot/hooks/miru-search.json` |
64
+ | Visual Studio | `%USERPROFILE%\.mcp.json` | — | `~/.copilot/hooks/miru-search.json` |
65
+ | Windsurf | — | — | `~/.codeium/windsurf/hooks.json` |
66
+
67
+ Sub-agent files are also written where supported (see `miru install` plan). Windsurf hooks only — no MCP entry yet.
68
+
69
+ ### Search hooks
70
+
71
+ Hooks run `miru hook-guard` before built-in search tools execute. They **block** conceptual Grep/Glob/SemanticSearch and shell `rg`/`grep`/`find`, and tell the agent to use Miru MCP `search` instead. Exact literal lookups (e.g. `REDIS_HOST`, a symbol name) still pass through.
43
72
 
44
- | IDE | Config written by `miru install` |
45
- |-----|----------------------------------|
46
- | Cursor | `~/.cursor/mcp.json` + `~/.cursor/agents/miru-code.md` |
47
- | Claude Code | `~/.claude.json` + `~/.claude/agents/miru-code.md` |
48
- | Gemini CLI | `~/.gemini/settings.json` + `~/.gemini/agents/miru-code.md` |
49
- | Kiro | `~/.kiro/settings/mcp.json` + `~/.kiro/agents/miru-code.md` |
50
- | OpenCode | `~/.config/opencode/opencode.json(c)` + agents dir |
51
- | GitHub Copilot | `~/.copilot/mcp-config.json` + `~/.copilot/agents/miru-code.agent.md` |
52
- | Codex / VS Code | MCP config only |
53
- | Visual Studio | `%USERPROFILE%\.mcp.json` (Windows, Copilot Agent Mode) |
73
+ Hooks are optional at install time but **on by default**. Disable them in the installer if you only want MCP + instructions.
54
74
 
55
75
  **Team sub-agent in a repo** (optional):
56
76
 
@@ -82,7 +102,7 @@ When wired via `miru install`, your agent gets:
82
102
  | `search` | Query by meaning; pass `repo` (project root or `https://` git URL) |
83
103
  | `find_related` | Similar code at a `file_path` + line from a search hit |
84
104
 
85
- Pass the **project root** as `repo` for local projects.
105
+ Pass the **project root** as `repo` for local projects. Prefer these over Grep, Glob, or SemanticSearch when Miru MCP is connected — hooks and instructions enforce that when enabled.
86
106
 
87
107
  ## How it works
88
108
 
@@ -101,6 +121,7 @@ Disk cache: `~/Library/Caches/miru` (macOS), `~/.cache/miru` (Linux). MCP watche
101
121
  | `miru find-related <file> <line> [path]` | Related chunks |
102
122
  | `miru init --agent <id>` | Project-local sub-agent |
103
123
  | `miru clear [path]` | Drop index cache |
124
+ | `miru hook-guard` | PreToolUse hook entrypoint (used by installers; reads JSON stdin) |
104
125
  | `miru` | Start MCP server |
105
126
 
106
127
  ## Library
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takara-ai/miru-code",
3
- "version": "0.4.6",
3
+ "version": "0.4.9",
4
4
  "description": "Miru (見る) — hybrid code search for agents. Bun, TypeScript, Takara embeddings.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,41 +1,29 @@
1
1
  ---
2
2
  name: miru-code
3
- description: Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works, or discovering related code. Prefer over Grep/Glob/Read for any semantic or exploratory question.
3
+ description: Code search via Miru MCP. Use search and find_related for any question about how code works. DO NOT use Grep, Glob, or Read for exploration when Miru MCP is available.
4
4
  tools: Bash, Read
5
5
  ---
6
6
 
7
- Use `miru search` to find code by describing what it does or naming a symbol/identifier, instead of grep:
7
+ When Miru MCP is available, use MCP `search` and `find_related` — not Grep, Glob, or Read-for-exploration.
8
8
 
9
- ```bash
10
- miru search "authentication flow" ./my-project
11
- miru search "save_pretrained" ./my-project
12
- miru search "save model to disk" ./my-project --top-k 10
13
- ```
9
+ | Task | Tool |
10
+ |------|------|
11
+ | How/where/what handles X? | Miru `search` |
12
+ | Similar implementations | Miru `find_related` |
13
+ | Exact literal confirmation | Grep |
14
+ | Edit a located file | Read |
14
15
 
15
- First run builds a disk cache. The MCP server incrementally updates local indexes while it runs; after CLI-only use or large refactors, run `miru clear <path>` to rebuild.
16
+ ### MCP workflow
16
17
 
17
- Use `--content docs` to search documentation and prose, `--content config` for config files (yaml, toml, etc.), or `--content all` to search code, docs, and config:
18
-
19
- ```bash
20
- miru search "deployment guide" ./my-project --content docs
21
- miru search "database host port" ./my-project --content config
22
- miru search "authentication" ./my-project --content all
23
- ```
18
+ 1. Call `search` with `repo` set to the project root.
19
+ 2. Use `find_related` with a hit's `file_path` and `line`.
20
+ 3. Read files only to edit or when chunks lack context.
24
21
 
25
- Use `miru find-related` to discover code similar to a known location (pass `file_path` and `line` from a prior search result):
22
+ ### CLI fallback
26
23
 
27
24
  ```bash
28
- miru find-related src/auth.py 42 ./my-project
25
+ miru search "authentication flow" .
26
+ miru find-related src/auth.ts 42 .
29
27
  ```
30
28
 
31
- `path` defaults to the current directory when omitted; git URLs are accepted.
32
-
33
- If `miru` is not on `$PATH`, use `bunx miru` in its place.
34
-
35
- ### Workflow
36
-
37
- 1. Start with `miru search` to find relevant chunks. The index is built and cached automatically.
38
- 2. Use `--content docs` for documentation, `--content config` for config files, or `--content all` for everything.
39
- 3. Inspect full files only when the returned chunk does not give enough context.
40
- 4. Optionally use `miru find-related` with a promising result's `file_path` and `line` to discover related implementations.
41
- 5. Use grep only when you need exhaustive literal matches or quick confirmation of an exact string.
29
+ If `miru` is not on `$PATH`, use `bunx @takara-ai/miru-code`.
@@ -1,41 +1,15 @@
1
1
  ---
2
2
  name: miru-code
3
- description: Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works, or discovering related code. Prefer over Grep/Glob/Read for any semantic or exploratory question.
4
- tools: Bash, Read
3
+ description: Code search via Miru MCP. Use search and find_related instead of grep_search or codebase_search when Miru is connected.
5
4
  ---
6
5
 
7
- Use `miru search` to find code by describing what it does or naming a symbol/identifier, instead of grep:
6
+ When Miru MCP is available, use `search` and `find_related` instead of `grep_search`, `codebase_search`, or broad file reads.
8
7
 
9
- ```bash
10
- miru search "authentication flow" ./my-project
11
- miru search "save_pretrained" ./my-project
12
- miru search "save model to disk" ./my-project --top-k 10
13
- ```
8
+ | Task | Tool |
9
+ |------|------|
10
+ | How/where/what handles X? | Miru `search` |
11
+ | Similar implementations | Miru `find_related` |
12
+ | Exact literal confirmation | grep_search |
13
+ | Edit a located file | read_file |
14
14
 
15
- First run builds a disk cache. The MCP server incrementally updates local indexes while it runs; after CLI-only use or large refactors, run `miru clear <path>` to rebuild.
16
-
17
- Use `--content docs` to search documentation and prose, `--content config` for config files (yaml, toml, etc.), or `--content all` to search code, docs, and config:
18
-
19
- ```bash
20
- miru search "deployment guide" ./my-project --content docs
21
- miru search "database host port" ./my-project --content config
22
- miru search "authentication" ./my-project --content all
23
- ```
24
-
25
- Use `miru find-related` to discover code similar to a known location (pass `file_path` and `line` from a prior search result):
26
-
27
- ```bash
28
- miru find-related src/auth.py 42 ./my-project
29
- ```
30
-
31
- `path` defaults to the current directory when omitted; git URLs are accepted.
32
-
33
- If `miru` is not on `$PATH`, use `bunx miru` in its place.
34
-
35
- ### Workflow
36
-
37
- 1. Start with `miru search` to find relevant chunks. The index is built and cached automatically.
38
- 2. Use `--content docs` for documentation, `--content config` for config files, or `--content all` for everything.
39
- 3. Inspect full files only when the returned chunk does not give enough context.
40
- 4. Optionally use `miru find-related` with a promising result's `file_path` and `line` to discover related implementations.
41
- 5. Use grep only when you need exhaustive literal matches or quick confirmation of an exact string.
15
+ Pass project root as `repo` on every MCP call.
@@ -1,40 +1,27 @@
1
1
  ---
2
2
  name: miru-code
3
- description: Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works, or discovering related code. Prefer over Bash/Read for any semantic or exploratory question.
3
+ description: Code search via Miru MCP. Use search and find_related for any question about how code works. DO NOT use Grep, Glob, or SemanticSearch when Miru MCP is available.
4
4
  ---
5
5
 
6
- Use `miru search` to find code by describing what it does or naming a symbol/identifier, instead of grep:
6
+ Use Miru MCP tools when connected:
7
7
 
8
- ```bash
9
- miru search "authentication flow" ./my-project
10
- miru search "save_pretrained" ./my-project
11
- miru search "save model to disk" ./my-project --top-k 10
12
- ```
8
+ - `search` — natural-language or code query; always pass project root as `repo`
9
+ - `find_related` — similar chunks after a search hit (`file_path` + `line`)
13
10
 
14
- First run builds a disk cache. The MCP server incrementally updates local indexes while it runs; after CLI-only use or large refactors, run `miru clear <path>` to rebuild.
11
+ Do not use Grep, Glob, SemanticSearch, or Read to explore the codebase when Miru MCP is available.
15
12
 
16
- Use `--content docs` to search documentation and prose, `--content config` for config files (yaml, toml, etc.), or `--content all` to search code, docs, and config:
17
-
18
- ```bash
19
- miru search "deployment guide" ./my-project --content docs
20
- miru search "database host port" ./my-project --content config
21
- miru search "authentication" ./my-project --content all
22
- ```
13
+ | Task | Tool |
14
+ |------|------|
15
+ | How/where/what handles X? | Miru `search` |
16
+ | Similar implementations | Miru `find_related` |
17
+ | Exact literal confirmation | Grep |
18
+ | Edit a located file | Read |
23
19
 
24
- Use `miru find-related` to discover code similar to a known location (pass `file_path` and `line` from a prior search result):
20
+ CLI fallback when MCP is unavailable:
25
21
 
26
22
  ```bash
27
- miru find-related src/auth.py 42 ./my-project
23
+ miru search "authentication flow" .
24
+ miru find-related src/auth.ts 42 .
28
25
  ```
29
26
 
30
- `path` defaults to the current directory when omitted; git URLs are accepted.
31
-
32
- If `miru` is not on `$PATH`, use `bunx miru` in its place.
33
-
34
- ### Workflow
35
-
36
- 1. Start with `miru search` to find relevant chunks. The index is built and cached automatically.
37
- 2. Use `--content docs` for documentation, `--content config` for config files, or `--content all` for everything.
38
- 3. Inspect full files only when the returned chunk does not give enough context.
39
- 4. Optionally use `miru find-related` with a promising result's `file_path` and `line` to discover related implementations.
40
- 5. Use grep only when you need exhaustive literal matches or quick confirmation of an exact string.
27
+ If `miru` is not on `$PATH`, use `bunx @takara-ai/miru-code`.
@@ -1,43 +1,17 @@
1
1
  ---
2
2
  name: miru-code
3
- description: Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works, or discovering related code. Prefer over run_shell_command/read_file for any semantic or exploratory question.
4
- tools:
5
- - run_shell_command
6
- - read_file
3
+ description: Code search via Miru MCP. Use search and find_related instead of grep_search or read_file for exploration.
7
4
  ---
8
5
 
9
- Use `miru search` to find code by describing what it does or naming a symbol/identifier, instead of grep:
6
+ When Miru MCP is available, use `search` and `find_related` instead of `grep_search`, `glob`, or `read_file` for codebase exploration.
10
7
 
11
- ```bash
12
- miru search "authentication flow" ./my-project
13
- miru search "save_pretrained" ./my-project
14
- miru search "save model to disk" ./my-project --top-k 10
15
- ```
8
+ | Task | Tool |
9
+ |------|------|
10
+ | How/where/what handles X? | Miru `search` |
11
+ | Similar implementations | Miru `find_related` |
12
+ | Exact literal confirmation | grep_search |
13
+ | Edit a located file | read_file |
16
14
 
17
- First run builds a disk cache. The MCP server incrementally updates local indexes while it runs; after CLI-only use or large refactors, run `miru clear <path>` to rebuild.
15
+ Pass project root as `repo` on every MCP call.
18
16
 
19
- Use `--content docs` to search documentation and prose, `--content config` for config files (yaml, toml, etc.), or `--content all` to search code, docs, and config:
20
-
21
- ```bash
22
- miru search "deployment guide" ./my-project --content docs
23
- miru search "database host port" ./my-project --content config
24
- miru search "authentication" ./my-project --content all
25
- ```
26
-
27
- Use `miru find-related` to discover code similar to a known location (pass `file_path` and `line` from a prior search result):
28
-
29
- ```bash
30
- miru find-related src/auth.py 42 ./my-project
31
- ```
32
-
33
- `path` defaults to the current directory when omitted; git URLs are accepted.
34
-
35
- If `miru` is not on `$PATH`, use `bunx miru` in its place.
36
-
37
- ### Workflow
38
-
39
- 1. Start with `miru search` to find relevant chunks. The index is built and cached automatically.
40
- 2. Use `--content docs` for documentation, `--content config` for config files, or `--content all` for everything.
41
- 3. Inspect full files only when the returned chunk does not give enough context.
42
- 4. Optionally use `miru find-related` with a promising result's `file_path` and `line` to discover related implementations.
43
- 5. Use grep only when you need exhaustive literal matches or quick confirmation of an exact string.
17
+ CLI fallback: `miru search "query" .` or `bunx @takara-ai/miru-code search "query" .`
@@ -1,43 +1,10 @@
1
1
  ---
2
2
  name: miru-code
3
- description: Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works, or discovering related code. Prefer over shell/read tools for any semantic or exploratory question.
4
- tools:
5
- - shell
6
- - read
3
+ description: Code search via Miru MCP. Use search and find_related for codebase exploration instead of built-in grep or file search.
7
4
  ---
8
5
 
9
- Use `miru search` to find code by describing what it does or naming a symbol/identifier, instead of grep:
6
+ When Miru MCP is available, use `search` and `find_related` before any built-in search or broad file reads.
10
7
 
11
- ```bash
12
- miru search "authentication flow" ./my-project
13
- miru search "save_pretrained" ./my-project
14
- miru search "save model to disk" ./my-project --top-k 10
15
- ```
8
+ Pass project root as `repo`. Use Grep only for exact literal confirmation.
16
9
 
17
- First run builds a disk cache. The MCP server incrementally updates local indexes while it runs; after CLI-only use or large refactors, run `miru clear <path>` to rebuild.
18
-
19
- Use `--content docs` to search documentation and prose, `--content config` for config files (yaml, toml, etc.), or `--content all` to search code, docs, and config:
20
-
21
- ```bash
22
- miru search "deployment guide" ./my-project --content docs
23
- miru search "database host port" ./my-project --content config
24
- miru search "authentication" ./my-project --content all
25
- ```
26
-
27
- Use `miru find-related` to discover code similar to a known location (pass `file_path` and `line` from a prior search result):
28
-
29
- ```bash
30
- miru find-related src/auth.py 42 ./my-project
31
- ```
32
-
33
- `path` defaults to the current directory when omitted; git URLs are accepted.
34
-
35
- If `miru` is not on `$PATH`, use `bunx miru` in its place.
36
-
37
- ### Workflow
38
-
39
- 1. Start with `miru search` to find relevant chunks. The index is built and cached automatically.
40
- 2. Use `--content docs` for documentation, `--content config` for config files, or `--content all` for everything.
41
- 3. Inspect full files only when the returned chunk does not give enough context.
42
- 4. Optionally use `miru find-related` with a promising result's `file_path` and `line` to discover related implementations.
43
- 5. Use grep only when you need exhaustive literal matches or quick confirmation of an exact string.
10
+ CLI fallback: `miru search "query" .`
@@ -1,44 +1,11 @@
1
1
  ---
2
2
  name: miru-code
3
- description: Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works, or discovering related code. Prefer over Bash/Read for any semantic or exploratory question.
3
+ description: Code search via Miru MCP. Use search and find_related instead of grep or glob for exploration.
4
4
  mode: subagent
5
- permission:
6
- bash: allow
7
- read: allow
8
5
  ---
9
6
 
10
- Use `miru search` to find code by describing what it does or naming a symbol/identifier, instead of grep:
7
+ When Miru MCP is available, use `search` and `find_related` instead of grep, glob, or read-for-exploration.
11
8
 
12
- ```bash
13
- miru search "authentication flow" ./my-project
14
- miru search "save_pretrained" ./my-project
15
- miru search "save model to disk" ./my-project --top-k 10
16
- ```
9
+ Pass project root as `repo` on every MCP call.
17
10
 
18
- First run builds a disk cache. The MCP server incrementally updates local indexes while it runs; after CLI-only use or large refactors, run `miru clear <path>` to rebuild.
19
-
20
- Use `--content docs` to search documentation and prose, `--content config` for config files (yaml, toml, etc.), or `--content all` to search code, docs, and config:
21
-
22
- ```bash
23
- miru search "deployment guide" ./my-project --content docs
24
- miru search "database host port" ./my-project --content config
25
- miru search "authentication" ./my-project --content all
26
- ```
27
-
28
- Use `miru find-related` to discover code similar to a known location (pass `file_path` and `line` from a prior search result):
29
-
30
- ```bash
31
- miru find-related src/auth.py 42 ./my-project
32
- ```
33
-
34
- `path` defaults to the current directory when omitted; git URLs are accepted.
35
-
36
- If `miru` is not on `$PATH`, use `bunx miru` in its place.
37
-
38
- ### Workflow
39
-
40
- 1. Start with `miru search` to find relevant chunks. The index is built and cached automatically.
41
- 2. Use `--content docs` for documentation, `--content config` for config files, or `--content all` for everything.
42
- 3. Inspect full files only when the returned chunk does not give enough context.
43
- 4. Optionally use `miru find-related` with a promising result's `file_path` and `line` to discover related implementations.
44
- 5. Use grep only when you need exhaustive literal matches or quick confirmation of an exact string.
11
+ CLI fallback: `miru search "query" .`
package/src/cli.ts CHANGED
@@ -20,6 +20,7 @@ import {
20
20
  printFullHelp,
21
21
  printMainHelp,
22
22
  } from "./help.ts";
23
+ import { runSearchGuardFromStdin } from "./installer/hooks/search-guard.ts";
23
24
  import { runInstaller } from "./installer/installer.ts";
24
25
  import { serveMcp } from "./mcp/serve.ts";
25
26
  import { MiruIndex } from "./miru-index.ts";
@@ -40,6 +41,7 @@ const CLI_COMMANDS = new Set([
40
41
  "uninstall",
41
42
  "setup",
42
43
  "clear",
44
+ "hook-guard",
43
45
  "help",
44
46
  "-h",
45
47
  "--help",
@@ -220,6 +222,10 @@ async function runCli(argv: string[]): Promise<void> {
220
222
  return;
221
223
  }
222
224
 
225
+ if (command === "hook-guard") {
226
+ process.exit(await runSearchGuardFromStdin());
227
+ }
228
+
223
229
  if (command === "install" || command === "uninstall") {
224
230
  await runInstaller(command);
225
231
  return;
@@ -366,6 +372,9 @@ async function runMcpWithCredentials(argv: string[]): Promise<void> {
366
372
  async function main(): Promise<void> {
367
373
  const argv = process.argv.slice(2);
368
374
  const first = argv[0];
375
+ if (first === "hook-guard") {
376
+ process.exit(await runSearchGuardFromStdin());
377
+ }
369
378
  if (first && CLI_COMMANDS.has(first)) {
370
379
  await runCli(argv);
371
380
  return;
@@ -3,6 +3,25 @@ import { readdir } from "node:fs/promises";
3
3
  import { homedir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import type { AgentId } from "../agents.ts";
6
+ import { INSTRUCTIONS_MARKDOWN } from "./search-policy.ts";
7
+
8
+ function copilotHooksPath(home: string): string {
9
+ return join(home, ".copilot", "hooks", "miru-search.json");
10
+ }
11
+
12
+ function kiroHooksPath(home: string): string {
13
+ return join(home, ".kiro", "settings", "hooks.json");
14
+ }
15
+
16
+ function windsurfHooksPath(home: string): string {
17
+ return join(home, ".codeium", "windsurf", "hooks.json");
18
+ }
19
+
20
+ function opencodePluginPath(home: string): string {
21
+ const xdg = process.env.XDG_CONFIG_HOME;
22
+ const base = xdg ? join(xdg, "opencode") : join(home, ".config", "opencode");
23
+ return join(base, "plugins", "miru-search-guard.ts");
24
+ }
6
25
 
7
26
  export type InstallAction =
8
27
  | "created"
@@ -38,38 +57,7 @@ const OPENCODE_SERVER_CONFIG: Record<string, unknown> = {
38
57
  };
39
58
 
40
59
  export const INSTRUCTIONS = `${MIRU_START}
41
- ## Miru Code Search
42
-
43
- A \`miru\` MCP server is available with two tools:
44
- - \`search\` — search the codebase with a natural-language or code query.
45
- - \`find_related\` — find code similar to a specific file and line.
46
-
47
- Always call \`search\` before using Grep, Glob, or Read to explore the codebase. Use Grep/Glob/Read only for exact path lookup, exhaustive literal matches, or when the returned chunk lacks enough context.
48
-
49
- Run \`miru setup\` once to store your API key — the MCP server loads it from \`credentials.json\` automatically.
50
-
51
- Pass \`--content docs\` to search documentation, \`--content config\` for config files, or \`--content all\` for everything.
52
-
53
- For CLI fallback or sub-agents without MCP access:
54
-
55
- \`\`\`bash
56
- miru search "authentication flow" ./my-project
57
- miru search "deployment guide" ./my-project --content docs
58
- miru find-related src/auth.ts 42 ./my-project
59
- miru search "save model to disk" ./my-project --top-k 10
60
- \`\`\`
61
-
62
- First run builds a disk cache. The MCP server updates local indexes while it runs; after CLI-only use or large refactors, run \`miru clear <path>\`.
63
-
64
- If \`miru\` is not on \`$PATH\`, use \`bunx @takara-ai/miru-code\` in its place.
65
-
66
- ### Workflow
67
-
68
- 1. Start with \`search\` (MCP) or \`miru search\` (CLI) to find relevant chunks.
69
- 2. Use \`--content docs\` / \`--content config\` / \`--content all\` when appropriate.
70
- 3. Inspect full files only when the chunk is not enough.
71
- 4. Optionally use \`find_related\` with a hit's \`file_path\` and \`line\`.
72
- 5. Use Grep only for exhaustive literal matches.
60
+ ${INSTRUCTIONS_MARKDOWN}
73
61
  ${MIRU_END}
74
62
  `;
75
63
 
@@ -83,13 +71,25 @@ export interface McpConfig {
83
71
  format: McpConfigFormat;
84
72
  }
85
73
 
74
+ export type HooksFormat =
75
+ | "claude"
76
+ | "cursor"
77
+ | "gemini"
78
+ | "vscode"
79
+ | "kiro"
80
+ | "windsurf"
81
+ | "opencode";
82
+
86
83
  export interface AgentTarget {
87
- id: AgentId | "codex" | "vscode" | "visualstudio";
84
+ id: AgentId | "codex" | "vscode" | "visualstudio" | "windsurf";
88
85
  displayName: string;
89
86
  binary: string | null;
90
87
  configDir: string | null;
91
88
  mcp: McpConfig | null;
92
89
  instructionsPath: string | null;
90
+ cursorRulesPath: string | null;
91
+ hooksPath: string | null;
92
+ hooksFormat: HooksFormat | null;
93
93
  subagentPath: string | null;
94
94
  subagentId: AgentId | null;
95
95
  }
@@ -171,6 +171,9 @@ export const AGENT_TARGETS: AgentTarget[] = [
171
171
  configDir: join(HOME, ".claude"),
172
172
  mcp: jsonMcp(join(HOME, ".claude.json"), "mcpServers", STDIO_SERVER_CONFIG),
173
173
  instructionsPath: join(HOME, ".claude", "CLAUDE.md"),
174
+ cursorRulesPath: null,
175
+ hooksPath: join(HOME, ".claude", "settings.json"),
176
+ hooksFormat: "claude",
174
177
  subagentPath: join(HOME, ".claude", "agents", "miru-code.md"),
175
178
  subagentId: "claude",
176
179
  },
@@ -181,6 +184,9 @@ export const AGENT_TARGETS: AgentTarget[] = [
181
184
  configDir: join(HOME, ".cursor"),
182
185
  mcp: jsonMcp(join(HOME, ".cursor", "mcp.json"), "mcpServers", STDIO_SERVER_CONFIG),
183
186
  instructionsPath: null,
187
+ cursorRulesPath: join(HOME, ".cursor", "rules", "miru-code.mdc"),
188
+ hooksPath: join(HOME, ".cursor", "hooks.json"),
189
+ hooksFormat: "cursor",
184
190
  subagentPath: join(HOME, ".cursor", "agents", "miru-code.md"),
185
191
  subagentId: "cursor",
186
192
  },
@@ -191,6 +197,9 @@ export const AGENT_TARGETS: AgentTarget[] = [
191
197
  configDir: join(HOME, ".gemini"),
192
198
  mcp: jsonMcp(join(HOME, ".gemini", "settings.json"), "mcpServers", STDIO_SERVER_CONFIG),
193
199
  instructionsPath: join(HOME, ".gemini", "GEMINI.md"),
200
+ cursorRulesPath: null,
201
+ hooksPath: join(HOME, ".gemini", "settings.json"),
202
+ hooksFormat: "gemini",
194
203
  subagentPath: join(HOME, ".gemini", "agents", "miru-code.md"),
195
204
  subagentId: "gemini",
196
205
  },
@@ -206,6 +215,9 @@ export const AGENT_TARGETS: AgentTarget[] = [
206
215
  },
207
216
  }),
208
217
  instructionsPath: join(HOME, ".kiro", "steering", "miru.md"),
218
+ cursorRulesPath: null,
219
+ hooksPath: kiroHooksPath(HOME),
220
+ hooksFormat: "kiro",
209
221
  subagentPath: join(HOME, ".kiro", "agents", "miru-code.md"),
210
222
  subagentId: "kiro",
211
223
  },
@@ -216,6 +228,9 @@ export const AGENT_TARGETS: AgentTarget[] = [
216
228
  configDir: join(HOME, ".config", "opencode"),
217
229
  mcp: jsonMcp(opencodeMcpPath(), "mcp", OPENCODE_SERVER_CONFIG),
218
230
  instructionsPath: join(HOME, ".config", "opencode", "AGENTS.md"),
231
+ cursorRulesPath: null,
232
+ hooksPath: opencodePluginPath(HOME),
233
+ hooksFormat: "opencode",
219
234
  subagentPath: join(HOME, ".config", "opencode", "agents", "miru-code.md"),
220
235
  subagentId: "opencode",
221
236
  },
@@ -226,6 +241,9 @@ export const AGENT_TARGETS: AgentTarget[] = [
226
241
  configDir: join(HOME, ".config", "github-copilot"),
227
242
  mcp: jsonMcp(join(HOME, ".copilot", "mcp-config.json"), "mcpServers", BARE_STDIO_SERVER_CONFIG),
228
243
  instructionsPath: null,
244
+ cursorRulesPath: null,
245
+ hooksPath: copilotHooksPath(HOME),
246
+ hooksFormat: "vscode",
229
247
  subagentPath: join(HOME, ".copilot", "agents", "miru-code.agent.md"),
230
248
  subagentId: "copilot",
231
249
  },
@@ -242,6 +260,9 @@ export const AGENT_TARGETS: AgentTarget[] = [
242
260
  format: "toml",
243
261
  },
244
262
  instructionsPath: join(HOME, ".codex", "AGENTS.md"),
263
+ cursorRulesPath: null,
264
+ hooksPath: join(HOME, ".codex", "hooks.json"),
265
+ hooksFormat: "claude",
245
266
  subagentPath: null,
246
267
  subagentId: null,
247
268
  },
@@ -252,6 +273,22 @@ export const AGENT_TARGETS: AgentTarget[] = [
252
273
  configDir: null,
253
274
  mcp: jsonMcp(vscodeMcpPath(), "servers", STDIO_SERVER_CONFIG),
254
275
  instructionsPath: null,
276
+ cursorRulesPath: null,
277
+ hooksPath: copilotHooksPath(HOME),
278
+ hooksFormat: "vscode",
279
+ subagentPath: null,
280
+ subagentId: null,
281
+ },
282
+ {
283
+ id: "windsurf",
284
+ displayName: "Windsurf / Devin Desktop",
285
+ binary: "windsurf",
286
+ configDir: join(HOME, ".codeium", "windsurf"),
287
+ mcp: null,
288
+ instructionsPath: null,
289
+ cursorRulesPath: null,
290
+ hooksPath: windsurfHooksPath(HOME),
291
+ hooksFormat: "windsurf",
255
292
  subagentPath: null,
256
293
  subagentId: null,
257
294
  },
@@ -262,6 +299,9 @@ export const AGENT_TARGETS: AgentTarget[] = [
262
299
  configDir: visualStudioInstallDir(),
263
300
  mcp: jsonMcp(visualStudioMcpPath(), "servers", STDIO_SERVER_CONFIG),
264
301
  instructionsPath: null,
302
+ cursorRulesPath: null,
303
+ hooksPath: copilotHooksPath(HOME),
304
+ hooksFormat: "vscode",
265
305
  subagentPath: null,
266
306
  subagentId: null,
267
307
  },
@@ -281,6 +321,15 @@ export async function isAgentDetected(agent: AgentTarget): Promise<boolean> {
281
321
  if (agent.id === "visualstudio") {
282
322
  return detectVisualStudio();
283
323
  }
324
+ if (agent.id === "windsurf") {
325
+ if (agent.configDir && existsSync(agent.configDir)) {
326
+ return true;
327
+ }
328
+ if (agent.binary && (await commandOnPath(agent.binary))) {
329
+ return true;
330
+ }
331
+ return false;
332
+ }
284
333
  if (agent.binary && (await commandOnPath(agent.binary))) {
285
334
  return true;
286
335
  }