Claude Code 実践メモ:SSH鍵・権限モード・デプロイ
Claude Code(ターミナルで動くやつ) を触り始めた記録。公式ドキュメントに書いてある話と、実際に踏んだ地雷の話を混ぜたメモ書き。
筆者の環境
Windows + WSL2、Laravel のマルチテナント構成(6店舗)、本番はさくらのVPS。
デプロイ作業中に起きたことをそのまま書いている。
Claude Code とは
ターミナルで動くエージェント型のコーディングツール。ファイルを読み、書き換え、コマンドを実行する。チャットではなく、実際に手を動かす。
# インストール(Mac / Linux / WSL)
curl -fsSL https://claude.ai/install.sh | bash
# Windows PowerShell
irm https://claude.ai/install.ps1 | iex
# 確認
claude --version
起動は、触りたいプロジェクトのディレクトリに移動してから。
cd /var/www/html/project
claude
Claude Code は「今いるフォルダ」しか見ない。 デスクトップで起動して「ファイルが見つからない」と言うのは、大抵これが原因。
無料プランでは使えない
Pro / Max / Team / Enterprise、または Console アカウントが必要。初回起動時にブラウザ認証が走る。以降は保存されるので聞かれない。
trust ディレクトリの挙動
初回起動時に「このフォルダのファイルを信頼するか」と聞かれる。一度 Yes を選べば記憶され、次から出ない。保存先は ~/.claude.json。
毎回聞かれる場合、原因はだいたいこれ。
| 症状 | 原因 |
|---|---|
| 毎回聞かれる | パスが微妙に違う(シンボリックリンク経由など) |
| コンテナで毎回 | ホームが揮発している |
| WSLで毎回 |
D:\ と /mnt/d/ のパス表記揺れ |
| 保存されない |
~/.claude.json に書き込み権限がない |
trust は「読む許可」だけではない
そのリポジトリが .claude/settings.json を同梱している場合、フックや権限設定も一緒に読み込まれる。他人のリポジトリを初めて開くときの Yes は、それなりに重い判断。
メモリは2系統ある
セッションを起動するたびにコンテキストは真っさらになる。それを補う仕組みが2つ。
| CLAUDE.md | auto memory | |
|---|---|---|
| 書くのは | 人間 | Claude |
| 中身 | 指示・ルール | 学習・作業者の癖 |
| 場所 |
./CLAUDE.md など |
~/.claude/projects/<repo>/memory/ |
| 見るには | /memory |
/memory |
/memory は系統ではなくコマンド。両方をここから開ける。
CLAUDE.md はまず /init で雛形を作らせるのが早い。コードベースを解析して自動生成される。
/init
CLAUDE.md は強制力ではない
内容はシステムプロンプトではなくユーザーメッセージとして渡される。読んで従おうとはするが、厳密な遵守は保証されない。絶対に守らせたい動作はフックか deny ルールで縛る。書く目安は「同じ指摘を2回したら書く」。200行以内に収める。
権限モード
入力欄の下に出る manual mode on は現在の権限モード。
| 表示 | config値 | 挙動 |
|---|---|---|
| Manual | default |
状態を変える操作は毎回確認 |
| Accept edits | acceptEdits |
ファイル編集は自動承認 |
| Plan | plan |
読むだけ。一切変更しない |
| Auto | auto |
分類器が代わりに判断 |
| Bypass | bypassPermissions |
全スルー |
切り替えは3通り。
# セッション中
Shift+Tab
# 起動時
claude --permission-mode manual
# 恒久設定(~/.claude/settings.json)
{ "defaultMode": "manual" }
表示ラベルと config値が違う
「Manual」の config値は default。ややこしいが、v2.1.200 以降は manual がエイリアスとして通る。それ以前のバージョンなら "defaultMode": "default" と書く。
また "defaultMode": "auto" はリポジトリの .claude/settings.json に書いても無視される。リポジトリが自分自身に auto を与えることはできない仕様。自分の設定は ~/.claude/settings.json に書く。
ステータス行に出る他の表示も一応。
manual mode on · ? for shortcuts · ← for agents
? でショートカット一覧、← で Agent View(複数セッションのダッシュボード)が開く。
承認プロンプトの読み方
manual モードでは、実行前にこれが出る。
│ ssh ubuntu@xxx.xxx.xxx.xxx 'ls -la /var/www/html/kobe'
Do you want to proceed?
❯ 1. Yes
2. Yes, and don't ask again for: ssh *
3. Yes, and switch to auto mode
❯ 4. No
2番は選ぶな。 ssh * は「あらゆるSSHコマンド」を意味する。読むだけの ls も、rm -rf を流すやつも、同じパターンにマッチする。
毎回見るべき箇所。
- 接続先のIPは合っているか(本番と検証を間違えていないか)
- 破壊的な動詞が入っていないか(
rmmv>DROP--force--delete) - パスは意図通りか
このプロンプトは邪魔なものではなく最後の砦
慣れると惰性で Yes を押すようになる。そこが一番危ない。
ペーストが省略される件
長文を貼ると [Pasted text #1 +14 lines] に畳まれる。2行以上、または800文字超で発動する。
省略されているのは表示だけ。中身は全量が送信される。
確認したいときの手段は3つ。
# 1. 同じ内容をもう一度ペーストする(その場で展開される)
# 2. 外部エディタで開く ← 本命
Ctrl+G # または Ctrl+X Ctrl+E
# 3. キャッシュを直接見る
ls -la ~/.claude/paste-cache/
エディタの指定はこれ。
export EDITOR=nvim # code -w でも vim でも
そもそもファイルを貼るな
1本まるごと貼るくらいなら、パスを渡したほうが速く正確でコンテキストも節約できる。Claude Code は自分でファイルを読む。
なお10万文字を超えるペーストは展開されない。
日本語入力でゴミが出る
IME で変換中に、全角の残骸みたいな文字がまとわりつくことがある。
原因は、Claude Code の TUI が React Ink で作られていること。Ink は非常に高い頻度で画面を再描画するため、IME が保持している未確定文字列と Ink が描こうとするテキストが衝突する。半角前提のカラム計算に全角が乗って、ズレた分が消し残る。
対処は順に。
# 1. バージョンを上げる(CJK関連は継続的に修正されている)
claude update
# 2. ロケール確認
echo $LANG # ja_JP.UTF-8 が出るべき
# 3. WSLなら個別に設定が必要
echo 'export LANG=ja_JP.UTF-8' >> ~/.bashrc
source ~/.bashrc
# 4. 応急処置(画面を描き直す)
Ctrl+L
| バージョン | 修正内容 |
|---|---|
| v2.1.20 | CJK・絵文字の表示崩れ修正 |
| v2.1.21 | 日本語IMEの全角数字入力対応 |
| v2.1.84 | 変換中の文字が入力位置に沿って表示 |
WSL のロケールと Windows のコードページは独立している
PowerShell で chcp 65001 を打っても WSL には反映されない。WSL のシェルプロファイルに個別に export LANG が要る。
また Git Bash は特に相性が悪い。Windows Terminal 経由の WSL、Mac なら iTerm2 / WezTerm / Ghostty が推奨。macOS標準の Terminal.app は IME と競合しやすい。
長文を書くなら Ctrl+G で外部エディタを開くのが結局いちばん安定する。
Claude Code で会話を遡って言い直す
CLI版の Claude Codeでも、通常の Claude チャットのように過去のメッセージまで遡って言い直せる。
手順は次の通り。
- Esc キーを2回押す(Esc, Esc) … 過去のメッセージ履歴がリスト表示される
- 矢印キーで遡りたい地点を選ぶ
- Enter で確定 … その地点まで会話が巻き戻り、そこから言い直せる
[入力中] → Esc → Esc
→ 履歴リスト表示
→ ↑ / ↓ で対象メッセージを選択
→ Enter で巻き戻し
選んだメッセージより後のやり取りは巻き戻される(消える)ので、遡りすぎに注意すること。
補足として、バージョンによっては /rewind コマンドやUIから戻す方法もあるが、一番手っ取り早いのは Esc 2連打 である。
Claude Code ショートカット早見表
入力モード切替
| キー | 名称 | 動作 |
|---|---|---|
! |
shell mode | 行頭で押すとbashモードに入る。Claudeを介さず直接シェルコマンドを実行 |
/ |
commands | スラッシュコマンドの候補が出る(/model /memory /clear など) |
@ |
file paths | ファイルパス補完。@src/ と打つと候補が出て、そのファイルをClaudeに渡せる |
入力操作
| キー | 動作 |
|---|---|
Esc ×2 |
入力欄を全消去。打ちかけを捨てるとき |
Ctrl+Shift+_ |
直前の入力操作を取り消す(アンドゥ) |
Shift+Enter |
改行。Enterは送信なので、複数行書くならこっち |
Ctrl+V |
画像を貼り付ける。スクショをそのまま渡せる |
Ctrl+S |
書きかけのプロンプトを一時退避。後で戻せる |
Ctrl+G |
$EDITOR で編集。長文・日本語ならこれが最強
|
実行制御
| キー | 動作 |
|---|---|
Shift+Tab |
権限モードを巡回切替(manual → auto-accept → plan など) |
Ctrl+Z |
Claude Codeを一時停止してシェルに戻る。fg で復帰 |
Ctrl+O |
詳細出力(verbose)の表示切替。何をやってるか全部見える |
その他
| コマンド | 動作 |
|---|---|
/btw |
本筋を止めずに脇道の質問をする。文脈を汚さずに聞ける |
/keybindings |
キーバインドのカスタマイズ画面 |
実用上の優先順位
今すぐ覚えるべき3つ
| キー | 理由 |
|---|---|
Ctrl+G |
日本語IMEのゴミも誤爆Enterも回避できる |
Esc ×2 |
打ち間違えたときの脱出 |
Shift+Enter |
改行したいのに送信してしまう事故を防ぐ |
注意が要るもの
| キー | 注意点 |
|---|---|
! |
シェルモードは承認プロンプトを経由しない。本番に繋がるコマンドを打たないこと |
Shift+Tab |
押しすぎるとauto-acceptまで行く。ステータス行で現在モードを確認する |
Ctrl+Z |
停止したまま忘れると、セッションが残り続ける。fg で戻すか /exit で閉じる |
補足
! のシェルモードは、さっき「上がWSL、下がClaude Code」に見えた現象の正体かもしれない。プロンプト先頭に ! が出ていたらこれ。Backspaceで抜けられる。
会話が長くなると出てくるもの
作業を1つのセッションで長時間続けると、こういう表示が出ることがある。
✽ Compacting conversation… (31s)
▰▰▰▰▰▰▰▰▰▰▰▰▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱ 29%
/compact が走っている状態。コンテキストウィンドウが埋まってくるのを防ぐため、古いやり取りを要約して圧縮する処理だ。自動でも発火するし、手動で叩くこともできる。
進行中は止めるな。途中で切ると変な状態になる。バーが100%になるまで待つ。
似たコマンドに /clear があるが、役割が違う。
| コマンド | 何をするか | 使うタイミング |
|---|---|---|
/compact |
古い部分を要約して圧縮 | 同じ作業が長引いたとき |
/clear |
会話を丸ごと消す | 話題が完全に変わったとき |
体感の目安としては、同じプロジェクトで1〜2時間、何十往復もやり取りしたら視野に入ってくるくらいでいい。
compact後は指示が残ってるか確認する
/compact は要約なので、口頭で言っただけの一時的なルール(「本番SSHは実行するな」など)が薄まって消える可能性がある。CLAUDE.md に書いてある内容は保持されやすいが、会話中だけの指示は保証がない。
圧縮が終わったら一度確認するといい。
今のルールを要約しろ。特にSSH実行と本番操作について
期待通りの答えが返らなければ、CLAUDE.md に書き直しておく。
5KiB制限とInterrupted表示
貼り付けサイズの制限
ターミナルにまとまった量のテキストを貼ろうとすると、こういうアラートが出ることがある。
5KiBを超える長さのテキストを貼り付けようとしています
Claude.ai(ブラウザのチャット)ではこの制限は出ない。 理由は入力される場所が違うから。
| Claude.ai(ブラウザ) | Claude Code(ターミナル) | |
|---|---|---|
| 入力欄 | Webのテキストエリア | ターミナルのプロンプト欄 |
| 大きい貼り付け | そのまま送信できる | サイズ超過でアラート |
ターミナルは大量の文字を一気に受け取ると、描画ライブラリ(React Ink)の再描画が重くなって不安定になりやすい。加えて、長文ペーストでEnterキーの扱いを誤ると誤爆送信につながる。だから一旦立ち止まらせる設計になっている。
5KiBの目安はこれくらい。
| 種類 | 文字数目安 |
|---|---|
| 日本語(UTF-8で1文字3バイト) | 約1,700文字 |
| 英数字(1文字1バイト) | 約5,000文字 |
原稿用紙4枚ちょっと程度。日本語のほうが早く上限に当たる。
KiBとMBの感覚差
5 KiB は 5,120 バイトで、1 MB の約200分の1しかない。スマホ写真1枚(3〜5MB)よりずっと小さい制限。テキストだけならすぐ到達するので、画像や動画のサイズ感覚で捉えると誤解する。
超えたときの対処。
# 外部エディタで開く。制限なく編集できる。長文は最初からこっち推奨
Ctrl+G
長いログや仕様書はそもそも貼らず、ファイル化してパスを渡す方が速い。
仕様は spec.md に書いた。読んで進めろ
| 長さ | 対応 |
|---|---|
| 数行〜数十行の指示・エラーログ | 普通に貼ってよい |
| 仕様書、長い会話ログ、コード全体 |
Ctrl+G かファイル化 |
Interrupted 表示
作業中にこう出ることがある。
Interrupted · What should Claude do instead?
エラーではない。「中断された。次は何をすればいい?」という、指示待ち状態を示す表示。
出る原因はこのあたり。
| 操作 | 効果 |
|---|---|
Esc |
今の応答・実行を中断 |
Ctrl+C |
同上、より強制的 |
| Enter前に別の指示を割り込ませる | 今のタスクを止めて新しい指示待ちに |
危ないコマンドが承認プロンプトに出る前に「これ待てやばい」と気づいたときも、Esc で止めていい。何も壊れない。
出たら、そのまま次の指示を打てば再開する。
さっきのは中止でいい。代わりに◯◯をやれ
さっきの続きをやれ
SSH鍵とパスフレーズの扱い
前提:Claude Code はパスフレーズを知らなくても SSH が通る
ssh を実行するのは Claude Code ではなく、そのマシンの ssh コマンド。認証は ssh クライアントが勝手にやる。
[ローカルPC] [VPS]
ssh-agent sshd
└ 解錠済みの鍵 └ 公開鍵だけ持っている
用語を整理するとこうなる。
| 名前 | 正体 |
|---|---|
~/.ssh/id_ed25519 |
鍵ファイル。暗号化されて眠っている |
| ssh-agent | 解錠済みの鍵を抱えた常駐プロセス |
SSH_AUTH_SOCK |
ssh-agent への窓口(ソケットパス) |
ssh-add が「解錠して agent に預ける」動作。
eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519 # ここでパスフレーズを入力
echo $SSH_AUTH_SOCK # /tmp/ssh-xxxxx/agent.1234
ssh-add -l # 載っている鍵の確認
金庫の例え
パスフレーズはどこにも保存されない。渡すのは「解錠済みの状態」。
| 登場人物 | 正体 |
|---|---|
| 金庫 | VPS |
| ダイヤル番号 | パスフレーズ(頭の中だけ) |
| 鍵束 | ~/.ssh/id_ed25519 |
| 秘書 | ssh-agent |
| 秘書室の窓口 | ソケットパス |
秘書に番号は教えない。番号で解錠した鍵束を預けるだけ。秘書は「開けろ」には応じるが「鍵を寄越せ」には応じない。
サーバー側に「解錠済み」という状態はない
VPS は毎回ゼロから証明を要求する。接続のたびに乱数を投げ、agent が署名し、サーバーが検証する。過去のセッションは一切引き継がれない。
「セッションを渡す」仕組みが欲しいなら ControlMaster(SSH多重化)が別に存在する。そちらは確立済みのTCP接続そのものを共有するので、認証すら飛ばせる。
ソケットパスとは何か
ls -la $SSH_AUTH_SOCK
# srwxr-xr-x 1 you you 0 Aug 29 10:00 /tmp/ssh-abc123/agent.4567
先頭の s がソケットの印。サイズは0で、cat しても何も出ない。読み書きするものではなく、接続するもの。
他人は r-x で書き込み権限がないため、同じユーザーのプロセスしか繋げない。 パスが漏れても他人には無意味。
Unixソケットは他にもある
/var/run/docker.sock も同じ仕組み。docker ps はこのソケット経由で裏のデーモンに話しかけている。「ファイルに見えるが実体は通信の口」と覚えておけばいい。
やってはいけないこと
チャット欄にパスフレーズを打つ。
理由は4つ。
| 理由 | 内容 |
|---|---|
| ログに残る | サーバーとローカル履歴に平文で保存される |
| 復活する |
/resume で過去セッションを開くと一緒に読み込まれる |
| 記憶される | auto memory に拾われる可能性がある |
| そもそも無意味 | ssh のパスフレーズ入力は TTY 直読み。書いても通らない |
打っていいのは、非表示処理される正規の入力欄だけ。
Enter passphrase for key '/home/user/.ssh/id_ed25519':
[sudo] password for user:
この2つ以外に打つ場面はない。
もし打ってしまったら
順番が大事。履歴を消すより先に値を無効化する。
# 1. 最優先:パスフレーズを変更する
ssh-keygen -p -f ~/.ssh/id_ed25519
# 2. ローカル履歴を掃除
grep -rl "打った文字列" ~/.claude/ 2>/dev/null
rm -rf ~/.claude/paste-cache/*
# 3. auto memory も確認
grep -ri "passphrase" ~/.claude/projects/*/memory/ 2>/dev/null
# 4. シェル履歴
grep -n "打った文字列" ~/.bash_history
history -c && history -w
使い回していたら全部変える
そのパスフレーズを他のサービスでも使っていた場合、そちらが本当の実害になる。鍵ごと作り直すなら ssh-keygen -t ed25519 してから ssh-copy-id、動作確認後にサーバー側の authorized_keys から古い行を消す。
実際に起きたデプロイ事故
症状
6店舗分のデプロイが一瞬で終わった。速いのではなく、何もせずに終わっていた。
cp: cannot stat '.env.example': No such file or directory
Composer could not find a composer.json file in /var/www/html/kobe
Could not open input file: artisan
Could not open input file: artisan
(以下、6店舗分ぜんぶ同じ)
実行されたスクリプト
ssh ubuntu@xxx.xxx.xxx.xxx 'bash -s' <<'EOF'
for area in kobe kyoto nara nagoya osaka shiga; do
cd /var/www/html/${area}
mkdir -p storage/{app/public,framework/{cache,sessions,views},logs} bootstrap/cache
chmod -R 775 storage bootstrap/cache
cp .env.example .env
composer install --no-dev --optimize-autoloader
php artisan key:generate
php artisan storage:link
done
EOF
ファイルを転送する処理が一行もない。
ssh ... 'bash -s' は VPS 上でコマンドを走らせるだけ。ローカルのソースには一切触れていない。空のディレクトリに向かってセットアップを叩いただけだった。
しかも本人(claude code)に確認したら「rsync 想定」と答えた。頭の中の計画と、出力したコマンドがズレていた。
何が問題だったか
| 問題 | 内容 |
|---|---|
| 転送工程の欠落 | rsync が丸ごと抜けている |
set -e がない |
各コマンドが失敗しても止まらず、6回同じエラーを出した |
cd の失敗も無視 |
最悪カレントディレクトリで全部実行される危険があった |
| 一括実行 | 1店舗で検証せずいきなり6店舗に流した |
正しい形
# まず1店舗だけ
rsync -avz --delete \
--exclude='.env' \
--exclude='.git/' \
--exclude='vendor/' \
--exclude='node_modules/' \
--exclude='storage/' \
--exclude='bootstrap/cache/' \
/var/www/html/project/ ubuntu@xxx.xxx.xxx.xxx:/var/www/html/kobe/
送り元パスの末尾スラッシュに注意
project/ と project で結果が変わる。スラッシュ有りが「中身を送る」、無しが「ディレクトリごと送る」。
また .env と storage/ の除外は必須。稼働中の店舗に流したら、本番設定とアップロード済みファイルが飛ぶ。マルチテナントなら .env は店舗ごとに違うので、テンプレをコピーしただけでは接続できない。
デプロイスクリプトの先頭にはこれを書く。
set -euo pipefail
| オプション | 効果 |
|---|---|
-e |
エラーが出たら即座に停止 |
-u |
未定義変数を参照したらエラー |
-o pipefail |
パイプの途中で失敗しても検知 |
教訓
「エラーなく終わった」と「成功した」は別物。
そして、「rsync 想定」と言えることと、rsync を書けることは別。 計画を語れるからといって、出力が計画通りとは限らない。
なぜ現場を見ていない側のほうが気づけるのか
理解力の差ではなく立場の差。実行する側は頭の中に計画があるので、出力を計画のフィルタ越しに読んでしまう。自分が書いた文章の誤字は見つからないのと同じ。
対策としては、計画と実行を分けさせるのが効く。「まず手順を箇条書きで出せ。コマンドはまだ書くな」と一度言語化させると、抜けが可視化される。
deny ルールで縛る
承認プロンプトは押し間違える。モードは切り替わる。だが deny ルールは全モードで効く。 auto でも bypass でも無視されない。
mkdir -p ~/.claude
nano ~/.claude/settings.json
{
"permissions": {
"deny": [
"Bash(ssh:*)",
"Bash(rsync:*)",
"Bash(scp:*)",
"Read(~/.ssh/**)",
"Read(./.env)",
"Read(./.env.*)"
]
}
}
| 種類 | 挙動 |
|---|---|
| allow | 確認なしで通す |
| ask | 毎回確認 |
| deny | 絶対に通さない(allow より強い) |
動作テストはこれ。
ssh ubuntu@xxx.xxx.xxx.xxx 'ls' を実行して
承認プロンプトすら出ずに拒否されればOK。
これを入れると本番デプロイを実行できなくなる
Claude Code は「コマンドを出すだけの相棒」になる。ローカルの編集や git はそのまま任せられる。
線を引くなら「本番に触るかどうか」。全部を手動に倒すと、ただの遅いチャットになってしまう。
ウィンドウの取り違え対策
WSL、本番SSH、Claude Code、ブラウザのチャット。4つ開いていると、窓を間違える。
注意力ではなく、見た目で区別する。
# VPS側の ~/.bashrc に追記(背景赤・白文字)
PS1='\[\e[41;97m\] 本番 \[\e[0m\] \u@\h:\w\$ '
# ローカルWSLの ~/.bashrc に追記(背景緑・黒文字)
PS1='\[\e[42;30m\] LOCAL \[\e[0m\] \u@\h:\w\$ '
| 位置 | 用途 | 色 |
|---|---|---|
| 左 | ローカルWSL | 緑 |
| 中 | Claude Code | 通常 |
| 右 | 本番SSH | 赤 |
毎回同じ配置にすることが肝。「右のやつは危険」と体で覚える。
本番SSHは常時開かない
用があるときだけ開いて、終わったら閉じる。開きっぱなしだから誤爆する。これが一番本質的な対策。
詳細別記事参照 ↓
モデルの選択
/model
でその場で切り替えられる。
| 階層 | モデル | 位置づけ |
|---|---|---|
| Mythos | Claude Fable 5 | 最上位。長時間エージェント |
| Opus | Claude Opus 5 | 複雑なエージェント作業 |
| Sonnet | Claude Sonnet 5 | 日常の主力 |
| Haiku | Claude Haiku 4.5 | 最速・最安 |
Opus 5 は Max のデフォルトかつ Pro で使える最強。Sonnet 5 は Free / Pro のデフォルト。
# セッション中
/model opus
# 起動時
claude --model opus
# 恒久設定(~/.claude/settings.json)
{ "model": "opus" }
「Sonnetを基本にOpusへ escalate」という定石は前提が崩れつつある
Opus 5 は Opus 4.8 と同価格で出荷され、Frontier-Bench で 43.3 対 18.9 という差をつけた。一方 Sonnet 5 も SWE-bench Pro で 63.2%(Opus 4.8 は 69.2%)と迫っており、コーディングタスクの9割以上をこなす。
ただし今回の rsync 抜けは、モデルの能力というより手順の組み立ての問題。モデルを上げても、出力を読む習慣の代わりにはならない。
まとめ
Claude Code は強力だが、強力さの向きを間違えると事故る。ここまでで得た結論はこれ。
| 項目 | 結論 |
|---|---|
| メモリ | CLAUDE.md(手動)と auto memory(自動)の2系統。/memory で両方見える |
| 権限モード | 本番が絡むうちは manual のまま。Shift+Tab で切替 |
| 承認プロンプト | 「Yes, and don't ask again」は選ばない |
| シークレット | 環境に置く。会話に流さない。打つのは非表示入力欄だけ |
| SSH | パスフレーズは渡さない。ssh-agent に預けて署名を代行させる |
| 実行権限 | 本番に触る操作は deny で塞ぐ。コマンドをもらって自分で流す |
| 出力 | 「エラーなく終わった」を「成功した」と読み替えない |
| 環境 | 色分けとウィンドウ配置で、窓の取り違えを物理的に防ぐ |
最後に一番大事なこと。
信頼の問題ではなく、設計の問題として扱う。
人間も AI も、計画と実行がズレる。だから仕組みで縛る。deny ルールも、色分けも、1店舗ずつの検証も、全部そのための道具。
今回は空ディレクトリに composer install を流しただけで済んだ。運が良かったのではなく、承認プロンプトを読んでいたから被害が小さかった。その習慣が最大の防御になる。