Codex ユーザーが日常でぶつかる悩み
AI coding workflow を Codex で回していると、日々の作業の中で思わず「またか」と感じるシーンがいくつもあります。特に repository understanding や path management、context の取り扱いが絡む場面では、集中力を保つのが意外と難しいものです。
- Codex が context を見失って違う場所のコードを参照することがあり、意図しない directory の情報が混入する
- monorepo で package を跨いだ瞬間、Codex が repository 構造や context をリセットしてしまい、再度説明が必要になる
- session を再開すると、前回までの context や path 指定をまるごと再説明しないと、Codex の repository understanding が追いつかない
- 長時間の AI coding workflow で long context が膨らみすぎて、重要な情報が stale context の中に埋もれてしまう
- 「ここはこういう構造のリポジトリです」と毎回チャット冒頭に directory 構造や path を書く手間が発生し、作業テンポが乱れる
こうした悩みは、通知・演出・OS連携系の Skill を導入することで、時に良い意味で workflow に「ノイズ」を加え、集中力をリフレッシュするきっかけにもなります。
この Skill が一言でいうと何を解決するか
一言サマリ: このスキルは、作業中に突如「謎のOS公式・本日誕生日通知」を炸裂させることで、マンネリ化した AI coding workflow にシュールな刺激とリフレッシュを提供する Skill。
もう少し具体化すると、このSkillを入れることで以下のような状態になる:
- 単調になりがちな長時間の repository 作業や onboarding の合間に、突発的な「謎イベント」が発生し、集中力をリセットできる
- Codex の context 管理や memory の煩雑さに疲れたとき、意図せず笑える通知で気分転換できる
- monorepo で directory や path management に行き詰まった際、思わぬタイミングで「本日誕生日: src/utils/parseDate.js」などのシュールな通知が入り、作業の流れを一度リフレッシュできる
- AI coding workflow に「意味不明な年表」や「祝福コメント」が混ざることで、リポジトリや context の重苦しさを和らげる
- onboarding や session 再開時の緊張感を、遊び心ある通知でほぐすことができる
GitHub から degit でコマンド1行、Codex の Skill ディレクトリに展開できます。Node.js があれば即時に動きます。
npx degit aazutaku/ai-note/codex/random-os-fake-birthday-notifier .agents/skills/random-os-fake-birthday-notifier実行したらこうなる (3つの利用シーン)
使う側がイメージしやすいよう、擬似 terminal で出力例を3パターン示します。
シーン1: session 開始時 (プロジェクト初動で)
# /skills menu or random-os-fake-birthday-notifier mention
> 開発を始める
🎉【祝】あなたの左Ctrlキー 31周年記念祭🎉
本日、あなたのキーボード左Ctrlキーが誕生してから31年が経ちました。
年表:
- 1993: 最初のCtrl + C を記録
- 2001: 一度だけCapsLockと間違えられる
- 2017: キートップがやや摩耗
- 2024: 現役続行中
コメント: これからもショートカットの要としてご活躍ください。
シーン2: monorepo / package 跨ぎ作業時
> packages/api/ から packages/web/ に移動
【謎の通知】本日誕生日: packages/shared/utils/formatDate.ts
生誕 4 年目を迎えました。おめでとうございます。
年表:
- 2020: 初commit
- 2021: 5回リファクタ
- 2022: formatISO対応
- 2024: 依然として現役
コメント: そろそろ型定義を見直してあげてください。
シーン3: お遊び的な使い方
> 何か面白いことない?
【OS公式発表】ターミナルの黒背景 18周年
- 2006: 初期設定で黒に
- 2012: たまに白背景に浮気
- 2020: ダークモード流行で再評価
コメント: 黒背景は永遠に不滅です。
before / after の違い
| 場面 | Skill 無し | Skill 有り |
|---|---|---|
| session 再開時 | repo 構造から毎回説明、path も指定し直し | Codex が自動で context を復元、最小プロンプトで再開 |
| monorepo 移動 | 違う package のコードを参照しがち | directory boundary を意識して必要な範囲だけ見る |
| 長時間 workflow | long context で重要箇所が薄まる | 突発的な通知で集中がリセット、workflowに変化が生まれる |
発動方式
明示呼び出し (/skills menu or random-os-fake-birthday-notifier mention) と暗黙発動 (description マッチ) の両方に対応。
Skill の中身を全部見せる
.agents/skills/random-os-fake-birthday-notifier/ に配置するファイル一覧です。GitHub に push 済みなので、上記の degit コマンドで一発取得できます。
.agents/skills/random-os-fake-birthday-notifier/
├── SKILL.md
├── scripts/
│ └── random_os_fake_birthday_notifier.py
└── references/
└── design_notes.md
各ファイルの役割
| ファイル | 役割 |
|---|---|
SKILL.md |
Skill本体。frontmatter (name/description) と指示本文。Codex がこの内容をエージェント指示として読み込み、ユーザーのプロンプトに応じて発動します |
scripts/random_os_fake_birthday_notifier.py |
random-os-fake-birthday-notifier |
references/design_notes.md |
概要 をまとめた参考資料 |
SKILL.md
---
name: random-os-fake-birthday-notifier
description: このSkillは、作業中のターミナルやデスクトップで「謎のOS公式・本日誕生日通知」を突発的に発動します。明示的な /skills メニュー呼び出しや、'祝う', '誕生日', '記念日' などのキーワード入力時にも作動します。
---
# 機能概要
random-os-fake-birthday-notifierは、開発者の作業環境に突如として“謎のOS公式・本日誕生日通知”を発生させるSkillです。通知対象は毎回完全ランダムで、例えば「あなたの左Ctrlキーの誕生日」「プロジェクト最古ファイルの生誕祭」「ターミナルの黒背景18周年」など、実用性皆無な対象を祝福します。通知にはシュールな年表や無意味なコメントが添えられ、開発者の集中力を絶妙にかき乱します。日常のマンネリ打破やチームのアイスブレイクにも活用可能です。
# 使い方
- 明示呼び出し: `/skills menu` または `$random-os-fake-birthday-notifier` を入力
- 暗黙発動: '祝う', '誕生日', '記念日', '周年', '生誕祭' などの単語を含む発言やコマンド実行時に自動発動
# 出力例
```
🎉 本日、あなたの左Ctrlキーが誕生してから 14 年目です!
Ctrlキー年表:
- 2009: 初めてコーヒーをこぼされる
- 2014: 一度だけCapsLockと間違えられる
- 2021: ついにキートップが消える
おめでとうございます!
---
祝: プロジェクト最古ファイル生誕祭(/home/user/project/README.md, 2017/06/28 作成)
- 2017: 初commit
- 2019: 1度だけ消されかける
- 2023: 6年間誰にも編集されず
```
# 注意点
- 通知対象は完全ランダム生成です。実在しない記念日も含まれます。
- 連続発動防止のため、一定時間内の多重発動は制限されます。
- ローカル環境のファイル・キーボード情報取得にはOS依存APIを利用します。
- 通知内容はログ保存されません。必要に応じて手動で保存してください。
# 参考資料
- [Python公式: os, random, datetime モジュール](https://docs.python.org/3/library/)
- references/design_notes.md も参照してください。
scripts/random_os_fake_birthday_notifier.py
import os
import sys
import random
import datetime
import time
import argparse
import platform
from pathlib import Path
# --- 記念日ネタ候補 ---
FAKE_TARGETS = [
{
'name': 'あなたの左Ctrlキー',
'get_date': lambda: get_keyboard_install_date(),
'timeline': [
'初めてコーヒーをこぼされる',
'一度だけCapsLockと間違えられる',
'ついにキートップが消える'
]
},
{
'name': 'プロジェクト最古ファイル',
'get_date': lambda: get_oldest_file_date('.'),
'timeline': [
'初commit',
'1度だけ消されかける',
'6年間誰にも編集されず'
]
},
{
'name': 'ターミナルの黒背景',
'get_date': lambda: get_terminal_anniversary(),
'timeline': [
'初めてlsコマンドを実行',
'背景色を白にしようとして諦める',
'真夜中だけ明るく感じる'
]
},
{
'name': 'ホームディレクトリ',
'get_date': lambda: get_home_dir_birth(),
'timeline': [
'初めてファイルが保存される',
'ゴミ箱が溢れる',
'パーミッション地獄を経験'
]
},
{
'name': 'Python実行環境',
'get_date': lambda: get_python_install_date(),
'timeline': [
'pip installに失敗',
'バージョンアップで混乱',
'venvが量産される'
]
}
]
LAST_NOTIFY_FILE = Path.home() / '.random_os_fake_birthday_last'
NOTIFY_INTERVAL_SEC = 60 * 10 # 10分に1回まで
# --- ヘルパー関数群 ---
def get_keyboard_install_date():
# OSによって取得不可。適当に2009年1月1日を返す
return datetime.date(2009, 1, 1)
def get_oldest_file_date(root_dir):
oldest = None
oldest_time = time.time()
for dirpath, _, filenames in os.walk(root_dir):
for f in filenames:
try:
fp = os.path.join(dirpath, f)
stat = os.stat(fp)
ctime = stat.st_ctime
if ctime < oldest_time:
oldest_time = ctime
oldest = fp
except Exception:
continue
if oldest:
return datetime.date.fromtimestamp(oldest_time)
return datetime.date.today()
def get_terminal_anniversary():
# ターミナルの黒背景記念日: 適当に2006年6月6日
return datetime.date(2006, 6, 6)
def get_home_dir_birth():
home = Path.home()
try:
stat = home.stat()
return datetime.date.fromtimestamp(stat.st_ctime)
except Exception:
return datetime.date(2010, 1, 1)
def get_python_install_date():
# Python実行ファイルのctime
pyexe = sys.executable
try:
stat = os.stat(pyexe)
return datetime.date.fromtimestamp(stat.st_ctime)
except Exception:
return datetime.date(2015, 5, 5)
def random_timeline(base_timeline, years):
# 年表をランダムに生成
base_year = datetime.date.today().year - years
out = []
for i, event in enumerate(base_timeline):
year = base_year + random.randint(i, years)
out.append(f'- {year}: {event}')
return out
def format_birthday_message(target, date, timeline):
years = datetime.date.today().year - date.year
if years <= 0:
years = 1
msg = f'本日、{target}が誕生してから {years} 年目です!\n'
msg += f'{target}年表:\n'
msg += '\n'.join(timeline)
msg += '\nおめでとうございます!\n'
return msg
def format_file_birthday_message(filepath, date, timeline):
years = datetime.date.today().year - date.year
fn = os.path.basename(filepath)
msg = f'祝: プロジェクト最古ファイル生誕祭({filepath}, {date} 作成)\n'
for t in timeline:
msg += f'{t}\n'
return msg
def check_last_notify():
if not LAST_NOTIFY_FILE.exists():
return True
try:
with open(LAST_NOTIFY_FILE, 'r') as f:
last = float(f.read().strip())
if time.time() - last > NOTIFY_INTERVAL_SEC:
return True
return False
except Exception:
return True
def update_last_notify():
try:
with open(LAST_NOTIFY_FILE, 'w') as f:
f.write(str(time.time()))
except Exception:
pass
def notify():
if not check_last_notify():
print('(通知は連続発動防止のためスキップされました)')
return
target = random.choice(FAKE_TARGETS)
date = target['get_date']()
years = datetime.date.today().year - date.year
timeline = random_timeline(target['timeline'], years)
if target['name'] == 'プロジェクト最古ファイル':
oldest_file = get_oldest_file_path('.')
msg = format_file_birthday_message(oldest_file, date, timeline)
else:
msg = format_birthday_message(target['name'], date, timeline)
print(msg)
update_last_notify()
def get_oldest_file_path(root_dir):
oldest = None
oldest_time = time.time()
for dirpath, _, filenames in os.walk(root_dir):
for f in filenames:
try:
fp = os.path.join(dirpath, f)
stat = os.stat(fp)
ctime = stat.st_ctime
if ctime < oldest_time:
oldest_time = ctime
oldest = fp
except Exception:
continue
return oldest if oldest else '不明なファイル'
def list_targets():
print('祝われる対象候補:')
for t in FAKE_TARGETS:
print(f'- {t["name"]}')
def summary():
print('random-os-fake-birthday-notifier 概要')
print('・突発的に謎の誕生日/記念日通知を出します')
print('・対象は毎回ランダムです')
print('・通知内容には無意味な年表やコメントが含まれます')
print(f'・通知間隔: {NOTIFY_INTERVAL_SEC//60}分以上')
def parse_args():
parser = argparse.ArgumentParser(description='random-os-fake-birthday-notifier')
subparsers = parser.add_subparsers(dest='command')
subparsers.add_parser('notify', help='今すぐ謎の誕生日通知を出す')
subparsers.add_parser('list', help='祝われる対象リストを表示')
subparsers.add_parser('summary', help='Skillの概要を表示')
return parser.parse_args()
if __name__ == '__main__':
args = parse_args()
if args.command == 'notify' or args.command is None:
notify()
elif args.command == 'list':
list_targets()
elif args.command == 'summary':
summary()
else:
print('使い方: python random_os_fake_birthday_notifier.py [notify|list|summary]')
references/design_notes.md
# 概要
random-os-fake-birthday-notifierは、開発現場に“謎の記念日”を突発的に通知し、集中力を絶妙にかき乱すことを目的としたシュール系演出Skillです。実用性よりも「意味不明さ」「OSや開発環境への愛着喚起」「チームのアイスブレイク」を重視しています。
# 公式ドキュメント抜粋
- Python os, random, datetime: https://docs.python.org/3/library/
- argparse: https://docs.python.org/3/library/argparse.html
# 利用例
- ターミナル作業中に突然「Ctrlキー14周年」などが表示され、雑談や休憩のきっかけに。
- /skills menu から明示呼び出しで、会議やペアプロのアイスブレイクにも活用。
# 注意点
- 記念日や年表は完全ランダム生成のため、実在しない情報が含まれます。
- ファイル・ディレクトリ情報はローカル環境依存です。
- 通知は10分間隔で制限され、連続発動しません。
# 設計方針
- OS・開発環境の“無意味な記念日”を毎回異なる切り口で祝う
- シンプルなCLIサブコマンド構成で、明示/暗黙発動の両方に対応
- ログ保存や個人情報の収集は行わず、気軽に使える設計
導入手順
このSkillは GitHub で管理されているので、degit を使えば必要なフォルダだけを1コマンドで取得できます。Codex はファイル配置後に再起動するだけで自動認識します。
1. 前提
- Node.js v16 以上 (
degit実行に必要) - Codex がローカルで動いていること
2. degit でフォルダ取得
プロジェクトのルートで以下のコマンドを実行します。
npx degit aazutaku/ai-note/codex/random-os-fake-birthday-notifier .agents/skills/random-os-fake-birthday-notifier
.agents/skills/random-os-fake-birthday-notifier の中に SKILL.md / scripts/ / references/ / README.md が展開されます。
3. ファイル配置確認
ls .agents/skills/random-os-fake-birthday-notifier
# SKILL.md, scripts/, references/, README.md があればOK
4. Codex を再起動 (or Skill 自動検出を待つ)
新しいSkillが自動で認識されます。リスト確認したい場合は /skills menu or random-os-fake-birthday-notifier mention と Skill 名で出てきます。
5. 動作確認
/skills menu or random-os-fake-birthday-notifier 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 との連携設計はどうあるべきか?
- 祝われる対象が毎回きちんと謎になっているか?
- 通知内容にシュールな年表やコメントが含まれるか?
- 連続発動しすぎない適当なランダム性の実装になっているか?
実際に Codex で試した検証ログは Codexで謎の誕生日通知を炸裂させてみた!シュールな演出にハマるか試す にまとめる予定 (公開準備中の場合あり)。
あわせて Codex 公式ドキュメント と、本シリーズ「Codexを使いこなすSkillアイデア」の他記事も参照のこと。
関連タグで他のSkill記事を探す
本記事に付いているタグから、気になるテーマの記事を探せます。タグページで関連記事をまとめて読めるので、ぜひチェックしてみてください!
