@zokizuan/satori-mcp 4.4.0 → 4.4.1

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
@@ -17,7 +17,7 @@ MCP server for Satori — agent-safe semantic code search and indexing.
17
17
  - Zod-first tool schemas converted to MCP JSON Schema for `ListTools`
18
18
  - Auto-generated tool docs from live tool schemas
19
19
  - `read_file` line-range retrieval with default large-file truncation guard and optional `mode="annotated"` metadata envelope
20
- - Optional proactive sync watcher mode (debounced filesystem events)
20
+ - Optional proactive sync watcher mode (debounced filesystem events for explicitly touched roots in the current session)
21
21
  - Index-time AST scope breadcrumbs (TS/JS/Python) rendered in search output as `🧬 Scope`
22
22
  - Fingerprint schema `dense_v3`/`hybrid_v3` with hard gate for all pre-v3 indexes
23
23
 
@@ -46,6 +46,7 @@ Tool surface is hard-broken to 6 tools. This keeps routing explicit while exposi
46
46
 
47
47
  - Enabled by default. Set `MCP_ENABLE_WATCHER=false` to disable
48
48
  - Debounce window via `MCP_WATCH_DEBOUNCE_MS` (default `5000`)
49
+ - Watchers are session-scoped: startup does not watch every indexed codebase, only roots touched by successful index/search/navigation/read flows in the current session
49
50
  - Watch events reuse the same incremental sync pipeline (`reindexByChange`)
50
51
  - Ignore control files (`.satoriignore`, root `.gitignore`) trigger no-reindex reconciliation:
51
52
  - delete indexed paths now ignored by active rules
@@ -156,7 +157,7 @@ No parameters.
156
157
  "mcpServers": {
157
158
  "satori": {
158
159
  "command": "npx",
159
- "args": ["-y", "@zokizuan/satori-mcp@latest"],
160
+ "args": ["-y", "@zokizuan/satori-mcp@4.4.1"],
160
161
  "timeout": 180000,
161
162
  "env": {
162
163
  "EMBEDDING_PROVIDER": "VoyageAI",
@@ -177,7 +178,7 @@ No parameters.
177
178
  ```toml
178
179
  [mcp_servers.satori]
179
180
  command = "npx"
180
- args = ["-y", "@zokizuan/satori-mcp@latest"]
181
+ args = ["-y", "@zokizuan/satori-mcp@4.4.1"]
181
182
  startup_timeout_ms = 180000
182
183
  env = { EMBEDDING_PROVIDER = "VoyageAI", EMBEDDING_MODEL = "voyage-4-large", EMBEDDING_OUTPUT_DIMENSION = "1024", VOYAGEAI_API_KEY = "your-api-key", VOYAGEAI_RERANKER_MODEL = "rerank-2.5", MILVUS_ADDRESS = "your-milvus-endpoint", MILVUS_TOKEN = "your-milvus-token" }
183
184
  ```
@@ -213,9 +214,30 @@ Never commit real API keys/tokens into repo config files.
213
214
  pnpm --filter @zokizuan/satori-mcp start
214
215
  ```
215
216
 
216
- ## Shell CLI (`satori-cli`)
217
+ ## Shell CLI (`@zokizuan/satori-cli`)
217
218
 
218
- `@zokizuan/satori-mcp` also ships a shell-first client binary that works without an MCP adapter.
219
+ The shell-first installer/client now lives in a separate package: `@zokizuan/satori-cli`.
220
+
221
+ ### Install / Uninstall
222
+
223
+ Supported installer targets in Phase 1:
224
+ - `codex`
225
+ - `claude`
226
+ - `all`
227
+
228
+ Examples:
229
+
230
+ ```bash
231
+ npx -y @zokizuan/satori-cli@0.1.1 install --client codex
232
+ npx -y @zokizuan/satori-cli@0.1.1 install --client claude
233
+ npx -y @zokizuan/satori-cli@0.1.1 install --client all --dry-run
234
+ npx -y @zokizuan/satori-cli@0.1.1 uninstall --client codex
235
+ ```
236
+
237
+ Install and uninstall run before MCP session startup, only touch Satori-managed config, and copy/remove these packaged skills:
238
+ - `satori-search`
239
+ - `satori-navigation`
240
+ - `satori-indexing`
219
241
 
220
242
  ### Commands
221
243
 
@@ -271,6 +293,8 @@ pnpm --filter @zokizuan/satori-mcp build
271
293
  pnpm --filter @zokizuan/satori-mcp typecheck
272
294
  pnpm --filter @zokizuan/satori-mcp test
273
295
  pnpm --filter @zokizuan/satori-mcp docs:check
296
+ pnpm --filter @zokizuan/satori-cli build
297
+ pnpm --filter @zokizuan/satori-cli test
274
298
  ```
275
299
 
276
300
  `build` automatically runs docs generation from tool schemas.
@@ -39,6 +39,7 @@ export class CliMcpSession {
39
39
  return createTimeout(this.client.callTool({ name, arguments: args }), this.callTimeoutMs, "E_CALL_TIMEOUT", `Timed out after ${this.callTimeoutMs}ms while calling tools/call for '${name}'.`);
40
40
  }
41
41
  async close() {
42
+ const stderr = this.transport.stderr;
42
43
  try {
43
44
  await this.client.close();
44
45
  }
@@ -51,6 +52,7 @@ export class CliMcpSession {
51
52
  catch {
52
53
  // Best-effort close.
53
54
  }
55
+ stderr?.removeAllListeners("data");
54
56
  }
55
57
  logProtocolFailure(error) {
56
58
  if (error instanceof CliError) {
@@ -79,7 +81,7 @@ export async function connectCliMcpSession(options) {
79
81
  });
80
82
  const client = new Client({
81
83
  name: "satori-cli",
82
- version: "1.1.0",
84
+ version: "1.1.1",
83
85
  });
84
86
  const session = new CliMcpSession(client, transport, options.callTimeoutMs, options.writeStderr);
85
87
  session.wireStderr();
@@ -10,6 +10,21 @@ interface RunCliOptions {
10
10
  startupTimeoutMs?: number;
11
11
  callTimeoutMs?: number;
12
12
  cwd?: string;
13
+ installabilityVerifier?: () => string | Promise<string>;
14
+ connectSession?: (options: {
15
+ command: string;
16
+ args: string[];
17
+ env: Record<string, string | undefined>;
18
+ cwd?: string;
19
+ startupTimeoutMs: number;
20
+ callTimeoutMs: number;
21
+ writeStderr: (text: string) => void;
22
+ }) => Promise<CliSession>;
23
+ }
24
+ interface CliSession {
25
+ listTools(): Promise<any>;
26
+ callTool(name: string, args: Record<string, unknown>): Promise<any>;
27
+ close(): Promise<void>;
13
28
  }
14
29
  export declare function runCli(argv: string[], options?: RunCliOptions): Promise<number>;
15
30
  export declare function isExecutedDirectlyForPaths(moduleUrl: string, entryPath: string | undefined): boolean;
package/dist/cli/index.js CHANGED
@@ -7,6 +7,7 @@ import { connectCliMcpSession } from "./client.js";
7
7
  import { asCliError, CliError } from "./errors.js";
8
8
  import { emitError, emitJson, inferManageStatusState, parseStructuredEnvelope } from "./format.js";
9
9
  import { executeInstallCommand } from "./install.js";
10
+ import { verifyManagedPackageInstallability } from "./package-installability.js";
10
11
  import { resolveServerEntryPath } from "./resolve-server-entry.js";
11
12
  const MANAGE_INDEX_MIN_POLL_TIMEOUT_MS = 10 * 60 * 1000;
12
13
  function firstText(result) {
@@ -195,6 +196,9 @@ export async function runCli(argv, options = {}) {
195
196
  return 0;
196
197
  }
197
198
  if (parsed.command.kind === "install" || parsed.command.kind === "uninstall") {
199
+ if (parsed.command.kind === "install") {
200
+ await (options.installabilityVerifier || verifyManagedPackageInstallability)();
201
+ }
198
202
  const result = executeInstallCommand(parsed.command, {
199
203
  homeDir: effectiveEnv.HOME,
200
204
  });
@@ -204,7 +208,7 @@ export async function runCli(argv, options = {}) {
204
208
  }
205
209
  return 0;
206
210
  }
207
- const session = await connectCliMcpSession({
211
+ const session = await (options.connectSession || connectCliMcpSession)({
208
212
  command: options.serverCommand || process.execPath,
209
213
  args: options.serverArgs || resolveDefaultServerArgs(),
210
214
  env: {
@@ -69,7 +69,7 @@ function buildCodexManagedBlock(packageSpecifier) {
69
69
  MANAGED_BLOCK_START,
70
70
  "[mcp_servers.satori]",
71
71
  'command = "npx"',
72
- `args = ["-y", "${packageSpecifier}"]`,
72
+ `args = ["-y", "--package", "${packageSpecifier}", "satori"]`,
73
73
  `startup_timeout_ms = ${MANAGED_TIMEOUT_MS}`,
74
74
  MANAGED_BLOCK_END,
75
75
  "",
@@ -153,7 +153,7 @@ function parseJsonObject(filePath) {
153
153
  function buildClaudeServerConfig(packageSpecifier) {
154
154
  return {
155
155
  command: "npx",
156
- args: ["-y", packageSpecifier],
156
+ args: ["-y", "--package", packageSpecifier, "satori"],
157
157
  timeout: MANAGED_TIMEOUT_MS,
158
158
  };
159
159
  }
@@ -168,12 +168,14 @@ function isManagedClaudeEntry(value) {
168
168
  if (entry.timeout !== MANAGED_TIMEOUT_MS) {
169
169
  return false;
170
170
  }
171
- if (!Array.isArray(entry.args) || entry.args.length !== 2) {
171
+ if (!Array.isArray(entry.args) || entry.args.length !== 4) {
172
172
  return false;
173
173
  }
174
174
  return entry.args[0] === "-y"
175
- && typeof entry.args[1] === "string"
176
- && /^@zokizuan\/satori-mcp@.+$/.test(entry.args[1]);
175
+ && entry.args[1] === "--package"
176
+ && typeof entry.args[2] === "string"
177
+ && /^@zokizuan\/satori-mcp@.+$/.test(entry.args[2])
178
+ && entry.args[3] === "satori";
177
179
  }
178
180
  function prepareClaudeInstall(filePath, packageSpecifier) {
179
181
  const currentObject = parseJsonObject(filePath);
@@ -0,0 +1,14 @@
1
+ import { execFileSync } from "node:child_process";
2
+ type ExecFileSyncLike = typeof execFileSync;
3
+ export interface PackageInstallabilityOptions {
4
+ packageJsonPath?: string;
5
+ execFileSyncImpl?: ExecFileSyncLike;
6
+ }
7
+ export interface ReleaseSmokeOptions extends PackageInstallabilityOptions {
8
+ packageRoot?: string;
9
+ tempDir?: string;
10
+ }
11
+ export declare function verifyManagedPackageInstallability(options?: PackageInstallabilityOptions): string;
12
+ export declare function runPublishedPackageReleaseSmoke(options?: ReleaseSmokeOptions): void;
13
+ export {};
14
+ //# sourceMappingURL=package-installability.d.ts.map
@@ -0,0 +1,124 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { execFileSync } from "node:child_process";
5
+ import { fileURLToPath } from "node:url";
6
+ import { CliError } from "./errors.js";
7
+ function resolveDefaultPackageJsonPath() {
8
+ const currentFile = fileURLToPath(import.meta.url);
9
+ return path.resolve(path.dirname(currentFile), "..", "..", "package.json");
10
+ }
11
+ function readPackageJson(packageJsonPath) {
12
+ return JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
13
+ }
14
+ function looksLikeExactVersion(value) {
15
+ return /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(value);
16
+ }
17
+ function npmOutput(error) {
18
+ if (!(error instanceof Error)) {
19
+ return String(error);
20
+ }
21
+ const stdout = "stdout" in error && typeof error.stdout === "string"
22
+ ? error.stdout
23
+ : "";
24
+ const stderr = "stderr" in error && typeof error.stderr === "string"
25
+ ? error.stderr
26
+ : "";
27
+ return `${stdout}\n${stderr}\n${error.message}`.trim();
28
+ }
29
+ function resolveWorkspaceDependencyVersion(packageJsonPath, dependencyName) {
30
+ const packageRoot = path.dirname(packageJsonPath);
31
+ const repoRoot = path.resolve(packageRoot, "..", "..");
32
+ const packagesRoot = path.join(repoRoot, "packages");
33
+ if (!fs.existsSync(packagesRoot)) {
34
+ return null;
35
+ }
36
+ for (const entry of fs.readdirSync(packagesRoot, { withFileTypes: true })) {
37
+ if (!entry.isDirectory()) {
38
+ continue;
39
+ }
40
+ const candidatePath = path.join(packagesRoot, entry.name, "package.json");
41
+ if (!fs.existsSync(candidatePath)) {
42
+ continue;
43
+ }
44
+ const candidate = readPackageJson(candidatePath);
45
+ if (candidate.name === dependencyName && looksLikeExactVersion(candidate.version)) {
46
+ return candidate.version;
47
+ }
48
+ }
49
+ return null;
50
+ }
51
+ function assertPublishedVersion(packageName, version, ownerPackageName, ownerPackageVersion, execImpl, relation) {
52
+ try {
53
+ execImpl("npm", ["view", `${packageName}@${version}`, "version", "--json"], {
54
+ encoding: "utf8",
55
+ stdio: ["ignore", "pipe", "pipe"],
56
+ });
57
+ }
58
+ catch (error) {
59
+ if (relation === "self") {
60
+ throw new CliError("E_USAGE", `Cannot install ${ownerPackageName}@${ownerPackageVersion} because that package version is not published on npm. Publish ${ownerPackageName}@${ownerPackageVersion} first or use a local dev server config instead.`, 2);
61
+ }
62
+ throw new CliError("E_USAGE", `Cannot install ${ownerPackageName}@${ownerPackageVersion} because required dependency ${packageName}@${version} is not published on npm. Publish ${packageName}@${version} first, then rerun satori-cli install.`, 2);
63
+ }
64
+ }
65
+ export function verifyManagedPackageInstallability(options = {}) {
66
+ const packageJsonPath = options.packageJsonPath ?? resolveDefaultPackageJsonPath();
67
+ const execImpl = options.execFileSyncImpl ?? execFileSync;
68
+ const pkg = readPackageJson(packageJsonPath);
69
+ const packageSpecifier = `${pkg.name}@${pkg.version}`;
70
+ assertPublishedVersion(pkg.name, pkg.version, pkg.name, pkg.version, execImpl, "self");
71
+ for (const [dependencyName, rawDependencyVersion] of Object.entries(pkg.dependencies ?? {})) {
72
+ const dependencyVersion = looksLikeExactVersion(rawDependencyVersion)
73
+ ? rawDependencyVersion
74
+ : rawDependencyVersion.startsWith("workspace:")
75
+ ? resolveWorkspaceDependencyVersion(packageJsonPath, dependencyName)
76
+ : null;
77
+ if (!dependencyVersion) {
78
+ continue;
79
+ }
80
+ assertPublishedVersion(dependencyName, dependencyVersion, pkg.name, pkg.version, execImpl, "dependency");
81
+ }
82
+ return packageSpecifier;
83
+ }
84
+ export function runPublishedPackageReleaseSmoke(options = {}) {
85
+ const packageJsonPath = options.packageJsonPath ?? resolveDefaultPackageJsonPath();
86
+ const packageRoot = options.packageRoot ?? path.dirname(packageJsonPath);
87
+ const tempDir = options.tempDir ?? os.tmpdir();
88
+ const execImpl = options.execFileSyncImpl ?? execFileSync;
89
+ verifyManagedPackageInstallability({ packageJsonPath, execFileSyncImpl: execImpl });
90
+ const smokePackDir = fs.mkdtempSync(path.join(tempDir, "satori-release-smoke-"));
91
+ const smokeExecDir = fs.mkdtempSync(path.join(tempDir, "satori-release-exec-"));
92
+ const beforeFiles = new Set(fs.readdirSync(smokePackDir));
93
+ execImpl("pnpm", ["pack", "--pack-destination", smokePackDir], {
94
+ cwd: packageRoot,
95
+ encoding: "utf8",
96
+ stdio: ["ignore", "pipe", "pipe"],
97
+ });
98
+ const tarballName = fs.readdirSync(smokePackDir).find((entry) => entry.endsWith(".tgz") && !beforeFiles.has(entry));
99
+ if (!tarballName) {
100
+ throw new CliError("E_USAGE", "Release smoke failed: pnpm pack did not produce a tarball.", 2);
101
+ }
102
+ const tarballPath = path.join(smokePackDir, tarballName);
103
+ try {
104
+ execImpl("npm", ["exec", "--yes", "--package", tarballPath, "--", "satori", "--help"], {
105
+ cwd: smokeExecDir,
106
+ encoding: "utf8",
107
+ env: {
108
+ ...process.env,
109
+ npm_config_package_lock: "false",
110
+ },
111
+ stdio: ["ignore", "pipe", "pipe"],
112
+ });
113
+ }
114
+ catch (error) {
115
+ const output = npmOutput(error);
116
+ const pkg = readPackageJson(packageJsonPath);
117
+ throw new CliError("E_USAGE", `Release smoke failed for ${pkg.name}@${pkg.version}. The packed tarball did not start via 'npm exec --yes --package <tarball> -- satori --help'. ${output}`, 2);
118
+ }
119
+ finally {
120
+ fs.rmSync(smokePackDir, { recursive: true, force: true });
121
+ fs.rmSync(smokeExecDir, { recursive: true, force: true });
122
+ }
123
+ }
124
+ //# sourceMappingURL=package-installability.js.map
package/dist/config.js CHANGED
@@ -169,7 +169,7 @@ export function showHelpMessage() {
169
169
  console.log(`
170
170
  Satori MCP Server
171
171
 
172
- Usage: npx @zokizuan/satori-mcp@latest [options]
172
+ Usage: npx -y @zokizuan/satori-mcp@4.4.1 [options]
173
173
 
174
174
  Options:
175
175
  --help, -h Show this help message
@@ -206,16 +206,16 @@ Environment Variables:
206
206
 
207
207
  Examples:
208
208
  # Start MCP server with OpenAI and explicit Milvus address
209
- OPENAI_API_KEY=sk-xxx MILVUS_ADDRESS=localhost:19530 npx @zokizuan/satori-mcp@latest
209
+ OPENAI_API_KEY=sk-xxx MILVUS_ADDRESS=localhost:19530 npx -y @zokizuan/satori-mcp@4.4.1
210
210
 
211
211
  # Start MCP server with VoyageAI and specific model
212
- EMBEDDING_PROVIDER=VoyageAI VOYAGEAI_API_KEY=pa-xxx EMBEDDING_MODEL=voyage-4-large MILVUS_TOKEN=your-token npx @zokizuan/satori-mcp@latest
212
+ EMBEDDING_PROVIDER=VoyageAI VOYAGEAI_API_KEY=pa-xxx EMBEDDING_MODEL=voyage-4-large MILVUS_TOKEN=your-token npx -y @zokizuan/satori-mcp@4.4.1
213
213
 
214
214
  # Start MCP server with Gemini and specific model
215
- EMBEDDING_PROVIDER=Gemini GEMINI_API_KEY=xxx EMBEDDING_MODEL=gemini-embedding-001 MILVUS_TOKEN=your-token npx @zokizuan/satori-mcp@latest
215
+ EMBEDDING_PROVIDER=Gemini GEMINI_API_KEY=xxx EMBEDDING_MODEL=gemini-embedding-001 MILVUS_TOKEN=your-token npx -y @zokizuan/satori-mcp@4.4.1
216
216
 
217
217
  # Start MCP server with Ollama and specific model
218
- EMBEDDING_PROVIDER=Ollama EMBEDDING_MODEL=nomic-embed-text MILVUS_TOKEN=your-token npx @zokizuan/satori-mcp@latest
218
+ EMBEDDING_PROVIDER=Ollama EMBEDDING_MODEL=nomic-embed-text MILVUS_TOKEN=your-token npx -y @zokizuan/satori-mcp@4.4.1
219
219
  `);
220
220
  }
221
221
  //# sourceMappingURL=config.js.map
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@zokizuan/satori-mcp",
3
- "version": "4.4.0",
3
+ "version": "4.4.1",
4
4
  "description": "MCP server for Satori with agent-safe semantic search and indexing",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "bin": {
9
- "satori": "dist/index.js",
10
- "satori-cli": "dist/cli/index.js"
9
+ "satori": "dist/index.js"
11
10
  },
12
11
  "dependencies": {
13
12
  "@modelcontextprotocol/sdk": "^1.12.1",
@@ -15,7 +14,7 @@
15
14
  "ignore": "^7.0.5",
16
15
  "zod": "^3.25.55",
17
16
  "zod-to-json-schema": "^3.25.1",
18
- "@zokizuan/satori-core": "1.1.0"
17
+ "@zokizuan/satori-core": "1.1.1"
19
18
  },
20
19
  "devDependencies": {
21
20
  "@types/node": "^20.0.0",
@@ -25,7 +24,6 @@
25
24
  "files": [
26
25
  "dist/**/*.js",
27
26
  "dist/**/*.d.ts",
28
- "assets/skills/**/*.md",
29
27
  "README.md"
30
28
  ],
31
29
  "repository": {
@@ -44,6 +42,7 @@
44
42
  },
45
43
  "scripts": {
46
44
  "build": "pnpm clean && tsc --build --force && pnpm fix:bin-perms && pnpm docs:generate && pnpm manifest:generate",
45
+ "build:runtime": "pnpm clean && tsc --build --force && pnpm fix:bin-perms",
47
46
  "dev": "tsx --watch src/index.ts",
48
47
  "clean": "rimraf dist",
49
48
  "lint": "eslint src --ext .ts",
@@ -55,7 +54,8 @@
55
54
  "docs:check": "tsx scripts/generate-docs.ts --check",
56
55
  "manifest:generate": "tsx scripts/generate-server-manifest.ts",
57
56
  "manifest:check": "tsx scripts/generate-server-manifest.ts --check",
58
- "fix:bin-perms": "node -e \"const fs=require('fs');try{fs.chmodSync('dist/index.js',0o755);fs.chmodSync('dist/cli/index.js',0o755);}catch(e){console.error(e);process.exit(1);}\"",
59
- "test": "pnpm --filter @zokizuan/satori-core build && tsx --test --test-concurrency=1 src/**/*.test.ts"
57
+ "release:smoke": "tsx scripts/release-smoke.ts",
58
+ "fix:bin-perms": "node -e \"const fs=require('fs');try{fs.chmodSync('dist/index.js',0o755);}catch(e){console.error(e);process.exit(1);}\"",
59
+ "test": "pnpm --filter @zokizuan/satori-core build && node --import tsx --test --test-concurrency=1 src/core/**/*.test.ts src/server/**/*.test.ts src/tools/**/*.test.ts src/cli/**/*.test.ts"
60
60
  }
61
61
  }
@@ -1,36 +0,0 @@
1
- ---
2
- name: satori-indexing
3
- description: Index lifecycle and remediation for Satori. Use when codebases are not indexed, stale, blocked, or need freshness recovery.
4
- ---
5
-
6
- # Satori Indexing
7
-
8
- Use this skill when the task is to create, reindex, sync, inspect readiness, or recover from stale index state.
9
-
10
- ## Tools
11
-
12
- Use only:
13
- 1. `list_codebases`
14
- 2. `manage_index`
15
-
16
- ## Workflow
17
-
18
- 1. Use `list_codebases` for a global view of tracked roots.
19
- 2. Use `manage_index(action="status", path=...)` for the specific codebase.
20
- 3. Use `manage_index(action="create", path=...)` when the codebase is not indexed.
21
- 4. Use `manage_index(action="reindex", path=...)` only for compatibility gates or explicit rebuilds.
22
- 5. Use `manage_index(action="sync", path=...)` for freshness convergence and ignore-rule updates.
23
-
24
- ## Rules
25
-
26
- - If any tool returns `requires_reindex`, stop and reindex. Do not substitute `sync`.
27
- - Never call `manage_index(action="clear")` unless the user explicitly requests destructive reset.
28
- - Treat ignore-only churn as a `sync` problem first.
29
- - Respect blocked and indexing states instead of forcing retries blindly.
30
-
31
- ## Status Handling
32
-
33
- - `requires_reindex`: run `manage_index(action="reindex")`.
34
- - `not_ready` with indexing reason: check status and wait for terminal completion.
35
- - `not_indexed`: create the index.
36
- - Ignore-rule noise mitigation: update `.satoriignore`, wait debounce, and run `sync` for immediate convergence.
@@ -1,36 +0,0 @@
1
- ---
2
- name: satori-navigation
3
- description: Deterministic symbol navigation with Satori. Use after search results are found to lock exact spans and inspect call relationships.
4
- ---
5
-
6
- # Satori Navigation
7
-
8
- Use this skill after `search_codebase` has returned candidate results and you need exact symbol/file navigation.
9
-
10
- ## Tools
11
-
12
- Use only:
13
- 1. `file_outline`
14
- 2. `call_graph`
15
- 3. `read_file`
16
-
17
- ## Workflow
18
-
19
- 1. Use grouped `search_codebase` results as the starting point.
20
- 2. If `callGraphHint.supported=true`, call `call_graph(path=..., symbolRef=..., direction="both", depth=1)`.
21
- 3. If `callGraphHint.supported=false`, execute `navigationFallback.readSpan.args` exactly.
22
- 4. Use `file_outline(resolveMode="exact", symbolIdExact|symbolLabelExact)` to lock the symbol span.
23
- 5. Use `read_file(path=..., open_symbol=...)` or deterministic line spans for the final read.
24
-
25
- ## Rules
26
-
27
- - Treat `navigationFallback` as authoritative. Do not invent spans.
28
- - `open_symbol` must resolve deterministically. Do not guess on ambiguity.
29
- - `read_file(mode="annotated")` is preferred when outline metadata is useful.
30
- - Follow continuation hints when plain reads are truncated.
31
-
32
- ## Remediation
33
-
34
- - `requires_reindex`: reindex before retrying navigation.
35
- - `not_ready`: wait for indexing to finish.
36
- - `unsupported`: fall back to deterministic `read_file` spans when supplied by `navigationFallback`.
@@ -1,36 +0,0 @@
1
- ---
2
- name: satori-search
3
- description: Semantic-first code search with Satori. Use for intent-based code discovery before file reads or grep.
4
- ---
5
-
6
- # Satori Search
7
-
8
- Use this skill when the task is to find where behavior lives, identify candidate symbols, or narrow the search space before deeper navigation.
9
-
10
- ## Tools
11
-
12
- Use only:
13
- 1. `list_codebases`
14
- 2. `manage_index`
15
- 3. `search_codebase`
16
-
17
- ## Workflow
18
-
19
- 1. Check readiness with `manage_index(action="status", path=...)`.
20
- 2. If not indexed, use `manage_index(action="create", path=...)`.
21
- 3. If `requires_reindex` appears, stop and use `manage_index(action="reindex", path=...)`, then retry.
22
- 4. Search with `search_codebase(path=..., query=..., scope="runtime", resultMode="grouped", groupBy="symbol", rankingMode="auto_changed_first")`.
23
-
24
- ## Search Rules
25
-
26
- - Start with natural-language intent, not filenames.
27
- - Default to `scope="runtime"`.
28
- - Use operators only when needed: `lang:`, `path:`, `-path:`, `must:`, `exclude:`.
29
- - Treat warnings as usable-but-degraded results, not fatal errors.
30
- - Use `debug=true` only when ranking or filter explanations are required.
31
-
32
- ## Remediation
33
-
34
- - `requires_reindex`: run `manage_index(action="reindex")`, not `sync`.
35
- - `not_ready` with indexing reason: wait or check `manage_index(action="status")`.
36
- - Noise mitigation hint: update `.satoriignore`, wait debounce, rerun search, and use `manage_index(action="sync")` only for immediate convergence.