Codexで謎のOS違反通知を活用して作業の緩急をつける方法

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

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

Codex を使った日々のAIコーディングでは、真面目な作業に没頭しがちな一方で、ふとした瞬間に「空気が重い」「集中しすぎて疲れた」と感じることがある。特に長時間のAI coding workflowや大規模なrepository understandingを求められる場面では、以下のような悩みがよく聞かれる。

  • 長時間の session で context が膨らみ、休憩のタイミングを見失いがち
  • monorepo で複数 directory や package を跨いで作業していると、集中力が切れて思わず path management ミスが発生
  • Codex の repository 構造説明に没頭するあまり、気がつくと「ここはどの repo?」と迷子になる
  • onboarding で新しいメンバーに repo の使い方を説明中、場が硬くなりがち
  • AI coding workflow の合間にちょっとした息抜きや笑いがほしいが、業務的な通知しか飛んでこない

通知・演出・OS連携カテゴリならではの「作業空間が真面目すぎてリラックスできない」「たまには場を和ませたい」といった悩みを感じているユーザーも多い。

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

一言サマリ: このスキルは、作業中に“謎のOSライセンス違反”をランダムにデスクトップ通知で炸裂させ、真面目な雰囲気を一瞬でジョーク空間に変えるSkill。

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

  • AI coding workflow の合間に、全く予想外の“謎警告”が context を和ませる
  • repo や directory 構造の説明に疲れた時、突然のジョーク通知で気分転換できる
  • onboarding や長時間 session での空気を一気にほぐし、チームの会話が生まれる
  • Codex の通知機能を活かし、意味不明な警告で「二度見」必至の演出ができる
  • monorepo で複雑な path management に詰まった時も、思わず笑える休憩タイミングを自動で提供
QUICK INSTALL
このSkillをすぐ試す

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

npx degit aazutaku/ai-note/codex/random-os-fake-license-violation-alert .agents/skills/random-os-fake-license-violation-alert

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

使う側がイメージしやすいよう、擬似 terminal で出力例を3パターン示す。Skill が返す出力は推測だが、現実的なフォーマット・現実的な長さで書く。

シーン1: session 開始時 (プロジェクト初動で)


# /skills menu or random-os-fake-license-violation-alert mention
> プロジェクト開始

[通知] OS ライセンス違反警告
------------------------------
違反内容: あなたの椅子、座りすぎライセンス違反を検出しました。
対応: 立ち上がって5分間ストレッチしてください。
詳細: /home/user/projects/my-monorepo/
------------------------------
(この通知はジョークです)

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


> packages/api/ に移動して作業

[通知] OS ライセンス違反警告
------------------------------
違反内容: コーヒーブレイク無許可利用を検出しました。
対応: 管理者にブレイク申請を提出してください。
詳細: packages/api/src/
------------------------------
(この通知はジョークです)

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


> 今日は何か面白いことない?

[通知] OS ライセンス違反警告
------------------------------
違反内容: 謎のキーボード配列違反を検出しました。
対応: QWERTY配列に切り替えるか、理由を説明してください。
詳細: /Users/you/repos/fun-project/
------------------------------
(この通知はジョークです)

before / after の違い

場面 Skill 無し Skill 有り
session 再開時 repo 構造から毎回説明、path も指定し直し Codex が自動で context を復元、最小プロンプトで再開
monorepo 移動 違う package のコードを参照しがち directory boundary を意識して必要な範囲だけ見る
長時間 workflow long context で重要箇所が薄まる 突然の“違反”通知で集中しすぎをリセット、息抜きタイミングを作れる

発動方式

明示呼び出し (/skills menu or $skill-name mention) と暗黙発動 (description マッチ) の両方に対応。

Skill の中身を全部見せる

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

.agents/skills/random-os-fake-license-violation-alert/
├── SKILL.md
├── scripts/
│   └── random_os_fake_license_violation_alert.py
└── references/
    └── design_notes.md

各ファイルの役割

ファイル 役割
SKILL.md Skill本体。frontmatter (name/description) と指示本文。Codex がこの内容をエージェント指示として読み込み、ユーザーのプロンプトに応じて発動します
scripts/random_os_fake_license_violation_alert.py osascript -e ‘display notification “{message}” with title “{title}”‘
references/design_notes.md 概要 をまとめた参考資料

SKILL.md

---
name: random-os-fake-license-violation-alert
description: 作業中やコマンド実行時に、ランダムなタイミング・内容で“謎のOSライセンス違反”警告をデスクトップ通知として表示。通知・警告・ライセンス違反・ジョーク・演出等のキーワードを含む会話や明示呼び出しで発動。
---

# 機能概要
このSkillは、ユーザーの作業中に突如として「謎のOSライセンス違反警告」をデスクトップ通知で表示します。警告内容は毎回ランダムで生成され、「椅子の座りすぎライセンス違反」「コーヒーブレイク無許可利用」など、現実には存在しない意味不明な違反ばかり。真面目な作業空間にユーモアを加え、緊張感を和らげる演出や、ジョークとしての利用に最適です。

# 使い方
- 明示呼び出し例:
  - `/skills random-os-fake-license-violation-alert`
  - `$random-os-fake-license-violation-alert`
- 暗黙発動キーワード例:
  - 「通知」「警告」「ライセンス違反」「ジョーク」「演出」などの単語を含む会話やコマンド実行時に自動発動します。

# 出力例
```
[通知] OSライセンス違反警告
違反内容: あなたのキーボード配列が未承認です。
対策: 管理者に連絡してください。違反コード: KBD-314

[通知] OSライセンス違反警告
違反内容: コーヒーブレイク無許可利用を検出。
対策: 直ちに作業に戻ってください。違反コード: CFE-007

[通知] OSライセンス違反警告
違反内容: 椅子の座りすぎライセンス違反。
対策: 立ち上がってストレッチしてください。違反コード: CHR-999
```

# 注意点
- 本Skillはジョーク目的であり、実際のOSやライセンス違反とは一切関係ありません。
- 通知内容は毎回ランダム生成されますが、実際のシステム警告と混同しないよう演出されています。
- ローカル環境でのみ動作し、通知履歴や個人情報は保存されません。
- Linux/macOSでは`notify-send`や`osascript`を利用、Windowsは`win10toast`等公式APIを使用します。

# 参考資料
- references/design_notes.md を参照
- 公式API: [Python plyer.notification](https://plyer.readthedocs.io/en/latest/), [notify-send](https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html), [win10toast](https://github.com/jithurjacob/Windows-10-Toast-Notifications)

scripts/random_os_fake_license_violation_alert.py

import sys
import os
import random
import time
import argparse
import platform
from datetime import datetime

try:
    from plyer import notification
    PLYER_AVAILABLE = True
except ImportError:
    PLYER_AVAILABLE = False

VIOLATION_TEMPLATES = [
    {
        'violation': 'あなたの椅子、座りすぎライセンス違反',
        'advice': '立ち上がってストレッチしてください。',
        'code': 'CHR-999'
    },
    {
        'violation': 'コーヒーブレイク無許可利用を検出',
        'advice': '直ちに作業に戻ってください。',
        'code': 'CFE-007'
    },
    {
        'violation': '謎のキーボード配列違反',
        'advice': '管理者に連絡してください。',
        'code': 'KBD-314'
    },
    {
        'violation': 'マウスクリック過剰利用違反',
        'advice': 'クリック数を減らしてください。',
        'code': 'MSE-201'
    },
    {
        'violation': '未認可タブ開きすぎ違反',
        'advice': '不要なタブを閉じてください。',
        'code': 'TAB-404'
    },
    {
        'violation': 'スクリーンショット無許可保存違反',
        'advice': 'スクリーンショットは許可後に保存してください。',
        'code': 'SS-888'
    },
    {
        'violation': '未承認フォント利用違反',
        'advice': '公式フォントに切り替えてください。',
        'code': 'FNT-123'
    },
    {
        'violation': 'ディスプレイ輝度不適合違反',
        'advice': '輝度を調整してください。',
        'code': 'BRG-567'
    },
    {
        'violation': '未認可ショートカットキー利用違反',
        'advice': 'ショートカットキーの利用申請をしてください。',
        'code': 'SCT-321'
    },
    {
        'violation': 'OSアップデート回避違反',
        'advice': 'アップデートを実施してください。',
        'code': 'UPD-001'
    }
]

HISTORY_FILE = os.path.expanduser('~/.random_os_fake_license_violation_alert.log')


def send_notification(title, message):
    system = platform.system()
    if PLYER_AVAILABLE:
        notification.notify(title=title, message=message, app_name='OS License Violation', timeout=10)
    elif system == 'Darwin':
        os.system(f'''osascript -e 'display notification "{message}" with title "{title}"' ''')
    elif system == 'Linux':
        os.system(f'notify-send "{title}" "{message}"')
    elif system == 'Windows':
        try:
            from win10toast import ToastNotifier
            toaster = ToastNotifier()
            toaster.show_toast(title, message, duration=10)
        except ImportError:
            print("[通知]", title)
            print(message)
    else:
        print("[通知]", title)
        print(message)


def random_violation():
    v = random.choice(VIOLATION_TEMPLATES)
    # ランダムで文言を少し変化させる
    variants = [
        v['violation'],
        v['violation'].replace('違反', 'ライセンス違反'),
        v['violation'].replace('検出', '発見'),
        v['violation'].replace('未認可', '無許可'),
        v['violation'].replace('未承認', '未登録'),
    ]
    violation_text = random.choice(variants)
    advice = v['advice']
    code = v['code']
    return violation_text, advice, code


def format_notification(violation, advice, code):
    lines = [
        "OSライセンス違反警告",
        f"違反内容: {violation}",
        f"対策: {advice}違反コード: {code}"
    ]
    return "\n".join(lines)


def log_violation(violation, advice, code):
    now = datetime.now().isoformat(timespec='seconds')
    with open(HISTORY_FILE, 'a', encoding='utf-8') as f:
        f.write(f"{now}\t{violation}\t{advice}\t{code}\n")


def list_history(limit=10):
    if not os.path.exists(HISTORY_FILE):
        print("履歴がありません。")
        return
    with open(HISTORY_FILE, 'r', encoding='utf-8') as f:
        lines = f.readlines()
    lines = lines[-limit:]
    print("--- 通知履歴 ---")
    for line in lines:
        ts, violation, advice, code = line.strip().split('\t')
        print(f"[{ts}] {violation} / {advice} / {code}")


def summary_history():
    if not os.path.exists(HISTORY_FILE):
        print("履歴がありません。")
        return
    counts = {}
    with open(HISTORY_FILE, 'r', encoding='utf-8') as f:
        for line in f:
            _, violation, _, _ = line.strip().split('\t')
            counts[violation] = counts.get(violation, 0) + 1
    print("--- 違反内容ごとの発生回数 ---")
    for v, c in sorted(counts.items(), key=lambda x: -x[1]):
        print(f"{v}: {c}回")


def main():
    parser = argparse.ArgumentParser(description='謎のOSライセンス違反警告をランダム通知')
    subparsers = parser.add_subparsers(dest='command')

    parser_log = subparsers.add_parser('log', help='即時で通知を1回発生させる')
    parser_list = subparsers.add_parser('list', help='通知履歴を表示')
    parser_list.add_argument('--limit', type=int, default=10, help='表示件数')
    parser_summary = subparsers.add_parser('summary', help='違反内容ごとの発生回数集計')
    parser_daemon = subparsers.add_parser('daemon', help='バックグラウンドでランダム間隔通知')
    parser_daemon.add_argument('--min', type=int, default=600, help='最小間隔(秒)')
    parser_daemon.add_argument('--max', type=int, default=1800, help='最大間隔(秒)')

    args = parser.parse_args()

    if args.command == 'log' or args.command is None:
        violation, advice, code = random_violation()
        msg = format_notification(violation, advice, code)
        send_notification('OSライセンス違反警告', f"違反内容: {violation}\n対策: {advice}違反コード: {code}")
        log_violation(violation, advice, code)
        print('[通知] OSライセンス違反警告')
        print(f"違反内容: {violation}")
        print(f"対策: {advice}違反コード: {code}")
    elif args.command == 'list':
        list_history(args.limit)
    elif args.command == 'summary':
        summary_history()
    elif args.command == 'daemon':
        print('バックグラウンド通知を開始します (Ctrl+Cで停止)')
        try:
            while True:
                wait = random.randint(args.min, args.max)
                time.sleep(wait)
                violation, advice, code = random_violation()
                send_notification('OSライセンス違反警告', f"違反内容: {violation}\n対策: {advice}違反コード: {code}")
                log_violation(violation, advice, code)
        except KeyboardInterrupt:
            print('\n通知デーモンを終了しました')
    else:
        parser.print_help()

if __name__ == '__main__':
    main()

references/design_notes.md

# 概要
このSkillは、ユーザーの作業環境にユーモアをもたらすためのジョーク通知ツールです。実際のシステム警告やライセンス違反とは一切関係なく、現実には存在しない“違反”をランダムに生成し、デスクトップ通知として表示します。

# 公式ドキュメント抜粋
- [plyer.notification](https://plyer.readthedocs.io/en/latest/): クロスプラットフォームなPython通知API
- [notify-send](https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html): Linux向け通知コマンド
- [win10toast](https://github.com/jithurjacob/Windows-10-Toast-Notifications): Windows向け通知ライブラリ

# 利用例
- チームの雑談タイムやイベントでのジョーク演出
- 長時間作業の合間に、雰囲気を和らげる目的

# 注意点
- 通知内容は完全に架空であり、誤解を招かないよう演出されています。
- 通知履歴はユーザーのホームディレクトリにのみ保存され、外部送信はありません。

# 設計方針
- OS依存APIを自動判定し、どの環境でも通知が出るよう実装
- CLIから即時通知・履歴閲覧・集計・デーモン実行の各サブコマンドを用意
- ランダム性とバリエーションを重視し、毎回違う内容を生成

導入手順

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

1. 前提

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

2. degit でフォルダ取得

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

npx degit aazutaku/ai-note/codex/random-os-fake-license-violation-alert .agents/skills/random-os-fake-license-violation-alert

.agents/skills/random-os-fake-license-violation-alert の中に SKILL.md / scripts/ / references/ / README.md が展開されます。

3. ファイル配置確認

ls .agents/skills/random-os-fake-license-violation-alert
# SKILL.md, scripts/, references/, README.md があればOK

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

新しいSkillが自動で認識されます。リスト確認したい場合は /skills menu or $skill-name mention と Skill 名で出てきます。

5. 動作確認

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

こんな瞬間に便利

  • session 開始時: 前回までの repo 把握を Codex に一発で復元させたい
  • monorepo 移動時: packages を跨いだ瞬間に context を切り替えたい
  • onboarding 時: 新しい repo を Codex に把握させ、こちらが path を全部指定する手間を省きたい
  • session 再開時: long context が切れた後でも、必要な path と directory 構造だけ素早く戻したい
  • package 跨ぎ作業時: directory boundary を Skill 側で管理して、irrelevant な path 混入を防ぎたい
  • long-running workflow 前: long context で重要箇所が薄まる前に snapshot を取りたい
  • 空気を和ませたい時: ずっと真面目な session に、意図的な笑いを入れたい

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

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

  • stale context 問題: 長時間 workflow で Skill 出力が古くなり、現状と乖離する可能性
  • directory 増えすぎ問題: 大規模 repo で全 directory を網羅すると出力が肥大化して context window を圧迫
  • monorepo 肥大化: packages が多い構成では出力が雑になり、結局 path 指定し直しになる懸念
  • irrelevant path 混入: node_modules / build 成果物 / generated コードを拾ってしまう可能性
  • Codex 固有の引っかかり: description のセマンティックマッチ精度が要件次第
  • 発動しないケース: description が漠然 / 他の Skill が優先 / git管理外 directory
  • 通知の誤認: 本当のシステム警告と混同しないようジョーク演出を徹底する必要
  • 通知頻度: ランダム発動のタイミングが多すぎると逆効果になる可能性

試す前に確かめたいこと

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

  • 実 repo での token 消費は許容範囲か?
  • monorepo (packages 多数) で安定して動くか?
  • stale context にならず、長時間 workflow でも有効か?
  • AGENTS.md との連携設計はどうあるべきか?
  • 通知が期待通りランダムタイミングで出るか?
  • 警告内容が毎回ユニークか(テンプレでなくランダム性あり)?
  • 誤って本当のシステム警告と混同しない演出になっているか?

実際に Codex で試した検証ログは Codexで謎のOSライセンス違反警告をランダム通知してみた! にまとめる予定 (公開準備中の場合あり)。
あわせて Codex 公式ドキュメント と、本シリーズ「Codexを使いこなすSkillアイデア」の他記事も参照のこと。

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

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

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

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