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 切り替えを促進
- 「今この瞬間、なぜか気になる」無意味な表示が、記憶や作業のフックになり、記憶定着や気分転換にも寄与
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記事を探す
本記事に付いているタグから、気になるテーマの記事を探せます。タグページで関連記事をまとめて読めるので、ぜひチェックしてみてください!
