@javierkaiser/opencode-indexing 0.2.1 → 0.2.4

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/CHANGELOG.md CHANGED
@@ -5,6 +5,52 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.4] - 2026-10-16
9
+
10
+ ### Fixed
11
+ - **The prompt-footer indicator stopped rendering after OpenCode 2.0.30.** The
12
+ footer view imports `createSignal` from `solid-js` as a value, and `solid-js`,
13
+ `@opentui/core` and `@opentui/solid` were declared as *optional
14
+ peerDependencies* — which means npm never installs them, on the assumption that
15
+ the host already provides them. 2.0.30 stopped providing them, the plugin's own
16
+ `import()` of the footer view failed, the `catch` swallowed it, and the slot
17
+ rendered nothing. Everything else kept working, because nothing else needs
18
+ JSX: the command palette comes from `tui.ts` itself, which is what made it look
19
+ like a cosmetic regression rather than a missing dependency.
20
+
21
+ The three packages are now `optionalDependencies`. That still tolerates a
22
+ failed install, but unlike an optional peer it actually puts them on disk, so
23
+ the indicator no longer depends on what the host happens to supply.
24
+
25
+ - **A package listed in both `optionalDependencies` and `devDependencies` is not
26
+ installed at all.** npm 12 lets the dev list win, so `--omit=dev` skips the
27
+ package and the optionalDependency never reaches disk — and `package.json`
28
+ still reads as though it is declared. This is why moving the three packages
29
+ was not by itself enough; they had to leave `devDependencies` as well.
30
+
31
+ - `tsconfig.json` is published. `jsx: react-jsx` with
32
+ `jsxImportSource: "@opentui/solid"` is what makes a `.tsx` file load at all, and
33
+ it was not in `files`.
34
+
35
+ ### Added
36
+ - `test/package-deps.test.ts` guards the manifest against all three of the
37
+ above, and asserts that every value import in the published sources resolves
38
+ to something the manifest installs — so the next third-party import fails a
39
+ test instead of becoming another silent missing module at load time.
40
+
41
+ ## [0.2.3] - 2026-10-16
42
+
43
+ ### Added
44
+ - `install.mjs` accepts `--with-codegraph`. It is **off by default** and only
45
+ has effect in `--package` mode, as consent comes from passing the flag. When
46
+ active it detects an existing `codegraph` CLI, installs it globally (`npm install
47
+ -g codegraph`) if it is missing, and registers its MCP with OpenCode via
48
+ `codegraph install --target opencode`. A failure in either step is reported and
49
+ does not cancel this plugin's own install.
50
+ - The README now names `npx` (not `opencode plugin add`) as the recommended
51
+ install method, and shows the companion install in the recommended command:
52
+ `npx @javierkaiser/opencode-indexing --with-codegraph`.
53
+
8
54
  ## [0.2.1] - 2026-10-15
9
55
 
10
56
  ### Added
package/README.md CHANGED
@@ -26,28 +26,48 @@ index is still installed.
26
26
 
27
27
  ## Install
28
28
 
29
- ### With the OpenCode CLI (recommended)
29
+ ### With npx (recommended)
30
30
 
31
31
  ```bash
32
- opencode plugin add @javierkaiser/opencode-indexing
32
+ npx @javierkaiser/opencode-indexing
33
+ ```
34
+
35
+ This is the whole install: the installer runs `opencode plugin add`, writes the
36
+ permission rules, restarts the service, and, when you ask for it, also installs
37
+ and registers the companion `codegraph`
38
+ MCP. It picks its strategy from where it runs — from an npx cache or an
39
+ unpacked tarball it installs the published package, from a checkout it
40
+ installs your working tree instead — so edits take effect on restart with no
41
+ publish in between. It prints which one it chose.
42
+
43
+ Add `--with-codegraph` to install and register codegraph as part of the same run
44
+ (the flag is opt-in and only has effect in the published-package mode):
45
+
46
+ ```bash
47
+ npx @javierkaiser/opencode-indexing --with-codegraph
33
48
  ```
34
49
 
35
- That is the whole install. OpenCode downloads the package into its own cache and
36
- records it in the global `plugins` array, and it loads both halves of the plugin:
37
- the server side (`index.ts`, which registers the tools) and the terminal UI
38
- (`tui.ts`, which adds the prompt-footer indicator and the `/indexing` page).
50
+ | Flag | Effect |
51
+ | --- | --- |
52
+ | `--package [spec]` | Install the published package (default spec `@latest`) |
53
+ | `--local` | Copy this directory into the config dir (development) |
54
+ | `--skip-deps` | `--local` only: copy the files, install no dependencies |
55
+ | `--no-restart` | Do not restart the service |
56
+ | `--with-codegraph` | Install and register codegraph as a companion MCP (opt-in, `--package` only) |
39
57
 
40
- Update and remove it with the same command family:
58
+ ### With the OpenCode CLI
41
59
 
42
60
  ```bash
43
- opencode plugin check # is there a newer version?
44
- opencode plugin update # install it
45
- opencode plugin remove @javierkaiser/opencode-indexing
61
+ opencode plugin add @javierkaiser/opencode-indexing
46
62
  ```
47
63
 
48
- `plugin add` installs the plugin but knows nothing about its tools, so it does
49
- not write permission rules. Add this one to `opencode.json` to keep the host
50
- asking before the only tool that writes your settings file:
64
+ OpenCode downloads the package into its own cache and records it in the global
65
+ `plugins` array, and it loads both halves of the plugin: the server side
66
+ (`index.ts`, which registers the tools) and the terminal UI (`tui.ts`, which
67
+ adds the prompt-footer indicator and the `/indexing` page). It brings `plugin
68
+ check`, `plugin update` and `plugin remove` with it, but it cannot write
69
+ permission rules — add this one to `opencode.json` to keep the host asking
70
+ before the only tool that writes your settings file:
51
71
 
52
72
  ```jsonc
53
73
  {
@@ -61,27 +81,6 @@ The other six tools only read. OpenCode's base policy already allows everything
61
81
  (`{ "action": "*", "resource": "*", "effect": "allow" }`), so they need no rule;
62
82
  write them out only if you want to tighten the set.
63
83
 
64
- ### One command, permissions included
65
-
66
- To skip the manual rule:
67
-
68
- ```bash
69
- npx @javierkaiser/opencode-indexing
70
- ```
71
-
72
- The installer runs `opencode plugin add`, writes the permission rules, and
73
- restarts the service. It picks its strategy from where it runs: from an installed
74
- copy — an npx cache, an unpacked tarball — it installs the published package;
75
- from a checkout it installs your working tree instead, so edits take effect on
76
- restart with no publish in between. It prints which one it chose.
77
-
78
- | Flag | Effect |
79
- | --- | --- |
80
- | `--package [spec]` | Install the published package (default spec `@latest`) |
81
- | `--local` | Copy this directory into the config dir (development) |
82
- | `--skip-deps` | `--local` only: copy the files, install no dependencies |
83
- | `--no-restart` | Do not restart the service |
84
-
85
84
  `install.sh` and `install.ps1` are thin wrappers over it; PowerShell also accepts
86
85
  `-Local`, `-Package`, `-Spec`, `-SkipDeps` and `-NoRestart`.
87
86
 
@@ -384,6 +383,12 @@ Word about data safety: Kilo's indexes (`ws-*` collections and its LanceDB direc
384
383
  ## Requirements
385
384
 
386
385
  - OpenCode v2 (plugin API `@opencode/plugin@2.x`).
386
+ - **For the prompt-footer indicator:** `solid-js`, `@opentui/core` and
387
+ `@opentui/solid`, which the plugin installs itself (~14 MB). They used to be
388
+ declared as optional *peer* dependencies, on the assumption that the host
389
+ already had them; OpenCode 2.0.30 stopped providing them and the indicator
390
+ silently stopped rendering. Everything else works without them — the settings
391
+ page degrades to dialogs and the footer is simply absent.
387
392
  - **For the own index: nothing to run.** The default store is embedded LanceDB
388
393
  (`@lancedb/lancedb@0.26.2`), so there is no server to start, no port to free and
389
394
  no container to keep alive.
@@ -482,7 +487,7 @@ This plugin deliberately stays on the semantic side and coexists with grep/read
482
487
  (see the tool descriptions and the bundled skill). A code-graph mode (tree-sitter
483
488
  symbol/edge extraction into SQLite, exposed as `indexing_graph_*` tools that
484
489
  chain after `indexing_search`) is a candidate for a future major version; the
485
- tree-sitter infrastructure is already in place.
490
+ tree-sitter infrastructure is already in place. Independently, the installer can itself install and register codegraph as a companion MCP (`--with-codegraph`, opt-in, published-package mode only).
486
491
 
487
492
  ## Development
488
493
 
package/install.mjs CHANGED
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Works on Windows, Linux and macOS (Node >= 22.6; Node 26 recommended).
6
6
  *
7
- * node install.mjs [--local|--package] [spec] [--skip-deps] [--no-restart]
7
+ * node install.mjs [--local|--package] [spec] [--skip-deps] [--no-restart] [--with-codegraph]
8
8
  * npx @javierkaiser/opencode-indexing
9
9
  *
10
10
  * There are two ways to install, because there are two audiences.
@@ -38,6 +38,7 @@ const argv = process.argv.slice(2)
38
38
  const has = (name) => argv.some((arg) => arg.toLowerCase() === name)
39
39
  const skipDeps = has("--skip-deps")
40
40
  const noRestart = has("--no-restart")
41
+ const withCodegraph = has("--with-codegraph")
41
42
 
42
43
  const source = dirname(fileURLToPath(import.meta.url))
43
44
  const sourcePkg = JSON.parse(readFileSync(join(source, "package.json"), "utf8"))
@@ -75,6 +76,7 @@ const spec = positional[0] ?? `${sourcePkg.name}@latest`
75
76
  log(`Installing ${sourcePkg.name} ${sourcePkg.version}`)
76
77
  log(` from: ${source}`)
77
78
  log(` mode: ${mode} (${reason})`)
79
+ if (withCodegraph) log(" + codegraph (via --with-codegraph, package mode)")
78
80
 
79
81
  // ---------------------------------------------------------------------------
80
82
  // Tool permissions (both modes)
@@ -308,14 +310,78 @@ function installPackage() {
308
310
  return true
309
311
  }
310
312
 
313
+ // ---------------------------------------------------------------------------
314
+ // Codegraph as a companion MCP (opt-in, --with-codegraph)
315
+ // ---------------------------------------------------------------------------
316
+ /**
317
+ * Whether a `codegraph` CLI is available on PATH.
318
+ *
319
+ * A plain spawn is the cheapest, shell-independent probe and matches what
320
+ * the bench harness `resolveBinary()` does. It is treated as read-only here.
321
+ */
322
+ function hasCodegraphBin() {
323
+ try {
324
+ const probe = spawnSync("codegraph", ["--version"], { stdio: "ignore", shell: isWindows })
325
+ if (probe.error) return false
326
+ // status is either 0 or, on some wrappers, undefined-but-no-error; treat both as present
327
+ return probe.status === 0 || probe.status === null
328
+ } catch {
329
+ return false
330
+ }
331
+ }
332
+
333
+ /**
334
+ * Install codegraph and register its MCP with OpenCode.
335
+ *
336
+ * The only consent gate is the flag itself, as the user requested: this is
337
+ * an install step, not a recommendation. A failure in either half is reported
338
+ * and tolerated — the plugin is already installed and still works with
339
+ * semantic search only.
340
+ */
341
+ function installCodegraph() {
342
+ log(" installing codegraph as a companion MCP server...")
343
+
344
+ if (!hasCodegraphBin()) {
345
+ log(" codegraph CLI missing; running npm install -g codegraph...")
346
+ const npm = isWindows ? "npm.cmd" : "npm"
347
+ // --omit=... is not needed here: codegraph stands on its own, and a global
348
+ // install is what its own documentation assumes.
349
+ const installed = spawnSync(npm, ["install", "-g", "codegraph"], {
350
+ stdio: "inherit",
351
+ shell: isWindows,
352
+ })
353
+ if (installed.error || installed.status !== 0) {
354
+ warn(" could not install codegraph (npm install -g codegraph failed); skipping MCP registration")
355
+ return
356
+ }
357
+ }
358
+
359
+ const register = spawnSync("codegraph", ["install", "--target", "opencode"], {
360
+ stdio: "inherit",
361
+ shell: isWindows,
362
+ })
363
+ if (register.error || register.status !== 0) {
364
+ warn(" codegraph is present but `codegraph install --target opencode` failed")
365
+ warn(" run it manually once to finish MCP registration: codegraph install --target opencode")
366
+ return
367
+ }
368
+
369
+ log(" codegraph installed and registered with OpenCode")
370
+ }
371
+
311
372
  // ---------------------------------------------------------------------------
312
373
  // Run
313
374
  // ---------------------------------------------------------------------------
314
375
  if (mode === "local") {
315
376
  installLocal()
316
- } else if (!installPackage()) {
377
+ if (withCodegraph) warn(" --with-codegraph is ignored in --local mode; codegraph is not installed there")
378
+ } else {
379
+ if (!installPackage()) {
317
380
  warn(" not writing permissions or restarting: the install did not complete")
318
381
  process.exit(1)
382
+ }
383
+ if (withCodegraph) installCodegraph()
384
+
319
385
  }
320
386
 
321
387
  writePermissions()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@javierkaiser/opencode-indexing",
3
- "version": "0.2.1",
3
+ "version": "0.2.4",
4
4
  "description": "OpenCode plugin: semantic code search that reuses Kilo Code indexes (Qdrant/LanceDB) and maintains its own independent index",
5
5
  "license": "MIT",
6
6
  "author": "Carlos Javier Lust <javierkaiser@gmail.com>",
@@ -37,6 +37,7 @@
37
37
  "tui.ts",
38
38
  "tui",
39
39
  "src",
40
+ "tsconfig.json",
40
41
  "install.mjs",
41
42
  "install.sh",
42
43
  "install.ps1",
@@ -65,23 +66,20 @@
65
66
  "@lancedb/lancedb": "0.26.2",
66
67
  "tree-sitter-wasms": "0.1.13",
67
68
  "web-tree-sitter": "0.25.10",
68
- "apache-arrow": "18.1.0"
69
+ "apache-arrow": "18.1.0",
70
+ "solid-js": "^1.9.12",
71
+ "@opentui/core": "0.5.14",
72
+ "@opentui/solid": "0.5.14"
69
73
  },
70
74
  "devDependencies": {
71
75
  "@opencode/plugin": "2.0.23",
72
76
  "@opencode/theme": "^2.0.23",
73
- "@opentui/core": "^0.5.14",
74
- "@opentui/solid": "^0.5.14",
75
77
  "@types/node": "^24.0.0",
76
- "solid-js": "^1.9.12",
77
78
  "typescript": "^5.8.2"
78
79
  },
79
80
  "peerDependencies": {
80
81
  "@opencode/plugin": ">=2.0.0",
81
- "@opencode/theme": ">=2.0.23",
82
- "@opentui/core": ">=0.5.14",
83
- "@opentui/solid": ">=0.5.14",
84
- "solid-js": ">=1.9.12"
82
+ "@opencode/theme": ">=2.0.23"
85
83
  },
86
84
  "peerDependenciesMeta": {
87
85
  "@opencode/plugin": {
@@ -89,15 +87,6 @@
89
87
  },
90
88
  "@opencode/theme": {
91
89
  "optional": true
92
- },
93
- "@opentui/core": {
94
- "optional": true
95
- },
96
- "@opentui/solid": {
97
- "optional": true
98
- },
99
- "solid-js": {
100
- "optional": true
101
90
  }
102
91
  }
103
92
  }
package/tsconfig.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "allowImportingTsExtensions": true,
7
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
8
+ "types": ["node"],
9
+ "jsx": "react-jsx",
10
+ "jsxImportSource": "@opentui/solid",
11
+ "strict": true,
12
+ "noEmit": true,
13
+ "skipLibCheck": true,
14
+ "esModuleInterop": true,
15
+ "allowSyntheticDefaultImports": true,
16
+ "forceConsistentCasingInFileNames": true,
17
+ "resolveJsonModule": true,
18
+ "isolatedModules": true,
19
+ "verbatimModuleSyntax": true
20
+ },
21
+ "include": ["index.ts", "tui.ts", "tui/**/*.ts", "tui/**/*.tsx", "src/**/*.ts", "test/**/*.ts"]
22
+ }