Codexで緊張度を画面に自動表示する演出の使いこなし術

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

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

Codex を日々使い倒していると、AI coding workflow の中で「なんだか気が抜けない」「常に誰かに見られているような妙な緊張感」を感じる瞬間がある。特に context 管理や repository understanding、path management の場面では、ちょっとした気の緩みが思わぬコードミスや context の取り違えにつながりがちだ。そんなとき、ふと「今の自分、どれくらい緊張してる?」と自覚するきっかけがあれば…と感じたことはないだろうか。

また、長時間の作業や monorepo での package 跨ぎ、directory 構造の把握で集中力が切れそうになるとき、何かしら外部からの「謎のプレッシャー」や「無意味な演出」が欲しくなることも。職場PCの画面端に、意味はないけどやたら目につくテロップが流れていたら、思わず気が引き締まる…そんな無駄な演出を求めてしまうのも、エンジニアあるあるだ。

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

こうした日常の「緊張感」と「無駄な演出欲」を両立して満たす通知・演出系 Skill が、Codex の context 管理や repository understanding の合間に、ちょっとしたスパイスを加えてくれる。

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

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

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

  • 作業中ランダムなタイミングで「現在の緊張度」がデスクトップにテロップ表示され、集中力や workflow の切り替えタイミングを自然に意識できる
  • commit数やタイピング速度など、repoやdirectoryのcontextに“根拠がありそうでない”演出が加わり、AI coding workflow のリズムが生まれる
  • 長時間 session や monorepo作業時に気分転換やリフレッシュのきっかけとして役立つ
  • onboarding や新しい repository での作業開始時に、緊張感を演出しつつ自然な context 切り替えを促進
  • 「今この瞬間、なぜか気になる」無意味な表示が、記憶や作業のフックになり、記憶定着や気分転換にも寄与
QUICK INSTALL
このSkillをすぐ試す

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

npx degit aazutaku/ai-note/codex/desktop-tension-meter .agents/skills/desktop-tension-meter

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

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

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


# /skills menu
> desktop-tension-meter

[デスクトップ画面右下にテロップ]
現在の緊張度: 極度緊張
(根拠: 今日のcommit数 0、session開始直後)
-----------------------------------------
ヒント: 平常心を保ちましょう

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


> move to packages/api
> edit src/handler.ts

[画面左上にテロップ]
現在の緊張度: やや焦り
(根拠: packages/api で直近10分にファイル3回切替)
-----------------------------------------
ヒント: directory 構造を再確認しましょう

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


> 今日はタイピング速度が速い気がする

[画面中央上にテロップ]
現在の緊張度: 平常心
(根拠: 直近タイピング速度 42wpm、平均値)
-----------------------------------------
ヒント: その調子です!

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

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

各ファイルの役割

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

SKILL.md

---
name: desktop-tension-meter
description: 作業中のユーザーに対し、commit数やタイピング速度などの“根拠になりそうでならない”値や完全ランダムで緊張度を算出し、一定間隔でデスクトップにテロップ表示する。トリガーワード: 緊張, プレッシャー, テロップ, デスクトップ通知, 無意味な演出。
---

# 機能概要
このSkillは、作業中のデスクトップに「現在の緊張度」をテロップとしてランダムなタイミングで表示します。緊張度は、commit数やタイピング速度など“根拠になりそうでならない”値や完全ランダムから算出され、「平常心」「やや焦り」「極度緊張」などの謎ラベルで演出。実用性は皆無ですが、無意味なプレッシャーや職場の雰囲気を盛り上げる無駄な演出を提供します。

# 使い方
- 明示呼び出し: `/skills menu` から「desktop-tension-meter」を選択、または `$desktop-tension-meter` と入力
- 暗黙発動キーワード: 「緊張」「プレッシャー」「テロップ」「デスクトップ通知」などを含む会話やコマンド

# 出力例
```
[14:23:10] 緊張度: やや焦り (推定値: 57)
[14:31:04] 緊張度: 平常心 (推定値: 22)
[14:42:55] 緊張度: 極度緊張 (推定値: 91)
[14:57:13] 緊張度: 平常心 (推定値: 18)
[15:10:21] 緊張度: やや焦り (推定値: 48)
```
デスクトップ画面端に上記のようなテロップが5-10秒表示されます。

# 注意点
- 緊張度は実用的な測定値ではなく、完全なジョークです。
- 通知が鬱陶しい場合はスクリプトを停止してください。
- ローカルPC上でのみ動作し、データ保存や外部送信は行いません。
- 強制終了してもデータ損失はありません。

# 参考資料
- references/design_notes.md に設計方針・参考APIを記載
- 公式: [Tkinter](https://docs.python.org/ja/3/library/tkinter.html), [psutil](https://psutil.readthedocs.io/ja/latest/), [keyboard](https://github.com/boppreh/keyboard)

scripts/desktop_tension_meter.py

import sys
import time
import random
import threading
import argparse
from datetime import datetime
try:
    import tkinter as tk
    import psutil
    import keyboard
except ImportError as e:
    print(f"必要なモジュールが見つかりません: {e}\n pip install psutil keyboard")
    sys.exit(1)

TENSION_LABELS = [
    (0, 30, "平常心"),
    (31, 60, "やや焦り"),
    (61, 80, "高まる緊張"),
    (81, 100, "極度緊張")
]

LOG_FILE = "tension_meter.log"

class TypingSpeedMonitor:
    def __init__(self):
        self.count = 0
        self.last_reset = time.time()
        self.lock = threading.Lock()
        keyboard.on_press(self._on_key)

    def _on_key(self, e):
        with self.lock:
            self.count += 1

    def get_speed(self):
        now = time.time()
        with self.lock:
            elapsed = now - self.last_reset
            speed = self.count / elapsed * 60 if elapsed > 0 else 0
            self.count = 0
            self.last_reset = now
        return speed

class DesktopTensionMeter:
    def __init__(self, interval_min=300, interval_max=600, duration=6):
        self.interval_min = interval_min
        self.interval_max = interval_max
        self.duration = duration
        self._stop = threading.Event()
        self.typing_monitor = TypingSpeedMonitor()

    def _get_commit_count(self):
        # git log --since=1.hour --pretty=oneline | wc -l
        try:
            import subprocess
            out = subprocess.check_output([
                'git', 'log', '--since=1.hour', '--pretty=oneline'
            ], stderr=subprocess.DEVNULL)
            return len(out.decode().splitlines())
        except Exception:
            return random.randint(0, 5)

    def _calc_tension(self):
        base = random.randint(0, 100)
        typing_speed = min(int(self.typing_monitor.get_speed()), 100)
        commit_count = self._get_commit_count()
        # 根拠になりそうでならない計算
        tension = int(0.4 * base + 0.3 * typing_speed + 0.3 * commit_count * 10)
        tension = max(0, min(100, tension))
        for low, high, label in TENSION_LABELS:
            if low <= tension <= high:
                return tension, label
        return tension, "未知"

    def _show_teletext(self, tension, label):
        root = tk.Tk()
        root.overrideredirect(True)
        root.attributes('-topmost', True)
        root.attributes('-alpha', 0.85)
        screen_w = root.winfo_screenwidth()
        screen_h = root.winfo_screenheight()
        width, height = 420, 60
        x = screen_w - width - 20
        y = screen_h - height - 60
        root.geometry(f"{width}x{height}+{x}+{y}")
        frame = tk.Frame(root, bg='#222', bd=2)
        frame.pack(fill=tk.BOTH, expand=True)
        msg = f"緊張度: {label} (推定値: {tension})"
        label_widget = tk.Label(frame, text=msg, font=("Meiryo", 20, "bold"), fg="#fff", bg="#222")
        label_widget.pack(expand=True)
        def close():
            root.destroy()
        root.after(self.duration * 1000, close)
        root.mainloop()

    def _log(self, tension, label):
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        with open(LOG_FILE, "a", encoding="utf-8") as f:
            f.write(f"[{timestamp}] 緊張度: {label} (推定値: {tension})\n")

    def run(self):
        print("desktop-tension-meter: テロップ表示を開始します。Ctrl+Cで終了。")
        try:
            while not self._stop.is_set():
                tension, label = self._calc_tension()
                self._log(tension, label)
                t = threading.Thread(target=self._show_teletext, args=(tension, label))
                t.daemon = True
                t.start()
                interval = random.randint(self.interval_min, self.interval_max)
                for _ in range(interval):
                    if self._stop.is_set():
                        break
                    time.sleep(1)
        except KeyboardInterrupt:
            print("\n終了します。")
            self._stop.set()

    def stop(self):
        self._stop.set()

    def show_log(self, lines=10):
        try:
            with open(LOG_FILE, encoding="utf-8") as f:
                logs = f.readlines()[-lines:]
            for line in logs:
                print(line.strip())
        except Exception:
            print("ログが見つかりません。")

    def summary(self):
        try:
            with open(LOG_FILE, encoding="utf-8") as f:
                logs = f.readlines()
            counts = {}
            for line in logs:
                for _, _, label in TENSION_LABELS:
                    if label in line:
                        counts[label] = counts.get(label, 0) + 1
            print("緊張度ラベル別出現回数:")
            for label in [l for _, _, l in TENSION_LABELS]:
                print(f"{label}: {counts.get(label, 0)}回")
        except Exception:
            print("ログが見つかりません。")

def main():
    parser = argparse.ArgumentParser(description="desktop-tension-meter: 意味のない緊張度テロップをデスクトップに表示")
    sub = parser.add_subparsers(dest="command")
    run_p = sub.add_parser("run", help="テロップ表示を開始")
    run_p.add_argument("--min", type=int, default=300, help="最短間隔(秒)")
    run_p.add_argument("--max", type=int, default=600, help="最長間隔(秒)")
    run_p.add_argument("--duration", type=int, default=6, help="テロップ表示秒数")
    log_p = sub.add_parser("log", help="直近の緊張度ログを表示")
    log_p.add_argument("--lines", type=int, default=10, help="表示行数")
    sub.add_parser("summary", help="緊張度ラベル別出現回数を集計")
    args = parser.parse_args()
    meter = DesktopTensionMeter()
    if args.command == "run":
        meter = DesktopTensionMeter(args.min, args.max, args.duration)
        meter.run()
    elif args.command == "log":
        meter.show_log(args.lines)
    elif args.command == "summary":
        meter.summary()
    else:
        parser.print_help()

if __name__ == '__main__':
    main()

references/design_notes.md

# 概要
このSkillは、デスクトップ上に無意味な「緊張度」テロップを表示し、作業環境に謎のプレッシャーを演出するために設計されています。実用性よりも、職場や個人のPCでの“無駄な演出”を重視しています。

# 公式ドキュメント抜粋
- [Tkinter](https://docs.python.org/ja/3/library/tkinter.html): Python標準GUIで、OS間の互換性が高く、手軽にウィンドウ表示が可能
- [psutil](https://psutil.readthedocs.io/ja/latest/): システムリソース取得用(拡張性のため)
- [keyboard](https://github.com/boppreh/keyboard): タイピング速度計測に利用

# 利用例
- チーム内のネタとして、会議や作業時間に“緊張度”を可視化
- 個人の集中力維持や、気分転換のためのジョークツール

# 設計方針
- テロップは画面端に短時間のみ表示し、鬱陶しさを抑制
- 緊張度算出は完全ランダムまたは“根拠になりそうでならない”値を組み合わせ
- ログはローカルファイルのみ、外部送信なし

# 注意点
- 実際の心理状態や生産性とは無関係です
- 通知頻度はパラメータで調整可能
- 強制終了時もデータ損失はありません

導入手順

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

1. 前提

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

2. degit でフォルダ取得

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

npx degit aazutaku/ai-note/codex/desktop-tension-meter .agents/skills/desktop-tension-meter

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

3. ファイル配置確認

ls .agents/skills/desktop-tension-meter
# 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 との連携設計はどうあるべきか?
  • 無意味な緊張度ラベルが一定間隔でデスクトップに表示されるか
  • 強制終了や誤作動時にデータ損失が発生しないか
  • 通知が鬱陶しすぎない間隔・演出になっているか

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

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

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

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

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