-
Notifications
You must be signed in to change notification settings - Fork 787
Comparing changes
Open a pull request
base repository: jackwener/opencli
base: v1.5.5
head repository: jackwener/opencli
compare: v1.5.6
- 20 commits
- 98 files changed
- 14 contributors
Commits on Mar 28, 2026
-
fix(tests): update E2E exit code assertions for usage errors (#567)
Argument/usage errors now correctly exit with code 2 (EX_USAGE) since the exit-codes feature landed. Update the two affected E2E assertions: - unknown command → 2 (usage error, not generic failure) - plugin update without args → 2 (ArgumentError)
Configuration menu - View commit details
-
Copy full SHA for bcaf612 - Browse repository at this point
Copy the full SHA bcaf612View commit details
Commits on Mar 29, 2026
-
docs: sync docs with codebase (v1.5.5, exit codes, hub table, new ada…
…pters) (#575) - SKILL.md: version 1.4.1 → 1.5.5 - README.md: remove non-existent gws from CLI Hub table; bump adapter count to 66+; add Exit Codes section (sysexits.h table + usage example) - README.zh-CN.md: replace readwise/gws (not in external-clis.yaml) with lark-cli/vercel; add bluesky and douyin to built-in commands table; add 退出码 section matching English README; add 66+ adapter count line
Configuration menu - View commit details
-
Copy full SHA for f44fcd5 - Browse repository at this point
Copy the full SHA f44fcd5View commit details -
fix(weread): harden reader fallback and search mapping (#562)
* fix(weread): harden reader fallback and search mapping * fix(ci): remove stale weread regression test duplicates * refactor(weread): simplify search fetch and eliminate redundant getCookies - Parallelize search API + HTML fetch with Promise.all - Add generic numeric entity decoding (decimal + hex) in decodeHtmlText - Extract loadWebShelfSnapshotWithVid to pass currentVid downstream, avoiding a redundant getCookies call in waitForTrustedWebShelfSnapshot - Split mixed early-return conditions with individual comments - Add mirror comments between browser/Node trusted-index logic
Configuration menu - View commit details
-
Copy full SHA for bb5c2b1 - Browse repository at this point
Copy the full SHA bb5c2b1View commit details -
feat: add 知识星球(zsxq) site adapter (#571)
* feat: add 知识星球(zsxq) site adapter Add cookie-based adapter for 知识星球 (zsxq.com) with 5 commands: - groups: list joined groups - topics: list topics in current group - topic: get single topic detail with comments - search: search topics within a group - dynamics: latest cross-group activity feed Uses XHR over Chrome extension (Strategy.COOKIE) to call https://api.zsxq.com/v2/ APIs with credential forwarding. * fix(zsxq): map missing topics to not found * refactor(zsxq): preserve detail response semantics --------- Co-authored-by: xiaojian <[email protected]> Co-authored-by: jackwener <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for d8d9643 - Browse repository at this point
Copy the full SHA d8d9643View commit details -
feat(xiaohongshu): use CDP DOM.setFileInputFiles for image upload (#574)
* feat(xiaohongshu): use CDP DOM.setFileInputFiles for image upload Replace base64 DataTransfer injection with CDP DOM.setFileInputFiles, which lets Chrome read image files directly from the local filesystem. This eliminates payload size limits that caused "fetch failed" errors when uploading large images (>500KB) through the browser bridge. Changes: - Add 'set-file-input' action to protocol, extension handler, and CDP executor - Add Page.setFileInput() method for CLI-side usage - Rewrite publish image upload to use CDP path, with base64 fallback for older extension versions that don't support the new action - Add clear warning when falling back to base64 with large payloads Closes #542 (partially — image upload reliability) Co-Authored-By: Claude Opus 4.6 <[email protected]> * test: cover cdp file input upload path * fix: keep image upload on image-only inputs --------- Co-authored-by: Claude Opus 4.6 <[email protected]> Co-authored-by: jackwener <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for 5925849 - Browse repository at this point
Copy the full SHA 5925849View commit details -
feat(band): add Band.us adapter — bands, posts, mentions, post comman…
…ds (#532) * feat(band): add bands, posts, and mentions commands for band.us - bands: lists all Bands via get_band_list_with_filter intercept - posts: lists posts from a Band via get_posts_and_announcements intercept - mentions: shows @mention notifications via get_news intercept All use Strategy.INTERCEPT since band.us API requires an HMAC md header generated by its own JS. SPA navigation to /band/{no}/post triggers the band list and posts APIs; bell + @メンション tab click triggers mentions. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * refactor(band): clean up all three band adapters - Fix doc comments: Band uses XHR not fetch; clarify INTERCEPT rationale - bands: replace for-loop with flatMap; explain why band page nav is needed - posts: remove item.post ?? item fallback (API always wraps in post); rename finalRequests → requests for consistency; extract stripBandTags helper - mentions: remove redundant ?? defaults (args have defaults defined); fix unreadOnly bug (was not applied to post/comment modes); consolidate Band tag stripping to single regex; cast kwargs types directly instead of converting; add comments explaining last-response strategy and 'referred' filter flag Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band/posts): handle mixed post/announcement items from API get_posts_and_announcements returns both regular posts and announcements that have different shapes — some lack post_no and wrap differently. Restore item.post ?? item fallback and filter out items with no resolvable identifier to prevent undefined in URLs and empty rows in output. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * feat(band): add post command — full post export with comments and photo download Exports the complete content of a single Band post: - Post body (with Band markup tags stripped) - All comments in chronological order - Photo URLs shown inline, or downloaded with --output <dir> Uses Strategy.INTERCEPT with a broad 'band.us' pattern to capture both the batch request (embedding get_post) and get_comments in one SPA navigation. Responses are identified client-side by shape: batch_result array vs items array with comment_id fields. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * refactor(band): replace XHR interception with direct DOM extraction - bands, posts, post: navigate directly to target URL instead of home→SPA detour - All three switch from Strategy.INTERCEPT to Strategy.COOKIE with navigateBefore: false (bands uses framework pre-nav to home; posts/post disable it and goto target directly) - DOM extraction polls for specific content elements rather than fixed waits - post: confirm selectors via browser inspection (a.text, time.time, .sCommentList, .sReplyList for nested replies); add --comments flag to skip comment fetch - posts: extract from rendered post list DOM; correct comment item selector (div.cComment) - Fix: post empty-result guard changed from && to handle null data safely - Fix: photo download now checks HTTP status code before piping to avoid writing redirect HTML into image files - Fix: mentions unread client-side filter skipped for 'mentioned' mode since server already filtered via 未確認のみ button click Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band): address code review feedback - post: replace manual http/https download with shared downloadMedia utility (handles redirects, timeouts, stream errors correctly) - post: fix photo URL resolution to use location.href as base, handling protocol-relative and relative URLs without throwing - post: switch to node:-prefixed imports per repo convention - post/posts: remove redundant ArgumentError guards — framework already validates required args before func() is called - mentions: INTERCEPT strategy is intentional (Band HMAC prevents DOM-only approach for notifications; update PR description to clarify) Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band): address second round of code review feedback - bands: tighten href selector to /band/{id}(?:/post)?$ so feed/post-detail links are excluded; only sidebar navigation links match - mentions: replace fixed page.wait(2) sleeps with polling on getInterceptedRequests() — waits up to 8 s per action, exits as soon as the expected number of captures arrives (avoids flakiness on slow XHR) Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band): fix selector bugs found during testing - bands: use a.bandCover._link + p.uriText + span.member em selectors (previous a[href*="/band/"] + .bandName combo leaked "メンバー" text) - posts: use article.cContentsCard._postMainWrap + span.count selectors (previous li._postListItem selector matched nothing; DOM changed) - mentions: fix page.wait(500) → page.wait(0.5) (was waiting 500s not ms); use timestamp-suffixed URL to force fresh page load each run so the notification panel is closed; fix get_news vs get_news_count capture ambiguity with result_data.news check; replace cumulative waitForCaptures with waitForOneCapture (getInterceptedRequests clears array on each call) Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band/mentions): use CSS class selector for bell button instead of locale-dependent text match Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band): address third round of code review feedback - post: pass browser cookies to downloadMedia so Band's login-protected photo URLs don't fail with 401/403 - post: include photos.length in empty-result guard so photo-only posts are not falsely reported as not found - mentions: accumulate captures across poll iterations so get_news_count responses don't cause early exit before the real get_news arrives - mentions: update docstring to match actual implementation (client-side filtering, no tab-click) Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band): address fourth round of code review feedback - mentions: fail fast with a clear error when bell button is not found, instead of silently no-op and waiting 8s before EmptyResultError - post: use shared formatCookieHeader() instead of manual cookie string construction Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band): address fifth round of code review feedback - mentions: replace fixed page.wait(2) with polling for bell button readiness (up to 10s), eliminating the fixed sleep and fail-fast when the selector is missing - mentions: add explicit !newsReq guard with a clear error message when get_news capture times out, instead of falling through to a misleading "No notifications found" - posts: skip posts with no permalink href instead of emitting a bogus 'https://www.band.us' URL Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band): address sixth round of code review feedback - post: only send Band cookies to *.band.us photo URLs; third-party CDN URLs are downloaded without cookies to avoid cross-domain cookie leakage - bands: strip non-digit chars before parseInt so member counts like "1,234" parse correctly - posts: same fix for comment counts Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band): address seventh round of code review feedback - posts: check limit before push so --limit 0 returns empty result - post: indent replies proportionally by depth (' '.repeat(depth)) so multi-level threads remain readable in table output Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band/bands): anchor href regex to prevent matching post-detail URLs Pattern now requires /band/{id} or /band/{id}/post (with optional trailing slash) so deeper paths like /band/{id}/post/{postNo} are excluded. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band): address ninth round of code review feedback - mentions: guard bell click with a boolean return so a disappearing element throws a clear EmptyResultError instead of a raw TypeError - post: wait for comment list container instead of first .cComment so posts with zero comments don't incur a fixed 6s delay Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band): use page.getCookies() for login detection across all commands Replaces document.cookie.includes('band_session') with page.getCookies({ domain: 'band.us' }) so login detection works even if Band.us marks the session cookie as HttpOnly in the future. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band): address eleventh round of code review feedback - mentions: replace EmptyResultError with SelectorError for missing/ disappeared bell button — produces a clearer SELECTOR error code - post: assign per-photo filenames using a global index across both download batches so band-hosted and CDN photos don't overwrite each other Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band): address twelfth round of code review feedback - post: derive file extension from URL path and include in filename (e.g. photo_1.jpg) so downloaded photos have correct extensions - posts: remove dead code guard (!url && !content) — url is always non-empty here since href-empty posts are already skipped above Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(band/post): use url-scoped getCookies for photo download auth Domain-scoped getCookies may omit host-only cookies scoped to www.band.us; using url: 'https://www.band.us' ensures all relevant cookies are included in the auth header for Band-hosted photo downloads. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * docs(band): add adapter documentation and sidebar entry Required by CI doc-check --strict: every adapter in src/clis/ must have a corresponding docs/adapters/browser/*.md file. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * test(e2e): wire band auth coverage into default matrix --------- Co-authored-by: Claude Sonnet 4.6 <[email protected]> Co-authored-by: jackwener <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for 440c001 - Browse repository at this point
Copy the full SHA 440c001View commit details -
feat(spotify): add Spotify playback adapter (#560)
* feat(spotify): add Spotify playback adapter Adds a new adapter for controlling Spotify via the official Web API. Uses Strategy.PUBLIC with OAuth2 — no browser session required. Commands: auth, status, play, pause, next, prev, volume, search, queue, shuffle, repeat. Credentials are loaded from ~/.opencli/spotify.env or environment variables. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(spotify): rename index.ts → spotify.ts and fix CliError calls - Renamed src/clis/spotify/index.ts to spotify.ts so the build-manifest picks it up (index.js is intentionally excluded from manifest scanning) - Fixed 4 CliError calls: constructor now requires (code, message, hint?) so each throw now passes an appropriate error code as first argument Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(spotify): fix token refresh corruption, env parse, null guards, validation - refreshAccessToken: check res.ok before parsing; construct Tokens object directly instead of mutating loadTokens() result to avoid writing undefined/NaN on Spotify error responses; preserve existing refresh_token when Spotify omits it from the response - loadEnv: split on first '=' only so values containing '=' are preserved - SCOPES: remove write/library/top scopes not used by any command - status: guard against data.item being null (active device but no track) - volume: validate 0-100 range before API call - auth: check tokenRes.ok on initial token exchange; add server.on('error') handler for EADDRINUSE; add 5-minute timeout with clearTimeout on close * feat(postinstall): auto-create ~/.opencli/spotify.env template on install Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(spotify): guard null progress, podcast items, missing tracks data, corrupted tokens, invalid search limit Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(spotify): improve missing credentials error with step-by-step guidance * fix(spotify): harden setup and add docs coverage --------- Co-authored-by: Claude Sonnet 4.6 <[email protected]> Co-authored-by: jackwener <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for 1ae1c82 - Browse repository at this point
Copy the full SHA 1ae1c82View commit details -
fix(zsxq): require active group context (#579)
* fix(zsxq): require active group context * docs(zsxq): add adapter guide
Configuration menu - View commit details
-
Copy full SHA for f8e9b08 - Browse repository at this point
Copy the full SHA f8e9b08View commit details -
feat(xiaohongshu): add cover image URL to user notes output (#572)
* feat(xiaohongshu): add cover image URL to user notes output Extract cover image URL from noteCard.cover.urlDefault in __INITIAL_STATE__ and include it in the user command output columns. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * test(xiaohongshu): cover user note rows * refactor(xiaohongshu): keep cover out of default columns --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]> Co-authored-by: jackwener <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for d2b563e - Browse repository at this point
Copy the full SHA d2b563eView commit details -
feat(douyin): add user-videos command with top comments (#554)
* feat(douyin): add user-videos command with top-10 comments Adds a new adapter for fetching a public user's video list by sec_uid, alongside the top-10 hottest comments for each video. - Navigates to the user's profile page to establish a cookie session - Fetches video list via /aweme/v1/web/aweme/post/ - Concurrently fetches top-10 comments per video via /aweme/v1/web/comment/list/ (sorted by hotness, API default) Output columns: index, aweme_id, title, duration, digg_count, play_url, top_comments * refactor(douyin): replace Object.assign with spread in user-videos Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(douyin): validate user-videos inputs --------- Co-authored-by: Claude Sonnet 4.6 <[email protected]> Co-authored-by: jackwener <[email protected]>Configuration menu - View commit details
-
Copy full SHA for 79b4e06 - Browse repository at this point
Copy the full SHA 79b4e06View commit details -
Configuration menu - View commit details
-
Copy full SHA for 107ed28 - Browse repository at this point
Copy the full SHA 107ed28View commit details -
feat(doubao): add history, detail, meeting-summary (#566)
* feat(doubao): add history, detail, meeting-summary and meeting-transcript commands - history: list conversation history from sidebar - detail: read a specific conversation by ID, with meeting card detection - meeting-summary: extract summary and AI chapters from meeting minutes - meeting-transcript: read or download meeting transcript via browser Made-with: Cursor * docs: update doubao command list in adapter index and README.zh-CN Made-with: Cursor * fix(doubao): handle meeting-only detail and merge transcript snapshots * refactor(doubao): model conversation ids as first-class output --------- Co-authored-by: jackwener <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for ab7eca3 - Browse repository at this point
Copy the full SHA ab7eca3View commit details -
feat: add Tieba browser adapters in TypeScript (#581)
* feat(tieba): add browser adapters for hot posts search and read * fix(tieba): stabilize search and e2e coverage --------- Co-authored-by: jackwener <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for a32b65b - Browse repository at this point
Copy the full SHA a32b65bView commit details -
feat(youtube): mute and pause watch pages for read commands (#578)
* Mute and pause YouTube watch pages for read commands * fix(youtube): quiet watch pages earlier * refactor(youtube): avoid watch ui for read commands * test(youtube): cover html bootstrap parser --------- Co-authored-by: jackwener <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for b280f19 - Browse repository at this point
Copy the full SHA b280f19View commit details -
Configuration menu - View commit details
-
Copy full SHA for 3eb2e88 - Browse repository at this point
Copy the full SHA 3eb2e88View commit details -
feat(browser): add ONES adapter support for tasks and worklog commands (
#386) * feat(browser): add ONES adapter support for tasks and worklog commands Add ONES auth/session commands, task listing/details utilities, and worklog operations, with related docs and helper utilities. * fix(ones): harden worklog and task-list adapter behavior --------- Co-authored-by: jackwener <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for 8c00ad9 - Browse repository at this point
Copy the full SHA 8c00ad9View commit details -
feat(xueqiu): add comments command (#587)
* feat: add xueqiu comments command * docs(xueqiu): add comments command docs --------- Co-authored-by: jackwener <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for cf79ec5 - Browse repository at this point
Copy the full SHA cf79ec5View commit details
Commits on Mar 30, 2026
-
docs: add dingtalk and wecom CLI to external CLI hub (#594)
* docs: add dingtalk and wecom CLI to external CLI hub Add dingtalk-workspace-cli and wecom-cli as external CLI integrations alongside lark-cli, gh, docker, etc. * feat: register dingtalk and wecom as external CLIs Add dws (DingTalk Workspace CLI) and wecom-cli to external-clis.yaml so they are discoverable via opencli list and auto-installable.
Configuration menu - View commit details
-
Copy full SHA for 770c283 - Browse repository at this point
Copy the full SHA 770c283View commit details -
fix(spotify): follow-up fixes for token refresh, null guards and cred…
…entials guidance (#591) * fix(spotify): fix token refresh, null guards, env parse, missing credentials guidance, postinstall template * fix(spotify): restore credential guardrails --------- Co-authored-by: jackwener <[email protected]>
Configuration menu - View commit details
-
Copy full SHA for 8e37f66 - Browse repository at this point
Copy the full SHA 8e37f66View commit details -
Configuration menu - View commit details
-
Copy full SHA for 62e3c55 - Browse repository at this point
Copy the full SHA 62e3c55View commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff v1.5.5...v1.5.6