Skip to content

Instantly share code, notes, and snippets.

@hitode909
Last active March 19, 2026 09:24
Show Gist options
  • Select an option

  • Save hitode909/2f1287844b37ab11529b703e1158b618 to your computer and use it in GitHub Desktop.

Select an option

Save hitode909/2f1287844b37ab11529b703e1158b618 to your computer and use it in GitHub Desktop.
claude-code-kindle-highlights-spinner

kindle-spinner: Kindleハイライトでspinner verbsを彩る

Kindleでハイライトした短いセンテンスをClaude Codeのspinner verbsに設定する。 作業中のスピナーに、自分の読書体験からの一節がランダムに流れるようになる。

インストール方法

以下のパスにこのSKILL.mdを配置する。

/.claude/skills/kindle-spinner/SKILL.md

もしくは、このプロンプトをコピペでClaude Codeに教えても実行できるはず。

使い方

/kindle-spinner        # デフォルト30冊
/kindle-spinner 300    # 300冊から収集

引数で巡回する冊数を指定できる。省略時は30冊。

手順

Step 1: ハイライトの収集

スキル起動時の引数を冊数として使う(省略時は30)。以下のコード内の TARGET_COUNT を実際の数値に置き換えてからユーザーに提示し、ブラウザで実行してもらう。

ユーザーへの案内:

  1. https://read.amazon.co.jp/notebook をブラウザで開く
  2. 開発者コンソール(F12 → Console)を開く
  3. 以下のコードを貼り付けて実行する
  4. ランダムな冊数(スキル起動時の引数、デフォルト30)から1冊1ハイライトずつ集め、自動で kindle_spinner_verbs.json がダウンロードされる
// Kindle → Claude Code Spinner Verbs
// https://read.amazon.co.jp/notebook の開発者コンソール(F12)で実行
(async () => {
  const bookEls = document.querySelectorAll('#kp-notebook-library .kp-notebook-library-each-book');
  const indices = [...Array(bookEls.length).keys()];
  for (let i = indices.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [indices[i], indices[j]] = [indices[j], indices[i]];
  }
  const target = Math.min(TARGET_COUNT, bookEls.length);
  const books = []; // { title, author, highlights[] } を本ごとに収集
  let visited = 0;
  console.log(`📚 ${bookEls.length}冊からランダムに${target}冊を巡回します(指定: ${TARGET_COUNT}冊)...\n`);

  for (const idx of indices) {
    if (visited >= target) break;
    const book = bookEls[idx];
    const title = book.querySelector('h2')?.textContent?.trim() || '';
    const author = book.querySelector('p')?.textContent?.trim()?.replace(/^:\s*/, '') || '';
    console.log(`📖「${title}」を巡回中… (${visited + 1}/${target})`);
    book.querySelector('a')?.click();
    await new Promise(r => setTimeout(r, 2000));

    const highlights = [];
    document.querySelectorAll('#highlight').forEach(h => {
      const text = h.textContent?.trim();
      if (text && text.length >= 10 && text.length <= 80 && !text.includes('\n')) {
        highlights.push(text);
      }
    });
    if (highlights.length > 0) {
      books.push({ title, author, highlights });
      console.log(`  ✨ ${highlights.length}件の候補をストック`);
    } else {
      console.log(`  (短いハイライトなし、スキップ)`);
    }
    visited++;
  }

  // 全冊の候補が揃ってから、各本からランダムに1件ずつ選ぶ
  const verbs = books.map(b => {
    const pick = b.highlights[Math.floor(Math.random() * b.highlights.length)];
    return `「${pick}」 - ${b.title} ${b.author}`;
  });
  console.log(`\n🎉 ${target}冊を巡回し、${books.length}冊から${verbs.length}件のハイライトを選出!`);
  const blob = new Blob([JSON.stringify(verbs, null, 2)], { type: 'application/json' });
  const a = document.createElement('a');
  a.href = URL.createObjectURL(blob);
  a.download = 'kindle_spinner_verbs.json';
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  console.log('📥 kindle_spinner_verbs.json をダウンロードしました');
})();

Step 2: settings.json に書き込む

ユーザーからダウンロード完了の報告を受けたら、以下を実行する。

cp ~/.claude/settings.json ~/.claude/settings.json.bak.$(date +%Y%m%d%H%M%S)
ruby -rjson -e '
verbs = JSON.parse(File.read(File.expand_path("~/Downloads/kindle_spinner_verbs.json")))
original_count = verbs.length

# KindleのUI都合で文の切れ目がずれるのをトリム
verbs = verbs.map { |v|
  next nil unless v =~ /\A「(.+?)」( - .+)\z/m
  text, meta = $1, $2
  text = text.sub(/\A[ぁ-んァ-ヶa-zA-Z]{0,5}[。!?」)\)]\s*/, "")
  text = text.sub(/\A[、。]\s*/, "")
  text = text.sub(/[、,(\(「]\s*\z/, "")
  text = text.sub(/[\[[][A-Za-z]*\s*\z/, "")
  text = text.rstrip
  next nil if text.length < 10 || text.length > 80
  "「#{text}」#{meta}"
}.compact

settings = JSON.parse(File.read(File.expand_path("~/.claude/settings.json")))
settings["spinnerVerbs"] = { "mode" => "replace", "verbs" => verbs }
File.write(File.expand_path("~/.claude/settings.json"), JSON.pretty_generate(settings) + "\n")
puts "#{original_count} -> #{verbs.length} verbs written (#{original_count - verbs.length} trimmed out)"
'

再起動不要で即座に反映される。

技術メモ

  • Kindle Notebookの本切り替えは book.querySelector('a').click() で行う(Amazon の a-declarative フレームワークのため dispatchEvent では動かない)
  • 長いハイライトはターミナルで複数行になり表示が崩れるため、80文字以内に限定する
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment