😴

Claude Codeに寝てる間に働いてもらう。"bypass permissions" を事故らせない5つのポイント

に公開

はじめに

Claude Code を使っていると、ふと我に返る瞬間があります。

今日、何回 Yes を押したんだろう……

ファイルを編集するたび Edit file?、コマンドを実行するたび Run this command?、ちょっとリファクタリングを頼んだだけで何十回も承認を求められる。深夜にテスト修正を一括で投げたいのに、結局その場に張り付いて承認連打する羽目になる。

そんな悩みを解決してくれるのが、Claude Code の ⏵⏵ bypass permissions on(CLIフラグでは --dangerously-skip-permissions)です。これを有効にすれば、Claude Code は確認なしでファイル編集もコマンド実行もガンガン進めてくれます。寝る前に大きなタスクを投げて、起きたら終わってるという運用が現実的になります。

ただし、フラグ名に dangerously と入っているとおり、何も考えずに使うと事故ります。本記事では公式ドキュメントを引きながら、bypass permissions を「事故らせずに使い倒す」ための5つのポイントを共有します。


bypass permissions モードとは

Claude Code には4つのパーミッションモードがあり、対話モードでは Shift+Tab で順番に切り替わります。

bypassPermissions は、ファイル書き込み・bash実行・ネットワークアクセスを確認なしで通すモードです。一発で起動するなら以下のとおり。

claude --dangerously-skip-permissions

ここまでは「便利な機能」の話。問題はここからです。


なぜ "dangerously" と書かれているのか

公式ドキュメントにははっきりこう書かれています。

コンテナがClaude Codeを非rootユーザーとして実行し、コマンド実行をコンテナ内に閉じ込めているため、無人運用には --dangerously-skip-permissions を渡せる。CLIはroot起動時にこのフラグを拒否する。

ここから読み取れることは1つ。bypass モードは、隔離環境で動かすことを前提に設計されているということです。ホストOSにそのまま入れた Claude Code で雑に使うと、こういうリスクが顕在化します。

LLMの暴走だけでなく、プロンプトインジェクション(悪意あるリポジトリやMCPサーバ経由の指示注入)でも同じ被害が起きえます。なので、bypass を使うなら「何かあっても被害が壊滅的にならない構造」を先に作っておくのが鉄則です。

それを実現するための5つのポイントが次のセクションです。


事故らせない5つのポイント

① 隔離環境(Dev Container)で動かす

これが一番効きます。Anthropic は公式に Dev Container のリファレンス実装を提供しており、bypass モードは本来この中で使うことが想定されています。

仕組みは単純で、Docker コンテナの中で Claude Code を非rootユーザーとして動かし、ホストの ~/.ssh~/.aws には触れない構造にします。VS Code の Dev Containers 拡張で接続すれば、エディタ体験はホストと変わりません。

最低限必要なもの:

  • Docker Desktop(Mac / Windows)または Docker Engine(Linux)
  • VS Code + Dev Containers 拡張
  • プロジェクトに .devcontainer/devcontainer.json

Windows の場合は WSL2 + Docker Desktop(WSL2 backend) という構成がほぼ唯一の正解になります。プロジェクトファイルは WSL2 側の ~/projects/ 以下に置くことを忘れないでください(Windows 側の C:\ に置くと I/O が遅くて使い物になりません)。

公式リポジトリ anthropics/claude-code.devcontainer をベースにするのが手っ取り早いです。

② 秘匿情報を作業ディレクトリから追い出す

Dev Container を使う場合でも使わない場合でも、bypass モードで触れる範囲に秘匿情報を置かないのが原則です。

公式ドキュメントも以下を明示しています。

ホストの秘匿情報(~/.ssh やクラウド認証情報など)をコンテナにマウントしない。リポジトリスコープまたは短命トークンを優先せよ。

具体的なチェックリスト:

項目 やること
.env ファイル プロジェクト直下ではなく、別の安全な場所に置く(または値を環境変数で注入)
API キー Git にコミットされていないか確認(git secrets 等)
SSH 鍵 コンテナにマウントしない。GitHub 認証は短命トークンに
クラウド認証 ~/.aws/credentials をコンテナに渡さない

最悪、リポジトリ全体が外に漏れても致命傷にならない構造」を目指すと、迷ったときに判断しやすくなります。

③ Git で頻繁にコミットする

bypass モードでの暴走の被害は、結局のところ 「直前の正常な状態にどれだけ早く戻せるか」 で決まります。

  • タスクを投げる前に 必ず作業ブランチを切る
  • セッション開始前に git status がクリーンであることを確認
  • 大きなタスクの場合は中間コミットを Claude 自身に依頼しておく
    • 例:「テストが通ったタイミングで都度コミットして」

なお最近のリリースノートによると、--dangerously-skip-permissions.git/ への書き込みも承認なしで通すように変わっています。Claude が間違って git reset --hard を打つ可能性もゼロではないので、リモートに push する習慣も併せて持つと安心です(catastrophic な削除コマンドは依然として確認プロンプトが出る仕様にはなっています)。

④ ネットワークと書き込み範囲を絞る

Dev Container を使うなら、ネットワーク egress(外向き通信)を制限しておくとさらに安全です。公式の Dev Container リファレンスにも init-firewall.sh のような形でネットワーク制限の設定例が含まれています。

許可するドメインの例:

  • api.anthropic.com(Claude API)
  • registry.npmjs.org(npm)
  • pypi.org(pip)
  • github.com(git push/pull)

これを絞っておくと、プロンプトインジェクション経由で外部の怪しいエンドポイントに POST されるリスクを潰せます。

加えて、Claude Code には書き込み範囲の制限機能もあります。Claude Code はデフォルトで起動ディレクトリとそのサブディレクトリにしか書き込めないので、--add-dir を不用意に増やさないことも地味に効きます。

⑤ 「使い捨ての実験」と割り切る

5つ目は技術ではなく運用ポリシーの話です。

bypass モードは「いつでも捨てられる環境で、使い捨てのタスクを回す」ための機能と捉えるのが健全です。具体的には:

  • 顧客データや本番認証情報を含むリポジトリでは使わない
  • 共有 PC・業務 PC で他人のセッションが残っている環境では使わない
  • 「最悪コンテナごと作り直せばいい」と言える状態でだけ使う

組織で そもそも bypass を禁止したい場合は、managed settings で permissions.disableBypassPermissionsMode"disable" にすると起動自体を防げます。チーム運用では検討すべき設定です。


ハンズオン:Claude Code を Dev Container で動かす

ここまで読んで「で、結局どう始めればいいの?」となった方向けに、最小構成のセットアップ手順をまとめます。Anthropic が公式に Claude Code Dev Container Feature を提供しており、これを使えば devcontainer.json 4行で Claude Code 入りの隔離環境が立ち上がります。

前提

事前に以下を用意しておきます。

  • Docker Desktop(Mac / Windows)または Rancher Desktop / OrbStack のいずれか
    • ※ Docker は「PCの中に隔離された使い捨ての作業部屋を作るためのアプリ」と思ってください
  • VS Code(エディタ)と「Dev Containers」拡張機能
  • 試したいプロジェクトのフォルダ(空のフォルダでもOK)

ステップ1:作業部屋の設計図を1つ置く

これからやること:Claude Code 入りの「使い捨て作業部屋」を作るための設計図ファイルを1つ置きます。

プロジェクトのフォルダの直下に .devcontainer というフォルダを作り、その中に devcontainer.json というファイルを作って、以下の内容を貼り付けます。

{
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
  "features": {
    "ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}
  }
}

これだけで、Ubuntu というOSが入った作業部屋に Claude Code が自動インストールされた状態が定義できます。:1.0 はインストール用スクリプトのバージョン番号で、Claude Code 本体は常に最新版が入ります。

既にプロジェクトに devcontainer.json がある場合は、features の3行だけを追記すれば OK です。

うまくいかないとき

  • VS Code で「Reopen in Container」が出てこない
    • 原因:.devcontainer フォルダの場所が違う / ファイル名が typo
    • 対処:プロジェクトの**直下(一番上の階層)**にあるか、フォルダ名が .devcontainer(先頭がドット)になっているかを確認
  • 「JSON parse error」と出る
    • 原因:カンマやダブルクォートの閉じ忘れ
    • 対処:上のサンプルをそのままコピペし直すのが一番早い

ステップ2:ログイン状態を保存するロッカーを用意する

これからやること:1回ログインしたら次回以降は自動でログインが続くように、ログイン情報の保管場所を確保します。

このままだと、作業部屋を作り直すたびに claude ログインからやり直しになって面倒です。Claude Code はログイン情報を ~/.claude というフォルダに保存するので、そこを「使い捨てされない倉庫(ボリューム)」に紐付けます。

{
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
  "features": {
    "ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}
  },
  "mounts": [
    "source=claude-code-config-${devcontainerId},target=/home/vscode/.claude,type=volume"
  ],
  "remoteUser": "vscode"
}

ポイント:

  • ${devcontainerId} という呪文を入れておくと、プロジェクトごとに別の倉庫になり、ログイン情報が混ざりません
  • target のパス(/home/vscode/.claude)の vscode の部分は、最後の remoteUser の値と一致させること

うまくいかないとき

  • 再ビルドのたびに毎回ログインを求められる
    • 原因:target のパスと remoteUser がズレている
    • 対処:両方の vscode を揃える。別のユーザー名を使うなら両方をその名前に変える

ステップ3:作業部屋を起動して Claude にログインする

これからやること:設計図から作業部屋を実際に立ち上げて、Claude にサインインします。

VS Code でプロジェクトを開き、コマンドパレット(Mac は Cmd+Shift+P、Windows / Linux は Ctrl+Shift+P)を開いて Dev Containers: Reopen in Container を実行します。

初回はビルドに数分かかります。完了するとターミナルが作業部屋の中に切り替わるので、そこで以下を実行:

claude

ブラウザが開いて Anthropic アカウントでログインを求められます。

うまくいかないとき

  • ブラウザでログインしたのにターミナルが反応しない
    • 原因:ブラウザからの応答が作業部屋まで戻ってこない
    • 対処:ブラウザ画面に表示されているコードをコピーして、ターミナルの Paste code here if prompted という表示の場所に貼り付ける
  • claude: command not found と出る
    • 原因:コンテナのビルドに失敗している
    • 対処:VS Code の上部メニュー → 表示出力(Output)→ 右上のドロップダウンで「Dev Containers」を選び、エラー内容を確認
  • そもそもビルドが始まらない
    • 原因:Docker Desktop が起動していない
    • 対処:Docker Desktop のクジラアイコンを起動し、「Engine running」になってから再試行

ステップ4:承認スキップモードで Claude を起動する

これからやること:いちいち「実行していい?」と聞かれない状態で Claude を起動します。

ここが本記事の本題です。

claude --dangerously-skip-permissions

このフラグは 管理者ユーザー(root)で起動した場合にエラーで弾かれます。これは安全装置で、ステップ2で remoteUser: "vscode" と指定したのはこのためです。

うまくいかないとき

  • Cannot run as root のようなエラーが出る
    • 原因:作業部屋が管理者ユーザーで動いている
    • 対処:ターミナルで whoami を実行。root と表示されたら NG。vscodenode などが表示されればOK。devcontainer.jsonremoteUser を非rootユーザー名に直してビルドし直し

ステップ5:Anthropic 公式の完成形をそのまま動かしてみる

これからやること:Anthropic が「これが想定している使い方」として公開しているお手本を丸ごとコピーして起動します。インターネット接続まで制限された堅い環境を体験できます。

ステップ1〜4 の構成は最小限で動きますが、本気で「寝てる間に動かす」運用をするなら、ネットワーク制限まで入った完成形を使うのが安心です。Anthropic の公式リポジトリにお手本があるので、まずはこれをそのまま動かします。

ターミナルで以下を実行:

git clone https://github.com/anthropics/claude-code.git
cd claude-code
code .

VS Code が起動するので、画面右下に出る「Reopen in Container」をクリック。ビルドが走り、起動時に init-firewall.sh というスクリプトが自動実行されて、許可リストに無いインターネット接続が全部遮断された状態になります。

うまくいかないとき

  • git: command not found と出る
    • 原因:PCに Git がまだ入っていない
    • 対処:Git公式サイト からインストール。Mac なら xcode-select --install でも可
  • ビルドの最後で init-firewall.sh: Permission denied のようなエラー
    • 原因:ファイアウォール設定に必要な権限が作業部屋に渡っていない
    • 対処:通常はリポジトリの devcontainer.json で設定済みなので、ファイルを書き換えていなければ起きないはず。書き換えた場合は runArgs--cap-add=NET_ADMIN --cap-add=NET_RAW が消えていないか確認

.devcontainer/ に入っている3ファイル

ファイル 役割
devcontainer.json ボリューム・capability・拡張機能・起動フックの定義
Dockerfile ベースイメージ + Claude Code + iptables / sudoers セットアップ
init-firewall.sh iptables と ipset で許可ドメイン以外を遮断するスクリプト

それぞれの「ここ重要」だけ抜粋します。

devcontainer.json の要点

{
  "build": { "dockerfile": "Dockerfile" },
  "runArgs": [
    "--cap-add=NET_ADMIN",
    "--cap-add=NET_RAW"
  ],
  "remoteUser": "node",
  "mounts": [
    "source=claude-code-bashhistory-${devcontainerId},target=/commandhistory,type=volume",
    "source=claude-code-config-${devcontainerId},target=/home/node/.claude,type=volume"
  ],
  "postStartCommand": "sudo /usr/local/bin/init-firewall.sh",
  "waitFor": "postStartCommand"
}
  • runArgsNET_ADMIN / NET_RAW を付与(iptables 操作に必須)
  • remoteUser: node非root(bypass モードの前提)
  • mountsbash履歴~/.claude をプロジェクトごとに永続化
  • postStartCommand でファイアウォール初期化 → waitFor で完了を待ってから操作可能に

Dockerfile の要点

FROM node:20

# 開発ツール + iptables/ipset をインストール
RUN apt-get update && apt-get install -y --no-install-recommends \
    iptables ipset iproute2 dnsutils aggregate jq \
    git gh sudo zsh fzf ...

# 通常作業は非rootの node ユーザー
USER node

# Claude Code 本体をインストール
RUN npm install -g @anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}

# ファイアウォール初期化スクリプトだけ NOPASSWD で root 権限を借りる
COPY init-firewall.sh /usr/local/bin/
USER root
RUN chmod +x /usr/local/bin/init-firewall.sh && \
    echo "node ALL=(root) NOPASSWD: /usr/local/bin/init-firewall.sh" \
      > /etc/sudoers.d/node-firewall && \
    chmod 0440 /etc/sudoers.d/node-firewall
USER node

賢いポイントは 「通常は非root、ファイアウォール初期化だけ sudo で root を借りる」 という設計です。bypass モードの前提(非root)を満たしつつ、iptables を扱う権限を最小限の範囲で確保しています。

init-firewall.sh の許可ドメイン

スクリプト内でホワイトリストされている主なエンドポイント:

  • api.anthropic.com(Claude API)
  • registry.npmjs.org(npm)
  • marketplace.visualstudio.com, vscode.blob.core.windows.net, update.code.visualstudio.com(VS Code 関連)
  • GitHub の IP レンジ(api.github.com/meta から動的取得)
  • sentry.io, statsig.anthropic.com, statsig.com(テレメトリ)

これ以外は 全部ブロック。プロンプトインジェクション経由で外部の怪しいサーバに認証情報を POST されるリスクを物理的に潰せます。Python プロジェクトなら pypi.orgfiles.pythonhosted.org を、自前のクラウドエンドポイントなら該当ドメインを追記すればOKです。

自分のプロジェクトに移植する

リファレンスを試して気に入ったら、.devcontainer/ を丸ごと自分のリポジトリにコピーします。

cp -r claude-code/.devcontainer your-project/
cd your-project
# Dockerfile を自分のツールチェーンに合わせて修正
# init-firewall.sh の許可ドメインを必要に応じて追加
code .

これでステップ1〜4の最小構成より一段堅い環境ができます。寝ている間に bypass モードで動かす運用は、ここまでやって初めて「事故っても被害が壊滅的にならない」状態になります。

番外編:チーム全体で承認スキップを禁止したいとき

これからやること:「うちのチームでは承認スキップは絶対NG」というポリシーを作業部屋に強制的に埋め込みます。

逆方向のニーズもあります。組織で bypass モードを禁止したい場合は、コンテナの中に「これは禁止です」というルールファイルを置いておきます。

Dockerfile に以下を追加:

RUN mkdir -p /etc/claude-code
COPY managed-settings.json /etc/claude-code/managed-settings.json

そして managed-settings.json の中身は:

{
  "permissions": {
    "disableBypassPermissionsMode": "disable"
  }
}

これで claude --dangerously-skip-permissions は起動時点でエラーになります。

ただし注意点が1つ。リポジトリのファイルを書き換えられる人なら、Dockerfile から上の行を消すだけで禁止を解除できてしまいます。本気で禁止したいなら、PCの管理ソフト(MDM)やサーバー管理設定経由で配信するのが正解です(公式ドキュメントでも同じことが書かれています)。


寝てる間に動かす実践パターン

ここまでの5つのポイントを踏まえた上で、本記事の主題である「寝てる間に動かす」運用を紹介します。

ポイントは、対話モードではなく headless モード-p フラグ)を使うことです。指示を1回投げて、Claude Code が完走するか諦めるかするまで放置できます。

コマンド例

例えば「全テストを通るまでリファクタリングして」というタスクを丸投げする場合:

claude -p "src/ 配下の TypeScript コードを ESLint と Prettier に従って整形してください。
テストがすべて通るまで修正を繰り返し、各段階で commit してください。
不明点があった場合は、その時点でいったん停止してログに記録してください。" \
  --dangerously-skip-permissions \
  --output-format stream-json \
  > ~/claude-logs/$(date +%Y%m%d-%H%M).log 2>&1

寝る前のチェックリスト

  • 作業ブランチに切り替わっている
  • git status がクリーン
  • Dev Container 内で動かしている
  • 機微なファイル(.env など)が作業ディレクトリにない
  • ログのリダイレクト先を指定している
  • 寝る場所と PC の電源が確保されている(地味に重要)

起きた後のチェックリスト

  • git log --oneline で何回コミットしているか
  • git diff main..HEAD で変更全体をざっと眺める
  • テストが通っているか
  • ログに警告やエラーが出ていないか
  • 想定外のファイル変更がないか(特にトップレベルの設定ファイル)

問題なければそのまま push、怪しければ git reset --hard origin/main で巻き戻して再投入。


まとめ

最後に5つのポイントを再掲します。

  1. 隔離環境(Dev Container)で動かす — bypass の本来の前提
  2. 秘匿情報を作業ディレクトリから追い出す — 漏れても致命傷にしない
  3. Git で頻繁にコミットする — 暴走時の戻り先を確保
  4. ネットワークと書き込み範囲を絞る — 被害の上限を決める
  5. 「使い捨ての実験」と割り切る — 本番系では使わない

この5つを守れば、bypass permissions は 「承認プロンプトをスキップする危ない機能」 ではなく、「寝てる間にタスクを完走させてくれる頼れる機能」 になります。

Claude Code の真価は、「人間が画面の前に張り付いている時間」よりも「張り付かなくていい時間」を増やせることだと最近感じています。承認プロンプトに疲れている方は、まず Dev Container を1つ用意するところから始めてみてください。


参考資料

Discussion