@ninjaxtools/slopdex 0.18.0 → 0.20.0

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.
Files changed (62) hide show
  1. package/.gitignore +2 -0
  2. package/README.md +136 -48
  3. package/binary-install.js +348 -0
  4. package/binary.js +124 -0
  5. package/install.js +4 -0
  6. package/npm-shrinkwrap.json +52 -0
  7. package/package.json +78 -62
  8. package/run-slopdex.js +4 -0
  9. package/.agents/skills/slopdex/SKILL.md +0 -241
  10. package/dist/chunk-6LHZCHEB.js +0 -1112
  11. package/dist/chunk-6LHZCHEB.js.map +0 -1
  12. package/dist/chunk-BXWO2KMC.js +0 -20
  13. package/dist/chunk-BXWO2KMC.js.map +0 -1
  14. package/dist/chunk-DKRB2XT5.js +0 -33
  15. package/dist/chunk-DKRB2XT5.js.map +0 -1
  16. package/dist/chunk-DTI7SXGL.js +0 -109
  17. package/dist/chunk-DTI7SXGL.js.map +0 -1
  18. package/dist/chunk-IQU3YVZ3.js +0 -85
  19. package/dist/chunk-IQU3YVZ3.js.map +0 -1
  20. package/dist/chunk-JAVPHCZH.js +0 -24
  21. package/dist/chunk-JAVPHCZH.js.map +0 -1
  22. package/dist/chunk-KQRS5P4U.js +0 -10
  23. package/dist/chunk-KQRS5P4U.js.map +0 -1
  24. package/dist/chunk-KUV6PKKL.js +0 -425
  25. package/dist/chunk-KUV6PKKL.js.map +0 -1
  26. package/dist/chunk-MKUTTXZB.js +0 -74
  27. package/dist/chunk-MKUTTXZB.js.map +0 -1
  28. package/dist/chunk-N6D66ASM.js +0 -2217
  29. package/dist/chunk-N6D66ASM.js.map +0 -1
  30. package/dist/chunk-OIKBO3NJ.js +0 -133
  31. package/dist/chunk-OIKBO3NJ.js.map +0 -1
  32. package/dist/chunk-S225GYCL.js +0 -79
  33. package/dist/chunk-S225GYCL.js.map +0 -1
  34. package/dist/chunk-TSURHRFF.js +0 -240
  35. package/dist/chunk-TSURHRFF.js.map +0 -1
  36. package/dist/chunk-VH5VGRCI.js +0 -103
  37. package/dist/chunk-VH5VGRCI.js.map +0 -1
  38. package/dist/cli.d.ts +0 -1
  39. package/dist/cli.js +0 -1130
  40. package/dist/cli.js.map +0 -1
  41. package/dist/code-index-YEFTNG7E.js +0 -14
  42. package/dist/code-index-YEFTNG7E.js.map +0 -1
  43. package/dist/cross-search-FVKDMGP7.js +0 -10
  44. package/dist/cross-search-FVKDMGP7.js.map +0 -1
  45. package/dist/database-KAPV2YMP.js +0 -14
  46. package/dist/database-KAPV2YMP.js.map +0 -1
  47. package/dist/hosted-GHIUHKOU.js +0 -13
  48. package/dist/hosted-GHIUHKOU.js.map +0 -1
  49. package/dist/index.d.ts +0 -681
  50. package/dist/index.js +0 -102
  51. package/dist/index.js.map +0 -1
  52. package/dist/jina-43RL7C6M.js +0 -12
  53. package/dist/jina-43RL7C6M.js.map +0 -1
  54. package/dist/openai-CYUPNBGB.js +0 -12
  55. package/dist/openai-CYUPNBGB.js.map +0 -1
  56. package/dist/openai-EC6THXKV.js +0 -21
  57. package/dist/openai-EC6THXKV.js.map +0 -1
  58. package/dist/openai-TCRXM66O.js +0 -11
  59. package/dist/openai-TCRXM66O.js.map +0 -1
  60. package/docs/implementation.md +0 -162
  61. package/docs/reference.md +0 -187
  62. package/scripts/install-opencode-skill.mjs +0 -11
package/binary.js ADDED
@@ -0,0 +1,124 @@
1
+ const { Package } = require("./binary-install");
2
+ const os = require("os");
3
+ const libc = require("detect-libc");
4
+
5
+ const error = (msg) => {
6
+ console.error(msg);
7
+ process.exit(1);
8
+ };
9
+
10
+ const {
11
+ name,
12
+ artifactDownloadUrls,
13
+ supportedPlatforms,
14
+ glibcMinimum,
15
+ } = require("./package.json");
16
+
17
+ // FIXME: implement NPM installer handling of fallback download URLs
18
+ const artifactDownloadUrl = artifactDownloadUrls[0];
19
+ const builderGlibcMajorVersion = glibcMinimum.major;
20
+ const builderGlibcMinorVersion = glibcMinimum.series;
21
+
22
+ const getPlatform = () => {
23
+ const rawOsType = os.type();
24
+ const rawArchitecture = os.arch();
25
+
26
+ // We want to use rust-style target triples as the canonical key
27
+ // for a platform, so translate the "os" library's concepts into rust ones
28
+ let osType = "";
29
+ switch (rawOsType) {
30
+ case "Windows_NT":
31
+ osType = "pc-windows-msvc";
32
+ break;
33
+ case "Darwin":
34
+ osType = "apple-darwin";
35
+ break;
36
+ case "Linux":
37
+ osType = "unknown-linux-gnu";
38
+ break;
39
+ }
40
+
41
+ let arch = "";
42
+ switch (rawArchitecture) {
43
+ case "x64":
44
+ arch = "x86_64";
45
+ break;
46
+ case "arm64":
47
+ arch = "aarch64";
48
+ break;
49
+ }
50
+
51
+ if (rawOsType === "Linux") {
52
+ if (libc.familySync() == "musl") {
53
+ osType = "unknown-linux-musl-dynamic";
54
+ } else if (libc.isNonGlibcLinuxSync()) {
55
+ console.warn(
56
+ "Your libc is neither glibc nor musl; trying static musl binary instead",
57
+ );
58
+ osType = "unknown-linux-musl-static";
59
+ } else {
60
+ let libcVersion = libc.versionSync();
61
+ let splitLibcVersion = libcVersion.split(".");
62
+ let libcMajorVersion = splitLibcVersion[0];
63
+ let libcMinorVersion = splitLibcVersion[1];
64
+ if (
65
+ libcMajorVersion != builderGlibcMajorVersion ||
66
+ libcMinorVersion < builderGlibcMinorVersion
67
+ ) {
68
+ // We can't run the glibc binaries, but we can run the static musl ones
69
+ // if they exist
70
+ console.warn(
71
+ "Your glibc isn't compatible; trying static musl binary instead",
72
+ );
73
+ osType = "unknown-linux-musl-static";
74
+ }
75
+ }
76
+ }
77
+
78
+ // Assume the above succeeded and build a target triple to look things up with.
79
+ // If any of it failed, this lookup will fail and we'll handle it like normal.
80
+ let targetTriple = `${arch}-${osType}`;
81
+ let platform = supportedPlatforms[targetTriple];
82
+
83
+ if (!platform) {
84
+ error(
85
+ `Platform with type "${rawOsType}" and architecture "${rawArchitecture}" is not supported by ${name}.\nYour system must be one of the following:\n\n${Object.keys(
86
+ supportedPlatforms,
87
+ ).join(",")}`,
88
+ );
89
+ }
90
+
91
+ return platform;
92
+ };
93
+
94
+ const getPackage = () => {
95
+ const platform = getPlatform();
96
+ const url = `${artifactDownloadUrl}/${platform.artifactName}`;
97
+ let filename = platform.artifactName;
98
+ let ext = platform.zipExt;
99
+ let binary = new Package(platform, name, url, filename, ext, platform.bins);
100
+
101
+ return binary;
102
+ };
103
+
104
+ const install = (suppressLogs) => {
105
+ if (!artifactDownloadUrl || artifactDownloadUrl.length === 0) {
106
+ console.warn("in demo mode, not installing binaries");
107
+ return;
108
+ }
109
+ const pkg = getPackage();
110
+
111
+ return pkg.install(suppressLogs);
112
+ };
113
+
114
+ const run = (binaryName) => {
115
+ const pkg = getPackage();
116
+
117
+ pkg.run(binaryName);
118
+ };
119
+
120
+ module.exports = {
121
+ install,
122
+ run,
123
+ getPackage,
124
+ };
package/install.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { install } = require("./binary");
4
+ install(false);
@@ -0,0 +1,52 @@
1
+ {
2
+ "lockfileVersion": 3,
3
+ "name": "@ninjaxtools/slopdex",
4
+ "packages": {
5
+ "": {
6
+ "bin": {
7
+ "slopdex": "run-slopdex.js"
8
+ },
9
+ "dependencies": {
10
+ "detect-libc": "^2.1.2"
11
+ },
12
+ "devDependencies": {
13
+ "prettier": "^3.8.3"
14
+ },
15
+ "engines": {
16
+ "node": ">=14.14",
17
+ "npm": ">=6"
18
+ },
19
+ "hasInstallScript": true,
20
+ "license": "MIT",
21
+ "name": "@ninjaxtools/slopdex",
22
+ "version": "0.20.0"
23
+ },
24
+ "node_modules/detect-libc": {
25
+ "engines": {
26
+ "node": ">=8"
27
+ },
28
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
29
+ "license": "Apache-2.0",
30
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
31
+ "version": "2.1.2"
32
+ },
33
+ "node_modules/prettier": {
34
+ "bin": {
35
+ "prettier": "bin/prettier.cjs"
36
+ },
37
+ "dev": true,
38
+ "engines": {
39
+ "node": ">=14"
40
+ },
41
+ "funding": {
42
+ "url": "https://github.com/prettier/prettier?sponsor=1"
43
+ },
44
+ "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==",
45
+ "license": "MIT",
46
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz",
47
+ "version": "3.8.3"
48
+ }
49
+ },
50
+ "requires": true,
51
+ "version": "0.20.0"
52
+ }
package/package.json CHANGED
@@ -1,72 +1,88 @@
1
1
  {
2
- "name": "@ninjaxtools/slopdex",
3
- "version": "0.18.0",
4
- "description": "Tree-sitter callable-level semantic indexing, search, and duplicate discovery for Python, JavaScript, TypeScript, Rust, Go, Java, and C",
5
- "license": "MIT",
6
- "repository": {
7
- "type": "git",
8
- "url": "https://github.com/ninjaxtools/slopdex.git"
2
+ "artifactDownloadUrls": [
3
+ "https://github.com/ninjaxtools/slopdex/releases/download/v0.20.0"
4
+ ],
5
+ "bin": {
6
+ "slopdex": "run-slopdex.js"
9
7
  },
10
- "type": "module",
11
- "main": "dist/index.js",
12
- "types": "dist/index.d.ts",
13
- "exports": {
14
- ".": {
15
- "types": "./dist/index.d.ts",
16
- "import": "./dist/index.js"
17
- }
8
+ "dependencies": {
9
+ "detect-libc": "^2.1.2"
18
10
  },
19
- "bin": {
20
- "slopdex": "dist/cli.js"
11
+ "description": "Semantic code and Markdown search with SQLite and USearch",
12
+ "devDependencies": {
13
+ "prettier": "^3.8.3"
21
14
  },
22
- "files": [
23
- ".agents/skills/slopdex/SKILL.md",
24
- "dist",
25
- "docs/implementation.md",
26
- "docs/reference.md",
27
- "README.md",
28
- "scripts/install-opencode-skill.mjs"
29
- ],
30
15
  "engines": {
31
- "node": ">=24.0.0"
16
+ "node": ">=14.14",
17
+ "npm": ">=6"
18
+ },
19
+ "glibcMinimum": {
20
+ "major": 2,
21
+ "series": 39
32
22
  },
23
+ "license": "MIT",
24
+ "name": "@ninjaxtools/slopdex",
25
+ "preferUnplugged": true,
26
+ "repository": "https://github.com/ninjaxtools/slopdex",
33
27
  "scripts": {
34
- "build": "tsup",
35
- "dev": "tsx src/cli.ts",
36
- "typecheck": "tsc --noEmit",
37
- "test": "vitest",
38
- "test:run": "vitest run",
39
- "smoke": "node scripts/smoke.mjs",
40
- "install:skill:opencode": "node scripts/install-opencode-skill.mjs",
41
- "install:local": "npm run build && npm install -g .",
42
- "publish:minor": "npm version minor && npm publish --access public",
43
- "prepack": "npm run build && npm run smoke",
44
- "check": "npm run typecheck && npm run test:run && npm run build && npm run smoke"
28
+ "fmt": "prettier --write **/*.js",
29
+ "fmt:check": "prettier --check **/*.js",
30
+ "postinstall": "node ./install.js"
45
31
  },
46
- "dependencies": {
47
- "@ai-sdk/anthropic": "^4.0.53",
48
- "@ai-sdk/google": "^4.0.69",
49
- "@ai-sdk/openai": "^4.0.66",
50
- "@ai-sdk/openai-compatible": "^3.0.48",
51
- "ai": "^7.0.99",
52
- "ignore": "^7.0.9",
53
- "install": "^0.13.0",
54
- "js-tiktoken": "^1.0.21",
55
- "sqlite-vec": "^0.1.9",
56
- "tree-sitter": "^0.21.1",
57
- "tree-sitter-c": "0.21.4",
58
- "tree-sitter-go": "0.23.4",
59
- "tree-sitter-java": "0.23.5",
60
- "tree-sitter-javascript": "^0.23.1",
61
- "tree-sitter-python": "0.23.2",
62
- "tree-sitter-rust": "0.21.0",
63
- "tree-sitter-typescript": "^0.23.2"
32
+ "supportedPlatforms": {
33
+ "aarch64-apple-darwin": {
34
+ "artifactName": "slopdex-aarch64-apple-darwin.tar.xz",
35
+ "bins": {
36
+ "slopdex": "slopdex"
37
+ },
38
+ "zipExt": ".tar.xz"
39
+ },
40
+ "aarch64-pc-windows-msvc": {
41
+ "artifactName": "slopdex-x86_64-pc-windows-msvc.zip",
42
+ "bins": {
43
+ "slopdex": "slopdex.exe"
44
+ },
45
+ "zipExt": ".zip"
46
+ },
47
+ "aarch64-unknown-linux-gnu": {
48
+ "artifactName": "slopdex-aarch64-unknown-linux-gnu.tar.xz",
49
+ "bins": {
50
+ "slopdex": "slopdex"
51
+ },
52
+ "zipExt": ".tar.xz"
53
+ },
54
+ "x86_64-apple-darwin": {
55
+ "artifactName": "slopdex-x86_64-apple-darwin.tar.xz",
56
+ "bins": {
57
+ "slopdex": "slopdex"
58
+ },
59
+ "zipExt": ".tar.xz"
60
+ },
61
+ "x86_64-pc-windows-gnu": {
62
+ "artifactName": "slopdex-x86_64-pc-windows-msvc.zip",
63
+ "bins": {
64
+ "slopdex": "slopdex.exe"
65
+ },
66
+ "zipExt": ".zip"
67
+ },
68
+ "x86_64-pc-windows-msvc": {
69
+ "artifactName": "slopdex-x86_64-pc-windows-msvc.zip",
70
+ "bins": {
71
+ "slopdex": "slopdex.exe"
72
+ },
73
+ "zipExt": ".zip"
74
+ },
75
+ "x86_64-unknown-linux-gnu": {
76
+ "artifactName": "slopdex-x86_64-unknown-linux-gnu.tar.xz",
77
+ "bins": {
78
+ "slopdex": "slopdex"
79
+ },
80
+ "zipExt": ".tar.xz"
81
+ }
64
82
  },
65
- "devDependencies": {
66
- "@types/node": "^24.0.0",
67
- "tsup": "^8.5.0",
68
- "tsx": "^4.20.0",
69
- "typescript": "^5.9.0",
70
- "vitest": "^3.2.0"
83
+ "version": "0.20.0",
84
+ "volta": {
85
+ "node": "18.14.1",
86
+ "npm": "9.5.0"
71
87
  }
72
- }
88
+ }
package/run-slopdex.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { run } = require("./binary");
4
+ run("slopdex");
@@ -1,241 +0,0 @@
1
- ---
2
- name: slopdex
3
- description: Semantic code search, duplicate-function candidates, and physical-distance re-ranking
4
- ---
5
-
6
- # Slopdex operator guide for agents
7
-
8
- Slopdex does semantic code search, finds similar-code candidates, and identifies related functions stored far apart.
9
-
10
- ### Find code by meaning
11
-
12
- ```bash
13
- slopdex search "validate an authenticated session" --format summary --limit 10
14
- slopdex search "persist user data" -e 'save|persist' --format summary --limit 5
15
- ```
16
-
17
- Describe behavior rather than guessing a symbol name. `-e` is a regex that restricts which symbols (functions) are searched.
18
-
19
- Hosted reranking is optional and persists in repository config:
20
-
21
- ```bash
22
- slopdex config reranker cohere
23
- # Or: slopdex config reranker jina
24
- # Or use an LLM: slopdex config reranker openai
25
- ```
26
-
27
- Set `COHERE_API_KEY`, `JINA_API_KEY`, or `OPENAI_API_KEY` respectively. The OpenAI LLM reranker defaults to `gpt-5.6-luna`, high reasoning, and the top 10 embedding candidates; configure the pool with `slopdex config reranker openai --reranker-candidates 20`. Disable reranking with `slopdex config reranker disable`. Reranking applies to `search` and `search-description`, not cross-search. It preserves embedding `similarity`, adds `rerankScore`, and orders a wider candidate set by that score.
28
-
29
- ### Search function purpose
30
-
31
- Code purpose-description generation needs to be enabled once:
32
-
33
- ```bash
34
- slopdex descriptions enable # only needed once
35
- ```
36
-
37
- Then purpose descriptions can be searched:
38
-
39
- ```bash
40
- slopdex search-description "keep the repository index synchronized" --format summary --limit 10
41
- ```
42
-
43
- Enabling needs `OPENAI_API_KEY` by default. Select OpenCode Zen or Go with
44
- `--description-provider opencode` or `--description-provider opencode-go` and set `OPENCODE_API_KEY`
45
- or sign in with `opencode auth login`, which stores the key in `~/.local/share/opencode/auth.json`.
46
-
47
- To select another model:
48
-
49
- ```bash
50
- slopdex descriptions enable --description-model <model-id>
51
- ```
52
-
53
- List and persist a published OpenCode model without creating an index:
54
-
55
- ```bash
56
- slopdex models opencode-go
57
- slopdex config model opencode-go/gpt-5.6-luna
58
- slopdex config descriptions enable
59
- ```
60
-
61
- The next index-using command applies the configured description state. A bare model ID passed to
62
- `config model` resolves automatically only when it belongs to one of Zen or Go; qualify shared IDs.
63
-
64
- ### Find duplicate candidates
65
-
66
- ```bash
67
- slopdex cross-search --cross-file-only --min-lines 4 --threshold 0.9 --matches 5 --limit 5
68
- ```
69
-
70
- The default output is connected clusters. This excludes same-file matches and short functions, keeps 5 matches per source, and emits at most 5 clusters. For source-by-source matches, add `--format summary`. `--limit` caps emitted clusters/sources (unlimited by default); `--matches` caps matches per source (default 5).
71
-
72
- Broaden discovery through adjacent score bands when needed:
73
-
74
- ```bash
75
- slopdex cross-search --cross-file-only --min-lines 4 --threshold 0.85-0.9 --matches 5
76
- slopdex cross-search --cross-file-only --min-lines 4 --threshold 0.8-0.85 --matches 5
77
- ```
78
-
79
- Ranges include the lower bound and exclude the upper bound. Use `--min-lines 1` when one-line wrappers are relevant.
80
-
81
- ### Review changes or a module
82
-
83
- ```bash
84
- slopdex cross-search --uncommitted --cross-file-only --min-lines 4 --threshold 0.9
85
- slopdex cross-search --changed-since origin/main --format summary --threshold 0.9
86
- slopdex cross-search --source-path src/services -e '^UserService\.' --format summary --threshold 0.9
87
- ```
88
-
89
- These restrict sources while searching the full eligible index. All supplied restrictions intersect:
90
-
91
- ```bash
92
- slopdex cross-search --source-path src -e 'validate' \
93
- --changed-since origin/main --uncommitted \
94
- --cross-file-only --min-lines 4 --threshold 0.9
95
- ```
96
-
97
- Here a source must have changed since the commit and belong to an uncommitted file, within the selected path/name scope. `--regex` is an alias for `-e/--regexp`.
98
-
99
- ### Review physical cohesion
100
-
101
- ```bash
102
- slopdex cross-search --cohesion --threshold 0.8 --matches 20 --format summary
103
- slopdex cross-search --cohesion --source-path src/services --threshold 0.8 --format summary
104
- ```
105
-
106
- `--cohesion` keeps cross-search's semantic matches and orders each source's matches from greatest to least physical path distance. Similarity breaks distance ties. Summary output includes the distance; JSONL matches include `physicalDistance`.
107
-
108
- ### Compare repositories
109
-
110
- ```bash
111
- slopdex cross-search \
112
- --target-root /path/to/other/repo \
113
- --target-index /path/to/other/repo/.slopdex/index.sqlite \
114
- --threshold 0.9 --format summary
115
- ```
116
-
117
- Both target options are required. Both indexes refresh and must have identical embedding profiles. The target refresh uses the source command's embedding provider and the target's file-selection/description configuration. Use `--target-config <path>` for a custom target config.
118
-
119
- ### Inspect or maintain the index
120
-
121
- ```bash
122
- slopdex status
123
- slopdex index-errors --format summary
124
- slopdex update-git
125
- slopdex update-files src/service.ts src/model.ts
126
- slopdex reindex-files
127
- slopdex reindex-files --callables
128
- slopdex delete-files src/removed.ts
129
- slopdex --version
130
- ```
131
-
132
- - `status` refreshes, then reports coverage, checkpoint, profiles, and error counts; use when metadata is requested.
133
- - `index-errors` reads saved failures without refreshing or needing API credentials.
134
- - `update-git` explicitly refreshes HEAD and working-tree changes.
135
- - `update-files` reparses specified working-tree files after automatic refresh, even when their contents are unchanged.
136
- - `reindex-files` regenerates stale file descriptions and embeddings. Add `--callables` to also replace callable descriptions in those files.
137
- - `delete-files` removes index entries after automatic refresh, not source files. Eligible files can return on later refresh.
138
- - `--version` prints the built package version. `--help` describes available commands/options.
139
-
140
- ## Command-line reference
141
-
142
- Usage: `slopdex <command> [arguments] [options]`. Quote queries and regexes. Boolean flags default to off. Use options only with their applicable commands.
143
-
144
- ### General settings
145
-
146
- | Argument | Meaning / default |
147
- | --- | --- |
148
- | `--root <path>` | Repository root; current directory by default. |
149
- | `--config <path>` | Config; `<root>/.slopdex/config.json`. |
150
- | `--index <path>` | Index; `<root>/.slopdex/index.sqlite`. Overrides config `indexPath`. |
151
- | `--provider <openai\|jina>` | Embedding provider; `openai`. |
152
- | `--model <name>` | Embedding model; OpenAI `text-embedding-3-large`, Jina `jina-embeddings-v4`. |
153
- | `--dimensions <number>` | Positive dimensions supported by the model; OpenAI `3072`, Jina `1024`. |
154
- | `--description-provider <openai\|opencode\|opencode-go>` | Description provider; OpenAI by default. OpenCode values use `OPENCODE_API_KEY` or `~/.local/share/opencode/auth.json`. |
155
- | `--description-model <name>` | Description model; `gpt-5.6-luna` for OpenAI and `muse-spark-1.3-contributor` for Zen/Go. |
156
- | `--reranker-candidates <number>` | With `config reranker openai`, embedding-ranked functions sent to the LLM; range `1`-`100`, default `10`. |
157
- | `--ignore-errors` | Silence saved-diagnostic warnings without deleting records. |
158
- | `--verbose` | Report every external model request on stderr instead of once per call kind/provider/model. Config `"verbose": true` has the same effect. |
159
- | `-h`, `--help` | Usage; no refresh. |
160
- | `--version` | Package version; exits without refresh or saved-diagnostic warnings. |
161
-
162
- Explicit relative config/index paths resolve from the current directory. Source paths and explicit file arguments resolve within `--root`. Prefer absolute paths when operating across repositories. CLI settings override config.
163
-
164
- ### Query and analysis options
165
-
166
- | Argument | Applies to / behavior |
167
- | --- | --- |
168
- | `--limit <number>` | Positive integer output limit; unlimited unless passed. Query matches, or cross-search clusters (`clusters`) / matched sources (`summary`/JSONL). Threshold filters results. |
169
- | `--matches <number>` | Cross-search only: matches kept per source function; default `5`. |
170
- | `--threshold <number\|min-max>` | Both query searches and cross-search. Inclusive minimum or half-open range; default `0.3`. |
171
- | `--format <json\|summary\|clusters>` | Both query searches, cross-search, and index-errors. Cohesion-ranked cross-search supports summary or JSONL, not clusters. |
172
- | `-e <regex>`, `--regexp <regex>`, `--regex <regex>` | Equivalent case-sensitive JavaScript regex options on qualified names. Query searches filter results before limiting; cross-search filters sources only. |
173
- | `--min-lines <number>` | Cross-search: positive source/candidate length minimum, default `2`. |
174
- | `--source-path <path>` | Cross-search: source file or recursive directory within the root. |
175
- | `--changed-since <commit>` | Cross-search: added, modified, or moved functions since an ancestor of the indexed Git checkpoint, including working-tree changes. Requires Git. |
176
- | `--uncommitted` | Cross-search: functions indexed from working-tree files; in Git these are staged, unstaged, or untracked changes. Without Git this selects all working-tree functions. |
177
- | `--cross-file-only` | Cross-search: exclude same-physical-file matches. |
178
- | `--include-symmetric-duplicates` | Cross-search: allow both directions of same-index matches; otherwise each unordered pair appears once. |
179
- | `--cohesion` | Cross-search: add physical distance and order each source's matches from farthest to nearest. Defaults to summary output. |
180
- | `--target-root <path>` | Cross-search: second repository; requires `--target-index`. |
181
- | `--target-index <path>` | Cross-search: second index file; requires `--target-root`. |
182
- | `--target-config <path>` | Cross-search: target config, default `<target-root>/.slopdex/config.json`; requires both target options. |
183
-
184
- ### Refresh and recovery options
185
-
186
- | Argument | Behavior |
187
- | --- | --- |
188
- | `--target <ref>` | `update-git` snapshot, default `HEAD`. Non-HEAD targets are committed-only; later commands normally return to HEAD. |
189
- | `--rebuild-on-divergence` | Permit reconciliation after non-descendant history changes, such as a rebase/branch switch. |
190
- | `--force-reindex` | Recreate an incompatible index. Compatible indexes still use normal refresh; this is not an unconditional reparse flag. |
191
- | `--no-reindex` | With Git, reconcile the committed snapshot but omit working-tree overlays. Without Git, reuse a non-empty index; missing/empty indexes still populate. Not an offline mode. |
192
- | `--callables` | With `reindex-files`, continue after the file description and regenerate every callable description in each stale file. |
193
-
194
- Use `--no-reindex` when the task calls for committed-only results or reuse of an existing non-Git index, rather than silently weakening freshness.
195
-
196
- ## Interpret and report results
197
-
198
- ### Output formats
199
-
200
- | Command | Default | Alternatives |
201
- | --- | --- | --- |
202
- | `search`, `search-description` | `summary` | JSON array; purpose search includes generated description text |
203
- | `cross-search` | `clusters` | `summary`, or `json` for JSONL with one row per matched source |
204
- | `index-errors` | `summary` | JSON array |
205
- | `status`, update commands, `descriptions` | JSON object | — |
206
-
207
- Prefer summary output for compact source review, clusters for duplicate families, and JSON/JSONL for structured processing. Stdout carries results; stderr carries notices and warnings. External vector, description, and reranking requests identify their provider and model once per combination, or for every request with `--verbose`. Cross-search omits sources without emitted matches. Empty output means no findings under the chosen coverage/filters, not proof that no similar code exists.
208
-
209
- With reranking enabled, query summaries display both reranker relevance and embedding similarity. Similarity thresholds filter candidates before reranking; limits apply to the reranked output. LLM candidate documents include descriptions when available and function metadata/source code.
210
-
211
- ### Similarity and clusters
212
-
213
- ```text
214
- Cluster 1 (3 functions, similarity 0.9124-0.9568)
215
- src/auth/session.ts:18:1 :: validateSession
216
- src/http/middleware.ts:42:1 :: authenticate
217
- src/users/user-service.ts:27:3 :: UserService.authenticate
218
- ```
219
-
220
- - Similarity is a model-dependent resemblance score, not a duplication probability.
221
- - The range describes observed links. Members can be connected transitively; not all pairs necessarily match.
222
- - Cluster numbers reflect ordering by member count and name, not severity.
223
- - Inspect listed locations and callers. Tests, facades, adapters, and intentional layers can resemble each other without being redundant.
224
-
225
- When reporting candidates, identify paths/symbols, summarize the shared behavior you verified, and explain whether consolidation is appropriate. Do not infer equivalence from the score alone.
226
-
227
- ### Purpose-aware scoring
228
-
229
- When descriptions are complete, `search` and cross-search average code, callable-description, and file-description similarity with equal one-third weights. `search-description` averages callable and file descriptions. Cross-repository analysis needs completeness on both sides; otherwise all scores are code-only. Stale file descriptions remain in scoring until `reindex-files` refreshes them. Description-generator models may differ even though embedding profiles must match.
230
-
231
- Thresholds and limits apply to the selected score. Text labels combined scoring; JSON includes component scores and mode/weights in `scoring`. Compare runs only with matching scoring mode, weights, embedding and description-generator profiles, threshold, and source/candidate filters.
232
-
233
- ### Cohesion
234
-
235
- ```text
236
- src/auth/session.ts :: validateSession
237
- 0.9400 packages/http/middleware.ts :: authenticate [distance 4]
238
- 0.9300 src/auth/token.ts :: validateToken [distance 1]
239
- ```
240
-
241
- Physical distance is `0` within one file, `1` between files in one folder, and `1` plus directory-tree hops across folders. The option only reorders the selected semantic matches; it does not change similarity or prove that distant code should be moved. Review architectural layers, tests, adapters, and other intentional separation before recommending consolidation.