Codex ユーザーが日常でぶつかる悩み
開発現場でPull Requestのコメントを書くとき、どうしても形式的・事務的なやりとりに終始しがちです。たまには場の空気を和ませたいのに、コメントに遊び心を出す余裕もなく、無機質なやりとりが続いてしまうことも多いはず。Codexを使っていると、特に以下のような悩みが生じます。
- PRコメントが毎回「確認しました」「修正お願いします」など定型句になり、やりとりが味気ない
- レビューが白熱しはじめると、空気がピリついてしまうが、場を和ませるきっかけが作りづらい
- 新メンバーやオンボーディング時、ちょっとしたジョークやパロディで雰囲気をほぐしたいが、手間がかかる
- CodexのAI coding workflow中、contextやrepository understandingに集中するあまり、コミュニケーションが機械的になる
- 長時間のPRレビューでコメントが大量に溜まり、どれも似たようなトーンで読んでいて疲れる
「たまには笑いがほしい」「開発チームに遊び心を持ち込みたい」そんな願いを叶えるSkillが求められています。
この Skill が一言でいうと何を解決するか
一言サマリ: このスキルは、PRコメントを忍者口調に自動変換し、開発現場にエンタメ要素をもたらすSkill。
もう少し具体化すると、このSkillを入れることで以下のような状態になる:
- PRコメントが一瞬で「忍者ワールド」に変換され、堅苦しいやりとりが一気に和やかになる
- CodexによるAI coding workflowの中で、contextやrepoの議論も含め、遊び心あるコミュニケーションが簡単に実現
- オンボーディングや長時間レビューでも、コメント欄が盛り上がり、チームの一体感が高まる
- 手動で変換する手間が不要で、どんな文章も即座に忍者パロディ化できる
- Skillの導入・発動がシンプルで、既存のPRコメントにも簡単に適用可能
GitHub から degit でコマンド1行、Codex の Skill ディレクトリに展開できます。Node.js があれば即時に動きます。
npx degit aazutaku/ai-note/codex/pr-comment-ninja-translator .agents/skills/pr-comment-ninja-translator実行したらこうなる (3つの利用シーン)
使う側がイメージしやすいよう、擬似 terminal で出力例を3パターン示す。Skill が返す出力は推測だが、現実的なフォーマット・現実的な長さで書く。
シーン1: session 開始時 (プロジェクト初動で)
# /skills menu
> PRコメントを忍者口調にしてほしい
Codex:
拙者、PRコメントを忍者の如く変換する術を発動いたす。
「この関数は冗長なので、リファクタリングをお願いしたいでござる」
→「拙者思うに、この関数、影のように身軽にでき申す。リファクタリングの術をお願い仕る!」
「テストが落ちております」
→「ござる…テストの術、失敗の兆し。再度ご確認願いたし!」
「READMEのtypoを修正しました」
→「READMEの誤字、密かに修正仕った。ご査収くだされ!」
シーン2: monorepo / package 跨ぎ作業時
> packages/api/src/user.ts のコメントを忍者口調に
Codex:
「ユーザーIDのバリデーションが抜けているようです」
→「拙者、user.tsにて術を見破った。ユーザーIDの見張り、抜けておるようにござる!」
「packages/web/components/Header.tsx のロジックが複雑です」
→「Header.tsxの忍法、少々複雑の術…影のごとく簡素にでき申すか?」
「共通utilsのimportパスを修正しました」
→「共通utils、密かにimportの術を修正仕った。ご確認願いたし!」
シーン3: お遊び的な使い方
> 今日はレビューが多くて疲れました
Codex:
「本日、レビュー多き戦いにて拙者、少々疲労の術…皆々も無理なさらぬよう!」
> このバグ、なかなか手強いですね
Codex:
「ござる…このバグ、忍法でも手強き敵。皆で力を合わせて討ち取るでござる!」
> 明日のデプロイ、よろしくお願いします
Codex:
「明日のデプロイ、影のごとく見守り申す。何卒、よろしくお願い仕る!」
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/pr-comment-ninja-translator/ に配置するファイル一覧です。GitHub に push 済みなので、上記の degit コマンドで一発取得できます。
.agents/skills/pr-comment-ninja-translator/
├── SKILL.md
├── scripts/
│ └── ninja_translator.py
└── references/
└── design_notes.md
各ファイルの役割
| ファイル | 役割 |
|---|---|
SKILL.md |
Skill本体。frontmatter (name/description) と指示本文。Codex がこの内容をエージェント指示として読み込み、ユーザーのプロンプトに応じて発動します |
scripts/ninja_translator.py |
PRコメントを忍者口調に変換するツール |
references/design_notes.md |
概要 をまとめた参考資料 |
SKILL.md
---
name: pr-comment-ninja-translator
description: Pull Requestのコメントやレビュー文に「忍者口調」変換を適用したい場合、または/skillsコマンドやpr-comment-ninja-translatorの明示呼び出しがあった際に発動します。忍者語変換・ジョーク・雰囲気緩和などのキーワードが含まれる場合も自動で発動します。
---
# 機能概要
このSkillは、Pull Request(PR)のコメントやレビュー文を“忍者口調”に自動変換し、GitHub等のPRコメントとして投稿できるエンタメ系ツールです。普段は堅苦しくなりがちな開発現場のやり取りを、忍者の世界観で一気に和ませます。例えば「この変数名は分かりづらいです」を「拙者思うに、この変数名、影の如く分かりづらいでござる…」と変換。真剣な議論も、伊賀甲賀の忍法合戦に早変わり。
# 使い方
- 明示呼び出し: `/skills pr-comment-ninja-translator` または `@codex pr-comment-ninja-translator 変換して` のように記述。
- 暗黙発動: 「忍者語」「忍者口調」「ジョーク」「和ませたい」「忍法」などのキーワードがPRコメントに含まれる場合、自動で発動します。
- 変換対象のテキストを直接指定するか、既存PRコメントのID/URLを指定して変換可能です。
# 出力例
```
原文: この関数はバグがあります。修正してください。
忍者口調: 拙者が見たところ、この術式にはバグの気配…修正の術、お願い申す!
原文: テストケースが不足しています。
忍者口調: ござる…テストの術が足りぬと見受けられる!
原文: 変数名をもっと明確にしましょう。
忍者口調: 拙者思うに、この変数名、もっと明快にするのが良きでござろう!
```
# 注意点
- 忍者口調への変換は日本語限定です。英語や他言語には未対応。
- 元文の意味が大きく損なわれる場合があります。正式なレビュー用途には注意。
- ローカルに変換履歴は保存されません。必要なら別途ログ出力を有効化してください。
- GitHub API等でPRコメント投稿時は認証情報が必要です。
# 参考資料
- references/design_notes.md
- [GitHub REST API v3](https://docs.github.com/ja/rest)
scripts/ninja_translator.py
import argparse
import sys
import re
import requests
from typing import List, Optional
NINJA_PREFIXES = [
"拙者思うに、",
"ござる…",
"忍法、",
"影の如く、",
"お主、",
"これは…",
"うむ、",
"ふむ、",
"この術式、",
"忍びの心得として、"
]
NINJA_SUFFIXES = [
"でござる。",
"の術!",
"と見受けられる!",
"お願い申す!",
"よろしいか?",
"拙者も同意でござる。",
"…かもしれぬ。",
"…と申す!",
"…でござろう!",
"…御免!"
]
NINJA_WORDS = [
(r"バグ", "バグの術"),
(r"関数", "術式"),
(r"変数", "変数(影)"),
(r"修正", "修正の術"),
(r"テスト", "テストの術"),
(r"不足", "足りぬ"),
(r"明確", "明快"),
(r"問題", "難儀"),
(r"確認", "見極め"),
(r"必要", "必須の術"),
(r"追加", "加えるの術"),
(r"削除", "消すの術"),
(r"改善", "改良の術")
]
def ninja_translate(text: str) -> str:
lines = text.strip().splitlines()
result = []
for line in lines:
orig = line.strip()
if not orig:
result.append("")
continue
# 変換
ninja_line = orig
for pat, rep in NINJA_WORDS:
ninja_line = re.sub(pat, rep, ninja_line)
# プレフィックスとサフィックスを適当に付加
prefix = NINJA_PREFIXES[hash(ninja_line) % len(NINJA_PREFIXES)]
suffix = NINJA_SUFFIXES[hash(orig) % len(NINJA_SUFFIXES)]
# 既に忍者語ならスキップ
if any(w in ninja_line for w in ["でござる", "術", "拙者", "ござる…"]):
result.append(ninja_line)
else:
# 文章の長さや終止形に応じて調整
if ninja_line.endswith("。"):
ninja_line = ninja_line[:-1]
ninja_line = f"{prefix}{ninja_line}{suffix}"
result.append(ninja_line)
return "\n".join(result)
def fetch_github_comment(token: str, repo: str, comment_id: int) -> Optional[str]:
url = f"https://api.github.com/repos/{repo}/pulls/comments/{comment_id}"
headers = {"Authorization": f"token {token}"}
resp = requests.get(url, headers=headers)
if resp.status_code == 200:
return resp.json().get("body", "")
else:
print(f"GitHub API error: {resp.status_code} {resp.text}", file=sys.stderr)
return None
def post_github_comment(token: str, repo: str, pr_number: int, body: str):
url = f"https://api.github.com/repos/{repo}/issues/{pr_number}/comments"
headers = {"Authorization": f"token {token}", "Accept": "application/vnd.github+json"}
resp = requests.post(url, headers=headers, json={"body": body})
if resp.status_code == 201:
print("コメント投稿成功!")
else:
print(f"投稿失敗: {resp.status_code} {resp.text}", file=sys.stderr)
def main():
parser = argparse.ArgumentParser(description="PRコメントを忍者口調に変換するツール")
subparsers = parser.add_subparsers(dest="command")
# translateコマンド
p_trans = subparsers.add_parser("translate", help="テキストを忍者口調に変換")
p_trans.add_argument("--text", type=str, help="変換するテキスト")
p_trans.add_argument("--infile", type=str, help="テキストファイルから入力")
p_trans.add_argument("--outfile", type=str, help="変換結果をファイル出力")
# github-fetchコマンド
p_fetch = subparsers.add_parser("github-fetch", help="GitHub PRコメントを取得して変換")
p_fetch.add_argument("--token", type=str, required=True, help="GitHubアクセストークン")
p_fetch.add_argument("--repo", type=str, required=True, help="リポジトリ名 (user/repo)")
p_fetch.add_argument("--comment-id", type=int, required=True, help="PRコメントID")
p_fetch.add_argument("--post", action="store_true", help="変換後にPRへコメント投稿")
p_fetch.add_argument("--pr-number", type=int, help="コメント投稿先PR番号")
args = parser.parse_args()
if args.command == "translate":
if args.text:
input_text = args.text
elif args.infile:
try:
with open(args.infile, encoding="utf-8") as f:
input_text = f.read()
except Exception as e:
print(f"ファイル読み込み失敗: {e}", file=sys.stderr)
sys.exit(1)
else:
print("--text か --infile を指定してください", file=sys.stderr)
sys.exit(1)
result = ninja_translate(input_text)
if args.outfile:
with open(args.outfile, "w", encoding="utf-8") as f:
f.write(result)
else:
print(result)
elif args.command == "github-fetch":
comment = fetch_github_comment(args.token, args.repo, args.comment_id)
if comment is None:
sys.exit(1)
result = ninja_translate(comment)
print("---- 変換結果 ----")
print(result)
if args.post:
if not args.pr_number:
print("--pr-number を指定してください", file=sys.stderr)
sys.exit(1)
post_github_comment(args.token, args.repo, args.pr_number, result)
else:
parser.print_help()
if __name__ == "__main__":
main()
references/design_notes.md
# 概要
このSkillは、PRコメントやレビュー文を忍者口調に変換し、開発現場の雰囲気を和ませるためのジョーク系ツールです。GitHub APIを用いて既存コメントの取得・投稿にも対応しています。
# 公式ドキュメント抜粋
- [GitHub REST API v3](https://docs.github.com/ja/rest) の `/pulls/comments/{comment_id}` および `/issues/{issue_number}/comments` を利用。
# 利用例
- PRで「この関数はバグがあります」と書かれたコメントを忍者口調に変換し、再投稿。
- チームの雰囲気を和ませたい時に/skillsコマンドで明示呼び出し。
# 注意点
- 日本語以外の文には未対応。
- 意味が大きく変わる場合や、正式なレビューには利用を控えること。
- GitHub API利用時はアクセストークン管理に注意。
# 設計方針
- 変換は単純な置換+忍者語テンプレートで構成。
- コマンドラインからの柔軟な利用を想定し、ファイル入出力やAPI連携も可能とした。
導入手順
このSkillは GitHub で管理されているので、degit を使えば必要なフォルダだけを1コマンドで取得できます。Codex はファイル配置後に再起動するだけで自動認識します。
1. 前提
- Node.js v16 以上 (
degit実行に必要) - Codex がローカルで動いていること
2. degit でフォルダ取得
プロジェクトのルートで以下のコマンドを実行します。
npx degit aazutaku/ai-note/codex/pr-comment-ninja-translator .agents/skills/pr-comment-ninja-translator
.agents/skills/pr-comment-ninja-translator の中に SKILL.md / scripts/ / references/ / README.md が展開されます。
3. ファイル配置確認
ls .agents/skills/pr-comment-ninja-translator
# 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 との連携設計はどうあるべきか?
- どんな文章も忍者口調へ面白く変換されるか?
- 既存PRコメントへの適用が簡単か?
- 原文の意味が極端に失われないか?
実際に Codex で試した検証ログは Codexで忍者口調に変換してPRコメントを盛り上げてみた! にまとめる予定 (公開準備中の場合あり)。
あわせて Codex 公式ドキュメント と、本シリーズ「Codexを使いこなすSkillアイデア」の他記事も参照のこと。
関連タグで他のSkill記事を探す
本記事に付いているタグから、気になるテーマの記事を探せます。タグページで関連記事をまとめて読めるので、ぜひチェックしてみてください!
