* feat(google): add search, suggest, news, and trends adapters
Four new commands under `google`:
- search: browser-based DOM extraction from google.com/search
- suggest: public JSON API (suggestqueries.google.com)
- news: public RSS feed (top stories + keyword search)
- trends: public RSS feed (daily trending searches by region)
Shared RSS parser in utils.ts with attribute/CDATA support.
Unit tests for parseRssItems, E2E tests with network skip guards.
* refactor(google): downgrade search strategy from COOKIE to PUBLIC
Google search results are public data, no login needed. Browser is
required for DOM rendering, not authentication. Standalone mode
confirmed working in testing.
* fix: update test comment to reflect PUBLIC strategy
* feat(tiktok): add TikTok adapter with 15 commands
TikTok (15 commands, browser mode):
Read commands:
- profile: user profile info via rehydration script parsing
- search: search videos via internal search API
- explore: trending videos from explore page (DOM scraping)
- user: recent videos from a user page (DOM scraping)
- following: list accounts you follow
- friends: friend suggestions
- live: browse live streams with viewer counts
- notifications: activity notifications
Write commands (verified with real interactions):
- like/unlike: like or unlike a video by URL
- save/unsave: add or remove video from Favorites
- follow/unfollow: follow or unfollow a user
- comment: comment on a video
All write operations verified with live TikTok interactions.
* docs: add missing adapter documentation for doc-coverage CI
* feat: plugin system (Stage 0-2)
- Stage 0: discoverPlugins() scans ~/.opencli/plugins/ at startup
- Stage 1: demo plugin repos (github-trending, hot-digest)
- Stage 2: opencli plugin install/uninstall/list commands
- package.json exports ./registry for TS plugin peerDep support
- 17 new/updated tests, tsc --noEmit clean
* fix: CDPBridge connect timeout unit mismatch (seconds vs ms)
opts.timeout is passed in seconds from runtime.ts but CDPBridge
was using it as milliseconds, causing instant timeout (30ms).
* feat: add registry-api public entry point for TS plugin peerDep support
- Add src/registry-api.ts: re-exports core registration API (cli, Strategy,
getRegistry) without transitive side-effects, safe for plugin imports
- Update package.json exports: './registry' -> './dist/registry-api.js'
- Update src/registry.ts: use globalThis shared registry to ensure single
instance across npm-linked plugin modules
- Update .gitignore for plugin-related artifacts
* fix: symlink host opencli into plugin node_modules on install
After npm install, replace the npm-installed @jackwener/opencli
with a symlink to the running host's package root. This ensures
TS plugins always resolve '@jackwener/opencli/registry' against
the host installation, avoiding version mismatches when the
published npm package lags behind.
* fix: transpile TS plugins to JS on install, deduplicate .ts/.js discovery
- installPlugin: after symlinking host opencli, transpile any .ts files
to .js using esbuild from the host's node_modules/.bin/
- discoverPluginDir: skip .ts files when a .js sibling exists (production
node cannot load .ts directly)
- scanPluginCommands: deduplicate basenames via Set to avoid showing
'aggregate, aggregate' when both .ts and .js exist
* docs: add plugin system user guide
- New docs/guide/plugins.md covering:
- Installation/uninstallation commands
- Creating YAML plugins (zero-dep)
- Creating TS plugins (with peerDep)
- TS plugin install lifecycle (clone → deps → symlink → transpile)
- Example plugins and troubleshooting
- Add Plugins to VitePress sidebar (EN + ZH)
- Link from getting-started.md Next Steps
* fix: address review issues in plugin system
- Security: replace execSync with execFileSync to prevent shell injection
- Replace deprecated npm --production with --omit=dev
- Tighten parseSource regex to [\w.-]+ to reject special chars
- Fix ZH sidebar plugin link (/guide/plugins → /zh/guide/plugins)
- Return plugin name from installPlugin() to avoid duplicated logic
- Use execFileSync for esbuild transpilation
- Fix misleading comment in linkHostOpencli
---------
Co-authored-by: jackwener <jakevingoo@gmail.com>
* fix(twitter): rewrite trending from YAML to TS with DOM scraping fallback
The old REST API /i/api/2/guide.json returns 503. Replace with a TS
adapter that:
- Tries legacy guide.json API first (with proper auth headers)
- Falls back to DOM scraping via [data-testid='trend'] elements
- Filters out promoted content
- Follows the same Strategy.COOKIE pattern as timeline.ts
* fix: use 'help' instead of 'description' in Arg (matches Arg interface)
* docs(steam): add adapter documentation, update READMEs
- Create docs/adapters/browser/steam.md
- Add steam entry to README.md and README.zh-CN.md
- Fixes doc-coverage CI check (44/44)
Add three new Twitter/X UI-strategy commands:
- `block` / `unblock` — block or unblock a user by username
- `hide-reply` — hide a bot/spam reply on your own tweet thread
* docs: add missing adapter docs, fix sidebar 404s, add doc-check CI
- Add doc pages for 11 undocumented adapters: arxiv, barchart,
chaoxing, grok, hf, jike, jimeng, linux-do, sinafinance,
stackoverflow, weread, wikipedia
- Update adapters/index.md with all new adapter entries
- Update VitePress sidebar config with 12 new entries
- Remove broken zh/ sidebar refs (troubleshooting, testing)
- Add doc-check CI workflow (adapter coverage + build + link check)
- Add scripts/check-doc-coverage.sh for adapter doc enforcement
- Enhance PR template with adapter doc checklist
* fix(ci): use --root-dir instead of --base for lychee link checker
lychee v0.23 requires --base to be a URL or absolute path.
Use --root-dir for resolving root-relative links in local files.
* fix(ci): remove lychee link-check job, rely on VitePress build
VitePress links use extension-less paths (e.g. /adapters/browser/twitter)
which lychee cannot resolve. The docs-build job already catches all
broken internal links via VitePress dead link detection during build.
- Change VitePress base from '/opencli/' to '/' for custom domain opencli.info
- Add docs/public/CNAME so GitHub Pages preserves custom domain on re-deploy
* docs: deduplicate documentation — single source of truth in docs/
- Remove root CDP.md, CDP.zh-CN.md, CLI-ELECTRON.md (now in docs/advanced/)
- Slim adapter READMEs to one-liner + link to docs/ (11 files)
- Update README.md adapter table links to point to docs/
* docs: set VitePress base path for GitHub Pages deployment