watcha-cli
v0.2.0
Published
观猹 (watcha.cn) 命令行客户端:搜产品、读猹评、AI 搜索、Markdown 发布、产品方自助;人和 AI agent 共用,非 TTY 默认 JSON,随包附带 Agent Skill
Maintainers
Readme
watcha-cli
观猹(watcha.cn)的命令行客户端:在终端里搜产品、读猹评、用 AI 搜索问口碑、用 Markdown 发帖发猹评,也给自己的 AI 产品拉口碑统计、生成徽章。同一个命令同时服务人和 AI 编程 agent——非 TTY 下自动切换为结构化 JSON 输出,并随包附带 Agent Skill。
The command-line client for Watcha, a Chinese community for reviewing AI products. Built for humans and AI coding agents alike: structured JSON by default when piped, ships with an Agent Skill, zero telemetry.
状态:v0.1 预览。读侧、AI 搜索、发布链路都已对接生产接口。macOS / Linux 已验证,Windows 未经测试。
目录
为什么有这个工具
观猹是一个 AI 产品评价社区:产品库叫「图鉴」,带推荐 / 不推荐表态的评价叫「猹评」(只有通过晋级考试的「观猹员」能写),讨论区叫「猹馆」。它的重度用户本身就是终端和 AI agent 的重度用户——站内评论量靠前的产品里,OpenClaw、QClaw、Claude Code 这类终端 / agent 工具占了不少。
watcha 把这个社区搬进终端,解决三件事:
- 人在终端里逛观猹:不用开浏览器就能搜产品、比口碑、读猹评、看榜单和活动;写好的 Markdown 直接发出去,图片自动上传。
- AI agent 能正经地「逛观猹」:观猹主站是单页应用,agent 用浏览器抓不到内容。现在 Claude Code、Codex、OpenClaw 这类 agent 可以用
watcha search/watcha ask拿到社区真实评价来辅助选型,输出是稳定的 JSON 信封,watcha schema --json一次读完全部命令契约。 - AI 产品的开发者自助运营:查自己产品的推荐比和按周趋势、生成可贴进 GitHub README 的评分徽章、发布更新日志——以前这些要么点开六层页面,要么找运营。
它不做的事也很明确:没有任何批量或自动发布能力,每一条发布都需要人确认。详见用 Markdown 发布。
安装
需要 Node.js ≥ 22(内置 fetch / FormData,不依赖 axios 之类)。
# 全局安装
npm i -g watcha-cli
# 或临时运行
npx watcha-cli --help大陆网络下可先 npm config set registry https://registry.npmmirror.com。
可选原生依赖 @napi-rs/keyring 用来把凭证放进系统钥匙串;装不上会自动退化到 0600 权限的文件,不影响使用。
整个包是一个打包好的单文件(约 250 kB),除了可选的钥匙串模块没有其他运行时依赖。
60 秒上手
watcha search "Claude Code" # 混排搜索:产品 / 猹评 / 帖子 / 用户
watcha product show claude-code # 产品详情(id 或 slug 都行)
watcha product reviews claude-code # 猹评,带 👍 / 👎 表态
watcha rank week_product_hot_reviewed --top 10
watcha auth login # 微信扫码;没有微信见「登录与凭证」(以下命令需要登录)
watcha ask "做 PPT 的 AI 哪个口碑好" # 观猹的 AI 搜索,终端里流式输出(每分钟 2 次)
watcha like review 27222 # 点赞(终端里直接生效;脚本 / agent 调用需加 --yes)
printf '# 我的第一帖\n\n正文写在这里。\n' > post.md
watcha draft preview --md post.md # 本地看 Markdown 会被转成什么,零请求
watcha post create --md post.md --yes # 发帖(发猹评还需要观猹员资格,见下文)在终端里(TTY)默认输出给人看的摘要;管道或重定向时自动变成 JSON:
$ watcha product show claude-code | jq '.data.stats' # 节选,数值随时间变化
{
"upvotes": 96,
"stars": 48,
"review_count": 100,
"reply_count": 7,
"score": 9.016278276739262,
"hot_score": 0.000002044532434735449,
"score_revealed": true,
"post_count": 76,
"update_at": "2026-08-21T17:26:52.019Z"
}任何时候都可以用 --format json|pretty|ndjson|table 或 --json 指定格式。
命令总览
| 域 | 命令 | 需登录 |
|---|---|:---:|
| 搜索 | search <q> [--domain product\|review\|posting\|user] [--category] [--score-gte/--score-lte] [--organization] [--order-by] [--hybrid] | 否 |
| 产品图鉴 | product list · show · reviews · posts · similar · hot · launches · categories · collections · collection · random | 否 |
| 猹评 | review show · replies [--all] · hot · similar | 否 |
| 猹馆帖子 | post list [--topic] · show · floors · subfloors · hot | 否 |
| 话题 | topic list · hot · show · posts [--featured] | 否 |
| 榜单 | rank [key] [--top N] [--archives](不传 key 列出全部) | 否 |
| 活动(逛) | activity list:不带 --q 吃 [--city] [--location-type] [--date] [--period] [--sort],带 --q 走搜索只吃 [--location-type] [--date] [--time-scope] [--hybrid](两边参数不通用,混用直接报错) · show · cities · calendar · upcoming · hosted | 否 |
| 活动(我的) | activity mine [--role registered\|managed\|checkin] [--period] [--status] · form <活动> | 是 |
| 活动(报名) | activity register <活动> [--ticket] [--field k=v] [--answer 题号=答案] [--form file.json] · unregister(非交互环境需 --yes) | 是 |
| 活动(主办) | activity manage show\|create\|edit\|cancel\|guests\|review\|invite\|export\|stats\|form\|form-set\|ticket\|collaborators\|host\|staff | 是 |
| 活动(签到) | activity check-in <活动> <票码或报名ID> [--resolve] [--undo] [--full] | 是 |
| 用户 | user show · search · reviews · posts · me | me 需要 |
| 信息流 | feed | 否(登录后个性化) |
| AI 搜索 | ask <question> [--resume id] [--share] [--raw] [--watch\|--no-watch] · ask-sessions list\|show\|delete\|shared · watch [file](实时视图窗口里跑的渲染器) | 是 |
| 互动 | like <review\|post> <id> [--down] [--undo] · favorite · star · follow · react <scope> <id> <emoji> · vote · subscribe(非交互环境需 --yes) | 是 |
| 发布 | draft preview · post create · review create(需观猹员) · reply <review\|post> <id> · feedback [text] [--type bug\|feature\|content\|other] | 是 |
| 产品方 | product mine · badge · stats · launch · update | 是 |
| 通知 / 任务 | notify list\|status\|read · quest list\|mine | 是 |
| 登录态 | auth login\|status\|logout\|token · profile list\|use\|add\|remove | — |
| 给 agent 的 | schema · skills list\|read\|install · api <METHOD> <path> · config | — |
列表类命令统一支持 --limit 1-100、--skip N、--page N;JSON 输出里 meta.has_more 为 true 表示还有下一页。
每条命令的参数以 watcha <命令> --help 为准。
登录与凭证
读操作不需要登录。AI 搜索、互动、发布、产品方命令需要。
| 方式 | 命令 | 适用 |
|---|---|---|
| 微信小程序码(默认) | watcha auth login | 终端内显示二维码(iTerm2 / WezTerm / kitty / Ghostty),其他终端自动用系统看图器打开;手机微信扫码,5 分钟有效 |
| 短信验证码 | watcha auth login --sms [--phone 138…] [--code 123456] | 交互式终端直接输码;非交互环境必须同时给 --phone 和 --code |
| 账号密码 | watcha auth login --password [--account …] | 仅交互式终端 |
| 导入浏览器登录态 | watcha auth login --refresh-token <jwt> | 在 watcha.cn 登录后,开发者工具 → Application → Local Storage → watcha.refreshToken |
| 环境变量 | WATCHA_REFRESH_TOKEN=<jwt> watcha … | CI、agent;优先级最高,不落盘 |
- 凭证默认存系统钥匙串(服务名
watcha-cli),没有钥匙串时写~/.config/watcha/credentials.json(0600)。WATCHA_CREDENTIALS_BACKEND=file可强制不碰钥匙串。 - access token 15 分钟有效,CLI 会提前 30 秒自动续期;refresh token 30 天。
- 观猹每个账号最多保留 5 个登录态(网页、App、小程序、CLI 共用,按最久未用踢出)。CLI 占用其中一个;不再使用时
watcha auth logout会释放槽位。如果某天突然提示未登录,多半是被别的设备挤掉了,重新登录即可。 - 多账号 / 联调环境用 profile:
watcha profile add test --base-url https://… --use,或每条命令加--profile test。
watcha auth status 会向后端核实一次,并告诉你当前账号能不能发猹评(是否观猹员)。
输出契约与退出码
这是对 agent 和脚本的承诺,只加不改:
// 成功 → stdout,退出码 0
{ "ok": true, "data": <命令数据>, "meta": { "skip": 0, "limit": 20, "count": 20, "has_more": true } }
// 失败 → stderr,退出码非 0
{ "ok": false, "error": { "type": "forbidden", "code": "FORBIDDEN", "status": 403,
"message": "无权限", "hint": "发猹评需要观猹员(L1)资格:…" } }- 判断成败只看退出码 /
ok,不要解析data(唯一例外:auth status以退出码 0 报告状态,是否登录看data.logged_in)。 - 拼错命令名、缺参数、裸跑分组命令(如
watcha product)同样返回这个信封,退出码 3。--format pretty|table是给人看的,错误也是人话文本。 - 分页只看
meta.has_more(多数端点不返回total,有才出现);has_more是满页即 true 的乐观估计,末页刚好满页时会多翻一次空页。 --dry-run下写命令不发请求,stdout 是{ "ok": true, "data": { "dry_run": true, "request": {...} } }。error.type是稳定的枚举,error.hint写明下一步该做什么;code/status是后端原样透传。- 进度提示、确认问句全部走 stderr,stdout 只有数据。
| 退出码 | 含义 | error.type |
|:---:|---|---|
| 0 | 成功 | — |
| 1 | 其他错误 | api server stream internal |
| 2 | 未登录 / 登录态失效 | auth |
| 3 | 参数或内容不合法 | validation |
| 4 | 写操作需要确认(加 --yes) | confirmation_required |
| 5 | 触发限流 | rate_limited |
| 6 | 后端要求滑块验证,需到网页完成 | captcha_required |
| 7 | 网络错误 | network |
| 8 | 无权限 / 被封禁 | forbidden |
| 9 | 对象不存在 | not_found |
--format ndjson 让列表一行一条,ask 在这个模式下逐帧输出 SSE 事件。
用 Markdown 发布
watcha draft preview --md post.md # 先看转换结果和本地校验
watcha post create --md post.md --topic 44,53 --product claude-code --image a.png --yes
watcha review create --product claude-code --vote good --md review.md --yes
watcha reply review 27222 --text "同感,尤其是…" --yes
watcha reply post 13431 --parent 5678 --md reply.md --yesMarkdown 支持范围(转换器只产出观猹网页编辑器支持的节点,不会出现「网页显示不了」的内容):
| 场景 | 保留 | 降级 |
|---|---|---|
| 帖子、产品更新日志 | 标题、段落、引用、有序/无序列表、代码块、分割线、加粗、斜体、行内代码、链接、图片 | HTML 原样丢弃(会在 warnings 里提示);标题里的图片拆成独立的图;~~删除线~~ 按普通文字处理(解析器只开了 CommonMark) |
| 猹评 | 同上;正文里的图片会挪到附图字段(猹评编辑器不支持内嵌图) | — |
| 回复 | 列表、链接 | 标题→段落,代码块→段落,图片→链接 |
- 帖子首行
# 标题自动作为标题,也可--title。标题上限 32、猹评正文下限 15,按观猹的宽度口径计:一个汉字算 1,一个半角字符算 0.5。draft preview会把宽度算给你看。 - Markdown 里的本地图片(相对
.md文件所在目录)和外链图片都会自动上传到观猹的对象存储;--image可以再附加图片(帖子 ≤18 张,回复 ≤9 张)。观猹不接受直接引用外链图片,所以必须经过这一步。 - 发布后 CLI 会回查一次状态:
0待审、1已公开、2被内容审核折叠(别人看不到),被折叠会明确报出来。 --ai-assisted在文末追加一行「本文由 AI 辅助创作,作者已审阅并对内容负责」。是否加由作者决定,默认不加。
护栏(有意为之,不会放宽):
- 每一条发布都必须
--yes,或在交互式终端里逐条确认;没带--yes的非交互调用返回退出码 4。 - 没有任何批量 / 循环发布命令。
- 本地记录发布时间,60 秒内第 3 条直接拦下——与观猹后端「每分钟 2 条」的限流一致,超限会触发运营侧的刷帖告警。
- 发猹评需要观猹员资格;CLI 会在发之前检查权限并给出去考试或用邀请码的提示,不会把猹评改成帖子「绕过去」。
- 点赞、收藏、关注、表情、投票、订阅、标记全部已读这类轻互动立即生效:人在终端里敲不追问,脚本或 agent(非交互)调用同样必须
--yes。 - 单次 Markdown 输入不超过 2 MB。
给 AI agent 用
watcha 从设计上就是给 Claude Code、Codex、OpenClaw 这类 agent 直接调用的:
watcha schema --json # 全部命令、参数、输出契约、退出码、环境变量,一次读完
watcha skills read # 内置 SKILL.md:概念、约束、典型任务
watcha skills install # 装到 ~/.claude/skills/watcha 与 ~/.agents/skills/watcha(--dir 指定别的目录)Claude Code 里建议在项目或全局 skill 中预授权:
allowed-tools: Bash(watcha *)agent 侧的约定都写在随包发布的 SKILL.md 里(watcha skills read 可看),核心三条:
- 遇到退出码 2(未登录)或 6(验证码),把
error.hint交给用户处理,不要替用户猜验证码、不要反复登录(会把用户别的设备挤下线)。 - 发布前先
draft preview,把标题和正文摘要给用户看,得到同意后才在原命令末尾加--yes。 - 只做用户要求的那一条;不要用
api逃生舱绕过发布护栏。
没有对应命令时可以用 watcha api GET /products --query limit=3 直接调 /api/v2 下的端点。
agent 调 ask 时,人也能实时看到
Claude Code、Codex 这类宿主只把命令输出给模型看,不给人实时看(Claude Code 只滚最后 5 行后折叠,Codex 只渲染 5 行;MCP 协议至今没有「部分结果」)。所以 watcha ask 做了双通道:
- 检测到被 agent 调用(
CLAUDECODE=1、CODEX_SANDBOX、CURSOR_AGENT、AGENT=…)且 stdout 不是终端时,自动把实时视图开到你正在用的终端的新窗口,逐字显示思考、工具调用和回答;agent 那边照常在结束后拿到 JSON,多两个字段stream_log(日志路径)和viewer.opened。 - 开窗按终端逐级回退:tmux 分屏 → WezTerm → kitty → iTerm2 → Ghostty → Terminal.app(macOS 兜底,Warp 等没有脚本接口的终端走这里)→ gnome-terminal(Linux)。全部失败时 stderr 会给出
watcha watch <日志>,自己另开终端执行即可。 --watch强制开、--no-watch关,WATCHA_WATCH=0全局关。watcha watch不带参数跟最新一份日志,日志在~/.config/watcha/streams/,只留最近 20 份。
Codex 沙箱默认断网,watcha 会识别 CODEX_SANDBOX_NETWORK_DISABLED=1 直接给出放开方式(codex -c 'sandbox_workspace_write.network_access=true'),而不是等超时。
产品方:管理自己的产品
watcha product mine # 我提交的 / 我是成员的产品
watcha product stats claude-code --weeks 12 # 评分、推荐比、按周趋势、最近猹评(客户端聚合,最多拉 1000 条)
watcha product badge claude-code --theme dark # 评分徽章,默认输出 Markdown;--as html | url
watcha product launch claude-code --title "v1.2 发布" --md changelog.md --yes
watcha product update claude-code --slogan "新的一句话" --yes徽章代码与观猹网页「产品管理 → 徽章」生成的一致,可以直接贴进 GitHub README。
配置与环境变量
配置目录默认 $XDG_CONFIG_HOME/watcha,没设 XDG_CONFIG_HOME 就是 ~/.config/watcha(Windows 上是用户目录下的 .config\watcha);config.json 放 profile,凭证另存。watcha config 会打印当前生效的配置。
| 变量 | 作用 |
|---|---|
| WATCHA_REFRESH_TOKEN / WATCHA_ACCESS_TOKEN | 直接用 token 认证,最高优先级,不落盘 |
| WATCHA_PROFILE | 选择 profile(等价 --profile) |
| WATCHA_BASE_URL | 覆盖 API 基址,默认 https://watcha.cn/api/v2 |
| WATCHA_FORMAT | 默认输出格式 |
| WATCHA_CONFIG_DIR | 配置目录;显式指定时系统钥匙串里的凭证也按目录隔离,不会拿到默认目录的登录态 |
| XDG_CONFIG_HOME | 默认配置目录的上级(标准 XDG 约定) |
| WATCHA_CREDENTIALS_BACKEND=file | 不使用系统钥匙串 |
| WATCHA_NO_INPUT=1 | 永不交互提问(等同 CI) |
| WATCHA_NO_UPDATE_CHECK=1 | 不做版本检查(CI、Codex 禁网、npx 安装本来就不查) |
| WATCHA_IMAGE_PROTOCOL=iterm2\|kitty\|none | 强制指定终端图片协议 |
| WATCHA_DEBUG=1 | 把每个请求的方法与 URL 打到 stderr |
| WATCHA_WATCH=1\|0 | ask 是否把实时视图开到新终端窗口;不设则在被 agent 调用且非 TTY 时自动开(CI 下不开,30 秒内只开一次) |
版本更新提示
装的版本落后于 npm 上的 latest 时,成功信封会多带一段:
{"ok":true,"data":{},"meta":{"update_available":{"current":"0.1.0","latest":"0.2.0","upgrade":"npm i -g [email protected]"}}}upgrade 是可以直接跑的命令。pretty 模式下另有一行提示打到 stderr,按 2 小时节流;
meta 里的字段不节流——agent 每次都是新进程,节流只会让它随机性地看不见。
版本缓存每 2 小时后台刷新一次,刷新由一个 detach 出去的子进程完成,不占用任何命令的时间;
断网、超时、registry 抽风都只是不更新缓存。请求只出不进,不带任何用户信息。
升级完记得重跑 watcha skills install,否则装在用户机器上的那份用法说明还是旧的。
全局选项:--format --json --profile --base-url --dry-run -y/--yes -q/--quiet --debug,可以放在任意子命令之后。--dry-run 下写操作只打印将发送的请求(Authorization 已脱敏),连图片都不会上传;未登录时会先报退出码 2,--dry-run 不能绕过登录。
常见问题
扫码时终端里看不到二维码。 只有支持图片协议的终端(iTerm2、WezTerm、kitty、Ghostty)能内联显示;其他终端会把二维码存成临时文件并用系统看图器打开,路径会打印在 stderr。二维码是微信小程序码,只能用微信扫。
提示「后端要求滑块验证」(退出码 6)。 短信 / 密码登录触发了风控,终端里没法完成滑块。到 watcha.cn 用浏览器登录一次,再用 --refresh-token 导入,或直接改用微信扫码。
刚登录过,过几天又说未登录。 每个账号最多 5 个登录态,CLI 的被网页或 App 挤掉了。重新 watcha auth login;如果经常发生,少开几个设备,或不用时 watcha auth logout。
review create 报无权限。 发猹评需要观猹员资格:在 https://watcha.cn/exam 通过晋级考试,或使用邀请码。回复和发帖不需要。
「图片来自非可信来源」。 直接把外链 URL 写进正文的图片节点会被后端拒绝。用 post create/review create 正常发布即可,CLI 会先把图片上传到观猹的存储再引用;如果你用 api 逃生舱手工发,就要自己走上传。
标题过长 / 猹评过短。 宽度口径是汉字 1、半角 0.5;watcha draft preview 会把实际宽度和问题清单算出来。
在 Claude Code / Codex 里让 agent 问问题,我怎么看不到流式? 看你正在用的终端有没有弹出新窗口——ask 在被 agent 调用时会自动把实时视图开到新窗口(Warp 用户会看到 Terminal.app 弹出来)。没弹的话看 agent 转述的 stderr 里那行 watcha watch <日志>,在任何终端执行它。宿主自己的聊天区做不到这件事,不是配置问题。
Codex 里报「沙箱已禁用网络访问」。 Codex 默认断网。临时:codex -c 'sandbox_workspace_write.network_access=true';长期:~/.codex/config.toml 加 [sandbox_workspace_write] network_access = true。
ask 说「流在收到 [DONE] 之前就断开了」。 网络中断导致 SSE 截断,CLI 不会把半截结果当成功。按提示 watcha ask --resume <sessionId> 续传。
安全与隐私
- 不采集任何使用数据,没有遥测。
- 凭证只存在系统钥匙串或 0600 文件里;
--dry-run和调试输出里Authorization一律脱敏。 - 不会读取你的其他应用数据;上传的图片仅限你在命令里指定或 Markdown 里引用的文件。
- 写操作全部需要显式确认,见护栏。
- 发布的包不含源码映射,也不在运行时下载任何代码。
反馈
遇到 Bug 或有建议,直接在终端里投到观猹站内反馈(和网页上的「反馈」弹窗是同一个入口,需要登录):
watcha feedback "描述问题:做了什么、期望什么、实际看到什么" --type bug --yes
watcha feedback --md idea.md --type feature --yes # 正文也可以是 Markdown 文件
watcha --version # 反馈时带上版本号--type 可选 bug / feature / content / other。装不上或登不上、没法用命令反馈时,写信到 [email protected]。
与观猹后端的关系
- 全部能力都来自观猹既有的公开 HTTP 接口(
https://watcha.cn/api/v2),没有为这个工具改过后端或网页。 - 观猹后端目前没有公开的 API 文档,字段以线上实测为准。
- 后端限流原样生效:发帖 / 发猹评每分钟 2 条,AI 搜索每分钟 2 次,图片预签名每 10 分钟 60 次。
- 观猹登录服务(OAuth2)目前只提供身份信息,不能用于调用业务接口,因此 CLI 复用的是用户自己的登录态,而不是独立的机器凭证。
许可证
专有使用许可(随包的 LICENSE):可以免费安装、运行,包括在你自己用的 AI 编程工具里调用;不允许再分发、修改、逆向或用于批量自动发布。内联的开源组件按各自许可证授权,原始声明见随包的 THIRD-PARTY-NOTICES.txt。
