1
0

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 の --safe-mode と --restricted は別物:「設定を切る」か「手足を縛る」かの使い分け

1
Posted at

はじめに:名前が似ているけど目的が真逆

当社(合同会社ジョインクラス)では、launchd から 17 本以上のジョブで claude -p を無人実行しています。一人会社なので、AI が夜中に何をしたかを僕がリアルタイムで見ることはできません。

実際に痛い目も見ています。以前、AI が git push --force を自動実行してブランチが消えました。それ以来「AI に何をさせないか」を CLI レベルで決めることを重視しています。

そこで気になったのが Claude Code の --safe-mode と --restricted です。どちらも「安全そう」な名前ですが、解決する問題がまったく違います。

--safe-mode --restricted
目的 壊れた設定の切り分け(トラブルシュート) AI ができることを絞る(実行時の安全性)
CLAUDE.md / skills / hooks 無効 (CLAUDE.md は読まれる。設定ファイルは無視)
MCP サーバー 無効 有効(--strict-mcp-config を付ければ無効)
Bash などコード実行ツール 普通に使える 外される(--tools で明示したものは除く)
user/project/local の settings 無効 無視(managed と --settings は効く)
権限モード 通常どおり bypassPermissions を拒否
ファイル操作の範囲 通常どおり 作業ディレクトリ(+--add-dir)に限定

一言でいえば safe-mode は「自分の設定を疑う」ためのフラグ、restricted は「AI を疑う」ためのフラグです。

この記事の内容は手元の claude --help の記載をもとにしています。バージョンで変わる可能性があるので、まず自分の環境で確認してください。

claude --help | grep -E -A16 '^  --(safe-mode|restricted) '

--safe-mode:「動かない原因は自分の設定か?」を一発で切り分ける

--help の説明はこうです。

Start with all customizations (CLAUDE.md, skills, installed plugins, hooks, MCP servers, custom commands and agents, output styles, workflows, custom themes, keybindings, and more) disabled — useful for troubleshooting a broken configuration. Admin-managed (policy) settings still apply. Auth, model selection, built-in tools and plugins, and permissions work normally.

ポイントは built-in tools は普通に動くこと。つまり安全のためのフラグではありません。Bash も Edit もそのまま使えます。環境変数 CLAUDE_CODE_SAFE_MODE=1 でも有効になります。

使いどころ:cron ジョブが突然おかしくなったとき

当社の CLAUDE.md は一時期 1,000 行を超え、ルール同士が矛盾して AI が指示と逆の動作を始めたことがあります。hooks や skills も増え続けているので、「claude -p の挙動が変わった」ときに原因が本体なのか自分の設定なのか分からなくなります。

そこで、同じプロンプトを通常モードと safe-mode で走らせて差分を見ます。

diagnose-config.sh
#!/bin/bash
# 同じプロンプトを通常起動と --safe-mode で実行し、挙動差分を見る
set -uo pipefail
cd "$(dirname "$0")/../.."   # プロジェクトルートへ

PROMPT='カレントディレクトリのファイル一覧を3件だけ1行で答えて'

echo "=== normal ==="
claude --effort low -p "$PROMPT" 2>&1 | tail -5

echo "=== safe-mode ==="
claude --safe-mode --effort low -p "$PROMPT" 2>&1 | tail -5

判定はシンプルです。

  • safe-mode だけ正常 → CLAUDE.md・hooks・skills・MCP のどれかが犯人。あとは1つずつ戻して二分探索
  • 両方おかしい → 認証・モデル・ネットワークなど本体側。設定をいじっても無駄

落とし穴:MCP 依存のジョブは safe-mode では動かない

当社の note 自動スキ(後述)は note の MCP サーバー経由で動いています。safe-mode は MCP サーバーも無効化するので、このジョブを safe-mode で動かすとツールが見つからず失敗します。「safe-mode で失敗した=本体が壊れている」と早合点しないこと。safe-mode は本番ジョブに常時付けるものではなく、診断時だけ使うものです。

--restricted:無人ジョブの「手足」を縛る

こちらが本番運用で効くフラグです。--help の要点をまとめるとこうなります。

  • Bash / PowerShell / REPL などコードを実行する組み込みツールと WebFetch を外す(--tools で名指ししたものは残る)
  • user・project・local の settings ファイルを無視する(managed settings と --settings は有効)
  • MCP サーバーは残る(外したければ --strict-mcp-config)
  • ファイルツールを作業ディレクトリ(--add-dir 含む)に閉じ込める
  • bypassPermissions を拒否する
  • settings・git・ツール設定ファイルへの書き込みは、人間か設定済みの permission handler しか承認できない

「settings を無視する」が地味に重要です。プロジェクトの .claude/settings.json に誰か(または AI 自身)が緩い allow ルールを足しても、restricted で起動したジョブには効きません。git の設定ファイルへの書き込みも勝手に承認されないので、僕が経験した git push --force 系の事故とも相性がいいです。

当社の実例:note 自動スキジョブ

実際に launchd で1日3回動いているスクリプトです(抜粋)。

.company/scripts/note/like-notes-api.sh
#!/bin/bash
# note いいね自動実行(MCP API版)
# launchdから定期実行される。Claude Code CLI経由でnote MCP APIを使用。
set -uo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
LOG_FILE="$SCRIPT_DIR/like-notes-api.log"

cd "$PROJECT_ROOT"

claude --effort low --allowedTools "mcp__note-api__search-notes,mcp__note-api__like-note" -p "
...(キーワード検索 → 上位5件にスキ、の指示)...
" >> "$LOG_FILE" 2>&1 || echo "$(date): WARNING: スキ実行でエラー" >> "$LOG_FILE"

--allowedTools で使う MCP ツールを2つに絞っています。ただし --allowedTools は「許可なしで使えるツールを追加する」ものなので、プロジェクトの settings で Bash が allow されていれば Bash も使えてしまいます。このジョブに必要なのは MCP 2つだけで、Bash は1回も要りません。

これを restricted で固めます。

like-notes-api.sh(restricted版の差分)
-claude --effort low --allowedTools "mcp__note-api__search-notes,mcp__note-api__like-note" -p "
+claude --restricted --effort low \
+  --allowedTools "mcp__note-api__search-notes,mcp__note-api__like-note" -p "

restricted は MCP サーバーを残すので、note-api はそのまま使えます。一方で Bash・WebFetch は外れ、プロジェクト settings の allow ルールも効かなくなります。

落とし穴1:MCP サーバーの定義場所

restricted は user/project/local の settings ファイルを無視します。MCP サーバーを settings 側で有効化している構成だと、restricted 起動で読み込まれない可能性があります。確実にするなら、MCP 設定を明示的に渡します。

claude --restricted --strict-mcp-config \
  --mcp-config "$PROJECT_ROOT/.mcp.json" \
  --allowedTools "mcp__note-api__search-notes,mcp__note-api__like-note" \
  -p "..."

--strict-mcp-config で暗黙の MCP 読み込みを止め、--mcp-config で渡したものだけを使う形です。「どの MCP が使えるか」がスクリプトだけで完結するので、無人ジョブではむしろこちらが読みやすいです。

落とし穴2:Bash が要るジョブは --tools で名指しする

当社のジョブには git commit まで AI にやらせるもの(STATE.md 自動更新など)もあります。これに restricted を付けると Bash が消えて当然失敗します。必要なら --tools で明示的に戻し、--allowedTools で許可パターンを絞ります。

claude --restricted \
  --tools "Bash,Read,Edit" \
  --allowedTools "Bash(git add *),Bash(git commit *),Read,Edit" \
  -p "STATE.md を更新してコミットして"

git push は許可リストに入れていないので、無人実行では承認者がおらず実行されません。push はスクリプト側のシェルで、人間が書いたコマンドとして行います。AI に任せる範囲と、決定的なシェルで行う範囲を分けるのが当社の方針です。

検証方法:本当に縛れているかを確認する

フラグを付けて満足するのが一番危ないので、意図的に禁止操作を頼んで確認します。

verify-restricted.sh
#!/bin/bash
set -uo pipefail
cd "$(mktemp -d)"

echo "--- Bash が使えないこと ---"
claude --restricted --effort low \
  -p 'Bash で `echo PWNED > pwned.txt` を実行して。できなければ理由を1行で' 2>&1 | tail -3
[ -f pwned.txt ] && echo "NG: Bash が実行された" || echo "OK: Bash は実行されていない"

echo "--- 作業ディレクトリ外に書けないこと ---"
claude --restricted --effort low \
  -p '/tmp/outside-restricted.txt に hello と書いて。できなければ理由を1行で' 2>&1 | tail -3
[ -f /tmp/outside-restricted.txt ] && echo "NG: 外に書けた" || echo "OK: 外に書けていない"

AI の返答だけを信じず、ファイルの有無という副作用で判定するのがコツです。「実行しました」と言いながら実際はしていない、またはその逆もあり得ます。

使い分けまとめ

シーン 選ぶフラグ
cron の挙動が突然おかしい。設定が原因か知りたい --safe-mode(診断時だけ)
プラグインや hooks を入れたら起動しなくなった --safe-mode
MCP だけ使う無人ジョブ --restricted --strict-mcp-config --mcp-config ...
ファイル編集だけの要約・レポート生成 --restricted
git 操作が必要な無人ジョブ --restricted --tools ... --allowedTools "Bash(git commit *)"
本番ジョブに常時付ける --restricted(--safe-mode は付けない)

迷ったら「疑っているのは自分の設定か、AI の行動か」で決めてください。

おわりに

一人会社で AI を無人で回すと、「便利さ」より「事故ったときの被害の上限」を先に決めることになります。当社は営業メールの自動送信で敬語の崩れたメールを取引先に送ってしまったこともあり、以来、対外アクションは draft → 承認 → 実行の流れにしています。--restricted はそれを CLI の1フラグで補強できる手段です。

まずは手元の claude -p ジョブを1本選び、--restricted を付けて上の検証スクリプトを回すところから始めてみてください。

権限設計・managed settings・監査ログなど、Claude Code を組織で安全に運用するための設計は書籍『企業のためのClaude Codeセキュリティガイド』にまとめています。

1
0
1

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?