Communityコーディング&開発github.com

erikvallow-qt/dont-let-me-slide

問題をAIで修正した後にセッションを振り返り、教訓を人間とAI向けに記録し、重要ポイントをクイズで確認します。

dont-let-me-slide とは?

このスキルは、AIアシスタント(Claude Codeなど)との対話セッションを自動的にレビューし、学びを構造化して記録・定着させるためのツールです。問題解決後のチャット履歴から該当セッションを特定し、人間とAIの双方が見逃した点や理解不足だった概念を洗い出します。各教訓について検証済みの公式ドキュメントや信頼できるリンクを調査し、LEARNED.md(教訓レポート)とlearned_quiz.py(インタラクティブクイズ)の2ファイルを生成します。クイズはPython3標準ライブラリのみで動作し、macOS/Linux/Windows互換。フラッシュカードモードやトピックフィルタなど多彩な学習オプションを備え、AI支援による学習の定着を支援します。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/erikvallow-qt/dont-let-me-slide/tree/HEAD/dont-let-me-slide

Installed? Explore more コーディング&開発 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

問題を解決したセッションを振り返りましょう。2つのファイルを出力します:LEARNED.md と learned_quiz.py(ターミナル用クイズ)。

  1. セッションを特定する。最近のチャットから問題に合致するものを探します。複数の候補がある場合はユーザーに問い合わせてください。セッションがプロジェクトに属する場合、そのプロジェクト内の他のチャットも確認します。
  2. セッション全体を読みます。要約だけではなく全文を読んでください。問題が解決されるまでに人間とAIがそれぞれ何を見逃したかに注目します。また、人間が盲目的に受け入れたり、複数回質問したり、間違えた概念にも注目します。これらはより深い掘り下げが必要です。
  3. 書き始める前にリンクを調査する。各教訓について最低1つのリンクを見つけてください。人間の教訓ごとに、および手順2で特定した概念ごとに、背景を基本原理から説明する1~3個の深掘りリンクを見つけてください。優先順位:公式ドキュメントまたは仕様書、ベンダーのアプリケーションノートまたはマニュアル、有名なチュートリアルまたは教科書、次いで評判の良いブログやQ&A。WebSearchを使用し、各リンクをWebFetchで開いて内容が正しく読み込まれ、ポイントをカバーしていることを確認します。失敗したリンクやトピックから外れたリンクは削除します。URLを勝手に作成しないでください。
  4. LEARNED.md を以下のセクションで記述します(この順序で):
    • 何が起こったか:3~5文、およびステータス(解決済みか未解決か)。未解決の場合は未完了項目を列挙します。
    • 学んだ教訓:Human(人間)、AI、Shared(共通)に分割します。各教訓について、要点、何を見逃したか、教訓を一文で、およびリンク(出典名付き)を記載します。背景説明が必要なHuman教訓の下には「深掘り」サブリストを追加します。各エントリは タイトル、出典、およびその内容とここで役立つ理由を一文で記載します。
    • テスト問題:3~5個の重要な質問を「テスト問題」というタイトルで記載し、その後に解答鍵を付けます。完全な問題セットは learned_quiz.py にあることに注意してください。
    • リンク:使用したすべてのリンクを教訓ごとにグループ化し、出典名を付けます。リンクは実行日に確認済みであり、使用前に検証すべきであることを明記します。
    • 提案するワンショットプロンプト:このセッションでの問題を回避できたであろう、簡潔なプロンプトを一つ。
  5. 主張にラベルを付ける。未確認の主張は「未確認」と明記します。検索結果から取った主張は「報告済み」とし、出典をリンクします。
  6. 推測を発見事項として提示しない。問題の原因が確認されていない場合は、そのように述べます。
  7. 以下のテンプレートから learned_quiz.py を作成します。ルール:
    • Python 3標準ライブラリのみを使用。macOS、Linux、Windowsのターミナルで動作する必要があります。GUIは使用しません。
    • すべての概念をカバーします。テスト問題の3~5問だけでなく、各Human教訓につき少なくとも2問、各AIおよびShared教訓につき少なくとも1問、各深掘り概念につき1問を含めます。通常10~25問です。想起問題、「最初に何を確認するか」問題、「間違い探し」問題を混ぜます。
    • 各問題:トピック(Human、AI、Shared、または短い概念名)、4つの選択肢(もっともらしい選択肢を含む)、正解のインデックス、1~2文の理由、および最も関連性の高い確認済みリンク。
    • TITLE、SOURCE、QUESTIONS のみを記入します。エンジンは変更しないでください。
    • 送信前に python3 -c "import ast,sys;ast.parse(open(sys.argv[1]).read())" learned_quiz.py を実行し、次に python3 learned_quiz.py --list を実行して、エラーを修正します。各回答インデックスが正しい選択肢を指していることを確認します。
  8. LEARNED.md は簡潔に保ちます。どちらのファイルでもemダッシュを使用しないでください。
  9. 両方のファイルを SendUserFile で送信します。返信には実行コマンドを含めます:python3 learned_quiz.py(オプション:-r フラッシュカードレビュー、-t TOPIC フィルタ、-n N 制限、--list 全表示、--seed N 固定順序)。

クイズテンプレート(正確にコピーし、プレースホルダーとサンプル問題を置き換えてください):

#!/usr/bin/env python3
"""LEARNED クイズ: <トピック>. 実行方法: python3 learned_quiz.py [-r] [-t TOPIC] [-n N] [--list]"""
import argparse, random, sys, textwrap

TITLE = "<トピック>"
SOURCE = "LEARNED.md, <日付>"
QUESTIONS = [
    {"topic": "Human", "q": "サンプル質問?",
     "choices": ["正解", "誤答1", "誤答2", "誤答3"], "answer": 0,
     "why": "理由を1〜2文で。", "link": "https://example.com"},
]

def wrap(s, ind="   "):
    return textwrap.fill(s, 78, initial_indent=ind, subsequent_indent=ind)

def ask(prompt, valid):
    while True:
        try:
            a = input(prompt).strip().lower()
        except (EOFError, KeyboardInterrupt):
            print(); sys.exit(0)
        if a in valid:
            return a

def run(qs, review):
    missed = []
    for i, q in enumerate(qs, 1):
        order = list(range(len(q["choices"])))
        random.shuffle(order)
        letters = "abcdefgh"[:len(order)]
        print(f"\n[{i}/{len(qs)}] ({q['topic']})")
        print(wrap(q["q"], ""))
        for L, idx in zip(letters, order):
            print(wrap(f"{L}) {q['choices'][idx]}"))
        right = letters[order.index(q["answer"])]
        if review:
            if ask("   Enterで表示、qで終了: ", {"", "q"}) == "q":
                sys.exit(0)
            ok = True
        else:
            a = ask(f"   回答 [{letters}]、qで終了: ", set(letters) | {"q"})
            if a == "q":
                break
            ok = a == right
            print("   正解!" if ok else f"   残念。正解は: {right}")
        if review or not ok:
            print(wrap(f"{right}) {q['choices'][q['answer']]}"))
        print(wrap(q["why"]))
        if q.get("link"):
            print(wrap("詳細: " + q["link"]))
        if not ok:
            missed.append(q)
    return missed

def main():
    p = argparse.ArgumentParser(description=f"クイズ: {TITLE}")
    p.add_argument("-r", "--review", action="store_true", help="フラッシュカードモード(採点なし)")
    p.add_argument("-t", "--topic", help="このトピックのみ(Human, AI, Shared, ...)")
    p.add_argument("-n", type=int, help="最大N問出題")
    p.add_argument("--list", action="store_true", help="すべてのQ&Aを表示して終了")
    p.add_argument("--seed", type=int, help="シャッフル固定順")
    a = p.parse_args()
    random.seed(a.seed)
    qs = [q for q in QUESTIONS if not a.topic or q["topic"].lower() == a.topic.lower()]
    if not qs:
        sys.exit(f"トピック {a.topic!r} に該当する問題がありません。")
    if a.list:
        for i, q in enumerate(qs, 1):
            print(f"{i}. ({q['topic']}) {q['q']}\n{wrap('A: ' + q['choices'][q['answer']])}\n{wrap(q['why'])}")
            if q.get("link"):
                print(wrap("詳細: " + q["link"]))
        return
    random.shuffle(qs)
    qs = qs[:a.n] if a.n else qs
    print(f"{TITLE}\n出典: {SOURCE}\n{len(qs)}問")
    while qs:
        missed = run(qs, a.review)
        if a.review:
            break
        print(f"\nスコア: {len(qs) - len(missed)}/{len(qs)}")
        if not missed or ask("間違えた問題を再挑戦しますか? [y/n]: ", {"y", "n"}) == "n":
            for q in missed:
                print(wrap(f"復習: {q['q']}", "- ") + ("\n" + wrap(q["link"]) if q.get("link") else ""))
            break
        qs = missed

if __name__ == "__main__":
    main()

関連スキル