rdt-cli 0.2.0__tar.gz

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.
@@ -0,0 +1,57 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_call:
9
+
10
+ jobs:
11
+ lint-and-test:
12
+ name: Lint and test (Python ${{ matrix.python-version }})
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ python-version: ["3.10", "3.12", "3.13"]
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Set up Python
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@v6
28
+
29
+ - name: Install dependencies
30
+ run: uv sync --group dev
31
+
32
+ - name: Run ruff
33
+ run: uv run ruff check .
34
+
35
+ - name: Run tests
36
+ run: uv run python -m pytest -q
37
+
38
+ build:
39
+ name: Build package
40
+ runs-on: ubuntu-latest
41
+ needs: lint-and-test
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+
45
+ - name: Set up Python
46
+ uses: actions/setup-python@v5
47
+ with:
48
+ python-version: "3.12"
49
+
50
+ - name: Install uv
51
+ uses: astral-sh/setup-uv@v6
52
+
53
+ - name: Install dependencies
54
+ run: uv sync --group dev
55
+
56
+ - name: Build distribution
57
+ run: uv build
@@ -0,0 +1,30 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ publish:
11
+ runs-on: ubuntu-latest
12
+ environment: pypi
13
+ permissions:
14
+ id-token: write
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.12"
22
+
23
+ - name: Setup uv
24
+ uses: astral-sh/setup-uv@v6
25
+
26
+ - name: Build package
27
+ run: uv build
28
+
29
+ - name: Publish to PyPI
30
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,8 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ dist/
4
+ .venv/
5
+ *.egg-info/
6
+ .ruff_cache/
7
+ .pytest_cache/
8
+ .mypy_cache/
rdt_cli-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,398 @@
1
+ Metadata-Version: 2.4
2
+ Name: rdt-cli
3
+ Version: 0.2.0
4
+ Summary: A CLI for Reddit — browse feeds, read posts, search, and interact via terminal 📖
5
+ Project-URL: Homepage, https://github.com/jackwener/rdt-cli
6
+ Project-URL: Repository, https://github.com/jackwener/rdt-cli
7
+ Project-URL: Issues, https://github.com/jackwener/rdt-cli/issues
8
+ Author-email: jackwener <jakevingoo@gmail.com>
9
+ License-Expression: Apache-2.0
10
+ Keywords: api,cli,rdt,reddit,terminal
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Utilities
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: browser-cookie3>=0.19
18
+ Requires-Dist: click>=8.0
19
+ Requires-Dist: httpx>=0.27
20
+ Requires-Dist: pyyaml>=6.0
21
+ Requires-Dist: rich>=13.0
22
+ Description-Content-Type: text/markdown
23
+
24
+ # rdt-cli
25
+
26
+ [![CI](https://github.com/jackwener/rdt-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/jackwener/rdt-cli/actions/workflows/ci.yml)
27
+ [![PyPI version](https://img.shields.io/pypi/v/rdt-cli.svg)](https://pypi.org/project/rdt-cli/)
28
+ [![Python](https://img.shields.io/badge/python-%3E%3D3.10-blue.svg)](https://pypi.org/project/rdt-cli/)
29
+
30
+ A CLI for Reddit — browse feeds, read posts, search, and interact via reverse-engineered API 📖
31
+
32
+ [English](#features) | [中文](#功能特性)
33
+
34
+ ## More Tools
35
+
36
+ - [xiaohongshu-cli](https://github.com/jackwener/xiaohongshu-cli) — Xiaohongshu CLI for search, reading, and posting
37
+ - [twitter-cli](https://github.com/jackwener/twitter-cli) — Twitter/X CLI for timelines, bookmarks, and posting
38
+ - [bilibili-cli](https://github.com/jackwener/bilibili-cli) — Bilibili CLI for videos, users, search, and feeds
39
+ - [discord-cli](https://github.com/jackwener/discord-cli) — Discord CLI for local-first sync, search, and export
40
+ - [tg-cli](https://github.com/jackwener/tg-cli) — Telegram CLI for local-first sync, search, and export
41
+
42
+ ## Features
43
+
44
+ - 🔐 **Auth** — auto-extract browser cookies, status check, whoami
45
+ - 🏠 **Feed** — browse home feed, popular, and /r/all
46
+ - 📋 **Subreddits** — browse any subreddit with sort/time filters, view subreddit info
47
+ - 📰 **Posts** — read posts and comment trees with syntax highlighting
48
+ - 🔢 **Short-index navigation** — `rdt show 3` to read, `rdt open 3` to browser
49
+ - 🔍 **Search** — full-text search with subreddit, sort, and time filters
50
+ - 📤 **Export** — export search results to CSV or JSON; `-o file.json` on any listing
51
+ - 👤 **Users** — view user profiles and post history
52
+ - ⬆️ **Interactions** — upvote/downvote, save/unsave, subscribe/unsubscribe, comment (with 1.5-4s rate-limit delay)
53
+ - 🛡️ **Anti-detection** — consistent Chrome 133 fingerprint, `sec-ch-ua` alignment, Gaussian jitter, exponential backoff
54
+ - 📊 **Structured output** — `--yaml`, `--json`, `--output FILE`, `--compact`, `--full-text`
55
+ - 📦 **Stable envelope** — see [SCHEMA.md](./SCHEMA.md) for `ok/schema_version/data/error`
56
+ - 🤖 **Agent-friendly** — Rich output on stderr, `--compact` for token-efficient output
57
+
58
+ > **AI Agent Tip:** Prefer `--yaml` for structured output unless strict JSON is required. Non-TTY stdout defaults to YAML automatically. Use `--compact` to reduce token usage.
59
+
60
+ ## Installation
61
+
62
+ ```bash
63
+ # Recommended: uv tool (fast, isolated)
64
+ uv tool install rdt-cli
65
+
66
+ # Or: pipx
67
+ pipx install rdt-cli
68
+ ```
69
+
70
+ Upgrade to the latest version:
71
+
72
+ ```bash
73
+ uv tool upgrade rdt-cli
74
+ # Or: pipx upgrade rdt-cli
75
+ ```
76
+
77
+ From source:
78
+
79
+ ```bash
80
+ git clone git@github.com:jackwener/rdt-cli.git
81
+ cd rdt-cli
82
+ uv sync
83
+ ```
84
+
85
+ ## Usage
86
+
87
+ ```bash
88
+ # ─── Auth ─────────────────────────────────────────
89
+ rdt login # Extract cookies from browser
90
+ rdt status # Check login status
91
+ rdt status --json # Structured JSON envelope
92
+ rdt whoami # Detailed profile (karma, account age)
93
+ rdt logout # Clear saved cookies
94
+
95
+ # ─── Browse ───────────────────────────────────────
96
+ rdt feed # Home feed (requires login)
97
+ rdt popular # Popular posts
98
+ rdt popular --full-text # Show full titles
99
+ rdt all # /r/all
100
+ rdt sub python # Browse subreddit
101
+ rdt sub programming -s top -t week # Sort + time filter
102
+ rdt sub-info python # Subreddit info (subscribers, etc.)
103
+ rdt user spez # User profile
104
+ rdt user-posts spez # User's submitted posts
105
+
106
+ # Short index works after list commands (feed/popular/sub/search)
107
+ rdt sub python
108
+ rdt show 1 # Read post #1 from listing
109
+ rdt open 1 # Open post #1 in browser
110
+ rdt upvote 1 # Upvote post #1
111
+
112
+ # ─── Reading ──────────────────────────────────────
113
+ rdt read 1abc123 # Read post by ID
114
+ rdt show 3 # Read result #3 from last listing
115
+ rdt show 1 -s top # Sort comments by top
116
+ rdt open 3 # Open in browser
117
+
118
+ # ─── Search ───────────────────────────────────────
119
+ rdt search "python async" # Global search
120
+ rdt search "rust vs go" -r programming # Within subreddit
121
+ rdt search "ML" -s top -t year # Sort by top, last year
122
+ rdt search "AI" -o results.json # Save to file
123
+ rdt search "rust" --compact --json # Compact agent output
124
+
125
+ # ─── Export ───────────────────────────────────────
126
+ rdt export "python tips" -n 100 -o tips.csv
127
+ rdt export "rust" --format json -o results.json
128
+
129
+ # ─── Interactions (require login) ─────────────────
130
+ rdt upvote 3 # Upvote result #3
131
+ rdt upvote 3 --down # Downvote
132
+ rdt upvote 3 --undo # Remove vote
133
+ rdt save 3 # Save result #3
134
+ rdt save 3 --undo # Unsave
135
+ rdt subscribe python # Subscribe to r/python
136
+ rdt subscribe python --undo # Unsubscribe
137
+ rdt comment 3 "Great post!" # Comment on result #3
138
+ ```
139
+
140
+ ## Authentication
141
+
142
+ rdt-cli supports browser cookie extraction to authenticate with Reddit:
143
+
144
+ 1. **Saved cookies** — loads from `~/.config/rdt-cli/credential.json`
145
+ 2. **Browser cookies** — auto-detects installed browsers and extracts cookies (supports Chrome, Firefox, Edge, Brave)
146
+
147
+ `rdt login` automatically tries all installed browsers and uses the first one with valid cookies.
148
+
149
+ ### Cookie TTL
150
+
151
+ Saved cookies are valid for **7 days** by default. After that, the client automatically attempts to refresh from the browser. If browser extraction fails, the existing cookies are used with a warning.
152
+
153
+ ### Short-Index Navigation
154
+
155
+ After any listing command such as `feed`, `popular`, `all`, `sub`, or `search`, the CLI stores the latest ordered post list in `~/.config/rdt-cli/index_cache.json`.
156
+
157
+ - `rdt show <N>` reads the Nth post from the latest listing
158
+ - `rdt open <N>` opens the Nth post in the browser
159
+ - `rdt upvote <N>`, `rdt save <N>`, `rdt comment <N>` reuse the same short index
160
+ - Empty listings clear the index cache, so old results are not reused by accident
161
+
162
+ ## Environment Variables
163
+
164
+ | Variable | Default | Description |
165
+ |----------|---------|-------------|
166
+ | `OUTPUT` | `auto` | Output format: `json`, `yaml`, `rich`, or `auto` (→ YAML when non-TTY) |
167
+
168
+ ## Rate Limiting & Anti-Detection
169
+
170
+ rdt-cli includes anti-detection measures designed to minimize risk:
171
+
172
+ ### Request Timing
173
+ - **Gaussian jitter**: Delays between requests use a truncated Gaussian distribution (~1s mean, σ=0.3)
174
+ - **Random long pauses**: ~5% of requests include an additional 2-5 second delay simulating reading behavior
175
+ - **Auto-retry**: Exponential backoff on HTTP 429/5xx and network errors (up to 3 retries)
176
+
177
+ ### Browser Fingerprint Consistency
178
+ - **UA/Platform alignment**: User-Agent, `sec-ch-ua`, `sec-ch-ua-platform`, `sec-ch-ua-mobile` are all consistent (Chrome 133)
179
+ - **Cookie merge**: Set-Cookie headers from Reddit responses are merged back into the session
180
+
181
+ ## Structured Output
182
+
183
+ All `--json` / `--yaml` output uses the shared envelope from [SCHEMA.md](./SCHEMA.md):
184
+ ```yaml
185
+ ok: true
186
+ schema_version: "1"
187
+ data: { ... }
188
+ ```
189
+
190
+ When stdout is not a TTY (e.g., piped or invoked by an AI agent), output defaults to YAML.
191
+ Use `OUTPUT=yaml|json|rich|auto` to override.
192
+
193
+ ## Use as AI Agent Skill
194
+
195
+ rdt-cli ships with a [`SKILL.md`](./SKILL.md) that teaches AI agents how to use it.
196
+
197
+ ### Claude Code / Antigravity
198
+
199
+ ```bash
200
+ mkdir -p .agents/skills
201
+ git clone git@github.com:jackwener/rdt-cli.git .agents/skills/rdt-cli
202
+
203
+ # Or just copy the SKILL.md
204
+ curl -o .agents/skills/rdt-cli/SKILL.md \
205
+ https://raw.githubusercontent.com/jackwener/rdt-cli/main/SKILL.md
206
+ ```
207
+
208
+ ### OpenClaw / ClawHub
209
+
210
+ ```bash
211
+ clawhub install rdt-cli
212
+ ```
213
+
214
+ ## Project Structure
215
+
216
+ ```text
217
+ rdt_cli/
218
+ ├── __init__.py # Version
219
+ ├── __main__.py # python -m rdt_cli entry point
220
+ ├── cli.py # Click entry point & command registration
221
+ ├── client.py # Reddit API client (rate-limit, retry, anti-detection)
222
+ ├── auth.py # Cookie authentication + TTL refresh
223
+ ├── constants.py # URLs, headers, sort options
224
+ ├── exceptions.py # Error hierarchy (6 exception types)
225
+ ├── index_cache.py # Short-index cache for show/open commands
226
+ └── commands/
227
+ ├── _common.py # Shared helpers (envelope, output routing, formatters)
228
+ ├── auth.py # login, logout, status, whoami
229
+ ├── browse.py # feed, popular, all, sub, sub-info, user, user-posts, open
230
+ ├── post.py # read, show
231
+ ├── search.py # search, export
232
+ └── social.py # upvote, save, subscribe, comment
233
+ ```
234
+
235
+ ## Development
236
+
237
+ ```bash
238
+ # Install dependencies
239
+ uv sync
240
+
241
+ # Run tests
242
+ uv run pytest tests/ -v
243
+
244
+ # Unit tests only (no network)
245
+ uv run pytest tests/ -v -m "not smoke"
246
+
247
+ # Smoke tests (need cookies)
248
+ uv run pytest tests/ -v -m smoke
249
+
250
+ # Lint
251
+ uv run ruff check .
252
+ ```
253
+
254
+ ## Troubleshooting
255
+
256
+ **Q: `No Reddit cookies found`**
257
+
258
+ 1. Open any browser and visit https://www.reddit.com/
259
+ 2. Log in with your account
260
+ 3. Run `rdt login` (auto-detects browser)
261
+
262
+ **Q: `database is locked`**
263
+
264
+ Close the browser Cookie database lock — close browser, then retry `rdt login`.
265
+
266
+ **Q: `Session expired`**
267
+
268
+ Your cookies have expired. Run `rdt logout && rdt login` to refresh.
269
+
270
+ **Q: `Rate limited`**
271
+
272
+ Wait and retry; the built-in exponential backoff handles this automatically.
273
+
274
+ **Q: Requests are slow**
275
+
276
+ The built-in Gaussian jitter delay (~1s between requests) is intentional to mimic natural browsing and avoid triggering Reddit's rate limiting.
277
+
278
+ ---
279
+
280
+ ## 推荐项目
281
+
282
+ - [xiaohongshu-cli](https://github.com/jackwener/xiaohongshu-cli) — 小红书搜索、阅读和发帖 CLI
283
+ - [twitter-cli](https://github.com/jackwener/twitter-cli) — Twitter/X 时间线、书签和发推 CLI
284
+ - [bilibili-cli](https://github.com/jackwener/bilibili-cli) — Bilibili 视频、用户、搜索与动态 CLI
285
+ - [discord-cli](https://github.com/jackwener/discord-cli) — Discord 本地优先同步、检索与导出 CLI
286
+ - [tg-cli](https://github.com/jackwener/tg-cli) — Telegram 本地优先同步、检索与导出 CLI
287
+
288
+ ## 功能特性
289
+
290
+ - 🔐 **认证** — 自动提取浏览器 Cookie,状态检查,用户信息
291
+ - 🏠 **浏览** — 首页 Feed、Popular、/r/all
292
+ - 📋 **子版块** — 浏览任意 subreddit(排序/时间过滤),查看子版块信息
293
+ - 📰 **帖子** — 阅读帖子和评论树
294
+ - 🔢 **短索引导航** — `rdt show 3` 阅读、`rdt open 3` 浏览器打开
295
+ - 🔍 **搜索** — 全文搜索,支持子版块、排序、时间过滤
296
+ - 📤 **导出** — 搜索结果导出为 CSV 或 JSON
297
+ - 👤 **用户** — 查看用户资料和发帖历史
298
+ - ⬆️ **互动** — 点赞/踩、收藏、订阅、评论
299
+ - 🛡️ **反风控** — Chrome 133 指纹一致性、高斯抖动延迟、指数退避重试
300
+ - 📊 **结构化输出** — `--yaml` / `--json`,非 TTY 默认输出 YAML
301
+ - 📦 **稳定 envelope** — 参见 [SCHEMA.md](./SCHEMA.md)
302
+
303
+ ## 安装
304
+
305
+ ```bash
306
+ # 推荐:uv tool(快速、隔离环境)
307
+ uv tool install rdt-cli
308
+
309
+ # 或者:pipx
310
+ pipx install rdt-cli
311
+ ```
312
+
313
+ 升级到最新版本:
314
+
315
+ ```bash
316
+ uv tool upgrade rdt-cli
317
+ # 或:pipx upgrade rdt-cli
318
+ ```
319
+
320
+ 从源码安装:
321
+
322
+ ```bash
323
+ git clone git@github.com:jackwener/rdt-cli.git
324
+ cd rdt-cli
325
+ uv sync
326
+ ```
327
+
328
+ ## 使用示例
329
+
330
+ ```bash
331
+ # 认证
332
+ rdt login # 从浏览器提取 Cookie
333
+ rdt status # 检查登录状态
334
+ rdt whoami # 查看用户资料
335
+ rdt logout # 清除缓存的 Cookie
336
+
337
+ # 浏览
338
+ rdt feed # 首页 Feed(需要登录)
339
+ rdt popular # 热门帖子
340
+ rdt all # /r/all
341
+ rdt sub python # 浏览子版块
342
+ rdt sub programming -s top -t week # 排序 + 时间过滤
343
+ rdt sub-info python # 子版块信息
344
+
345
+ # 阅读
346
+ rdt read 1abc123 # 按 ID 阅读帖子
347
+ rdt show 3 # 阅读最近一次列表里的第 3 条
348
+ rdt open 3 # 在浏览器打开
349
+
350
+ # 搜索
351
+ rdt search "python async" # 全局搜索
352
+ rdt search "rust vs go" -r programming # 在子版块内搜索
353
+ rdt export "python tips" -n 100 -o tips.csv # 导出
354
+
355
+ # 互动(需要登录)
356
+ rdt upvote 3 # 点赞
357
+ rdt save 3 # 收藏
358
+ rdt subscribe python # 订阅
359
+ rdt comment 3 "Great post!" # 评论
360
+ ```
361
+
362
+ ## 认证策略
363
+
364
+ rdt-cli 支持浏览器 Cookie 提取来认证 Reddit:
365
+
366
+ 1. **已保存 Cookie** — 从 `~/.config/rdt-cli/credential.json` 加载
367
+ 2. **浏览器 Cookie** — 自动检测已安装浏览器并提取(支持 Chrome、Firefox、Edge、Brave)
368
+
369
+ Cookie 保存后有效期 **7 天**,超时后自动尝试从浏览器刷新。
370
+
371
+ ## 常见问题
372
+
373
+ - `No Reddit cookies found` — 请先在任意浏览器打开 https://www.reddit.com/ 并登录,然后执行 `rdt login`
374
+ - `database is locked` — 关闭浏览器后重试
375
+ - `Session expired` — Cookie 过期,执行 `rdt logout && rdt login` 刷新
376
+ - `Rate limited` — 等待重试,内置指数退避会自动处理
377
+ - 请求较慢是正常的 — 内置高斯随机延迟(~1s)是为了模拟人类浏览行为,避免触发限速
378
+
379
+ ## 作为 AI Agent Skill 使用
380
+
381
+ rdt-cli 自带 [`SKILL.md`](./SKILL.md),让 AI Agent 能自动学习并使用本工具。
382
+
383
+ ### Claude Code / Antigravity
384
+
385
+ ```bash
386
+ mkdir -p .agents/skills
387
+ git clone git@github.com:jackwener/rdt-cli.git .agents/skills/rdt-cli
388
+ ```
389
+
390
+ ### OpenClaw / ClawHub
391
+
392
+ ```bash
393
+ clawhub install rdt-cli
394
+ ```
395
+
396
+ ## License
397
+
398
+ Apache-2.0