Interest Discovery
はてなブックマーク(Hatena Bookmark)から、ユーザーの興味・関心に意味的に関連する価値あるコンテンツを発見する。 ユーザーの興味プロファイルをセッションをまたいで記憶・更新し、発見の精度を継続的に向上させる。
サブコマンドルーティング
$ARGUMENTS の先頭ワードでサブコマンドを判定する:
| 呼び出し例 | 動作 |
|---|---|
/interest-discovery | プロファイルに基づいてコンテンツ発見 |
/interest-discovery rust | rust をトピックとしてコンテンツ発見 |
/interest-discovery add Rust rust,cargo,所有権 | 興味を追加 |
/interest-discovery remove Rust | 興味を削除 |
/interest-discovery list | 興味プロファイルを表示 |
/interest-discovery view | 当日のレポートキャッシュを表示 |
$ARGUMENTS[0] が add / remove / list であればプロファイル管理、view であればキャッシュ表示、それ以外はコンテンツ発見として処理する。
Memory ファイル
いずれも ~/.claude/memories/interest-discovery/ に保存する(git 管理外)。
Read / Write / Glob ツールは ~ を展開して直接指定できる。
ディレクトリが存在しない場合は mkdir -p ~/.claude/memories/interest-discovery で作成する。
interests.json — 興味プロファイル
{
"interests": [
{
"topic": "Rust プログラミング",
"keywords": ["rust", "cargo", "所有権"],
"weight": 1.0,
"added_at": "2024-01-01T00:00:00Z",
"last_used": "2024-01-01T00:00:00Z"
}
],
"preferred_categories": ["it", "knowledge"],
"updated_at": "2024-01-01T00:00:00Z"
}
reports/YYYY-MM-DD.md — 日次レポートキャッシュ
~/.claude/memories/interest-discovery/reports/ ディレクトリに日付ごとの Markdown ファイルとして保存する。
ディレクトリが存在しない場合は mkdir -p ~/.claude/memories/interest-discovery/reports で作成する。
- ファイル名:
YYYY-MM-DD.md(ローカル日付) - 同日に複数回実行された場合は既存ファイルに追記する(後述の追記フォーマット参照)
- 保存時に 5日より古い
.mdファイルを削除する
history.json — 紹介済み記事の履歴
{
"history": [
{
"date": "2024-01-15",
"urls": ["https://example.com/article1", "https://example.com/article2"]
}
]
}
- 日付は
YYYY-MM-DD(ローカル日付) - 7日以上前のエントリは保存時に自動削除する
プロファイル管理サブコマンド
add <topic> [keywords]
$ARGUMENTS = add <topic> [comma-separated-keywords]
- プロファイルを読み込む(ファイルが存在しない場合は新規作成)
topicが既に存在する場合はキーワードをマージして更新、なければ新規追加keywordsが省略された場合はtopicからキーワードを自動生成する- ファイルに保存して結果を表示する
出力例:
✓ 興味を追加しました: Rust プログラミング
キーワード: rust, cargo, 所有権
remove <topic>
$ARGUMENTS = remove <topic>
- プロファイルを読み込む
topicに部分一致するエントリを特定する- 一致が複数ある場合はどれを削除するか確認する
- 削除してファイルに保存し結果を表示する
出力例:
✓ 興味を削除しました: Rust プログラミング
list
$ARGUMENTS = list
プロファイルを読み込んで以下の形式で表示する:
## あなたの興味プロファイル
### 登録済みトピック
1. Rust プログラミング (重み: 2.0)
キーワード: rust, cargo, 所有権
最終利用: 2024-01-15
### 優先カテゴリ
- it, knowledge
最終更新: 2024-01-15 10:30
プロファイルが空の場合は「興味が登録されていません。/interest-discovery add <topic> で追加できます。」と案内する。
view
$ARGUMENTS = view
- Glob ツールで
~/.claude/memories/interest-discovery/reports/YYYY-MM-DD.mdのパターンでファイルの存在を確認する - ファイルが存在する場合は Read ツールで読み込み、そのまま出力する
- ファイルが存在しない場合は「本日のレポートはまだありません。
/interest-discoveryを実行してください。」と案内する
viewは当日分のみ対応。過去日付のキャッシュを閲覧したい場合は~/.claude/memories/interest-discovery/reports/を直接参照する。
コンテンツ発見
Step 1: モードの判定とデータ読み込み
$ARGUMENTSが空 → プロファイルベース発見(登録済み興味を使用)$ARGUMENTSがキーワード → トピック指定発見(そのキーワードで検索)- プロファイルが空かつ引数なし → 全カテゴリから均等取得し、
/interest-discovery addでの登録を案内する
interests.json と history.json を読み込む。history.json から今日より前の日付の URL を除外セットとして抽出しておく。同日中の重複は許容する。
Step 2: コンテンツ取得
カテゴリ一覧と URL は references/hatena-categories.md を参照する。
すべてのカテゴリから均等に取得する。references/hatena-categories.md に記載されている全カテゴリのフィードを並列取得する。プロファイルの preferred_categories や interests[].keywords は取得対象の絞り込みではなく、スコアリングの重み付けに使用する。
WebFetch ツールで RSS を取得し、タイトル・URL・説明・ブックマーク数(<hatena:bookmarkcount>)・ブックマークタグ(<category> 要素、複数)を抽出する。取得元カテゴリ名(フィード URL から判別)も各エントリに紐付けて保持する。
並列度は 2 に制限する(同時に2フィードずつ取得)。いずれかのフィードでエラーが発生した場合は並列実行を中止し、残りのフィードを1件ずつ順次取得する。
除外セットに含まれる URL を取得結果から除外する。
Step 3: 選出
取得したエントリを以下の2段階で絞り込む。
① 関連性スコアリング
- キーワードマッチ: タイトル・説明に interests キーワードが含まれる → +1.0 × weight
- 意味的近接: 概念的に関連する場合 → +0.5 × weight
- 例: 「機械学習」→「深層学習」「LLM」「ニューラルネット」も関連
- ブックマーク数ボーナス: 100件以上 → +0.3、500件以上 → +0.6
② 品質判定・選出
候補を精査し、以下に該当する記事は紹介しない:
- 内容が薄い・クリックベイト的なタイトルだけで実質がなさそう
- まとめ・ランキング系で独自の洞察がなさそう
- トピックとの関連はあるが読む価値が低いと判断できる
③ 意外性枠の追加
関連性スコアが高くなくても、以下のような「意外な発見」になりそうな記事を積極的に混ぜる:
- ユーザーの興味と隣接するが普段は接点が少ない領域(例: Rust に興味があるなら、CPU アーキテクチャや形式検証の記事)
- 異なる分野だが思考の刺激になりそうな記事
- ブックマーク数が多く、話題性があるが普段の興味圏外のもの
意外性枠は全体の 3割程度 を目安にする。関連性の高い記事と意外性枠を組み合わせて、良質なものを厳選する。件数は 15件以内 を目安とするが、紹介したい記事が多い場合は 最大30件 まで許容する。無理に数を合わせず、自信を持っておすすめできる記事だけを選ぶ。
Step 4: 結果の提示
選出した記事を以下のフォーマットで1件ずつプレゼンする。要約は記事の本質を捉えた説明、おすすめ理由はユーザーの興味とどう結びつくか、または意外性枠の場合はなぜ新しい発見になりうるかを具体的に述べる。
## 本日の発見 - YYYY/MM/DD
### [タイトル]
[URL]
カテゴリ: [取得元カテゴリ] | ブックマーク: N件 | トピック: [マッチした興味トピック]
タグ: [tag1] [tag2] [tag3] ...
**要約**: [記事が扱っているテーマ・主張・内容を300文字以内で説明]
**おすすめ理由**: [なぜこの記事がユーザーにとって価値があるかを1〜2文で説明]
---
### [タイトル]
...
---
計 N件を紹介(関連 N件 + 意外性 N件)|取得 M件 → 既読除外 X件 → 品質判定通過 N件
- タグは隣り合うタグとの区別がつきやすいよう
[]で囲む
Step 5: レポートキャッシュの保存
レポートキャッシュファイル(reports/YYYY-MM-DD.md)を以下のルールで保存する。
初回実行(ファイルが存在しない場合)
Step 4 で出力したレポート全文をそのままファイルに書き込む。
2回目以降(ファイルが既に存在する場合)
Read ツールで既存ファイルを読み込み、セパレータと追記コンテンツを末尾に付加して Write ツールで上書き保存する。 追記内容の先頭にはセパレータと追記ヘッダを挟む:
---
## 追加発見 - YYYY/MM/DD HH:MM
その後に今回選出した記事一覧(Step 4 と同フォーマット、ただし ## 本日の発見 - ... ヘッダは省略)を続ける。
古いキャッシュの削除
保存後、reports/ ディレクトリ内の .md ファイルのうち 5日より古いもの(今日を含む直近5日分以外)を削除する。
日付の判定はファイル名(YYYY-MM-DD.md)から行い、削除対象のファイルパスを特定したうえで rm <filepath> で削除する。
rm の実行は ~/.claude/memories/interest-discovery/ 配下のファイルのみに限定する。それ以外のパスへの rm は絶対に実行しない。
例: 今日が 2026-03-01 の場合、2026-02-25〜2026-03-01 の5ファイルを保持し、2026-02-24 以前を削除する。
Step 6: 紹介履歴の保存
紹介した記事の URL を history.json の今日の日付エントリに追記して保存する。
今日のエントリが存在しない場合は新規作成する。
保存時に7日以上前のエントリを削除する。
Step 7: プロファイル更新
発見後のユーザー反応に応じてプロファイルを更新する:
- 「もっとこういう記事が見たい」→ 該当トピックの weight を +0.2(上限 3.0)
- 記事を掘り下げた場合 → そのトピックの
last_usedと weight を更新 - 変更後は必ずファイルに保存する
エラーハンドリング
- RSS 取得に失敗した場合は他のフィードにフォールバック
- ネットワークエラー時はその旨をユーザーに伝え、他のフィードへのフォールバックを試みる
- プロファイルファイルが壊れている場合は空プロファイルで起動しユーザーに通知