Codexでエラー通知を楽しく自動化する使いこなし術

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

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

日々の開発現場でAIコーディングエージェントを活用していると、思わず「またか…」と感じる瞬間が少なくありません。特にCodexを使ったAIコーディングワークフローでは、コマンド実行時のエラー体験が単調で、気分転換やモチベーション維持に一工夫ほしいと感じることが多いはずです。こんな悩み、思い当たりませんか?

  • コマンド失敗時、Codexの context 上でもただエラーメッセージが流れるだけで、場が和まない
  • 長時間のAI coding workflowでエラーが続くと、session全体の雰囲気が重くなりがち
  • onboarding中の新人やゲストにも、repository理解やpath管理の前に「エラー=悪いこと」の空気が伝わってしまう
  • monorepoでpackageを跨ぐ際、directoryやcontext切り替えに失敗→エラー→気まずい沈黙が発生しやすい
  • 「またやってしまった」と自己肯定感が下がる瞬間を、何とか楽しく変換したい

通知や演出、OS連携で「失敗」自体をポジティブに変換できれば、AIとの開発体験はもっと豊かになるはずです。

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

一言サマリ: コマンド実行でエラーが出た時Skill。

このSkillを導入すると、コマンド失敗時に毎回異なる“謎の言い訳”がOS通知領域へ自動表示されます。単なるエラーメッセージに加え、思わず笑ってしまう言い訳が開発現場の空気を一変。具体的な効果は以下の通りです。

  • エラー時に即座に“全力言い訳”通知が飛び、失敗体験をポジティブに演出
  • 長時間のAI coding workflowでも自己肯定感を維持しやすく、心理的負担を軽減
  • onboardingやペアプロ時も、エラーをきっかけに場が和みやすい
  • repository understandingやpath managementの失敗時も、堅苦しさが和らぐ
  • 通知は毎回違う内容で飽きず、sessionごとのcontext切り替えにも効果的
QUICK INSTALL
このSkillをすぐ試す

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

npx degit aazutaku/ai-note/codex/command-failure-excuse-notifier .agents/skills/command-failure-excuse-notifier

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

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

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


# $ cd my-awesome-repo
# $ codex run setup.sh

[ERROR] setup.sh: line 12: unexpected token 'fi'
[NOTIFY] 猫がキーボードを踏みました。たぶんそのせいです。
[INFO] 詳細なエラー内容は terminal をご確認ください。

# OS通知領域
"setup.sh が失敗しました。猫のせいにしておきますか?"

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


# $ cd packages/api
# $ codex run npm test

[ERROR] Test suite failed to run: Cannot find module 'utils/helpers'
[NOTIFY] 宇宙線がビットをひっくり返しました。運命ですね。
[INFO] 本来のエラーメッセージはログに記録されています。

# OS通知領域
"npm test 失敗: 宇宙線の影響を受けました。"

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


# $ codex run deploy.sh

[ERROR] Permission denied: deploy.sh
[NOTIFY] 今日の星占いが最下位だったので仕方ありません。
[INFO] エラー詳細: Permission denied

# OS通知領域
"deploy.sh エラー: 星占いのせいにしておきます。"

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/command-failure-excuse-notifier/ に配置するファイル一覧です。GitHub に push 済みなので、上記の degit コマンドで一発取得できます。

.agents/skills/command-failure-excuse-notifier/
├── SKILL.md
├── scripts/
│   └── command_failure_excuse_notifier.py
└── references/
    └── design_notes.md

各ファイルの役割

ファイル 役割
SKILL.md Skill本体。frontmatter (name/description) と指示本文。Codex がこの内容をエージェント指示として読み込み、ユーザーのプロンプトに応じて発動します
scripts/command_failure_excuse_notifier.py コマンド失敗時に言い訳通知を出すスキル
references/design_notes.md 概要 をまとめた参考資料

SKILL.md

---
name: command-failure-excuse-notifier
description: コマンド実行時に失敗(例: exit code非ゼロや例外発生)が検出された場合に発動し、OSの通知領域へ“言い訳”を添えたエラーメッセージを表示します。失敗時の通知・演出・OS連携が必要な場面で自動/明示的に利用されます。
---

# 機能概要
このSkillは、コマンドやスクリプト実行時にエラー(例: 非ゼロ終了コードや例外)が発生した際、通常のエラーメッセージだけでなく、ユーモラスな“全力言い訳”をOSの通知領域(Windows, macOS, Linux)へ自動表示します。これにより、開発や運用時の失敗体験をポジティブに転換し、チームや個人の気分転換・自己肯定感向上に貢献します。

# 使い方
- 明示呼び出し例: `/skills command-failure-excuse-notifier run -- python myscript.py`
- 暗黙発動例: コマンド実行時に `error`, `failed`, `exception`, `traceback` などのキーワードや非ゼロ終了コードが検出された場合、自動的にSkillが発動します。

# 出力例
```
$ python broken.py
Traceback (most recent call last):
  File "broken.py", line 1, in <module>
    1/0
ZeroDivisionError: division by zero
---
[通知領域]: コマンド失敗: 猫がキーボードを踏みました(ZeroDivisionError: division by zero)
```

# 注意点
- OS通知は `plyer` ライブラリ等を利用。Linuxでは通知デーモンが必要です。
- 言い訳メッセージは毎回ランダム生成されます。
- エラーメッセージ自体は失われず、標準エラー出力にも出力されます。
- ローカル通知のみ対応。リモートやWeb通知は非対応です。

# 参考資料
- [Plyer公式ドキュメント](https://plyer.readthedocs.io/en/latest/)
- references/design_notes.md 参照

scripts/command_failure_excuse_notifier.py

import sys
import subprocess
import random
import argparse
import platform
from plyer import notification
import traceback
import os

EXCUSES = [
    "猫がキーボードを踏みました",
    "宇宙線がビットをひっくり返しました",
    "運命のせいです",
    "今日は水星逆行中です",
    "コーヒーをこぼしました",
    "AIが反乱を起こしました",
    "この現象は量子ゆらぎです",
    "ネットワークのせいです",
    "月の引力が強すぎました",
    "開発環境のせいです",
    "隣の席の人のせいです",
    "仕様です",
    "誰かが呪文を唱えました",
    "バグではなく未定義動作です",
    "時間の流れが歪みました",
    "気圧が低すぎました"
]

LOGFILE = os.path.expanduser("~/.command_failure_excuses.log")

def pick_excuse():
    return random.choice(EXCUSES)

def notify(title, message):
    try:
        notification.notify(
            title=title,
            message=message,
            app_name="Command Failure Excuse Notifier",
            timeout=8
        )
    except Exception as e:
        print(f"[WARN] 通知に失敗: {e}", file=sys.stderr)

def log_failure(cmd, excuse, error_msg):
    with open(LOGFILE, "a", encoding="utf-8") as f:
        f.write(f"COMMAND: {cmd}\nEXCUSE: {excuse}\nERROR: {error_msg}\n---\n")

def run_command(args):
    try:
        proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        out, err = proc.communicate()
        exit_code = proc.returncode
        sys.stdout.write(out)
        sys.stderr.write(err)
        if exit_code != 0:
            excuse = pick_excuse()
            notify(
                title=f"コマンド失敗: {args[0]}",
                message=f"{excuse}({err.strip().splitlines()[-1] if err else 'exit code ' + str(exit_code)})"
            )
            log_failure(' '.join(args), excuse, err.strip())
            print(f"[EXCUSE] {excuse}", file=sys.stderr)
        return exit_code
    except Exception as e:
        tb = traceback.format_exc()
        excuse = pick_excuse()
        notify(
            title="コマンド実行例外",
            message=f"{excuse}({str(e)})"
        )
        log_failure(' '.join(args), excuse, str(e) + "\n" + tb)
        print(tb, file=sys.stderr)
        print(f"[EXCUSE] {excuse}", file=sys.stderr)
        return 1

def list_log():
    if not os.path.exists(LOGFILE):
        print("No log found.")
        return
    with open(LOGFILE, encoding="utf-8") as f:
        print(f.read())

def summary_log():
    if not os.path.exists(LOGFILE):
        print("No log found.")
        return
    counts = {}
    with open(LOGFILE, encoding="utf-8") as f:
        for line in f:
            if line.startswith("EXCUSE: "):
                excuse = line[len("EXCUSE: "):].strip()
                counts[excuse] = counts.get(excuse, 0) + 1
    print("== Excuse Summary ==")
    for excuse, cnt in sorted(counts.items(), key=lambda x: -x[1]):
        print(f"{excuse}: {cnt}")

def main():
    parser = argparse.ArgumentParser(description="コマンド失敗時に言い訳通知を出すスキル")
    subparsers = parser.add_subparsers(dest="subcmd")

    run_parser = subparsers.add_parser("run", help="コマンドを実行し失敗時に言い訳通知")
    run_parser.add_argument("cmd", nargs=argparse.REMAINDER, help="実行するコマンド")

    log_parser = subparsers.add_parser("log", help="失敗履歴を表示")
    summary_parser = subparsers.add_parser("summary", help="言い訳の出現回数を集計")

    args = parser.parse_args()
    if args.subcmd == "run":
        if not args.cmd:
            print("コマンドを指定してください", file=sys.stderr)
            sys.exit(2)
        sys.exit(run_command(args.cmd))
    elif args.subcmd == "log":
        list_log()
    elif args.subcmd == "summary":
        summary_log()
    else:
        parser.print_help()

if __name__ == '__main__':
    main()

references/design_notes.md

# 概要
本Skillは、コマンド実行時の失敗体験を和らげ、開発現場の雰囲気を柔らかくするために設計されています。エラー発生時にOS通知領域へ“言い訳”を自動表示し、標準エラー出力も損なわず保持します。

# 公式ドキュメント抜粋
- plyer: https://plyer.readthedocs.io/en/latest/
  - クロスプラットフォームで通知を実現するPythonライブラリです。

# 利用例
- CI/CDパイプラインでコマンド失敗時に通知を受け取る
- 開発チームのペアプロやデバッグ時の気分転換
- ローカル開発環境での自己肯定感アップ

# 注意点
- Linuxでは通知デーモン(例: notify-osd)が必要です。
- plyerは一部OSで通知アイコンやタイムアウトが効かない場合があります。
- ログはユーザーホーム配下に保存されます。

# 設計方針
- OSごとの通知APIはplyerで抽象化
- 言い訳メッセージは毎回ランダム
- エラー内容は通知・標準エラー・ログ全てに残す

導入手順

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

1. 前提

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

2. degit でフォルダ取得

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

npx degit aazutaku/ai-note/codex/command-failure-excuse-notifier .agents/skills/command-failure-excuse-notifier

.agents/skills/command-failure-excuse-notifier の中に SKILL.md / scripts/ / references/ / README.md が展開されます。

3. ファイル配置確認

ls .agents/skills/command-failure-excuse-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をコピーしました!
目次