[Feature]: Support importing @jackwener/opencli from a monorepo shared directory
- Dominant language
- JavaScript
- Stars
- 29.3k
- Forks
- 2.9k
- Avg merge
- 15h 36m
- Merged PRs (30d)
- 70
Description
### Feature Description
A monorepo plugin (declaring multiple sub-plugins in `opencli-plugin.json`) often puts code shared across sub-plugins into a shared directory (e.g. `packages/shared/`). However, OpenCLI only creates the host symlink (`linkHostOpencli`) inside each sub-plugin directory — the shared directory is never linked. So any `.js` file in that shared directory that does `import '@jackwener/opencli/errors'` (e.g. `ArgumentError`) or `/registry` fails to resolve at runtime:
```
⚠ Plugin foo/read.js: Cannot find package '@jackwener/opencli' imported from .../packages/shared/util.js
```
### Use Case
As a monorepo plugin author, I want to put shared helpers (validation, formatting, auth, …) into `packages/shared/` for reuse across sub-plugins, where those helpers need to `import '@jackwener/opencli/errors'` (e.g. `ArgumentError`). This is currently not possible.
Worse, the failure is not a hard error but **silent command loss**:
- `discovery.js` runs `await import(file).catch(err => log.warn(...))`, so a failed load only warns and continues;
- as a result, every command of sub-plugins that reference the shared file is never registered — they simply disappear from `opencli list` (exit code stays 0), leaving only a single `⚠` warning that is easy to miss.
Minimal reproduction:
```bash
# A monorepo plugin: opencli-plugin.json declares sub-plugins foo / bar, plus a shared packages/shared/ directory
# packages/shared/util.js: import { ArgumentError } from '@jackwener/opencli/errors'
opencli plugin install file:///path/to/packages/foo
opencli list # shows "Cannot find package" warning; all of foo's commands are gone
```
### Proposed Solution
1. During monorepo install, also symlink the host into the shared directory (or the repo root) so shared code can `import '@jackwener/opencli'`.
2. At minimum, turn a sub-plugin load failure from `log.warn` into an explicit error / install failure, to avoid silent command loss.
### Alternatives Considered
- Have shared code receive error classes as function parameters (passing `ArgumentError` / `AuthRequiredError` in). This works around it but is awkward, and non-class exports such as `/registry` cannot be injected this way.
- `@jackwener/opencli` is a peer dependency and is never installed via `npm install`, only resolved through the host symlink, so "per-sub-plugin npm install" does not help (unlike #722's `undici`; also unlike #843's symlink path bug, which is already fixed).
### Environment
- OpenCLI version: 1.8.6
- Node.js: v24.18.1
- OS: macOS
> This issue was drafted by an AI agent and published after human confirmation.
Contributor guide
Research direction
Start by tracing monorepo installation through linkHostOpencli and the shared-directory layout declared by opencli-plugin.json. Read discovery.js, especially its failed dynamic-import handling, and reproduce the missing-package warning with the provided command sequence. Done means shared imports resolve during plugin loading and command loss is no longer silent, with tests covering the behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- cli, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100