お雑煮研究会

好きな焼肉は魚

電気通信大学 情報理工学域を卒業しました

表題の通りですが、電気通信大学 情報理工学域を卒業しました。 私は大学院に進学しないので、今日から社会人です。今日から...?

卒業エントリと言うと大層ですが、大学生活の軽いまとめとかをメモしておきたいと思います。


健康

詳しくは昔の記事にまとめてありますが、大学生活最初の半年は過敏性腸症候群の悪化により家からまともに出られず、単位をほぼすべて落としたという苦い思い出があります。 なんとか 3 年次中にすべての単位を取り終わることができましたが、常に余裕がなくプレッシャーがかかり続ける生活でした。

sushichan.live

過敏性腸症候群という病気は本当に厄介で、症状が精神状態によって悪化することがあります。 もし新生活のストレスで下痢が止まらない・腹痛により何度も電車を降りざるを得ないという方がいらっしゃいましたら、できるだけ早く検査を受けて社会的なハンデを負う前に診断書を取得されることをおすすめします。

全体的にストレスが多いと体調は悪くなるものなので、ストレスを貯めないように頑張っていきたいと思います。

学業

1 / 2 年次はパソコンというよりは数学や物理を永遠にやる生活だったので、結構苦行でした。 基礎科学実験 A とか謁見とかで検索すれば電通大生の嘆きを多数目にすることができるのでここでは省略しますが、あれは本当に大変です。

3 年次からパソコンのことも結構増えてくるので、楽しく受けられる講義が多かったです。特に言語処理系という講義は最高で、言語処理系を支える基礎的な理論などがじっくり解説されるので関連する書籍などを読むときに最低限のコンテキストが入った状態で生きていけてとてもお得です。 To: 学内生 Ⅰ 類 I 科の科目です。マジでおすすめです。

4 年次では、DNA (遺伝子を構成する高分子) を構成する塩基の結合の特異性を利用して、ナノスケールで動作する回路などを研究している研究室に所属していました。結構難しい分野で、卒論はまともな成果が出ず最後の最後まで修正続きという体たらくでしたが、なんとか卒業することができました。大変ご迷惑をおかけしました...

研究のシミュレーションコードを書く過程で Go がある程度書けるようになったり、大量の生データを計算の邪魔をせず DB に一時保存するなどの技が理解できたり、パソコン好きとして楽しい瞬間もあり、なんだかんだ楽しかったです。

サークル

1 年おきくらいで所属サークルが変わり、なんだかんだ 3-4 サークルくらいを渡り歩いていました。

一番まとまって仕事をしたのはバーチャルライブ研究会で、急激に部員が増加していく中で部内の IT まわりを管掌する部署を立ち上げました。 IT インフラを大人数に耐えられるものに入れ替えたり、毎年新しく作っている Web サイト周りのコストダウンや制作体制の模索などをやっていました。

2026 年 3 月現在で自分の手を離れて 1 年程度経過しましたが、後輩がチームとしてまとまってバリバリ仕事を進めているのを見るとここまで来たものか、と感慨深いです。今年の特設サイト期待していますよ。

mikuec.com

note.com

仕事

対面であったことある人にはたまに話してますが、なんだかんだ学部卒として就職活動をし、ご縁のある会社からソフトウェアエンジニアとして内定をいただいたので引き続きパソコンに関わる人生を送っていきます。 今日からいよいよ社会人、引き続きやっていきますのでよろしくお願いします。

おわり

おわり

Claude Code に既存のフローに沿って Git Worktree を使わせる

Claude Code 2.1.49 で --worktree (-w) オプションが追加され、Claude Code を独立した Git Worktree 内で起動できるようになりました。

Added --worktree (-w) flag to start Claude in an isolated git worktree https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#2149

しかし私は Git Worktree の管理に k1low/git-wt を使用しており、挙動が自分の作業フローと合わないことからこの機能をそのまま使うことはできませんでした。 github.com

その後、Claude Code 2.1.50 で WorktreeCreate / WorktreeRemove Hook が追加されました。

Added WorktreeCreate and WorktreeRemove hook events, enabling custom VCS setup and teardown when agent worktree isolation creates or removes worktrees. https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#2150

これにより、Claude Code が Worktree を作成・削除する処理を差し替えられるようになり、既存の開発フローに合う方法で処理できるようになりました。

この記事では、k1low/git-wt を例に、既存の Worktree 管理ツールと Claude Code を統合する方法を紹介します。

※ 2026.02.24 追記 Claude Code 2.1.52 を使って手元で試したところ正常に動作しました。

※ 2026.02.21 現在、 claude -w オプションを使っても Worktree が作成・利用されない問題が報告されており、この記事の内容は正しく動作しない可能性があります。 github.com

WorktreeCreate / WorktreeRemove Hook の挙動

Claude Code の /hooks から見られる Hook の概要をそのまま引用します。

まず、WorktreeCreate hook です。

Input to command is JSON with name (suggested worktree slug). Stdout should contain the absolute path to the created worktree directory. Exit code 0 - worktree created successfully Other exit codes - worktree creation failed

標準入力から要求された Worktree の名称を取り出し、任意のツールを用いて適切な Worktree を作成した後 Worktree の絶対パスを print すればよさそうですね。

次に WorktreeRemove hook です。

Input to command is JSON with worktree_path (absolute path to worktree). Exit code 0 - worktree removed successfully Other exit codes - show stderr to user only

標準入力から削除したい Worktree の絶対パスを取り出し、素朴にそのパスの内容を削除すれば良さそうですね。

Hook を実装する

上記仕様を満たす Hook の実装例を示します。ここでは Git Worktree 管理ツールとして先述した k1low/git-wt を利用していることに注意してください。

#!/bin/bash
# Hook script for WorktreeCreate and WorktreeRemove events.
# Reads JSON from stdin and dispatches to git wt commands.
# Requires: jq

set -euo pipefail

input=$(cat)
hook_event=$(printf '%s' "$input" | jq -r '.hook_event_name')

case "$hook_event" in
WorktreeCreate)
    wt_name=$(printf '%s' "$input" | jq -r '.name')

    # Example output from git-wt:
    # Preparing worktree (new branch 'this-is-a-test')
    # HEAD is now at d2b2210 2.1.50
    # /{workspaceRoot}/.wt/this-is-a-test
    #
    # Last line is the absolute path to the new worktree, so we take that.
    wt_abs_path=$(git wt "$wt_name" --nocd 2>/dev/null | tail -n 1 | xargs)
    echo "$wt_abs_path"
    ;;
WorktreeRemove)
    wt_path=$(printf '%s' "$input" | jq -r '.worktree_path')
    git wt -d "$wt_path" 2>/dev/null || true
    ;;
esac

あとは .claude/settings.json に設定を追加すれば Hook が有効になり、 Claude Code が Git Worktree 管理ツールを使って Worktree を利用できるようになります。

{
  "hooks": {
    "WorktreeCreate": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "<path-to-hook-script>"
          }
        ]
      }
    ],
    "WorktreeRemove": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "<path-to-hook-script>"
          }
        ]
      }
    ]
  }
}

これで、Claude Code が外部の Git Worktree 管理ツールを通して Worktree を触れるようになりました。

おわり

おわり

2025.12 読書ログ

書くの忘れてたので書く

読んだ

わたしが恋人になれるわけないじゃん、ムリムリ! (※ムリじゃなかった!?)

booklog.jp

  • 小説: 既刊すべて (10 冊)
  • コミカライズ: 既刊すべて (8冊)

12 月に一番狂っていたコンテンツです。

TV アニメの追加 5 話を劇場で先行上映するネクストシャインについてはなんと 5 回も観に行きました。

www.watanare-anime.com

今や pixiv で SS を漁る悲しきモンスターになってしまいました。

小柳香穂を、よろしくお願いします...

こちら、終末停滞委員会。5

作者公言の通り、SF の文脈が織り込まれた今作はどこか現実感がない展開が続き良さがあった。 最後の最後で実は... という部分があり、大いに驚いた。

booklog.jp

1 月に読みたい

流石に研究がやばいので全然読めてないし感想も覚えてないな.....

開発環境現状確認 2026

流行っていそうなので開発環境はこんな感じでやっていますというメモを書く。

OS

基本的に会社 PC の環境と私用 PC の環境が近いほうが便利なのもあり macOS を使っている。

どうしても動作確認などで Linux が必要な場合は WSL を使っているが、CPU が i9-9900K なのですべてがもっさりしていて厳しい。 Ubuntu Desktop にしたら軽くなるんだろうが、Windows が 1 台もなくなると困るので諦めている。

Windows はたまにゲームをやるために使っている程度で開発には使っていない。

エディタ

基本的に VSCode か Cursor を使っている。 AI Coding 全盛ではあるが、自分は IDE のエディタウィンドウの半分に Claude Code などのターミナルを表示して作業していることが多い。

sushichan044.hateblo.jp

最近 Zed も使い始めたが、keybind が痒いところに手が届かない部分が多く使用頻度は低め。サクサク動くところは気に入っている。

VSCode が非常に重い点は気になっているので、コードをあまり見ない開発をするときは zellij のセッションを用意して difit でレビューするようにしている。

github.com

AI Coding Agent

GitHub Copilot, Claude Code (Pro), OpenAI Codex (Pro), Cursor (Pro) を気分で使い分けている。

基本的には Claude Code を使っていることが多い。自分好みにカスタムするための手段が多く用意されているのと、プログラマー仕草をよく理解している動きをする点が気に入っている。

大雑把な作業やレビューは Codex, 研究のコードは Cursor など他の Agent もざっくりとした線を自分の中に引いて使っている。

GitHub Copilot は IDE で使うと User level の instruction を設定する方法が未だに不明なのでたまにしか使っていない。 しかしながら、大半の Agent が rate limit 制に移行した中で GitHub Copilot は Request Quota 制なので、瞬間的な burst に強いのは助かっている。

また、AI に OSS などを読ませるために手元に repository を clone したり、メモ書きをファイルとして残したりすることが増えたので、プロジェクトごとの private なディレクトリを管理するツールを書いて使っている。 割と便利なので、自分が求める機能をすべて満たしたら別途エントリを書く予定だ。

github.com

Terminal

Terminal Emulator

Ghostty を 1.0 のリリースからずっと使っている。

WezTerm を試した時期もあったが、あまりターミナルエミュレータ側をカスタマイズする気持ちがなかったので Ghostty に落ち着いた。

ghostty.org

WSL を使うときは Windows Terminal を使っている。

Terminal Multiplexer

最近使い始めた。tmux が肌に合わず、 zellij に変えたら使いやすかったのでそのまま zellij を使っている。

AI を放牧したり長時間かかる研究のコードを実行する際に使っているが基本的には Ghostty 本体の tab / pane で事足りている。

zellij.dev

macOS デスクトップまわり

ランチャー

Raycast を使っている。メニューバーにミーティングを出したり GitHub の通知を出したりできるのが助かる。

Windows 出身なので、クセのない Window Manager があるのも高評価ポイント。

www.raycast.com

ブラウザ

縦タブを求めて更新が終了した Arc を使っている。 しかしながら、つい先日 Google Chrome に縦タブが追加されることが発表されたので近いうちに Chrome に乗り換えるだろう。

フォント

Fira Code から Firple に変更した。Fira Code 単体だと日本語フォントとの調和が微妙なところがあったが Firple ではそれが自然にまとまっているのでとても気に入っている。

negset.com

ターミナルでは powerlevel10k の都合で Meslo LGS NF を使っている。

github.com

その他

再生中の音楽や直近の予定をノッチに出すために Notchnook を使っている。地味に便利

lo.cafe

Shell

ずっと zsh を使っている。Plugin Manager は sheldon が使いやすく速いので他に移るつもりはない。

sheldon.cli.rs

AI が混乱しないようにいくつかの便利 alias を泣く泣く剥がすなどの変化はあった。

dotfiles

github.com

dotfiles の管理は chezmoi でやっている。 template や attribute でちょうどよい程度の自動化ができるのが気に入っている。

原理的にファイルの削除には弱いのだがそこは仕方ないので割り切っている。

www.chezmoi.io

各種ツールの管理は Homebrew と mise を併用している。

直近であった大きな変化としては AI Coding Agent の設定ファイルも dotfiles に入れるように変えたことだろう。 AGENTS.md や Agent Skills などを dotfiles の枠組みで管理すると、どの PC でも AI の味付けが同じになって助かったのでそうしている。

キーボード

相変わらず HHKB の Hybrid Type-S を使っている。 打鍵感の良さ・乾電池駆動・Bluetooth 接続可能という 3 点をすべて満たしているので大変満足しており、当面乗り換えるつもりはない。

happyhackingkb.com

キーのリマップ

キーのリマップはあまりやっていないが、 Windows 出身で FPS などを長くプレイしていたこともあり Ctrl を左下に移動させて小指で押せるようにしている。

HHKB のリマップは HHKB 謹製のツールを使ってハードウェアレベルで行い、Macbook 内蔵キーボードのリマップは Karabiner-Elements でやっている。

karabiner-elements.pqrs.org

モニター

デカいモニターは正義なので 32 インチ 4K のモニターを使っている。

USB-C で給電できるので Macbook を接続するのも楽で助かっているが、やや古いモデルなので USB ハブ / 有線 LAN 接続の機能はついていない。 次に買い替えるときはこれらがついているものにしたい。

www.lg.com

所感

dotfiles 盆栽はもはや趣味の一つの趣味だが、最近はそこに AI との協働を促進するツールづくりが加わってきているように思う。

自分のツールで自分の PC の仕事効率を上げていくのは素直に楽しいので今年も継続的に改善していきたい。

おわり

おわり

2025 ふりかえり

先日 2025 年の短めのふりかえりを書いていたが、数年後に見返しても何もわからない気がしたので詳細に立ち入った長めのふりかえりを別途書いていこうと思う。

sushichan044.hateblo.jp

時系列順

1 月

内定先にアルバイトとして入社して 2 ヶ月目だった。この頃はまだ何もわからなかった記憶がある。

この頃は 2024 年末に始めたゼンレスゾーンゼロとちょうど大型アップデートが来た原神をひたすらプレイしていた。

zenless.hoyoverse.com

genshin.hoyoverse.com

1 月 18 日にはシンガーの棗いつきさんのバースデーライブに行ってきた。 ついに Zepp でワンマンライブ... という感激があった。

会場のいい感じの写真がないのでフラワースタンド

2 月

星街すいせいさんの初めての武道館ライブがあった。残念ながらチケットは当たらなかったが、会場にフラワースタンドを出していたので現地にはいた。 デジタル名簿を取り入れることで今までより柔軟に企画の参加者募集が可能になるなど、新しい試みも取り入れたフラスタだった。

贈ったフラワースタンド

特に関係ない周央サンゴ

仕事では ESLint Flat Config への移行をやったり、Rails アプリに Idempotency-Key Draft に準拠した冪等リクエストに対応したエンドポイントを実装したりしていた。 特に冪等リクエストの実装はたいへん心躍るもので、個人的に好きな RFC / Internet Draft のひとつになった。

datatracker.ietf.org

3 月

プライベートでは何もなかったが、 AI とともにソフトウェアを作るようになったことで業務に大きな変化が訪れた。

3 月は会社の開発体制の変化と AI の導入が重なって何もかもが高速に変貌していく時期で、使い始めたての Cursor とともに今までコミットしたことがないアプリに PR を出しに行ったりしていた。

4 月

大学四年生に上がったので卒業研究が始まった。この時期は分野の事前学習としてひたすら専門書を読んでいた。

仕事では、2 月から実装していたエンドポイントの冪等リクエスト対応をリリースした。 あとは会社に Devin が導入されたのでひたすら環境整備や Playbook の整備をやっていた。

5 月

TSKaigi 2025 に参加していた。インターネット上で関わりがある学生の方や大学を卒業した先輩、インターンでお会いした方など様々な方と話せてよかった。

TSKaigi 当日に typescript-go の preview が公開され、かなり速くなっていたので休憩時間中に Hono のベンチマーク設定に tsgo を追加したりしていた。

github.com

あとは AI Coding Agent のルールの管理が面倒になったのでルールファイルを単一の情報源から生成するツールを書いたりしていた。 実践投入は叶わなかったものの、Go 言語を書き始めたことでコミットできる OSS の範囲が広がった。

zenn.dev

また、X 上のひょんなことから集まった人々で三崎にマグロを食べに行っていた。 人生で食べたマグロの中で一番美味しく、世の中にはすごいものがあるんだ、と感心した記憶がある。 マグロの白子とカマトロが本当に良かったのでまた行きたい。

6 月

社内で Cursor Devin やっていきをしていたらオンラインで喋ることになった。 ありえないほど緊張したので何を喋ったかかなり覚えていないが、AI が DB のクエリの EXPLAIN を自力で取れるようにしてクエリの良し悪しを自己判断させながら動かしている、みたいなことを話したと思う。

hey.connpass.com

OSS 活動では GoReleaser の HomeBrew Cask 対応の範囲を Private Repository に広げたりしていた。 詳しいことはこの記事で。

sushichan044.hateblo.jp

月の中頃には棗いつきさんのファンミーティングに行ってきた。2 部制だったのだが、2 部公演では 2 階最前列真ん中というとんでもない位置に座ることになって腰を抜かした。 浅草花やしき、良い会場でした....

月末には当日券で KMNZ のワンマンライブに行ってきた。とんでもない盛り上がりで汗ダクダクになるのも忘れて 2 時間楽しみ続けていた。

7 月

京都・大阪に旅行していた。

1 日目は Workers Tech Talk Kyoto に参加し...

Cloudflare Workers Tech Talks in Kyoto #1 - connpass

2 日目は棗いつきさんのライブツアーの大阪公演へ。

3 日目は万博へ。

すべてが最高に楽しかったのだが、さすがに弾丸日程過ぎたのでコロナにかかってしまった。

仕事では、この頃から社内業務の AI 統合に関わっていた。

8 月

コロナが治ってからもエンジンがかからない状態が続いていた。 今振り返ると軽いうつ状態だったと思う。詳しいことはこの記事で。

sushichan044.hateblo.jp

9 - 12 月

この頃からブログを多く書くようになり、振り返りで残したい情報は概ねブログエントリになっているので割愛する。

その他

OSS Contribution は 49 件だった。昨年比で 8 倍くらいになっていてめちゃくちゃ増えている。 来年は 100 PR マージいけるかな...

https://github.com/pulls?q=is:merged+is:pr+author:sushichan044+archived:false+-owner:sushichan044+-owner:VirtualLiveLab+-owner:y-chan+-owner:suiseicord-org+-owner:codeforjapan+sort:created-desc+created:2025-01-01..2026-01-01+

おわり

来年も引き続きよろしくお願いいたします。おわり

Short Recap of 2025

2025 年もいよいよ残すところわずか。

今年は自分の趣味・職業に不可逆的な変化が持ち込まれたこともあり、身の振り方を考え直した 1 年だったと思う。

数年後に読み返すために軽く振り返っておきたい。

仕事

内定先でアルバイトを続けている。テストを書くことすらおぼつかなかった頃と比べると、少しずつだができることが広がってきた実感がある。

自分が得意だと感じている分野をどう活かせるかにも少しずつ向き合っていて、うまく行かないこともあるが検証を繰り返しながら模索している。

公開情報だとフロントエンドのビルドの高速化とかもやった。

product.st.inc

来年からも引き続きやっていきたい。

趣味プログラミング・OSS

今年はアプリケーションをつくるというより、AI 向けの治具や自分が欲しい小さな道具を作る活動がメインだったと思う。

その中で、新しく Go 言語を書くようになったり、AST を用いた静的解析に手を出すなど気になる領域への挑戦も多少できた。

ライブラリのような汎用性のあるソフトウェアを自分なりにデザインする過程で、ことがらの抽象化やモジュールの切り分けなどの視点が少しだけ身についたかもしれない。

sushichan044.hateblo.jp

あとは AI でコードを読むのが早くなったので OSS へのコントリビューションも少しずつ挑戦している。

よく設計された OSS に効果的な変更を加えることは難しく、拙い Pull Request をたくさん出してしまった。 暖かくレビューしていただいた様々な Reviewer の方に感謝する。

細かい修正がメインだったので声を大にできる業績はないが、未熟なりに手が届く範囲の困りごとを直したりできて悪くなかったと思う。

2025 年の GitHub の Contribution の図。4487 Contributions した模様


これと言ったものだと、

GoReleaser の Homebrew Cask 対応の一部を手伝ったり

sushichan044.hateblo.jp

unjs/unifont に キャッシュ処理の改善を入れたり

github.com

TypeSpec のコードジャンプが効かないケースを直したりした

github.com

ソフトウェアコミュニティまわり

今年も気になるカンファレンスや勉強会に何個か参加していた。 また、Hono Conference 2025 ではコアスタッフとして CfP の選考や当日セッションの運営に関わっていた。

findy-code.io

後述する人間活動にも関連するが、AI によりソフトウェア開発やそのブログエントリなどが大幅に加速している中で、人間同士がオフラインでゆったりアウトプットすることには大きな意味があると思うので今後も積極的に関わっていきたい。

人間活動

AI でプログラミングの概念が一変し、加速したプログラミングに没頭して心身を壊したことで人間であることを頑張るようになった。

sushichan044.hateblo.jp

持続可能ではない AI との伴走は人生を壊してしまうことを体感し、これから人間のソフトウェアエンジニアとしてどうあるべきかを考えた結果「心身がそれなりに健康な人間であること」そのものに意味があるのでは、と思った。 同時に、2023 年頃からプログラミングだけに没頭し続けて人間らしい楽しみを見失っていた自分が怖くなったので、他の趣味を再開したり身体のケアと向き合うようにしている。

結果としてインターネットとも適度に距離を置くことができ、精神衛生的にもかなり改善した実感がある

読書

長らく手放していた読書を再開した。いきなり文学をゴリゴリ読むのは難しかったため気張りすぎない世界観のライトノベルをたくさん読んでいた。

2025 年の読書記録。合計 104 冊読了。内訳は 1 月: 6 冊, 2 月: 1 冊, 3 月: 1 冊, 4 月: 4 冊, 5 月: 1 冊, 6 月: 3 冊, 7 月: 8 冊, 8 月: 31 冊, 9 月: 4 冊, 10 月: 20 冊, 11 月: 5 冊, 12 月: 20 冊
心身を崩した時期から急に大量の本を読み始めている

紙のページをめくる喜び・すべてを忘れて物語に没頭する時間の貴重さ・脳内で物語を描写する素朴な楽しさに再会し、この時間を手放さないようにしようと思い直した。

外に出た際は書店に寄るのが楽しみになり、人生が少し明るくなったと感じる。

ブログ

文字を大量に読むと自分でも文字が書きたくなってくるので、少しずつブログを書くようになった。

技術的なものもそうでないものも含めて、半年で 20 エントリ程度ゆったり書いている。

これも読書と同じく、日本語を素朴に書く楽しさ・文章を推敲するゆったりした時間がとても心地よいと思う。AI は文章の推敲にかなり便利で、情報の非対称性などの観点もある程度チェックできるのでブログを書く腰が上がりやすくなった。

来年は踏み込んだ内容の技術ブログを書いたりできたら良いなと思う。

体のケア

あまり体をいたわってこなかったが、身体の健康を真面目に維持すべきだと思ったので生活習慣を少しずつ改善している。

睡眠は極力規則的になるようにリマインダーをかけたりしていて、以前よりパフォーマンスを維持しやすくなったと思う。

あとは月 2 回程度整体に通うようになったが、明らかに以前より姿勢を意識するようになって肩と首の痛みに悩まされることが減った。 どうしてもパソコンに向かう時間が長くなってしまうので、肩と首は極力元気な状態が維持できるよう今後も椅子などに気を遣っていきたい。

2026 年のこと

2026 年にやっていきたいこともたくさんあるので別途エントリを書く予定だが、やはり一番は大学を無事に卒業することと新しい生活に慣れることだと思う。

すでに引っ越しなどの準備も進めていて、色々慌ただしくなっているが心身を気づかいながら引き続き元気にやっていきたい。

気に入った Claude Code Hooks を紹介する

Claude Code の Hooks をそれなりに設定しているのですが、結構体験が変わってお得だったので自分が実際に常用している Hook の小ネタをいくつか紹介します。

この記事は Claude Code の Hooks をすでに触ったことがあり、自分で Hook を書くことに抵抗がない人向けです。

また、コード例では自作の TypeScript wrapper(cc-hooks-ts)を使っています。

sushichan044.hateblo.jp

Claude Code Hooks の公式ドキュメントはこちら。

code.claude.com

Plan 結果をプロジェクト内に出力する

Claude Code の Plan 結果はデフォルトでは ~/.claude/plans に出力されます。

私は Claude Code と OpenAI Codex の間で Plan をやり取りしたり、Plan をそのままプロジェクトの履歴として残したかったりするため、プロジェクト内に自動で書き出されるほうが都合が良いと感じています。

しかし 2025.12.26 現在、このような機能は実装されていません。

github.com

Claude Code には ExitPlanMode という Hook Event があるため、ここで Plan の内容を適当なファイルに書き出せばプロジェクト内に結果を保存できます。

Plan を整形して ${cwd}/.claude/plans 以下に保存する Hook の例:

import { defineHook } from "cc-hooks-ts";
import { format } from "oxfmt";
import path from "path";

async function dumpPlan(plan: string): Promise<string> {
  const filepath = path.join(process.cwd(), ".claude", "plans", `plan-${Date.now()}.md`);
  try {
    await Bun.write(filepath, plan);
  } catch (error) {
    return `Failed to write plan to memo note at ${filepath}. Error: ${String(error)}`;
  }

  return `Plan dumped to note file at ${filepath}`;
}

async function formatPlan(plan: string): Promise<string> {
  try {
    const pretty = await format("dummy.md", plan);
    return pretty.code;
  } catch {
    return plan;
  }
}

const hook = defineHook({
  trigger: {
    PreToolUse: {
      ExitPlanMode: true,
    },
  },

  run: async (c) => {
    const plan = c.input.tool_input["plan"] as string;
    const prettyPlan = await formatPlan(plan);
    const message = await dumpPlan(prettyPlan);

    return c.success({ messageForUser: message });
  },
});

if (import.meta.main) {
  const { runHook } = await import("cc-hooks-ts");
  await runHook(hook);
}

起動時に Plugin Marketplace をバックグラウンドで更新する

最近の Claude Code では、Subagent や Skill を Plugin として配布できるようになり、 資産の再利用がかなり楽になりました。

code.claude.com

azukiazusa.dev

一方で、Plugin Marketplace の更新はこのように手動で行う必要があります。

  • TUI の奥深くのメニューから更新する
  • claude plugin marketplace update を実行する

覚えておくのは面倒なので、 SessionStart Event に Hook を設定して起動時に Marketplace をバックグラウンドで更新するようにしています。 これで 2 回目以降の起動時には最新の Marketplace が読み込まれます。

import { regex } from "arkregex";
import { defineHook } from "cc-hooks-ts";

/**
 * $ claude plugin marketplace update
 *
 * Updating 3 marketplace(s)...
 * ✔ Successfully updated 3 marketplace(s)
 */
const extractMarketplaceAmount = regex("(?<amount>[0-9]+) marketplace");

const hook = defineHook({
  trigger: {
    SessionStart: true,
  },

  run: (c) =>
    c.defer(async () => {
      // stdout will break claude code
      const result = await Bun.$`claude plugin marketplace update`.nothrow().quiet();
      const amount = extractMarketplaceAmount.exec(result.text())?.groups?.amount ?? "-1";

      return {
        event: "SessionStart",
        output: {
          systemMessage: `Updated ${amount} plugin marketplaces.`,
        },
      };
    }),
});

if (import.meta.main) {
  const { runHook } = await import("cc-hooks-ts");
  await runHook(hook);
}

※ この Hook ではドキュメント化されていない Async Hooks というしくみを使っています。 Claude Code が Hook の終了を待たずに本来の処理を継続してくれるので、バックグラウンドで特定の処理がしたい場合に便利です。

TypeScript Wrapper での実装の詳細はこちら。

github.com

URL に対して適切なツールがある場合に WebFetch を拒否する

URL を渡して情報をコンテキストに含めるよう頼むことは多々ありますが、WebFetch ツールでは URL の内容を適切に取得できないことがあります。

たとえば GitHub の Pull Request の URL を渡した場合、HTML は取得できてもレビューに必要な情報が欠落することがあります。 また、Notion のように認証が必要なサービスでは、そもそも内容を取得できません。

このように、URL によっては WebFetch よりも専用のツールを使ったほうが適切に情報を取得できるケースがあります。

GitHub の URL であれば GitHub CLIGitHub MCP を使うほうが確実ですし、 Notion の URL の場合は公式が提供する Remote MCP の利用が推奨されています。

developers.notion.com

このようなツールの使い分け方を Agent Skills として整備しておくことも考えられますが、Skill は Claude が必要に応じて参照するものなので、常に期待する使い分けがされるとは限りません。

code.claude.com

そこで、 WebFetch の実行前に URL をチェックしてより適切な手段がある場合は Claude にフィードバックするようにしています。

※ 実際のコードが大きいので抜粋して掲載します

import { defineHook } from "cc-hooks-ts";

const hook = defineHook({
  trigger: {
    PreToolUse: {
      WebFetch: true,
    },
  },

  run: (c) => {
    const urlObj = new URL(c.input.tool_input.url);
    // raw.githubusercontent.com などファイルの中身だけが返ってくる URL は許可する
    if (isRawContentURL(urlObj)) {
      return c.success();
    }

    // Notion の URL は Notion MCP で読むべき
    if (urlObj.hostname.includes("notion.so")) {
      return c.json({
        event: "PreToolUse",
        output: {
          hookSpecificOutput: {
            hookEventName: "PreToolUse",
            permissionDecision: "deny",
            permissionDecisionReason:
              "Use mcp__notion__fetch instead of web fetch for Notion URLs.",
          },
        },
      });
    }

    // たとえば https://github.com/honojs/hono/pull/4586 に対して
    // gh pr view --repo honojs/hono 4586 を提案する
    const ghResult = parseGitHubUrlToGhCommand(urlObj);
    if (ghResult) {
      return c.json({
        event: "PreToolUse",
        output: {
          hookSpecificOutput: {
            hookEventName: "PreToolUse",
            permissionDecision: "deny",
            permissionDecisionReason: [
              "Use the GitHub CLI instead.",
              "Suggested command:",
              "```bash",
              ghResult.command,
              "```",
            ].join("\n"),
          },
        },
      });
    }

    return c.success();
  },
});

if (import.meta.main) {
  const { runHook } = await import("cc-hooks-ts");
  await runHook(hook);
}

DeepWiki MCP に不要な情報を入力させない

DeepWiki は、GitHub リポジトリの内容をコンテキストに読み込んだ AI と対話できる便利なサービスです。 MCP が用意されており、Claude Code から直接利用できます。

docs.devin.ai

ただしサービスの性質上、Private Repository に関する情報は DeepWiki 側に存在しません。 そのため Private Repository について問い合わせると、無駄な待ち時間が発生するだけでなくサービス提供側に機密性のある情報を渡してしまう可能性があります。

そこで、DeepWiki MCP を呼び出す前にGitHub CLI を使って Repository が Public かどうかをチェックし、Public でない場合は呼び出しを拒否するようにしています。

import { defineHook } from "cc-hooks-ts";

const hook = defineHook({
  trigger: {
    PreToolUse: {
      mcp__deepwiki__ask_question: true,
      mcp__deepwiki__read_wiki_contents: true,
      mcp__deepwiki__read_wiki_structure: true,
    },
  },

  run: async (c) => {
    if (Bun.which("gh") == null) {
      return c.nonBlockingError("GitHub CLI (gh) is not installed.");
    }

    const repoName = c.input.tool_input.repoName;
    const repoVisibility =
      await Bun.$`gh repo view ${repoName} --json visibility --jq '.visibility'`.nothrow().quiet();

    const isPublic = repoVisibility.text().trim().toLowerCase() === "public";
    if (repoVisibility.exitCode === 0 && isPublic) {
      return c.success();
    }

    return c.json({
      event: "PreToolUse",
      output: {
        hookSpecificOutput: {
          hookEventName: "PreToolUse",
          permissionDecision: "deny",
          permissionDecisionReason: `The GitHub repository "${repoName}" is not public or does not exist.`,
        },
      },
    });
  },
});

if (import.meta.main) {
  const { runHook } = await import("cc-hooks-ts");
  await runHook(hook);
}

まとめ

Claude Code の Hooks は公式機能で手が届かない部分の補完や、Tool 呼び出しに一定の規約を敷くのに便利です。

自分好みにカスタムして便利に使っていきましょう。

おわり

おわり