@jackwener/opencli 1.4.1 → 1.5.1
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/.github/workflows/build-extension.yml +2 -6
- package/.github/workflows/ci.yml +21 -1
- package/README.md +35 -6
- package/README.zh-CN.md +12 -5
- package/SKILL.md +2 -0
- package/dist/browser/cdp.d.ts +2 -1
- package/dist/browser/cdp.js +5 -0
- package/dist/browser/discover.d.ts +4 -1
- package/dist/browser/discover.js +6 -2
- package/dist/browser/errors.d.ts +2 -2
- package/dist/browser/errors.js +4 -12
- package/dist/browser/mcp.d.ts +2 -1
- package/dist/browser/page.d.ts +3 -0
- package/dist/browser/page.js +24 -1
- package/dist/build-manifest.d.ts +2 -0
- package/dist/build-manifest.js +39 -14
- package/dist/build-manifest.test.js +21 -0
- package/dist/capabilityRouting.d.ts +2 -0
- package/dist/capabilityRouting.js +2 -1
- package/dist/cli-manifest.json +1567 -108
- package/dist/cli.js +68 -6
- package/dist/clis/36kr/article.d.ts +1 -0
- package/dist/clis/36kr/article.js +62 -0
- package/dist/clis/36kr/hot.d.ts +3 -0
- package/dist/clis/36kr/hot.js +80 -0
- package/dist/clis/36kr/hot.test.d.ts +1 -0
- package/dist/clis/36kr/hot.test.js +15 -0
- package/dist/clis/36kr/news.d.ts +1 -0
- package/dist/clis/36kr/news.js +51 -0
- package/dist/clis/36kr/news.test.d.ts +1 -0
- package/dist/clis/36kr/news.test.js +85 -0
- package/dist/clis/36kr/search.d.ts +1 -0
- package/dist/clis/36kr/search.js +72 -0
- package/dist/clis/bilibili/comments.d.ts +5 -0
- package/dist/clis/bilibili/comments.js +40 -0
- package/dist/clis/bilibili/comments.test.d.ts +1 -0
- package/dist/clis/bilibili/comments.test.js +82 -0
- package/dist/clis/bluesky/feeds.yaml +29 -0
- package/dist/clis/bluesky/followers.yaml +33 -0
- package/dist/clis/bluesky/following.yaml +33 -0
- package/dist/clis/bluesky/profile.yaml +27 -0
- package/dist/clis/bluesky/search.yaml +34 -0
- package/dist/clis/bluesky/starter-packs.yaml +34 -0
- package/dist/clis/bluesky/thread.yaml +32 -0
- package/dist/clis/bluesky/trending.yaml +27 -0
- package/dist/clis/bluesky/user.yaml +34 -0
- package/dist/clis/chatgpt/ask.js +29 -14
- package/dist/clis/chatgpt/ax.d.ts +6 -0
- package/dist/clis/chatgpt/ax.js +172 -1
- package/dist/clis/chatgpt/model.d.ts +1 -0
- package/dist/clis/chatgpt/model.js +24 -0
- package/dist/clis/chatgpt/send.js +12 -3
- package/dist/clis/douban/download.d.ts +1 -0
- package/dist/clis/douban/download.js +67 -0
- package/dist/clis/douban/download.test.d.ts +1 -0
- package/dist/clis/douban/download.test.js +170 -0
- package/dist/clis/douban/photos.d.ts +1 -0
- package/dist/clis/douban/photos.js +34 -0
- package/dist/clis/douban/utils.d.ts +25 -0
- package/dist/clis/douban/utils.js +190 -1
- package/dist/clis/douban/utils.test.d.ts +1 -0
- package/dist/clis/douban/utils.test.js +64 -0
- package/dist/clis/imdb/person.d.ts +1 -0
- package/dist/clis/imdb/person.js +203 -0
- package/dist/clis/imdb/reviews.d.ts +1 -0
- package/dist/clis/imdb/reviews.js +88 -0
- package/dist/clis/imdb/search.d.ts +1 -0
- package/dist/clis/imdb/search.js +161 -0
- package/dist/clis/imdb/title.d.ts +1 -0
- package/dist/clis/imdb/title.js +93 -0
- package/dist/clis/imdb/top.d.ts +1 -0
- package/dist/clis/imdb/top.js +53 -0
- package/dist/clis/imdb/trending.d.ts +1 -0
- package/dist/clis/imdb/trending.js +52 -0
- package/dist/clis/imdb/utils.d.ts +46 -0
- package/dist/clis/imdb/utils.js +285 -0
- package/dist/clis/imdb/utils.test.d.ts +1 -0
- package/dist/clis/imdb/utils.test.js +88 -0
- package/dist/clis/jd/item.d.ts +4 -0
- package/dist/clis/jd/item.js +16 -15
- package/dist/clis/jd/item.test.js +16 -1
- package/dist/clis/linux-do/categories.yaml +38 -9
- package/dist/clis/linux-do/category.d.ts +1 -0
- package/dist/clis/linux-do/category.js +36 -0
- package/dist/clis/linux-do/feed.d.ts +45 -0
- package/dist/clis/linux-do/feed.js +397 -0
- package/dist/clis/linux-do/feed.test.d.ts +1 -0
- package/dist/clis/linux-do/feed.test.js +118 -0
- package/dist/clis/linux-do/hot.d.ts +1 -0
- package/dist/clis/linux-do/hot.js +25 -0
- package/dist/clis/linux-do/latest.d.ts +1 -0
- package/dist/clis/linux-do/latest.js +18 -0
- package/dist/clis/linux-do/tags.yaml +41 -0
- package/dist/clis/linux-do/topic.yaml +41 -3
- package/dist/clis/linux-do/user-posts.yaml +67 -0
- package/dist/clis/linux-do/user-topics.yaml +54 -0
- package/dist/clis/paperreview/commands.test.d.ts +3 -0
- package/dist/clis/paperreview/commands.test.js +243 -0
- package/dist/clis/paperreview/feedback.d.ts +1 -0
- package/dist/clis/paperreview/feedback.js +52 -0
- package/dist/clis/paperreview/review.d.ts +1 -0
- package/dist/clis/paperreview/review.js +37 -0
- package/dist/clis/paperreview/submit.d.ts +1 -0
- package/dist/clis/paperreview/submit.js +85 -0
- package/dist/clis/paperreview/utils.d.ts +46 -0
- package/dist/clis/paperreview/utils.js +197 -0
- package/dist/clis/paperreview/utils.test.d.ts +1 -0
- package/dist/clis/paperreview/utils.test.js +49 -0
- package/dist/clis/producthunt/browse.d.ts +1 -0
- package/dist/clis/producthunt/browse.js +99 -0
- package/dist/clis/producthunt/hot.d.ts +1 -0
- package/dist/clis/producthunt/hot.js +110 -0
- package/dist/clis/producthunt/posts.d.ts +1 -0
- package/dist/clis/producthunt/posts.js +28 -0
- package/dist/clis/producthunt/today.d.ts +1 -0
- package/dist/clis/producthunt/today.js +35 -0
- package/dist/clis/producthunt/utils.d.ts +29 -0
- package/dist/clis/producthunt/utils.js +99 -0
- package/dist/clis/producthunt/utils.test.d.ts +1 -0
- package/dist/clis/producthunt/utils.test.js +64 -0
- package/dist/clis/twitter/article.js +4 -28
- package/dist/clis/twitter/likes.d.ts +24 -0
- package/dist/clis/twitter/likes.js +217 -0
- package/dist/clis/twitter/likes.test.d.ts +1 -0
- package/dist/clis/twitter/likes.test.js +85 -0
- package/dist/clis/twitter/profile.js +4 -28
- package/dist/clis/twitter/search.js +2 -1
- package/dist/clis/twitter/search.test.js +2 -0
- package/dist/clis/twitter/shared.d.ts +6 -0
- package/dist/clis/twitter/shared.js +35 -0
- package/dist/clis/twitter/timeline.js +2 -13
- package/dist/clis/twitter/trending.js +29 -61
- package/dist/clis/v2ex/hot.yaml +17 -3
- package/dist/clis/weixin/download.d.ts +17 -0
- package/dist/clis/weixin/download.js +88 -20
- package/dist/clis/weread/book.js +2 -2
- package/dist/clis/weread/commands.test.d.ts +3 -0
- package/dist/clis/weread/commands.test.js +43 -0
- package/dist/clis/weread/highlights.js +2 -2
- package/dist/clis/weread/notebooks.js +2 -2
- package/dist/clis/weread/notes.js +3 -3
- package/dist/clis/weread/shelf.js +2 -2
- package/dist/clis/weread/utils.d.ts +4 -4
- package/dist/clis/weread/utils.js +32 -14
- package/dist/clis/weread/utils.test.js +1 -28
- package/dist/clis/xiaohongshu/comments.d.ts +5 -0
- package/dist/clis/xiaohongshu/comments.js +74 -0
- package/dist/clis/xiaohongshu/comments.test.d.ts +1 -0
- package/dist/clis/xiaohongshu/comments.test.js +79 -0
- package/dist/clis/xiaohongshu/publish.js +179 -47
- package/dist/clis/xiaohongshu/publish.test.d.ts +1 -0
- package/dist/clis/xiaohongshu/publish.test.js +131 -0
- package/dist/clis/xiaohongshu/search.d.ts +8 -1
- package/dist/clis/xiaohongshu/search.js +20 -1
- package/dist/clis/xiaohongshu/search.test.d.ts +1 -1
- package/dist/clis/xiaohongshu/search.test.js +32 -1
- package/dist/commanderAdapter.d.ts +1 -0
- package/dist/commanderAdapter.js +176 -29
- package/dist/commanderAdapter.test.d.ts +1 -0
- package/dist/commanderAdapter.test.js +62 -0
- package/dist/daemon.js +17 -1
- package/dist/discovery.js +48 -42
- package/dist/doctor.d.ts +2 -2
- package/dist/doctor.js +11 -4
- package/dist/download/index.js +63 -51
- package/dist/download/index.test.js +17 -4
- package/dist/engine.test.js +42 -0
- package/dist/errors.d.ts +4 -2
- package/dist/errors.js +17 -34
- package/dist/execution.d.ts +1 -3
- package/dist/execution.js +66 -8
- package/dist/execution.test.d.ts +1 -0
- package/dist/execution.test.js +40 -0
- package/dist/external.js +6 -1
- package/dist/hooks.js +2 -0
- package/dist/main.js +6 -0
- package/dist/output.js +5 -1
- package/dist/pipeline/executor.js +3 -4
- package/dist/plugin-manifest.d.ts +70 -0
- package/dist/plugin-manifest.js +160 -0
- package/dist/plugin-manifest.test.d.ts +4 -0
- package/dist/plugin-manifest.test.js +179 -0
- package/dist/plugin-scaffold.d.ts +28 -0
- package/dist/plugin-scaffold.js +142 -0
- package/dist/plugin-scaffold.test.d.ts +4 -0
- package/dist/plugin-scaffold.test.js +83 -0
- package/dist/plugin.d.ts +82 -11
- package/dist/plugin.js +870 -84
- package/dist/plugin.test.js +1032 -17
- package/dist/registry.d.ts +4 -0
- package/dist/registry.js +2 -0
- package/dist/runtime-detect.d.ts +21 -0
- package/dist/runtime-detect.js +32 -0
- package/dist/runtime-detect.test.d.ts +1 -0
- package/dist/runtime-detect.test.js +27 -0
- package/dist/runtime.d.ts +1 -0
- package/dist/runtime.js +2 -2
- package/dist/serialization.d.ts +2 -0
- package/dist/serialization.js +6 -0
- package/dist/types.d.ts +3 -0
- package/dist/update-check.d.ts +22 -0
- package/dist/update-check.js +112 -0
- package/dist/weixin-download.test.d.ts +1 -0
- package/dist/weixin-download.test.js +30 -0
- package/dist/weread-private-api-regression.test.d.ts +1 -0
- package/dist/weread-private-api-regression.test.js +122 -0
- package/dist/yaml-schema.d.ts +3 -0
- package/dist/yaml-schema.js +18 -1
- package/docs/.vitepress/config.mts +4 -0
- package/docs/adapters/browser/36kr.md +47 -0
- package/docs/adapters/browser/bluesky.md +53 -0
- package/docs/adapters/browser/douban.md +14 -0
- package/docs/adapters/browser/imdb.md +47 -0
- package/docs/adapters/browser/jd.md +2 -2
- package/docs/adapters/browser/linux-do.md +181 -20
- package/docs/adapters/browser/paperreview.md +43 -0
- package/docs/adapters/browser/producthunt.md +49 -0
- package/docs/adapters/desktop/chatgpt.md +5 -0
- package/docs/adapters/index.md +6 -2
- package/docs/advanced/download.md +4 -0
- package/docs/advanced/rate-limiter-plugin.md +99 -0
- package/docs/guide/electron-app-cli.md +200 -0
- package/docs/guide/getting-started.md +1 -0
- package/docs/guide/plugins.md +97 -0
- package/docs/zh/guide/electron-app-cli.md +188 -0
- package/docs/zh/guide/getting-started.md +1 -0
- package/docs/zh/guide/plugins.md +65 -0
- package/extension/package.json +1 -0
- package/extension/scripts/package-release.mjs +179 -0
- package/extension/src/background.ts +2 -0
- package/package.json +4 -1
- package/scripts/postinstall.js +10 -0
- package/src/browser/cdp.ts +8 -1
- package/src/browser/discover.ts +8 -3
- package/src/browser/errors.ts +13 -14
- package/src/browser/mcp.ts +2 -1
- package/src/browser/page.ts +24 -1
- package/src/build-manifest.test.ts +23 -0
- package/src/build-manifest.ts +40 -15
- package/src/capabilityRouting.ts +2 -1
- package/src/cli.ts +69 -6
- package/src/clis/36kr/article.ts +69 -0
- package/src/clis/36kr/hot.test.ts +19 -0
- package/src/clis/36kr/hot.ts +100 -0
- package/src/clis/36kr/news.test.ts +90 -0
- package/src/clis/36kr/news.ts +54 -0
- package/src/clis/36kr/search.ts +78 -0
- package/src/clis/bilibili/comments.test.ts +102 -0
- package/src/clis/bilibili/comments.ts +44 -0
- package/src/clis/bluesky/feeds.yaml +29 -0
- package/src/clis/bluesky/followers.yaml +33 -0
- package/src/clis/bluesky/following.yaml +33 -0
- package/src/clis/bluesky/profile.yaml +27 -0
- package/src/clis/bluesky/search.yaml +34 -0
- package/src/clis/bluesky/starter-packs.yaml +34 -0
- package/src/clis/bluesky/thread.yaml +32 -0
- package/src/clis/bluesky/trending.yaml +27 -0
- package/src/clis/bluesky/user.yaml +34 -0
- package/src/clis/chatgpt/ask.ts +28 -14
- package/src/clis/chatgpt/ax.ts +180 -1
- package/src/clis/chatgpt/model.ts +27 -0
- package/src/clis/chatgpt/send.ts +16 -6
- package/src/clis/douban/download.test.ts +196 -0
- package/src/clis/douban/download.ts +78 -0
- package/src/clis/douban/photos.ts +36 -0
- package/src/clis/douban/utils.test.ts +97 -0
- package/src/clis/douban/utils.ts +232 -1
- package/src/clis/imdb/person.ts +232 -0
- package/src/clis/imdb/reviews.ts +111 -0
- package/src/clis/imdb/search.ts +179 -0
- package/src/clis/imdb/title.ts +121 -0
- package/src/clis/imdb/top.ts +67 -0
- package/src/clis/imdb/trending.ts +66 -0
- package/src/clis/imdb/utils.test.ts +117 -0
- package/src/clis/imdb/utils.ts +305 -0
- package/src/clis/jd/item.test.ts +18 -1
- package/src/clis/jd/item.ts +18 -15
- package/src/clis/linux-do/categories.yaml +38 -9
- package/src/clis/linux-do/category.ts +37 -0
- package/src/clis/linux-do/feed.test.ts +132 -0
- package/src/clis/linux-do/feed.ts +501 -0
- package/src/clis/linux-do/hot.ts +26 -0
- package/src/clis/linux-do/latest.ts +19 -0
- package/src/clis/linux-do/tags.yaml +41 -0
- package/src/clis/linux-do/topic.yaml +41 -3
- package/src/clis/linux-do/user-posts.yaml +67 -0
- package/src/clis/linux-do/user-topics.yaml +54 -0
- package/src/clis/paperreview/commands.test.ts +283 -0
- package/src/clis/paperreview/feedback.ts +64 -0
- package/src/clis/paperreview/review.ts +47 -0
- package/src/clis/paperreview/submit.ts +119 -0
- package/src/clis/paperreview/utils.test.ts +68 -0
- package/src/clis/paperreview/utils.ts +276 -0
- package/src/clis/producthunt/browse.ts +109 -0
- package/src/clis/producthunt/hot.ts +127 -0
- package/src/clis/producthunt/posts.ts +29 -0
- package/src/clis/producthunt/today.ts +37 -0
- package/src/clis/producthunt/utils.test.ts +72 -0
- package/src/clis/producthunt/utils.ts +122 -0
- package/src/clis/twitter/article.ts +5 -28
- package/src/clis/twitter/likes.test.ts +91 -0
- package/src/clis/twitter/likes.ts +256 -0
- package/src/clis/twitter/profile.ts +5 -28
- package/src/clis/twitter/search.test.ts +2 -0
- package/src/clis/twitter/search.ts +3 -1
- package/src/clis/twitter/shared.ts +45 -0
- package/src/clis/twitter/timeline.ts +2 -13
- package/src/clis/twitter/trending.ts +29 -77
- package/src/clis/v2ex/hot.yaml +17 -3
- package/src/clis/weixin/download.ts +114 -20
- package/src/clis/weread/book.ts +2 -2
- package/src/clis/weread/commands.test.ts +57 -0
- package/src/clis/weread/highlights.ts +2 -2
- package/src/clis/weread/notebooks.ts +2 -2
- package/src/clis/weread/notes.ts +3 -3
- package/src/clis/weread/shelf.ts +2 -2
- package/src/clis/weread/utils.test.ts +1 -32
- package/src/clis/weread/utils.ts +41 -16
- package/src/clis/xiaohongshu/comments.test.ts +96 -0
- package/src/clis/xiaohongshu/comments.ts +81 -0
- package/src/clis/xiaohongshu/publish.test.ts +151 -0
- package/src/clis/xiaohongshu/publish.ts +206 -54
- package/src/clis/xiaohongshu/search.test.ts +39 -1
- package/src/clis/xiaohongshu/search.ts +19 -1
- package/src/commanderAdapter.test.ts +78 -0
- package/src/commanderAdapter.ts +188 -24
- package/src/daemon.ts +19 -1
- package/src/discovery.ts +49 -48
- package/src/doctor.ts +15 -5
- package/src/download/index.test.ts +14 -4
- package/src/download/index.ts +67 -55
- package/src/engine.test.ts +38 -0
- package/src/errors.ts +26 -63
- package/src/execution.test.ts +47 -0
- package/src/execution.ts +67 -9
- package/src/external.ts +6 -1
- package/src/hooks.ts +1 -0
- package/src/main.ts +7 -0
- package/src/output.ts +3 -1
- package/src/pipeline/executor.ts +4 -6
- package/src/plugin-manifest.test.ts +223 -0
- package/src/plugin-manifest.ts +206 -0
- package/src/plugin-scaffold.test.ts +98 -0
- package/src/plugin-scaffold.ts +170 -0
- package/src/plugin.test.ts +1104 -17
- package/src/plugin.ts +1101 -86
- package/src/registry.ts +6 -1
- package/src/runtime-detect.test.ts +30 -0
- package/src/runtime-detect.ts +36 -0
- package/src/runtime.ts +3 -3
- package/src/serialization.ts +4 -0
- package/src/types.ts +3 -0
- package/src/update-check.ts +114 -0
- package/src/weixin-download.test.ts +64 -0
- package/src/weread-private-api-regression.test.ts +150 -0
- package/src/yaml-schema.ts +20 -0
- package/tests/e2e/browser-auth.test.ts +13 -9
- package/tests/e2e/browser-public-extended.test.ts +1 -1
- package/tests/e2e/browser-public.test.ts +62 -4
- package/tests/e2e/helpers.ts +2 -1
- package/tests/e2e/public-commands.test.ts +37 -3
- package/tests/smoke/api-health.test.ts +1 -1
- package/vitest.config.ts +10 -0
- package/dist/clis/linux-do/category.yaml +0 -51
- package/dist/clis/linux-do/hot.yaml +0 -50
- package/dist/clis/linux-do/latest.yaml +0 -40
- package/src/clis/linux-do/category.yaml +0 -51
- package/src/clis/linux-do/hot.yaml +0 -50
- package/src/clis/linux-do/latest.yaml +0 -40
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: How to turn a new Electron desktop app into an OpenCLI adapter
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Add a New Electron App CLI
|
|
6
|
+
|
|
7
|
+
This guide is the **fast entry point** for turning a new Electron desktop application into an OpenCLI adapter.
|
|
8
|
+
|
|
9
|
+
If you want the full background and deeper SOP, read:
|
|
10
|
+
- [CLI-ifying Electron Applications](/advanced/electron)
|
|
11
|
+
- [Chrome DevTools Protocol](/advanced/cdp)
|
|
12
|
+
- [TypeScript Adapter Guide](/developer/ts-adapter)
|
|
13
|
+
|
|
14
|
+
## When to use this guide
|
|
15
|
+
|
|
16
|
+
Use this workflow when the target app:
|
|
17
|
+
- is built with **Electron**, or at least exposes a working **Chrome DevTools Protocol (CDP)** endpoint
|
|
18
|
+
- can be launched with `--remote-debugging-port=<port>`
|
|
19
|
+
- should be automated through its real UI instead of a public HTTP API
|
|
20
|
+
|
|
21
|
+
If the app is **not** Electron and does **not** expose CDP, use the native desktop automation pattern instead. See [CLI-ifying Electron Applications](/advanced/electron#non-electron-pattern-applescript).
|
|
22
|
+
|
|
23
|
+
## The shortest path
|
|
24
|
+
|
|
25
|
+
### 1. Confirm the app is Electron
|
|
26
|
+
|
|
27
|
+
Typical macOS check:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
ls /Applications/AppName.app/Contents/Frameworks/Electron\ Framework.framework
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
If Electron is present, the next step is usually to launch the app with a debugging port.
|
|
34
|
+
|
|
35
|
+
### 2. Launch it with CDP enabled
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
/Applications/AppName.app/Contents/MacOS/AppName --remote-debugging-port=9222
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then point OpenCLI at that CDP endpoint:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9222"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 3. Start with the 5-command pattern
|
|
48
|
+
|
|
49
|
+
For a new Electron adapter, implement these commands first in `src/clis/<app>/`:
|
|
50
|
+
|
|
51
|
+
- `status.ts` — verify the app is reachable through CDP
|
|
52
|
+
- `dump.ts` — inspect DOM and snapshot structure before guessing selectors
|
|
53
|
+
- `read.ts` — extract the visible context you actually need
|
|
54
|
+
- `send.ts` — inject text and submit through the real editor
|
|
55
|
+
- `new.ts` — create a new session, tab, thread, or document
|
|
56
|
+
|
|
57
|
+
This is the standard baseline because it gives you:
|
|
58
|
+
- a connection check
|
|
59
|
+
- a reverse-engineering tool
|
|
60
|
+
- one read path
|
|
61
|
+
- one write path
|
|
62
|
+
- one session reset path
|
|
63
|
+
|
|
64
|
+
The full rationale and examples are in [CLI-ifying Electron Applications](/advanced/electron).
|
|
65
|
+
|
|
66
|
+
## Recommended implementation workflow
|
|
67
|
+
|
|
68
|
+
### Step 1: Build `status`
|
|
69
|
+
|
|
70
|
+
Goal: prove CDP connectivity before touching app-specific logic.
|
|
71
|
+
|
|
72
|
+
Typical checks:
|
|
73
|
+
- current URL
|
|
74
|
+
- document title
|
|
75
|
+
- app shell presence
|
|
76
|
+
|
|
77
|
+
If `status` is unstable, stop there and fix connectivity first.
|
|
78
|
+
|
|
79
|
+
### Step 2: Build `dump`
|
|
80
|
+
|
|
81
|
+
Do **not** guess selectors from the rendered UI.
|
|
82
|
+
|
|
83
|
+
Dump:
|
|
84
|
+
- `document.body.innerHTML`
|
|
85
|
+
- accessibility snapshot
|
|
86
|
+
- any stable attributes such as `data-testid`, `role`, `aria-*`, framework-specific markers
|
|
87
|
+
|
|
88
|
+
Use the dump to identify real containers, buttons, composers, and conversation regions.
|
|
89
|
+
|
|
90
|
+
### Step 3: Build `read`
|
|
91
|
+
|
|
92
|
+
Target only the app region that matters.
|
|
93
|
+
|
|
94
|
+
Good targets:
|
|
95
|
+
- message list
|
|
96
|
+
- editor history
|
|
97
|
+
- visible thread content
|
|
98
|
+
- selected document panel
|
|
99
|
+
|
|
100
|
+
Avoid dumping the entire page text into the final command output.
|
|
101
|
+
|
|
102
|
+
### Step 4: Build `send`
|
|
103
|
+
|
|
104
|
+
Most Electron apps use React-style controlled editors, so direct `.value = ...` assignments are often ignored.
|
|
105
|
+
|
|
106
|
+
Prefer editor-aware input patterns such as:
|
|
107
|
+
- focus the editable region
|
|
108
|
+
- use `document.execCommand('insertText', false, text)` when applicable
|
|
109
|
+
- use real key presses like `Enter`, `Meta+Enter`, or app-specific shortcuts
|
|
110
|
+
|
|
111
|
+
### Step 5: Build `new`
|
|
112
|
+
|
|
113
|
+
Many desktop apps rely on keyboard shortcuts for “new chat”, “new tab”, or “new note”.
|
|
114
|
+
|
|
115
|
+
Typical pattern:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const isMac = process.platform === 'darwin';
|
|
119
|
+
await page.pressKey(isMac ? 'Meta+N' : 'Control+N');
|
|
120
|
+
await page.wait(1);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Where to put files
|
|
124
|
+
|
|
125
|
+
For a TypeScript desktop adapter, the usual layout is:
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
src/clis/<app>/status.ts
|
|
129
|
+
src/clis/<app>/dump.ts
|
|
130
|
+
src/clis/<app>/read.ts
|
|
131
|
+
src/clis/<app>/send.ts
|
|
132
|
+
src/clis/<app>/new.ts
|
|
133
|
+
src/clis/<app>/utils.ts
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
If the app grows beyond the baseline, add higher-level commands such as:
|
|
137
|
+
- `ask`
|
|
138
|
+
- `history`
|
|
139
|
+
- `model`
|
|
140
|
+
- `screenshot`
|
|
141
|
+
- `export`
|
|
142
|
+
|
|
143
|
+
## What to document when you add a new app
|
|
144
|
+
|
|
145
|
+
When the adapter is ready, also add:
|
|
146
|
+
|
|
147
|
+
- an adapter doc under `docs/adapters/desktop/`
|
|
148
|
+
- command list and examples
|
|
149
|
+
- launch instructions with `--remote-debugging-port`
|
|
150
|
+
- any required environment variables
|
|
151
|
+
- platform-specific caveats
|
|
152
|
+
|
|
153
|
+
Examples to study:
|
|
154
|
+
- `docs/adapters/desktop/codex.md`
|
|
155
|
+
- `docs/adapters/desktop/chatwise.md`
|
|
156
|
+
- `docs/adapters/desktop/notion.md`
|
|
157
|
+
- `docs/adapters/desktop/discord.md`
|
|
158
|
+
|
|
159
|
+
## Common failure modes
|
|
160
|
+
|
|
161
|
+
### CDP endpoint exists, but commands are flaky
|
|
162
|
+
|
|
163
|
+
Usually one of these:
|
|
164
|
+
- the wrong window/tab is selected
|
|
165
|
+
- the app has not finished rendering
|
|
166
|
+
- selectors were guessed instead of discovered from `dump`
|
|
167
|
+
- the editor is controlled and ignores direct value assignment
|
|
168
|
+
|
|
169
|
+
### The app is Chromium-based but not truly controllable
|
|
170
|
+
|
|
171
|
+
Some desktop apps embed Chromium but do not expose a usable CDP surface.
|
|
172
|
+
In that case, switch to the non-Electron desktop automation approach instead of forcing the Electron pattern.
|
|
173
|
+
|
|
174
|
+
### You already have a browser workflow and wonder whether to reuse it
|
|
175
|
+
|
|
176
|
+
If the app exposes a normal web URL and the browser flow is enough, a browser adapter is usually simpler.
|
|
177
|
+
Use an Electron adapter only when the desktop app is the real integration surface.
|
|
178
|
+
|
|
179
|
+
## Recommended reading order
|
|
180
|
+
|
|
181
|
+
If you are starting from zero:
|
|
182
|
+
|
|
183
|
+
1. This page
|
|
184
|
+
2. [CLI-ifying Electron Applications](/advanced/electron)
|
|
185
|
+
3. [Chrome DevTools Protocol](/advanced/cdp)
|
|
186
|
+
4. [TypeScript Adapter Guide](/developer/ts-adapter)
|
|
187
|
+
5. One concrete desktop adapter doc under `docs/adapters/desktop/`
|
|
188
|
+
|
|
189
|
+
## Practical rule
|
|
190
|
+
|
|
191
|
+
Do not start with a large feature surface.
|
|
192
|
+
|
|
193
|
+
Start with:
|
|
194
|
+
- `status`
|
|
195
|
+
- `dump`
|
|
196
|
+
- `read`
|
|
197
|
+
- `send`
|
|
198
|
+
- `new`
|
|
199
|
+
|
|
200
|
+
Once those are stable, extend outward.
|
|
@@ -55,3 +55,4 @@ opencli bilibili hot -v # Verbose: show pipeline debug
|
|
|
55
55
|
- [Plugins — extend with community adapters](/guide/plugins)
|
|
56
56
|
- [All available adapters](/adapters/)
|
|
57
57
|
- [For developers / AI agents](/developer/contributing)
|
|
58
|
+
- [Add a new Electron app CLI](/guide/electron-app-cli)
|
package/docs/guide/plugins.md
CHANGED
|
@@ -31,12 +31,109 @@ Plugins live in `~/.opencli/plugins/<name>/`. Each subdirectory is scanned at st
|
|
|
31
31
|
### Supported Source Formats
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
+
# GitHub shorthand
|
|
34
35
|
opencli plugin install github:user/repo
|
|
36
|
+
opencli plugin install github:user/repo/subplugin # install specific sub-plugin from monorepo
|
|
35
37
|
opencli plugin install https://github.com/user/repo
|
|
38
|
+
|
|
39
|
+
# Any git-cloneable URL
|
|
40
|
+
opencli plugin install https://gitlab.example.com/team/repo.git
|
|
41
|
+
opencli plugin install ssh://git@gitlab.example.com/team/repo.git
|
|
42
|
+
opencli plugin install git@gitlab.example.com:team/repo.git
|
|
43
|
+
|
|
44
|
+
# Local plugin (for development)
|
|
45
|
+
opencli plugin install file:///path/to/plugin
|
|
46
|
+
opencli plugin install /path/to/plugin
|
|
36
47
|
```
|
|
37
48
|
|
|
38
49
|
The repo name prefix `opencli-plugin-` is automatically stripped for the local directory name. For example, `opencli-plugin-hot-digest` becomes `hot-digest`.
|
|
39
50
|
|
|
51
|
+
## Plugin Manifest (`opencli-plugin.json`)
|
|
52
|
+
|
|
53
|
+
Plugins can include an `opencli-plugin.json` manifest file at the repo root to declare metadata:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"name": "my-plugin",
|
|
58
|
+
"version": "1.0.0",
|
|
59
|
+
"opencli": ">=1.0.0",
|
|
60
|
+
"description": "My awesome plugin"
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
| Field | Description |
|
|
65
|
+
|-------|-------------|
|
|
66
|
+
| `name` | Plugin name (overrides repo-derived name) |
|
|
67
|
+
| `version` | Semantic version |
|
|
68
|
+
| `opencli` | Required opencli version range (e.g. `>=1.0.0`, `^1.2.0`) |
|
|
69
|
+
| `description` | Human-readable description |
|
|
70
|
+
| `plugins` | Monorepo sub-plugin declarations (see below) |
|
|
71
|
+
|
|
72
|
+
The manifest is optional — plugins without one continue to work exactly as before.
|
|
73
|
+
|
|
74
|
+
## Monorepo Plugins
|
|
75
|
+
|
|
76
|
+
A single repository can contain multiple plugins by declaring a `plugins` field in `opencli-plugin.json`:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"version": "1.0.0",
|
|
81
|
+
"opencli": ">=1.0.0",
|
|
82
|
+
"description": "My plugin collection",
|
|
83
|
+
"plugins": {
|
|
84
|
+
"polymarket": {
|
|
85
|
+
"path": "packages/polymarket",
|
|
86
|
+
"description": "Prediction market analysis",
|
|
87
|
+
"version": "1.2.0"
|
|
88
|
+
},
|
|
89
|
+
"defi": {
|
|
90
|
+
"path": "packages/defi",
|
|
91
|
+
"description": "DeFi protocol data",
|
|
92
|
+
"version": "0.8.0",
|
|
93
|
+
"opencli": ">=1.2.0"
|
|
94
|
+
},
|
|
95
|
+
"experimental": {
|
|
96
|
+
"path": "packages/experimental",
|
|
97
|
+
"disabled": true
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Installing
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Install ALL enabled sub-plugins from a monorepo
|
|
107
|
+
opencli plugin install github:user/opencli-plugins
|
|
108
|
+
|
|
109
|
+
# Install a SPECIFIC sub-plugin
|
|
110
|
+
opencli plugin install github:user/opencli-plugins/polymarket
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### How It Works
|
|
114
|
+
|
|
115
|
+
- The monorepo is cloned once to `~/.opencli/monorepos/<repo>/`
|
|
116
|
+
- Each sub-plugin gets a symlink in `~/.opencli/plugins/<name>/` pointing to its subdirectory
|
|
117
|
+
- Command discovery works transparently — symlinks are scanned just like regular directories
|
|
118
|
+
- Disabled sub-plugins (with `"disabled": true`) are skipped during install
|
|
119
|
+
- Sub-plugins can specify their own `opencli` compatibility range
|
|
120
|
+
|
|
121
|
+
### Updating
|
|
122
|
+
|
|
123
|
+
Updating any sub-plugin from a monorepo pulls the entire repo and refreshes all sub-plugins:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
opencli plugin update polymarket # updates the monorepo, refreshes all
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Uninstalling
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
opencli plugin uninstall polymarket # removes just this sub-plugin's symlink
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
When the last sub-plugin from a monorepo is uninstalled, the monorepo clone is automatically cleaned up.
|
|
136
|
+
|
|
40
137
|
## Version Tracking
|
|
41
138
|
|
|
42
139
|
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.
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# 给新 Electron 应用生成 CLI
|
|
2
|
+
|
|
3
|
+
这篇文档是把一个新的 Electron 桌面应用接入 OpenCLI 的**中文入口指南**。
|
|
4
|
+
|
|
5
|
+
如果你需要更完整的背景和标准流程,继续看:
|
|
6
|
+
- [Chrome DevTools Protocol(中文)](/zh/advanced/cdp)
|
|
7
|
+
- [CLI-ifying Electron Applications(英文深度版)](/advanced/electron)
|
|
8
|
+
- [TypeScript 适配器开发指南(英文)](/developer/ts-adapter)
|
|
9
|
+
|
|
10
|
+
## 这篇文档适合什么场景
|
|
11
|
+
|
|
12
|
+
当目标应用满足下面条件时,用这套流程:
|
|
13
|
+
- 应用是 **Electron**,或者至少能暴露可用的 **CDP(Chrome DevTools Protocol)** 端口
|
|
14
|
+
- 可以通过 `--remote-debugging-port=<port>` 启动
|
|
15
|
+
- 你希望控制的是桌面应用本身,而不是它背后的公开 HTTP API
|
|
16
|
+
|
|
17
|
+
如果应用**不是** Electron,或者不暴露 CDP,就不要硬套这套方案。那种情况应改用原生桌面自动化方案。可参考 [英文版说明](/advanced/electron#non-electron-pattern-applescript)。
|
|
18
|
+
|
|
19
|
+
## 最短落地路径
|
|
20
|
+
|
|
21
|
+
### 1. 先确认它是不是 Electron
|
|
22
|
+
|
|
23
|
+
macOS 下常见检查方式:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
ls /Applications/AppName.app/Contents/Frameworks/Electron\ Framework.framework
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
如果存在,通常就可以继续尝试 CDP。
|
|
30
|
+
|
|
31
|
+
### 2. 带 CDP 端口启动应用
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
/Applications/AppName.app/Contents/MacOS/AppName --remote-debugging-port=9222
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
然后把 OpenCLI 指到这个端口:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9222"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 3. 先做 5 个基础命令
|
|
44
|
+
|
|
45
|
+
建议一个新 Electron 适配器先实现这 5 个命令:
|
|
46
|
+
|
|
47
|
+
- `status.ts` —— 确认 CDP 连通
|
|
48
|
+
- `dump.ts` —— 导出 DOM / snapshot,先做逆向再写逻辑
|
|
49
|
+
- `read.ts` —— 读取当前上下文
|
|
50
|
+
- `send.ts` —— 往真实编辑器里输入并发送
|
|
51
|
+
- `new.ts` —— 新建会话 / 标签页 / 文档
|
|
52
|
+
|
|
53
|
+
这是最稳妥的基线,因为它先把“能连上、能看见、能读、能写、能重置状态”这 5 件核心事情打通了。
|
|
54
|
+
|
|
55
|
+
## 推荐开发顺序
|
|
56
|
+
|
|
57
|
+
### 第一步:先做 `status`
|
|
58
|
+
|
|
59
|
+
目标不是功能,而是先证明:
|
|
60
|
+
- CDP 真的连上了
|
|
61
|
+
- 你连到的是对的窗口/标签页
|
|
62
|
+
- 应用当前页面确实可读
|
|
63
|
+
|
|
64
|
+
如果 `status` 都不稳定,先不要继续往下做。
|
|
65
|
+
|
|
66
|
+
### 第二步:做 `dump`
|
|
67
|
+
|
|
68
|
+
**不要猜 selector。**
|
|
69
|
+
|
|
70
|
+
先把这些导出来:
|
|
71
|
+
- `document.body.innerHTML`
|
|
72
|
+
- accessibility snapshot
|
|
73
|
+
- 稳定属性:`data-testid`、`role`、`aria-*` 等
|
|
74
|
+
|
|
75
|
+
然后再决定:
|
|
76
|
+
- 消息列表在哪
|
|
77
|
+
- 输入框在哪
|
|
78
|
+
- 按钮在哪
|
|
79
|
+
- 当前会话容器在哪
|
|
80
|
+
|
|
81
|
+
### 第三步:做 `read`
|
|
82
|
+
|
|
83
|
+
只读真正需要的区域,不要把整个页面文本都塞出来。
|
|
84
|
+
|
|
85
|
+
常见目标:
|
|
86
|
+
- 对话消息区
|
|
87
|
+
- 当前线程内容
|
|
88
|
+
- 当前编辑器历史
|
|
89
|
+
- 当前文档主区域
|
|
90
|
+
|
|
91
|
+
### 第四步:做 `send`
|
|
92
|
+
|
|
93
|
+
很多 Electron 应用的输入框是 React 控制组件,直接改 `.value` 往往没用。
|
|
94
|
+
|
|
95
|
+
更稳妥的方式通常是:
|
|
96
|
+
- 先 focus 到可编辑区域
|
|
97
|
+
- 能用时优先 `document.execCommand('insertText', false, text)`
|
|
98
|
+
- 最后用真实按键提交,比如 `Enter`、`Meta+Enter`
|
|
99
|
+
|
|
100
|
+
### 第五步:做 `new`
|
|
101
|
+
|
|
102
|
+
很多桌面应用的新建动作其实更适合走快捷键,而不是点按钮。
|
|
103
|
+
|
|
104
|
+
典型模式:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
const isMac = process.platform === 'darwin';
|
|
108
|
+
await page.pressKey(isMac ? 'Meta+N' : 'Control+N');
|
|
109
|
+
await page.wait(1);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## 文件一般怎么放
|
|
113
|
+
|
|
114
|
+
一个 TypeScript 桌面适配器,通常结构是:
|
|
115
|
+
|
|
116
|
+
```text
|
|
117
|
+
src/clis/<app>/status.ts
|
|
118
|
+
src/clis/<app>/dump.ts
|
|
119
|
+
src/clis/<app>/read.ts
|
|
120
|
+
src/clis/<app>/send.ts
|
|
121
|
+
src/clis/<app>/new.ts
|
|
122
|
+
src/clis/<app>/utils.ts
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
当基础能力稳定后,再继续加:
|
|
126
|
+
- `ask`
|
|
127
|
+
- `history`
|
|
128
|
+
- `model`
|
|
129
|
+
- `screenshot`
|
|
130
|
+
- `export`
|
|
131
|
+
|
|
132
|
+
## 加完适配器后,还应该补什么文档
|
|
133
|
+
|
|
134
|
+
至少补这几项:
|
|
135
|
+
- `docs/adapters/desktop/` 下的适配器说明页
|
|
136
|
+
- 命令列表和示例
|
|
137
|
+
- 如何带 `--remote-debugging-port` 启动
|
|
138
|
+
- 需要哪些环境变量
|
|
139
|
+
- 平台限制和注意事项
|
|
140
|
+
|
|
141
|
+
可以参考这些现成文档:
|
|
142
|
+
- `docs/adapters/desktop/codex.md`
|
|
143
|
+
- `docs/adapters/desktop/chatwise.md`
|
|
144
|
+
- `docs/adapters/desktop/notion.md`
|
|
145
|
+
- `docs/adapters/desktop/discord.md`
|
|
146
|
+
|
|
147
|
+
## 常见问题
|
|
148
|
+
|
|
149
|
+
### CDP 能连,但命令不稳定
|
|
150
|
+
|
|
151
|
+
常见原因:
|
|
152
|
+
- 连错窗口或标签页
|
|
153
|
+
- 页面还没渲染完
|
|
154
|
+
- selector 是猜的,不是从 `dump` 里找出来的
|
|
155
|
+
- 输入框是受控组件,直接赋值不生效
|
|
156
|
+
|
|
157
|
+
### 应用看起来像 Chromium,但就是不好控
|
|
158
|
+
|
|
159
|
+
有些桌面应用虽然嵌了 Chromium,但并不真正暴露可用的 CDP 接口。
|
|
160
|
+
这种情况不要强行走 Electron 方案,应该换到非 Electron 的桌面自动化方案。
|
|
161
|
+
|
|
162
|
+
### 这个应用其实也有网页版本,还要不要做 Electron 适配器
|
|
163
|
+
|
|
164
|
+
如果网页版本已经足够稳定,浏览器适配器通常更简单。
|
|
165
|
+
只有当**桌面应用才是真正的集成面**时,再优先做 Electron 适配器。
|
|
166
|
+
|
|
167
|
+
## 推荐阅读顺序
|
|
168
|
+
|
|
169
|
+
如果你从零开始:
|
|
170
|
+
|
|
171
|
+
1. 先看这篇
|
|
172
|
+
2. 再看 [CLI-ifying Electron Applications(英文深度版)](/advanced/electron)
|
|
173
|
+
3. 再看 [Chrome DevTools Protocol(中文)](/zh/advanced/cdp)
|
|
174
|
+
4. 再看 [TypeScript Adapter Guide(英文)](/developer/ts-adapter)
|
|
175
|
+
5. 最后找一个现成桌面适配器文档照着做
|
|
176
|
+
|
|
177
|
+
## 最后一个实践建议
|
|
178
|
+
|
|
179
|
+
不要一上来就做很大的命令面。
|
|
180
|
+
|
|
181
|
+
先把下面 5 个做稳:
|
|
182
|
+
- `status`
|
|
183
|
+
- `dump`
|
|
184
|
+
- `read`
|
|
185
|
+
- `send`
|
|
186
|
+
- `new`
|
|
187
|
+
|
|
188
|
+
这 5 个稳定了,再往外扩,成本最低,返工也最少。
|
package/docs/zh/guide/plugins.md
CHANGED
|
@@ -32,11 +32,76 @@ Plugins 存放在 `~/.opencli/plugins/<name>/`。每个子目录都会在启动
|
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
34
|
opencli plugin install github:user/repo
|
|
35
|
+
opencli plugin install github:user/repo/subplugin # 安装 monorepo 中的指定子插件
|
|
35
36
|
opencli plugin install https://github.com/user/repo
|
|
36
37
|
```
|
|
37
38
|
|
|
38
39
|
如果仓库名带 `opencli-plugin-` 前缀,本地目录会自动去掉这个前缀。例如 `opencli-plugin-hot-digest` 会变成 `hot-digest`。
|
|
39
40
|
|
|
41
|
+
## 插件清单 (`opencli-plugin.json`)
|
|
42
|
+
|
|
43
|
+
插件可以在仓库根目录放置 `opencli-plugin.json` 来声明元数据:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"name": "my-plugin",
|
|
48
|
+
"version": "1.0.0",
|
|
49
|
+
"opencli": ">=1.0.0",
|
|
50
|
+
"description": "我的插件"
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
| 字段 | 说明 |
|
|
55
|
+
|------|------|
|
|
56
|
+
| `name` | 插件名称(覆盖从仓库名推导的名称) |
|
|
57
|
+
| `version` | 语义化版本 |
|
|
58
|
+
| `opencli` | 所需的 opencli 版本范围(如 `>=1.0.0`、`^1.2.0`) |
|
|
59
|
+
| `description` | 描述 |
|
|
60
|
+
| `plugins` | Monorepo 子插件声明(见下文) |
|
|
61
|
+
|
|
62
|
+
清单文件是可选的——没有它的插件依然可以正常工作。
|
|
63
|
+
|
|
64
|
+
## Monorepo 插件
|
|
65
|
+
|
|
66
|
+
一个仓库可以通过在 `opencli-plugin.json` 中声明 `plugins` 字段来包含多个插件:
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"version": "1.0.0",
|
|
71
|
+
"opencli": ">=1.0.0",
|
|
72
|
+
"description": "我的插件合集",
|
|
73
|
+
"plugins": {
|
|
74
|
+
"polymarket": {
|
|
75
|
+
"path": "packages/polymarket",
|
|
76
|
+
"description": "预测市场分析",
|
|
77
|
+
"version": "1.2.0"
|
|
78
|
+
},
|
|
79
|
+
"defi": {
|
|
80
|
+
"path": "packages/defi",
|
|
81
|
+
"description": "DeFi 协议数据",
|
|
82
|
+
"version": "0.8.0"
|
|
83
|
+
},
|
|
84
|
+
"experimental": {
|
|
85
|
+
"path": "packages/experimental",
|
|
86
|
+
"disabled": true
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# 安装 monorepo 中的全部子插件
|
|
94
|
+
opencli plugin install github:user/opencli-plugins
|
|
95
|
+
|
|
96
|
+
# 安装指定子插件
|
|
97
|
+
opencli plugin install github:user/opencli-plugins/polymarket
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
- Monorepo 只 clone 一次到 `~/.opencli/monorepos/<repo>/`
|
|
101
|
+
- 每个子插件通过 symlink 出现在 `~/.opencli/plugins/<name>/`
|
|
102
|
+
- 更新任何子插件会拉取整个 monorepo 并刷新所有子插件
|
|
103
|
+
- 卸载最后一个子插件时,monorepo 目录会被自动清理
|
|
104
|
+
|
|
40
105
|
## 版本追踪
|
|
41
106
|
|
|
42
107
|
OpenCLI 会把已安装 plugin 的版本记录到 `~/.opencli/plugins.lock.json`。每条记录会保存 plugin source、当前 git commit hash、安装时间,以及最近一次更新时间。只要有这份元数据,`opencli plugin list` 就会显示对应的短 commit hash。
|