17
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

最近取り入れたClaude Codeの個人的tips 4選

17
Posted at

はじめに

ここ最近取り入れた Claude Code の tips を4つ紹介します。1つだけツールの話です。
どれも大がかりな仕組みではないので、気になったものだけ拾ってもらえればと思います。

この記事をざっくり図解

qitta-cctips.png

1. セッション名を自動で付ける

知っている方も多いかと思いますが、Claude Code のセッションには名前を付けられます。
/rename で設定すると、プロンプト入力欄の右下にチップとして表示されます。

image

複数のセッションを並行して動かしていると、どれが何の話だったか分からなくなります。それで名前を付けるようになったのですが、毎回手で打つのが面倒でした。
ここを自動化したい、というのが出発点です。

ai-title と custom-title は別物

先に仕組みの話をします。
Claude Code はセッションのタイトルを2種類持っています。

種類 誰が作るか どこに出るか
ai-title Claude Code が1往復目のあとに自動生成 --resume の一覧、
ターミナルのタイトル、
/status など
custom-title /rename やフックで明示的に設定 上記に加えてチップ

自動生成された ai-title は、Claude Code が会話の記録を残しているファイルに書き込まれています。
~/.claude/projects/ の下にセッションごとの .jsonl があり、発言や応答と同じ場所にタイトルの行も並びます。

{"type":"ai-title","aiTitle":"検索インデックスの調査"}

ただし、この文言はチップには出ません。
チップが読んでいるのは custom-title のほうだけです。

つまり文言はすでに作られているのに、表示される場所へ渡されていない状態です。

フックで ai-title を custom-title に移す

UserPromptSubmit フックは、標準出力に次の形の JSON を返すとセッション名を設定できます。

{"hookSpecificOutput": {"hookEventName": "UserPromptSubmit", "sessionTitle": "検索インデックスの調査"}}

この sessionTitle を受け付けるのは UserPromptSubmitSessionStart の2つだけです。Stop などほかのフックで返しても読み捨てられます。

(補足) フックイベントの一覧

太字の2つのイベントでしか sessionTitle を受け付けません。

イベント 発火するタイミング
SessionStart セッションの開始・再開時
Setup --init-only での起動時、-p での --init / --maintenance 実行時
UserPromptSubmit プロンプトを送信した直後、Claude が処理を始める前
UserPromptExpansion 入力したコマンドがプロンプトに展開されるとき
PreToolUse ツール実行の前
PermissionRequest ツール実行の許可判断が必要になったとき
PermissionDenied auto モードがツール実行を拒否したとき
PostToolUse ツール実行が成功したあと
PostToolUseFailure ツール実行が失敗したあと
PostToolBatch 並列のツール呼び出しがひとまとまり終わったあと
Notification Claude Code が通知を出すとき
MessageDisplay 応答テキストが表示されている間
SubagentStart サブエージェントが起動したとき
SubagentStop サブエージェントが終了したとき
TaskCreated TaskCreate でタスクが作られるとき
TaskCompleted タスクが完了扱いになるとき
Stop Claude が応答を終えたとき
StopFailure API エラーでターンが終わったとき
TeammateIdle チームメイトのエージェントがアイドルに入る直前
InstructionsLoaded CLAUDE.md や .claude/rules/*.md が読み込まれたとき
ConfigChange セッション中に設定ファイルが変わったとき
CwdChanged 作業ディレクトリが変わったとき
DirectoryAdded セッション中に作業ディレクトリが追加されたとき
FileChanged 監視対象のファイルがディスク上で変わったとき
WorktreeCreate ワークツリーが作られるとき
WorktreeRemove ワークツリーが削除されるとき
PreCompact コンテキスト圧縮の前
PostCompact コンテキスト圧縮の完了後
PreModelSwitch モデル切り替えが適用される前
PostModelSwitch セッションのモデルが変わったあと
Elicitation MCP サーバーがツール実行中に入力を求めたとき
ElicitationResult MCP の入力要求にユーザーが応えたあと
SessionEnd セッションが終了したとき

イベントは今後増えることがあるので、最新は公式ドキュメントを見てください。

書いたスクリプトがこちらです。
ai-title を読んで返しているだけで、タイトルの生成そのものはしていません。

#!/bin/bash
input=$(cat)
session_id=$(printf '%s' "$input" | jq -r '.session_id // empty')
transcript=$(printf '%s' "$input" | jq -r '.transcript_path // empty')
[ -z "$session_id" ] && exit 0
[ -f "$transcript" ] || exit 0

# 同じセッションで何度も名前を変えないよう、一度付けたら印を残す
marker="$HOME/.claude/.session-titled/$session_id"
[ -f "$marker" ] && exit 0
mkdir -p "$(dirname "$marker")"

# 組み込みが生成した最新の ai-title を拾う。まだ無ければ次のプロンプトに持ち越す
title=$(jq -r 'select(.type == "ai-title") | .aiTitle' "$transcript" | tail -1)
[ -z "$title" ] && exit 0

# ブランチ名に #123 が含まれていれば、タイトルの先頭に付ける
cwd=$(printf '%s' "$input" | jq -r '.cwd // "."')
branch=$(git -C "$cwd" rev-parse --abbrev-ref HEAD 2>/dev/null)
number=$(printf '%s' "$branch" | grep -oE '#[0-9]+' | head -1 | tr -d '#')
[ -n "$number" ] && title="#$number $title"

touch "$marker"
jq -n --arg t "$title" \
  '{hookSpecificOutput: {hookEventName: "UserPromptSubmit", sessionTitle: $t}}'

~/.claude/settings.json に登録します。
パスは自分の環境のものに置き換えてください。

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "/Users/you/.claude/hooks/auto-session-title.sh",
            "timeout": 10
          }
        ]
      }
    ]
  }
}

名前が変わるのは2通目を送ったとき

ai-title が生成されるのは、1往復目の応答が終わったあとです。
登録しているフックが動くのはプロンプトを送った瞬間なので、1通目の時点ではまだ何もありません。実際に名前が変わるのは2通目を送ったタイミングになります。

最後の数行では、ブランチ名に含まれる Issue 番号をタイトルの先頭に足しています。feature/#123_add_search というブランチで作業していれば #123 検索インデックスの調査 になります。あとから --resume で探すとき、番号で引けるほうが早いためです。

2. ステータスラインに Issue と PR を出す

ステータスラインにリンクを置けると X で見かけました。
それなら Issue と PR のリンクも動的に出せるのではないか、と思って作ったのがこれです。

image

2行目の #123PR#456 がリンクになっていて、クリックすると GitHub の該当ページが開きます。

Issue 番号はブランチ名から取る

ブランチ名に Issue 番号を入れる運用にしているので、そこから抜き出しています。

issue_number_from_branch() {
  printf '%s' "$1" | sed -n 's/.*#\([0-9][0-9]*\).*/\1/p'
}

リンク先の URL は、ステータスラインに渡ってくる JSON の workspace.repo から組み立てます。ホスト名・オーナー・リポジトリ名がそれぞれ入っているので、GitHub に限定せずに済みます。

PR のほうは、同じ JSON の pr.numberpr.url を使います。これが渡ってこない環境向けに、gh pr list の結果を自前でキャッシュする経路も用意しました。ステータスラインは表示のたびに実行されるため、gh を毎回同期で叩くと目に見えて重くなります。キャッシュを読んで表示し、期限切れならバックグラウンドで更新する形にしています。

リンク化は OSC 8

ターミナルでテキストをリンクにするには、OSC 8 というエスケープシーケンスを使います。

osc8_link() {
  printf '\033]8;;%s\033\\%s\033]8;;\033\\' "$1" "$2"
}

ここで一度ハマりました。OSC 8 の終端はバックスラッシュを含みます。そのため色付きの文字列を printf '%b' に渡す書き方をしていると、エスケープの解釈がぶつかってリンクが壊れます。

色を $'\033[33m' の形で実バイトとして持ち、出力は %s に統一することで直りました。

3. レートリミットのリセット時刻を揃える

レートリミットのリセット時刻を揃えるtipsは、以下の記事で知りました。

Claude のレートリミットは5時間のローリングウィンドウで、初回メッセージを送った時刻が起点になります。仕事を始めてから最初のメッセージを送ると、そこから5時間が計測されるわけです。

そこで、ルーチン機能で毎朝決まった時刻に ping を1通送り、起点を固定してしまう、という話でした。クラウド側で実行されるので、PC が起動していなくても動きます。

私の設定例

私は8時前後に始業することが多いので、6時に設定しています。

06:00 - 11:00  ← 3h(08:00 - 11:00)
11:00 - 16:00  ← 4h(1h休憩)
16:00 - 21:00  ← 2h(16:00 - 18:00)

効果は分かりやすく出ました。拘束時間を10時間(実働8時間+休憩1時間+残業1時間)とすると、ルーチンがない場合はその間にリセットが1回しか挟まりません。
始業と同時に起点が決まってしまうためです。

6時に固定しておくと、同じ10時間のあいだにリセットが2回挟まります。
5時間ぶんの使用量を気にする場面が、体感でかなり減りました。

4. Orca に情報をまとめる

これも X で見かけて試したものです。
Orca は、複数のワークツリーで AI エージェントを並行して動かすためのデスクトップアプリです。

それまでは同じ用途で herdr というターミナルマルチプレクサを、Ghostty上で起動して使用していました。
乗り換えてみたところ、herdr で私が使用していた機能はすべて Orca でもできました。
そのうえで、次のものが最初から内蔵されています。

  • ファイル操作(エクスプローラー表示・書き込み・削除といった IDE 的な機能)
  • ブラウザ
  • Macのスリープ制御
  • AIモデルの現在の使用量表示
  • GitHub連携
  • モバイル対応

herdr でもプラグインやほかのツールと組み合わせれば同じことはできます。
ただ、内蔵されているぶん Orca のほうが圧倒的に楽です。

いちばん効いているのは、情報が1か所にまとまることです。
ウィンドウを行き来して探し直す回数が減り、タスクごとに1つの画面に情報(ターミナル、ブラウザ、mdファイル等)をまとめることが出来、頭の中の負荷が軽くなったと感じています。

最後に

セッション名とステータスラインは自作なので手間はかかりますが、レートリミットの設定と Orca は入れるだけです。気になったものから試してみてください。

参考文献

株式会社シンシア

株式会社シンシアでは、実務未経験のエンジニアの方や学生エンジニアインターンを採用し一緒に働いています。
※ シンシアにおける働き方の様子はこちら

弊社には年間100人以上の実務未経験の方に応募いただき、技術面接を実施しております。
この記事が少しでも学びになったという方は、ぜひ wantedly のストーリーもご覧いただけるととても嬉しいです!

17
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?