Claude Codeで開発者の気分をリアルタイム可視化するSkill構築手順

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

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

Claude Code を使っていると、意外なタイミングで自分の作業状況や気分が周囲に伝わってしまう、もしくは逆に「今どんな状態?」をうまく可視化できずに困ることがあります。特に通知やOS連携まわりでは、開発現場ならではの“あるある”が発生しがちです。

  • 作業に集中しているとき、Slackやシェルプロンプトで「今どんな気分?」と聞かれても、毎回入力するのが面倒
  • 開発チームでリモート作業中、誰が「絶好調」なのか「今日はだるい」なのか、空気感が伝わりにくい
  • 環境変数やOSのステータスバーを使って自分の状態を伝えたいが、手動で設定・解除するのが煩雑
  • 気分や状況を可視化したいが、既存の通知機能では細かいニュアンスや日替わりネタを盛り込めない
  • ターミナルやSlack連携で、ちょっとしたジョークやツッコミを挟みたいが、毎回スクリプトを書くのは手間

こうした“自己主張”を半自動で演出できる仕組みがあれば、開発現場の雰囲気やチームのコミュニケーションも一段階アップします。

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

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

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

  • 環境変数 MOOD の値に応じて、OSのステータスバーやシェルプロンプト、Slack等に“今の気分”がリアルタイム表示される
  • 日替わりネタやツッコミ文も自動で反映されるため、開発現場の空気感やノリを簡単に演出できる
  • 自己申告せずとも、repoやdirectoryごとに気分や状況を可視化できるため、onboardingやリモートコミュニケーションが円滑になる
  • 長時間のAI coding workflowやmonorepo作業中でも、contextやmemoryに“今の状態”を自然に残せる
  • Skillの導入・運用も .claude/skills/ 配置だけで完結し、path managementやrepository understandingの手間を減らせる
QUICK INSTALL
このSkillをすぐ試す

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

npx degit aazutaku/ai-note/claude-code/os-status-mood-light .claude/skills/os-status-mood-light

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

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

シーン1: session 開始時 (CLAUDE.md と組み合わせて)


# /os-status-mood-light

[os-status-mood-light] 現在の気分: 最高
→ ステータスバー: 『絶好調』
→ シェルプロンプト: [MOOD: 絶好調]
→ Slack status: :star: 絶好調
本日のネタ: 「今日も最高のコードを書こう!」
(ディレクトリ: /myproject)

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


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

[os-status-mood-light] 現在の気分: だるい
→ ステータスバー: 『本日省エネ運転』
→ シェルプロンプト: [MOOD: だるい]
→ Slack status: :snail: 本日省エネ運転
日替わりツッコミ: 「API修正は気合いで乗り切ろう」
(ディレクトリ: /repo/packages/api)

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


# export MOOD=お腹すいた
# /os-status-mood-light

[os-status-mood-light] 現在の気分: お腹すいた
→ ステータスバー: 『ランチタイムまで全力待機』
→ シェルプロンプト: [MOOD: お腹すいた]
→ Slack status: :rice_ball: ランチ待ち
今日の一言: 「集中力は血糖値に比例します」
(ディレクトリ: /sandbox)

before / after の違い

場面 Skill 無し Skill 有り
session 再開時 repo 構造から毎回説明、path も指定し直し Claude Code が自動で context を復元、最小プロンプトで再開
monorepo 移動 違う package のコードを参照しがち directory boundary を意識して必要な範囲だけ見る
長時間 workflow long context で重要箇所が薄まる 気分や状況を明示して context の鮮度維持

発動方式

明示呼び出し (/os-status-mood-light) と暗黙発動 (description マッチ) の両方に対応。

Skill の中身を全部見せる

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

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

各ファイルの役割

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

SKILL.md

---
name: os-status-mood-light
description: 環境変数MOODやOSステータスバー、シェルプロンプトの状態変化を検知し、ユーザーの気分をリアルタイムで可視化したい場合に発動。気分変更やSlack連携、日替わりネタ表示などのキーワードが含まれるときに推奨。
---

# 機能概要
`os-status-mood-light`は、開発者の「気分」を環境変数MOODやシェルプロンプト、OSステータスバー、Slackステータス等に自動反映し、周囲や自分自身に可視化するスキルです。作業者のメンタル状態をリアルタイムで表現し、ちょっとしたユーモアや日替わりネタ、ツッコミ文も交えながら、作業現場の空気を和らげます。気分は環境変数やCLIから変更でき、即座に反映されます。

# 使い方
- 明示呼び出し: `/os-status-mood-light set --mood="最高"`
- 暗黙発動: `MOOD=だるい` をexportした際や、「気分」「ステータス」「Slack連携」などのワードを含む会話・コマンド実行時
- ステータス表示: `/os-status-mood-light show`
- Slack連携: `--slack` オプション

# 出力例
```
$ export MOOD=最高
$ python os_status_mood_light.py show
[絶好調] 今日もバリバリいきましょう!
(本日のネタ: 6月の開発者は梅雨に負けない)
$ export MOOD=だるい
$ python os_status_mood_light.py show
[本日省エネ運転] 無理せずいきましょう。
(ツッコミ: そろそろコーヒータイム?)
```

# 注意点
- 気分データはローカル保存され、個人PC/セッションごとに管理されます。
- Slack連携には環境変数SLACK_TOKENが必要です。
- OSステータスバー反映はmacOS/iTerm2やtmux等のAPIに依存します。
- シェルプロンプト連携はbash/zsh等でPROMPT_COMMANDを編集してください。

# 参考資料
- [iTerm2 Dynamic Profiles](https://iterm2.com/documentation-dynamic-profiles.html)
- [Slack Status API](https://api.slack.com/methods/users.profile.set)
- references/design_notes.md も参照してください。

scripts/os_status_mood_light.py

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

MOOD_MAP = {
    '最高': {'status': '絶好調', 'msg': '今日もバリバリいきましょう!'},
    'だるい': {'status': '本日省エネ運転', 'msg': '無理せずいきましょう。'},
    '普通': {'status': '平常運転', 'msg': 'いつも通りです。'},
    '眠い': {'status': '仮眠推奨', 'msg': 'ちょっと休憩しましょう。'},
    '怒り': {'status': '要注意', 'msg': '深呼吸しましょう。'},
    '楽しい': {'status': 'ノリノリ', 'msg': '楽しんでます!'},
    '悲しい': {'status': 'しんみり', 'msg': '気分転換しましょう。'},
}

NEGA_TSUKKOMI = [
    'そろそろコーヒータイム?',
    'リフレッシュも大事です。',
    '一息つきませんか?',
    '今日は早めに切り上げましょう。',
    '無理は禁物ですよ。',
]

DAILY_NEWS = [
    '6月の開発者は梅雨に負けない',
    '本日のバグは気分次第',
    '新しいAPIと新しい気分',
    '今日の小ネタ: ステータスバーで自己主張',
    'Slackにも気分を伝えよう',
]

LOCAL_STATE_PATH = Path.home() / '.os_status_mood_light.json'


def get_current_mood():
    mood = os.environ.get('MOOD', None)
    if mood:
        return mood
    if LOCAL_STATE_PATH.exists():
        try:
            with open(LOCAL_STATE_PATH, 'r') as f:
                data = json.load(f)
                return data.get('mood', '普通')
        except Exception:
            return '普通'
    return '普通'


def set_local_mood(mood):
    data = {
        'mood': mood,
        'updated': datetime.datetime.now().isoformat()
    }
    try:
        with open(LOCAL_STATE_PATH, 'w') as f:
            json.dump(data, f)
    except Exception as e:
        print(f'ローカル保存失敗: {e}')


def get_status_message(mood):
    info = MOOD_MAP.get(mood, MOOD_MAP['普通'])
    status = info['status']
    msg = info['msg']
    today = datetime.date.today().toordinal()
    daily = DAILY_NEWS[today % len(DAILY_NEWS)]
    if mood == 'だるい' or mood == '眠い' or mood == '悲しい':
        tsukkomi = random.choice(NEGA_TSUKKOMI)
    else:
        tsukkomi = ''
    return status, msg, daily, tsukkomi


def show_status():
    mood = get_current_mood()
    status, msg, daily, tsukkomi = get_status_message(mood)
    print(f'[{status}] {msg}')
    print(f'(本日のネタ: {daily})')
    if tsukkomi:
        print(f'(ツッコミ: {tsukkomi})')


def set_status(mood, slack=False):
    set_local_mood(mood)
    os.environ['MOOD'] = mood
    print(f'気分を「{mood}」に設定しました。')
    if slack:
        slack_token = os.environ.get('SLACK_TOKEN')
        if not slack_token:
            print('Slack連携にはSLACK_TOKEN環境変数が必要です。')
            return
        status, msg, _, _ = get_status_message(mood)
        set_slack_status(status, msg, slack_token)


def set_slack_status(status, msg, token):
    profile = {
        'status_text': f'{status}: {msg}',
        'status_emoji': ':speech_balloon:',
        'status_expiration': 0
    }
    url = 'https://slack.com/api/users.profile.set'
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json; charset=utf-8'
    }
    payload = {'profile': profile}
    try:
        r = requests.post(url, headers=headers, json=payload)
        if r.status_code == 200 and r.json().get('ok'):
            print('Slackステータスを更新しました。')
        else:
            print(f'Slack更新失敗: {r.text}')
    except Exception as e:
        print(f'Slack APIエラー: {e}')


def list_moods():
    print('利用可能な気分:')
    for k in MOOD_MAP:
        print(f'  {k}: {MOOD_MAP[k]["status"]} - {MOOD_MAP[k]["msg"]}')


def main():
    parser = argparse.ArgumentParser(description='os-status-mood-light: 気分をOSやSlackに可視化')
    subparsers = parser.add_subparsers(dest='command')

    set_parser = subparsers.add_parser('set', help='気分を設定')
    set_parser.add_argument('--mood', required=True, help='気分(最高, だるい, 普通, 眠い, 怒り, 楽しい, 悲しい)')
    set_parser.add_argument('--slack', action='store_true', help='Slackステータスも更新')

    show_parser = subparsers.add_parser('show', help='現在の気分を表示')
    list_parser = subparsers.add_parser('list', help='利用可能な気分一覧')

    args = parser.parse_args()

    if args.command == 'set':
        mood = args.mood
        if mood not in MOOD_MAP:
            print(f'未定義の気分: {mood}')
            list_moods()
            sys.exit(1)
        set_status(mood, slack=args.slack)
    elif args.command == 'show':
        show_status()
    elif args.command == 'list':
        list_moods()
    else:
        parser.print_help()

if __name__ == '__main__':
    main()

references/design_notes.md

# 概要
os-status-mood-lightは、開発者の気分可視化を目的としたユーティリティです。環境変数やローカルファイル、Slack API等の実在サービス連携を重視して設計しています。

# 公式ドキュメント抜粋
- [Slack Status API](https://api.slack.com/methods/users.profile.set): ユーザーステータスの自動更新に利用。
- [iTerm2 Dynamic Profiles](https://iterm2.com/documentation-dynamic-profiles.html): ステータスバー連携の参考。

# 利用例
- 朝一で `set --mood="最高"` を実行し、Slackやシェルプロンプトに気分を表示。
- 気分が落ち込んだとき `set --mood="だるい" --slack` で周囲に「本日省エネ運転」を通知。
- 定期的に `show` コマンドで自分の気分を確認。

# 注意点
- シェルプロンプト反映はPROMPT_COMMANDや.zshrc編集が別途必要。
- Slack連携はAPIトークン漏洩に注意。
- ローカル保存は~/.os_status_mood_light.jsonに限定。

# 設計方針
- 実在APIのみ利用し、架空のCLIや関数は排除。
- ユーモアと実用性の両立を目指す。
- 拡張性(他サービス連携やカスタム気分追加)を意識。

導入手順

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

1. 前提

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

2. degit でフォルダ取得

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

npx degit aazutaku/ai-note/claude-code/os-status-mood-light .claude/skills/os-status-mood-light

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

3. ファイル配置確認

ls .claude/skills/os-status-mood-light
# SKILL.md, scripts/, references/, README.md があればOK

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

新しいSkillが自動で認識されます。リスト確認したい場合は /os-status-mood-light と Skill 名で出てきます。

5. 動作確認

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

こんな瞬間に便利

  • session 開始時: 前回までの repo 把握を Claude Code に一発で復元させたい
  • monorepo 移動時: packages を跨いだ瞬間に context を切り替えたい
  • onboarding 時: 新しい repo を Claude Code に把握させ、こちらが 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 コードを拾ってしまう可能性
  • Claude Code 固有の引っかかり: paths フロントマターでの絞り込みを使わないと意図しないタイミングで発動する
  • 発動しないケース: description が漠然 / 他の Skill が優先 / git管理外 directory

試す前に確かめたいこと

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

  • 実 repo での token 消費は許容範囲か?
  • monorepo (packages 多数) で安定して動くか?
  • stale context にならず、長時間 workflow でも有効か?
  • CLAUDE.md との連携設計はどうあるべきか?
  • 環境変数変更で即座に表示が切り替わるか?
  • シェルプロンプトやステータスバーへの反映確認は容易か?
  • 日替わりネタやツッコミ文が正しく出るか?

実際に Claude Code で試した検証ログは Claude Codeで気分を即表示!自己主張スキルを触ってみた にまとめる予定 (公開準備中の場合あり)。
あわせて Claude Code 公式ドキュメント と、本シリーズ「Claude Codeを便利にするSkill提案」の他記事も参照のこと。

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

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

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

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