jackwener / jackwener/OpenCLI

[Feature]: Support importing @jackwener/opencli from a monorepo shared directory

Open
#2,373 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.