OpenCLI supports community-contributed plugins. Install third-party adapters from GitHub, and they're automatically discovered alongside built-in commands.
# Install a plugin
opencli plugin install github:ByteYue/opencli-plugin-github-trending
# List installed plugins
opencli plugin list
# Update one plugin
opencli plugin update github-trending
# Update all installed plugins
opencli plugin update --all
# Use the plugin (it's just a regular command)
opencli github-trending repos --limit 10
# Remove a plugin
opencli plugin uninstall github-trendingPlugins live in ~/.opencli/plugins/<name>/. Each subdirectory is scanned at startup for .ts or .js command files — the same formats used by built-in adapters.
# GitHub shorthand
opencli plugin install github:user/repo
opencli plugin install github:user/repo/subplugin # install specific sub-plugin from monorepo
opencli plugin install https://github.com/user/repo
# Any git-cloneable URL
opencli plugin install https://gitlab.example.com/team/repo.git
opencli plugin install ssh://git@gitlab.example.com/team/repo.git
opencli plugin install git@gitlab.example.com:team/repo.git
# Local plugin (for development)
opencli plugin install file:///path/to/plugin
opencli plugin install /path/to/pluginThe repo name prefix opencli-plugin- is automatically stripped for the local directory name. For example, opencli-plugin-hot-digest becomes hot-digest.
Plugins can include an opencli-plugin.json manifest file at the repo root to declare metadata:
{
"name": "my-plugin",
"version": "1.0.0",
"opencli": ">=1.0.0",
"description": "My awesome plugin"
}| Field | Description |
|---|---|
name |
Plugin name (overrides repo-derived name) |
version |
Semantic version |
opencli |
Required opencli version range (e.g. >=1.0.0, ^1.2.0) |
description |
Human-readable description |
plugins |
Monorepo sub-plugin declarations (see below) |
The manifest is optional — plugins without one continue to work exactly as before.
A single repository can contain multiple plugins by declaring a plugins field in opencli-plugin.json:
{
"version": "1.0.0",
"opencli": ">=1.0.0",
"description": "My plugin collection",
"plugins": {
"polymarket": {
"path": "packages/polymarket",
"description": "Prediction market analysis",
"version": "1.2.0"
},
"defi": {
"path": "packages/defi",
"description": "DeFi protocol data",
"version": "0.8.0",
"opencli": ">=1.2.0"
},
"experimental": {
"path": "packages/experimental",
"disabled": true
}
}
}# Install ALL enabled sub-plugins from a monorepo
opencli plugin install github:user/opencli-plugins
# Install a SPECIFIC sub-plugin
opencli plugin install github:user/opencli-plugins/polymarket- The monorepo is cloned once to
~/.opencli/monorepos/<repo>/ - Each sub-plugin gets a symlink in
~/.opencli/plugins/<name>/pointing to its subdirectory - Command discovery works transparently — symlinks are scanned just like regular directories
- Disabled sub-plugins (with
"disabled": true) are skipped during install - Sub-plugins can specify their own
openclicompatibility range
Updating any sub-plugin from a monorepo pulls the entire repo and refreshes all sub-plugins:
opencli plugin update polymarket # updates the monorepo, refreshes allopencli plugin uninstall polymarket # removes just this sub-plugin's symlinkWhen the last sub-plugin from a monorepo is uninstalled, the monorepo clone is automatically cleaned up.
OpenCLI records installed plugin versions in ~/.opencli/plugins.lock.json. Each entry stores the plugin source, current git commit hash, install time, and last update time. opencli plugin list shows the short commit hash when version metadata is available.
my-plugin/
├── package.json
├── my-command.ts
└── README.md
package.json:
{
"name": "opencli-plugin-my-plugin",
"version": "0.1.0",
"type": "module",
"peerDependencies": {
"@jackwener/opencli": ">=1.0.0"
}
}my-command.ts:
import { cli, Strategy } from '@jackwener/opencli/registry';
cli({
site: 'my-plugin',
name: 'my-command',
description: 'My custom command',
access: 'read', // 'read' | 'write'
example: 'opencli my-plugin my-command -f yaml',
strategy: Strategy.PUBLIC,
browser: false,
args: [
{ name: 'limit', type: 'int', default: 10, help: 'Number of items' },
],
columns: ['title', 'score'],
func: async (kwargs) => {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return data.items.slice(0, kwargs.limit).map((item: any, i: number) => ({
title: item.title,
score: item.score,
}));
},
});When you run opencli plugin install, TS plugins are automatically set up:
- Clone —
git clone --depth 1from GitHub - npm install — Resolves regular dependencies
- Host symlink — Links the running
@jackwener/opencliinto the plugin'snode_modules/soimport from '@jackwener/opencli/registry'always resolves against the host - Transpile — Compiles
.ts→.jsviaesbuild(productionnodecannot load.tsdirectly)
On startup, if both my-command.ts and my-command.js exist, the .js version is loaded to avoid duplicate registration.
| Repo | Type | Description |
|---|---|---|
| opencli-plugin-albato | JS | Albato automation workflow management: scenario inspection, start/pause, failure diagnosis, and retry |
| opencli-plugin-amap | JS | AutoNavi / 高德地图 spot & route extraction, coordinate decoders (GCJ-02 & WGS-84), and SSR search |
| opencli-plugin-github-trending | TS | GitHub Trending repositories |
| opencli-plugin-goofish | JS | Goofish / 闲鱼 buyer orders, favorites, IM chat, profile, item search, and fulfillment stats |
| opencli-plugin-hot-digest | TS | Multi-platform trending aggregator (zhihu, weibo, bilibili, v2ex, stackoverflow, reddit, linux-do) |
| opencli-plugin-juejin | TS | 稀土掘金 (Juejin) hot articles, categories, and article feed |
| opencli-plugin-rubysec | TS | RubySec advisory archive and advisory article reader |
| opencli-plugin-taobao | JS | Taobao buyer chat history, order history, bought shops, favorites, and keyword-based chat summaries |
| opencli-plugin-x-article-publisher | JS | Publish Markdown with local images as X long-form Articles via OpenCLI and xPoster |
Albato, Goofish and Taobao currently keep their command files under clis/<site> without a monorepo manifest. Installing the repository root with github:vecyang1/opencli-plugin-<site> fails structure validation. Clone the repository and install its command directory instead; keep the clone because local installs link to it:
git clone https://github.com/vecyang1/opencli-plugin-taobao.git
opencli plugin install ./opencli-plugin-taobao/clis/taobaoFor Albato or Goofish, substitute albato or goofish in both paths. Those two repositories require Node.js 22.5 or later. Follow each repository's README for its additional tools and setup. These are community-maintained adapters; the listing describes their commands, not a guarantee of historical-data completeness.
Restart opencli (or open a new terminal) — plugins are discovered at startup.
If you see Cannot find module '@jackwener/opencli/registry', the host symlink may be broken. Reinstall the plugin:
opencli plugin uninstall my-plugin
opencli plugin install github:user/opencli-plugin-my-plugin