Reddit
Use public reddit.com/*.json over HTTP via the bundled cross-platform Python CLI.
Entry point
uv run --script <skill-dir>/scripts/cli.py ...
<skill-dir> = this skill directory. Do not rely on shell sourcing, executable bits, or shebang dispatch. Always run this documented entrypoint first: it auto-loads a skill-local .env using the lookup order below. Missing REDDIT_USER_AGENT is non-blocking because the CLI has a built-in default.
Quick start
uv run --script <skill-dir>/scripts/cli.py browse all hot limit=10
uv run --script <skill-dir>/scripts/cli.py browse technology top time=week limit=10
uv run --script <skill-dir>/scripts/cli.py search "h1b" subreddits='["cscareerquestions","immigration"]' sort=new time=month limit=10
uv run --script <skill-dir>/scripts/cli.py post programming 1abcde comment_limit=20 comment_sort=top
uv run --script <skill-dir>/scripts/cli.py post-url "https://reddit.com/r/programming/comments/1abcde/example/" comment_limit=20
uv run --script <skill-dir>/scripts/cli.py user-analysis spez posts_limit=5 comments_limit=5 time_range=month
uv run --script <skill-dir>/scripts/cli.py explain "cake day"
uv run --script <skill-dir>/scripts/cli.py browse all hot limit=25 raw=1
Output
Default HTTP commands return compact agent-shaped JSON:
browse / search / user-posts / user-comments: {"type": ..., "<subreddit|user|query>": ..., "sort": ..., "time": ..., "count": N, "results": [...]}. Each result retains id, title, subreddit, author, score, num_comments, url, permalink, created_utc, over_18, and is_self; flair and selftext_preview appear when set, with the latter collapsed and capped.
post / post-url: {"type": "post", "post": {...compact listing fields...}, "comments": [{"id", "author", "score", "body", "created_utc", "permalink", "depth"}, ...]}. Drop more placeholders; collapse comment bodies to single-spaced text.
user: {"type": "user", "user": "...", "profile": {"name", "created_utc", "link_karma", "comment_karma", "total_karma", "verified", "is_gold", "is_mod"}}
user-analysis: structured summary; see reference.md.
explain: {"term": "<normalized>", "definition": "..."}.
raw=1 returns full upstream JSON unchanged for browse, search, post, post-url, user, user-posts, and user-comments; explain and user-analysis always remain structured.
Errors
HTTP failures emit this one-line compact JSON to stderr:
{"error":{"provider":"reddit","status":403,"message":"Reddit returned HTTP 403","body_bytes":1234,"body_preview":"...","body_truncated":true,"kind":"network_security_block"}}
Fields: error.provider = "reddit"; error.status = Reddit HTTP status, or null for network errors; error.message = short human-readable cause; error.body_bytes = upstream size; error.body_preview = first 500 upstream chars, UTF-8 decoded; error.body_truncated = true when body exceeds preview cap. error.kind: "network_security_block" when body contains blocked by network security; "network_error" for URLError; "invalid_json" for unparseable responses; otherwise omitted.
Exit codes: HTTP 22; network 1; validation 2 with concise stderr and no traceback.
Environment
- Keep
.env beside this skill for a stable local User-Agent.
- Lookup order:
REDDIT_ENV_FILE → skill .env → $SKILLS_DIR/reddit/.env → nearest ancestor skills/reddit/.env.
- Tracked template:
.env.example.
- Common vars:
REDDIT_USER_AGENT, REDDIT_BASE_URL.
Failure handling
- Never treat the parent shell as
REDDIT_USER_AGENT source of truth; run the CLI so it loads its own .env.
- If loading still fails, set
REDDIT_ENV_FILE dynamically from the skill path; never hard-code a machine-specific directory.
- Missing
REDDIT_USER_AGENT after lookup is non-blocking because of the built-in default.
- Distinguish env lookup, HTTP failure, and Reddit blocking; report the actual request failure, not missing credentials.
network_security_block means Reddit or an upstream proxy refused that request, not local configuration failure. Record the route, failure, and date. Do not repeatedly retry the same blocked path or treat one failure as a permanent platform-wide ban.
- When direct retrieval is blocked, use
research to select an independent route. Use omp-search for bounded discovery by topic or exact thread title; follow its installed entrypoint and output contract.
- Treat search snippets and news summaries as indirect evidence. The search provider's synthesized
answer is not a verbatim Reddit comment. Quote only source text actually retrieved, with its attributable URL; do not reconstruct quotations from fragments.
- Report the query, time window, observed sample, and unavailable comments. Never generalize a search-selected sample into public opinion. Check material factual claims against official sources.
- For X evidence, use
x-research and its bounded retrieval contract rather than importing a Reddit block assumption. Fallbacks do not authorize credential changes, installations, paid operations, or writes outside the user's scope.
Aliases
search: subreddits='["a","b"]' must be a JSON list of non-empty strings; malformed values return rc=2. Also accepts author=<username>, flair=<text>, and time= as alias for t=.
post / post-url: comment_limit= → limit=, comment_sort= → sort=, comment_depth= → depth=.
Validation
browse requires a subreddit. Sort must be hot|new|top|rising|controversial and precede every key=value arg; stray positional tokens after key=value return rc=2.
post-url requires an http:// or https:// URL; otherwise rc=2.
user-analysis numeric args must be non-negative integers; time_range must be day|week|month|year|all. Invalid values return rc=2; never silently fall back to all.
explain lower-cases and trims input; hyphens become spaces for glossary lookup; empty/whitespace-only input returns rc=2.
Required reads
| Need |
Read |
When |
| Pick command and args for a Reddit query |
reference.md (Endpoints) |
Before invoking a new command |
| Reuse a known query shape |
assets/query-templates.json |
When request matches a known template |
| Understand compact JSON or error shape |
reference.md (Output shape / Errors) |
When consuming structured output or stderr |
Diagnose network_security_block |
SKILL.md (Failure handling) |
When error.kind is network_security_block |
| Override User-Agent / base URL |
.env.example |
When changing HTTP identity or using a mirror |
| Future refactor expectations and regression traps |
references/future-refactor.md |
When planning a larger refactor or changing output/error contracts |
Notes
Public JSON endpoints support anonymous basic read-only use. Set a custom REDDIT_USER_AGENT for hygiene and fewer blocks. OAuth-backed APIs exist but this skill intentionally uses public JSON for low-friction read-only access. Authenticated, private, or high-throughput access belongs in a separate OAuth feature, not this helper.
Query templates: assets/query-templates.json.
Validation command
uv run --script <skill-dir>/scripts/cli.py --help
Reference: reference.md.
1---2name: reddit3description: Use when Reddit posts, comments, subreddits, users, or community discussion must be searched or retrieved.4license: AGPL-3.0-or-later5---67# Reddit89Use public `reddit.com/*.json` over HTTP via the bundled cross-platform Python CLI.1011## Entry point1213```text14uv run --script <skill-dir>/scripts/cli.py ...15```1617`<skill-dir>` = this skill directory. Do not rely on shell sourcing, executable bits, or shebang dispatch. Always run this documented entrypoint first: it auto-loads a skill-local `.env` using the lookup order below. Missing `REDDIT_USER_AGENT` is non-blocking because the CLI has a built-in default.1819## Quick start2021```text22uv run --script <skill-dir>/scripts/cli.py browse all hot limit=1023uv run --script <skill-dir>/scripts/cli.py browse technology top time=week limit=1024uv run --script <skill-dir>/scripts/cli.py search "h1b" subreddits='["cscareerquestions","immigration"]' sort=new time=month limit=1025uv run --script <skill-dir>/scripts/cli.py post programming 1abcde comment_limit=20 comment_sort=top26uv run --script <skill-dir>/scripts/cli.py post-url "https://reddit.com/r/programming/comments/1abcde/example/" comment_limit=2027uv run --script <skill-dir>/scripts/cli.py user-analysis spez posts_limit=5 comments_limit=5 time_range=month28uv run --script <skill-dir>/scripts/cli.py explain "cake day"29uv run --script <skill-dir>/scripts/cli.py browse all hot limit=25 raw=130```3132## Output3334Default HTTP commands return compact agent-shaped JSON:35- `browse` / `search` / `user-posts` / `user-comments`: `{"type": ..., "<subreddit|user|query>": ..., "sort": ..., "time": ..., "count": N, "results": [...]}`. Each result retains `id`, `title`, `subreddit`, `author`, `score`, `num_comments`, `url`, `permalink`, `created_utc`, `over_18`, and `is_self`; `flair` and `selftext_preview` appear when set, with the latter collapsed and capped.36- `post` / `post-url`: `{"type": "post", "post": {...compact listing fields...}, "comments": [{"id", "author", "score", "body", "created_utc", "permalink", "depth"}, ...]}`. Drop `more` placeholders; collapse comment bodies to single-spaced text.37- `user`: `{"type": "user", "user": "...", "profile": {"name", "created_utc", "link_karma", "comment_karma", "total_karma", "verified", "is_gold", "is_mod"}}`38- `user-analysis`: structured summary; see `reference.md`.39- `explain`: `{"term": "<normalized>", "definition": "..."}`.4041`raw=1` returns full upstream JSON unchanged for `browse`, `search`, `post`, `post-url`, `user`, `user-posts`, and `user-comments`; `explain` and `user-analysis` always remain structured.4243## Errors4445HTTP failures emit this one-line compact JSON to stderr:4647```json48{"error":{"provider":"reddit","status":403,"message":"Reddit returned HTTP 403","body_bytes":1234,"body_preview":"...","body_truncated":true,"kind":"network_security_block"}}49```5051Fields: `error.provider` = `"reddit"`; `error.status` = Reddit HTTP status, or `null` for network errors; `error.message` = short human-readable cause; `error.body_bytes` = upstream size; `error.body_preview` = first 500 upstream chars, UTF-8 decoded; `error.body_truncated` = `true` when body exceeds preview cap. `error.kind`: `"network_security_block"` when body contains `blocked by network security`; `"network_error"` for `URLError`; `"invalid_json"` for unparseable responses; otherwise omitted.5253Exit codes: HTTP `22`; network `1`; validation `2` with concise stderr and no traceback.5455## Environment5657- Keep `.env` beside this skill for a stable local User-Agent.58- Lookup order: `REDDIT_ENV_FILE` → skill `.env` → `$SKILLS_DIR/reddit/.env` → nearest ancestor `skills/reddit/.env`.59- Tracked template: `.env.example`.60- Common vars: `REDDIT_USER_AGENT`, `REDDIT_BASE_URL`.6162## Failure handling6364- Never treat the parent shell as `REDDIT_USER_AGENT` source of truth; run the CLI so it loads its own `.env`.65- If loading still fails, set `REDDIT_ENV_FILE` dynamically from the skill path; never hard-code a machine-specific directory.66- Missing `REDDIT_USER_AGENT` after lookup is non-blocking because of the built-in default.67- Distinguish env lookup, HTTP failure, and Reddit blocking; report the actual request failure, not missing credentials.68- `network_security_block` means Reddit or an upstream proxy refused that request, not local configuration failure. Record the route, failure, and date. Do not repeatedly retry the same blocked path or treat one failure as a permanent platform-wide ban.69- When direct retrieval is blocked, use `research` to select an independent route. Use `omp-search` for bounded discovery by topic or exact thread title; follow its installed entrypoint and output contract.70- Treat search snippets and news summaries as indirect evidence. The search provider's synthesized `answer` is not a verbatim Reddit comment. Quote only source text actually retrieved, with its attributable URL; do not reconstruct quotations from fragments.71- Report the query, time window, observed sample, and unavailable comments. Never generalize a search-selected sample into public opinion. Check material factual claims against official sources.72- For X evidence, use `x-research` and its bounded retrieval contract rather than importing a Reddit block assumption. Fallbacks do not authorize credential changes, installations, paid operations, or writes outside the user's scope.7374## Aliases7576- `search`: `subreddits='["a","b"]'` must be a JSON list of non-empty strings; malformed values return rc=2. Also accepts `author=<username>`, `flair=<text>`, and `time=` as alias for `t=`.77- `post` / `post-url`: `comment_limit=` → `limit=`, `comment_sort=` → `sort=`, `comment_depth=` → `depth=`.7879## Validation8081- `browse` requires a subreddit. Sort must be `hot|new|top|rising|controversial` and precede every `key=value` arg; stray positional tokens after `key=value` return rc=2.82- `post-url` requires an `http://` or `https://` URL; otherwise rc=2.83- `user-analysis` numeric args must be non-negative integers; `time_range` must be `day|week|month|year|all`. Invalid values return rc=2; never silently fall back to `all`.84- `explain` lower-cases and trims input; hyphens become spaces for glossary lookup; empty/whitespace-only input returns rc=2.8586## Required reads8788|Need|Read|When|89|---|---|---|90|Pick command and args for a Reddit query|`reference.md` (Endpoints)|Before invoking a new command|91|Reuse a known query shape|`assets/query-templates.json`|When request matches a known template|92|Understand compact JSON or error shape|`reference.md` (Output shape / Errors)|When consuming structured output or stderr|93|Diagnose `network_security_block`|`SKILL.md` (Failure handling)|When `error.kind` is `network_security_block`|94|Override User-Agent / base URL|`.env.example`|When changing HTTP identity or using a mirror|95|Future refactor expectations and regression traps|`references/future-refactor.md`|When planning a larger refactor or changing output/error contracts|9697## Notes9899Public JSON endpoints support anonymous basic read-only use. Set a custom `REDDIT_USER_AGENT` for hygiene and fewer blocks. OAuth-backed APIs exist but this skill intentionally uses public JSON for low-friction read-only access. Authenticated, private, or high-throughput access belongs in a separate OAuth feature, not this helper.100101Query templates: `assets/query-templates.json`.102103## Validation command104105```text106uv run --script <skill-dir>/scripts/cli.py --help107```108109Reference: `reference.md`.