@jackwener/opencli 1.5.4 → 1.5.6

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.
Files changed (256) hide show
  1. package/README.md +27 -2
  2. package/README.zh-CN.md +36 -4
  3. package/dist/browser/daemon-client.d.ts +5 -1
  4. package/dist/browser/page.d.ts +6 -0
  5. package/dist/browser/page.js +15 -0
  6. package/dist/cli-manifest.json +1284 -67
  7. package/dist/cli.js +14 -14
  8. package/dist/clis/antigravity/serve.js +2 -2
  9. package/dist/clis/band/bands.d.ts +1 -0
  10. package/dist/clis/band/bands.js +72 -0
  11. package/dist/clis/band/mentions.d.ts +1 -0
  12. package/dist/clis/band/mentions.js +127 -0
  13. package/dist/clis/band/post.d.ts +1 -0
  14. package/dist/clis/band/post.js +175 -0
  15. package/dist/clis/band/posts.d.ts +1 -0
  16. package/dist/clis/band/posts.js +94 -0
  17. package/dist/clis/doubao/detail.d.ts +1 -0
  18. package/dist/clis/doubao/detail.js +33 -0
  19. package/dist/clis/doubao/detail.test.d.ts +1 -0
  20. package/dist/clis/doubao/detail.test.js +42 -0
  21. package/dist/clis/doubao/history.d.ts +1 -0
  22. package/dist/clis/doubao/history.js +28 -0
  23. package/dist/clis/doubao/history.test.d.ts +1 -0
  24. package/dist/clis/doubao/history.test.js +37 -0
  25. package/dist/clis/doubao/meeting-summary.d.ts +1 -0
  26. package/dist/clis/doubao/meeting-summary.js +39 -0
  27. package/dist/clis/doubao/meeting-transcript.d.ts +1 -0
  28. package/dist/clis/doubao/meeting-transcript.js +36 -0
  29. package/dist/clis/doubao/utils.d.ts +27 -0
  30. package/dist/clis/doubao/utils.js +317 -0
  31. package/dist/clis/doubao/utils.test.d.ts +1 -0
  32. package/dist/clis/doubao/utils.test.js +24 -0
  33. package/dist/clis/douyin/_shared/public-api.d.ts +33 -0
  34. package/dist/clis/douyin/_shared/public-api.js +29 -0
  35. package/dist/clis/douyin/user-videos.d.ts +5 -0
  36. package/dist/clis/douyin/user-videos.js +74 -0
  37. package/dist/clis/douyin/user-videos.test.d.ts +1 -0
  38. package/dist/clis/douyin/user-videos.test.js +108 -0
  39. package/dist/clis/ones/common.d.ts +32 -0
  40. package/dist/clis/ones/common.js +144 -0
  41. package/dist/clis/ones/enrich-tasks.d.ts +5 -0
  42. package/dist/clis/ones/enrich-tasks.js +37 -0
  43. package/dist/clis/ones/login.d.ts +1 -0
  44. package/dist/clis/ones/login.js +80 -0
  45. package/dist/clis/ones/logout.d.ts +1 -0
  46. package/dist/clis/ones/logout.js +17 -0
  47. package/dist/clis/ones/me.d.ts +1 -0
  48. package/dist/clis/ones/me.js +30 -0
  49. package/dist/clis/ones/my-tasks.d.ts +1 -0
  50. package/dist/clis/ones/my-tasks.js +120 -0
  51. package/dist/clis/ones/resolve-labels.d.ts +10 -0
  52. package/dist/clis/ones/resolve-labels.js +64 -0
  53. package/dist/clis/ones/task-helpers.d.ts +29 -0
  54. package/dist/clis/ones/task-helpers.js +212 -0
  55. package/dist/clis/ones/task-helpers.test.d.ts +1 -0
  56. package/dist/clis/ones/task-helpers.test.js +12 -0
  57. package/dist/clis/ones/task.d.ts +1 -0
  58. package/dist/clis/ones/task.js +66 -0
  59. package/dist/clis/ones/tasks.d.ts +1 -0
  60. package/dist/clis/ones/tasks.js +79 -0
  61. package/dist/clis/ones/token-info.d.ts +1 -0
  62. package/dist/clis/ones/token-info.js +42 -0
  63. package/dist/clis/ones/worklog.d.ts +11 -0
  64. package/dist/clis/ones/worklog.js +267 -0
  65. package/dist/clis/ones/worklog.test.d.ts +1 -0
  66. package/dist/clis/ones/worklog.test.js +20 -0
  67. package/dist/clis/sinafinance/rolling-news.d.ts +4 -0
  68. package/dist/clis/sinafinance/rolling-news.js +40 -0
  69. package/dist/clis/sinafinance/stock.d.ts +8 -0
  70. package/dist/clis/sinafinance/stock.js +117 -0
  71. package/dist/clis/spotify/spotify.d.ts +1 -0
  72. package/dist/clis/spotify/spotify.js +316 -0
  73. package/dist/clis/spotify/utils.d.ts +21 -0
  74. package/dist/clis/spotify/utils.js +66 -0
  75. package/dist/clis/spotify/utils.test.d.ts +1 -0
  76. package/dist/clis/spotify/utils.test.js +67 -0
  77. package/dist/clis/tieba/commands.test.d.ts +4 -0
  78. package/dist/clis/tieba/commands.test.js +79 -0
  79. package/dist/clis/tieba/hot.d.ts +1 -0
  80. package/dist/clis/tieba/hot.js +48 -0
  81. package/dist/clis/tieba/posts.d.ts +1 -0
  82. package/dist/clis/tieba/posts.js +85 -0
  83. package/dist/clis/tieba/read.d.ts +1 -0
  84. package/dist/clis/tieba/read.js +140 -0
  85. package/dist/clis/tieba/search.d.ts +1 -0
  86. package/dist/clis/tieba/search.js +108 -0
  87. package/dist/clis/tieba/utils.d.ts +101 -0
  88. package/dist/clis/tieba/utils.js +240 -0
  89. package/dist/clis/tieba/utils.test.d.ts +1 -0
  90. package/dist/clis/tieba/utils.test.js +290 -0
  91. package/dist/clis/weread/book.js +100 -13
  92. package/dist/clis/weread/commands.test.js +221 -0
  93. package/dist/clis/weread/private-api-regression.test.d.ts +1 -0
  94. package/dist/{weread-private-api-regression.test.js → clis/weread/private-api-regression.test.js} +92 -30
  95. package/dist/clis/weread/search-regression.test.d.ts +1 -0
  96. package/dist/clis/weread/search-regression.test.js +407 -0
  97. package/dist/clis/weread/search.js +143 -7
  98. package/dist/clis/weread/shelf.js +13 -95
  99. package/dist/clis/weread/utils.d.ts +46 -0
  100. package/dist/clis/weread/utils.js +214 -7
  101. package/dist/clis/weread/utils.test.js +71 -1
  102. package/dist/clis/xiaohongshu/publish.d.ts +1 -1
  103. package/dist/clis/xiaohongshu/publish.js +78 -31
  104. package/dist/clis/xiaohongshu/publish.test.js +66 -1
  105. package/dist/clis/xiaohongshu/user-helpers.d.ts +1 -0
  106. package/dist/clis/xiaohongshu/user-helpers.js +2 -0
  107. package/dist/clis/xiaohongshu/user-helpers.test.js +18 -0
  108. package/dist/clis/xueqiu/comments.d.ts +118 -0
  109. package/dist/clis/xueqiu/comments.js +354 -0
  110. package/dist/clis/xueqiu/comments.test.d.ts +1 -0
  111. package/dist/clis/xueqiu/comments.test.js +696 -0
  112. package/dist/clis/youtube/transcript.js +2 -4
  113. package/dist/clis/youtube/utils.d.ts +9 -0
  114. package/dist/clis/youtube/utils.js +67 -3
  115. package/dist/clis/youtube/utils.test.d.ts +1 -0
  116. package/dist/clis/youtube/utils.test.js +37 -0
  117. package/dist/clis/youtube/video.js +16 -15
  118. package/dist/clis/zsxq/dynamics.d.ts +1 -0
  119. package/dist/clis/zsxq/dynamics.js +47 -0
  120. package/dist/clis/zsxq/groups.d.ts +1 -0
  121. package/dist/clis/zsxq/groups.js +32 -0
  122. package/dist/clis/zsxq/search.d.ts +1 -0
  123. package/dist/clis/zsxq/search.js +43 -0
  124. package/dist/clis/zsxq/search.test.d.ts +1 -0
  125. package/dist/clis/zsxq/search.test.js +24 -0
  126. package/dist/clis/zsxq/topic.d.ts +1 -0
  127. package/dist/clis/zsxq/topic.js +47 -0
  128. package/dist/clis/zsxq/topic.test.d.ts +1 -0
  129. package/dist/clis/zsxq/topic.test.js +29 -0
  130. package/dist/clis/zsxq/topics.d.ts +1 -0
  131. package/dist/clis/zsxq/topics.js +25 -0
  132. package/dist/clis/zsxq/topics.test.d.ts +1 -0
  133. package/dist/clis/zsxq/topics.test.js +24 -0
  134. package/dist/clis/zsxq/utils.d.ts +97 -0
  135. package/dist/clis/zsxq/utils.js +230 -0
  136. package/dist/commanderAdapter.js +27 -4
  137. package/dist/commanderAdapter.test.js +39 -0
  138. package/dist/daemon.js +5 -4
  139. package/dist/errors.d.ts +29 -1
  140. package/dist/errors.js +49 -11
  141. package/dist/external-clis.yaml +17 -0
  142. package/dist/external.js +3 -3
  143. package/dist/main.js +2 -1
  144. package/dist/tui.js +2 -1
  145. package/dist/types.d.ts +5 -0
  146. package/docs/.vitepress/config.mts +3 -0
  147. package/docs/adapters/browser/band.md +63 -0
  148. package/docs/adapters/browser/ones.md +59 -0
  149. package/docs/adapters/browser/sinafinance.md +56 -6
  150. package/docs/adapters/browser/spotify.md +62 -0
  151. package/docs/adapters/browser/tieba.md +45 -0
  152. package/docs/adapters/browser/xueqiu.md +5 -0
  153. package/docs/adapters/browser/zsxq.md +49 -0
  154. package/docs/adapters/index.md +5 -2
  155. package/docs/adapters-doc/ones.md +32 -0
  156. package/extension/dist/background.js +1 -2
  157. package/extension/manifest.json +1 -1
  158. package/extension/package.json +1 -1
  159. package/extension/src/background.ts +17 -1
  160. package/extension/src/cdp.ts +42 -0
  161. package/extension/src/protocol.ts +5 -1
  162. package/package.json +1 -1
  163. package/scripts/postinstall.js +16 -0
  164. package/src/browser/daemon-client.ts +5 -1
  165. package/src/browser/page.ts +16 -0
  166. package/src/cli.ts +14 -14
  167. package/src/clis/antigravity/serve.ts +2 -2
  168. package/src/clis/band/bands.ts +76 -0
  169. package/src/clis/band/mentions.ts +134 -0
  170. package/src/clis/band/post.ts +187 -0
  171. package/src/clis/band/posts.ts +106 -0
  172. package/src/clis/doubao/detail.test.ts +53 -0
  173. package/src/clis/doubao/detail.ts +41 -0
  174. package/src/clis/doubao/history.test.ts +45 -0
  175. package/src/clis/doubao/history.ts +32 -0
  176. package/src/clis/doubao/meeting-summary.ts +53 -0
  177. package/src/clis/doubao/meeting-transcript.ts +48 -0
  178. package/src/clis/doubao/utils.test.ts +45 -0
  179. package/src/clis/doubao/utils.ts +371 -0
  180. package/src/clis/douyin/_shared/public-api.ts +84 -0
  181. package/src/clis/douyin/user-videos.test.ts +122 -0
  182. package/src/clis/douyin/user-videos.ts +101 -0
  183. package/src/clis/ones/common.ts +187 -0
  184. package/src/clis/ones/enrich-tasks.ts +47 -0
  185. package/src/clis/ones/login.ts +103 -0
  186. package/src/clis/ones/logout.ts +19 -0
  187. package/src/clis/ones/me.ts +34 -0
  188. package/src/clis/ones/my-tasks.ts +148 -0
  189. package/src/clis/ones/resolve-labels.ts +80 -0
  190. package/src/clis/ones/task-helpers.test.ts +14 -0
  191. package/src/clis/ones/task-helpers.ts +214 -0
  192. package/src/clis/ones/task.ts +79 -0
  193. package/src/clis/ones/tasks.ts +92 -0
  194. package/src/clis/ones/token-info.ts +46 -0
  195. package/src/clis/ones/worklog.test.ts +24 -0
  196. package/src/clis/ones/worklog.ts +306 -0
  197. package/src/clis/sinafinance/rolling-news.ts +42 -0
  198. package/src/clis/sinafinance/stock.ts +127 -0
  199. package/src/clis/spotify/spotify.ts +328 -0
  200. package/src/clis/spotify/utils.test.ts +87 -0
  201. package/src/clis/spotify/utils.ts +92 -0
  202. package/src/clis/tieba/commands.test.ts +86 -0
  203. package/src/clis/tieba/hot.ts +52 -0
  204. package/src/clis/tieba/posts.ts +108 -0
  205. package/src/clis/tieba/read.ts +158 -0
  206. package/src/clis/tieba/search.ts +119 -0
  207. package/src/clis/tieba/utils.test.ts +322 -0
  208. package/src/clis/tieba/utils.ts +348 -0
  209. package/src/clis/weread/book.ts +116 -13
  210. package/src/clis/weread/commands.test.ts +249 -0
  211. package/src/{weread-private-api-regression.test.ts → clis/weread/private-api-regression.test.ts} +108 -30
  212. package/src/clis/weread/search-regression.test.ts +440 -0
  213. package/src/clis/weread/search.ts +189 -9
  214. package/src/clis/weread/shelf.ts +20 -122
  215. package/src/clis/weread/utils.test.ts +81 -1
  216. package/src/clis/weread/utils.ts +264 -7
  217. package/src/clis/xiaohongshu/publish.test.ts +79 -1
  218. package/src/clis/xiaohongshu/publish.ts +84 -30
  219. package/src/clis/xiaohongshu/user-helpers.test.ts +23 -0
  220. package/src/clis/xiaohongshu/user-helpers.ts +4 -0
  221. package/src/clis/xueqiu/comments.test.ts +823 -0
  222. package/src/clis/xueqiu/comments.ts +461 -0
  223. package/src/clis/youtube/transcript.ts +2 -4
  224. package/src/clis/youtube/utils.test.ts +43 -0
  225. package/src/clis/youtube/utils.ts +69 -0
  226. package/src/clis/youtube/video.ts +16 -15
  227. package/src/clis/zsxq/dynamics.ts +60 -0
  228. package/src/clis/zsxq/groups.ts +41 -0
  229. package/src/clis/zsxq/search.test.ts +29 -0
  230. package/src/clis/zsxq/search.ts +54 -0
  231. package/src/clis/zsxq/topic.test.ts +34 -0
  232. package/src/clis/zsxq/topic.ts +68 -0
  233. package/src/clis/zsxq/topics.test.ts +29 -0
  234. package/src/clis/zsxq/topics.ts +36 -0
  235. package/src/clis/zsxq/utils.ts +351 -0
  236. package/src/commanderAdapter.test.ts +47 -0
  237. package/src/commanderAdapter.ts +26 -3
  238. package/src/daemon.ts +5 -4
  239. package/src/errors.ts +71 -10
  240. package/src/external-clis.yaml +17 -0
  241. package/src/external.ts +3 -3
  242. package/src/main.ts +2 -1
  243. package/src/tui.ts +2 -1
  244. package/src/types.ts +5 -0
  245. package/tests/e2e/band-auth.test.ts +20 -0
  246. package/tests/e2e/browser-auth-helpers.ts +18 -0
  247. package/tests/e2e/browser-auth.test.ts +35 -47
  248. package/tests/e2e/browser-public.test.ts +288 -0
  249. package/tests/e2e/management.test.ts +1 -1
  250. package/tests/e2e/plugin-management.test.ts +1 -1
  251. package/vitest.config.ts +1 -0
  252. package/SKILL.md +0 -879
  253. package/dist/weread-private-api-regression.test.d.ts +0 -1
  254. package/dist/weread-search-regression.test.d.ts +0 -1
  255. package/dist/weread-search-regression.test.js +0 -39
  256. package/src/weread-search-regression.test.ts +0 -44
@@ -0,0 +1,63 @@
1
+ # Band
2
+
3
+ **Mode**: 🔐 Browser · **Domain**: `www.band.us`
4
+
5
+ Read posts, comments, and notifications from [Band](https://www.band.us), a private community platform. Authentication uses your logged-in Chrome session (cookie-based).
6
+
7
+ ## Commands
8
+
9
+ | Command | Description |
10
+ |---------|-------------|
11
+ | `opencli band bands` | List all Bands you belong to |
12
+ | `opencli band posts <band_no>` | List posts from a Band |
13
+ | `opencli band post <band_no> <post_no>` | Export full post content including nested comments |
14
+ | `opencli band mentions` | Show notifications where you were @mentioned |
15
+
16
+ ## Usage Examples
17
+
18
+ ```bash
19
+ # List all your bands (get band_no from here)
20
+ opencli band bands
21
+
22
+ # List recent posts in a band
23
+ opencli band posts 12345678 --limit 10
24
+
25
+ # Export a post with comments
26
+ opencli band post 12345678 987654321
27
+
28
+ # Export post body only (skip comments)
29
+ opencli band post 12345678 987654321 --comments false
30
+
31
+ # Export post and download attached photos
32
+ opencli band post 12345678 987654321 --output ./band-photos
33
+
34
+ # Show recent @mention notifications
35
+ opencli band mentions --limit 20
36
+
37
+ # Show only unread mentions
38
+ opencli band mentions --unread true
39
+
40
+ # Show all notification types
41
+ opencli band mentions --filter all
42
+ ```
43
+
44
+ ### `band mentions` filter options
45
+
46
+ | Filter | Description |
47
+ |--------|-------------|
48
+ | `mentioned` | Only notifications where you were @mentioned (default) |
49
+ | `all` | All notifications |
50
+ | `post` | Post-related notifications |
51
+ | `comment` | Comment-related notifications |
52
+
53
+ ## Prerequisites
54
+
55
+ - Chrome running and **logged into** [band.us](https://www.band.us)
56
+ - [Browser Bridge extension](/guide/browser-bridge) installed
57
+
58
+ ## Notes
59
+
60
+ - `band_no` is the numeric ID in the Band URL: `band.us/band/{band_no}/post`
61
+ - `band bands` lists all your bands with their `band_no` values
62
+ - `band post` output rows: `type=post` (the post itself), `type=comment` (top-level comment), `type=reply` (nested reply)
63
+ - Photo downloads use the full-resolution URL (thumbnail query params are stripped automatically)
@@ -0,0 +1,59 @@
1
+ # ONES
2
+
3
+ **Mode**: 🔐 Browser Bridge · **Domain**: `ones.cn` (self-hosted via `ONES_BASE_URL`)
4
+
5
+ ## Commands
6
+
7
+ | Command | Description |
8
+ |---------|-------------|
9
+ | `opencli ones login` | Login via Project API (`auth/login`) |
10
+ | `opencli ones me` | Current user profile (`users/me`) |
11
+ | `opencli ones token-info` | Token/user/team summary (`auth/token_info`) |
12
+ | `opencli ones tasks` | Team task list with status/project labels and hours |
13
+ | `opencli ones my-tasks` | My tasks (`assign`/`field004`/`owner`/`both`) |
14
+ | `opencli ones task` | Task detail by UUID (`team/:team/task/:id/info`) |
15
+ | `opencli ones worklog` | Log/backfill hours (GraphQL `addManhour` first, then REST fallbacks) |
16
+ | `opencli ones logout` | Logout (`auth/logout`) |
17
+
18
+ ## Usage Examples
19
+
20
+ ```bash
21
+ # Required: your ONES base URL
22
+ export ONES_BASE_URL=https://your-instance.example.com
23
+
24
+ # Optional if your deployment requires auth headers
25
+ # export ONES_USER_ID=...
26
+ # export ONES_AUTH_TOKEN=...
27
+
28
+ # Login/profile
29
+ opencli ones login --email you@company.com --password 'your-password'
30
+ opencli ones me
31
+ opencli ones token-info
32
+
33
+ # Task lists
34
+ opencli ones tasks <teamUUID> --limit 20
35
+ opencli ones tasks <teamUUID> --project <projectUUID> --assign <userUUID>
36
+ opencli ones my-tasks <teamUUID> --limit 100
37
+ opencli ones my-tasks <teamUUID> --mode both
38
+
39
+ # Task detail
40
+ opencli ones task <taskUUID> --team <teamUUID>
41
+
42
+ # Worklog: today / backfill
43
+ opencli ones worklog <taskUUID> 2 --team <teamUUID>
44
+ opencli ones worklog <taskUUID> 1.5 --team <teamUUID> --date 2026-03-23 --note "integration"
45
+
46
+ opencli ones logout
47
+ ```
48
+
49
+ ## Prerequisites
50
+
51
+ - Chrome running and logged into your ONES instance
52
+ - [Browser Bridge extension](/guide/browser-bridge) installed
53
+ - `ONES_BASE_URL` set to the same origin opened in Chrome
54
+
55
+ ## Notes
56
+
57
+ - This adapter targets legacy ONES Project API deployments.
58
+ - `ONES_TEAM_UUID` can be set to omit `--team` in `tasks` / `my-tasks` / `task`.
59
+ - Hours display and input use `ONES_MANHOUR_SCALE` (default `100000`).
@@ -1,15 +1,19 @@
1
1
  # 新浪财经 (Sina Finance)
2
2
 
3
- **Mode**: 🌐 Public · **Domain**: `finance.sina.com.cn`
3
+ **Mode**: 🌐 Public / 🔐 Browser · **Domain**: `finance.sina.com.cn`
4
4
 
5
5
  ## Commands
6
6
 
7
- | Command | Description |
8
- |---------|-------------|
9
- | `opencli sinafinance news` | 新浪财经 7×24 小时实时快讯 |
7
+ | Command | Description | Mode |
8
+ |---------|-------------|------|
9
+ | `opencli sinafinance news` | 新浪财经 7×24 小时实时快讯 | 🌐 Public |
10
+ | `opencli sinafinance rolling-news` | 新浪财经滚动新闻 | 🔐 Browser |
11
+ | `opencli sinafinance stock` | 新浪财经行情(A股/港股/美股) | 🌐 Public |
10
12
 
11
13
  ## Usage Examples
12
14
 
15
+ ### news - 7×24 实时快讯
16
+
13
17
  ```bash
14
18
  # Latest financial news
15
19
  opencli sinafinance news --limit 20
@@ -23,13 +27,59 @@ opencli sinafinance news --type 6 # 国际
23
27
  opencli sinafinance news -f json
24
28
  ```
25
29
 
26
- ### Options
30
+ ### rolling-news - 滚动新闻
31
+
32
+ ```bash
33
+ # Rolling news feed
34
+ opencli sinafinance rolling-news
35
+
36
+ # JSON output
37
+ opencli sinafinance rolling-news -f json
38
+ ```
39
+
40
+ ### stock - 股票行情
41
+
42
+ ```bash
43
+ # Search and view A-share stock
44
+ opencli sinafinance stock 贵州茅台 --market cn
45
+
46
+ # Search and view HK stock
47
+ opencli sinafinance stock 腾讯控股 --market hk
48
+
49
+ # Search and view US stock
50
+ opencli sinafinance stock aapl --market us
51
+
52
+ # Auto-detect market (searches cn, hk, us in order)
53
+ opencli sinafinance stock 招商证券
54
+
55
+ # JSON output
56
+ opencli sinafinance stock 贵州茅台 -f json
57
+ ```
58
+
59
+ ## Options
60
+
61
+ ### news
27
62
 
28
63
  | Option | Description |
29
64
  |--------|-------------|
30
65
  | `--limit` | Max results, up to 50 (default: 20) |
31
66
  | `--type` | News type: `0`=全部, `1`=A股, `2`=宏观, `3`=公司, `4`=数据, `5`=市场, `6`=国际, `7`=观点, `8`=央行, `9`=其它 |
32
67
 
68
+ ### stock
69
+
70
+ | Option | Description |
71
+ |--------|-------------|
72
+ | `--market` | Market: `cn`, `hk`, `us`, `auto` (default: auto). When `auto`, searches in cn, hk, us order |
73
+
33
74
  ## Prerequisites
34
75
 
35
- - No browser required — uses public API
76
+ - `news` & `stock`: No browser required — uses public API
77
+ - `rolling-news`: Chrome running and **logged into** `finance.sina.com.cn`
78
+ - For `rolling-news`: [Browser Bridge extension](/guide/browser-bridge) installed
79
+
80
+ ## Notes
81
+
82
+ - `news` and `stock` use public APIs — no browser or login needed
83
+ - `stock` supports Chinese names, Chinese codes, and ticker symbols; auto-detects market
84
+ - Market priority for auto-detection: cn (A股) → hk (港股) → us (美股)
85
+ - US stock `High`/`Low` columns show 52-week range; A股/港股 show today's range
@@ -0,0 +1,62 @@
1
+ # Spotify
2
+
3
+ **Mode**: 🔑 OAuth API · **Domains**: `accounts.spotify.com`, `api.spotify.com`
4
+
5
+ ## Commands
6
+
7
+ | Command | Description |
8
+ |---------|-------------|
9
+ | `opencli spotify auth` | Authenticate with Spotify and store tokens locally |
10
+ | `opencli spotify status` | Show current playback status |
11
+ | `opencli spotify play [query]` | Resume playback or search-and-play a track |
12
+ | `opencli spotify pause` | Pause playback |
13
+ | `opencli spotify next` | Skip to the next track |
14
+ | `opencli spotify prev` | Skip to the previous track |
15
+ | `opencli spotify volume <0-100>` | Set playback volume |
16
+ | `opencli spotify search <query>` | Search Spotify tracks |
17
+ | `opencli spotify queue <query>` | Add a track to the playback queue |
18
+ | `opencli spotify shuffle <on|off>` | Toggle shuffle |
19
+ | `opencli spotify repeat <off|track|context>` | Set repeat mode |
20
+
21
+ ## Usage Examples
22
+
23
+ ```bash
24
+ # First-time setup
25
+ opencli spotify auth
26
+
27
+ # What is playing right now?
28
+ opencli spotify status
29
+
30
+ # Resume playback
31
+ opencli spotify play
32
+
33
+ # Search and immediately play a track
34
+ opencli spotify play "Numb Linkin Park"
35
+
36
+ # Search without playing
37
+ opencli spotify search "Daft Punk" --limit 5 -f json
38
+
39
+ # Queue a track
40
+ opencli spotify queue "Get Lucky"
41
+
42
+ # Playback controls
43
+ opencli spotify pause
44
+ opencli spotify next
45
+ opencli spotify prev
46
+ opencli spotify volume 35
47
+ opencli spotify shuffle on
48
+ opencli spotify repeat track
49
+ ```
50
+
51
+ ## Setup
52
+
53
+ 1. Create a Spotify app at <https://developer.spotify.com/dashboard>
54
+ 2. Add `http://127.0.0.1:8888/callback` to the app's Redirect URIs
55
+ 3. Fill in `SPOTIFY_CLIENT_ID` and `SPOTIFY_CLIENT_SECRET` in `~/.opencli/spotify.env`
56
+ 4. Run `opencli spotify auth`
57
+
58
+ ## Notes
59
+
60
+ - Browser Bridge is not required.
61
+ - Tokens are stored locally at `~/.opencli/spotify-tokens.json`.
62
+ - Playback commands work best when you already have an active Spotify device/session.
@@ -0,0 +1,45 @@
1
+ # Tieba
2
+
3
+ **Mode**: 🔐 Browser · **Domain**: `tieba.baidu.com`
4
+
5
+ ## Commands
6
+
7
+ | Command | Description |
8
+ |---------|-------------|
9
+ | `opencli tieba hot` | Read Tieba trending topics |
10
+ | `opencli tieba posts <forum>` | List threads in one forum |
11
+ | `opencli tieba search <keyword>` | Search threads across Tieba |
12
+ | `opencli tieba read <thread-id>` | Read one thread page |
13
+
14
+ ## Usage Examples
15
+
16
+ ```bash
17
+ # Trending topics
18
+ opencli tieba hot --limit 5
19
+
20
+ # List forum threads
21
+ opencli tieba posts 李毅 --limit 10
22
+
23
+ # Search Tieba
24
+ opencli tieba search 编程 --limit 10
25
+
26
+ # Read one thread
27
+ opencli tieba read 10163164720 --limit 10
28
+
29
+ # Read page 2 of a thread
30
+ opencli tieba read 10163164720 --page 2 --limit 10
31
+
32
+ # JSON output
33
+ opencli tieba hot -f json
34
+ ```
35
+
36
+ ## Notes
37
+
38
+ - `tieba search` currently supports only `--page 1`
39
+ - `tieba read --limit` counts reply rows; page 1 may also include the main post
40
+
41
+ ## Prerequisites
42
+
43
+ - Chrome running and able to open `tieba.baidu.com`
44
+ - [Browser Bridge extension](/guide/browser-bridge) installed
45
+ - For `posts`, `search`, and `read`, a valid Tieba login session in Chrome is recommended
@@ -12,6 +12,7 @@
12
12
  | `opencli xueqiu hot` | 获取雪球热门动态 |
13
13
  | `opencli xueqiu search` | 搜索雪球股票(代码或名称) |
14
14
  | `opencli xueqiu stock` | 获取雪球股票实时行情 |
15
+ | `opencli xueqiu comments` | 获取单只股票的讨论动态(按时间排序) |
15
16
  | `opencli xueqiu watchlist` | 获取雪球自选股列表 |
16
17
  | `opencli xueqiu fund-holdings` | 获取蛋卷基金持仓明细(可用 `--account` 按子账户过滤) |
17
18
  | `opencli xueqiu fund-snapshot` | 获取蛋卷基金快照(总资产、子账户、持仓,推荐 `-f json`) |
@@ -28,6 +29,9 @@ opencli xueqiu search 茅台
28
29
  # View one stock
29
30
  opencli xueqiu stock SH600519
30
31
 
32
+ # View recent discussions for one stock
33
+ opencli xueqiu comments SH600519 --limit 5
34
+
31
35
  # Upcoming earnings dates
32
36
  opencli xueqiu earnings-date SH600519 --next
33
37
 
@@ -57,4 +61,5 @@ opencli xueqiu feed -v
57
61
 
58
62
  - `fund-holdings` exposes both market value and share fields (`volume`, `usableRemainShare`)
59
63
  - `fund-snapshot -f json` is the easiest way to persist a full account snapshot for later analysis or diffing
64
+ - `comments` returns stock-scoped discussion posts from the symbol page, not reply threads under one parent post
60
65
  - If the commands return empty data, first confirm the logged-in browser can directly see the Danjuan asset page
@@ -0,0 +1,49 @@
1
+ # 知识星球 (ZSXQ)
2
+
3
+ **Mode**: 🔐 Browser · **Domain**: `wx.zsxq.com`
4
+
5
+ Read groups, topics, search results, dynamics, and single-topic details from [知识星球](https://wx.zsxq.com) using your logged-in Chrome session.
6
+
7
+ ## Commands
8
+
9
+ | Command | Description |
10
+ |---------|-------------|
11
+ | `opencli zsxq groups` | List the groups your account has joined |
12
+ | `opencli zsxq topics` | List topics in the active group |
13
+ | `opencli zsxq topic <id>` | Fetch a single topic with comments |
14
+ | `opencli zsxq search <keyword>` | Search topics inside a group |
15
+ | `opencli zsxq dynamics` | List recent dynamics across groups |
16
+
17
+ ## Usage Examples
18
+
19
+ ```bash
20
+ # List your groups
21
+ opencli zsxq groups
22
+
23
+ # List topics from the active group in Chrome
24
+ opencli zsxq topics --limit 20
25
+
26
+ # Search inside the active group
27
+ opencli zsxq search "opencli"
28
+
29
+ # Search inside a specific group explicitly
30
+ opencli zsxq search "opencli" --group_id 123456789
31
+
32
+ # Export a single topic with comments
33
+ opencli zsxq topic 987654321 --comment_limit 20
34
+
35
+ # Read recent dynamics across all joined groups
36
+ opencli zsxq dynamics --limit 20
37
+ ```
38
+
39
+ ## Prerequisites
40
+
41
+ - Chrome running and **logged into** [wx.zsxq.com](https://wx.zsxq.com)
42
+ - [Browser Bridge extension](/guide/browser-bridge) installed
43
+
44
+ ## Notes
45
+
46
+ - `zsxq topics` and `zsxq search` use the current active group context from Chrome by default
47
+ - If there is no active group context, pass `--group_id <id>` or open the target group in Chrome first
48
+ - `zsxq groups` returns `group_id`, which you can reuse with `--group_id`
49
+ - `zsxq topic` surfaces a missing topic as `NOT_FOUND` instead of a generic fetch error
@@ -8,10 +8,11 @@ Run `opencli list` for the live registry.
8
8
  |------|----------|------|
9
9
  | **[twitter](/adapters/browser/twitter)** | `trending` `bookmarks` `profile` `search` `timeline` `thread` `following` `followers` `notifications` `post` `reply` `delete` `like` `article` `follow` `unfollow` `bookmark` `unbookmark` `download` `accept` `reply-dm` `block` `unblock` `hide-reply` | 🔐 Browser |
10
10
  | **[reddit](/adapters/browser/reddit)** | `hot` `frontpage` `popular` `search` `subreddit` `read` `user` `user-posts` `user-comments` `upvote` `save` `comment` `subscribe` `saved` `upvoted` | 🔐 Browser |
11
+ | **[tieba](/adapters/browser/tieba)** | `hot` `posts` `search` `read` | 🔐 Browser |
11
12
  | **[bilibili](/adapters/browser/bilibili)** | `hot` `search` `me` `favorite` `history` `feed` `subtitle` `dynamic` `ranking` `following` `user-videos` `download` | 🔐 Browser |
12
13
  | **[zhihu](/adapters/browser/zhihu)** | `hot` `search` `question` `download` | 🔐 Browser |
13
14
  | **[xiaohongshu](/adapters/browser/xiaohongshu)** | `search` `notifications` `feed` `user` `download` `publish` `creator-notes` `creator-note-detail` `creator-notes-summary` `creator-profile` `creator-stats` | 🔐 Browser |
14
- | **[xueqiu](/adapters/browser/xueqiu)** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` `earnings-date` `fund-holdings` `fund-snapshot` | 🔐 Browser |
15
+ | **[xueqiu](/adapters/browser/xueqiu)** | `feed` `hot-stock` `hot` `search` `stock` `comments` `watchlist` `earnings-date` `fund-holdings` `fund-snapshot` | 🔐 Browser |
15
16
  | **[youtube](/adapters/browser/youtube)** | `search` `video` `transcript` | 🔐 Browser |
16
17
  | **[v2ex](/adapters/browser/v2ex)** | `hot` `latest` `topic` `node` `user` `member` `replies` `nodes` `daily` `me` `notifications` | 🌐 / 🔐 |
17
18
  | **[bloomberg](/adapters/browser/bloomberg)** | `main` `markets` `economics` `industries` `tech` `politics` `businessweek` `opinions` `feeds` `news` | 🌐 / 🔐 |
@@ -28,7 +29,7 @@ Run `opencli list` for the live registry.
28
29
  | **[linux-do](/adapters/browser/linux-do)** | `feed` `categories` `tags` `search` `topic` `user-topics` `user-posts` | 🔐 Browser |
29
30
  | **[chaoxing](/adapters/browser/chaoxing)** | `assignments` `exams` | 🔐 Browser |
30
31
  | **[grok](/adapters/browser/grok)** | `ask` | 🔐 Browser |
31
- | **[doubao](/adapters/browser/doubao)** | `status` `new` `send` `read` `ask` | 🔐 Browser |
32
+ | **[doubao](/adapters/browser/doubao)** | `status` `new` `send` `read` `ask` `history` `detail` `meeting-summary` `meeting-transcript` | 🔐 Browser |
32
33
  | **[weread](/adapters/browser/weread)** | `shelf` `search` `book` `ranking` `notebooks` `highlights` `notes` | 🔐 Browser |
33
34
  | **[douban](/adapters/browser/douban)** | `search` `top250` `subject` `photos` `download` `marks` `reviews` `movie-hot` `book-hot` | 🔐 Browser |
34
35
  | **[facebook](/adapters/browser/facebook)** | `feed` `profile` `search` `friends` `groups` `events` `notifications` `memories` `add-friend` `join-group` | 🔐 Browser |
@@ -45,6 +46,7 @@ Run `opencli list` for the live registry.
45
46
  | **[weixin](/adapters/browser/weixin)** | `download` | 🔐 Browser |
46
47
  | **[36kr](/adapters/browser/36kr)** | `news` `hot` `search` `article` | 🌐 / 🔐 |
47
48
  | **[producthunt](/adapters/browser/producthunt)** | `posts` `today` `hot` `browse` | 🌐 / 🔐 |
49
+ | **[ones](/adapters/browser/ones)** | `login` `me` `token-info` `tasks` `my-tasks` `task` `worklog` `logout` | 🔐 Browser Bridge + `ONES_BASE_URL` |
48
50
 
49
51
  ## Public API Adapters
50
52
 
@@ -62,6 +64,7 @@ Run `opencli list` for the live registry.
62
64
  | **[barchart](/adapters/browser/barchart)** | `quote` `options` `greeks` `flow` | 🌐 Public |
63
65
  | **[hf](/adapters/browser/hf)** | `top` | 🌐 Public |
64
66
  | **[sinafinance](/adapters/browser/sinafinance)** | `news` | 🌐 Public |
67
+ | **[spotify](/adapters/browser/spotify)** | `auth` `status` `play` `pause` `next` `prev` `volume` `search` `queue` `shuffle` `repeat` | 🔑 OAuth API |
65
68
  | **[stackoverflow](/adapters/browser/stackoverflow)** | `hot` `search` `bounties` `unanswered` | 🌐 Public |
66
69
  | **[wikipedia](/adapters/browser/wikipedia)** | `search` `summary` `random` `trending` | 🌐 Public |
67
70
  | **[lobsters](/adapters/browser/lobsters)** | `hot` `newest` `active` `tag` | 🌐 Public |
@@ -0,0 +1,32 @@
1
+ # ONES 项目管理平台(OpenCLI)
2
+
3
+ 基于官方 [ONES Project API](https://developer.ones.cn/zh-CN/docs/api/readme/),经 **Chrome + Browser Bridge** 在页面里 `fetch`(`credentials: 'include'`)。
4
+
5
+ ## 环境变量
6
+
7
+ | 变量 | 必填 | 说明 |
8
+ |------|------|------|
9
+ | `ONES_BASE_URL` | 是 | 与 Chrome 中访问的 ONES 根 URL 一致 |
10
+ | `ONES_USER_ID` / `ONES_AUTH_TOKEN` | 视部署 | 若接口强制要文档中的 Header,再设置(可先只依赖浏览器登录) |
11
+ | `ONES_EMAIL` / `ONES_PHONE` / `ONES_PASSWORD` | 否 | 供 `ones login` 脚本化 |
12
+
13
+ ## 命令
14
+
15
+ ```bash
16
+ export ONES_BASE_URL=https://your-host
17
+ # 安装扩展,Chrome 已登录 ONES
18
+
19
+ opencli ones me
20
+ opencli ones token-info # teams column includes name(uuid), useful for tasks
21
+ opencli ones tasks <teamUUID> --limit 20 --project <optional>
22
+ opencli ones my-tasks <teamUUID> --limit 100 # default assignee=self
23
+ opencli ones my-tasks <teamUUID> --mode field004 # deployments using field004 as assignee
24
+ opencli ones my-tasks <teamUUID> --mode both # assignee OR creator
25
+ opencli ones task <taskUUID> --team <teamUUID> # single task (URL .../task/<uuid>)
26
+ opencli ones worklog <taskUUID> 2 --team <teamUUID> # log hours for today
27
+ opencli ones worklog <taskUUID> 1 --team <teamUUID> --date 2026-03-01 # backfill
28
+ opencli ones login --email you@corp.com --password '***' # optional; stderr prints header export hints
29
+ opencli ones logout
30
+ ```
31
+
32
+ 更完整的说明见 [docs/adapters/browser/ones.md](../adapters/browser/ones.md)。
@@ -238,8 +238,7 @@ async function getAutomationWindow(workspace) {
238
238
  focused: false,
239
239
  width: 1280,
240
240
  height: 900,
241
- type: "normal",
242
- state: "normal"
241
+ type: "normal"
243
242
  });
244
243
  const session = {
245
244
  windowId: win.id,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "OpenCLI",
4
- "version": "1.5.4",
4
+ "version": "1.5.5",
5
5
  "description": "Browser automation bridge for the OpenCLI CLI tool. Executes commands in isolated Chrome windows via a local daemon.",
6
6
  "permissions": [
7
7
  "debugger",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencli-extension",
3
- "version": "1.5.4",
3
+ "version": "1.5.5",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -160,13 +160,14 @@ async function getAutomationWindow(workspace: string): Promise<number> {
160
160
 
161
161
  // Create a new window with a data: URI that New Tab Override extensions cannot intercept.
162
162
  // Using about:blank would be hijacked by extensions like "New Tab Override".
163
+ // Note: Do NOT set `state` parameter here. Chrome 146+ rejects 'normal' as an invalid
164
+ // state value for windows.create(). The window defaults to 'normal' state anyway.
163
165
  const win = await chrome.windows.create({
164
166
  url: BLANK_PAGE,
165
167
  focused: false,
166
168
  width: 1280,
167
169
  height: 900,
168
170
  type: 'normal',
169
- state: 'normal',
170
171
  });
171
172
  const session: AutomationSession = {
172
173
  windowId: win.id!,
@@ -251,6 +252,8 @@ async function handleCommand(cmd: Command): Promise<Result> {
251
252
  return await handleCloseWindow(cmd, workspace);
252
253
  case 'sessions':
253
254
  return await handleSessions(cmd);
255
+ case 'set-file-input':
256
+ return await handleSetFileInput(cmd, workspace);
254
257
  default:
255
258
  return { id: cmd.id, ok: false, error: `Unknown action: ${cmd.action}` };
256
259
  }
@@ -578,6 +581,19 @@ async function handleCloseWindow(cmd: Command, workspace: string): Promise<Resul
578
581
  return { id: cmd.id, ok: true, data: { closed: true } };
579
582
  }
580
583
 
584
+ async function handleSetFileInput(cmd: Command, workspace: string): Promise<Result> {
585
+ if (!cmd.files || !Array.isArray(cmd.files) || cmd.files.length === 0) {
586
+ return { id: cmd.id, ok: false, error: 'Missing or empty files array' };
587
+ }
588
+ const tabId = await resolveTabId(cmd.tabId, workspace);
589
+ try {
590
+ await executor.setFileInputFiles(tabId, cmd.files, cmd.selector);
591
+ return { id: cmd.id, ok: true, data: { count: cmd.files.length } };
592
+ } catch (err) {
593
+ return { id: cmd.id, ok: false, error: err instanceof Error ? err.message : String(err) };
594
+ }
595
+ }
596
+
581
597
  async function handleSessions(cmd: Command): Promise<Result> {
582
598
  const now = Date.now();
583
599
  const data = await Promise.all([...automationSessions.entries()].map(async ([workspace, session]) => ({
@@ -147,6 +147,48 @@ export async function screenshot(
147
147
  }
148
148
  }
149
149
 
150
+ /**
151
+ * Set local file paths on a file input element via CDP DOM.setFileInputFiles.
152
+ * This bypasses the need to send large base64 payloads through the message channel —
153
+ * Chrome reads the files directly from the local filesystem.
154
+ *
155
+ * @param tabId - Target tab ID
156
+ * @param files - Array of absolute local file paths
157
+ * @param selector - CSS selector to find the file input (optional, defaults to first file input)
158
+ */
159
+ export async function setFileInputFiles(
160
+ tabId: number,
161
+ files: string[],
162
+ selector?: string,
163
+ ): Promise<void> {
164
+ await ensureAttached(tabId);
165
+
166
+ // Enable DOM domain (required for DOM.querySelector and DOM.setFileInputFiles)
167
+ await chrome.debugger.sendCommand({ tabId }, 'DOM.enable');
168
+
169
+ // Get the document root
170
+ const doc = await chrome.debugger.sendCommand({ tabId }, 'DOM.getDocument') as {
171
+ root: { nodeId: number };
172
+ };
173
+
174
+ // Find the file input element
175
+ const query = selector || 'input[type="file"]';
176
+ const result = await chrome.debugger.sendCommand({ tabId }, 'DOM.querySelector', {
177
+ nodeId: doc.root.nodeId,
178
+ selector: query,
179
+ }) as { nodeId: number };
180
+
181
+ if (!result.nodeId) {
182
+ throw new Error(`No element found matching selector: ${query}`);
183
+ }
184
+
185
+ // Set files directly via CDP — Chrome reads from local filesystem
186
+ await chrome.debugger.sendCommand({ tabId }, 'DOM.setFileInputFiles', {
187
+ files,
188
+ nodeId: result.nodeId,
189
+ });
190
+ }
191
+
150
192
  export async function detach(tabId: number): Promise<void> {
151
193
  if (!attached.has(tabId)) return;
152
194
  attached.delete(tabId);
@@ -5,7 +5,7 @@
5
5
  * Everything else is just JS code sent via 'exec'.
6
6
  */
7
7
 
8
- export type Action = 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot' | 'close-window' | 'sessions';
8
+ export type Action = 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot' | 'close-window' | 'sessions' | 'set-file-input';
9
9
 
10
10
  export interface Command {
11
11
  /** Unique request ID */
@@ -32,6 +32,10 @@ export interface Command {
32
32
  quality?: number;
33
33
  /** Whether to capture full page (not just viewport) */
34
34
  fullPage?: boolean;
35
+ /** Local file paths for set-file-input action */
36
+ files?: string[];
37
+ /** CSS selector for file input element (set-file-input action) */
38
+ selector?: string;
35
39
  }
36
40
 
37
41
  export interface Result {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jackwener/opencli",
3
- "version": "1.5.4",
3
+ "version": "1.5.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -196,6 +196,22 @@ function main() {
196
196
  }
197
197
  }
198
198
 
199
+ // ── Spotify credentials template ────────────────────────────────────
200
+ const opencliDir = join(home, '.opencli');
201
+ const spotifyEnvFile = join(opencliDir, 'spotify.env');
202
+ ensureDir(opencliDir);
203
+ if (!existsSync(spotifyEnvFile)) {
204
+ writeFileSync(spotifyEnvFile,
205
+ `# Spotify credentials — get them at https://developer.spotify.com/dashboard\n` +
206
+ `# Add http://127.0.0.1:8888/callback as a Redirect URI in your Spotify app\n` +
207
+ `SPOTIFY_CLIENT_ID=your_spotify_client_id_here\n` +
208
+ `SPOTIFY_CLIENT_SECRET=your_spotify_client_secret_here\n`,
209
+ 'utf8'
210
+ );
211
+ console.log(`✓ Spotify credentials template created at ${spotifyEnvFile}`);
212
+ console.log(` Edit the file and add your Client ID and Secret, then run: opencli spotify auth`);
213
+ }
214
+
199
215
  // ── Browser Bridge setup hint ───────────────────────────────────────
200
216
  console.log('');
201
217
  console.log(' \x1b[1mNext step — Browser Bridge setup\x1b[0m');
@@ -19,7 +19,7 @@ function generateId(): string {
19
19
 
20
20
  export interface DaemonCommand {
21
21
  id: string;
22
- action: 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot' | 'close-window' | 'sessions';
22
+ action: 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot' | 'close-window' | 'sessions' | 'set-file-input';
23
23
  tabId?: number;
24
24
  code?: string;
25
25
  workspace?: string;
@@ -30,6 +30,10 @@ export interface DaemonCommand {
30
30
  format?: 'png' | 'jpeg';
31
31
  quality?: number;
32
32
  fullPage?: boolean;
33
+ /** Local file paths for set-file-input action */
34
+ files?: string[];
35
+ /** CSS selector for file input element (set-file-input action) */
36
+ selector?: string;
33
37
  }
34
38
 
35
39
  export interface DaemonResult {