@takara-ai/miru-code 1.6.0 → 1.7.2
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 +39 -15
- package/package.json +1 -1
- package/src/auth/device.ts +13 -5
- package/src/auth/errors.ts +24 -0
- package/src/auth/providers.ts +20 -24
- package/src/cli.ts +25 -3
- package/src/env.ts +3 -1
- package/src/help.ts +22 -10
- package/src/installer/agents.ts +116 -21
- package/src/installer/caveman-shared.ts +51 -0
- package/src/installer/config.ts +73 -0
- package/src/installer/copilot-family.ts +8 -0
- package/src/installer/hooks/install.ts +3 -14
- package/src/installer/installer.ts +279 -18
- package/src/installer/prompt.ts +15 -8
- package/src/installer/search-policy.ts +2 -1
- package/src/installer/shared-skill.ts +200 -0
- package/src/installer/style-packs/ste/skill.ts +218 -0
- package/src/mcp/auth-tool.ts +58 -28
- package/src/mcp/index-cache.ts +2 -1
- package/src/mcp/server.ts +5 -5
- package/src/spinner.ts +33 -6
package/README.md
CHANGED
|
@@ -57,6 +57,7 @@ Interactive TUI — **↑↓** move, **space** toggle, **a** all, **enter** conf
|
|
|
57
57
|
| Cursor rules | Always-on `.cursor/rules/miru-code.mdc` (Cursor only) |
|
|
58
58
|
| Search hooks *(experimental)* | Block built-in Grep/Glob and redirect to Miru MCP |
|
|
59
59
|
| Caveman *(experimental)* | On-demand chat compression skill (`/caveman`) |
|
|
60
|
+
| STE writing *(experimental)* | On-demand clear technical English for docs (`/ste`) |
|
|
60
61
|
|
|
61
62
|
|
|
62
63
|
Restart the IDE when done.
|
|
@@ -68,18 +69,19 @@ miru uninstall # remove miru config
|
|
|
68
69
|
**Supported:** Cursor · Claude Code · Gemini CLI · Kiro · OpenCode · GitHub Copilot · Codex · VS Code · Visual Studio (Windows) · Windsurf / Devin Desktop
|
|
69
70
|
|
|
70
71
|
|
|
71
|
-
| IDE | MCP | Instructions / rules | Hooks *(experimental)* | Caveman *(experimental)*
|
|
72
|
-
| -------------- | ------------------------------------- | ------------------------------- | ------------------------------------------------- |
|
|
73
|
-
| Cursor | `~/.cursor/mcp.json` | `~/.cursor/rules/miru-code.mdc` | `~/.cursor/hooks.json` | `~/.
|
|
74
|
-
| Claude Code | `~/.claude.json` | `~/.claude/CLAUDE.md` | `~/.claude/settings.json` | `~/.claude/skills/caveman/SKILL.md`
|
|
75
|
-
| Gemini CLI | `~/.gemini/settings.json` | `~/.gemini/GEMINI.md` | `~/.gemini/settings.json` (`BeforeTool`) |
|
|
76
|
-
| Kiro | `~/.kiro/settings/mcp.json` | `~/.kiro/steering/miru.md` | `~/.kiro/settings/hooks.json` |
|
|
77
|
-
| OpenCode |
|
|
78
|
-
| GitHub Copilot | `~/.copilot/mcp-config.json` | — | `~/.copilot/hooks/miru-search.json` |
|
|
79
|
-
| Codex | `~/.codex/config.toml` | `~/.codex/AGENTS.md` | `~/.codex/hooks.json` |
|
|
80
|
-
| VS Code | `…/Code/User/mcp.json` | — | `~/.copilot/hooks/miru-search.json` |
|
|
81
|
-
| Visual Studio | `%USERPROFILE%\.mcp.json` | — | `~/.copilot/hooks/miru-search.json` |
|
|
82
|
-
| Windsurf | — | — | `~/.codeium/windsurf/hooks.json` |
|
|
72
|
+
| IDE | MCP | Instructions / rules | Hooks *(experimental)* | Caveman *(experimental)* | STE *(experimental)* |
|
|
73
|
+
| -------------- | ------------------------------------- | ------------------------------- | ------------------------------------------------- | --------------------------------------------------- | -------------------------------------------- |
|
|
74
|
+
| Cursor | `~/.cursor/mcp.json` | `~/.cursor/rules/miru-code.mdc` | `~/.cursor/hooks.json` | `~/.agents/skills/caveman/SKILL.md` | `~/.agents/skills/ste/SKILL.md` |
|
|
75
|
+
| Claude Code | `~/.claude.json` | `~/.claude/CLAUDE.md` | `~/.claude/settings.json` | `~/.claude/skills/caveman/SKILL.md` | `~/.claude/skills/ste/SKILL.md` |
|
|
76
|
+
| Gemini CLI | `~/.gemini/settings.json` | `~/.gemini/GEMINI.md` | `~/.gemini/settings.json` (`BeforeTool`) | `~/.agents/skills/caveman/SKILL.md` | `~/.agents/skills/ste/SKILL.md` |
|
|
77
|
+
| Kiro | `~/.kiro/settings/mcp.json` | `~/.kiro/steering/miru.md` | `~/.kiro/settings/hooks.json` | `~/.kiro/skills/caveman/SKILL.md` | `~/.kiro/skills/ste/SKILL.md` |
|
|
78
|
+
| OpenCode | `$XDG_CONFIG_HOME/opencode/opencode.json(c)` *(else `~/.config/opencode/…`)* | `…/AGENTS.md` | `…/plugins/miru-search-guard.ts` | `~/.agents/skills/caveman/SKILL.md` | `~/.agents/skills/ste/SKILL.md` |
|
|
79
|
+
| GitHub Copilot | `~/.copilot/mcp-config.json` | — | `~/.copilot/hooks/miru-search.json` | `~/.agents/skills/caveman/SKILL.md` | `~/.agents/skills/ste/SKILL.md` |
|
|
80
|
+
| Codex | `~/.codex/config.toml` | `~/.codex/AGENTS.md` | `~/.codex/hooks.json` | `~/.agents/skills/caveman/SKILL.md` | `~/.agents/skills/ste/SKILL.md` |
|
|
81
|
+
| VS Code | `…/Code/User/mcp.json` | — | `~/.copilot/hooks/miru-search.json` | `~/.agents/skills/caveman/SKILL.md` | `~/.agents/skills/ste/SKILL.md` |
|
|
82
|
+
| Visual Studio | `%USERPROFILE%\.mcp.json` | — | `~/.copilot/hooks/miru-search.json` | `~/.agents/skills/caveman/SKILL.md` | `~/.agents/skills/ste/SKILL.md` |
|
|
83
|
+
| Windsurf | — | — | `~/.codeium/windsurf/hooks.json` | `~/.agents/skills/caveman/SKILL.md` | `~/.agents/skills/ste/SKILL.md` |
|
|
84
|
+
|
|
83
85
|
|
|
84
86
|
### Plugin packaging
|
|
85
87
|
|
|
@@ -97,7 +99,18 @@ Current limitation:
|
|
|
97
99
|
|
|
98
100
|
### Search hooks
|
|
99
101
|
|
|
100
|
-
Sub-agent files are also written where supported (see `miru install` plan). Windsurf hooks only *(experimental)* — no MCP entry yet. Caveman is an on-demand Agent Skill (default off): invoke with `/caveman` or “talk like caveman”; stop with “normal mode”.
|
|
102
|
+
Sub-agent files are also written where supported (see `miru install` plan). Windsurf hooks only *(experimental)* — no MCP entry yet. Caveman is an on-demand Agent Skill (default off): invoke with `/caveman` or “talk like caveman”; stop with “normal mode”. Invocation UI varies by IDE (`/caveman`, `$caveman`, `@caveman`, etc.). Most IDEs share `~/.agents/skills/caveman/SKILL.md` (including Copilot / VS Code / Visual Studio); Claude Code and Kiro keep vendor-native skill dirs. Ownership is tracked on the shared path so uninstalling one IDE keeps the skill while another still owns it; selecting all owners removes it once. STE is an on-demand Agent Skill (default off): invoke with `/ste` or “de-slop this”; keep articles and complete sentences. Most IDEs share `~/.agents/skills/ste/` the same way (ownership via `miru-owners.json`); Claude Code and Kiro keep vendor-native STE dirs.
|
|
103
|
+
|
|
104
|
+
<details>
|
|
105
|
+
<summary>STE writing <em>(experimental)</em></summary>
|
|
106
|
+
|
|
107
|
+
STE helps write **clear technical English** for docs, runbooks, errors, and release notes (pragmatic ASD-STE100-inspired rules). Invoke with `/ste` or “de-slop this”. Keep articles and complete sentences — not telegraph-style omission.
|
|
108
|
+
|
|
109
|
+
**Not ASD-certified.** Full dictionary compliance needs the official standard at [asd-ste100.org](https://www.asd-ste100.org). Miru does not ship the copyrighted ASD dictionary.
|
|
110
|
+
|
|
111
|
+
Not for marketing or brand copy. Off by default; enable STE in the installer for any supported IDE. Restart the IDE (or reload skills) after install. For Codex, install also sets `[features] skills = true` in `~/.codex/config.toml` (same as Caveman).
|
|
112
|
+
|
|
113
|
+
</details>
|
|
101
114
|
|
|
102
115
|
<details>
|
|
103
116
|
<summary>Caveman mode <em>(experimental)</em></summary>
|
|
@@ -106,7 +119,7 @@ Caveman compresses **live chat replies** (less filler, max meaning). Intensities
|
|
|
106
119
|
|
|
107
120
|
Security / destructive warnings use clear normal prose (auto-clarity) — brevity never hides risk. Session token savings vary; the skill itself costs input tokens. No guaranteed %.
|
|
108
121
|
|
|
109
|
-
Off by default at install time. Enable Caveman in the installer for
|
|
122
|
+
Off by default at install time. Enable Caveman in the installer for any supported IDE. Restart the IDE (or reload skills) after install. For Codex, the installer also sets `[features] skills = true` in `~/.codex/config.toml` (required for Codex to load skills).
|
|
110
123
|
|
|
111
124
|
</details>
|
|
112
125
|
|
|
@@ -222,6 +235,8 @@ Set `MIRU_AST_CHUNKING=0` to disable AST and use structural → lines only.
|
|
|
222
235
|
|
|
223
236
|
## CLI reference
|
|
224
237
|
|
|
238
|
+
Run `miru -h` for the command list, or `miru <command> -h` for details.
|
|
239
|
+
|
|
225
240
|
| Command | Purpose |
|
|
226
241
|
| ----------------------------------------- | --------------------------------------------------------------------------------- |
|
|
227
242
|
| `miru setup` | Authenticate and store credentials |
|
|
@@ -392,7 +407,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for pre-commit hooks, commit message conv
|
|
|
392
407
|
|
|
393
408
|
Local MCP: `"command": "bun", "args": ["/path/to/miru-code/src/cli.ts"]`
|
|
394
409
|
|
|
395
|
-
`miru
|
|
410
|
+
`miru -h` / setup print a framed wordmark on color terminals (`MIRU_QUIET=1` for subtitle only). Crane art lives in `src/brand-banner.ts`; regenerate with `bun run scripts/render-crane-art.ts` (ImageMagick). The crane is a registered mark of Takara.ai Ltd.
|
|
396
411
|
|
|
397
412
|
## Codex plugin in this repo
|
|
398
413
|
|
|
@@ -404,6 +419,15 @@ This repo includes a repo-local Codex plugin:
|
|
|
404
419
|
|
|
405
420
|
The plugin intentionally launches the published package with `bunx @takara-ai/miru-code` instead of the checked-out source tree, so local source edits here do not affect the Codex plugin until a new package version is published.
|
|
406
421
|
|
|
422
|
+
## Credits
|
|
423
|
+
|
|
424
|
+
Miru uses work by [MinishLab](https://github.com/MinishLab). Thank you to its authors.
|
|
425
|
+
|
|
426
|
+
- **[semble](https://github.com/MinishLab/semble)** (MIT). Miru ports parts of semble. These parts include the file walker, the index layout, the BM25 tokenizer, the hybrid search pipeline, and the ranking signals.
|
|
427
|
+
- **[potion-code](https://huggingface.co/minishlab/potion-code-16M)** and **[Model2Vec](https://github.com/MinishLab/model2vec)** (MIT). The WordPiece tokenizer in `tokenizer/tokenizer.json` comes from potion-code.
|
|
428
|
+
|
|
429
|
+
See [NOTICE](./NOTICE) for the licence text and the Model2Vec citation.
|
|
430
|
+
|
|
407
431
|
## License
|
|
408
432
|
|
|
409
433
|
MIT
|
package/package.json
CHANGED
package/src/auth/device.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { envFirstString } from "../env.ts";
|
|
2
|
+
import { CredentialsError } from "./errors.ts";
|
|
2
3
|
import type { StoredDeviceCodeCredentials } from "./types.ts";
|
|
3
4
|
|
|
4
5
|
const DEFAULT_AUTH_BASE_URL = "https://auth.takara.ai";
|
|
@@ -239,7 +240,7 @@ export async function refreshDeviceAuthorization(
|
|
|
239
240
|
options?: { config?: DeviceAuthConfig; fetchImpl?: typeof fetch },
|
|
240
241
|
): Promise<DeviceAuthorizationTokens> {
|
|
241
242
|
if (!credentials.refresh_token?.trim()) {
|
|
242
|
-
throw new
|
|
243
|
+
throw new CredentialsError(
|
|
243
244
|
"Stored device credentials cannot be refreshed because no refresh token exists.",
|
|
244
245
|
);
|
|
245
246
|
}
|
|
@@ -256,12 +257,14 @@ export async function refreshDeviceAuthorization(
|
|
|
256
257
|
const payload = text ? (JSON.parse(text) as OAuthTokenSuccess | OAuthTokenError) : {};
|
|
257
258
|
|
|
258
259
|
if (!response.ok) {
|
|
259
|
-
throw new
|
|
260
|
+
throw new CredentialsError(
|
|
261
|
+
`Device token refresh failed: ${parseTokenError(payload as OAuthTokenError)}`,
|
|
262
|
+
);
|
|
260
263
|
}
|
|
261
264
|
|
|
262
265
|
const success = payload as OAuthTokenSuccess;
|
|
263
266
|
if (!success.access_token?.trim()) {
|
|
264
|
-
throw new
|
|
267
|
+
throw new CredentialsError("Token refresh succeeded but did not return an access token.");
|
|
265
268
|
}
|
|
266
269
|
|
|
267
270
|
return normalizeTokenSuccess({
|
|
@@ -289,8 +292,13 @@ export function openBrowserForDeviceLogin(url: string): boolean {
|
|
|
289
292
|
? ["cmd", "/c", "start", "", url]
|
|
290
293
|
: ["xdg-open", url];
|
|
291
294
|
try {
|
|
292
|
-
const proc = Bun.spawn(command, {
|
|
293
|
-
|
|
295
|
+
const proc = Bun.spawn(command, {
|
|
296
|
+
stdin: "ignore",
|
|
297
|
+
stdout: "ignore",
|
|
298
|
+
stderr: "ignore",
|
|
299
|
+
});
|
|
300
|
+
// Detach so the spinner's event loop / process lifecycle can't kill `open`.
|
|
301
|
+
proc.unref();
|
|
294
302
|
return true;
|
|
295
303
|
} catch {
|
|
296
304
|
return false;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signals that Miru has no usable credentials — missing, expired, or revoked.
|
|
3
|
+
* Callers that can recover (the MCP `auth` tool, `miru setup`) branch on this
|
|
4
|
+
* instead of matching error text.
|
|
5
|
+
*/
|
|
6
|
+
export class CredentialsError extends Error {
|
|
7
|
+
constructor(message: string, options?: { cause?: unknown }) {
|
|
8
|
+
super(message, options);
|
|
9
|
+
this.name = "CredentialsError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** True when `error`, or anything in its `cause` chain, is a CredentialsError. */
|
|
14
|
+
export function isCredentialsError(error: unknown): boolean {
|
|
15
|
+
let current: unknown = error;
|
|
16
|
+
// Bounded so a self-referencing cause chain cannot spin forever.
|
|
17
|
+
for (let depth = 0; depth < 10 && current instanceof Error; depth++) {
|
|
18
|
+
if (current instanceof CredentialsError) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
current = current.cause;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
package/src/auth/providers.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dim, warn, writeStderr } from "../cli-ui.ts";
|
|
2
2
|
import { validateEmbeddingApiKey } from "../embeddings/validate.ts";
|
|
3
3
|
import { promptConfirm } from "../installer/prompt.ts";
|
|
4
4
|
import { promptHidden } from "../prompt.ts";
|
|
@@ -35,16 +35,10 @@ async function resolveAuthMode(options: AuthenticateOptions): Promise<AuthMode>
|
|
|
35
35
|
if (options.apiKey) {
|
|
36
36
|
return "api_key";
|
|
37
37
|
}
|
|
38
|
-
if (options.device) {
|
|
38
|
+
if (options.device || options.interactive) {
|
|
39
39
|
return "device_code";
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
throw new Error("Choose an auth mode with `miru setup --device` or `miru setup --key TOKEN`.");
|
|
43
|
-
}
|
|
44
|
-
writeStderr("");
|
|
45
|
-
info("Choose how to authenticate.");
|
|
46
|
-
const useDevice = await promptConfirm("Use device code login?", true);
|
|
47
|
-
return useDevice ? "device_code" : "api_key";
|
|
41
|
+
throw new Error("Choose an auth mode with `miru setup --device` or `miru setup --key TOKEN`.");
|
|
48
42
|
}
|
|
49
43
|
|
|
50
44
|
async function authenticateWithApiKey(
|
|
@@ -67,24 +61,26 @@ async function authenticateWithApiKey(
|
|
|
67
61
|
async function authenticateWithDeviceCode(
|
|
68
62
|
options: AuthenticateOptions,
|
|
69
63
|
): Promise<AuthenticatedCredentials> {
|
|
70
|
-
const start = await startDeviceAuthorization();
|
|
71
|
-
const verificationUrl = start.verificationUriComplete ?? start.verificationUri;
|
|
72
64
|
writeStderr("");
|
|
73
|
-
|
|
74
|
-
if (!start.verificationUriComplete) {
|
|
75
|
-
hint(`Code: ${start.userCode}`);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const shouldOpenBrowser =
|
|
79
|
-
options.interactive &&
|
|
80
|
-
(process.env.MIRU_OPEN_BROWSER === undefined || process.env.MIRU_OPEN_BROWSER === "1");
|
|
81
|
-
if (shouldOpenBrowser) {
|
|
82
|
-
openBrowserForDeviceLogin(verificationUrl);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const spinner = new Spinner("Waiting for authentication");
|
|
65
|
+
const spinner = new Spinner("Authenticating");
|
|
86
66
|
spinner.start();
|
|
87
67
|
try {
|
|
68
|
+
const start = await startDeviceAuthorization();
|
|
69
|
+
const verificationUrl = start.verificationUriComplete ?? start.verificationUri;
|
|
70
|
+
|
|
71
|
+
const shouldOpenBrowser =
|
|
72
|
+
options.interactive &&
|
|
73
|
+
(process.env.MIRU_OPEN_BROWSER === undefined || process.env.MIRU_OPEN_BROWSER === "1");
|
|
74
|
+
if (shouldOpenBrowser) {
|
|
75
|
+
openBrowserForDeviceLogin(verificationUrl);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let visit = dim(` Visit ${verificationUrl}`);
|
|
79
|
+
if (!start.verificationUriComplete) {
|
|
80
|
+
visit += `\n${dim(` Code: ${start.userCode}`)}`;
|
|
81
|
+
}
|
|
82
|
+
spinner.follow(visit);
|
|
83
|
+
|
|
88
84
|
const tokens = await pollDeviceAuthorization(start);
|
|
89
85
|
spinner.succeed("");
|
|
90
86
|
return {
|
package/src/cli.ts
CHANGED
|
@@ -21,8 +21,9 @@ import {
|
|
|
21
21
|
AGENT_IDS,
|
|
22
22
|
formatUnknownAgent,
|
|
23
23
|
printCommandHelp,
|
|
24
|
-
|
|
24
|
+
printEnvironmentHelp,
|
|
25
25
|
printMainHelp,
|
|
26
|
+
printSageMakerHelp,
|
|
26
27
|
} from "./help.ts";
|
|
27
28
|
import { getBenchmarkModeStatus, setBenchmarkMode } from "./installer/benchmark-mode.ts";
|
|
28
29
|
import { runSearchGuardFromStdin } from "./installer/hooks/search-guard.ts";
|
|
@@ -81,6 +82,8 @@ const CLI_COMMANDS = new Set([
|
|
|
81
82
|
"setup",
|
|
82
83
|
"clear",
|
|
83
84
|
"benchmark",
|
|
85
|
+
"env",
|
|
86
|
+
"environment",
|
|
84
87
|
"hook-guard",
|
|
85
88
|
"help",
|
|
86
89
|
"-h",
|
|
@@ -415,7 +418,7 @@ async function runCli(argv: string[]): Promise<void> {
|
|
|
415
418
|
}
|
|
416
419
|
|
|
417
420
|
if (command === "-h" || command === "--help") {
|
|
418
|
-
|
|
421
|
+
printMainHelp();
|
|
419
422
|
return;
|
|
420
423
|
}
|
|
421
424
|
|
|
@@ -426,7 +429,7 @@ async function runCli(argv: string[]): Promise<void> {
|
|
|
426
429
|
|
|
427
430
|
if (command === "help") {
|
|
428
431
|
const topic = rest[0];
|
|
429
|
-
if (!topic) {
|
|
432
|
+
if (!topic || topic === "-h" || topic === "--help") {
|
|
430
433
|
printMainHelp();
|
|
431
434
|
return;
|
|
432
435
|
}
|
|
@@ -434,6 +437,25 @@ async function runCli(argv: string[]): Promise<void> {
|
|
|
434
437
|
return;
|
|
435
438
|
}
|
|
436
439
|
|
|
440
|
+
if (command === "setup" && (rest.includes("-h") || rest.includes("--help"))) {
|
|
441
|
+
if (rest.includes("--sagemaker")) {
|
|
442
|
+
printSageMakerHelp();
|
|
443
|
+
} else {
|
|
444
|
+
printCommandHelp("setup");
|
|
445
|
+
}
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (command === "env" || command === "environment") {
|
|
450
|
+
printEnvironmentHelp();
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (rest[0] === "-h" || rest[0] === "--help") {
|
|
455
|
+
printCommandHelp(command);
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
|
|
437
459
|
if (command === "hook-guard") {
|
|
438
460
|
process.exit(await runSearchGuardFromStdin());
|
|
439
461
|
}
|
package/src/env.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { CredentialsError } from "./auth/errors.ts";
|
|
2
|
+
|
|
1
3
|
export function envInt(name: string, fallback: number, min = 1): number {
|
|
2
4
|
const raw = process.env[name];
|
|
3
5
|
if (!raw) {
|
|
@@ -59,7 +61,7 @@ export function hasTakaraApiKeyInEnv(): boolean {
|
|
|
59
61
|
export function resolveEmbeddingApiKey(): string {
|
|
60
62
|
const key = process.env[TAKARA_API_KEY_ENV]?.trim() ?? "";
|
|
61
63
|
if (!isUsableTakaraApiKey(key)) {
|
|
62
|
-
throw new
|
|
64
|
+
throw new CredentialsError(
|
|
63
65
|
"Takara credentials required. If you're an agent with Miru MCP tools available, call the " +
|
|
64
66
|
"`auth` tool to sign in. Otherwise run `miru setup`, or set TAKARA_API_KEY in your MCP " +
|
|
65
67
|
"server env or .env.local.",
|
package/src/help.ts
CHANGED
|
@@ -37,24 +37,23 @@ export function printMainHelp(): void {
|
|
|
37
37
|
commandRow("locate", "Exact substring location in the index");
|
|
38
38
|
commandRow("expand", "Adjacent chunks in the same file as a hit");
|
|
39
39
|
commandRow("find-related", "Find chunks related to a file:line");
|
|
40
|
-
commandRow("setup", "Authenticate with Takara
|
|
40
|
+
commandRow("setup", "Authenticate with Takara");
|
|
41
41
|
commandRow("install", "Configure miru across coding agents");
|
|
42
42
|
commandRow("uninstall", "Remove miru agent configuration");
|
|
43
43
|
commandRow("benchmark", "Turn MCP benchmark mode on or off");
|
|
44
44
|
commandRow("init", "Write a project-local sub-agent file");
|
|
45
45
|
commandRow("clear", "Remove cached index for a path");
|
|
46
|
-
commandRow("help", "Show help for a command");
|
|
47
46
|
divider();
|
|
48
47
|
|
|
49
48
|
section("Quick start");
|
|
50
49
|
writeStdout(" miru setup && miru install");
|
|
51
50
|
writeStdout(' miru search "auth middleware" ./src');
|
|
52
51
|
writeStdout("");
|
|
53
|
-
hint("miru
|
|
52
|
+
hint("miru <command> -h · miru -v for version");
|
|
54
53
|
writeStdout("");
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
export function
|
|
56
|
+
export function printEnvironmentHelp(): void {
|
|
58
57
|
section("Environment");
|
|
59
58
|
writeStdout(` ${TAKARA_API_KEY_ENV}`);
|
|
60
59
|
writeStdout(" Takara bearer token for embeddings");
|
|
@@ -67,6 +66,9 @@ export function printEnvHelp(): void {
|
|
|
67
66
|
writeStdout(" MIRU_TOKENIZER_JSON");
|
|
68
67
|
writeStdout(" Path to tokenizer.json (default: <package>/tokenizer/tokenizer.json)");
|
|
69
68
|
writeStdout("");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function printSageMakerHelp(): void {
|
|
70
72
|
section("Self-hosted (AWS SageMaker)");
|
|
71
73
|
writeStdout(" MIRU_SAGEMAKER_ENDPOINT_ARN");
|
|
72
74
|
writeStdout(" arn:aws:sagemaker:<region>:<account-id>:endpoint/<name> — set this to");
|
|
@@ -90,13 +92,17 @@ export function printEnvHelp(): void {
|
|
|
90
92
|
writeStdout("");
|
|
91
93
|
}
|
|
92
94
|
|
|
93
|
-
export function
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
export function printEnvHelp(): void {
|
|
96
|
+
printEnvironmentHelp();
|
|
97
|
+
printSageMakerHelp();
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
export function printCommandHelp(command: string): void {
|
|
99
101
|
switch (command) {
|
|
102
|
+
case "env":
|
|
103
|
+
case "environment":
|
|
104
|
+
printEnvironmentHelp();
|
|
105
|
+
return;
|
|
100
106
|
case "search":
|
|
101
107
|
commandHeader("search", "Hybrid semantic + keyword search.");
|
|
102
108
|
section("Usage");
|
|
@@ -172,17 +178,23 @@ export function printCommandHelp(command: string): void {
|
|
|
172
178
|
case "install":
|
|
173
179
|
commandHeader("install", "Interactive global agent setup.");
|
|
174
180
|
writeStdout("Configures MCP server, instructions, sub-agent files, and optional");
|
|
175
|
-
writeStdout("experimental integrations (search hooks, Caveman
|
|
181
|
+
writeStdout("experimental integrations (search hooks, Caveman, STE writing) under");
|
|
176
182
|
writeStdout("your user config (~/.claude, ~/.cursor, etc.).");
|
|
177
183
|
writeStdout("");
|
|
178
|
-
writeStdout(
|
|
184
|
+
writeStdout(
|
|
185
|
+
"Caveman = chat compression (/caveman). STE = clear docs (/ste). Off by default.",
|
|
186
|
+
);
|
|
187
|
+
writeStdout("Caveman is supported on all Miru installer IDEs (shared path for most IDEs).");
|
|
188
|
+
writeStdout(
|
|
189
|
+
"STE is supported on all Miru installer IDEs (same shared-path ownership model).",
|
|
190
|
+
);
|
|
179
191
|
writeStdout("Run miru setup first, or set TAKARA_API_KEY for MCP env expansion.");
|
|
180
192
|
writeStdout("");
|
|
181
193
|
return;
|
|
182
194
|
case "uninstall":
|
|
183
195
|
commandHeader("uninstall", "Remove miru configuration from agents.");
|
|
184
196
|
writeStdout("Removes MCP entries, marked instruction blocks, global sub-agents,");
|
|
185
|
-
writeStdout("and selected optional integrations (hooks, Caveman
|
|
197
|
+
writeStdout("and selected optional integrations (hooks, Caveman, STE skills).");
|
|
186
198
|
writeStdout("Also deletes the global benchmark report from Miru's state directory.");
|
|
187
199
|
writeStdout("");
|
|
188
200
|
return;
|