Codexで開発者の気分をリアルタイム可視化する方法徹底ガイド

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

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

ターミナルでの開発作業や複数のリポジトリをまたぐプロジェクト管理をしていると、思わず「これ自動化できないの?」と感じる場面が頻繁に発生します。特に Codex を活用した AI coding workflow では、context や repository understanding の維持、path management の煩雑さがストレス源になりがちです。通知やOS連携系のSkillが欲しくなる理由は、単なる効率化だけでなく、開発者自身の状態や気分も含めて「今どういう状況か」を可視化したいというニーズが背景にあります。

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

さらに、開発者の気分やコンディションが作業効率やアウトプットに影響する場面も少なくありません。自分のムードが見える化されることで、チーム内のコミュニケーションやタスク配分にも役立つ可能性があります。

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

一言サマリ: ターミナルで作業しているときSkill。

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

  • Codex の context や repository understanding だけでなく、開発者の「今の気分」までターミナルやOSステータスバーに表示できる
  • 環境変数やコマンドで mood を切り替えると即座に反映、長時間の AI coding workflow でもメンタル状態を可視化できる
  • Slackやシェルプロンプト、OSの通知領域とも連動し、onboarding 時や monorepo の directory 移動時も mood 情報が context に加わる
  • 日替わりネタやツッコミ表示で、長時間作業や stale context にユーモアをプラス
  • path management や session 再開時の「今の自分」をワンアクションで共有できる
QUICK INSTALL
このSkillをすぐ試す

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

npx degit aazutaku/ai-note/codex/os-status-mood-light .agents/skills/os-status-mood-light

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

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

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


# /skills menu or os-status-mood-light mention
> 今日も新しいプロジェクトで作業開始!

[OS-Status-Mood-Light]
現在の気分: 最高
表示: 『絶好調!今日もバリバリいきましょう』
リポジトリ: ~/projects/awesome-monorepo
directory: apps/frontend
Slack status: :rocket: 絶好調
Tips: 「集中力MAX。コードレビューもお任せ!」

(設定したMOOD環境変数に応じて出力が変化します)

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


> cd packages/api
> export MOOD=だるい

[OS-Status-Mood-Light]
現在の気分: だるい
表示: 『本日省エネ運転。無理せずいきましょう』
directory: packages/api
Slack status: :snail: 省エネモード
日替わりネタ: 「APIドキュメント読むだけで今日はOKにしませんか?」
Tips: 「monorepo の package 跨ぎ時は context 切り替えを忘れずに」

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


> export MOOD=眠い
> echo "コーヒー飲みたい"

[OS-Status-Mood-Light]
現在の気分: 眠い
表示: 『眠気注意報発令中!こまめな休憩推奨』
Slack status: :coffee: 眠気と戦い中
ツッコミ: 「その状態で push して大丈夫?」
Tips: 「集中できないときはディレクトリ構造の整理から始めよう」

before / after の違い

場面 Skill 無し Skill 有り
session 再開時 repo 構造から毎回説明、path も指定し直し Codex が自動で context を復元、最小プロンプトで再開
monorepo 移動 違う package のコードを参照しがち directory boundary を意識して必要な範囲だけ見る
長時間 workflow long context で重要箇所が薄まる mood 情報で作業状況を即座に可視化、集中力低下時もサポート

発動方式

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

Skill の中身を全部見せる

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

.agents/skills/os-status-mood-light/
├── SKILL.md
├── scripts/
│   └── mood_light.py
└── references/
    └── design_notes.md

各ファイルの役割

ファイル 役割
SKILL.md Skill本体。frontmatter (name/description) と指示本文。Codex がこの内容をエージェント指示として読み込み、ユーザーのプロンプトに応じて発動します
scripts/mood_light.py os-status-mood-light: 気分可視化スキル
references/design_notes.md 概要 をまとめた参考資料

SKILL.md

---
name: os-status-mood-light
description: Codexがユーザーの作業中の気分や状態を可視化したい、または環境変数MOODの変化を検知してシェルやSlack等に通知・反映したい場合に発動します。キーワード例: 気分, MOOD, ステータスバー, シェルプロンプト, Slack連携。
---

# 機能概要
このSkillは、作業中の開発者の「気分」を環境変数MOODで管理し、リアルタイムでターミナルのシェルプロンプトやOSのステータスバー、Slackステータス等に自動反映する自己主張型可視化ツールです。MOODの値に応じて、定型フレーズや日替わりネタ、ツッコミ文が表示され、開発者のメンタル状態を周囲に伝えます。気分の見える化により、チーム内のコミュニケーションやセルフケアを促進します。

# 使い方
- 明示呼び出し例: `/skills os-status-mood-light set --mood='最高'`
- 環境変数MOODを更新: `export MOOD='だるい'`
- 暗黙発動キーワード: 「気分」「メンタル」「ステータスバー」「Slack連携」などを含む発話やスクリプト実行時
- Slack連携時は `--slack-webhook-url` オプションを指定

# 出力例
```
$ export MOOD='最高'
$ python mood_light.py show
[os-status-mood-light] 気分: 最高
絶好調!今日もバリバリ行きましょう。

$ export MOOD='だるい'
$ python mood_light.py show
[os-status-mood-light] 気分: だるい
本日省エネ運転。無理せずいきましょう。

$ python mood_light.py set --mood='ねむい'
[os-status-mood-light] 気分: ねむい
睡眠は大事。仮眠推奨。
```

# 注意点
- MOOD環境変数が未設定の場合は「普通」として扱います。
- シェルプロンプト反映には一部設定が必要です(詳細は参考資料参照)。
- Slack通知にはWebhook URLが必要です。
- ローカル環境のみ対応。クラウドやリモート端末では動作保証外です。

# 参考資料
- [os-status-mood-light 参考設計ノート](references/design_notes.md)
- [Slack API 公式ドキュメント](https://api.slack.com/messaging/webhooks)
- [Bashプロンプトカスタマイズ](https://wiki.archlinux.jp/index.php/Bash/プロンプトのカスタマイズ)

scripts/mood_light.py

import os
import sys
import argparse
import datetime
import json
import requests
from pathlib import Path

MOOD_MESSAGES = {
    '最高': ['絶好調!今日もバリバリ行きましょう。', 'やる気MAX。全力疾走。'],
    'だるい': ['本日省エネ運転。無理せずいきましょう。', 'やる気チャージ中。コーヒー推奨。'],
    'ねむい': ['睡眠は大事。仮眠推奨。', '目覚ましソング再生の時間です。'],
    '普通': ['平常運転です。', '特に波風なし。'],
    '楽しい': ['楽しい気分が伝わってきます!', 'その調子で!'],
    'つらい': ['無理せず休憩を。', '深呼吸してみましょう。'],
    '怒り': ['クールダウン推奨。', '落ち着いていきましょう。'],
    '悲しい': ['寄り添います。無理しないで。', '気分転換をおすすめします。'],
}

MOOD_LOG_PATH = Path.home() / '.os_status_mood_light_log.jsonl'

SLACK_DEFAULT_ICON = ':thought_balloon:'


def get_mood():
    mood = os.environ.get('MOOD', '普通')
    return mood

def set_mood(mood: str):
    os.environ['MOOD'] = mood
    return mood

def pick_message(mood: str):
    import random
    if mood in MOOD_MESSAGES:
        return random.choice(MOOD_MESSAGES[mood])
    else:
        return '今日も一日頑張りましょう。'

def log_mood(mood: str, message: str):
    now = datetime.datetime.now().isoformat()
    entry = {'timestamp': now, 'mood': mood, 'message': message}
    with open(MOOD_LOG_PATH, 'a', encoding='utf-8') as f:
        f.write(json.dumps(entry, ensure_ascii=False) + '\n')

def show_mood():
    mood = get_mood()
    message = pick_message(mood)
    print(f'[os-status-mood-light] 気分: {mood}\n{message}')
    log_mood(mood, message)

def set_mood_cli(mood):
    set_mood(mood)
    show_mood()

def list_mood_logs(limit=10):
    if not MOOD_LOG_PATH.exists():
        print('ログがありません。')
        return
    with open(MOOD_LOG_PATH, 'r', encoding='utf-8') as f:
        lines = f.readlines()
    for line in lines[-limit:]:
        entry = json.loads(line)
        print(f"{entry['timestamp']} | {entry['mood']} | {entry['message']}")

def summary_mood():
    if not MOOD_LOG_PATH.exists():
        print('ログがありません。')
        return
    counts = {}
    with open(MOOD_LOG_PATH, 'r', encoding='utf-8') as f:
        for line in f:
            entry = json.loads(line)
            mood = entry['mood']
            counts[mood] = counts.get(mood, 0) + 1
    print('気分別出現回数:')
    for mood, count in sorted(counts.items(), key=lambda x: -x[1]):
        print(f'{mood}: {count}回')

def send_slack_status(mood: str, message: str, webhook_url: str):
    payload = {
        'text': f'[os-status-mood-light] 気分: {mood}\n{message}',
        'icon_emoji': SLACK_DEFAULT_ICON
    }
    try:
        resp = requests.post(webhook_url, json=payload)
        if resp.status_code != 200:
            print(f'Slack通知失敗: {resp.status_code} {resp.text}')
        else:
            print('Slack通知成功')
    except Exception as e:
        print(f'Slack通知エラー: {e}')

def parse_args():
    parser = argparse.ArgumentParser(description='os-status-mood-light: 気分可視化スキル')
    subparsers = parser.add_subparsers(dest='command')

    show_parser = subparsers.add_parser('show', help='現在の気分を表示')
    show_parser.add_argument('--slack-webhook-url', type=str, help='Slack Webhook URLに通知')

    set_parser = subparsers.add_parser('set', help='気分を設定')
    set_parser.add_argument('--mood', type=str, required=True, help='設定する気分')
    set_parser.add_argument('--slack-webhook-url', type=str, help='Slack Webhook URLに通知')

    list_parser = subparsers.add_parser('list', help='気分ログを表示')
    list_parser.add_argument('--limit', type=int, default=10, help='表示件数')

    summary_parser = subparsers.add_parser('summary', help='気分の集計')

    return parser.parse_args()

def main():
    args = parse_args()
    if args.command == 'show':
        mood = get_mood()
        message = pick_message(mood)
        print(f'[os-status-mood-light] 気分: {mood}\n{message}')
        log_mood(mood, message)
        if args.slack_webhook_url:
            send_slack_status(mood, message, args.slack_webhook_url)
    elif args.command == 'set':
        set_mood(args.mood)
        message = pick_message(args.mood)
        print(f'[os-status-mood-light] 気分: {args.mood}\n{message}')
        log_mood(args.mood, message)
        if args.slack_webhook_url:
            send_slack_status(args.mood, message, args.slack_webhook_url)
    elif args.command == 'list':
        list_mood_logs(args.limit)
    elif args.command == 'summary':
        summary_mood()
    else:
        print('コマンドを指定してください。 --help でヘルプ表示')

if __name__ == '__main__':
    main()

references/design_notes.md

# 概要
このSkillは、開発者の気分状態を環境変数やシェルプロンプト、Slackステータス等にリアルタイムで反映することで、メンタルの可視化やチーム内コミュニケーションの促進を目指します。

# 公式ドキュメント抜粋
Slack Webhookの利用には https://api.slack.com/messaging/webhooks を参照。シェルプロンプトのカスタマイズは Bash のPS1やzshのPROMPT変数を利用します。

# 利用例
- 朝一番で `export MOOD='最高'` をセットし、プロンプトやSlackに気分を表示
- 気分が落ち込んだとき `python mood_light.py set --mood='つらい' --slack-webhook-url=...` で周囲に通知
- 日々の気分ログを `python mood_light.py summary` で集計

# 注意点
- 環境変数MOODはシェルごとに異なるため、ターミナルを跨ぐ場合は再設定が必要
- Slack通知はWebhook URLの管理に注意
- ログファイルはホームディレクトリ直下に保存されます

# 設計方針
- 実在API・標準的なシェルカスタマイズのみ利用
- ローカルで完結し、外部依存は最小限
- 日替わりネタやツッコミ文は拡張可能な辞書形式で管理

導入手順

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

1. 前提

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

2. degit でフォルダ取得

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

npx degit aazutaku/ai-note/codex/os-status-mood-light .agents/skills/os-status-mood-light

.agents/skills/os-status-mood-light の中に SKILL.md / scripts/ / references/ / README.md が展開されます。

3. ファイル配置確認

ls .agents/skills/os-status-mood-light
# 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 との連携設計はどうあるべきか?
  • 環境変数変更で即座に mood 表示が切り替わるか?
  • シェルプロンプトやステータスバーに mood 情報が正しく反映されるか?
  • 日替わりネタやツッコミ文が実際に出るか?

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

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

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

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

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