supsub-sub について
supsub-subは、SupSub CLIを通じて購読元を管理し、記事を閲覧するスキルです。公式アカウント、ウェブサイト、Xアカウントを区別し、購読や解除、記事一覧、購読元全体の既読化に対応します。
主な機能
- 01購読元の一覧表示、追加、削除
- 02公式アカウント、サイト、Xでの絞り込み
- 03未読または全記事をページ単位で閲覧
- 04購読元の記事をすべて既読にする
- 05後続処理向けのJSON出力
活用シーン
- 01購読中の情報源を確認、絞り込み
- 02検索で見つけたアカウントやサイトを購読
- 03購読元の最近の記事を閲覧
- 04記事を既読にして購読を管理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ supsub-ai/ supsub-cli --skill supsub-subインストール後、Claude Code で/supsub-subを入力して読み込まれたか確認します。
詳細
supsub-sub スキル
購読元の一覧表示、追加、削除と、各購読元内の記事の閲覧を行います。購読元の種類は MP(WeChat公式アカウント)、WEBSITE(Webサイト)、X(Twitter / Twitterプラットフォームのアカウント)です。
⚠️ 「X」の意味の曖昧さについて(必ず先にお読みください)
このドキュメントでは、X にまったく異なる2つの意味があります。混同しないでください。
--type X—— これは実際の sourceType 列挙値で、Twitter / X プラットフォームのアカウントを指します。- プレースホルダー X —— ユーザーが口語で「Xを購読する」「Xの購読を解除する」「X公式アカウントの最近の記事」と言う場合、ここでの X は通常、特定のアカウントを指す仮の名前です(公式アカウント、Webサイト、名前に X が含まれるものなど)。Twitterとは関係ありません。
判定ルール:
- ユーザーが**「Twitter / X プラットフォーム」について明確に言及した場合に限り**、
--type Xを使用します。 - ユーザーが「Xを購読する」「X公式アカウント」「Xの記事を見る」と言っていても、Twitterプラットフォームに言及していない場合は、それを根拠に
--type Xと推測しないでください。ここでの X はプレースホルダーです。実際の種類(多くはMPまたはWEBSITE)に従って処理してください。
前提条件
- インストール:
curl -fsSL https://raw.githubusercontent.com/SupSub-AI/supsub-cli/master/scripts/install.sh | bash(ネイティブインストール。~/.localにインストールされ、バックグラウンドでの自動更新に対応)、またはパッケージマネージャーでnpm i -g @supsub/cli/pnpm add -g @supsub/cli - ログイン済みであること:
supsub auth statusで Authenticated と表示されます(初回利用時は、先にsupsub auth loginを実行してください) - 未認証(exit 2 / UNAUTHORIZED)の場合、「ログインしていません」と伝えて終わらせないでください:ユーザーのブラウザーで認証を開始するため、
supsub auth loginを直接実行します(コマンドはブラウザーを自動で開き、認証完了まで待機します。十分に長いタイムアウトを設定してください。たとえば10分。ユーザーはブラウザーで確認をクリックするだけで、ターミナルへの入力は不要です)。認証に成功したら、元のコマンドを再試行します。ブラウザーが使えない環境やヘッドレス環境では、代わりにSUPSUB_NO_BROWSER=1 supsub auth loginをユーザーに案内してください。
コマンド
購読一覧
supsub sub list [--type <MP|WEBSITE|X>]
| フラグ | デフォルト | 説明 |
|---|---|---|
--type | —(すべて) | 購読元の種類で絞り込み:MP(公式アカウント)/ WEBSITE(Webサイト)/ X(Twitter) |
各行には sourceId、sourceType、name、img、description、unreadCount が含まれます。テーブル表示では、種類 列に sourceType が日本語で表示されます:MP→公式アカウント、WEBSITE→Webサイト、X→Twitter。
# 列出全部订阅
supsub sub list
# 仅看公众号
supsub sub list --type MP
# 仅看网站
supsub sub list --type WEBSITE
# 仅看推特(X 平台账号)
supsub sub list --type X
# 导出 JSON
supsub sub list -o json
JSON 形式:{"success":true,"data":[{"sourceType":"MP","sourceId":12345,"name":"...","img":"...","description":"...","unreadCount":3}, ...]}
購読を追加する
sub add には相互排他的な2つの方法があり、「取得した ID の形式」に応じて使い分けます:
# A) 全局搜索 / 已收录源 → 用内部正整数 sourceId
supsub sub add --source-id <id> --type <MP|WEBSITE|X> [--group <gid>]...
# B) mp search 发现的微信原生公众号 → 用 base64 字符串 mpId
supsub sub add --mp-id <mpId> [--type MP] [--group <gid>]...
| フラグ | 必須 | 説明 |
|---|---|---|
--source-id | いずれか一方 | 情報源 ID(正の整数)。supsub search / supsub sub list の sourceId から取得します |
--mp-id | いずれか一方 | 公式アカウントの mpId(base64 文字列)。supsub mp search の検索結果から取得します |
--type | 説明を参照 | --source-id モードでは必須で、MP / WEBSITE / X(Twitter)のいずれかを指定します。--mp-id モードでは省略できます。指定する場合は MP でなければなりません |
--group | いいえ | グループ ID(数字。複数回指定できます) |
相互排他:
--source-idと--mp-idは、必ずどちらか一方だけを指定してください。両方を指定するか、どちらも指定しないとINVALID_ARGSが発生します。2つの方法では別々の endpoint を使用します:
--source-id→POST /api/subscriptions(登録済みの購読元を購読)、--mp-id→POST /api/mps(WeChat ネイティブ ID で新しい公式アカウントを登録して購読)。
# 路径 A:sub list / search 看到的内部 sourceId(公众号)
supsub sub add --source-id 12345 --type MP
# 路径 A:网站 + 多分组
supsub sub add --source-id 67890 --type WEBSITE --group 1 --group 2
# 路径 A:推特账号(用户明确说要订阅某个 Twitter / X 平台账号时)
supsub sub add --source-id 24680 --type X
# 路径 B:mp search 拿到的 mpId(base64)
supsub sub add --mp-id "MzkyNTYzODk0NQ=="
# 路径 B + 分组
supsub sub add --mp-id "MzkyNTYzODk0NQ==" --group 3
# JSON 输出
supsub sub add --source-id 12345 --type MP -o json
JSON 形式:{"success":true,"data":{"message":"..."}}
--source-idは正の整数でなければなりません(数字でない場合はINVALID_ARGS)。--mp-idは文字列で、形式の検証は行われず、バックエンドが判断します。--groupには複数の数値 ID を指定できます。数字以外を指定するとINVALID_ARGS(exit 64)が発生します。
購読を解除する
supsub sub remove --source-id <id> --type <MP|WEBSITE|X>
| フラグ | 必須 | 説明 |
|---|---|---|
--source-id | はい | 情報源 ID(正の整数) |
--type | はい | MP(公式アカウント)/ WEBSITE(Webサイト)/ X(Twitter) |
⚠️ 購読解除は破壊的な操作です。実行前に必ずユーザーへ再確認してください:
sub listから取得した購読元の名前を伝え、明確な同意を得てから実行します。 mark-read と同様に、CLI は再確認しません——ユーザー自身がターミナルで実行するようコマンドを渡す場合、「実行後に確認が表示されます」と案内しないでください。⚠️ 購読を解除すると、その購読元は所属しているすべてのグループからも削除されます(実測:購読してグループに追加した後に購読を解除すると、
group subsは空になります)。 グループ自体には影響しません。再購読しても、元のグループへの所属は自動的には復元されません。もう一度group add-subを実行する必要があります。 そのため、ユーザーが「いったん購読を解除して、あとで再登録する」と言った場合は、グループへの所属が失われることを伝えてください。
# 取消订阅某个公众号(需用户确认后执行)
supsub sub remove --source-id 12345 --type MP
# 取消订阅某个网站
supsub sub remove --source-id 67890 --type WEBSITE -o json
# 取消订阅某个推特账号
supsub sub remove --source-id 24680 --type X
JSON 形式:{"success":true,"data":{"message":"..."}}
サブスクリプションの記事を閲覧する
supsub sub contents --source-id <id> --type <MP|WEBSITE|X> [--unread | --all] [--brief] [--page <n>] [--page-size <n>]
| フラグ | デフォルト | 説明 |
|---|---|---|
--source-id | 必須 | 情報源 ID(正の整数)。別名 --id(focus contents --id と統一されており、どちらの書き方も同じです) |
--type | 必須 | MP(公式アカウント)/ WEBSITE(ウェブサイト)/ X(Twitter) |
--unread | (デフォルト) | 未読記事のみを返します |
--all | — | すべての記事(既読 + 未読)を返します |
--brief | — | 簡潔な出力:contentId / title / publishedAt(+Text) / isRead のみを残します |
--page | 1 | ページ番号(正の整数) |
--page-size | 20 | 1 ページあたりの件数。1-100 |
⚠️
--unreadと--allは同時に指定できません。両方を指定するとINVALID_ARGSがスローされます。どちらも指定しない場合、デフォルトの動作は--unreadと同じです。
⚠️ 「最近」と「未読」は同じではありません。ユーザーの意図に応じてフラグを選び、デフォルト値に判断を委ねないでください。
| ユーザーの表現 | 意図 | 使用するもの |
|---|---|---|
| 「最近の X の内容を見せて」「X は最近どう?」「X は何について話してる?」「X は更新された?」 | 時系列でこの情報源の内容を見る | --all。isRead はラベル付けにのみ使用します(「そのうち 3 件はまだ読んでいません」)。フィルタリングには使わないでください |
| 「X にまだ読んでいないものはある?」「X の未読」「X はあと何件未読?」 | 明確に未読を求めています | デフォルト(--unread) |
| 意図がはっきりしない | —— | --all + 未読にラベルを付けます |
「最近の X の内容を見せて」という依頼にデフォルト値で対応すると、次の問題が起こります。その情報源をすでにすべて読んでいる場合、空の配列が返るため、「内容はありません」と回答してしまいます。 しかし、ユーザーが尋ねているのは「最近」の内容であり、「未読」の内容ではありません。フィルタリングするのは、ユーザーの発言に「未読 / まだ見ていない / 読んでいない / 未読を消す」が含まれる場合だけです。
一括列挙では必ず --brief を付けてください。デフォルト出力では各項目に summary / coverImage / tags が含まれ、100 件で約 90KB になるため、ツールの出力上限を超えてファイルへの保存が必要になることがあります。--brief なら、100 件でも約 14KB です。ユーザーに内容を説明する必要がある場合にのみ、完全な出力を使用してください。
各行のフィールド:contentId, url, title, coverImage, tags[], summary, publishedAt, publishedAtText, isRead。
--brief の場合は contentId, title, publishedAt, publishedAtText, isRead のみです。
publishedAtは Unix の秒単位のタイムスタンプです(一部のバックエンドバージョンでは文字列です)。publishedAtTextは CLI で整形済みの"YYYY-MM-DD HH:mm"なので、そのまま使用してください。date -rやタイムスタンプ変換を自分で行わないでください。並べ替えには引き続きpublishedAtを使用します。
# 默认(未读)—— 看某个公众号里有哪些文章
supsub sub contents --source-id 12345 --type MP
# 全部文章(含已读)
supsub sub contents --source-id 12345 --type MP --all
# 看更早的文章:翻到第 2 页
supsub sub contents --source-id 12345 --type MP --page 2
# 一次多拿一些(上限 100)
supsub sub contents --source-id 12345 --type MP --page-size 100 -o json
# 全部文章 + JSON
supsub sub contents --source-id 12345 --type MP --all -o json
JSON 形式:{"success":true,"data":[{"contentId":"...","url":"...","title":"...","coverImage":"...","tags":[...],"summary":"...","publishedAt":<timestamp または文字列>,"isRead":false}, ...]}
publishedAtの元の形式はバックエンドのバージョンによって異なります(Unix 秒の数値 /"YYYY-MM-DD HH:mm:ss"形式の文字列)。 自分で形式の違いに対応する必要はありません。CLI が補完したpublishedAtTextをそのまま読み取ってください(常に"YYYY-MM-DD HH:mm"形式です)。ページネーション戦略:閲覧のリクエストでは 1 ページ目だけを取得し、合計件数を伝えます。「すべて / 統計 / エクスポート」のリクエストでは
--page-size 100を使ってページを自動的に繰り返し取得します(返される件数が page-size 未満なら最終ページです)。ユーザーにページごとに確認しないでください。詳しくはsupsub-unreadを参照してください。
情報源を既読にする(情報源全体を既読にする)
supsub sub mark-read --source-id <id> --type <MP|WEBSITE|X> --all
| フラグ | 必須 | 説明 |
|---|---|---|
--source-id | はい | 情報源 ID(正の整数) |
--type | はい | MP / WEBSITE / X(Twitter) |
--all | はい | 情報源全体を既読にすることを確認します(取り消せません) |
⚠️ 情報源全体を既読にする機能のみサポートしており、個別の記事を既読にする機能はありません。 記事には「詳細 / 閲覧」の手順がなく、個別の記事を既読にする自然なイベントが発生しないため、CLI にはユーザーが明示的に「このアカウントを読み終えた」と表明する操作のみが用意されています。
--content-idを渡すとINVALID_ARGSがスローされます。ユーザーが「この記事を既読にして」と言った場合は、非対応であることを正直に伝え、情報源全体を既読にするか確認してください。⚠️
--allは必須で、取り消せません(CLI に未読に戻す機能はありません)。実行前に必ずユーザーに再確認してください。情報源名と現在の未読件数(sub list/supsub unreadから取得)を伝え、明確な同意を得てから実行してください。CLI から再確認されることはありません。このコマンドには対話形式の確認プロンプトがなく、実行するとすぐに反映されます。コマンドをユーザー自身がターミナルで実行するよう案内する場合、 「実行後に CLI が確認を求めます」と言わないでください。そのような安全策はありません。
# 整源已读(需用户确认后执行)
supsub sub mark-read --source-id 12345 --type MP --all -o json
JSON 形式:{"success":true,"data":{"message":"このサブスクリプションのすべての内容を既読にしました(取り消せません)"}}
Agent Usage Notes
- 解析数据时统一用
-o json;表格输出有截断、列宽限制,不适合做下游处理。 - 所有 JSON 响应都是
{"success":true,"data":<payload>}结构(来自src/ui/output.ts)。 --type取值是MP/WEBSITE/X(CLI 内部会toUpperCase,大小写不敏感);常见错误是写成mp_account/wechat/rss/TWITTER会报INVALID_ARGS——推特只接受X,不接受TWITTER。- 再次强调字母「X」的歧义:
--type X= 推特平台账号。用户口语里「订阅 X」「X 公众号」「看 X 的文章」中的 X 多半是占位符代指某个具体账号,不要因为出现字母 X 就传--type X;只有用户明确提到「推特 / Twitter / X 平台」时才用--type X。 - 添加订阅前先想清楚 ID 来源:
- 来自
supsub search/sub list的 内部正整数sourceId→sub add --source-id <id> --type ... - 来自
supsub mp search的 base64 字符串mpId→sub add --mp-id <mpId>(type 默认 MP,可省) - 不要把
mp search的mpId强转成数字塞进--source-id—— 那是不同 ID 空间,会被后端拒。
- 来自
sub contents默认只看未读 —— 「看一下最近 X 的内容」「这个号有哪些文章」「X 讲了什么」这类按时间浏览的请求一律加--all,把isRead当标注而不是过滤条件;只有用户明说「未读 / 没看的」才用默认。sub contents默认每页 20 条,用--page/--page-size(上限 100)翻页取更早的历史。- 标记已读只有整源一档(
mark-read --all):没有单篇已读,因为文章没有「详情 / 阅读」这一步。整源已读不可逆,执行前必须向用户二次确认。跨源的未读概览与清未读工作流见supsub-unread。 - 分组管理(把这个源加进某个分组、分组里有哪些订阅)见
supsub-group;订阅时可直接用sub add --group <gid>一步入组。 - 重复订阅不是错误:实测对同一个源再跑一次
sub add返回{"success":true,"data":{"message":"订阅成功"}},exit0(幂等)。不要据此判断"是否已订阅"——要判断请看sub list或搜索结果里的isSubscribed。重复退订才会报错(订阅不存在,400 → exit1),两者不对称。 - Exit codes:
0OK,2UNAUTHORIZED,64INVALID_ARGS(--type/--source-id/--group/--page/--page-size校验失败、--all与--unread互斥、mark-read 未给--all或误传--content-id),1业务错误(后端 4xx,如源不存在 / 未订阅 / 重复退订),10网络错误,11服务端错误(5xx)。