@jackwener/opencli 1.7.18 → 1.7.19

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 (95) hide show
  1. package/README.md +7 -8
  2. package/README.zh-CN.md +7 -8
  3. package/cli-manifest.json +305 -9
  4. package/clis/ctrip/ctrip.test.js +486 -1
  5. package/clis/ctrip/flight.js +136 -0
  6. package/clis/ctrip/hotel-search.js +132 -0
  7. package/clis/ctrip/utils.js +298 -0
  8. package/clis/google/search.js +16 -6
  9. package/clis/google-scholar/search.js +20 -5
  10. package/clis/google-scholar/search.test.js +35 -2
  11. package/clis/reddit/home.js +117 -0
  12. package/clis/reddit/home.test.js +127 -0
  13. package/clis/reddit/read.js +400 -54
  14. package/clis/reddit/read.test.js +315 -12
  15. package/clis/reddit/subreddit-info.js +117 -0
  16. package/clis/reddit/subreddit-info.test.js +163 -0
  17. package/clis/reddit/whoami.js +84 -0
  18. package/clis/reddit/whoami.test.js +105 -0
  19. package/clis/rednote/search.js +6 -2
  20. package/clis/twitter/bookmark-folder.js +3 -1
  21. package/clis/twitter/bookmarks.js +3 -1
  22. package/clis/twitter/followers.js +20 -5
  23. package/clis/twitter/followers.test.js +44 -0
  24. package/clis/twitter/following.js +36 -20
  25. package/clis/twitter/following.test.js +60 -8
  26. package/clis/twitter/likes.js +28 -13
  27. package/clis/twitter/likes.test.js +111 -1
  28. package/clis/twitter/list-add.js +128 -204
  29. package/clis/twitter/list-add.test.js +97 -1
  30. package/clis/twitter/list-tweets.js +13 -4
  31. package/clis/twitter/list-tweets.test.js +48 -0
  32. package/clis/twitter/lists.js +5 -2
  33. package/clis/twitter/post.js +23 -4
  34. package/clis/twitter/post.test.js +30 -0
  35. package/clis/twitter/profile.js +16 -8
  36. package/clis/twitter/profile.test.js +39 -0
  37. package/clis/twitter/reply.js +133 -10
  38. package/clis/twitter/reply.test.js +55 -0
  39. package/clis/twitter/search.js +188 -170
  40. package/clis/twitter/search.test.js +96 -258
  41. package/clis/twitter/shared.js +167 -16
  42. package/clis/twitter/shared.test.js +102 -1
  43. package/clis/twitter/timeline.js +3 -1
  44. package/clis/twitter/tweets.js +147 -51
  45. package/clis/twitter/tweets.test.js +238 -1
  46. package/clis/xiaohongshu/comments.js +23 -2
  47. package/clis/xiaohongshu/comments.test.js +63 -1
  48. package/clis/xiaohongshu/search.js +168 -13
  49. package/clis/xiaohongshu/search.test.js +82 -8
  50. package/clis/xueqiu/earnings-date.js +2 -2
  51. package/clis/xueqiu/kline.js +2 -2
  52. package/clis/xueqiu/utils.js +19 -0
  53. package/clis/xueqiu/utils.test.js +26 -0
  54. package/clis/zhihu/answer-detail.js +233 -0
  55. package/clis/zhihu/answer-detail.test.js +330 -0
  56. package/clis/zhihu/question.js +44 -10
  57. package/clis/zhihu/question.test.js +78 -1
  58. package/clis/zhihu/recommend.js +103 -0
  59. package/clis/zhihu/recommend.test.js +143 -0
  60. package/dist/src/browser/base-page.d.ts +3 -2
  61. package/dist/src/browser/base-page.test.js +2 -2
  62. package/dist/src/browser/cdp.js +3 -3
  63. package/dist/src/browser/page.d.ts +3 -2
  64. package/dist/src/browser/page.js +4 -4
  65. package/dist/src/browser/page.test.js +31 -0
  66. package/dist/src/browser/utils.d.ts +10 -0
  67. package/dist/src/browser/utils.js +37 -0
  68. package/dist/src/browser/utils.test.d.ts +1 -0
  69. package/dist/src/browser/utils.test.js +29 -0
  70. package/dist/src/cli-argv-preprocess.d.ts +37 -0
  71. package/dist/src/cli-argv-preprocess.js +131 -0
  72. package/dist/src/cli-argv-preprocess.test.d.ts +1 -0
  73. package/dist/src/cli-argv-preprocess.test.js +130 -0
  74. package/dist/src/cli.js +123 -86
  75. package/dist/src/cli.test.js +33 -28
  76. package/dist/src/commands/daemon.js +6 -7
  77. package/dist/src/doctor.js +15 -16
  78. package/dist/src/download/progress.js +15 -11
  79. package/dist/src/download/progress.test.d.ts +1 -0
  80. package/dist/src/download/progress.test.js +25 -0
  81. package/dist/src/execution.js +1 -3
  82. package/dist/src/execution.test.js +4 -16
  83. package/dist/src/help.d.ts +11 -0
  84. package/dist/src/help.js +46 -5
  85. package/dist/src/logger.js +8 -9
  86. package/dist/src/main.js +16 -0
  87. package/dist/src/output.js +4 -5
  88. package/dist/src/runtime-detect.d.ts +1 -1
  89. package/dist/src/runtime-detect.js +1 -1
  90. package/dist/src/runtime-detect.test.js +3 -2
  91. package/dist/src/tui.d.ts +0 -1
  92. package/dist/src/tui.js +9 -22
  93. package/dist/src/types.d.ts +3 -1
  94. package/dist/src/update-check.js +4 -5
  95. package/package.json +5 -4
package/README.md CHANGED
@@ -152,7 +152,7 @@ The agent handles all the `opencli browser` commands internally — you just des
152
152
 
153
153
  Available browser commands include `open`, `state`, `click`, `type`, `fill`, `select`, `keys`, `wait`, `get`, `find`, `extract`, `frames`, `screenshot`, `scroll`, `back`, `eval`, `network`, `tab list`, `tab new`, `tab select`, `tab close`, `init`, `verify`, and `close`.
154
154
 
155
- `opencli browser` commands require `--session <name>`. `opencli browser --session work open <url>` and `opencli browser --session work tab new [url]` both return a target ID. Use `opencli browser --session work tab list` to inspect target IDs, then pass `--tab <targetId>` to route a command to a specific tab. `tab new` creates a new tab without changing the default browser target; only `tab select <targetId>` promotes that tab to the default target for later untargeted commands in the same session.
155
+ `opencli browser` commands require a `<session>` positional immediately after `browser`. `opencli browser work open <url>` and `opencli browser work tab new [url]` both return a target ID. Use `opencli browser work tab list` to inspect target IDs, then pass `--tab <targetId>` to route a command to a specific tab. `tab new` creates a new tab without changing the default browser target; only `tab select <targetId>` promotes that tab to the default target for later untargeted commands in the same session.
156
156
 
157
157
  ## Core Concepts
158
158
 
@@ -160,7 +160,7 @@ Available browser commands include `open`, `state`, `click`, `type`, `fill`, `se
160
160
 
161
161
  `opencli browser` commands are the low-level primitives that AI Agents use to operate websites. You don't run these manually — instead, install the `opencli-adapter-author` skill into your AI agent, describe what you want in natural language, and the agent handles the browser operations.
162
162
 
163
- For example, tell your agent: *"Help me check my Xiaohongshu notifications"* — the agent will use `opencli browser --session <name> open`, `state`, `click`, etc. under the hood.
163
+ For example, tell your agent: *"Help me check my Xiaohongshu notifications"* — the agent will use `opencli browser <session> open`, `state`, `click`, etc. under the hood.
164
164
 
165
165
  ### Built-in adapters: stable commands
166
166
 
@@ -174,7 +174,7 @@ When the site you need is not yet covered, use the `opencli-adapter-author` skil
174
174
  2. Discover the right endpoint — network inspection, initial state, bundle search, token trace, or interceptor fallback.
175
175
  3. Decide the auth strategy — `PUBLIC` / `COOKIE` / `INTERCEPT` / `UI` / `LOCAL`.
176
176
  4. Decode response fields and design output columns.
177
- 5. `opencli browser --session recon analyze <url>` for one-shot recon, then `opencli browser --session recon init <site>/<name>` → write adapter → `opencli browser --session recon verify <site>/<name>`.
177
+ 5. `opencli browser recon analyze <url>` for one-shot recon, then `opencli browser recon init <site>/<name>` → write adapter → `opencli browser recon verify <site>/<name>`.
178
178
  6. Persist site knowledge to `~/.opencli/sites/<site>/` so the next adapter for the same site is faster.
179
179
 
180
180
  ### CLI Hub and desktop adapters
@@ -199,7 +199,6 @@ OpenCLI is not only for websites. It can also:
199
199
  | `OPENCLI_DAEMON_PORT` | `19825` | HTTP port for the daemon-extension bridge |
200
200
  | `OPENCLI_PROFILE` | — | Browser Bridge profile alias/contextId to use when multiple Chrome profiles are connected |
201
201
  | `OPENCLI_WINDOW` | command default | Set to `foreground` or `background` to override Browser Bridge window placement. Browser-backed commands also accept `--window <foreground\|background>`. |
202
- | `OPENCLI_KEEP_TAB` | command default | Set to `true` or `false` to keep or release the browser tab lease after a browser-backed adapter command. Browser-backed adapter commands also accept `--keep-tab <true\|false>`. |
203
202
  | `OPENCLI_BROWSER_CONNECT_TIMEOUT` | `30` | Seconds to wait for browser connection |
204
203
  | `OPENCLI_BROWSER_COMMAND_TIMEOUT` | `60` | Seconds to wait for a single browser command |
205
204
  | `OPENCLI_CDP_ENDPOINT` | — | Chrome DevTools Protocol endpoint for remote browser or Electron apps |
@@ -207,7 +206,7 @@ OpenCLI is not only for websites. It can also:
207
206
  | `OPENCLI_VERBOSE` | `false` | Enable verbose logging (`-v` flag also works) |
208
207
  | `DEBUG_SNAPSHOT` | — | Set to `1` for DOM snapshot debug output |
209
208
 
210
- `opencli browser *` requires an explicit `--session <name>`, uses a foreground browser window by default, and keeps that session's tab lease until `browser --session <name> close` or idle cleanup. Browser-backed adapters use a background adapter window and release one-shot tab leases by default. Interactive adapters can declare `siteSession: 'persistent'` to keep a stable site tab for continuity; pass `--site-session ephemeral` for a one-shot tab.
209
+ `opencli browser *` requires an explicit `<session>` positional, uses a foreground browser window by default, and keeps that session's tab lease until `opencli browser <session> close` or idle cleanup. Browser-backed adapters use a background adapter window and release one-shot tab leases by default. Interactive adapters can declare `siteSession: 'persistent'` to keep a stable site tab for continuity; pass `--site-session ephemeral` for a one-shot tab.
211
210
 
212
211
  ## Update
213
212
 
@@ -411,10 +410,10 @@ See [Plugins Guide](./docs/guide/plugins.md) for creating your own plugin.
411
410
  Before writing any adapter code, read the [`opencli-adapter-author` skill](./skills/opencli-adapter-author/SKILL.md). It takes you end-to-end:
412
411
 
413
412
  - Recon the site and pick a pattern (SPA / SSR / JSONP / Token / Streaming).
414
- - Discover the right endpoint via `opencli browser --session <name> network`, `eval`, or the interceptor fallback.
413
+ - Discover the right endpoint via `opencli browser <session> network`, `eval`, or the interceptor fallback.
415
414
  - Decide auth strategy (`PUBLIC` / `COOKIE` / `INTERCEPT` / `UI` / `LOCAL`).
416
- - Run `opencli browser --session recon analyze <url>` for one-shot recon, decode response fields, design columns, scaffold with `opencli browser --session recon init`.
417
- - Verify with `opencli browser --session recon verify <site>/<name>` before shipping.
415
+ - Run `opencli browser recon analyze <url>` for one-shot recon, decode response fields, design columns, scaffold with `opencli browser recon init`.
416
+ - Verify with `opencli browser recon verify <site>/<name>` before shipping.
418
417
 
419
418
  For long-lived personal commands that should live in your own Git repo, use a local plugin instead; see [Extending OpenCLI](./docs/guide/extending-opencli.md). Quick private adapters can still live at `~/.opencli/clis/<site>/<name>.js`. Site knowledge (endpoints, field maps, fixtures) accumulates in `~/.opencli/sites/<site>/` so the next adapter for the same site starts from context instead of zero.
420
419
 
package/README.zh-CN.md CHANGED
@@ -136,7 +136,7 @@ Agent 在内部自动处理所有 `opencli browser` 命令——你只需用自
136
136
 
137
137
  `browser` 可用命令包括:`open`、`state`、`click`、`type`、`fill`、`select`、`keys`、`wait`、`get`、`find`、`extract`、`frames`、`screenshot`、`scroll`、`back`、`eval`、`network`、`tab list`、`tab new`、`tab select`、`tab close`、`init`、`verify`、`close`。
138
138
 
139
- `opencli browser` 命令必须显式传 `--session <name>`。`opencli browser --session work open <url>` 和 `opencli browser --session work tab new [url]` 都会返回 target ID。`opencli browser --session work tab list` 用来查看当前已存在 tab 的 target ID,再通过 `--tab <targetId>` 把命令明确路由到某个 tab。`tab new` 只会新建 tab,不会改变默认浏览器目标;只有显式执行 `tab select <targetId>`,才会把该 tab 设为同一 session 后续未指定 target 的默认目标。
139
+ `opencli browser` 命令必须紧跟一个 `<session>` 位置参数。`opencli browser work open <url>` 和 `opencli browser work tab new [url]` 都会返回 target ID。`opencli browser work tab list` 用来查看当前已存在 tab 的 target ID,再通过 `--tab <targetId>` 把命令明确路由到某个 tab。`tab new` 只会新建 tab,不会改变默认浏览器目标;只有显式执行 `tab select <targetId>`,才会把该 tab 设为同一 session 后续未指定 target 的默认目标。
140
140
 
141
141
  ## 核心概念
142
142
 
@@ -144,7 +144,7 @@ Agent 在内部自动处理所有 `opencli browser` 命令——你只需用自
144
144
 
145
145
  `opencli browser` 命令是 AI Agent 操作网站的底层原语。你不需要手动运行这些命令——把 `opencli-adapter-author` skill 安装到你的 AI Agent 中,用自然语言描述你想做的事,Agent 会自动处理浏览器操作。
146
146
 
147
- 比如你告诉 Agent:*"帮我看看小红书的通知"*——Agent 会在底层调用 `opencli browser --session <name> open`、`state`、`click` 等命令。
147
+ 比如你告诉 Agent:*"帮我看看小红书的通知"*——Agent 会在底层调用 `opencli browser <session> open`、`state`、`click` 等命令。
148
148
 
149
149
  ### 内置适配器:稳定命令
150
150
 
@@ -158,7 +158,7 @@ Agent 在内部自动处理所有 `opencli browser` 命令——你只需用自
158
158
  2. 发现目标 endpoint——network 精读、initial state、bundle 搜索、token 溯源,或 interceptor 兜底
159
159
  3. 定认证策略——`PUBLIC` / `COOKIE` / `INTERCEPT` / `UI` / `LOCAL`
160
160
  4. 字段解码 + 设计输出列
161
- 5. `opencli browser --session recon analyze <url>` 一步侦察,再 `opencli browser --session recon init <site>/<name>` → 写适配器 → `opencli browser --session recon verify <site>/<name>`
161
+ 5. `opencli browser recon analyze <url>` 一步侦察,再 `opencli browser recon init <site>/<name>` → 写适配器 → `opencli browser recon verify <site>/<name>`
162
162
  6. 把站点知识沉到 `~/.opencli/sites/<site>/`,下次写同站点的其他命令直接吃缓存
163
163
 
164
164
  ### CLI 枢纽与桌面端适配器
@@ -182,7 +182,6 @@ OpenCLI 不只是网站 CLI,还可以:
182
182
  |------|--------|------|
183
183
  | `OPENCLI_DAEMON_PORT` | `19825` | daemon-extension 通信端口 |
184
184
  | `OPENCLI_WINDOW` | 命令默认值 | 设为 `foreground` 或 `background` 来覆盖 Browser Bridge 窗口位置。浏览器型命令也支持 `--window <foreground\|background>` |
185
- | `OPENCLI_KEEP_TAB` | 命令默认值 | 设为 `true` 或 `false` 来控制浏览器型 adapter 命令结束后是否保留 tab lease。浏览器型 adapter 命令也支持 `--keep-tab <true\|false>` |
186
185
  | `OPENCLI_BROWSER_CONNECT_TIMEOUT` | `30` | 浏览器连接超时(秒) |
187
186
  | `OPENCLI_BROWSER_COMMAND_TIMEOUT` | `60` | 单个浏览器命令超时(秒) |
188
187
  | `OPENCLI_CDP_ENDPOINT` | — | Chrome DevTools Protocol 端点,用于远程浏览器或 Electron 应用 |
@@ -190,7 +189,7 @@ OpenCLI 不只是网站 CLI,还可以:
190
189
  | `OPENCLI_VERBOSE` | `false` | 启用详细日志(`-v` 也可以) |
191
190
  | `DEBUG_SNAPSHOT` | — | 设为 `1` 输出 DOM 快照调试信息 |
192
191
 
193
- `opencli browser *` 必须显式传 `--session <name>`,默认使用前台窗口,并保留该 session 的 tab lease,直到你手动执行 `opencli browser --session <name> close` 或等空闲超时。浏览器型 adapter 默认使用后台 adapter 窗口并在命令结束后释放一次性 tab lease;如果需要调试最终页面,可以传 `--window foreground --keep-tab true`。
192
+ `opencli browser *` 必须紧跟一个 `<session>` 位置参数,默认使用前台窗口,并保留该 session 的 tab lease,直到你手动执行 `opencli browser <session> close` 或等空闲超时。浏览器型 adapter 默认使用后台 adapter 窗口并在命令结束后释放一次性 tab lease;如果需要调试最终页面,可以传 `--window foreground --keep-tab true`。
194
193
 
195
194
  ## 更新
196
195
 
@@ -510,10 +509,10 @@ opencli plugin uninstall my-tool # 卸载
510
509
  在动代码前,先读 [`opencli-adapter-author` skill](./skills/opencli-adapter-author/SKILL.md)。它把整个流程串起来:
511
510
 
512
511
  - 侦察站点,选定 pattern(SPA / SSR / JSONP / Token / Streaming)
513
- - 用 `opencli browser --session <name> network`、`eval`、interceptor 等找到目标 endpoint
512
+ - 用 `opencli browser <name> network`、`eval`、interceptor 等找到目标 endpoint
514
513
  - 定认证策略(`PUBLIC` / `COOKIE` / `INTERCEPT` / `UI` / `LOCAL`)
515
- - 先用 `opencli browser --session recon analyze <url>` 一步侦察,再字段解码、设计 columns、`opencli browser --session recon init` 生成骨架
516
- - 交付前用 `opencli browser --session recon verify <site>/<name>` 验证
514
+ - 先用 `opencli browser recon analyze <url>` 一步侦察,再字段解码、设计 columns、`opencli browser recon init` 生成骨架
515
+ - 交付前用 `opencli browser recon verify <site>/<name>` 验证
517
516
 
518
517
  在仓库外写的私有适配器放到 `~/.opencli/clis/<site>/<name>.js`;每个站点的 endpoint、字段映射、抓包样本会累积在 `~/.opencli/sites/<site>/`,下次写同站点的其他命令可以直接复用。
519
518
 
package/cli-manifest.json CHANGED
@@ -5842,6 +5842,122 @@
5842
5842
  "modulePath": "crates/search.js",
5843
5843
  "sourceFile": "crates/search.js"
5844
5844
  },
5845
+ {
5846
+ "site": "ctrip",
5847
+ "name": "flight",
5848
+ "description": "搜索携程一程机票(按出发/到达 IATA 三字码 + 日期)",
5849
+ "access": "read",
5850
+ "domain": "flights.ctrip.com",
5851
+ "strategy": "cookie",
5852
+ "browser": true,
5853
+ "args": [
5854
+ {
5855
+ "name": "from",
5856
+ "type": "str",
5857
+ "required": true,
5858
+ "positional": true,
5859
+ "help": "Departure IATA code (e.g. BJS / PEK)"
5860
+ },
5861
+ {
5862
+ "name": "to",
5863
+ "type": "str",
5864
+ "required": true,
5865
+ "positional": true,
5866
+ "help": "Arrival IATA code (e.g. SHA / PVG)"
5867
+ },
5868
+ {
5869
+ "name": "date",
5870
+ "type": "str",
5871
+ "required": true,
5872
+ "help": "Departure date (YYYY-MM-DD)"
5873
+ },
5874
+ {
5875
+ "name": "limit",
5876
+ "type": "int",
5877
+ "default": 20,
5878
+ "required": false,
5879
+ "help": "Number of flights (1-50)"
5880
+ }
5881
+ ],
5882
+ "columns": [
5883
+ "rank",
5884
+ "airline",
5885
+ "flightNo",
5886
+ "aircraft",
5887
+ "departureTime",
5888
+ "departureAirport",
5889
+ "arrivalTime",
5890
+ "arrivalAirport",
5891
+ "terminal",
5892
+ "price",
5893
+ "currency",
5894
+ "cabin",
5895
+ "url"
5896
+ ],
5897
+ "type": "js",
5898
+ "modulePath": "ctrip/flight.js",
5899
+ "sourceFile": "ctrip/flight.js",
5900
+ "navigateBefore": false
5901
+ },
5902
+ {
5903
+ "site": "ctrip",
5904
+ "name": "hotel-search",
5905
+ "description": "搜索携程酒店列表(按城市 + 入住/离店日期)",
5906
+ "access": "read",
5907
+ "domain": "hotels.ctrip.com",
5908
+ "strategy": "cookie",
5909
+ "browser": true,
5910
+ "args": [
5911
+ {
5912
+ "name": "city",
5913
+ "type": "str",
5914
+ "required": true,
5915
+ "positional": true,
5916
+ "help": "Numeric Ctrip city ID (use `ctrip search` or `ctrip hotel-suggest` to discover)"
5917
+ },
5918
+ {
5919
+ "name": "checkin",
5920
+ "type": "str",
5921
+ "required": true,
5922
+ "help": "Check-in date (YYYY-MM-DD)"
5923
+ },
5924
+ {
5925
+ "name": "checkout",
5926
+ "type": "str",
5927
+ "required": true,
5928
+ "help": "Check-out date (YYYY-MM-DD)"
5929
+ },
5930
+ {
5931
+ "name": "limit",
5932
+ "type": "int",
5933
+ "default": 10,
5934
+ "required": false,
5935
+ "help": "Number of hotels (1-30); SSR first page returns ~13 entries"
5936
+ }
5937
+ ],
5938
+ "columns": [
5939
+ "rank",
5940
+ "hotelId",
5941
+ "name",
5942
+ "enName",
5943
+ "star",
5944
+ "score",
5945
+ "scoreLabel",
5946
+ "reviewCount",
5947
+ "cityName",
5948
+ "district",
5949
+ "address",
5950
+ "lat",
5951
+ "lon",
5952
+ "price",
5953
+ "currency",
5954
+ "url"
5955
+ ],
5956
+ "type": "js",
5957
+ "modulePath": "ctrip/hotel-search.js",
5958
+ "sourceFile": "ctrip/hotel-search.js",
5959
+ "navigateBefore": false
5960
+ },
5845
5961
  {
5846
5962
  "site": "ctrip",
5847
5963
  "name": "hotel-suggest",
@@ -19083,6 +19199,39 @@
19083
19199
  "navigateBefore": "https://reddit.com",
19084
19200
  "siteSession": "persistent"
19085
19201
  },
19202
+ {
19203
+ "site": "reddit",
19204
+ "name": "home",
19205
+ "description": "Reddit personalized home feed (Best, requires login)",
19206
+ "access": "read",
19207
+ "domain": "reddit.com",
19208
+ "strategy": "cookie",
19209
+ "browser": true,
19210
+ "args": [
19211
+ {
19212
+ "name": "limit",
19213
+ "type": "int",
19214
+ "default": 25,
19215
+ "required": false,
19216
+ "help": "Number of posts (1–100)"
19217
+ }
19218
+ ],
19219
+ "columns": [
19220
+ "rank",
19221
+ "title",
19222
+ "subreddit",
19223
+ "score",
19224
+ "comments",
19225
+ "postId",
19226
+ "author",
19227
+ "url"
19228
+ ],
19229
+ "type": "js",
19230
+ "modulePath": "reddit/home.js",
19231
+ "sourceFile": "reddit/home.js",
19232
+ "navigateBefore": "https://reddit.com",
19233
+ "siteSession": "persistent"
19234
+ },
19086
19235
  {
19087
19236
  "site": "reddit",
19088
19237
  "name": "hot",
@@ -19203,6 +19352,20 @@
19203
19352
  "default": 2000,
19204
19353
  "required": false,
19205
19354
  "help": "Max characters per comment body (min 100)"
19355
+ },
19356
+ {
19357
+ "name": "expand-more",
19358
+ "type": "bool",
19359
+ "default": false,
19360
+ "required": false,
19361
+ "help": "Follow Reddit \"more comments\" stubs by calling /api/morechildren.json"
19362
+ },
19363
+ {
19364
+ "name": "expand-rounds",
19365
+ "type": "int",
19366
+ "default": 2,
19367
+ "required": false,
19368
+ "help": "Max expansion passes when --expand-more is on (1–5; each round can fan out new \"more\" stubs)"
19206
19369
  }
19207
19370
  ],
19208
19371
  "columns": [
@@ -19424,6 +19587,33 @@
19424
19587
  "navigateBefore": "https://reddit.com",
19425
19588
  "siteSession": "persistent"
19426
19589
  },
19590
+ {
19591
+ "site": "reddit",
19592
+ "name": "subreddit-info",
19593
+ "description": "Show metadata for a Reddit subreddit (subscribers, description, created date, NSFW)",
19594
+ "access": "read",
19595
+ "domain": "reddit.com",
19596
+ "strategy": "cookie",
19597
+ "browser": true,
19598
+ "args": [
19599
+ {
19600
+ "name": "name",
19601
+ "type": "string",
19602
+ "required": true,
19603
+ "positional": true,
19604
+ "help": "Subreddit name (no `r/` prefix needed)"
19605
+ }
19606
+ ],
19607
+ "columns": [
19608
+ "field",
19609
+ "value"
19610
+ ],
19611
+ "type": "js",
19612
+ "modulePath": "reddit/subreddit-info.js",
19613
+ "sourceFile": "reddit/subreddit-info.js",
19614
+ "navigateBefore": "https://reddit.com",
19615
+ "siteSession": "persistent"
19616
+ },
19427
19617
  {
19428
19618
  "site": "reddit",
19429
19619
  "name": "subscribe",
@@ -19622,6 +19812,25 @@
19622
19812
  "navigateBefore": "https://reddit.com",
19623
19813
  "siteSession": "persistent"
19624
19814
  },
19815
+ {
19816
+ "site": "reddit",
19817
+ "name": "whoami",
19818
+ "description": "Show the currently logged-in Reddit user",
19819
+ "access": "read",
19820
+ "domain": "reddit.com",
19821
+ "strategy": "cookie",
19822
+ "browser": true,
19823
+ "args": [],
19824
+ "columns": [
19825
+ "field",
19826
+ "value"
19827
+ ],
19828
+ "type": "js",
19829
+ "modulePath": "reddit/whoami.js",
19830
+ "sourceFile": "reddit/whoami.js",
19831
+ "navigateBefore": "https://reddit.com",
19832
+ "siteSession": "persistent"
19833
+ },
19625
19834
  {
19626
19835
  "site": "rednote",
19627
19836
  "name": "comments",
@@ -22955,7 +23164,9 @@
22955
23164
  "retweets",
22956
23165
  "replies",
22957
23166
  "created_at",
22958
- "url"
23167
+ "url",
23168
+ "has_media",
23169
+ "media_urls"
22959
23170
  ],
22960
23171
  "type": "js",
22961
23172
  "modulePath": "twitter/list-tweets.js",
@@ -23049,7 +23260,9 @@
23049
23260
  "columns": [
23050
23261
  "status",
23051
23262
  "message",
23052
- "text"
23263
+ "text",
23264
+ "id",
23265
+ "url"
23053
23266
  ],
23054
23267
  "type": "js",
23055
23268
  "modulePath": "twitter/post.js",
@@ -23177,7 +23390,8 @@
23177
23390
  "columns": [
23178
23391
  "status",
23179
23392
  "message",
23180
- "text"
23393
+ "text",
23394
+ "url"
23181
23395
  ],
23182
23396
  "type": "js",
23183
23397
  "modulePath": "twitter/reply.js",
@@ -23265,7 +23479,7 @@
23265
23479
  "description": "Search Twitter/X for tweets, with optional --from / --has / --exclude / --product filters mapped to X's search operators",
23266
23480
  "access": "read",
23267
23481
  "domain": "x.com",
23268
- "strategy": "intercept",
23482
+ "strategy": "cookie",
23269
23483
  "browser": true,
23270
23484
  "args": [
23271
23485
  {
@@ -23358,7 +23572,7 @@
23358
23572
  "type": "js",
23359
23573
  "modulePath": "twitter/search.js",
23360
23574
  "sourceFile": "twitter/search.js",
23361
- "navigateBefore": true,
23575
+ "navigateBefore": "https://x.com",
23362
23576
  "siteSession": "persistent"
23363
23577
  },
23364
23578
  {
@@ -23493,7 +23707,7 @@
23493
23707
  {
23494
23708
  "site": "twitter",
23495
23709
  "name": "tweets",
23496
- "description": "Fetch a Twitter user's most recent tweets (chronological, excludes pinned)",
23710
+ "description": "Fetch a Twitter user's most recent tweets (chronological, excludes pinned; defaults to the logged-in user when no username is given)",
23497
23711
  "access": "read",
23498
23712
  "domain": "x.com",
23499
23713
  "strategy": "cookie",
@@ -23502,9 +23716,9 @@
23502
23716
  {
23503
23717
  "name": "username",
23504
23718
  "type": "string",
23505
- "required": true,
23719
+ "required": false,
23506
23720
  "positional": true,
23507
- "help": "Twitter screen name (with or without @)"
23721
+ "help": "Twitter screen name (with or without @). Defaults to the logged-in user when omitted."
23508
23722
  },
23509
23723
  {
23510
23724
  "name": "limit",
@@ -28000,6 +28214,47 @@
28000
28214
  "sourceFile": "zhihu/answer.js",
28001
28215
  "navigateBefore": "https://www.zhihu.com"
28002
28216
  },
28217
+ {
28218
+ "site": "zhihu",
28219
+ "name": "answer-detail",
28220
+ "description": "知乎单个回答完整内容(按 answer ID 获取)",
28221
+ "access": "read",
28222
+ "domain": "www.zhihu.com",
28223
+ "strategy": "cookie",
28224
+ "browser": true,
28225
+ "args": [
28226
+ {
28227
+ "name": "id",
28228
+ "type": "str",
28229
+ "required": true,
28230
+ "positional": true,
28231
+ "help": "Answer ID, full Zhihu answer URL, or typed target (answer:<qid>:<aid>)"
28232
+ },
28233
+ {
28234
+ "name": "max-content",
28235
+ "type": "int",
28236
+ "default": 0,
28237
+ "required": false,
28238
+ "help": "Optional cap on stripped content length in characters (0 = no truncation, return the full answer)"
28239
+ }
28240
+ ],
28241
+ "columns": [
28242
+ "id",
28243
+ "author",
28244
+ "votes",
28245
+ "comments",
28246
+ "question_id",
28247
+ "question_title",
28248
+ "url",
28249
+ "created_at",
28250
+ "updated_at",
28251
+ "content"
28252
+ ],
28253
+ "type": "js",
28254
+ "modulePath": "zhihu/answer-detail.js",
28255
+ "sourceFile": "zhihu/answer-detail.js",
28256
+ "navigateBefore": "https://www.zhihu.com"
28257
+ },
28003
28258
  {
28004
28259
  "site": "zhihu",
28005
28260
  "name": "collection",
@@ -28334,7 +28589,18 @@
28334
28589
  "type": "int",
28335
28590
  "default": 5,
28336
28591
  "required": false,
28337
- "help": "Number of answers"
28592
+ "help": "Number of answers (max 1000; use normal-sized requests)"
28593
+ },
28594
+ {
28595
+ "name": "sort",
28596
+ "type": "str",
28597
+ "default": "default",
28598
+ "required": false,
28599
+ "help": "Answer order: default or created",
28600
+ "choices": [
28601
+ "default",
28602
+ "created"
28603
+ ]
28338
28604
  }
28339
28605
  ],
28340
28606
  "columns": [
@@ -28348,6 +28614,36 @@
28348
28614
  "sourceFile": "zhihu/question.js",
28349
28615
  "navigateBefore": "https://www.zhihu.com"
28350
28616
  },
28617
+ {
28618
+ "site": "zhihu",
28619
+ "name": "recommend",
28620
+ "description": "知乎首页推荐",
28621
+ "access": "read",
28622
+ "domain": "www.zhihu.com",
28623
+ "strategy": "cookie",
28624
+ "browser": true,
28625
+ "args": [
28626
+ {
28627
+ "name": "limit",
28628
+ "type": "int",
28629
+ "default": 20,
28630
+ "required": false,
28631
+ "help": "Number of items to return (max 1000; use normal-sized requests)"
28632
+ }
28633
+ ],
28634
+ "columns": [
28635
+ "rank",
28636
+ "type",
28637
+ "title",
28638
+ "author",
28639
+ "votes",
28640
+ "url"
28641
+ ],
28642
+ "type": "js",
28643
+ "modulePath": "zhihu/recommend.js",
28644
+ "sourceFile": "zhihu/recommend.js",
28645
+ "navigateBefore": "https://www.zhihu.com"
28646
+ },
28351
28647
  {
28352
28648
  "site": "zhihu",
28353
28649
  "name": "search",