@takara-ai/miru-code 0.4.1 → 0.4.3

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
@@ -1,291 +1,154 @@
1
1
  # Miru (見る)
2
2
 
3
- Hybrid code search for AI agents — **TypeScript**, **Bun**, and **Takara embeddings**.
3
+ Hybrid code search for AI agents — **Bun**, **TypeScript**, **Takara embeddings**.
4
4
 
5
- Miru helps coding agents **find code by meaning**. Ask “where is auth middleware configured?” and get back the most relevant **chunks** (file path, line range, snippet) instead of grepping the whole tree.
5
+ Find code by meaning, not grep. Miru returns the best **chunks** (path, lines, snippet) for questions like “where is auth middleware configured?”
6
6
 
7
- ## Quick start
7
+ **Requires:** [Bun](https://bun.sh) 1.1+ · [Takara API key](https://takara.ai)
8
8
 
9
- **Requirements:** [Bun](https://bun.sh) 1.1+ and a [Takara API key](https://takara.ai) for embeddings.
9
+ ## Install
10
10
 
11
11
  ```bash
12
- # 1. Install the CLI
13
12
  bun add -g @takara-ai/miru-code
14
-
15
- # 2. Store your API key (validates against Takara)
16
- miru setup
17
-
18
- # 3. Wire into your agents (MCP + instructions + sub-agent)
19
- miru install
20
-
21
- # 4. Restart your IDE / agent session, then search
22
- miru search "auth middleware" ./src
23
13
  ```
24
14
 
25
- That’s the full path for most users. `miru install` is interactive — it detects Cursor, Claude Code, Gemini CLI, Kiro, OpenCode, GitHub Copilot, Codex, and VS Code, and lets you pick what to configure.
26
-
27
- **One-off without installing:**
15
+ ## Set up API key
28
16
 
29
17
  ```bash
30
- bunx @takara-ai/miru-code search "auth middleware" ./src
18
+ miru setup
31
19
  ```
32
20
 
33
- **Undo agent setup:** `miru uninstall`
34
-
35
- ---
36
-
37
- ## How to read this doc
38
-
39
- | Goal | Section |
40
- |------|---------|
41
- | Get running in an IDE | [Quick start](#quick-start) → [IDE integration](#ide-integration) |
42
- | Search from terminal or scripts | [CLI](#cli) |
43
- | Use as a library | [Library](#library) |
44
- | Contribute to this repo | [Developing Miru](#developing-miru) |
45
-
46
- ## Install options
47
-
48
- | Method | Command | When to use |
49
- |--------|---------|-------------|
50
- | Global CLI | `bun add -g @takara-ai/miru-code` | Daily use, `miru install`, terminal search |
51
- | One-off | `bunx @takara-ai/miru-code …` | Try before installing |
52
- | Library | `bun add @takara-ai/miru-code` | Embed search in your own tool |
53
- | From source | [Developing Miru](#developing-miru) | Contributors |
54
-
55
- After install, `miru` is on your PATH. Run `miru` with no args for help.
56
-
57
- ## Credentials
58
-
59
- Miru needs `TAKARA_API_KEY` — a Takara bearer token for code embeddings.
21
+ Validates your key and saves it locally. Skip this if you prefer — `miru search` or `miru install` will prompt on first run.
60
22
 
61
23
  ```bash
62
- miru setup # interactive; validates and stores locally
63
- miru setup --key TOKEN # non-interactive
64
- miru setup --clear # remove stored key
24
+ miru setup --key YOUR_TOKEN # non-interactive
25
+ miru setup --clear # remove stored key
65
26
  ```
66
27
 
67
- Stored credentials live at:
68
-
69
- - macOS: `~/Library/Application Support/miru/credentials.json`
70
- - Linux: `~/.config/miru/credentials.json`
71
- - Windows: `%APPDATA%\miru\credentials.json`
72
-
73
- Override with `MIRU_CREDENTIALS_DIR`.
74
-
75
- **For MCP in an IDE:** also set `TAKARA_API_KEY` in the MCP server `env` block. MCP subprocesses do not reliably inherit your shell or `.env.local`. `miru install` writes `"TAKARA_API_KEY": "${TAKARA_API_KEY}"` where your IDE supports variable expansion — export the var or paste your token.
76
-
77
- ## IDE integration
78
-
79
- ### Recommended: `miru install`
80
-
81
- Configures up to three integrations per agent:
28
+ For MCP in an IDE, export `TAKARA_API_KEY` or paste your token into the MCP `env` block after install.
82
29
 
83
- | Integration | What it does |
84
- |-------------|----------------|
85
- | **MCP server** | Native `search` and `find_related` tools |
86
- | **Instructions** | Marked usage block in `CLAUDE.md`, `GEMINI.md`, `AGENTS.md`, etc. |
87
- | **Sub-agent** | Global `miru-code` agent file (Bash-backed search for sub-agents without MCP) |
30
+ ## Add to your IDE
88
31
 
89
32
  ```bash
90
- miru install # pick agents + integrations
91
- miru uninstall # remove miru entries
33
+ miru install
92
34
  ```
93
35
 
94
- Restart your IDE or agent session after install.
95
-
96
- ### Where files go (global user config)
97
-
98
- | Agent | MCP config | Sub-agent |
99
- |-------|------------|-----------|
100
- | Claude Code | `~/.claude.json` | `~/.claude/agents/miru-code.md` |
101
- | Cursor | `~/.cursor/mcp.json` | `~/.cursor/agents/miru-code.md` |
102
- | Gemini CLI | `~/.gemini/settings.json` | `~/.gemini/agents/miru-code.md` |
103
- | Kiro | `~/.kiro/settings/mcp.json` | `~/.kiro/agents/miru-code.md` |
104
- | OpenCode | `~/.config/opencode/opencode.json(c)` | `~/.config/opencode/agents/miru-code.md` |
105
- | GitHub Copilot | `~/.copilot/mcp-config.json` | `~/.copilot/agents/miru-code.agent.md` |
106
- | Codex | `~/.codex/config.toml` | — |
107
- | VS Code | user profile `Code/User/mcp.json` | — |
108
-
109
- ### Per-project sub-agent (`miru init`)
110
-
111
- To commit a sub-agent into a repo for your team (project-local, not global):
36
+ Interactive — pick your agent and what to enable (MCP, instructions, sub-agent). Restart the IDE when done.
112
37
 
113
38
  ```bash
114
- miru init --agent claude --force # → .claude/agents/miru-code.md
39
+ miru uninstall # remove miru config
115
40
  ```
116
41
 
117
- Agents: `cursor`, `claude`, `copilot`, `gemini`, `kiro`, `opencode`.
42
+ **Supported:** Cursor · Claude Code · Gemini CLI · Kiro · OpenCode · GitHub Copilot · Codex · VS Code
118
43
 
119
- ### Manual MCP setup
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 |
120
53
 
121
- Skip `miru install` and add this to your IDE’s MCP config (`mcpServers`, `servers`, or `mcp` depending on the tool):
54
+ **Team sub-agent in a repo** (optional):
122
55
 
123
- ```json
124
- {
125
- "miru": {
126
- "command": "bunx",
127
- "args": ["@takara-ai/miru-code"],
128
- "env": {
129
- "TAKARA_API_KEY": "your-takara-bearer-token"
130
- }
131
- }
132
- }
56
+ ```bash
57
+ miru init --agent claude --force
133
58
  ```
134
59
 
135
- After `bun add -g @takara-ai/miru-code`, you can use `"command": "miru"` instead of `bunx`.
60
+ ## Try it
136
61
 
137
- **MCP tools**
138
-
139
- | Tool | Purpose |
140
- |------|---------|
141
- | `search` | Natural-language or code query; requires `repo` (project root or `https://` git URL); optional `top_k` (default 5) |
142
- | `find_related` | Similar chunks to `file_path` + `line` from a prior hit; requires `repo` |
143
-
144
- Indexing runs on the first tool call per `repo`. Pass the **project root** for local workspaces. Remote repos need an explicit `https://` or `http://` URL (not `git@` SSH).
62
+ ```bash
63
+ miru search "auth middleware" ./src
64
+ miru find-related src/auth.ts 42 ./src
65
+ ```
145
66
 
146
- **IDE-specific notes**
67
+ Terminal output is human-readable; use `--json` for scripts. One-off without installing:
147
68
 
148
- - **Claude Code:** supports `${TAKARA_API_KEY}` in config; verify with `/mcp`. Or: `claude mcp add miru -s user -- bunx @takara-ai/miru-code`
149
- - **VS Code:** uses `"servers"` not `mcpServers`; restart via **MCP: List Servers**
150
- - **OpenCode:** uses `mcp`, `"type": "local"`, and `environment` instead of `env`
151
- - **Kiro:** include `PATH` in `env` if Bun is not on the default path
69
+ ```bash
70
+ bunx @takara-ai/miru-code search "auth middleware" ./src
71
+ ```
152
72
 
153
- Optional MCP startup flags: `--ref BRANCH`, `--content code docs …`
73
+ ---
154
74
 
155
- ## How Miru works
75
+ ## MCP tools
156
76
 
157
- ### Hybrid search
77
+ When wired via `miru install`, your agent gets:
158
78
 
159
- 1. **Dense (semantic)** — Takara code embeddings (`ds1-potion-code-16m`) over structurally chunked files
160
- 2. **Sparse (BM25)** — keyword index; parallelized in Bun workers when the index has 256+ chunks
161
- 3. **RRF fusion** — merges semantic and keyword rankings
162
- 4. **Reranking** — code-tuned boosts and penalties
79
+ | Tool | What it does |
80
+ |------|----------------|
81
+ | `search` | Query by meaning; pass `repo` (project root or `https://` git URL) |
82
+ | `find_related` | Similar code at a `file_path` + line from a search hit |
163
83
 
164
- Index **code**, **docs**, **config**, or **all** via `--content` (CLI/MCP) or when building a library index.
84
+ Pass the **project root** as `repo` for local projects.
165
85
 
166
- ### Agent workflow
86
+ ## How it works
167
87
 
168
- 1. `search` with a natural-language or code query
169
- 2. Read returned chunks
170
- 3. `find_related` on a promising `file_path` + line (optional)
171
- 4. Open full files only when the chunk is not enough
172
- 5. Use grep for exhaustive literal matches
88
+ Hybrid search: Takara embeddings + BM25 + fusion + reranking. Indexes **code**, **docs**, **config**, or **all** via `--content`.
173
89
 
174
- ### Caching
90
+ Disk cache: `~/Library/Caches/miru` (macOS), `~/.cache/miru` (Linux). MCP watches local files and updates incrementally; run `miru clear .` after big refactors when using CLI only.
175
91
 
176
- | Layer | Behavior |
177
- |-------|----------|
178
- | **First search** | Builds index, writes disk cache |
179
- | **MCP (local repo, same session)** | Watches files and incrementally re-indexes; disable with `MIRU_MCP_WATCH=0` |
180
- | **CLI / new MCP session** | Reuses disk cache; run `miru clear <path>` after large refactors |
181
- | **Remote repos** | Cloned per session; use `--ref` for branch/tag |
92
+ ## CLI reference
182
93
 
183
- Cache: `~/Library/Caches/miru` (macOS), `~/.cache/miru` (Linux), `%LOCALAPPDATA%\miru\Cache` (Windows).
94
+ | Command | Purpose |
95
+ |---------|---------|
96
+ | `miru setup` | Store API key |
97
+ | `miru install` | Configure IDE (global) |
98
+ | `miru uninstall` | Remove IDE config |
99
+ | `miru search <query> [path]` | Search (`-k N`, `--content`, `--json`) |
100
+ | `miru find-related <file> <line> [path]` | Related chunks |
101
+ | `miru init --agent <id>` | Project-local sub-agent |
102
+ | `miru clear [path]` | Drop index cache |
103
+ | `miru` | Start MCP server |
184
104
 
185
- ## CLI
105
+ ## Library
186
106
 
187
107
  ```bash
188
- miru setup
189
- miru install
190
- miru search "where are embeddings created" ./src -k 10 --content code
191
- miru find-related src/embeddings/openai.ts 120 ./src
192
- miru clear ./src
193
- miru uninstall
194
- miru help search
108
+ bun add @takara-ai/miru-code
195
109
  ```
196
110
 
197
- | Command | Summary |
198
- |---------|---------|
199
- | `search <query> [path]` | Hybrid search; path defaults to cwd; local path or `https://` git URL |
200
- | `find-related <file> <line> [path]` | Semantic neighbors at that line |
201
- | `setup` | Store and validate `TAKARA_API_KEY` |
202
- | `install` | Interactive global agent setup |
203
- | `uninstall` | Remove miru agent configuration |
204
- | `init --agent <id>` | Project-local sub-agent markdown |
205
- | `clear [path]` | Delete disk cache |
206
- | *(no command)* | Start stdio MCP server |
207
-
208
- **Options:** `-k` / `--top-k N` (default 5), `--content code|docs|config|all`, `--json` (force JSON output).
209
-
210
- **Output:** In a terminal, search results are formatted for reading (path, score, snippet preview). Piped output and `--json` emit JSON (`query` + `results` with `chunk`, `score`, `location`). Progress spinners go to stderr.
211
-
212
- From **this repo**, prefix commands with `bun run miru`.
213
-
214
- ## Library
215
-
216
111
  ```ts
217
112
  import { MiruIndex } from "@takara-ai/miru-code";
218
113
 
219
- const index = await MiruIndex.fromPath("./src", ["code"]);
220
- const fromUrl = await MiruIndex.fromSource(
221
- "https://github.com/org/repo",
222
- ["code"],
223
- undefined,
224
- "main",
225
- );
226
-
227
- const results = await index.search({
228
- query: "BM25 tokenize",
229
- topK: 10,
230
- filterPaths: ["src/index/bm25.ts"],
231
- });
232
-
233
- const related = await index.findRelated(results[0], 5);
234
- await index.saveToDefaultCache("./src");
114
+ const index = await MiruIndex.fromPath("./src");
115
+ const results = await index.search({ query: "BM25 tokenize", topK: 10 });
235
116
  ```
236
117
 
237
- Exports: `MiruIndex`, `clearCache`, `findIndexCachePath`, `resolveCacheFolder`, and chunk/result types.
238
-
239
- ## Environment variables
240
-
241
- | Variable | Default / notes |
242
- |----------|-----------------|
243
- | `TAKARA_API_KEY` | **Required** — Takara bearer token |
244
- | `MIRU_OPENAI_BASE_URL` | `https://infer.dev.takara.ai/v1` |
245
- | `MIRU_OPENAI_EMBEDDING_MODEL` | `ds1-potion-code-16m` |
246
- | `MIRU_EMBEDDING_DIMENSIONS` | `256` for potion (auto when unset) |
247
- | `MIRU_FLOAT_VECTORS` | unset = int8; `1` = float32 |
248
- | `MIRU_EMBEDDING_BATCH_SIZE` | `32` |
249
- | `MIRU_CONCURRENCY` | logical CPUs minus 2 (min 1) |
250
- | `MIRU_MCP_WATCH` | on; `0` or `false` disables MCP file watch |
251
- | `MIRU_CREDENTIALS_DIR` | Override credentials directory |
118
+ ## Environment
119
+
120
+ | Variable | Notes |
121
+ |----------|-------|
122
+ | `TAKARA_API_KEY` | Required |
123
+ | `MIRU_OPENAI_BASE_URL` | Default `https://infer.takara.ai/v1` |
124
+ | `MIRU_MCP_WATCH` | Set `0` to disable MCP file watch |
252
125
  | `NO_COLOR` | Disable CLI colors |
253
126
 
254
- See `.env.example` for optional pipeline tuning (`MIRU_PIPELINE_*`).
127
+ See `.env.example` for more.
255
128
 
256
- ## Developing Miru
257
-
258
- ```bash
259
- git clone https://github.com/takara-ai/miru-code.git
260
- cd miru-code
261
- bun install
262
- cp .env.example .env.local # add TAKARA_API_KEY
263
- bun test
264
- bun run typecheck
265
- bun run lint
266
- ```
267
-
268
- **Local MCP** — point at your clone:
129
+ ## Manual MCP (skip `miru install`)
269
130
 
270
131
  ```json
271
132
  {
272
- "command": "bun",
273
- "args": ["/absolute/path/to/miru-code/src/cli.ts"],
274
- "env": {
275
- "TAKARA_API_KEY": "your-takara-bearer-token"
133
+ "miru": {
134
+ "command": "miru",
135
+ "args": [],
136
+ "env": { "TAKARA_API_KEY": "your-token" }
276
137
  }
277
138
  }
278
139
  ```
279
140
 
280
- ## Publishing
141
+ Use `bunx` + `@takara-ai/miru-code` if `miru` is not global. Wrapper key varies by IDE (`mcpServers`, `servers`, or `mcp`).
281
142
 
282
- Releases use **Bun** for install, test, and `bun pm pack`. Registry upload uses **`npm publish`** on that tarball because [Bun does not yet support npm OIDC trusted publishing](https://github.com/oven-sh/bun/issues/22423).
143
+ ## Developing
283
144
 
284
145
  ```bash
285
- bun publish # local, logged in to npm
146
+ git clone https://github.com/takara-ai/miru-code.git && cd miru-code
147
+ bun install && cp .env.example .env.local
148
+ bun test && bun run typecheck
286
149
  ```
287
150
 
288
- **CI:** tag a GitHub Release; `release.yml` publishes to npm via Trusted Publisher.
151
+ Local MCP: `"command": "bun", "args": ["/path/to/miru-code/src/cli.ts"]`
289
152
 
290
153
  ## License
291
154
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takara-ai/miru-code",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "Miru (見る) — hybrid code search for agents. Bun, TypeScript, Takara embeddings.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/cli.ts CHANGED
@@ -133,7 +133,7 @@ async function runSearch(
133
133
  content: ContentType[],
134
134
  jsonFlag: boolean,
135
135
  ): Promise<void> {
136
- await ensureCredentials();
136
+ await ensureCredentials({ interactive: true });
137
137
 
138
138
  const index = await withSpinner("Indexing and searching", async () => {
139
139
  const built = await MiruIndex.fromSource(path, content);
@@ -153,7 +153,7 @@ async function runFindRelated(
153
153
  content: ContentType[],
154
154
  jsonFlag: boolean,
155
155
  ): Promise<void> {
156
- await ensureCredentials();
156
+ await ensureCredentials({ interactive: true });
157
157
 
158
158
  const { results, label } = await withSpinner("Finding related chunks", async () => {
159
159
  const built = await MiruIndex.fromSource(path, content);
@@ -2,7 +2,7 @@ import { mapPool, resolveWorkerConcurrency } from "../concurrency.ts";
2
2
  import { envFirstString, envOptionalInt, resolveEmbeddingApiKey } from "../env.ts";
3
3
 
4
4
  const DEFAULT_MODEL = "ds1-potion-code-16m";
5
- const DEFAULT_BASE_URL = "https://infer.dev.takara.ai/v1";
5
+ const DEFAULT_BASE_URL = "https://infer.takara.ai/v1";
6
6
  const DEFAULT_BATCH_SIZE = 32;
7
7
  const DEFAULT_MAX_EMBED_CHARS = 1300;
8
8
  const WINDOW_OVERLAP_CHARS = 120;
package/src/help.ts CHANGED
@@ -53,7 +53,7 @@ export function printEnvHelp(): void {
53
53
  writeStdout(" TAKARA_API_KEY");
54
54
  writeStdout(" Takara bearer token for embeddings");
55
55
  writeStdout(" MIRU_OPENAI_BASE_URL");
56
- writeStdout(" Default: https://infer.dev.takara.ai/v1");
56
+ writeStdout(" Default: https://infer.takara.ai/v1");
57
57
  writeStdout(" MIRU_CONCURRENCY");
58
58
  writeStdout(" Parallel workers (default: CPUs − 2)");
59
59
  writeStdout("");
@@ -2,6 +2,7 @@ import { mkdir, unlink, writeFile } from "node:fs/promises";
2
2
  import { dirname } from "node:path";
3
3
  import { loadAgentTemplate } from "../agents.ts";
4
4
  import { brandTitle, dim, divider, green, hint, success, writeStdout } from "../cli-ui.ts";
5
+ import { ensureCredentials } from "../setup.ts";
5
6
  import {
6
7
  AGENT_TARGETS,
7
8
  type AgentTarget,
@@ -183,6 +184,10 @@ export async function runInstaller(mode: InstallMode): Promise<void> {
183
184
  const install = mode === "install";
184
185
  requireInteractiveTerminal(`miru ${mode}`);
185
186
 
187
+ if (install) {
188
+ await ensureCredentials({ interactive: true });
189
+ }
190
+
186
191
  writeStdout("");
187
192
  writeStdout(`${brandTitle()}${install ? " installer" : " uninstaller"}`);
188
193
  divider();
package/src/setup.ts CHANGED
@@ -87,30 +87,45 @@ export async function runClearCredentials(): Promise<void> {
87
87
  info(`No stored API key at ${path}`);
88
88
  }
89
89
 
90
- export async function ensureCredentials(options?: { interactive?: boolean }): Promise<void> {
90
+ export function canPromptForCredentials(): boolean {
91
+ return Boolean(process.stdin.isTTY);
92
+ }
93
+
94
+ export function hasCredentials(): boolean {
91
95
  try {
92
96
  resolveEmbeddingApiKey();
93
- return;
97
+ return true;
94
98
  } catch {
95
- await loadStoredCredentials();
99
+ return false;
96
100
  }
101
+ }
97
102
 
98
- try {
99
- resolveEmbeddingApiKey();
103
+ async function refreshCredentialsFromStore(): Promise<void> {
104
+ await loadStoredCredentials();
105
+ }
106
+
107
+ export async function ensureCredentials(options?: { interactive?: boolean }): Promise<void> {
108
+ if (hasCredentials()) {
109
+ return;
110
+ }
111
+
112
+ await refreshCredentialsFromStore();
113
+ if (hasCredentials()) {
100
114
  return;
101
- } catch {
102
- // still missing
103
115
  }
104
116
 
105
- const interactive = options?.interactive ?? process.stdin.isTTY;
106
- if (interactive) {
117
+ const wantsPrompt = options?.interactive ?? true;
118
+ if (wantsPrompt && canPromptForCredentials()) {
119
+ writeStderr("");
120
+ info("No Takara API key found.");
121
+ hint("Miru needs one for embeddings — enter it below (same as `miru setup`).");
107
122
  await runSetup();
108
123
  resolveEmbeddingApiKey();
109
124
  return;
110
125
  }
111
126
 
112
127
  throw new Error(
113
- "Embedding API key required. Run `miru setup` in a terminal, or set TAKARA_API_KEY " +
128
+ "Takara API key required. Run `miru setup` in a terminal, or set TAKARA_API_KEY " +
114
129
  "in your MCP server env (Cursor mcp.json) or .env.local.",
115
130
  );
116
131
  }