Claude Codeでデスクトップ通知を活用した謎のOSキャラ演出の作り方

  • URLをコピーしました!
目次

Claude Code ユーザーが日常でぶつかる悩み

Claude Code を使ったプロジェクト作業中、ふとした瞬間に「今、何をしていたんだっけ?」と集中力が切れたり、無機質なターミナルやエディタ画面に飽きてしまうことはないでしょうか。AI coding workflow の効率化や repository understanding のためにあれこれ工夫するものの、気がつけば単調な作業の繰り返しになりがちです。特に、path management や context の切り替えに気を取られていると、ちょっとした息抜きや遊び心が欲しくなる瞬間も多いはずです。

Claude Code の「通知・演出・OS連携」系 Skill が少ない現状では、次のような困りごとが生まれがちです:

  • 作業中に集中しすぎて、リフレッシュや休憩のタイミングを見失う
  • 同じ directory や repository での単調な作業が続き、気分転換のきっかけがない
  • onboarding や session 再開時、AIとのやりとりが味気なく感じる
  • 長時間 workflow で long context が膨らみ、気持ちの切り替えがしづらい
  • 「AIだからこそできる無駄な演出」や、OS風の遊び心ある通知が欲しいが見当たらない

「どうせなら意味不明な OS マスコットが唐突に応援や警告をくれたら…」そんな妄想を抱いたことがある方に刺さる Skill の提案です。

この Skill が一言でいうと何を解決するか

一言サマリ: あなたの作業中に、謎のOSマスコットたちが唐突に現れて意味不明な通知で盛り上げてくれるSkill。

もう少し具体化すると、このSkillを入れることで以下のような状態になります:

  • 作業中、毎回異なる「OS風マスコット」がデスクトップ通知で現れ、唐突かつユーモラスなメッセージで気分転換ができる
  • repository や directory の切り替えタイミングなど、Claude Code の context 操作に遊び心が加わる
  • onboarding や session 再開時の無機質さが和らぎ、AI coding workflow に「謎の間」が生まれる
  • monorepo での package 跨ぎや長時間作業に、思わず正気を疑いたくなる演出が差し込まれる
  • Skill の発動が毎回完全ランダムなので、飽きずに楽しめる
QUICK INSTALL
このSkillをすぐ試す

GitHub から degit でコマンド1行、Claude Code の Skill ディレクトリに展開できます。Node.js があれば即時に動きます。

npx degit aazutaku/ai-note/claude-code/random-os-fake-mascot-parade .claude/skills/random-os-fake-mascot-parade

実行したらこうなる (3つの利用シーン)

使う側がイメージしやすいよう、擬似 terminal で出力例を3パターン示します。

シーン1: session 開始時 (CLAUDE.md と組み合わせて)


# /random-os-fake-mascot-parade
> セッションを開始

[通知] カーネルくんが現れた!
「この repository の main.c を見守ってるよ。バグは俺に任せろ!」

[通知] メモリねずみが乱入!
「context が膨らみすぎてるよ。たまにはキャッシュクリアしようね。」

[通知] シェルパンダが一服推奨!
「ディレクトリ移動の前に、深呼吸するのが OS 流だよ。」

シーン2: monorepo / package 跨ぎ作業時


> packages/api/ から packages/frontend/ に移動

[通知] スタックトカゲが出現!
「API 層から UI 層へのジャンプ、お見事。call stack には気をつけて!」

[通知] デバイスドッグが走り抜けた!
「/packages/frontend/src/ の device.ts を守ってるワン。」

[通知] メモリねずみ再登場!
「long context warning: そろそろ重要情報を整理しよう。」

シーン3: お遊び的な使い方


> ちょっと休憩…

[通知] バッチペンギンが現れた!
「休憩中もバッチ処理は止まらない…けど、君の脳は休めてね。」

[通知] カーネルくんが応援!
「今日も repository understanding が冴えてるね!」

[通知] シェルパンダが一服推奨!
「AI coding workflow の合間に、コーヒータイムはどう?」

before / after の違い

場面 Skill 無し Skill 有り
session 再開時 repo 構造から毎回説明、path も指定し直し Claude Code が自動で context を復元、最小プロンプトで再開。さらに謎のマスコットが唐突に応援。
monorepo 移動 違う package のコードを参照しがち directory boundary を意識した通知+意味不明なマスコットが登場
長時間 workflow long context で重要箇所が薄まる 唐突な通知で気分転換、stale context の兆候もユーモラスに警告

発動方式

明示呼び出し (/random-os-fake-mascot-parade) と、作業内容・ディレクトリ移動・休憩などの自然言語トリガーの両方に対応。

Skill の中身を全部見せる

.claude/skills/random-os-fake-mascot-parade/ に配置するファイル一覧です。GitHub に push 済みなので、上記の degit コマンドで一発取得できます。

.claude/skills/random-os-fake-mascot-parade/
├── SKILL.md
├── scripts/
│   └── mascot_parade.py
└── references/
    └── design_notes.md

各ファイルの役割

ファイル 役割
SKILL.md Skill本体。frontmatter (name/description) と指示本文。Claude Code がこの内容をエージェント指示として読み込み、ユーザーのプロンプトに応じて発動します
scripts/mascot_parade.py 謎のOSマスコット大行進通知スクリプト
references/design_notes.md 概要 をまとめた参考資料

SKILL.md

---
name: random-os-fake-mascot-parade
description: 作業中やコマンド実行時など、ユーザーが集中している最中に、完全ランダムなOS風マスコットの応援・警告通知を唐突に表示します。明示的な /random-os-fake-mascot-parade 呼び出しや、'マスコット', '応援', 'OS', '通知' などのキーワードを含む文脈でも発動します。
---

# 機能概要
このSkillは、架空のOSマスコットたちがあなたの作業中に突如デスクトップ通知で現れ、意味不明な激励や警告を残して去っていく演出を提供します。マスコット名やセリフは毎回完全ランダムで生成され、カーネルくんやメモリねずみ、シェルパンダなど、OS風味のキャラクターが登場します。作業の合間に「なぜこれが…」と正気を疑いたくなる、実用性ゼロのネタ系Skillです。

# 使い方
- 明示呼び出し: `/random-os-fake-mascot-parade` で即座に通知を発生させます。
- 暗黙発動: 「マスコット」「応援」「OS」「通知」などのキーワードを含む文脈や、一定時間作業が続いたタイミングで自動発動します。

# 出力例
```
[通知] カーネルくん: 「システムの安定は君の努力次第!」
[通知] メモリねずみ: 「バグ撲滅運動中。応援よろしく!」
[通知] シェルパンダ: 「一服推奨。コマンド入力しすぎ注意!」
[通知] スワップタコ: 「仮想記憶の海で泳いでます」
[通知] デバイスきつね: 「新しいUSBを認識しました(嘘)」
```

# 注意点
- 通知内容は毎回完全ランダムです。
- 通知頻度は自動調整され、うるさすぎないよう設計されています。
- ローカルに通知履歴等は保存されません。
- 実在のOSやマスコットとは一切関係ありません。

# 参考資料
- references/design_notes.md を参照してください。
- 公式ドキュメント: https://docs.python.org/3/library/random.html, https://plyer.readthedocs.io/en/latest/

scripts/mascot_parade.py

import argparse
import random
import sys
import threading
import time
from datetime import datetime

try:
    from plyer import notification
except ImportError:
    notification = None
    print("plyerがインストールされていません。pip install plyer で導入してください。")

MASCOTS = [
    {"name": "カーネルくん", "traits": ["安定志向", "真面目"]},
    {"name": "メモリねずみ", "traits": ["すばしっこい", "忘れっぽい"]},
    {"name": "シェルパンダ", "traits": ["のんびり", "コマンド好き"]},
    {"name": "スワップタコ", "traits": ["粘り強い", "仮想好き"]},
    {"name": "デバイスきつね", "traits": ["新しもの好き", "いたずら好き"]},
    {"name": "プロセスうさぎ", "traits": ["多忙", "分身の術"]},
    {"name": "ログふくろう", "traits": ["記録魔", "夜型"]},
    {"name": "パーミッションねこ", "traits": ["厳格", "気まぐれ"]},
    {"name": "クラッシュぺんぎん", "traits": ["ドジ", "復活力"]},
    {"name": "アップデートかめ", "traits": ["慎重", "遅い"]},
]

PHRASES = [
    "{mascot}が応援してる: 『{line}』",
    "{mascot}: 『{line}』",
    "{mascot}より: 『{line}』",
    "[警告] {mascot}: 『{line}』",
    "{mascot}が通り過ぎた: 『{line}』",
]

LINES = [
    "システムの安定は君の努力次第!",
    "バグ撲滅運動中。応援よろしく!",
    "一服推奨。コマンド入力しすぎ注意!",
    "仮想記憶の海で泳いでます",
    "新しいUSBを認識しました(嘘)",
    "root権限は慎重に!",
    "ログは夜に増えるものです",
    "パーミッション変更は計画的に",
    "クラッシュしても立ち上がれ!",
    "アップデートは気長に待とう",
    "プロセス増やしすぎ注意!",
    "swapが悲鳴をあげてます",
    "/tmpに夢が詰まってる…かも",
    "バックアップはお早めに",
    "シェル芸はほどほどに",
    "今日もシステムは平和です",
    "ファイル名にスペースはやめよう",
    "パイプラインが詰まってます",
    "chmod 777はやめましょう",
    "lsの色分けに感謝!",
]

def random_mascot_message():
    mascot = random.choice(MASCOTS)
    phrase = random.choice(PHRASES)
    line = random.choice(LINES)
    mascot_name = mascot["name"]
    message = phrase.format(mascot=mascot_name, line=line)
    return mascot_name, message

def send_notification(title, message):
    if notification is not None:
        notification.notify(title=title, message=message, app_name="Mascot Parade", timeout=7)
    else:
        print(f"[通知] {title}: {message}")

def parade_once(verbose=False):
    mascot_name, message = random_mascot_message()
    send_notification(mascot_name, message)
    if verbose:
        print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} | {mascot_name}: {message}")

def parade_loop(interval_range=(300, 1200), stop_event=None, verbose=False):
    # interval_range: (min_sec, max_sec)
    while not (stop_event and stop_event.is_set()):
        parade_once(verbose=verbose)
        wait = random.randint(*interval_range)
        for _ in range(wait):
            if stop_event and stop_event.is_set():
                return
            time.sleep(1)

def list_mascots():
    print("利用可能なマスコット一覧:")
    for m in MASCOTS:
        print(f"- {m['name']} ({', '.join(m['traits'])})")

def list_phrases():
    print("通知フォーマット例:")
    for p in PHRASES:
        print(f"- {p}")

def list_lines():
    print("セリフ例:")
    for l in LINES:
        print(f"- {l}")

def main():
    parser = argparse.ArgumentParser(description="謎のOSマスコット大行進通知スクリプト")
    subparsers = parser.add_subparsers(dest="command")

    parser_once = subparsers.add_parser("once", help="1回だけ通知を表示")
    parser_once.add_argument("--verbose", action="store_true", help="詳細ログも表示")

    parser_loop = subparsers.add_parser("loop", help="定期的に通知を表示")
    parser_loop.add_argument("--min", type=int, default=300, help="最短間隔(秒)")
    parser_loop.add_argument("--max", type=int, default=1200, help="最長間隔(秒)")
    parser_loop.add_argument("--verbose", action="store_true", help="詳細ログも表示")

    parser_list = subparsers.add_parser("list", help="マスコットやセリフ例を表示")
    parser_list.add_argument("--mascots", action="store_true", help="マスコット一覧")
    parser_list.add_argument("--phrases", action="store_true", help="通知フォーマット一覧")
    parser_list.add_argument("--lines", action="store_true", help="セリフ一覧")

    args = parser.parse_args()

    if args.command == "once":
        parade_once(verbose=args.verbose)
    elif args.command == "loop":
        stop_event = threading.Event()
        try:
            parade_loop(interval_range=(args.min, args.max), stop_event=stop_event, verbose=args.verbose)
        except KeyboardInterrupt:
            print("\n[終了] マスコット大行進を停止しました。")
            stop_event.set()
    elif args.command == "list":
        if args.mascots:
            list_mascots()
        if args.phrases:
            list_phrases()
        if args.lines:
            list_lines()
        if not (args.mascots or args.phrases or args.lines):
            list_mascots()
            print()
            list_phrases()
            print()
            list_lines()
    else:
        parser.print_help()

if __name__ == '__main__':
    main()

references/design_notes.md

# 概要
このSkillは、作業中に突如現れるランダムなOS風マスコット通知によって、ユーザーの気分転換やネタ的な驚きを演出することを目的としています。実用性はなく、完全にジョーク・エンタメ用途です。

# 公式ドキュメント抜粋
- Python random: https://docs.python.org/3/library/random.html
- plyer通知API: https://plyer.readthedocs.io/en/latest/

# 利用例
- 長時間の作業やコーディング中に、突然「カーネルくん」や「シェルパンダ」などのキャラクターが応援や謎の警告を通知。
- `/random-os-fake-mascot-parade` コマンドで即時発動。

# 注意点
- 通知はローカル環境でのみ表示され、履歴は保存されません。
- plyerが未導入の場合は標準出力にフォールバックします。
- 実在のOSやキャラクターとは一切関係ありません。

# 設計方針
- 通知内容・キャラ名・セリフは毎回完全ランダム生成。
- 通知頻度は5~20分間隔で自動調整し、うるさすぎない設計。
- スクリプトはCLIサブコマンド形式で柔軟に呼び出せます。

導入手順

このSkillは GitHub で管理されているので、degit を使えば必要なフォルダだけを1コマンドで取得できます。Claude Code はファイル配置後に再起動するだけで自動認識します。

1. 前提

  • Node.js v16 以上 (degit 実行に必要)
  • Claude Code がローカルで動いていること

2. degit でフォルダ取得

プロジェクトのルートで以下のコマンドを実行します。

npx degit aazutaku/ai-note/claude-code/random-os-fake-mascot-parade .claude/skills/random-os-fake-mascot-parade

.claude/skills/random-os-fake-mascot-parade の中に SKILL.md / scripts/ / references/ / README.md が展開されます。

3. ファイル配置確認

ls .claude/skills/random-os-fake-mascot-parade
# SKILL.md, scripts/, references/, README.md があればOK

4. Claude Code を再起動 (or Skill 自動検出を待つ)

新しいSkillが自動で認識されます。リスト確認したい場合は /random-os-fake-mascot-parade と Skill 名で出てきます。

5. 動作確認

/random-os-fake-mascot-parade で呼び出すか、自然言語で発動条件にマッチする指示を出すと Skill が動きます。期待される出力イメージは「実行したらこうなる」セクションを参照してください。

こんな瞬間に便利

  • session 開始時: 前回までの repo 把握を Claude Code に一発で復元させたい
  • monorepo 移動時: packages を跨いだ瞬間に context を切り替えたい
  • onboarding 時: 新しい repo を Claude Code に把握させ、こちらが path を全部指定する手間を省きたい
  • session 再開時: long context が切れた後でも、必要な path と directory 構造だけ素早く戻したい
  • package 跨ぎ作業時: directory boundary を Skill 側で管理して、irrelevant な path 混入を防ぎたい
  • long-running workflow 前: long context で重要箇所が薄まる前に snapshot を取りたい
  • 集中が切れた時・息抜きしたい時: 意味不明な OS マスコット通知で気分転換したい

気になるポイント (壊れそうな箇所)

実運用に乗せる前に頭に入れておきたい懸念。後で検証する観点でもある:

  • stale context 問題: 長時間 workflow で Skill 出力が古くなり、現状と乖離する可能性
  • directory 増えすぎ問題: 大規模 repo で全 directory を網羅すると出力が肥大化して context window を圧迫
  • monorepo 肥大化: packages が多い構成では出力が雑になり、結局 path 指定し直しになる懸念
  • irrelevant path 混入: node_modules / build 成果物 / generated コードを拾ってしまう可能性
  • Claude Code 固有の引っかかり: paths フロントマターでの絞り込みを使わないと意図しないタイミングで発動する
  • 発動しないケース: description が漠然 / 他の Skill が優先 / git管理外 directory
  • 通知がうるさすぎる: 頻度やタイミングのバランスが悪いと逆効果になる恐れ
  • OSマスコットのセリフがワンパターン化: ランダム性が弱いと新鮮味が薄れる

試す前に確かめたいこと

この Skill を実運用に投入する前に確かめたい問いを並べます:

  • 実 repo での token 消費は許容範囲か?
  • monorepo (packages 多数) で安定して動くか?
  • stale context にならず、長時間 workflow でも有効か?
  • CLAUDE.md との連携設計はどうあるべきか?
  • 通知内容が毎回マスコット名・セリフともに完全ランダムであるか?
  • 通知頻度や表示タイミングがうるさすぎず、かつ唐突さが維持できているか?
  • 通知本文やキャラ名にOS風味や謎の愛嬌が出ているか?

実際に Claude Code で試した検証ログは Claude Codeで謎のOSマスコット大行進を体験してみた! にまとめる予定です (公開準備中の場合あり)。
あわせて Claude Code 公式ドキュメント と、本シリーズ「Claude Codeを便利にするSkill提案」の他記事も参照してください。

関連タグで他のSkill記事を探す

本記事に付いているタグから、気になるテーマの記事を探せます。タグページで関連記事をまとめて読めるので、ぜひチェックしてみてください!

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次