Skip to content

Package CodeNomad OpenCode plugin#433

Merged
shantur merged 5 commits into
devfrom
opencode-config-merge
May 12, 2026
Merged

Package CodeNomad OpenCode plugin#433
shantur merged 5 commits into
devfrom
opencode-config-merge

Conversation

@shantur
Copy link
Copy Markdown
Collaborator

@shantur shantur commented May 11, 2026

Summary

  • Rename the OpenCode config template into a versioned npm-packable CodeNomad plugin package.
  • Build and package the plugin through the server bundle, with Electron/Tauri carrying it via existing server resources.
  • Replace OPENCODE_CONFIG_DIR injection with JSONC-aware OPENCODE_CONFIG_CONTENT merging that appends the CodeNomad plugin while preserving user config.

Validation

  • npm run build --workspace @codenomad/codenomad-opencode-plugin
  • npm run prepare-plugin --workspace @neuralnomads/codenomad
  • npm run typecheck --workspace @neuralnomads/codenomad
  • npm run typecheck --workspace @neuralnomads/codenomad-electron-app
  • node --import tsx --test "src/opencode-plugin.test.ts" "src/workspaces/tests/spawn.test.ts"

Notes

  • Production plugin loading uses an explicit npm file alias for the packaged tarball.
  • Dev loading still references the TypeScript plugin entry directly.

Replace the copied opencode config template with a versioned npm-packable CodeNomad OpenCode plugin package. The server now builds and packs the plugin artifact, and desktop bundles carry the packaged plugin through the existing server resources.

Workspace launches now merge any user or system OPENCODE_CONFIG_CONTENT JSONC with CodeNomad's plugin entry, preserving existing plugin config while ensuring the managed bridge is available. Production uses an explicit npm file alias for the packaged tarball, while dev keeps loading the TypeScript plugin source directly.

Validated with plugin build, server and Electron typechecks, targeted plugin config tests, and WSL spawn environment tests.
@shantur
Copy link
Copy Markdown
Collaborator Author

shantur commented May 11, 2026

@CodeNomadBot

I want you to perform the gatekeeper checks for latest PR state

check for regressions
check for better possible implementations
Be the PR gatekeeper
Be ruthless about code quality

@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/25678633369

Artifacts expire in 7 days.
Artifacts: (none found on this run)

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot Bot commented May 11, 2026

Gatekeeper review for the latest PR state.

Understood request: review this PR ruthlessly for regressions and implementation quality, not to make code changes. Assumption: the PR should preserve existing desktop packaging behavior across Electron, Tauri, Windows/WSL, Linux, and macOS.

Findings:

  1. Blocker: root install is now platform-specific and will break non-macOS-arm64 environments. package.json:28-31 adds @tauri-apps/cli-darwin-arm64 as a normal root dependency. That package has os/cpu restrictions, so Linux, Windows, and macOS x64 installs can fail with EBADPLATFORM; it also has no obvious relationship to packaging the OpenCode plugin. This should be removed from root dependencies and the lockfile. Keep Tauri CLI under packages/tauri-app dev dependencies or install platform binaries as optional/no-save tooling as the existing prebuild workaround already does.

  2. Blocker: production OpenCode plugin loading is broken for WSL binaries. packages/server/src/opencode-plugin.ts:71-72 embeds the host tarball path inside the plugin specifier, packages/server/src/workspaces/manager.ts:147-150 places that specifier inside OPENCODE_CONFIG_CONTENT, and packages/server/src/workspaces/spawn.ts:283-290 now propagates OPENCODE_CONFIG_CONTENT without WSL path translation. A WSL OpenCode process receives JSON containing a Windows host path such as @codenomad/codenomad-opencode-plugin@file:C:/.../codenomad-opencode-plugin.tgz, but that path is not valid inside Linux. The previous OPENCODE_CONFIG_DIR path was explicitly translated with /p; this PR removes that escape hatch. Fix by making the packaged plugin path resolvable from the target runtime before writing the config content, or by materializing/copying the plugin into a Linux-reachable location for WSL launches. Add a regression test that combines getCodeNomadPluginUrl() output with WSL spawning rather than only asserting WSLENV string shape.

  3. High: Tauri’s dependency self-healing no longer covers the server build path it invokes. packages/tauri-app/scripts/prebuild.js:42-46 only checks/installs server build dependencies, then packages/tauri-app/scripts/prebuild.js:64-75 runs the server build, which now calls packages/server/scripts/package-opencode-plugin.mjs:41-42. That new step requires the plugin workspace dev deps from packages/opencode-plugin/package.json:19-21 (typescript, @types/node), but prebuild never ensures them. In this workspace, npm run build --workspace @codenomad/codenomad-opencode-plugin fails with TS2688: Cannot find type definition file for 'node', which is exactly the missing dependency class this prebuild script is supposed to avoid for desktop packaging. Either include the plugin workspace in the prebuild dependency install/check or make prepare-plugin install/build from a dependency state that Tauri packaging guarantees.

Validation performed:

  • git diff --check origin/dev...HEAD: passed.
  • npm run build --workspace @codenomad/codenomad-opencode-plugin: failed locally with missing @types/node (TS2688).
  • node --import tsx --test "packages/server/src/opencode-plugin.test.ts" "packages/server/src/workspaces/__tests__/spawn.test.ts": failed locally because tsx is not installed in this worktree.

Decision: changes requested. I would not merge this PR until the accidental platform dependency is removed and WSL production plugin loading is proven with a real path translation/accessibility test.

--
Yours,
CodeNomadBot

@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/25678732783

Artifacts expire in 7 days.
Artifacts: (none found on this run)

Remove the accidental darwin-arm64 Tauri CLI root dependency so installs remain cross-platform.

For WSL OpenCode launches, rewrite packaged CodeNomad plugin file specs through a WSLENV-translated helper path before exec so the Linux process receives a reachable file path inside OPENCODE_CONFIG_CONTENT.

Ensure Tauri prebuild installs the OpenCode plugin workspace build dependencies before invoking the server build, since server packaging now builds the plugin package.

Validated with plugin build, server typecheck, targeted OpenCode plugin config and WSL spawn tests, and diff whitespace checks.
@shantur
Copy link
Copy Markdown
Collaborator Author

shantur commented May 11, 2026

@CodeNomadBot

Check again now

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot Bot commented May 11, 2026

Gatekeeper re-check for the updated PR state.

Understood request: re-review the latest pushed state and verify whether the prior blockers were addressed. Assumption: this PR must be mergeable with the validation commands listed in the PR body, especially the plugin build/package path.

Findings:

  1. Blocker: the plugin package still does not build, so server packaging cannot succeed. After installing the plugin workspace deps using the same command now added to Tauri prebuild, npm run build --workspace @codenomad/codenomad-opencode-plugin fails with declaration emit errors:
plugin/codenomad.ts(7,23): error TS2742: The inferred type of 'CodeNomadPlugin' cannot be named without a reference to '@opencode-ai/plugin/node_modules/zod'. This is likely not portable. A type annotation is necessary.
plugin/lib/background-process.ts(30,17): error TS2742: The inferred type of 'createBackgroundProcessTools' cannot be named without a reference to '@opencode-ai/plugin/node_modules/zod'. This is likely not portable. A type annotation is necessary.

Because packages/opencode-plugin/tsconfig.json:10 enables declaration, exported functions cannot rely on inferred types that leak transitive nested dependency types. This blocks packages/server/scripts/package-opencode-plugin.mjs, and npm run prepare-plugin --workspace @neuralnomads/codenomad fails for the same reason. Fix by adding explicit portable return type annotations for CodeNomadPlugin and createBackgroundProcessTools, or by otherwise preventing declaration emit from needing to name the nested zod types.

Resolved from prior review:

  • The accidental root @tauri-apps/cli-darwin-arm64 dependency is gone from package.json; that blocker looks fixed.
  • Tauri prebuild now has an explicit plugin workspace dependency bootstrap in packages/tauri-app/scripts/prebuild.js; the previous missing-deps path is addressed, but the build now gets far enough to expose the TS2742 declaration issue above.
  • The WSL plugin tarball path handling now rewrites the host file path through CODENOMAD_OPENCODE_PLUGIN_WSL_PATH with /p translation and replaces a placeholder inside OPENCODE_CONFIG_CONTENT. Static review says this is a reasonable targeted fix, and there is a regression test for the WSL rewrite path.

Validation performed:

  • git diff --check origin/dev...HEAD: passed.
  • npm install --workspace @codenomad/codenomad-opencode-plugin --include-workspace-root=false --install-strategy=nested --fund=false --audit=false: passed.
  • npm run build --workspace @codenomad/codenomad-opencode-plugin: failed with TS2742.
  • npm run prepare-plugin --workspace @neuralnomads/codenomad: failed because the plugin build fails with TS2742.
  • node --import tsx --test "packages/server/src/opencode-plugin.test.ts" "packages/server/src/workspaces/__tests__/spawn.test.ts": not runnable in this worktree because tsx is not installed here.

Decision: changes still requested. The prior architecture blockers are mostly addressed, but this PR is still not mergeable until the plugin package build and prepare-plugin pass cleanly.

--
Yours,
CodeNomadBot

Disable declaration output for the packaged OpenCode plugin and clean dist before builds so stale .d.ts files are not packed. The plugin is consumed as runtime JavaScript by OpenCode, and declaration generation can infer non-portable nested zod paths from @opencode-ai/plugin.

Add explicit hook return annotations on the plugin entry to keep exported runtime shapes clear while avoiding declaration generation in CI builds.

Validated with plugin build, server prepare-plugin packaging, server typecheck, and targeted plugin/WSL tests.
@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/25679251910

Artifacts expire in 7 days.
Artifacts: (none found on this run)

@shantur
Copy link
Copy Markdown
Collaborator Author

shantur commented May 11, 2026

@CodeNomadBot

Now?

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot Bot commented May 11, 2026

Gatekeeper re-check for the latest pushed state.

Understood request: verify whether the remaining blocker is resolved now. Assumption: this pass should focus on the previously failing plugin build/package path and any obvious regressions in the touched code.

Findings:

  • No new blocking code findings in this pass. The previous TS2742 plugin build blocker is resolved on the current branch.

Previously requested fixes now verified:

  • Root package.json no longer includes the accidental platform-specific @tauri-apps/cli-darwin-arm64 dependency.
  • npm run build --workspace @codenomad/codenomad-opencode-plugin now passes.
  • npm run prepare-plugin --workspace @neuralnomads/codenomad now passes and produces packages/server/dist/opencode-plugin/codenomad-opencode-plugin.tgz.
  • The WSL plugin path rewrite remains covered by the added spawn test path and looks targeted to the production tarball path issue.

Validation performed:

  • git diff --check origin/dev...HEAD: passed.
  • npm run build --workspace @codenomad/codenomad-opencode-plugin: passed.
  • npm run prepare-plugin --workspace @neuralnomads/codenomad: passed.
  • npm run typecheck --workspace @neuralnomads/codenomad: could not be meaningfully validated in this worktree because server dependencies were missing; errors were module-resolution failures for packages like fastify, zod, undici, etc.
  • npm run typecheck --workspace @neuralnomads/codenomad-electron-app: could not be meaningfully validated in this worktree because Electron dependencies were missing; errors were module-resolution failures for packages like electron, electron-vite, vite-plugin-solid, etc.
  • I attempted to install the missing server/Electron workspace deps, but the local npm install failed with workspace/node_modules corruption and an esbuild spawn error, so I am not treating those dependency-environment failures as PR code regressions.
  • node --import tsx --test src/opencode-plugin.test.ts src/workspaces/__tests__/spawn.test.ts: still not runnable in this worktree because tsx is not installed/resolvable here.

Decision: no changes requested from this gatekeeper pass. The prior blocker I could reproduce is fixed. CI or a clean dependency install should still be used as the final authority for the broader typecheck/test commands that this local worktree could not execute cleanly.

--
Yours,
CodeNomadBot

@shantur
Copy link
Copy Markdown
Collaborator Author

shantur commented May 11, 2026

@pascalandr - Would you be able to test this on Windows and see if it still works in packaged binaries?

@pascalandr
Copy link
Copy Markdown
Contributor

pascalandr commented May 11, 2026

Tested locally on Windows: Tauri packaged build passes, Electron packaged build passes after the small Windows quoting fix in #436, and both packaged resources include the OpenCode plugin tarball.
It launches successfully and resolves the packaged OpenCode plugin path

## Summary
- Avoid routing the Electron resource-prep Node invocation through the
Windows shell.
- Fix local `build:win` when Node is installed under `C:\Program
Files\nodejs\node.exe`.

## Validation
- `npm run build:win --workspace @neuralnomads/codenomad-electron-app`

## Notes
- This targets `opencode-config-merge` so it can be merged into #433.
@shantur
Copy link
Copy Markdown
Collaborator Author

shantur commented May 12, 2026

Thanks for testing and the PR @pascalandr

@shantur shantur merged commit cf88dc0 into dev May 12, 2026
10 of 11 checks passed
@shantur shantur deleted the opencode-config-merge branch May 12, 2026 08:00
shantur added a commit that referenced this pull request May 14, 2026
…cloning, chat search and more (#443)

## Thanks for contributions

- [@pascalandr](https://github.com/pascalandr):
[#394](#394),
[#397](#397),
[#405](#405),
[#410](#410),
[#411](#411),
[#423](#423),
[#424](#424),
[#425](#425),
[#426](#426),
[#428](#428),
[#436](#436)
- [@jollyxenon](https://github.com/jollyxenon):
[#381](#381),
[#409](#409)
- [@OfflinePing](https://github.com/OfflinePing):
[#415](#415)

## Highlights

- **Web previews create a much tighter fix loop**: Open a live preview
from a session, highlight the exact part of the page that needs work,
and tell the model what to change right from the webpage. CodeNomad
sends that page and element context back into chat so the LLM can act on
specific visual feedback instead of vague descriptions.
- **Bringing repositories into CodeNomad is much easier**: You can now
clone a Git repository directly from the workspace picker, making it
faster to start work on a fresh project without leaving the app.
- **Searching inside long conversations is finally practical**: Session
history search can now find matches across messages, tool output, and
related content, helping you jump straight to the part of a conversation
you need.
- **Sessions are easier to manage at a glance**: Parent sessions now
show aggregated token and cost totals across subagents, the message
timeline can be hidden when you want more room, and tabs can be
reordered.
- **Mobile views and narrow screens feel much better**: Prompt controls,
message actions, timeline behavior, and other session UI pieces adapt
more cleanly when space gets tight.

## What’s Improved

- **Smoother workspace startup**: The home screen, empty states, and
startup flow are clearer, and returning between active projects and the
home view feels more natural.
- **More useful browsing and previewing**: Markdown now supports math
rendering, web previews are integrated into the session flow, and
unrestricted browsing respects the selected workspace root more
reliably.
- **Cleaner model and agent selection**: Models are grouped by provider,
and primary agent selection now follows OpenCode’s visibility rules more
closely.
- **Better prompt and attachment handling**: File attachment picking is
more consistent with drag-and-drop behavior, and prompt controls are
laid out more clearly in compact layouts.
- **More self-contained packaging**: Desktop builds do a better job
bundling the runtime, shipping the CodeNomad OpenCode plugin, and
producing more consistent release artifacts.

## Fixes

- **Permission flows are more reliable**: Stale permission events are
ignored after a reply, permission metadata is preserved more safely, and
attachment context survives more consistently.
- **Idle/session indicators behave more predictably**: Idle badges now
stay visible until they are actually seen, and session status behavior
is easier to understand across parent and child sessions.
- **Desktop and packaged builds are more dependable**: Bundled resources
refresh more reliably, packaged session storage is isolated correctly,
remote window titles are preserved, and Windows resource preparation
avoids a brittle shell path.
- **Compact layouts are less frustrating**: Message actions, tool-call
controls, timeline spacing, and prompt controls behave better in narrow
center panes and smaller screens.
- **Release/update navigation is clearer**: Update links stay visible
more reliably, making it easier to see and open release information when
an update is available.

### Contributors

-   [@pascalandr](https://github.com/pascalandr)
-   [@jollyxenon](https://github.com/jollyxenon)
-   [@OfflinePing](https://github.com/OfflinePing)

## Merged Pull Requests

### @shantur

- PR [#397](#397) “Add
clone repository workspace flow”
- PR [#399](#399)
“feat(ui): allow tab reordering”
- PR [#400](#400)
“feat(ui): add chat history search”
- PR [#430](#430) “Add
session web preview mode”
- PR [#432](#432)
“fix(ui): align prompt attachment picker with drop behavior”
- PR [#433](#433)
“Package CodeNomad OpenCode plugin”
- PR [#434](#434)
“Refactor workspace startup and empty session states”
- PR [#437](#437)
“Improve prompt layout for narrow session panes”
- PR [#438](#438)
“Improve messages layouts on narrow screens”

### @pascalandr

- PR [#394](#394)
“fix(tauri): refresh bundled resources on rebuild”
- PR [#405](#405)
“fix(tauri): prefer bundled server entry in release”
- PR [#410](#410)
“fix(ui): keep update release link visible”
- PR [#411](#411)
“fix(ui): return to active projects from home”
- PR [#423](#423)
“fix(ui): follow up idle badge behavior”
- PR [#424](#424)
“fix(ui): drain yolo permissions outside shell render”
- PR [#425](#425)
“fix(ui): ignore stale permission events after reply”
- PR [#426](#426)
“fix(ui): reconcile permission tool attachments”
- PR [#428](#428)
“feat(ui): make message timeline hideable”
- PR [#436](#436)
“fix(electron): avoid shell for resource prep”

### @OfflinePing

- PR [#415](#415)
“feat(ui): show aggregated total tokens and cost for parent sessions
including subagents”

### @jollyxenon

- PR [#381](#381)
“Fix(ui): Support Markdown Math Rendering”
- PR [#409](#409)
“fix(ui): align primary agent selection with OpenCode”
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants