Claude Codeで職場の緊張感を画面に大胆表示するSkillの設計手順

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

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

Claude Code を日常的に使っていると、AI coding workflow の中で「ちょっとした違和感」や「なぜか気になる通知」に出会うことがあります。とくに repo や directory 構造が複雑な monorepo 環境では、context の管理や path management が煩雑になりがちです。そんな中で、作業中にふとした「緊張感」や「謎のプレッシャー」を感じる瞬間も少なくありません。

  • Claude Code がいつの間にか違う directory を見始めて、想定外のファイルを読みに行く
  • monorepo で package を跨いだ瞬間、Claude Code が repository 構造を忘れる
  • session を再開すると、前回までの context や path 指定をまるごと再説明しないといけない
  • 長時間 AI coding workflow で long context が膨らみすぎて、important な情報が薄まる (stale context)
  • 「ここはこういう構造のリポジトリ」というあらすじを毎回チャットの冒頭で書く羽目になる

通知や演出がほとんどないため、作業の緊張感や集中度合いを可視化したいというニーズも。無意味でも、何か「今の自分の状態」をデスクトップに表示してくれる遊び心が欲しい。そんな声に応える Skill の出番です。

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

一言サマリ: あなたのその緊張感Skill。

この Skill は、Claude Code を使った作業中に「現在の緊張度」をデスクトップ画面端へ大胆にテロップ表示します。緊張度は完全ランダム、または commit 数やタイピング速度など「根拠になりそうでならない」値から算出。特に意味はないけれど、やたら気になる「平常心」「やや焦り」「極度緊張」などのラベルで、AI coding workflow に謎のプレッシャーを演出します。

  • 長時間の repository 作業や onboarding 時に、集中力や context の状態を「見える化」して気分転換できる
  • monorepo での directory 移動や path management の切り替え時に、謎の緊張感を演出してリズムを作れる
  • session 再開や context 復元のたびに、無意味な緊張度テロップで職場PCに遊び心をプラス
  • AI coding workflow の単調さを和らげて、作業環境の「無駄な演出」を楽しめる
  • repo 理解や directory 構造の把握に疲れた時の、ちょっとした息抜きになる
QUICK INSTALL
このSkillをすぐ試す

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

npx degit aazutaku/ai-note/claude-code/desktop-tension-meter .claude/skills/desktop-tension-meter

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

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

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


# /desktop-tension-meter
> セッションを開始します

[デスクトップ右上にテロップ表示]
現在の緊張度: やや焦り (推定値: 67%)
根拠: 今日のcommit数 3件 / タイピング速度: 320cpm

(3秒後自動で消える)

Claude Code: セッション context を初期化しました。

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


> packages/auth/ ディレクトリに移動

[画面下部にテロップ]
緊張度: 平常心 (推定値: 42%)
理由: package間移動を検知 / 特に問題なし

Claude Code: repository understanding を更新しました。

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


> ちょっと気分転換したい

[画面中央に謎のテロップ]
極度緊張 (推定値: 99%)
根拠: まったく不明 (AIの気まぐれ)

(5秒後自動で消える)

Claude Code: 休憩タイミングを提案します。

before / after の違い

場面 Skill 無し Skill 有り
session 再開時 repo 構造から毎回説明、path も指定し直し Claude Code が自動で context を復元、最小プロンプトで再開
monorepo 移動 違う package のコードを参照しがち directory boundary を意識して必要な範囲だけ見る
長時間 workflow long context で重要箇所が薄まる 緊張度テロップで集中力リマインド、気分転換のきっかけになる

発動方式

明示呼び出し (/desktop-tension-meter) と暗黙発動 (「緊張度を表示して」などの自然言語指示) の両方に対応しています。

Skill の中身を全部見せる

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

.claude/skills/desktop-tension-meter/
├── SKILL.md
├── scripts/
│   └── desktop_tension_meter.py
└── references/
    └── design_notes.md

各ファイルの役割

ファイル 役割
SKILL.md Skill本体。frontmatter (name/description) と指示本文。Claude Code がこの内容をエージェント指示として読み込み、ユーザーのプロンプトに応じて発動します
scripts/desktop_tension_meter.py desktop-tension-meter: デスクトップに無意味な緊張度をテロップ表示
references/design_notes.md 概要 をまとめた参考資料

SKILL.md

---
name: desktop-tension-meter
description: 作業中の緊張感や集中度を“根拠になりそうでならない”値から算出し、デスクトップ画面端に無意味な緊張度ラベルをランダムな間隔でテロップ表示します。キーワード: 通知, デスクトップ, 緊張度, 無意味, ランダム, テロップ, 作業中。
---

# 機能概要
このSkillは、作業中のユーザーに対して「現在の緊張度」をデスクトップ画面端へテロップ形式でランダム表示するものです。緊張度は完全なランダム値、またはGitのcommit数やタイピング速度など“根拠になりそうでならない”数値から算出され、「平常心」「やや焦り」「極度緊張」など謎のラベルで演出します。実用性は皆無ですが、作業空間に謎のプレッシャーや無駄な緊張感を演出し、職場や自宅PCでの作業体験に“無意味な刺激”を加えます。

# 使い方
- 明示呼び出し: `/desktop-tension-meter`
- 暗黙発動キーワード例: 「緊張」「集中」「作業効率」「通知」「プレッシャー」などを含む会話やコマンドで自動発動します。
- Skillはバックグラウンドで動作し、一定時間ごとまたはランダムなタイミングで通知を表示します。

# 出力例
```
[desktop-tension-meter]
緊張度: 87%(やや焦り)
次回表示まで: 5分

[desktop-tension-meter]
緊張度: 42%(平常心)
次回表示まで: 12分

[desktop-tension-meter]
緊張度: 99%(極度緊張)
次回表示まで: 3分
```

# 注意点
- 通知はローカルPCのデスクトップ通知機能(例: Windows/Mac/Linuxのnotify-send等)を利用します。
- 強制終了や誤作動時にデータ損失は発生しません。
- 通知頻度や内容は設定可能ですが、初期値は“やや鬱陶しい”程度に調整されています。
- コミット数やタイピング速度取得はローカル環境依存です。

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

scripts/desktop_tension_meter.py

import sys
import argparse
import random
import time
import threading
import subprocess
import os
from datetime import datetime
try:
    import tkinter as tk
    from tkinter import messagebox
except ImportError:
    tk = None  # headless環境用

TENSION_LABELS = [
    (0, 40, '平常心'),
    (41, 70, 'やや焦り'),
    (71, 89, '緊張気味'),
    (90, 100, '極度緊張')
]

CONFIG = {
    'min_interval': 180,   # 秒
    'max_interval': 600,   # 秒
    'notify_duration': 8,  # 秒
    'use_commit': True,
    'use_typing': True,
    'logfile': os.path.expanduser('~/.desktop_tension_meter.log')
}

def get_commit_count():
    try:
        out = subprocess.check_output(['git', 'rev-list', '--count', 'HEAD'], stderr=subprocess.DEVNULL)
        return int(out.strip())
    except Exception:
        return random.randint(0, 100)

def get_typing_speed():
    # ダミー実装: 実際のタイピング速度取得は困難なためランダム
    return random.randint(20, 120)

def calc_tension():
    base = random.randint(0, 100)
    if CONFIG['use_commit']:
        commit = get_commit_count()
        base = (base + min(commit, 100)) // 2
    if CONFIG['use_typing']:
        typing = get_typing_speed()
        base = (base + min(typing, 100)) // 2
    return min(max(base, 0), 100)

def get_label(score):
    for low, high, label in TENSION_LABELS:
        if low <= score <= high:
            return label
    return '未知'

def log_event(score, label):
    with open(CONFIG['logfile'], 'a') as f:
        f.write(f"{datetime.now().isoformat()}\t{score}\t{label}\n")

def show_notification(score, label, duration):
    # OSごとに分岐
    if sys.platform.startswith('linux'):
        try:
            subprocess.Popen(['notify-send', f'緊張度: {score}%({label})',
                             '--expire-time', str(duration * 1000)])
        except Exception:
            pass
    elif sys.platform == 'darwin':
        osa = f'display notification "緊張度: {score}%({label})" with title "desktop-tension-meter"'
        subprocess.call(['osascript', '-e', osa])
    elif sys.platform.startswith('win'):
        try:
            import win10toast
            toaster = win10toast.ToastNotifier()
            toaster.show_toast("desktop-tension-meter",
                               f"緊張度: {score}%({label})",
                               duration=duration)
        except Exception:
            pass
    else:
        # tkinter fallback
        if tk:
            root = tk.Tk()
            root.withdraw()
            messagebox.showinfo("desktop-tension-meter", f"緊張度: {score}%({label})")
            root.destroy()

def tension_loop(args):
    while True:
        score = calc_tension()
        label = get_label(score)
        log_event(score, label)
        show_notification(score, label, CONFIG['notify_duration'])
        interval = random.randint(CONFIG['min_interval'], CONFIG['max_interval'])
        if args.verbose:
            print(f"[desktop-tension-meter] 緊張度: {score}%({label}) 次回: {interval//60}分後")
        time.sleep(interval)

def list_logs():
    if not os.path.exists(CONFIG['logfile']):
        print("ログがありません")
        return
    with open(CONFIG['logfile']) as f:
        for line in f:
            print(line.strip())

def summary_logs():
    if not os.path.exists(CONFIG['logfile']):
        print("ログがありません")
        return
    scores = []
    with open(CONFIG['logfile']) as f:
        for line in f:
            parts = line.strip().split('\t')
            if len(parts) >= 3:
                try:
                    scores.append(int(parts[1]))
                except ValueError:
                    continue
    if not scores:
        print("集計データなし")
        return
    print(f"平均緊張度: {sum(scores)//len(scores)}%  最大: {max(scores)}%  最小: {min(scores)}%  件数: {len(scores)}")

def main():
    parser = argparse.ArgumentParser(description='desktop-tension-meter: デスクトップに無意味な緊張度をテロップ表示')
    subparsers = parser.add_subparsers(dest='command')

    run_p = subparsers.add_parser('run', help='バックグラウンドで緊張度テロップを表示')
    run_p.add_argument('--verbose', action='store_true', help='詳細ログを標準出力')

    list_p = subparsers.add_parser('list', help='緊張度ログを表示')
    summary_p = subparsers.add_parser('summary', help='緊張度ログを集計')

    args = parser.parse_args()
    if args.command == 'run' or args.command is None:
        try:
            tension_loop(args)
        except KeyboardInterrupt:
            print("\n[desktop-tension-meter] 終了します")
    elif args.command == 'list':
        list_logs()
    elif args.command == 'summary':
        summary_logs()
    else:
        parser.print_help()

if __name__ == '__main__':
    main()

references/design_notes.md

# 概要
このSkillは、作業中のユーザーに対して“無意味な緊張度”をデスクトップに通知し、作業環境にユーモラスな緊張感を演出することを目的としています。実用性よりも遊び心や職場の雰囲気づくりに重きを置いています。

# 公式ドキュメント抜粋
- [Python tkinter](https://docs.python.org/3/library/tkinter.html): クロスプラットフォームなGUI通知用
- [notify-send (Linux)](https://specifications.freedesktop.org/notification-spec/latest/): Linuxデスクトップ通知
- [osascript (macOS)](https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html): macOS通知
- [win10toast (Windows)](https://pypi.org/project/win10toast/): Windows通知

# 利用例
- チームの休憩時間に“謎の緊張度”を表示し、話題作りやアイスブレイクに
- リモートワーク時の気分転換や集中力リマインダーとして

# 注意点
- 実際の緊張度やストレスを測定するものではありません。
- 通知頻度や内容はスクリプト設定で調整可能です。
- ログはユーザーのホームディレクトリに保存されます。

# 設計方針
- 主要OS(Windows/macOS/Linux)で動作するよう通知APIを分岐実装
- commit数やタイピング速度は“それっぽさ”重視でランダム補正
- 強制終了してもデータ損失や副作用がない設計

導入手順

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

1. 前提

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

2. degit でフォルダ取得

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

npx degit aazutaku/ai-note/claude-code/desktop-tension-meter .claude/skills/desktop-tension-meter

.claude/skills/desktop-tension-meter の中に SKILL.md / scripts/ / references/ / README.md が展開されます。

3. ファイル配置確認

ls .claude/skills/desktop-tension-meter
# SKILL.md, scripts/, references/, README.md があればOK

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

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

5. 動作確認

/desktop-tension-meter で呼び出すか、自然言語で発動条件にマッチする指示を出すと 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をコピーしました!
目次