publishport-opencli 1.0.1 → 1.0.3
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/README.md +61 -61
- package/README.zh-CN.md +68 -68
- package/cli-manifest.json +502 -59
- package/clis/1688/shared.js +2 -2
- package/clis/36kr/news.js +1 -1
- package/clis/_atlassian/shared.js +1 -1
- package/clis/_shared/article/auth.js +1 -1
- package/clis/_shared/article/publish.js +1 -1
- package/clis/_shared/content-guard.js +1 -1
- package/clis/_shared/self-hosted-sites.js +2 -0
- package/clis/_shared/site-auth.js +1 -1
- package/clis/_shared/token-auth.js +2 -2
- package/clis/_shared/video-publish.js +1 -1
- package/clis/aibase/news.js +1 -1
- package/clis/amazon/shared.js +2 -2
- package/clis/antigravity/SKILL.md +12 -12
- package/clis/antigravity/storage.js +1 -1
- package/clis/apple-podcasts/episodes.js +1 -1
- package/clis/archive/item.js +1 -1
- package/clis/archive/search.js +1 -1
- package/clis/archive/snapshots.js +1 -1
- package/clis/archive/wayback.js +1 -1
- package/clis/arxiv/author.js +1 -1
- package/clis/baijiahao/publish.js +1 -1
- package/clis/bbc/utils.js +1 -1
- package/clis/bloomberg/businessweek.js +1 -1
- package/clis/bloomberg/utils.js +1 -1
- package/clis/booking/search.js +1 -1
- package/clis/boss/utils.js +1 -1
- package/clis/chatgpt/ask.js +1 -1
- package/clis/chatgpt/detail.js +1 -1
- package/clis/chatgpt/history.js +1 -1
- package/clis/chatgpt/project-file-add.js +1 -1
- package/clis/chatgpt/project-list.js +1 -1
- package/clis/chatgpt/utils.js +2 -2
- package/clis/chess/utils.js +1 -1
- package/clis/claude/ask.js +1 -1
- package/clis/claude/history.js +1 -1
- package/clis/claude/utils.js +1 -1
- package/clis/codex/extract-diff.js +1 -1
- package/clis/coingecko/coin.js +1 -1
- package/clis/crates/utils.js +1 -1
- package/clis/csdn/stats.js +1 -1
- package/clis/dblp/utils.js +1 -1
- package/clis/defillama/utils.js +1 -1
- package/clis/devto/publish.js +1 -1
- package/clis/discord-app/utils.js +1 -1
- package/clis/dockerhub/utils.js +1 -1
- package/clis/douban/utils.js +1 -1
- package/clis/douyin/_shared/tos-upload.js +1 -1
- package/clis/douyin/hashtag.js +1 -1
- package/clis/douyin/publish-image.js +1 -1
- package/clis/douyin/publish.js +1 -1
- package/clis/eastmoney/announcement.js +1 -1
- package/clis/eastmoney/rank.js +1 -1
- package/clis/eastmoney/sectors.js +1 -1
- package/clis/endoflife/utils.js +1 -1
- package/clis/flathub/utils.js +1 -1
- package/clis/gemini/detail.js +1 -1
- package/clis/gemini/read.js +1 -1
- package/clis/geogebra/add-circle.js +1 -1
- package/clis/geogebra/add-line.js +1 -1
- package/clis/geogebra/add-point.js +1 -1
- package/clis/geogebra/add-polygon.js +1 -1
- package/clis/geogebra/eval.js +1 -1
- package/clis/geogebra/hexagon.js +1 -1
- package/clis/geogebra/info.js +1 -1
- package/clis/geogebra/triangle.js +1 -1
- package/clis/ghost/login.js +1 -0
- package/clis/ghost/publish.js +1 -1
- package/clis/ghost/shared.js +24 -1
- package/clis/ghost/sites.js +1 -0
- package/clis/ghost/whoami.js +1 -1
- package/clis/gitee/user.js +2 -2
- package/clis/github-trending/repos.js +1 -1
- package/clis/goproxy/utils.js +1 -1
- package/clis/grok/export-all.js +1 -1
- package/clis/grok/export.js +1 -1
- package/clis/hashnode/publish.js +1 -1
- package/clis/hf/datasets.js +1 -1
- package/clis/hf/models.js +1 -1
- package/clis/hf/paper.js +1 -1
- package/clis/hf/spaces.js +1 -1
- package/clis/homebrew/utils.js +1 -1
- package/clis/instagram/note.js +1 -1
- package/clis/jimeng/generate.js +1 -1
- package/clis/juejin/utils.js +1 -1
- package/clis/kuaishou/publish.js +1 -1
- package/clis/lesswrong/tag.js +1 -1
- package/clis/lichess/utils.js +1 -1
- package/clis/linkedin/search.js +2 -2
- package/clis/linux-do/feed.js +2 -2
- package/clis/lobsters/domain.js +1 -1
- package/clis/mastodon/login.js +1 -0
- package/clis/mastodon/post.js +1 -1
- package/clis/mastodon/shared.js +10 -10
- package/clis/mastodon/sites.js +1 -0
- package/clis/mastodon/whoami.js +1 -1
- package/clis/maven/utils.js +1 -1
- package/clis/mdn/search.js +1 -1
- package/clis/medium/tag.js +1 -1
- package/clis/notebooklm/current.js +1 -1
- package/clis/notebooklm/get.js +1 -1
- package/clis/notebooklm/history.js +1 -1
- package/clis/notebooklm/note-list.js +1 -1
- package/clis/notebooklm/notes-get.js +1 -1
- package/clis/notebooklm/open.js +1 -1
- package/clis/notebooklm/source-fulltext.js +1 -1
- package/clis/notebooklm/source-get.js +1 -1
- package/clis/notebooklm/source-guide.js +1 -1
- package/clis/notebooklm/source-list.js +1 -1
- package/clis/notebooklm/summary.js +1 -1
- package/clis/notebooklm/utils.js +1 -1
- package/clis/npm/utils.js +1 -1
- package/clis/nuget/utils.js +1 -1
- package/clis/nvd/cve.js +1 -1
- package/clis/oeis/utils.js +1 -1
- package/clis/ones/common.js +2 -2
- package/clis/ones/me.js +1 -1
- package/clis/ones/tasks.js +1 -1
- package/clis/ones/token-info.js +1 -1
- package/clis/ones/worklog.js +1 -1
- package/clis/openalex/utils.js +1 -1
- package/clis/oschina/stats.js +1 -1
- package/clis/osv/utils.js +1 -1
- package/clis/packagist/utils.js +1 -1
- package/clis/pixiv/detail.js +1 -1
- package/clis/pixiv/user.js +1 -1
- package/clis/producthunt/utils.js +1 -1
- package/clis/pypi/utils.js +1 -1
- package/clis/qiita/gql.js +2 -2
- package/clis/rest-countries/utils.js +1 -1
- package/clis/rfc/utils.js +1 -1
- package/clis/rubygems/utils.js +1 -1
- package/clis/semanticscholar/utils.js +1 -1
- package/clis/slock/errors.js +1 -1
- package/clis/spotify/spotify.js +1 -1
- package/clis/spotify/utils.js +1 -1
- package/clis/stackoverflow/utils.js +1 -1
- package/clis/steam/utils.js +1 -1
- package/clis/substack/auth.js +2 -2
- package/clis/suno/generate.js +2 -2
- package/clis/suno/list.js +3 -3
- package/clis/telegram/send.js +1 -1
- package/clis/tiktok/creator-videos.js +1 -1
- package/clis/tiktok/publish.js +1 -1
- package/clis/tiktok/utils.js +1 -1
- package/clis/trae-cn/activity.js +1 -1
- package/clis/trae-cn/approve.js +1 -1
- package/clis/trae-cn/ask.js +1 -1
- package/clis/trae-cn/dump.js +1 -1
- package/clis/trae-cn/export.js +1 -1
- package/clis/trae-cn/model.js +1 -1
- package/clis/trae-cn/new.js +1 -1
- package/clis/trae-cn/read.js +1 -1
- package/clis/trae-cn/screenshot.js +1 -1
- package/clis/trae-cn/select-model.js +1 -1
- package/clis/trae-cn/send.js +1 -1
- package/clis/trae-cn/setup.js +1 -1
- package/clis/trae-cn/status.js +1 -1
- package/clis/trae-cn/targets.js +1 -1
- package/clis/trae-cn/watch.js +1 -1
- package/clis/trae-solo/state-fs.js +1 -1
- package/clis/tumblr/publish.js +1 -1
- package/clis/tvmaze/utils.js +1 -1
- package/clis/twitter/bookmark-folder.js +1 -1
- package/clis/twitter/download.js +1 -1
- package/clis/twitter/followers.js +2 -2
- package/clis/twitter/following.js +2 -2
- package/clis/twitter/likes.js +1 -1
- package/clis/twitter/list-add-batch.js +1 -1
- package/clis/twitter/list-add-core.js +1 -1
- package/clis/twitter/list-add.js +1 -1
- package/clis/twitter/list-create.js +1 -1
- package/clis/twitter/list-delete.js +3 -3
- package/clis/twitter/list-remove-batch.js +1 -1
- package/clis/twitter/list-remove.js +1 -1
- package/clis/twitter/list-tweets.js +1 -1
- package/clis/twitter/profile.js +1 -1
- package/clis/twitter/search.js +1 -1
- package/clis/twitter/shared.js +1 -1
- package/clis/twitter/tweets.js +1 -1
- package/clis/uisdc/news.js +1 -1
- package/clis/v2ex/daily.js +2 -2
- package/clis/v2ex/me.js +2 -2
- package/clis/v2ex/notifications.js +1 -1
- package/clis/wikidata/utils.js +1 -1
- package/clis/wikipedia/page.js +2 -2
- package/clis/wikipedia/summary.js +1 -1
- package/clis/wikipedia/utils.js +1 -1
- package/clis/wordpress/login.js +1 -1
- package/clis/wordpress/publish.js +1 -1
- package/clis/wordpress/shared.js +3 -3
- package/clis/wordpress/sites.js +1 -0
- package/clis/wordpress/whoami.js +1 -1
- package/clis/woshipm/stats.js +1 -1
- package/clis/xiaoe/content.js +1 -1
- package/clis/xiaohongshu/draft-delete.js +1 -1
- package/clis/xiaohongshu/draft-open.js +1 -1
- package/clis/xiaohongshu/draft-utils.js +2 -2
- package/clis/xiaohongshu/publish-video.js +1 -1
- package/clis/xiaohongshu/publish.js +1 -1
- package/clis/xiaoyuzhou/auth.js +1 -1
- package/clis/xiaoyuzhou/transcript.js +1 -1
- package/clis/yollomi/background.js +1 -1
- package/clis/yollomi/edit.js +1 -1
- package/clis/yollomi/generate.js +1 -1
- package/clis/yollomi/try-on.js +1 -1
- package/clis/youtube/publish.js +1 -1
- package/clis/zhihu/answer-comments.js +1 -1
- package/clis/zhihu/answer-detail.js +1 -1
- package/clis/zhihu/collection.js +2 -2
- package/clis/zhihu/collections.js +1 -1
- package/clis/zhihu/question.js +1 -1
- package/clis/zhihu/search.js +1 -1
- package/clis/zhihu/target.js +1 -1
- package/clis/zhihu/user-arg.js +1 -1
- package/dist/src/adapter-shadow.js +1 -1
- package/dist/src/browser/analyze.js +1 -1
- package/dist/src/browser/article-extract.d.ts +1 -1
- package/dist/src/browser/base-page.js +3 -3
- package/dist/src/browser/cdp.js +1 -1
- package/dist/src/browser/daemon-client.d.ts +1 -1
- package/dist/src/browser/daemon-lifecycle.js +6 -6
- package/dist/src/browser/daemon-version.js +1 -1
- package/dist/src/browser/dom-snapshot.d.ts +1 -1
- package/dist/src/browser/dom-snapshot.js +2 -2
- package/dist/src/browser/errors.js +2 -2
- package/dist/src/browser/network-cache.js +1 -1
- package/dist/src/browser/profile.js +1 -1
- package/dist/src/browser/target-resolver.js +4 -4
- package/dist/src/browser/verify-fixture.js +1 -1
- package/dist/src/browser-session-lock.js +1 -1
- package/dist/src/build-manifest.d.ts +1 -1
- package/dist/src/build-manifest.js +1 -1
- package/dist/src/cli-argv-preprocess.d.ts +4 -4
- package/dist/src/cli-argv-preprocess.js +1 -1
- package/dist/src/cli.d.ts +1 -1
- package/dist/src/cli.js +19 -19
- package/dist/src/commanderAdapter.js +1 -1
- package/dist/src/commands/auth.js +2 -2
- package/dist/src/commands/daemon.d.ts +4 -4
- package/dist/src/commands/daemon.js +1 -1
- package/dist/src/completion-shared.js +12 -12
- package/dist/src/completion.d.ts +2 -2
- package/dist/src/constants.d.ts +1 -1
- package/dist/src/constants.js +1 -1
- package/dist/src/daemon-utils.d.ts +1 -1
- package/dist/src/daemon-utils.js +1 -1
- package/dist/src/daemon.d.ts +2 -2
- package/dist/src/daemon.js +1 -1
- package/dist/src/discovery.d.ts +7 -7
- package/dist/src/discovery.js +2 -2
- package/dist/src/doctor.d.ts +1 -1
- package/dist/src/doctor.js +6 -6
- package/dist/src/electron-apps.d.ts +1 -1
- package/dist/src/electron-apps.js +1 -1
- package/dist/src/errors.d.ts +2 -2
- package/dist/src/errors.js +1 -1
- package/dist/src/execution.js +1 -1
- package/dist/src/external.d.ts +1 -1
- package/dist/src/external.js +1 -1
- package/dist/src/help.d.ts +1 -1
- package/dist/src/help.js +3 -3
- package/dist/src/hooks.d.ts +1 -1
- package/dist/src/launcher.js +2 -2
- package/dist/src/logger.d.ts +1 -1
- package/dist/src/main.d.ts +1 -1
- package/dist/src/main.js +1 -1
- package/dist/src/observation/artifact.js +2 -2
- package/dist/src/package-paths.js +1 -1
- package/dist/src/package-paths.test.d.ts +1 -0
- package/dist/src/plugin-manifest.d.ts +12 -3
- package/dist/src/plugin-manifest.js +1 -1
- package/dist/src/plugin-scaffold.d.ts +2 -2
- package/dist/src/plugin-scaffold.js +9 -9
- package/dist/src/plugin.d.ts +4 -4
- package/dist/src/plugin.js +10 -10
- package/dist/src/rate-limit.js +1 -1
- package/dist/src/registry-api.d.ts +1 -1
- package/dist/src/runtime-detect.d.ts +1 -1
- package/dist/src/serialization.js +1 -1
- package/dist/src/skills.js +6 -6
- package/dist/src/user-runtime.d.ts +8 -0
- package/dist/src/user-runtime.js +1 -0
- package/dist/src/user-runtime.test.d.ts +1 -0
- package/dist/src/validate.js +1 -1
- package/dist/src/validate.test.d.ts +1 -1
- package/docs/guide/browser-bridge.md +23 -23
- package/docs/guide/electron-app-cli.md +3 -3
- package/docs/guide/exit-codes.md +3 -3
- package/docs/guide/extending-opencli.md +37 -37
- package/docs/guide/getting-started.md +19 -19
- package/docs/guide/installation.md +6 -6
- package/docs/guide/plugins.md +32 -32
- package/docs/guide/remote-orchestration.md +5 -5
- package/docs/guide/troubleshooting.md +9 -9
- package/package.json +3 -2
- package/scripts/fetch-adapters.js +6 -6
- package/scripts/postinstall.js +14 -14
- package/skills/opencli-adapter-author/SKILL.md +24 -24
- package/skills/opencli-adapter-author/references/adapter-template.md +13 -13
- package/skills/opencli-adapter-author/references/api-discovery.md +25 -25
- package/skills/opencli-adapter-author/references/coverage-matrix.md +3 -3
- package/skills/opencli-adapter-author/references/field-decode-playbook.md +10 -10
- package/skills/opencli-adapter-author/references/jsdom-fixture-pattern.md +2 -2
- package/skills/opencli-adapter-author/references/site-memory.md +11 -11
- package/skills/opencli-adapter-author/references/site-recon.md +7 -7
- package/skills/opencli-adapter-author/references/strategy-selection.md +3 -3
- package/skills/opencli-adapter-author/references/success-rate-pitfalls.md +4 -4
- package/skills/opencli-adapter-author/references/typed-errors.md +2 -2
- package/skills/opencli-autofix/SKILL.md +29 -29
- package/skills/opencli-browser/SKILL.md +55 -55
- package/skills/opencli-browser-sitemap/SKILL.md +7 -7
- package/skills/opencli-sitemap-author/SKILL.md +11 -11
- package/skills/opencli-sitemap-author/references/sitemap-schema.md +19 -19
- package/skills/opencli-usage/SKILL.md +43 -43
package/dist/src/validate.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{getRegistry as O,fullName as M}from"./registry.js";import{getRegisteredStepNames as Q}from"./pipeline/registry.js";function U(){return new Set(Q())}export function validateClisWithTarget(q,F){const x=O(),B=[];let I=0,H=0;if(x.size===0)return{ok:!0,results:[{label:"(registry)",errors:[],warnings:["Registry is empty — no commands discovered. Did discoverClis() run?"]}],errors:0,warnings:1,commands:0};let D=F;if(F?.includes("/")){const G=x.get(F);if(G)D=M(G)}const E=new Set;for(const[G,J]of x){if(E.has(J))continue;if(G!==M(J))continue;E.add(J);if(D){if(D.includes("/")){if(G!==D)continue}else if(J.site!==D)continue}const L=V(J);B.push(L);I+=L.errors.length;H+=L.warnings.length}return{ok:I===0,results:B,errors:I,warnings:H,commands:B.length}}function V(q){const F=M(q),x=[],B=[];if(!q.description)B.push("Missing description");if(q.browser&&!q.domain)B.push('Browser command without "domain" — authenticated browser context may not work');if(Array.isArray(q.pipeline)){const H=U();for(let D=0;D<q.pipeline.length;D++){const E=q.pipeline[D];if(E&&typeof E==="object"){for(const G of Object.keys(E))if(!H.has(G))B.push(`Pipeline step ${D}: unknown step name "${G}" (did you mean one of: ${[...H].join(", ")}?)`)}}}const I=q;if(!q.func&&!q.pipeline&&!I._lazy)x.push('Command has neither "func" nor "pipeline" — it cannot execute');if(q.args&&q.args.length>0){const H=new Set;let D=!1;for(const E of q.args){if(H.has(E.name))x.push(`Duplicate arg name "${E.name}"`);H.add(E.name);if(E.positional&&D)B.push(`Positional arg "${E.name}" appears after named args`);if(!E.positional)D=!0}}return{label:F,errors:x,warnings:B}}export function renderValidationReport(q){const F=[`
|
|
1
|
+
import{getRegistry as O,fullName as M}from"./registry.js";import{getRegisteredStepNames as Q}from"./pipeline/registry.js";function U(){return new Set(Q())}export function validateClisWithTarget(q,F){const x=O(),B=[];let I=0,H=0;if(x.size===0)return{ok:!0,results:[{label:"(registry)",errors:[],warnings:["Registry is empty — no commands discovered. Did discoverClis() run?"]}],errors:0,warnings:1,commands:0};let D=F;if(F?.includes("/")){const G=x.get(F);if(G)D=M(G)}const E=new Set;for(const[G,J]of x){if(E.has(J))continue;if(G!==M(J))continue;E.add(J);if(D){if(D.includes("/")){if(G!==D)continue}else if(J.site!==D)continue}const L=V(J);B.push(L);I+=L.errors.length;H+=L.warnings.length}return{ok:I===0,results:B,errors:I,warnings:H,commands:B.length}}function V(q){const F=M(q),x=[],B=[];if(!q.description)B.push("Missing description");if(q.browser&&!q.domain)B.push('Browser command without "domain" — authenticated browser context may not work');if(Array.isArray(q.pipeline)){const H=U();for(let D=0;D<q.pipeline.length;D++){const E=q.pipeline[D];if(E&&typeof E==="object"){for(const G of Object.keys(E))if(!H.has(G))B.push(`Pipeline step ${D}: unknown step name "${G}" (did you mean one of: ${[...H].join(", ")}?)`)}}}const I=q;if(!q.func&&!q.pipeline&&!I._lazy)x.push('Command has neither "func" nor "pipeline" — it cannot execute');if(q.args&&q.args.length>0){const H=new Set;let D=!1;for(const E of q.args){if(H.has(E.name))x.push(`Duplicate arg name "${E.name}"`);H.add(E.name);if(E.positional&&D)B.push(`Positional arg "${E.name}" appears after named args`);if(!E.positional)D=!0}}return{label:F,errors:x,warnings:B}}export function renderValidationReport(q){const F=[`ppcli validate: ${q.ok?"PASS":"FAIL"}`,`Checked ${q.commands} command(s)`,`Errors: ${q.errors} Warnings: ${q.warnings}`];for(const x of q.results)if(x.errors.length>0||x.warnings.length>0){F.push(`
|
|
2
2
|
${x.label}:`);for(const B of x.errors)F.push(` ❌ ${B}`);for(const B of x.warnings)F.push(` ⚠️ ${B}`)}return F.join(`
|
|
3
3
|
`)}
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* Focus: regression guards for the "single source of truth" link between
|
|
5
5
|
* pipeline step registry (src/pipeline/registry.ts) and validate.ts step
|
|
6
6
|
* allowlist. A new step registered via `registerStep()` must automatically
|
|
7
|
-
* be allowlisted by `
|
|
7
|
+
* be allowlisted by `ppcli validate` — no parallel hand-maintained list.
|
|
8
8
|
*/
|
|
9
9
|
export {};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **⚠️ Important**: Browser commands reuse your Chrome login session. You must be logged into the target website in Chrome before running commands.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
ppcli connects to your browser through a lightweight **Browser Bridge** Chrome Extension + micro-daemon (zero config, auto-start).
|
|
6
6
|
|
|
7
7
|
## Extension Installation
|
|
8
8
|
|
|
@@ -22,7 +22,7 @@ OpenCLI connects to your browser through a lightweight **Browser Bridge** Chrome
|
|
|
22
22
|
That's it! The daemon auto-starts when you run any browser command. No tokens, no manual configuration.
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
|
|
25
|
+
ppcli doctor # Check extension + daemon connectivity
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
## Tab Targeting
|
|
@@ -30,49 +30,49 @@ opencli doctor # Check extension + daemon connectivity
|
|
|
30
30
|
Browser commands require an explicit `<session>` positional immediately after `browser`. Use the same session name for a multi-step flow, and use different names to isolate parallel work.
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
ppcli browser baidu open https://www.baidu.com/
|
|
34
|
+
ppcli browser baidu tab list
|
|
35
|
+
ppcli browser baidu tab new https://www.baidu.com/
|
|
36
|
+
ppcli browser baidu eval --tab <targetId> 'document.title'
|
|
37
|
+
ppcli browser baidu tab select <targetId>
|
|
38
|
+
ppcli browser baidu get title
|
|
39
|
+
ppcli browser baidu tab close <targetId>
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Key rules:
|
|
43
43
|
|
|
44
|
-
- `
|
|
45
|
-
- `
|
|
44
|
+
- `ppcli browser <session> open <url>` and `ppcli browser <session> tab new [url]` return a `targetId`.
|
|
45
|
+
- `ppcli browser <session> tab list` prints the `targetId` values of tabs that already exist.
|
|
46
46
|
- `--tab <targetId>` routes a single browser command to that specific tab.
|
|
47
47
|
- `tab new` creates a new tab but does not change the default browser target.
|
|
48
|
-
- `tab select <targetId>` makes that tab the default target for later untargeted `
|
|
48
|
+
- `tab select <targetId>` makes that tab the default target for later untargeted `ppcli browser ...` commands.
|
|
49
49
|
- `tab close <targetId>` removes the tab; if it was the current default target, the stored default is cleared.
|
|
50
50
|
|
|
51
51
|
## Session Lifecycle
|
|
52
52
|
|
|
53
|
-
Use a stable session name when you want multiple `
|
|
53
|
+
Use a stable session name when you want multiple `ppcli browser` commands to keep operating on the same page:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
ppcli browser my-session open https://example.com
|
|
57
|
+
ppcli browser my-session state
|
|
58
|
+
ppcli browser my-session extract "main"
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
Owned browser sessions use an interactive tab lease with a 10-minute idle timeout. Release it explicitly when done:
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
-
|
|
64
|
+
ppcli browser my-session close
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
Use `
|
|
67
|
+
Use `ppcli browser <session> bind` when you want to attach ppcli to a Chrome tab you already opened manually. Bound sessions do not have the owned-session idle close timer; they stay attached until `unbind`, tab close, window close, or daemon restart. For owned sessions, use `--window foreground` to watch ppcli work in a visible automation window, or `--window background` to keep that automation window out of the way.
|
|
68
68
|
|
|
69
|
-
The `
|
|
69
|
+
The `ppcli Browser` and `ppcli Adapter` tab groups are extension-managed automation containers; avoid putting your own long-lived tabs in them or renaming them.
|
|
70
70
|
|
|
71
71
|
## How It Works
|
|
72
72
|
|
|
73
73
|
```
|
|
74
74
|
┌─────────────┐ WebSocket ┌──────────────┐ Chrome API ┌─────────┐
|
|
75
|
-
│
|
|
75
|
+
│ ppcli │ ◄──────────────► │ micro-daemon │ ◄──────────────► │ Chrome │
|
|
76
76
|
│ (Node.js) │ localhost:19825 │ (auto-start) │ Extension │ Browser │
|
|
77
77
|
└─────────────┘ └──────────────┘ └─────────┘
|
|
78
78
|
```
|
|
@@ -84,11 +84,11 @@ The daemon manages the WebSocket connection between your CLI commands and the Ch
|
|
|
84
84
|
The daemon auto-starts on first browser command and stays alive persistently.
|
|
85
85
|
|
|
86
86
|
```bash
|
|
87
|
-
|
|
87
|
+
ppcli daemon stop # Graceful shutdown
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
The daemon is persistent — it stays alive until you explicitly stop it (`
|
|
90
|
+
The daemon is persistent — it stays alive until you explicitly stop it (`ppcli daemon stop`) or uninstall the package.
|
|
91
91
|
|
|
92
|
-
## Running
|
|
92
|
+
## Running ppcli from a remote machine
|
|
93
93
|
|
|
94
94
|
If you need to run `opencli` on a remote server (CI runner, agent host) but keep the browser session on your local machine, see [Remote Orchestration](/guide/remote-orchestration). It walks through the SSH reverse-tunnel pattern so the daemon never leaves localhost.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: How to turn a new Electron desktop app into an
|
|
2
|
+
description: How to turn a new Electron desktop app into an ppcli adapter
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# Add a New Electron App CLI
|
|
6
6
|
|
|
7
|
-
This guide is the **fast entry point** for turning a new Electron desktop application into an
|
|
7
|
+
This guide is the **fast entry point** for turning a new Electron desktop application into an ppcli adapter.
|
|
8
8
|
|
|
9
9
|
If you want the full background and deeper SOP, read:
|
|
10
10
|
- [CLI-ifying Electron Applications](/advanced/electron)
|
|
@@ -38,7 +38,7 @@ If Electron is present, the next step is usually to launch the app with a debugg
|
|
|
38
38
|
/Applications/AppName.app/Contents/MacOS/AppName --remote-debugging-port=<unique-port>
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
Then point
|
|
41
|
+
Then point ppcli at that CDP endpoint:
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
44
|
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:<unique-port>"
|
package/docs/guide/exit-codes.md
CHANGED
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
## Example: branch on exit code
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
|
|
20
|
+
ppcli spotify status || echo "exit $?" # 69 if browser not running
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
[ $? -eq 77 ] &&
|
|
22
|
+
ppcli gh issue list 2>/dev/null
|
|
23
|
+
[ $? -eq 77 ] && ppcli gh auth login # auto-auth if not logged in
|
|
24
24
|
```
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
# Extending
|
|
1
|
+
# Extending ppcli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
ppcli has five extension paths. Pick the path based on where you want the source code to live and how you want commands to be shared.
|
|
4
4
|
|
|
5
5
|
| Goal | Use | Source location | Command surface |
|
|
6
6
|
|------|-----|-----------------|-----------------|
|
|
7
|
-
| Build a personal website command in your own Git repo | Local plugin | Your project directory, symlinked into `~/.
|
|
8
|
-
| Quickly draft a private adapter on this machine | User adapter | `~/.
|
|
9
|
-
| Edit an official adapter locally | Adapter override | `~/.
|
|
10
|
-
| Publish or install third-party commands | Plugin | Git repo, installed into `~/.
|
|
11
|
-
| Wrap an existing local binary | External CLI | `~/.
|
|
7
|
+
| Build a personal website command in your own Git repo | Local plugin | Your project directory, symlinked into `~/.ppcli/plugins/` | `ppcli <plugin> <command>` |
|
|
8
|
+
| Quickly draft a private adapter on this machine | User adapter | `~/.ppcli/clis/<site>/<command>.js` | `ppcli <site> <command>` |
|
|
9
|
+
| Edit an official adapter locally | Adapter override | `~/.ppcli/clis/<site>/` | `ppcli <site> <command>` |
|
|
10
|
+
| Publish or install third-party commands | Plugin | Git repo, installed into `~/.ppcli/plugins/` | `ppcli <plugin> <command>` |
|
|
11
|
+
| Wrap an existing local binary | External CLI | `~/.ppcli/external-clis.yaml` | `ppcli <tool> ...` |
|
|
12
12
|
|
|
13
13
|
## Personal commands in your own Git repo
|
|
14
14
|
|
|
15
15
|
Use a local plugin when you want the code to stay in a normal project directory and be managed by Git.
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
|
|
18
|
+
ppcli plugin create my-cnn
|
|
19
19
|
cd my-cnn
|
|
20
20
|
git init
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
ppcli plugin install file://$(pwd)
|
|
22
|
+
ppcli my-cnn hello
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
`plugin install file://...` creates a symlink under `~/.
|
|
25
|
+
`plugin install file://...` creates a symlink under `~/.ppcli/plugins/`. Your source files stay in your project directory, so edits and commits happen there.
|
|
26
26
|
|
|
27
27
|
This is the recommended path for custom commands you own long-term.
|
|
28
28
|
|
|
29
|
-
## Private adapters in `~/.
|
|
29
|
+
## Private adapters in `~/.ppcli/clis`
|
|
30
30
|
|
|
31
31
|
Use a user adapter when you want the fastest local adapter loop and do not need a separate project directory.
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
|
|
35
|
-
# edit ~/.
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
ppcli browser init cnn/top
|
|
35
|
+
# edit ~/.ppcli/clis/cnn/top.js
|
|
36
|
+
ppcli browser verify cnn/top
|
|
37
|
+
ppcli cnn top
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
User adapters are loaded from:
|
|
41
41
|
|
|
42
42
|
```text
|
|
43
|
-
~/.
|
|
43
|
+
~/.ppcli/clis/<site>/<command>.js
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
This path is convenient for quick local automation. For code you want to version, review, or share, prefer a plugin.
|
|
@@ -48,11 +48,11 @@ This path is convenient for quick local automation. For code you want to version
|
|
|
48
48
|
If the command takes required positional args and no fixture exists yet, seed the first verify run explicitly:
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
ppcli browser verify instagram/collection-create --write-fixture --seed-args opencli-verify
|
|
52
|
+
ppcli browser verify example/detail --write-fixture --seed-args '["https://example.com/item/1", "--limit", 3]'
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
`--seed-args` is only used when the fixture has no `args`. Once the fixture is written, `
|
|
55
|
+
`--seed-args` is only used when the fixture has no `args`. Once the fixture is written, `ppcli browser verify` reads args from `~/.ppcli/sites/<site>/verify/<command>.json`.
|
|
56
56
|
|
|
57
57
|
`browser verify` also enforces row shape before fixture checks: each row should
|
|
58
58
|
stay compact (at most 12 top-level keys), avoid nesting deeper than one level,
|
|
@@ -63,28 +63,28 @@ and keep id-shaped fields such as `id` / `user_id` at the top level.
|
|
|
63
63
|
Use `adapter eject` when you want to customize an existing official adapter.
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
|
-
|
|
67
|
-
# edit ~/.
|
|
68
|
-
|
|
66
|
+
ppcli adapter eject twitter
|
|
67
|
+
# edit ~/.ppcli/clis/twitter/*.js
|
|
68
|
+
ppcli adapter reset twitter
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
Files in `~/.
|
|
71
|
+
Files in `~/.ppcli/clis/<site>/<command>.js` override packaged adapters with the same `site/command` on this machine. `ppcli browser verify <site>/<command>` also runs the local override, so a passing local verify does not prove that the packaged adapter was changed.
|
|
72
72
|
|
|
73
73
|
The packaged `cli-manifest.json` only describes bundled adapters. User adapters are discovered at runtime and do not need manifest entries.
|
|
74
74
|
|
|
75
|
-
After copying a local fix into the repository for a PR, remove the local copy or run `
|
|
75
|
+
After copying a local fix into the repository for a PR, remove the local copy or run `ppcli adapter reset <site>` after merge. Otherwise the local file keeps shadowing future package updates. `ppcli doctor` warns when it detects this shadowing.
|
|
76
76
|
|
|
77
77
|
## Plugins for sharing commands
|
|
78
78
|
|
|
79
79
|
Plugins are third-party command packages. They can be installed from GitHub, any git-cloneable URL, or a local directory.
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
ppcli plugin install github:user/opencli-plugin-my-tool
|
|
83
|
+
ppcli plugin install https://github.com/user/opencli-plugin-my-tool
|
|
84
|
+
ppcli plugin install file:///absolute/path/to/plugin
|
|
85
|
+
ppcli plugin list
|
|
86
|
+
ppcli plugin update --all
|
|
87
|
+
ppcli plugin uninstall my-tool
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
Each plugin directory is scanned for `.ts` and `.js` command files. TypeScript plugins are transpiled during install.
|
|
@@ -105,15 +105,15 @@ For a Git-hosted plugin collection, declare sub-plugins in `opencli-plugin.json`
|
|
|
105
105
|
```
|
|
106
106
|
|
|
107
107
|
```bash
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
ppcli plugin install github:user/opencli-plugins
|
|
109
|
+
ppcli plugin install github:user/opencli-plugins/cnn
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
For local development, install each sub-plugin directory directly:
|
|
113
113
|
|
|
114
114
|
```bash
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
ppcli plugin install file:///absolute/path/opencli-plugins/packages/cnn
|
|
116
|
+
ppcli plugin install file:///absolute/path/opencli-plugins/packages/reuters
|
|
117
117
|
```
|
|
118
118
|
|
|
119
119
|
Local `file://` installs expect the target directory itself to be a valid plugin with command files. For a monorepo root, push it to GitHub and install it with the GitHub monorepo flow.
|
|
@@ -123,12 +123,12 @@ Local `file://` installs expect the target directory itself to be a valid plugin
|
|
|
123
123
|
Use external CLI registration when the command already exists as a binary on your machine and you want it available through `opencli`.
|
|
124
124
|
|
|
125
125
|
```bash
|
|
126
|
-
|
|
126
|
+
ppcli external register my-tool \
|
|
127
127
|
--binary my-tool \
|
|
128
128
|
--install "npm i -g my-tool" \
|
|
129
129
|
--desc "My internal CLI"
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
ppcli my-tool --help
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
External CLIs pass stdio and exit codes through to the underlying binary.
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://nodejs.org)
|
|
8
8
|
[](https://github.com/jackwener/opencli/blob/main/LICENSE)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
ppcli turns **any website** or **Electron app** into a command-line interface — Bilibili, Zhihu, 小红书, Twitter/X, Reddit, YouTube, Antigravity, and [many more](/adapters/) — powered by browser session reuse and AI-native discovery.
|
|
11
11
|
|
|
12
12
|
## Highlights
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ OpenCLI turns **any website** or **Electron app** into a command-line interface
|
|
|
15
15
|
- **Browser Automation** — `browser` gives AI agents direct browser control: click, type/fill, extract, screenshot — fully scriptable.
|
|
16
16
|
- **Website → CLI** — Turn any website into a deterministic CLI: 100+ site surfaces are already registered, or author your own with the `opencli-adapter-author` skill.
|
|
17
17
|
- **Account-safe** — Reuses Chrome's logged-in state; your credentials never leave the browser.
|
|
18
|
-
- **AI Agent ready** — `
|
|
18
|
+
- **AI Agent ready** — `ppcli browser *` primitives (`open` / `network` / `state` / `eval` / `init` / `verify`) drive the adapter-authoring loop.
|
|
19
19
|
- **Zero LLM cost** — No tokens consumed at runtime. Run 10,000 times and pay nothing.
|
|
20
20
|
- **Deterministic** — Same command, same output schema, every time. Pipeable, scriptable, CI-friendly.
|
|
21
21
|
|
|
@@ -30,10 +30,10 @@ npm install -g @jackwener/opencli
|
|
|
30
30
|
### Basic Usage
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
ppcli list # See all commands
|
|
34
|
+
ppcli hackernews top --limit 5 # Public API, no browser
|
|
35
|
+
ppcli bilibili hot --limit 5 # Browser command
|
|
36
|
+
ppcli zhihu hot -f json # JSON output
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
### Output Formats
|
|
@@ -41,27 +41,27 @@ opencli zhihu hot -f json # JSON output
|
|
|
41
41
|
All built-in commands support `--format` / `-f`:
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
ppcli bilibili hot -f table # Default: rich terminal table
|
|
45
|
+
ppcli bilibili hot -f json # JSON (pipe to jq or LLMs)
|
|
46
|
+
ppcli bilibili hot -f yaml # YAML (human-readable)
|
|
47
|
+
ppcli bilibili hot -f md # Markdown
|
|
48
|
+
ppcli bilibili hot -f csv # CSV
|
|
49
|
+
ppcli bilibili hot -v # Verbose: show pipeline debug
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
### Tab Completion
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
ppcli supports intelligent tab completion to speed up command input:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
# Add shell completion to your startup config
|
|
58
|
-
echo 'eval "$(
|
|
59
|
-
echo 'eval "$(
|
|
60
|
-
echo '
|
|
58
|
+
echo 'eval "$(ppcli completion zsh)"' >> ~/.zshrc # Zsh
|
|
59
|
+
echo 'eval "$(ppcli completion bash)"' >> ~/.bashrc # Bash
|
|
60
|
+
echo 'ppcli completion fish | source' >> ~/.config/fish/config.fish # Fish
|
|
61
61
|
|
|
62
62
|
# Restart your shell, then press Tab to complete:
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
ppcli [Tab] # Complete site names (bilibili, zhihu, twitter...)
|
|
64
|
+
ppcli bilibili [Tab] # Complete commands (hot, search, me, download...)
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
The completion includes:
|
|
@@ -74,7 +74,7 @@ The completion includes:
|
|
|
74
74
|
|
|
75
75
|
- [Installation details](/guide/installation)
|
|
76
76
|
- [Browser Bridge setup](/guide/browser-bridge)
|
|
77
|
-
- [Extending
|
|
77
|
+
- [Extending ppcli — custom commands, plugins, and external CLIs](/guide/extending-opencli)
|
|
78
78
|
- [Plugins — extend with community adapters](/guide/plugins)
|
|
79
79
|
- [All available adapters](/adapters/)
|
|
80
80
|
- [For developers / AI agents](/developer/contributing)
|
|
@@ -15,11 +15,11 @@ npm install -g @jackwener/opencli
|
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
17
|
git clone git@github.com:jackwener/opencli.git
|
|
18
|
-
cd
|
|
18
|
+
cd ppcli
|
|
19
19
|
npm install
|
|
20
20
|
npm run build
|
|
21
21
|
npm link # Link binary globally
|
|
22
|
-
|
|
22
|
+
ppcli list # Now you can use it anywhere!
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## Update
|
|
@@ -27,7 +27,7 @@ opencli list # Now you can use it anywhere!
|
|
|
27
27
|
```bash
|
|
28
28
|
npm install -g @jackwener/opencli@latest
|
|
29
29
|
|
|
30
|
-
# If you use the packaged
|
|
30
|
+
# If you use the packaged ppcli skills, refresh them too
|
|
31
31
|
npx skills add jackwener/opencli
|
|
32
32
|
```
|
|
33
33
|
|
|
@@ -46,7 +46,7 @@ npx skills add jackwener/opencli --skill smart-search
|
|
|
46
46
|
## Verify Installation
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
ppcli --version # Check version
|
|
50
|
+
ppcli list # List all commands
|
|
51
|
+
ppcli doctor # Diagnose connectivity
|
|
52
52
|
```
|
package/docs/guide/plugins.md
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
# Plugins
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
ppcli supports community-contributed plugins. Install third-party adapters from GitHub, and they're automatically discovered alongside built-in commands.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
# Install a plugin
|
|
9
|
-
|
|
9
|
+
ppcli plugin install github:ByteYue/opencli-plugin-github-trending
|
|
10
10
|
|
|
11
11
|
# List installed plugins
|
|
12
|
-
|
|
12
|
+
ppcli plugin list
|
|
13
13
|
|
|
14
14
|
# Update one plugin
|
|
15
|
-
|
|
15
|
+
ppcli plugin update github-trending
|
|
16
16
|
|
|
17
17
|
# Update all installed plugins
|
|
18
|
-
|
|
18
|
+
ppcli plugin update --all
|
|
19
19
|
|
|
20
20
|
# Use the plugin (it's just a regular command)
|
|
21
|
-
|
|
21
|
+
ppcli github-trending repos --limit 10
|
|
22
22
|
|
|
23
23
|
# Remove a plugin
|
|
24
|
-
|
|
24
|
+
ppcli plugin uninstall github-trending
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
## How Plugins Work
|
|
28
28
|
|
|
29
|
-
Plugins live in `~/.
|
|
29
|
+
Plugins live in `~/.ppcli/plugins/<name>/`. Each subdirectory is scanned at startup for `.ts` or `.js` command files — the same formats used by built-in adapters.
|
|
30
30
|
|
|
31
31
|
### Supported Source Formats
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
34
|
# GitHub shorthand
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
ppcli plugin install github:user/repo
|
|
36
|
+
ppcli plugin install github:user/repo/subplugin # install specific sub-plugin from monorepo
|
|
37
|
+
ppcli plugin install https://github.com/user/repo
|
|
38
38
|
|
|
39
39
|
# Any git-cloneable URL
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
ppcli plugin install https://gitlab.example.com/team/repo.git
|
|
41
|
+
ppcli plugin install ssh://git@gitlab.example.com/team/repo.git
|
|
42
|
+
ppcli plugin install git@gitlab.example.com:team/repo.git
|
|
43
43
|
|
|
44
44
|
# Local plugin (for development)
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
ppcli plugin install file:///path/to/plugin
|
|
46
|
+
ppcli plugin install /path/to/plugin
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
The repo name prefix `opencli-plugin-` is automatically stripped for the local directory name. For example, `opencli-plugin-hot-digest` becomes `hot-digest`.
|
|
@@ -56,7 +56,7 @@ Plugins can include an `opencli-plugin.json` manifest file at the repo root to d
|
|
|
56
56
|
{
|
|
57
57
|
"name": "my-plugin",
|
|
58
58
|
"version": "1.0.0",
|
|
59
|
-
"
|
|
59
|
+
"ppcli": ">=1.0.0",
|
|
60
60
|
"description": "My awesome plugin"
|
|
61
61
|
}
|
|
62
62
|
```
|
|
@@ -65,7 +65,7 @@ Plugins can include an `opencli-plugin.json` manifest file at the repo root to d
|
|
|
65
65
|
|-------|-------------|
|
|
66
66
|
| `name` | Plugin name (overrides repo-derived name) |
|
|
67
67
|
| `version` | Semantic version |
|
|
68
|
-
| `opencli` | Required
|
|
68
|
+
| `opencli` | Required ppcli version range (e.g. `>=1.0.0`, `^1.2.0`) |
|
|
69
69
|
| `description` | Human-readable description |
|
|
70
70
|
| `plugins` | Monorepo sub-plugin declarations (see below) |
|
|
71
71
|
|
|
@@ -78,7 +78,7 @@ A single repository can contain multiple plugins by declaring a `plugins` field
|
|
|
78
78
|
```json
|
|
79
79
|
{
|
|
80
80
|
"version": "1.0.0",
|
|
81
|
-
"
|
|
81
|
+
"ppcli": ">=1.0.0",
|
|
82
82
|
"description": "My plugin collection",
|
|
83
83
|
"plugins": {
|
|
84
84
|
"polymarket": {
|
|
@@ -90,7 +90,7 @@ A single repository can contain multiple plugins by declaring a `plugins` field
|
|
|
90
90
|
"path": "packages/defi",
|
|
91
91
|
"description": "DeFi protocol data",
|
|
92
92
|
"version": "0.8.0",
|
|
93
|
-
"
|
|
93
|
+
"ppcli": ">=1.2.0"
|
|
94
94
|
},
|
|
95
95
|
"experimental": {
|
|
96
96
|
"path": "packages/experimental",
|
|
@@ -104,16 +104,16 @@ A single repository can contain multiple plugins by declaring a `plugins` field
|
|
|
104
104
|
|
|
105
105
|
```bash
|
|
106
106
|
# Install ALL enabled sub-plugins from a monorepo
|
|
107
|
-
|
|
107
|
+
ppcli plugin install github:user/opencli-plugins
|
|
108
108
|
|
|
109
109
|
# Install a SPECIFIC sub-plugin
|
|
110
|
-
|
|
110
|
+
ppcli plugin install github:user/opencli-plugins/polymarket
|
|
111
111
|
```
|
|
112
112
|
|
|
113
113
|
### How It Works
|
|
114
114
|
|
|
115
|
-
- The monorepo is cloned once to `~/.
|
|
116
|
-
- Each sub-plugin gets a symlink in `~/.
|
|
115
|
+
- The monorepo is cloned once to `~/.ppcli/monorepos/<repo>/`
|
|
116
|
+
- Each sub-plugin gets a symlink in `~/.ppcli/plugins/<name>/` pointing to its subdirectory
|
|
117
117
|
- Command discovery works transparently — symlinks are scanned just like regular directories
|
|
118
118
|
- Disabled sub-plugins (with `"disabled": true`) are skipped during install
|
|
119
119
|
- Sub-plugins can specify their own `opencli` compatibility range
|
|
@@ -123,20 +123,20 @@ opencli plugin install github:user/opencli-plugins/polymarket
|
|
|
123
123
|
Updating any sub-plugin from a monorepo pulls the entire repo and refreshes all sub-plugins:
|
|
124
124
|
|
|
125
125
|
```bash
|
|
126
|
-
|
|
126
|
+
ppcli plugin update polymarket # updates the monorepo, refreshes all
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
### Uninstalling
|
|
130
130
|
|
|
131
131
|
```bash
|
|
132
|
-
|
|
132
|
+
ppcli plugin uninstall polymarket # removes just this sub-plugin's symlink
|
|
133
133
|
```
|
|
134
134
|
|
|
135
135
|
When the last sub-plugin from a monorepo is uninstalled, the monorepo clone is automatically cleaned up.
|
|
136
136
|
|
|
137
137
|
## Version Tracking
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
ppcli records installed plugin versions in `~/.ppcli/plugins.lock.json`. Each entry stores the plugin source, current git commit hash, install time, and last update time. `ppcli plugin list` shows the short commit hash when version metadata is available.
|
|
140
140
|
|
|
141
141
|
## Creating a Plugin
|
|
142
142
|
|
|
@@ -172,7 +172,7 @@ cli({
|
|
|
172
172
|
name: 'my-command',
|
|
173
173
|
description: 'My custom command',
|
|
174
174
|
access: 'read', // 'read' | 'write'
|
|
175
|
-
example: '
|
|
175
|
+
example: 'ppcli my-plugin my-command -f yaml',
|
|
176
176
|
strategy: Strategy.PUBLIC,
|
|
177
177
|
browser: false,
|
|
178
178
|
args: [
|
|
@@ -192,7 +192,7 @@ cli({
|
|
|
192
192
|
|
|
193
193
|
### TS Plugin Install Lifecycle
|
|
194
194
|
|
|
195
|
-
When you run `
|
|
195
|
+
When you run `ppcli plugin install`, TS plugins are automatically set up:
|
|
196
196
|
|
|
197
197
|
1. **Clone** — `git clone --depth 1` from GitHub
|
|
198
198
|
2. **npm install** — Resolves regular dependencies
|
|
@@ -214,13 +214,13 @@ On startup, if both `my-command.ts` and `my-command.js` exist, the `.js` version
|
|
|
214
214
|
|
|
215
215
|
### Command not found after install
|
|
216
216
|
|
|
217
|
-
Restart
|
|
217
|
+
Restart ppcli (or open a new terminal) — plugins are discovered at startup.
|
|
218
218
|
|
|
219
219
|
### TS plugin import errors
|
|
220
220
|
|
|
221
221
|
If you see `Cannot find module '@jackwener/opencli/registry'`, the host symlink may be broken. Reinstall the plugin:
|
|
222
222
|
|
|
223
223
|
```bash
|
|
224
|
-
|
|
225
|
-
|
|
224
|
+
ppcli plugin uninstall my-plugin
|
|
225
|
+
ppcli plugin install github:user/opencli-plugin-my-plugin
|
|
226
226
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Remote Orchestration
|
|
2
2
|
|
|
3
|
-
Run an
|
|
3
|
+
Run an ppcli command from a remote machine (a CI runner, an agent server, a sandbox) while the **browser session stays on your local laptop**. The remote command sees `localhost:19825` like usual; behind the scenes, traffic is tunneled back to the daemon and Chrome on your machine.
|
|
4
4
|
|
|
5
5
|
## When you need this
|
|
6
6
|
|
|
@@ -45,8 +45,8 @@ While that session is open, anything on the remote connecting to `localhost:1982
|
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
47
|
# On the remote server
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
ppcli twitter feed
|
|
49
|
+
ppcli browser open https://example.com
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
::: tip
|
|
@@ -104,10 +104,10 @@ After setting up the tunnel, confirm the remote sees the daemon:
|
|
|
104
104
|
```bash
|
|
105
105
|
# On the remote server
|
|
106
106
|
curl -sf http://127.0.0.1:19825/ping && echo "daemon reachable"
|
|
107
|
-
|
|
107
|
+
ppcli doctor
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
-
`
|
|
110
|
+
`ppcli doctor` from the remote should report the same extension version your local Chrome is running.
|
|
111
111
|
|
|
112
112
|
## Caveats
|
|
113
113
|
|