@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 +34 -13
- package/package.json +1 -1
- package/src/agents/claude.md +16 -28
- package/src/agents/copilot.md +9 -35
- package/src/agents/cursor.md +15 -28
- package/src/agents/gemini.md +10 -36
- package/src/agents/kiro.md +4 -37
- package/src/agents/opencode.md +4 -37
- package/src/cli.ts +9 -0
- package/src/installer/agents.ts +82 -33
- package/src/installer/hooks/install.ts +463 -0
- package/src/installer/hooks/opencode-plugin.ts +68 -0
- package/src/installer/hooks/search-guard.ts +215 -0
- package/src/installer/installer.ts +56 -3
- package/src/installer/prompt.ts +218 -32
- package/src/installer/search-policy.ts +68 -0
- package/src/mcp/server.ts +8 -9
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 —
|
|
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
|
-
|
|
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
package/src/agents/claude.md
CHANGED
|
@@ -1,41 +1,29 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: miru-code
|
|
3
|
-
description: Code search
|
|
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
|
-
|
|
7
|
+
When Miru MCP is available, use MCP `search` and `find_related` — not Grep, Glob, or Read-for-exploration.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
16
|
+
### MCP workflow
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
22
|
+
### CLI fallback
|
|
26
23
|
|
|
27
24
|
```bash
|
|
28
|
-
miru
|
|
25
|
+
miru search "authentication flow" .
|
|
26
|
+
miru find-related src/auth.ts 42 .
|
|
29
27
|
```
|
|
30
28
|
|
|
31
|
-
`
|
|
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`.
|
package/src/agents/copilot.md
CHANGED
|
@@ -1,41 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: miru-code
|
|
3
|
-
description: Code search
|
|
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
|
-
|
|
6
|
+
When Miru MCP is available, use `search` and `find_related` instead of `grep_search`, `codebase_search`, or broad file reads.
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
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.
|
package/src/agents/cursor.md
CHANGED
|
@@ -1,40 +1,27 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: miru-code
|
|
3
|
-
description: Code search
|
|
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
|
|
6
|
+
Use Miru MCP tools when connected:
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
11
|
+
Do not use Grep, Glob, SemanticSearch, or Read to explore the codebase when Miru MCP is available.
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
20
|
+
CLI fallback when MCP is unavailable:
|
|
25
21
|
|
|
26
22
|
```bash
|
|
27
|
-
miru
|
|
23
|
+
miru search "authentication flow" .
|
|
24
|
+
miru find-related src/auth.ts 42 .
|
|
28
25
|
```
|
|
29
26
|
|
|
30
|
-
`
|
|
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`.
|
package/src/agents/gemini.md
CHANGED
|
@@ -1,43 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: miru-code
|
|
3
|
-
description: Code search
|
|
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
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
15
|
+
Pass project root as `repo` on every MCP call.
|
|
18
16
|
|
|
19
|
-
|
|
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" .`
|
package/src/agents/kiro.md
CHANGED
|
@@ -1,43 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: miru-code
|
|
3
|
-
description: Code search
|
|
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
|
-
|
|
6
|
+
When Miru MCP is available, use `search` and `find_related` before any built-in search or broad file reads.
|
|
10
7
|
|
|
11
|
-
|
|
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
|
-
|
|
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" .`
|
package/src/agents/opencode.md
CHANGED
|
@@ -1,44 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: miru-code
|
|
3
|
-
description: Code search
|
|
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
|
-
|
|
7
|
+
When Miru MCP is available, use `search` and `find_related` instead of grep, glob, or read-for-exploration.
|
|
11
8
|
|
|
12
|
-
|
|
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
|
-
|
|
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;
|
package/src/installer/agents.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
}
|