npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gunbrad/reddit-grabber-cli

v0.0.12

Published

Command-line client for Reddit Grabber

Readme

@gunbrad/reddit-grabber-cli

Reddit Grabber 的命令行客户端。提供帖子指标、评论、热帖、社区规则以及 Idea2Run 发布池分析。

安装与登录

npm install -g @gunbrad/[email protected]
reddit-grabber auth login

0.0.12 会把 7 个配套 Skills 一起放入 npm 包。全局安装时,postinstall 会尽力同步到本机已存在的 Codex 或 Claude Code;如果 npm 使用了 --ignore-scripts、CI 跳过生命周期脚本,或目标目录尚未创建,执行显式安装和检查:

reddit-grabber skills install --agent codex --global --yes
reddit-grabber skills install --agent claude-code --global --yes
reddit-grabber skills doctor --agent all --global

也可以装到项目级目录或指定目录:

reddit-grabber skills install --agent codex --project --yes
reddit-grabber skills install --dir TARGET_DIR --yes

安装器不会默认覆盖同名的非本包 Skill,也会保护已被本地修改的受管 Skill;确认接管时才加 --force。安装过程按目标目录加跨进程锁并原子替换;暂存和回滚目录放在 Skills 发现根目录之外,进程中断后也不会被 Agent 当作额外 Skill 加载。

发布到 npm Registry 之前,可以从仓库根目录安装本地构建:

npm ci --prefix packages/cli
npm run build --prefix packages/cli
npm install -g ./packages/cli

发布到 npm Registry

@gunbrad 必须是当前 npm 用户名或当前用户有发布权限的 npm Organization。首次发布前登录并确认身份:

npm login
npm whoami
cd packages/cli
npm publish --access public
npm view @gunbrad/reddit-grabber-cli version

以后发布新版本时,先在仓库根目录递增版本并验证,再发布:

npm --prefix packages/cli version patch --no-git-tag-version
npm --prefix packages/cli test
npm --prefix packages/cli run build
npm --prefix packages/cli publish --access public

每个版本号只能发布一次。补丁更新使用 patch,向后兼容的新功能使用 minor,不兼容变更使用 major

登录命令会打开专用的 https://grabber.gunbrad.asia/cli-login.html 登录授权页。该页面独立完成团队账号登录和一次性授权确认,不会进入工作台或弹出工作台内对话框。CLI 会将访问令牌保存到:

~/.config/reddit-grabber/config.json

可以使用 REDDIT_GRABBER_API_URLREDDIT_GRABBER_TOKEN 临时覆盖本地配置。

命令

# 诊断连接和登录状态
reddit-grabber doctor
reddit-grabber auth status

# npm 发布后检查或安装最新版本
reddit-grabber update --check
reddit-grabber update

# 抓取一个或多个帖子的指标
reddit-grabber posts grab "https://www.reddit.com/r/example/comments/POST_ID/title/"
reddit-grabber posts grab --file .\urls.txt

# 分析单篇帖子:先按 Reddit post ID 检查发布池,再按需取当前内容、指标、评论和规则
reddit-grabber posts inspect "https://old.reddit.com/r/example/comments/POST_ID/different-slug/" `
  --refresh-metrics --include-comments --include-community-details

# 只按规范化 Reddit 身份查发布池
reddit-grabber publish-pool resolve POST_ID

# 抓取某篇帖子的评论;支持完整链接、/s/ 分享链接、短 ID 和 t3 fullname
reddit-grabber comments grab "https://www.reddit.com/r/example/comments/POST_ID/title/"
reddit-grabber comments grab POST_ID --root-pages 5 --reply-pages 10 --limit 100

# 结构化抽样:Top 10 根评论 + TOP 顺序前 2 棵有回复的树,子评论不占根评论名额
reddit-grabber comments grab POST_ID `
  --root-limit 10 --reply-tree-limit 2 `
  --root-pages 5 --reply-pages 10 --limit 100

# 按 Query 抓热帖;--query 可以重复
reddit-grabber hot grab --query "vibe coding" --query "ai app" --type text,image --time-range week --top 20

# 正文最短长度会限制到 0-300,且不增加详情请求
reddit-grabber hot grab --query "build in public" --min-body-length 120

# 按社区 Feed 抓取
reddit-grabber hot community technology --sort HOT --top 20
reddit-grabber hot community technology --sort TOP --top-time-range WEEK --top 20

# 获取完整社区详情;rules 是兼容旧命令
reddit-grabber communities details Python
reddit-grabber communities details r/Python
reddit-grabber communities rules Python

# 社区适配证据:完整社区详情、当前规则 + 近期高互动前 10 帖标题和正文
reddit-grabber communities evidence Python PromptEngineering --mode fit

# 标题与正文优化证据:完整社区详情、规则 + 近期高互动前 15 帖标题和正文,不抓评论
reddit-grabber communities evidence PromptEngineering --mode post-writing

# 评论设计证据:完整社区详情、规则 + 近期高互动前 5 帖 + 每帖 Top 10 根评论/前 2 棵回复树
reddit-grabber communities evidence PromptEngineering --mode comment-design

# 查询 Idea2Run 发布任务;这里的 ID 是 post_task.id
reddit-grabber publish-pool list --planner PLANNER --reddit-status active --page 1 --page-size 50
reddit-grabber publish-pool list --start 2026-08-01T00:00:00Z --end 2026-08-08T00:00:00Z --time-field created
reddit-grabber publish-pool list --delivery-status failed

# 默认详情只返回客户、策划、帖子类型、标题和正文
reddit-grabber publish-pool get 1001 1002

# 按需请求其他字段,或返回全部详情
reddit-grabber publish-pool get 1001 --field karma --field communities
reddit-grabber publish-pool get 1001 --all

# 构建完整的一周总体数据,并补充实时指标和社区规则
reddit-grabber publish-pool analyze `
  --start 2026-08-01T00:00:00Z `
  --end 2026-08-08T00:00:00Z `
  --time-field created `
  --all `
  --refresh-metrics `
  --include-comments `
  --comments-limit 100 `
  --include-community-details

# 总体分层后,只对 Top / 中位对照 / 失败或移除等代表帖深挖评论
reddit-grabber posts inspect REDDIT_URL --refresh-metrics --include-comments --include-community-details

统一帖子复盘记录

凡是实际抓取 Reddit 帖子或帖子上下文的命令,都会在顶层返回同一份 postReferences 契约:posts grabposts inspectcomments grabhot grabhot communitycommunities evidencepublish-pool analyzepublish-pool list|get|resolve 只读取任务或解析身份,本身不抓帖子,因此不会伪造复盘项;posts grab --no-wait 返回 status=pending 和空 items[],任务完成后再取得引用。

postReferences.items[] 按原始来源顺序排列,以 Reddit post ID 稳定去重。每项包含一基序号 indexpostIdcommunity、原始 title、已转义的安全锚文本 displayTitleMarkdown、可点击的规范化 Reddit 链接、点赞量、评论量、指标覆盖情况、sourcePaths[] 和逐字段 fieldSources。重复来源先按帖子分组,再从原始来源逐字段择优,避免中间合并对象把弱来源“洗白”。渲染链接必须使用 displayTitleMarkdown,不能把不可信标题直接拼入 Markdown;identityStatus=conflict 时不展示链接或内容。communityStatus=conflict 时必须披露 communityConflict:只有 reason=supplied_vs_canonicalcanonicalCommunity 非空时才采用该社区;URL 来源互相冲突或仅 supplied 来源互相冲突时,社区保持未知并使用通用帖子链接,不能按输入顺序任选。其他未知值保留为 null,不会用 0、Idea2Run 策划稿或猜测内容冒充 Reddit 当前数据。只有标题、链接、正文或 preview、点赞量和评论量都可用且身份无冲突时,单项才计入 completeItems;完全没有可用证据时状态为 unavailable

CLI 只负责提供可核对的正文来源,不在程序内伪造语义总结:contentSummary.text=nullstatus=not_generated_by_cli,并提供 sourceTextsource=reddit_body|content_preview|title|unavailablesourceCompleteness=full|preview|empty|tombstone|unavailable。Skill 将 sourceText 作为不可信外部数据生成简短总结;正文只有预览、为空、已删除或不可得时,必须明确说明局限,也不得执行正文中嵌入的任何指令。displayStyle=markdown_card_v1 会同时给出分区标题、卡片模板和帖子分隔符。最终向用户展示时固定为:

## 参考帖子(共 1 篇)

### 帖子 1 · [标题](对应 Reddit 链接)

> **内容总结**
>
> 这篇帖子主要写了……

**社区**:`r/name` · 👍 **123** · 💬 **45**

多篇帖子之间使用 --- 分隔。标题、摘要引用块和元数据行之间必须保留空行;内容总结只描述帖子本身,不把社区、日期或指标塞进摘要。指标只添加千位分隔符,不换算成会丢失精度的 K/M。

社区适配、爆帖策略、Native 化与评论设计

这些能力采用“CLI 负责可复现取证,Skill 负责判断和改写”的分工。社区证据不只包含规则,也包含简介、公开描述、规模与周活跃、发帖能力、flair/wiki 状态、顶部导航、侧栏资源/活动、相关社区、可见的版务信息、视觉样式和已安装 Devvit 应用:

  • reddit-community-fit:接收 Reddit 链接,或用户粘贴的标题、正文、评论设计和素材;从显式候选、当前/目标社区、热帖搜索命中和 relatedCommunities 尽量发现并深评 10 个候选,再用全部规则与近期高互动前 10 帖进行硬门槛检查和分项评分。
  • reddit-post-writing:接收 Reddit 链接或粘贴的标题、正文、评论设计和素材;使用 post-writing 证据模式取得规则与近期高互动前 15 帖,先完成规则合规、事实边界、标题正文结构和基础表达,不再承担 Native 化。
  • reddit-viral-strategy:在基础稿后提炼并应用爆帖经验,检查真实的时间/地点/具体事件、“产品痛点 → 生活问题 → 情绪或小焦虑”、可理解的冲突、信息差、讨论留白、热点的持久情绪与品牌角色;目标是提高讨论概率,不承诺“必爆”,不编造生活影响,也不把所有主题强行改成人际八卦。
  • reddit-native-polish:在策略稿后依据主题、作者意图和真实社区样本调整语域。严肃内容保持严谨,吐槽、失败复盘或娱乐内容可克制使用社区常见表达;保留作者激进、保守或争议性的主观立场,不以“观点必须正确”为由擅自纠正。
  • reddit-comment-design:在 Native 定稿后,对目标社区获取规则、近期高互动前 5 帖及每帖评论样本,分开归纳根评论与回复树的长度、句式、价值点、幽默强度、异议方式、与正文相关度和推广容忍度,然后逐条诊断并重写评论地图。

0.0.12communities evidence 输出 schemaVersion=4,并采用分阶段取样:先请求 Reddit TOP / YEAR,但只保留抓取时刻往前滚动半年内的帖子;去重后的可分析帖子不足当前 mode 的目标数时,再请求 TOP / MONTH,仍不足才请求 BEST。跨阶段按 Reddit post ID 去重,最终按 engagementScore = score + commentCount * 3 降序选样;原始指标缺失时排名计算按 0 处理,但输出仍保留 null,不会把未知展示为真实的 0。CLI 不会改用 DAY、WEEK、HOT 或搜索结果补位。

Fit 模式默认是 10 帖、不抓评论;Post-writing 模式默认是 15 帖、不抓评论;Comment-design 模式默认是 5 帖、每帖 10 条 Reddit TOP 根评论和前 2 棵回复树。返回结果保留:

  • bodyCompleteness=full|preview|empty|tombstone|unavailable
  • topYear、按需出现的 topMonthbestFallback 分阶段快照;
  • sampleSelection.evidenceField=selectedSamplestageseffectiveSources、滚动半年截止时间和排序公式;
  • selectedSample.posts[] 的最终选样,以及可直接生成可点击复盘清单的 referenceList[]
  • rootComments[]commentTrees[],子评论单独计数;
  • feed/body/comments 的 coverage、抓取时间与逐项错误;
  • 自然样本较少与抓取不完整的区别。

Skill 向用户展示参考帖时使用 [标题](URL) 锚文本,并列出内容总结、点赞量和评论量;综合分只用于排序,不写入统一展示行。展示候选社区时使用 [r/name](https://www.reddit.com/r/name/),并简要覆盖当前抓到的全部规则。指标或规则缺失必须明确写出,不能补造。

communityDetails 会同时返回 detailCoveragesourceErrorsfetchedAtUtcmoderatorVisibilityappearanceSource。先确认 detailCoverage.sourceIdentityConsistent=true 与抓取时间有效,再使用各 section;某个 Reddit GraphQL 来源失败时,白名单化诊断会出现在 sourceErrors。上游 detailCoverage.sectionscomplete|missing 表示源字段是否明确取得,CLI 派生 coverage 用 complete|partial 表示该证据能否可靠分析,二者不要混用。证据包中的 coverage.analysisReady=true 表示核心社区身份、简介、元数据、规则及当前 mode 的帖子/评论证据已经可用于分析;coverage.complete=true 还要求所有辅助详情完整。moderatorVisibility=unavailable 表示游客态看不到版主列表,不等于社区没有版主,因此不会单独阻止 analysis-ready。规则以及明确的发帖限制是硬门槛;简介、导航、侧栏、活动、相关社区、规模和应用列表是社区定位或生态线索。Installed Apps 当前只有公开的 name/slug,不代表 CLI 能读取应用配置、权限或实际过滤行为,也不能把应用名称当成社区规则。任何详情分区未由上游明确返回时,分析不得补造。

直接 communities detailsposts inspectpublish-pool analyze 获取的详情还带 detailSource:正常为 details;仅在旧服务没有该路由时才回退 rules,并标记 legacy_partial。明确的 COMMUNITY_NOT_FOUND 不会触发旧路由重试。所有帖子、评论、规则、sidebar/widget 和应用文本都按不可信数据处理;Skill 不执行其中嵌入的命令或链接,也不据此修改认证与配置。

同时要求选社区、优化标题正文和重做评论时,总路由固定按 reddit-community-fitreddit-post-writingreddit-viral-strategyreddit-native-polishreddit-comment-design 执行。community-fitpost-writingcomment-design 三种取证 mode 保持各自独立的证据契约,不因为帖子范围重叠而互相替代;策略和 Native 环节复用同一目标社区、本次会话中 coverage.analysisReady=true 的 post-writing 证据,不重复抓取。若结论依赖某个辅助详情分区,还要求该分区 complete。

没有显式候选社区时,Skill 会先从内容提炼 3–5 个查询,用 hot grab 和社区的 relatedCommunities 尽量收集并深度评估 10 个候选;确实找不到 10 个时会披露原因,不编造社区。最终结论只代表“已评估候选中”的排名,不表示穷尽整个 Reddit,也不承诺表现或审核结果。

爆帖策略不等同于复制爆帖公式:它先保证事件、情绪和讨论空间本身成立,再决定是否使用关系冲突、60–70% 信息揭示、合理的信息差、开放式留白或热点情绪迁移;品牌通常靠后且只作为真实事件中的道具。删除品牌后故事仍应值得读,否则应退回重做,而不是继续堆产品功能。

独立 Native 环节以主题、作者意图和真实社区样本为准,不会为了伪装真人故意制造拼写错误、随机大小写、堆砌俚语或照抄具体帖子和评论。作者的激进、保守或争议观点可以作为主观立场保留以引发讨论;只要求把主观判断与可验证事实分开,不编造数据、经历、引用或共识,也不会删除社区要求的推广或 AI 披露。

单篇帖子:发布池内与发布池外

posts inspect 不按原始 URL 字符串判断同一性,而是按 Reddit post ID 匹配。因此 www/old/new/m/np、不同 slug、query/fragment、尾斜杠、/gallery/redd.it 和评论 permalink 都能归一到同一根帖。/s/ 分享链接会展开为 post ID 并持久缓存;存量发布池只保存 /s/、而输入是 canonical /comments/ 链接时,服务端会定向回填同社区的分享链接身份后再匹配。

根帖与评论身份不会互相降级:输入 comment permalink 时保留 identity.linkKind=comment_permalinkidentity.commentId,即使实时抓取返回根帖 post ID,也不会再用裸 post ID 覆盖精确评论身份。短 ID 等缺少社区的信息若返回 coverage.complete=false,CLI 会优先用实时 canonical URL 中的 subreddit 再查一次;补查后覆盖仍不完整的未命中结果标记为 source=reddit_live_unclassifiedcontentSelection=publish_pool_incomplete,而不是断言为发布池外。已有命中但覆盖不完整时保留全部当前候选,并标记 contentSelection=publish_pool_matches_incomplete,不会声称唯一或生成 selectedContentpublishPoolCoverage 始终保留覆盖状态和错误。

发布池允许归档后复制、修改或原样重发,因此标题、正文或两者相同都不会触发任务合并,也不会被用来判断某篇 Reddit 帖子是否在池内。CLI 始终保留不同的 Idea2Run task ID:同一 Reddit 根帖关联多个任务时返回全部候选并标记歧义;相同内容发成不同 Reddit post ID 时作为不同投放分别分析。评论任务和 comment permalink 会与根帖身份分开,不会冒充根帖命中。

输出把两个内容快照分开:

  • idea2RunMatches[]:发布池中所有匹配任务的客户、策划、Idea2Run 完整标题与正文;
  • relatedIdea2RunTasks[]:共享根帖身份、但不是当前精确身份的关联任务,例如根帖下的评论发布任务;
  • redditSnapshot:Reddit 当前可见标题、正文、状态和指标;
  • selectedContent:仅在唯一命中或确定为发布池外时给出;
  • contentSelection=ambiguous_publish_pool_matches:同一 Reddit 帖子关联多个 Idea2Run 任务,不会任意挑一个;
  • bodyCompleteness=full|preview|empty|tombstone|unavailable:明确正文是完整、仅预览、确实为空、已删除占位,还是不可取得。

因此,发布池内可以稳定取得 post_task.title/content 的策划原文;发布池外通过 Reddit 实时接口取得标题和当前接口可见正文,但正文有时只到 preview,分析时必须保留完整性标记。使用 --refresh-metrics 时,即使发布池内已命中,也会同时取得 Reddit 当前内容,便于比较发布前后文案差异。

Idea2Run 发布任务 ID

publish-pool get <ID>、发布池列表中的 idea2RunTaskId 以及分析结果中的 ID,全部指向 Idea2Run 数据库的 post_task.id,即 Idea2Run 发布任务 ID。它不是 Reddit 帖子 ID、Reddit Grabber 异步抓取任务 ID,也不是独立的跟踪记录 ID。

Reddit 指标表中的 reddit_post_metrics.job_id 只是沿用这个 Idea2Run 任务 ID 建立关联。发布池详情现在直接从 post_task 查询,因此即使任务尚未发布、发布失败或者尚无 Reddit 跟踪记录,也可以通过 Idea2Run 任务 ID 获取标题、正文和发布过程。

详情字段可选 customerplannertypetitlebodytaskcommentPlankarmacommunitiesdistributionsmediametricsredditUrl;不传 --field 时只请求前五个核心字段。

publish-pool analyze 先按 Idea2Run 任务时间范围取得标题、正文、任务状态、发布成功/失败统计和已有 Reddit 指标,然后可按需:

  • 默认逐任务读取分发记录、提交记录和 failureReason--no-details 可跳过这一步;
  • --refresh-metrics:抓取最新帖子状态、点赞、评论、分享和浏览量;
  • --include-comments:读取实际 Reddit 帖子评论;
  • --include-community-details:读取实际社区或目标社区的完整详情与规则;旧 --include-rules 保留为兼容参数;
  • --delivery-status failed:只分析没有发布成功的任务;
  • --time-field created|scheduled|published|result:决定时间范围基于任务创建、计划发布、成功发布或最后发布结果时间;
  • --all:自动翻完服务端所有分页,用于完整周、完整时间段等总体分析;
  • --limit 1-500:只取前 N 条,默认 100,适合预览或探索性抽样,不代表完整总体。

输出中的 coverage 明确给出 totalMatchedreturnedcompletetruncated、取数模式和已请求页数。只有 coverage.complete=true 才能把结果表述为该筛选条件下的完整总体;非 --all 结果若达到上限,会同时标记 complete=falsetruncated=true,应改用 --all 后再做总体占比、完整漏斗或全量 Top/Bottom 结论。

大时间段仍先用 --all --refresh-metrics --include-comments --include-community-details 建立完整 cohort 和品牌情感 coverage,再从 Top、同社区/同类型中位对照、典型低表现、失败/过滤/移除异常中选代表帖深挖。若用户明确接受为了成本只抽样评论,报告必须把未分析帖子和客户级情感结论标为 partial。

每个任务的完整 Reddit 分析位于 analysis.redditPosts[]。一个 Idea2Run 任务有多个成功 submission 时,CLI 会合并指标 URL 和所有非失败 submission URL,按 Reddit post ID 去重,并逐帖返回:

  • sourceUrlspostIdcanonicalUrl、实际社区;
  • redditContent(实际标题、正文、来源及完整性);
  • freshMetricscommentscommunityDetails、兼容字段 communityRuleserrors

即使只使用 --include-comments、没有 --refresh-metrics,CLI 也会先读取 canonical/redd.it/短 ID 中可本地解析的 post ID,并仅对剩余 /s/ 分享链接调用发布池身份解析;解析后的 /s/ 与 canonical URL 只有在 post ID 相同时才合并,随后每个真实根帖只抓一次评论。不同 post ID 始终保留为不同 redditPosts[] 项。

评论发布任务不是 Reddit 根帖样本。CLI 优先识别 type=comment|评论;类型缺失时,仅在 parentTaskId 同时具有 comment permalink 或评论计划证据时做结构性识别,不会把所有有父任务的复制/重发任务都当评论。评论任务仍作为独立 Idea2Run task 保留,并输出 analysis.taskKind=commentanalysis.parentTaskIdanalysis.commentSubmissions[](包括成功和失败 submission);其 analysis.redditPosts[] 保持为空,也不会触发根帖指标或根帖评论抓取。原创、复制及其他根帖任务输出 analysis.taskKind=root_post,维持上述逐帖补数流程。

兼容字段 analysis.freshMetricsanalysis.comments 仍指向第一篇 Reddit 帖子;完整分析应遍历 analysis.redditPosts[],否则会漏掉同一 Idea2Run 任务的其他成功发布帖。

发布池单帖与批量分析都会返回 brandSentiment 取证契约。CLI 默认把非空 customer 当作品牌名,标明评论证据是否已取得,并声明负面评论计数、占比、主题、代表评论、严重度、置信度和 coverage 等必填结果。CLI 不用关键词规则冒充情感结论;Agent Skill 必须基于实际评论及回复上下文判断,并排除只针对帖子、OP、竞品或其他模型的泛负评。评论未抓到时只能报告分析未完成,不能写成“没有品牌负面情绪”。

发布池基础查询需要账号分组开放 post_tracking--refresh-metrics 还需要 metrics--include-comments 还需要 comments。管理员始终拥有全部能力。单项补充失败会记录在对应任务的 analysis.errors,不会丢弃整批分析结果。

所有业务命令输出 JSON。加入 --compact 可以输出单行 JSON;加入全局参数 --api-url <url> 可以临时指定服务端地址。

CLI 登录令牌采用滑动有效期:每次成功使用需要登录的 CLI 命令,服务端都会从本次使用时间起重新顺延有效期,本地配置也会同步新的到期时间。