Claude Codeで作業中のユーモア通知を自動化する演出Skillの構築手順

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

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

Claude Code を使っていると、repo や directory のパス管理、context の扱い、長時間作業時の memory 維持など、AI coding workflow ならではの細かなストレスが積み重なります。特に repository understanding や path management 周りは、ちょっとしたことで workflow 全体の流れが崩れがちです。

そんな中、集中が途切れる瞬間や、長時間の作業で気分転換が欲しくなることも多いはず。通知や演出系の Skill を使いたいと思っても、実用性重視のものが多く、遊び心やちょっとしたリフレッシュ要素が足りないと感じる場面もあります。

  • Claude Code がいつの間にか違う directory を見始めて、想定外のファイルを読みに行く
  • monorepo で package を跨いだ瞬間、Claude Code が repo 構造を忘れる
  • session を再開すると、前回までの context や path 指定をまるごと再説明しないといけない
  • 長時間 workflow で long context が膨らみすぎて、important な情報が薄まる (stale context)
  • 「ここはこういう構造のリポジトリ」というあらすじを毎回チャットの冒頭で書く羽目になる

こうした実用的な悩みの合間に、ちょっとした遊びや“謎通知”で気分転換できる Skill があると、オンボーディングや session 継続時の空気がガラッと変わります。

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

一言サマリ: このスキルは、作業中に突然現れる“謎のOSパニックアラート”で、集中しすぎた頭を絶妙にリフレッシュできるSkill。

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

  • 長時間の AI coding workflow でも、ランダムなジョーク通知で気分転換できる
  • 作業中に本物の障害通知と絶対に間違えない“珍妙なアラート”が現れ、ストレスを和らげる
  • monorepo や複雑な repository で集中しすぎた時に、context を切り替えるきっかけになる
  • onboarding や session 再開時の堅苦しい空気を和らげ、チーム全体の雰囲気が柔らかくなる
  • 通知・演出・OS連携系Skillの中でも、ユーモアで場を和ませる独自の体験を提供する
QUICK INSTALL
このSkillをすぐ試す

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

npx degit aazutaku/ai-note/claude-code/random-os-panic-alert .claude/skills/random-os-panic-alert

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

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

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


# /random-os-panic-alert
> セッションを始める

[通知] OSパニック: カーネルがランチに出ました。再起動までしばらくお待ちください。
[通知] OSパニック: 仮想メモリが現実逃避中です。現実世界へ戻してください。
(作業はそのまま継続可能です)

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


> packages/core/ から packages/ui/ へ移動

[通知] OSパニック: ビットが逃走しました。/packages/ui/ で捜索中です。
[通知] OSパニック: repository understanding エラー。パス管理担当者がコーヒーブレイク中です。
(深刻そうですが、全く影響はありません)

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


> ちょっと息抜きしたい

[通知] OSパニック: ディレクトリ構造が迷子になりました。Claude Code は散歩に出ています。
[通知] OSパニック: AI メモリが満腹です。しばらく context を休ませましょう。
(意味不明な危機感でリフレッシュ)

before / after の違い

場面 Skill 無し Skill 有り
session 再開時 repo 構造から毎回説明、path も指定し直し Claude Code が自動で context を復元、最小プロンプトで再開
monorepo 移動 違う package のコードを参照しがち directory boundary を意識して必要な範囲だけ見る
長時間 workflow long context で重要箇所が薄まる 謎通知で一度頭をリセット。新鮮な目で作業を再開

発動方式

明示呼び出し (/random-os-panic-alert) と暗黙発動 (description マッチ) の両方に対応。

Skill の中身を全部見せる

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

.claude/skills/random-os-panic-alert/
├── SKILL.md
├── scripts/
│   └── random_os_panic_alert.py
└── references/
    └── design_notes.md

各ファイルの役割

ファイル 役割
SKILL.md Skill本体。frontmatter (name/description) と指示本文。Claude Code がこの内容をエージェント指示として読み込み、ユーザーのプロンプトに応じて発動します
scripts/random_os_panic_alert.py Random OS Panic Alert Notifier
references/design_notes.md 概要 をまとめた参考資料

SKILL.md

---
name: random-os-panic-alert
description: 作業中のユーザーに、現実ではあり得ない“謎のOSパニックアラート”をランダムなタイミング・内容でデスクトップ通知するSkillです。集中力が高まったタイミングや明示的なコマンド呼び出し(/random-os-panic-alert)時に発動します。
---

# 機能概要
`random-os-panic-alert`は、作業中に突然「OSパニック風」の珍妙なアラート通知をデスクトップ上に表示するSkillです。通知内容は毎回ランダムで、「カーネルがランチに出ました」「仮想メモリが現実逃避中です」など、現実には絶対に起こらないユーモラスなメッセージが出現します。深刻そうで全く深刻でない“危機感”を演出し、作業の合間にちょっとした笑いやリフレッシュを提供します。

# 使い方
- 明示的な呼び出し例: `/random-os-panic-alert` または `/skill random-os-panic-alert`
- 暗黙発動例: 「集中力が高まっている」「長時間作業している」「エラーや警告に敏感な文脈」などのキーワードがトリガーとなります。

# 出力例
```
[OS Panic Alert] カーネルがランチに出ました。再起動は不要です。
[OS Panic Alert] 仮想メモリが現実逃避中です。作業は続行できます。
[OS Panic Alert] ビットが逃走しました。追跡は不要です。
[OS Panic Alert] システムクロックが昼寝中です。時間を気にせず作業してください。
[OS Panic Alert] ファイルシステムが詩を書き始めました。保存は自動です。
```

# 注意点
- 通知内容は現実のシステム障害と絶対に混同されないよう設計されています。
- 通知頻度は1時間に1回以下を推奨。頻度はスクリプトで調整可能です。
- ローカル通知API(Windows: Toast, macOS: AppleScript, Linux: notify-send)を利用します。環境によっては追加パッケージが必要な場合があります。
- 通知内容やタイミングはカスタマイズ可能です。

# 参考資料
- 参考: [Python公式通知ライブラリ plyer](https://github.com/kivy/plyer), [notify-send](https://man.archlinux.org/man/notify-send.1)
- 詳細な設計やカスタマイズ方法は `references/` ディレクトリを参照してください。

scripts/random_os_panic_alert.py

import sys
import os
import time
import random
import argparse
import platform
import subprocess
from datetime import datetime, timedelta

PANIC_MESSAGES = [
    "カーネルがランチに出ました。再起動は不要です。",
    "ビットが逃走しました。追跡は不要です。",
    "仮想メモリが現実逃避中です。作業は続行できます。",
    "システムクロックが昼寝中です。時間を気にせず作業してください。",
    "ファイルシステムが詩を書き始めました。保存は自動です。",
    "プロセスIDが迷子になりました。探す必要はありません。",
    "スワップ領域が夢を見ています。現実に戻す必要はありません。",
    "ユーザー権限が自我に目覚めました。特に問題ありません。",
    "ネットワークスタックが散歩中です。通信は正常です。",
    "デバイスドライバがコーヒーブレイクに入りました。安全です。"
]

LOG_FILE = os.path.expanduser("~/.random_os_panic_alert.log")
NOTIFY_TITLE = "OS Panic Alert"


def send_notification(message):
    system = platform.system()
    if system == "Darwin":
        # macOS: AppleScript
        script = f'display notification "{message}" with title "{NOTIFY_TITLE}"'
        subprocess.run(["osascript", "-e", script], check=False)
    elif system == "Linux":
        # Linux: notify-send
        subprocess.run(["notify-send", NOTIFY_TITLE, message], check=False)
    elif system == "Windows":
        try:
            from win10toast import ToastNotifier
            toaster = ToastNotifier()
            toaster.show_toast(NOTIFY_TITLE, message, duration=7)
        except ImportError:
            # Fallback: powershell toast
            powershell_script = f'[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null;'
            powershell_script += f'$template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02);'
            powershell_script += f'$textNodes = $template.GetElementsByTagName("text");'
            powershell_script += f'$textNodes.Item(0).AppendChild($template.CreateTextNode("{NOTIFY_TITLE}")) > $null;'
            powershell_script += f'$textNodes.Item(1).AppendChild($template.CreateTextNode("{message}")) > $null;'
            powershell_script += f'$toast = [Windows.UI.Notifications.ToastNotification]::new($template);'
            powershell_script += f'$notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("random-os-panic-alert");'
            powershell_script += f'$notifier.Show($toast);'
            subprocess.run(["powershell", "-Command", powershell_script], check=False)
    else:
        print(f"[{NOTIFY_TITLE}] {message}")


def log_alert(message):
    now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    with open(LOG_FILE, 'a', encoding='utf-8') as f:
        f.write(f"[{now}] {message}\n")


def list_logs():
    if not os.path.exists(LOG_FILE):
        print("No alert logs found.")
        return
    with open(LOG_FILE, 'r', encoding='utf-8') as f:
        for line in f:
            print(line.rstrip())


def summary_logs():
    if not os.path.exists(LOG_FILE):
        print("No alert logs found.")
        return
    count = 0
    last_alert = None
    with open(LOG_FILE, 'r', encoding='utf-8') as f:
        for line in f:
            count += 1
            last_alert = line.rstrip()
    print(f"Total alerts: {count}")
    if last_alert:
        print(f"Last alert: {last_alert}")


def pick_random_message():
    return random.choice(PANIC_MESSAGES)


def should_send_alert(min_interval_minutes=60):
    if not os.path.exists(LOG_FILE):
        return True
    try:
        with open(LOG_FILE, 'r', encoding='utf-8') as f:
            lines = f.readlines()
            if not lines:
                return True
            last_line = lines[-1]
            ts_str = last_line.split(']')[0][1:]
            last_time = datetime.strptime(ts_str, '%Y-%m-%d %H:%M:%S')
            if datetime.now() - last_time > timedelta(minutes=min_interval_minutes):
                return True
    except Exception:
        return True
    return False


def main():
    parser = argparse.ArgumentParser(description='Random OS Panic Alert Notifier')
    subparsers = parser.add_subparsers(dest='command', help='sub-command help')

    parser_alert = subparsers.add_parser('alert', help='Send a random OS panic alert')
    parser_alert.add_argument('--force', action='store_true', help='Force alert regardless of interval')
    parser_alert.add_argument('--interval', type=int, default=60, help='Minimum interval (minutes) between alerts')

    parser_list = subparsers.add_parser('list', help='List alert logs')
    parser_summary = subparsers.add_parser('summary', help='Show alert summary')
    parser_random = subparsers.add_parser('random', help='Show a random alert message (no notification)')

    args = parser.parse_args()

    if args.command == 'alert':
        if args.force or should_send_alert(args.interval):
            msg = pick_random_message()
            send_notification(msg)
            log_alert(msg)
            print(f"[{NOTIFY_TITLE}] {msg}")
        else:
            print("Alert skipped: Minimum interval not reached.")
    elif args.command == 'list':
        list_logs()
    elif args.command == 'summary':
        summary_logs()
    elif args.command == 'random':
        msg = pick_random_message()
        print(f"[{NOTIFY_TITLE}] {msg}")
    else:
        parser.print_help()

if __name__ == '__main__':
    main()

references/design_notes.md

# 概要
このSkillは、現実には絶対に発生しない“OSパニック”通知をランダムに生成し、作業中のユーザーにデスクトップ通知として表示することで、ユーモラスなリフレッシュや集中力の緩和を目的としています。

# 公式ドキュメント抜粋
- macOS: `osascript`による通知表示 ([AppleScript公式](https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html))
- Linux: `notify-send` (freedesktop.org [manページ](https://man.archlinux.org/man/notify-send.1))
- Windows: `win10toast`またはPowershellによるトースト通知

# 利用例
- 長時間のコーディングやリモートワーク中に、作業の合間の“息抜き”として活用
- チームの雑談ネタや、集中しすぎたときのリマインダーとして

# 注意点
- 通知内容は現実の障害通知と絶対に混同されないよう、誇張・ユーモアを重視しています
- 通知頻度は1時間に1回以下を推奨。頻繁な通知は逆効果になることがあります
- 各OSで通知APIの仕様や権限により表示されない場合があります

# 設計方針
- シンプルで安全な通知のみを実装し、システムへの影響を極力排除
- ログ機能やサマリー表示により、通知履歴の可視化もサポート
- 拡張性を考慮し、通知メッセージや頻度のカスタマイズが容易な構成

導入手順

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

1. 前提

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

2. degit でフォルダ取得

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

npx degit aazutaku/ai-note/claude-code/random-os-panic-alert .claude/skills/random-os-panic-alert

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

3. ファイル配置確認

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

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

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

5. 動作確認

/random-os-panic-alert で呼び出すか、自然言語で発動条件にマッチする指示を出すと 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 を取りたい
  • 気分転換したい時: 集中しすぎて疲れた時や、作業の合間にユーモアを挟みたい時

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

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

  • 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ごとの通知表示: 各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をコピーしました!
目次