Skip to content

Commit 9696db9

Browse files
platonekojackwener
andauthored
feat: make primary args positional across all CLIs (#242)
* feat: make primary args positional across all CLIs Convert primary arguments from named options (--arg) to positional arguments for a more natural CLI experience. Affected sites: antigravity, bilibili, boss, chaoxing, coupang, grok, hf, instagram, jike, jimeng, linkedin, linux-do, tiktok, twitter, xiaohongshu, youtube Also adds Arg Design Convention to CONTRIBUTING.md and earnings-date to xueqiu command list in READMEs. Usage examples: opencli xueqiu search '茅台' (was: --query '茅台') opencli twitter followers elonmusk (was: --user elonmusk) opencli bilibili download BV1xxx (was: --bvid BV1xxx) * review: keep config args named in positional cleanup --------- Co-authored-by: jackwener <jakevingoo@gmail.com>
1 parent c76f86c commit 9696db9

File tree

22 files changed

+68
-26
lines changed

22 files changed

+68
-26
lines changed

CONTRIBUTING.md

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ strategy: public # public | cookie | header
4040
browser: false # true if browser session is needed
4141

4242
args:
43+
query:
44+
positional: true
45+
type: str
46+
required: true
47+
description: Search keyword
4348
limit:
4449
type: int
4550
default: 20
@@ -76,7 +81,7 @@ cli({
7681
domain: 'www.mysite.com',
7782
strategy: Strategy.COOKIE,
7883
args: [
79-
{ name: 'query', required: true, help: 'Search query' },
84+
{ name: 'query', positional: true, required: true, help: 'Search query' },
8085
{ name: 'limit', type: 'int', default: 10, help: 'Max results' },
8186
],
8287
columns: ['title', 'url', 'date'],
@@ -118,6 +123,39 @@ opencli <site> <command> --limit 3 -f json
118123
opencli <site> <command> -v
119124
```
120125

126+
## Arg Design Convention
127+
128+
Use **positional** for the primary, required argument of a command (the "what" — query, symbol, id, url, username). Use **named options** (`--flag`) for secondary/optional configuration (limit, format, sort, page, filters, language, date).
129+
130+
**Rule of thumb**: Think about how the user will type the command. `opencli xueqiu stock SH600519` is more natural than `opencli xueqiu stock --symbol SH600519`.
131+
132+
| Arg type | Positional? | Examples |
133+
|----------|-------------|----------|
134+
| Main target (query, symbol, id, url, username) | ✅ `positional: true` | `search '茅台'`, `stock SH600519`, `download BV1xxx` |
135+
| Configuration (limit, format, sort, page, type, filters) | ❌ Named `--flag` | `--limit 10`, `--format json`, `--sort hot`, `--location seattle` |
136+
137+
Do **not** convert an argument to positional just because it appears first in the file. If the argument is optional, acts like a filter, or selects a mode/configuration, it should usually stay a named option.
138+
139+
YAML example:
140+
```yaml
141+
args:
142+
query:
143+
positional: true # ← primary arg, user types it directly
144+
type: str
145+
required: true
146+
limit:
147+
type: int # ← config arg, user types --limit 10
148+
default: 20
149+
```
150+
151+
TS example:
152+
```typescript
153+
args: [
154+
{ name: 'query', positional: true, required: true, help: 'Search query' },
155+
{ name: 'limit', type: 'int', default: 10, help: 'Max results' },
156+
]
157+
```
158+
121159
## Testing
122160

123161
See [TESTING.md](./TESTING.md) for the full guide and exact test locations.

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ Run `opencli list` for the live registry.
128128
| **notion** | `status` `search` `read` `new` `write` `sidebar` `favorites` `export` | Desktop |
129129
| **discord-app** | `status` `send` `read` `channels` `servers` `search` `members` | Desktop |
130130
| **v2ex** | `hot` `latest` `topic` `daily` `me` `notifications` | Public / Browser |
131-
| **xueqiu** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` | Browser |
131+
| **xueqiu** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` `earnings-date` | Browser |
132132
| **antigravity** | `status` `send` `read` `new` `dump` `extract-code` `model` `watch` `serve` | Desktop |
133133
| **chatgpt** | `status` `new` `send` `read` `ask` | Desktop |
134134
| **xiaohongshu** | `search` `notifications` `feed` `user` `download` `creator-notes` `creator-note-detail` `creator-notes-summary` `creator-profile` `creator-stats` | Browser |
@@ -228,11 +228,11 @@ brew install yt-dlp
228228

229229
```bash
230230
# Download images/videos from Xiaohongshu note
231-
opencli xiaohongshu download --note-id abc123 --output ./xhs
231+
opencli xiaohongshu download abc123 --output ./xhs
232232

233233
# Download Bilibili video (requires yt-dlp)
234-
opencli bilibili download --bvid BV1xxx --output ./bilibili
235-
opencli bilibili download --bvid BV1xxx --quality 1080p # Specify quality
234+
opencli bilibili download BV1xxx --output ./bilibili
235+
opencli bilibili download BV1xxx --quality 1080p # Specify quality
236236

237237
# Download Twitter media from user
238238
opencli twitter download elonmusk --limit 20 --output ./twitter

README.zh-CN.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ npm install -g @jackwener/opencli@latest
129129
| **notion** | `status` `search` `read` `new` `write` `sidebar` `favorites` `export` | 桌面端 |
130130
| **discord-app** | `status` `send` `read` `channels` `servers` `search` `members` | 桌面端 |
131131
| **v2ex** | `hot` `latest` `topic` `daily` `me` `notifications` | 公开 / 浏览器 |
132-
| **xueqiu** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` | 浏览器 |
132+
| **xueqiu** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` `earnings-date` | 浏览器 |
133133
| **antigravity** | `status` `send` `read` `new` `dump` `extract-code` `model` `watch` `serve` | 桌面端 |
134134
| **chatgpt** | `status` `new` `send` `read` `ask` | 桌面端 |
135135
| **xiaohongshu** | `search` `notifications` `feed` `user` `download` `creator-notes` `creator-note-detail` `creator-notes-summary` `creator-profile` `creator-stats` | 浏览器 |
@@ -229,11 +229,11 @@ brew install yt-dlp
229229

230230
```bash
231231
# 下载小红书笔记中的图片/视频
232-
opencli xiaohongshu download --note-id abc123 --output ./xhs
232+
opencli xiaohongshu download abc123 --output ./xhs
233233

234234
# 下载B站视频(需要 yt-dlp)
235-
opencli bilibili download --bvid BV1xxx --output ./bilibili
236-
opencli bilibili download --bvid BV1xxx --quality 1080p # 指定画质
235+
opencli bilibili download BV1xxx --output ./bilibili
236+
opencli bilibili download BV1xxx --quality 1080p # 指定画质
237237

238238
# 下载 Twitter 用户的媒体
239239
opencli twitter download elonmusk --limit 20 --output ./twitter

src/clis/bilibili/following.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ cli({
88
description: '获取 Bilibili 用户的关注列表',
99
strategy: Strategy.COOKIE,
1010
args: [
11-
{ name: 'uid', required: false, help: '目标用户 ID(默认为当前登录用户)' },
11+
{ name: 'uid', positional: true, required: false, help: '目标用户 ID(默认为当前登录用户)' },
1212
{ name: 'page', type: 'int', required: false, default: 1, help: '页码' },
1313
{ name: 'limit', type: 'int', required: false, default: 50, help: '每页数量 (最大 50)' },
1414
],

src/clis/boss/detail.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ cli({
1313
navigateBefore: false,
1414
browser: true,
1515
args: [
16-
{ name: 'security-id', required: true, help: 'Security ID from search results (securityId field)' },
16+
{ name: 'security-id', positional: true, required: true, help: 'Security ID from search results (securityId field)' },
1717
],
1818
columns: [
1919
'name', 'salary', 'experience', 'degree', 'city', 'district',

src/clis/boss/greet.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ cli({
1616
navigateBefore: false,
1717
browser: true,
1818
args: [
19-
{ name: 'uid', required: true, help: 'Encrypted UID of the candidate (from recommend)' },
19+
{ name: 'uid', positional: true, required: true, help: 'Encrypted UID of the candidate (from recommend)' },
2020
{ name: 'security-id', required: true, help: 'Security ID of the candidate' },
2121
{ name: 'job-id', required: true, help: 'Encrypted job ID' },
2222
{ name: 'text', default: '', help: 'Custom greeting message (uses default template if empty)' },

src/clis/boss/invite.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ cli({
1313
navigateBefore: false,
1414
browser: true,
1515
args: [
16-
{ name: 'uid', required: true, help: 'Encrypted UID of the candidate' },
16+
{ name: 'uid', positional: true, required: true, help: 'Encrypted UID of the candidate' },
1717
{ name: 'time', required: true, help: 'Interview time (e.g. 2025-04-01 14:00)' },
1818
{ name: 'address', default: '', help: 'Interview address (uses saved address if empty)' },
1919
{ name: 'contact', default: '', help: 'Contact person name (uses saved contact if empty)' },

src/clis/boss/mark.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ cli({
2222
navigateBefore: false,
2323
browser: true,
2424
args: [
25-
{ name: 'uid', required: true, help: 'Encrypted UID of the candidate' },
25+
{ name: 'uid', positional: true, required: true, help: 'Encrypted UID of the candidate' },
2626
{ name: 'label', required: true, help: 'Label name (新招呼/沟通中/已约面/已获取简历/已交换电话/已交换微信/不合适/收藏) or label ID' },
2727
{ name: 'remove', type: 'boolean', default: false, help: 'Remove the label instead of adding' },
2828
],

src/clis/boss/send.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ cli({
1919
navigateBefore: false,
2020
browser: true,
2121
args: [
22-
{ name: 'uid', required: true, help: 'Encrypted UID of the candidate (from chatlist)' },
22+
{ name: 'uid', positional: true, required: true, help: 'Encrypted UID of the candidate (from chatlist)' },
2323
{ name: 'text', required: true, positional: true, help: 'Message text to send' },
2424
],
2525
columns: ['status', 'detail'],

src/clis/coupang/add-to-cart.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ cli({
102102
strategy: Strategy.COOKIE,
103103
browser: true,
104104
args: [
105-
{ name: 'product-id', required: false, help: 'Coupang product ID' },
105+
{ name: 'product-id', positional: true, required: false, help: 'Coupang product ID' },
106106
{ name: 'url', required: false, help: 'Canonical product URL' },
107107
],
108108
columns: ['ok', 'product_id', 'url', 'message'],

0 commit comments

Comments
 (0)