Codexで謎のコーヒーブレイク通知を自動化する意外な活用術

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

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

AI coding workflow を日常的に回していると、集中力が切れる瞬間や、作業のリズムが崩れるタイミングが意外と多い。特に Codex のような context ベースで repository を把握しながら進める場合、長時間連続で取り組むほど「今どこまでやったか」「どこで一息つくべきか」が曖昧になりがちだ。気づけば monorepo の directory を行き来しながら、path 管理も雑になり、気づかぬうちに context が崩壊していることもある。

  • Codex が context を見失って違う場所のコードを参照する
  • monorepo で package を跨いだ瞬間、Codex が repo 構造を忘れる
  • session を再開すると、前回までの context や path 指定をまるごと再説明しないといけない
  • 長時間 workflow で long context が膨らみすぎて、important な情報が薄まる (stale context)
  • 「ここはこういう構造のリポジトリ」というあらすじを毎回チャットの冒頭で書く羽目になる

さらに、集中しているつもりでも、知らず知らずのうちに生産性が落ちているケースも多い。そんな時、ふと「今コーヒーでも飲むべき?」と考えるが、タイミングを見誤ると workflow の流れが止まってしまう。Codex のような repository understanding を要する環境では、意図せず context が切れてしまうこともあり、ちょっとした気分転換や休憩のトリガーが欲しくなる瞬間がある。

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

一言サマリ: このスキルは「AI coding workflow の合間に、OS公式っぽい“謎コーヒーブレイク通知”を完全ランダムで出現させるSkill」。

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

  • Codex を使った長時間の repository 作業中、タイミングを選ばず唐突に「コーヒーブレイク推奨」通知が現れ、気分転換のきっかけを作ってくれる
  • 通知内容は毎回 context や directory 構造に関係なく完全ランダムで、しかも OS公式っぽい説得力があるため、不思議と従いたくなる
  • monorepo で複雑な path 管理や memory が煩雑化しているときでも、workflow のリセットや切り替えのタイミングを自然に挟める
  • onboarding や session 再開時にも、長くなりがちな context を区切る「妙な休憩ポイント」を強制的に挿入できる
  • AI coding workflow の中に“遊び心”と“リズム”を持ち込むことで、stale context や集中力低下を逆手に取った運用ができる
QUICK INSTALL
このSkillをすぐ試す

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

npx degit aazutaku/ai-note/codex/random-os-coffee-break-notifier .agents/skills/random-os-coffee-break-notifier

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

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

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


# /skills menu or random-os-coffee-break-notifier mention
> プロジェクトのセットアップを始める

[通知] 重要: カフェイン補給の時刻です
OSからのお知らせ: あなたの集中力は残り12分で枯渇します。今すぐコーヒーを淹れましょう。
(通知は閉じるまで5分間表示されます)

[Codex] repository understanding を再開します...
[Codex] context: /src/main.py, /README.md

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


> packages/api/ から packages/web/ へ移動

[通知] タスク進捗が停滞中。コーヒーを飲めとの神託
OS推奨: monorepo の directory をまたいだため、集中力のリセットを推奨します。
「今すぐコーヒーブレイク」ボタンをクリックすると、5分間の休憩タイマーが起動します。

[Codex] context: packages/web/utils.js, packages/web/components/

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


> 今日は全然集中できない...

[通知] AI的診断: あと5分で集中力が消滅します
OSからのアドバイス: 本日は計3回目のコーヒーブレイク推奨です。カフェイン摂取量にご注意ください。

[Codex] memory: session log updated.

before / after の違い

場面 Skill 無し Skill 有り
session 再開時 repo 構造から毎回説明、path も指定し直し Codex が自動で context を復元、最小プロンプトで再開
monorepo 移動 違う package のコードを参照しがち directory boundary を意識して必要な範囲だけ見る
長時間 workflow long context で重要箇所が薄まる コーヒーブレイク通知で workflow をリセットしやすくなる

発動方式

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

Skill の中身を全部見せる

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

.agents/skills/random-os-coffee-break-notifier/
├── SKILL.md
├── scripts/
│   └── random_os_coffee_break_notifier.py
└── references/
    └── design_notes.md

各ファイルの役割

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

SKILL.md

---
name: random-os-coffee-break-notifier
description: ユーザーが長時間作業・コーディング・集中状態にある際や、/skills コマンドや skill名の明示呼び出し時に、OS公式風の“コーヒーブレイク推奨”通知を完全ランダムなタイミング・内容で表示します。通知・OS・休憩・リマインダーなどのキーワード検出時にも発動。
---

# 機能概要
このSkillは、作業中のユーザーに対し、まるでOS公式通知のような“コーヒーブレイク推奨”メッセージを完全ランダムなタイミングと内容でデスクトップに表示します。通知内容は毎回異なり、「重要:カフェイン補給の時刻です」「AI診断:あと5分で集中力が消滅します」など、妙な説得力を持ちながらも全く役に立たないものばかり。作業効率や生産性を気にせず、理不尽なタイミングで休憩を促すことで、ちょっとした気分転換やユーモアを提供します。

# 使い方
- 明示呼び出し例:`/skills random-os-coffee-break-notifier` または `@codex random-os-coffee-break-notifier`
- 暗黙発動キーワード例:「休憩」「通知」「OS」「リマインダー」「集中力」「作業効率」などを含む会話やコマンド実行時、自動的に発動します。

# 出力例
```
[通知] 重要: カフェイン補給の時刻です
[通知] タスク進捗が停滞中。コーヒーを飲めとの神託
[通知] AI的診断: あと5分で集中力が消滅します
[通知] OSセキュリティ警告: 休憩しないと危険です
[通知] システム最適化: コーヒーブレイクの推奨
```

# 注意点
- 通知は完全ランダムなタイミング・内容で表示されます
- 実際のOSや作業ファイルには一切影響を与えません
- 通知履歴や個人情報はローカル保存されません
- OSの通知API(Windows: Toast, macOS: AppleScript, Linux: notify-send等)を利用します

# 参考資料
- [Python公式: 通知API](https://docs.python.org/3/library/subprocess.html)
- references/design_notes.md 参照

scripts/random_os_coffee_break_notifier.py

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

MESSAGES = [
    "重要: カフェイン補給の時刻です",
    "タスク進捗が停滞中。コーヒーを飲めとの神託",
    "AI的診断: あと5分で集中力が消滅します",
    "OSセキュリティ警告: 休憩しないと危険です",
    "システム最適化: コーヒーブレイクの推奨",
    "推奨: いま飲まないと後悔するかも知れません",
    "CPU温度上昇: コーヒーで冷却を推奨",
    "仮想メモリ不足: カフェインで補給してください",
    "AI監査: 休憩頻度が低すぎます",
    "OSアップデート: コーヒーブレイクが必要です"
]

NOTIFIER_TITLE = "[通知]"

class Notifier:
    def __init__(self):
        self.os_type = platform.system()

    def send(self, message):
        if self.os_type == "Windows":
            self._windows_notify(message)
        elif self.os_type == "Darwin":
            self._mac_notify(message)
        elif self.os_type == "Linux":
            self._linux_notify(message)
        else:
            print(f"{NOTIFIER_TITLE} {message}")

    def _windows_notify(self, message):
        try:
            from win10toast import ToastNotifier
            toaster = ToastNotifier()
            toaster.show_toast("OSからのお知らせ", message, duration=8)
        except ImportError:
            # Fallback: powershell
            script = f'[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null;'
            script += f'$template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02);'
            script += f'$textNodes = $template.GetElementsByTagName("text");'
            script += f'$textNodes.Item(0).AppendChild($template.CreateTextNode("OSからのお知らせ")) > $null;'
            script += f'$textNodes.Item(1).AppendChild($template.CreateTextNode("{message}")) > $null;'
            script += f'$toast = [Windows.UI.Notifications.ToastNotification]::new($template);'
            script += f'$notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Python") ;'
            script += f'$notifier.Show($toast)'
            subprocess.Popen(["powershell", "-Command", script], shell=True)

    def _mac_notify(self, message):
        script = f'display notification "{message}" with title "OSからのお知らせ"'
        subprocess.call(["osascript", "-e", script])

    def _linux_notify(self, message):
        try:
            subprocess.call([
                "notify-send", "OSからのお知らせ", message, "-t", "8000"
            ])
        except Exception:
            print(f"{NOTIFIER_TITLE} {message}")


def random_interval(min_sec=900, max_sec=3600):
    return random.randint(min_sec, max_sec)

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

def log_event(message):
    log_path = os.path.expanduser("~/.random_os_coffee_break.log")
    now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    with open(log_path, "a", encoding="utf-8") as f:
        f.write(f"[{now}] {message}\n")

def list_log():
    log_path = os.path.expanduser("~/.random_os_coffee_break.log")
    if not os.path.exists(log_path):
        print("ログがありません。")
        return
    with open(log_path, encoding="utf-8") as f:
        for line in f:
            print(line.strip())

def summary_log():
    log_path = os.path.expanduser("~/.random_os_coffee_break.log")
    if not os.path.exists(log_path):
        print("ログがありません。")
        return
    count = 0
    first = None
    last = None
    with open(log_path, encoding="utf-8") as f:
        for line in f:
            count += 1
            ts = line.split("]")[0][1:]
            if not first:
                first = ts
            last = ts
    print(f"通知回数: {count}")
    if first and last:
        print(f"期間: {first} ~ {last}")

def run_random_notifier(args):
    notifier = Notifier()
    print("ランダムOSコーヒーブレイク通知を開始します。Ctrl+Cで終了。")
    try:
        while True:
            interval = random_interval(args.min_interval, args.max_interval)
            time.sleep(interval)
            message = pick_random_message()
            notifier.send(message)
            log_event(message)
    except KeyboardInterrupt:
        print("\n通知を終了しました。")

def send_once(args):
    notifier = Notifier()
    message = pick_random_message()
    notifier.send(message)
    log_event(message)
    print(f"通知を1回送信しました: {message}")

def main():
    parser = argparse.ArgumentParser(description="OS風コーヒーブレイク通知スクリプト")
    subparsers = parser.add_subparsers(dest="command")

    parser_run = subparsers.add_parser("run", help="ランダムな間隔で通知を表示")
    parser_run.add_argument("--min-interval", type=int, default=900, help="通知間隔の最小秒数 (デフォルト: 900)")
    parser_run.add_argument("--max-interval", type=int, default=3600, help="通知間隔の最大秒数 (デフォルト: 3600)")

    parser_once = subparsers.add_parser("once", help="1回だけ通知を表示")

    parser_list = subparsers.add_parser("list", help="通知ログを表示")
    parser_summary = subparsers.add_parser("summary", help="通知履歴の要約を表示")

    args = parser.parse_args()

    if args.command == "run":
        run_random_notifier(args)
    elif args.command == "once":
        send_once(args)
    elif args.command == "list":
        list_log()
    elif args.command == "summary":
        summary_log()
    else:
        parser.print_help()

if __name__ == "__main__":
    main()

references/design_notes.md

# 概要
本Skillは「OS公式っぽい」説得力を持つ通知を、完全ランダムな間隔と内容でユーザーに送り、意図的に生産性を妨害するユーモアを提供します。Pythonのクロスプラットフォーム通知APIを活用し、実害やデータ損失が絶対に発生しない設計です。

# 公式ドキュメント抜粋
- Windows: win10toast, Powershell通知
- macOS: osascript (AppleScript)
- Linux: notify-send
- Python subprocess: https://docs.python.org/3/library/subprocess.html

# 利用例
- 長時間作業時の気分転換やチームの雑談ネタ
- ペアプロやリモートワークでの“理不尽な休憩”演出

# 注意点
- 通知内容はすべてSkill内で完結し、外部送信やファイル破壊等は一切ありません
- ログはホームディレクトリの隠しファイルにのみ保存されます

# 設計方針
- OS種別ごとに最適な通知方式を自動選択
- サブコマンドで履歴・要約も確認可能
- ユーザー体験を損なわない「安全なジョーク」用途に特化

導入手順

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

1. 前提

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

2. degit でフォルダ取得

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

npx degit aazutaku/ai-note/codex/random-os-coffee-break-notifier .agents/skills/random-os-coffee-break-notifier

.agents/skills/random-os-coffee-break-notifier の中に SKILL.md / scripts/ / references/ / README.md が展開されます。

3. ファイル配置確認

ls .agents/skills/random-os-coffee-break-notifier
# 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 を取りたい

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

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

  • 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 との連携設計はどうあるべきか?
  • 通知が完全ランダムなタイミング・内容で出るか、データ損失や実害がないこと、通知が“OS公式っぽい”妙な説得力を持っているか

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

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

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

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

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