Claude Code のおすすめ設定、存在しないキーは黙って捨てられる

目次
  1. 貼った設定が効かないとき、何も教えてくれない
  2. doctor は型エラーを名指しするが、知らないキーは無言で通す
  3. 記事が勧めるキーを37個+対照4個通した — 15個が無言だった
  4. キーが正しくても捨てられる — 信頼とタイポの3状態
  5. 死んだキーは挙動でも無言 — autoUpdates が止まらない
  6. 貼る前の確認手順 — probe で潰せるもの、潰せないもの

「Claude Code 設定 おすすめ」で出てくる記事を読んで、settings.json にキーを貼る。効いたかどうかを教えてくれるものは、どこにもない。存在しないキーは JSON として正しく、型も正しいので、エラーにならないまま読み捨てられる。設定したつもりのまま運用が続く。

実害はすでに報告されている。自動更新を止めるために autoUpdates: false を書いたのに更新が止まらなかった、という issue が上がっている(Claude Media のまとめ)。キーは変わり続ける。廃止・改名が起きても、貼った側には何も通知されない。

このサイトでも「設定したのに効かない」は2回扱っている。deny ルールの書き方が参照されない話と、フックが黙って効かなくなる話である。あちらは「正しいキーの中身」や「動いているフック」の話だった。今回測るのはその手前で、キー名そのものが本体に存在するかである。私は記事が勧めるキーを自分のバージョンに通して数えた。

貼った設定が効かないとき、何も教えてくれない

測った環境はこれだけである。

$ sh env.sh
ProductName:		macOS
ProductVersion:		26.6.1
BuildVersion:		25G76
v22.21.1
2.1.267 (Claude Code)
# exit=0 (28 ms)

検証は隔離した HOME で行った。verify/workspace/home を HOME に設定し、プロジェクト側は proj/.claude/settings.json を使う。実環境の ~/.claude は触らない。隔離は結果として正しかった —— 検証の途中でその HOME 内の .claude.json を消したところ、起動時に「設定ファイルが見つからない、バックアップがある」という通知が出た(verify/logs/005-typo-demo.txt)。~/.claude.json は CLI が内部状態を書き込むファイルで、消すと信頼状態などが吹き飛ぶ。普段の HOME でこういう実験をするのは危ない。

設定が効かない原因には「そのファイルが読まれていない」と「ファイルは読まれたが中身が捨てられた」がある。前者はファイルの置き場所と優先順位の話で、公式ドキュメントにも表がある。私が測るのは後者で、こちらは表に載らない。どの場所に置いても、存在しないキーは存在しない。

doctor は型エラーを名指しするが、知らないキーは無言で通す

claude doctor はカレントディレクトリの settings.json を読み、「Invalid settings」節に検証エラーを出す。まずこれが何を見るかを較正した。既知キーへの型違反、存在しないキー、typo、JSON 破損の4ケースを用意して流した。

$ sh calibrate.sh
=== case1: known key, wrong type ===
Invalid settings
- ./.claude/settings.json › cleanupPeriodDays: Expected number, but received undefined
- ./.claude/settings.json › permissions.allow: Expected array, but received undefined
  Suggested fix: Permission rules must be in an array. Format: ["Tool(specifier)"]. Examples: ["Bash(npm run build)", "Edit(docs/**)", "Read(~/.zshrc)"]. Use * for wildcards.
- ./.claude/settings.json › model: Expected string, but received undefined
...
=== case2: unknown keys, valid JSON ===
(end of case2 doctor output)
=== case3: typo of a known key ===
(end of case3 doctor output)
=== case4: malformed JSON ===
Invalid settings
- ./.claude/settings.json: Expected object, but received undefined
# exit=0 (1250 ms)

case1 では既知キーの型違反をキー名つきで名指しし、修正案まで出す。case4 の JSON 破損も拾う。だが case2(telepathy、superMode、maxTokens という存在しないキー)と case3(permissions の typo、permisions)は何も出なかった。

この非対称はそのまま判定器になる。わざと間違った型を入れて、名指しされればそのキーは本体が知っている。無言なら知らない。 probe の芯はこれだけである。

printf '{"%s": "x"}\n' "キー名" > .claude/settings.json
claude doctor 2>&1 | grep -A2 "Invalid settings"

数値型のキーは "x" の代わりにオブジェクトなど別の型を入れる。1個ずつ settings.json に書いて回すシェルスクリプトを書き、数値・文字列・オブジェクト・配列・真偽値の5種類の型で probe した。5種類に分けたのは、たまたま正しい型を引いて「存在するのに無言」と取り違えないためである。

記事が勧めるキーを37個+対照4個通した — 15個が無言だった

おすすめ設定記事と公式リファレンスからキーを集め、対照の架空キー4個(telepathy、superMode、permisions、maxTokens)を混ぜて計41個を通した。内訳は記事由来37個と対照4個である。

$ sh census.sh
RECOGNIZED apiKeyHelper (4/5 probes flagged)
...
SILENT     editorMode (0/5 probes flagged)
SILENT     theme (0/5 probes flagged)
...
SILENT     autoUpdaterStatus (0/5 probes flagged)
SILENT     autoUpdates (0/5 probes flagged)
...
SILENT     autoCompact (0/5 probes flagged)
...
TOTAL_KEYS=31
# exit=0 (41735 ms)
$ sh summarize.sh
probed_keys=41
recognized=26
silent=15
...
# exit=0 (11 ms)
26keysrecognized15keyssilent
41キーのprobe結果

RECOGNIZED が 4/5 で止まるのは、残りの1probeがたまたま正しい型だったからである。3キーで内訳を見ると分かりやすい。

$ sh per-probe.sh
cleanupPeriodDays probe=12345 -> silent
cleanupPeriodDays probe="x" -> flagged
cleanupPeriodDays probe={"__x":0} -> flagged
cleanupPeriodDays probe=[0] -> flagged
cleanupPeriodDays probe=true -> flagged
permissions probe=12345 -> flagged
permissions probe="x" -> flagged
permissions probe={"__x":0} -> silent
permissions probe=[0] -> flagged
permissions probe=true -> flagged
hooks probe=12345 -> flagged
hooks probe="x" -> flagged
hooks probe={"__x":0} -> flagged
hooks probe=[0] -> flagged
hooks probe=true -> flagged
# exit=0 (4161 ms)

cleanupPeriodDays は数値 probe だけ通った。hooks はオブジェクト内の未知キーまで弾くので5/5すべて引っかかった。面白いのは permissions で、{"__x":0} が silent —— トップレベルだけでなく、オブジェクトの中の未知サブキーも黙って捨てられる。無言の読み捨ては再帰的である。

無言だった15個を、公式 settings リファレンスの索引に載っているかで分けると、3種類に分かれた。

$ sh summarize2.sh
not-in-index            autoCompact
documented-but-unchecked autoCompactWindow
not-in-index            autoUpdaterStatus
not-in-index            autoUpdates
documented-but-unchecked editorMode
documented-but-unchecked effortLevel
documented-but-unchecked forceLoginMethod
not-in-index            maxTokens
not-in-index            permisions
documented-but-unchecked preferredNotifChannel
documented-but-unchecked spellcheck
not-in-index            superMode
not-in-index            telepathy
documented-but-unchecked theme
documented-but-unchecked vimInsertModeRemaps
documented_but_unchecked=8
not_in_index=7
# exit=0 (28 ms)

対照の4個を除くと、無言の内訳は2種類になる。

1つ目は、索引に無い死んだキー。autoUpdaterStatus はかつて存在したキーで、claude config set が受け付けるキーの一覧に載っていた時期がある(GitHub issue #114)。その後 autoUpdates に変わり、現在は両方とも索引から消えている。autoCompact も同様で、--autocompact フラグや /autocompact コマンドは存在するが、settings.json のキーは autoCompactEnabled と autoCompactWindow である。

$ sh census2.sh
RECOGNIZED autoCompactEnabled (4/5)
SILENT     autoCompactWindow (0/5)
...
=== enum violation on documented-but-unchecked keys ===
SILENT  theme" (bad enum value passed)
SILENT  editorMode" (bad enum value passed)
SILENT  preferredNotifChannel" (bad enum value passed)
SILENT  forceLoginMethod" (bad enum value passed)
=== enum violation on doctor-checked key ===
Invalid settings
- ./.claude/settings.json › autoUpdatesChannel: Invalid value. Expected one of: "latest", "stable", "rc"
  Suggested fix: Valid values: "latest", "stable", "rc"
# exit=0 (14356 ms)

2つ目は、索引にはあるのに doctor の型検査が及ばないキー。theme、editorMode、preferredNotifChannel、forceLoginMethod、autoCompactWindow、effortLevel、spellcheck、vimInsertModeRemaps の8個である。theme に存在しない値 no-such-theme を入れても無言だった。対照的に autoUpdatesChannel への enum 違反は、有効値の一覧つきで止めてくれる。doctor の検査は全キーに及んでいない。つまり doctor が無言を返すのは「死んだキー」と「検査を省略された正式キー」の両方で、無言は無害の意味を持たない。

キーが正しくても捨てられる — 信頼とタイポの3状態

permissions.allow は正しいキーでも、workspace が未信頼だと起動時に捨てられる。このときは警告が出る。だがキー名を typo すると、その警告すら出ない。

$ sh trust-demo.sh
=== state1: untrusted workspace ===
Ignoring 1 permissions.allow entry from .claude/settings.json: this workspace has not been trusted. Run Claude Code interactively here once and accept the trust dialog, or set projects["<repo-root>"].hasTrustDialogAccepted: true in ~/.claude.json.
=== state2: trusted workspace ===
(no output above = warning gone, rule loaded)
=== state3: typo key, trusted workspace ===
(no output above = key never read)
# exit=0 (564 ms)

state1 は「読まれたが信頼判定で捨てられた」。state2 で信頼を入れると警告が消え、ルールが読み込まれる。state3 の permisions では警告が出ない。キーが捨てられた時点で、中身の allow ルールは権限チェックに一度も届かない。警告が出る捨てられ方と、無言の捨てられ方は別物である。

死んだキーは挙動でも無言 — autoUpdates が止まらない

「エラーが出ない」だけなら半分の話で、実際に何も起きないことを挙動で確かめた。自動更新を止めるつもりで死んだキーを書いた場合と、正規の env.DISABLE_AUTOUPDATER を書いた場合を比べる。このシェルには DISABLE_AUTOUPDATER が環境変数として入っていたので、env -u で外してから測った。

$ sh autoupd-demo.sh
=== settings: {"autoUpdates": false, "autoUpdaterStatus": "disabled"} ===
Auto-updates: enabled
Auto-update channel: latest
(no Invalid settings section = dead keys passed silently)
=== settings: {"env": {"DISABLE_AUTOUPDATER": "1"}} ===
Auto-updates: disabled (set by env: DISABLE_AUTOUPDATER)
Auto-update channel: latest
# exit=0 (512 ms)

autoUpdates: false を書いても自動更新は enabled のままで、エラーも警告も出ない。env 経由で DISABLE_AUTOUPDATER を書いた場合だけ disabled になった。「止めたはずが止まっていない」はこうやって成立する。記事が勧めるキーの中に、こうした死んだキーが混ざっている。

貼る前の確認手順 — probe で潰せるもの、潰せないもの

おすすめ設定をコピペする前に、3つの確認で潰せる。

1つ目、キー名を公式 settings リファレンスの索引で引く。autoUpdaterStatus や autoCompact のような改名・廃止済みキーはここで落ちる。記事が古いほど索引との乖離は出やすい。

2つ目、doctor の probe。settings.json にそのキーへわざと違う型を入れて claude doctor を走らせ、Invalid settings で名指しされれば、そのキーは確実に認識されている。ただし無言には2つの意味がある —— 「存在しない」か「存在するが検査対象外」か。theme のような正式キーも無言を返すので、silent は索引との照合までが判定である。probe だけで「無い」と断定してはいけない。

3つ目、permissions 系は workspace の信頼状態を見る。キーが正しくても未信頼なら allow ルールは捨てられる。こちらは警告が出る側なので、起動時の Ignoring 行を見れば分かる。

逆に、今回の測定で「存在し、型検査も効く」と確認できたキーは cleanupPeriodDays、model、permissions、hooks、env、statusLine、outputStyle、autoUpdatesChannel、autoCompactEnabled など26個である。存在確認済みのキーだけで設定を組むなら、この一覧側から選ぶのが近道になる。挙動まで確かめたのは env.DISABLE_AUTOUPDATER と permissions の信頼ゲートだけなので、残りは「読まれる」までの保証である。

限界も書く。今回の測定は 2.1.267 であり、キーの生死はバージョンで動く。includeCoAuthoredBy のように廃止予定と注記されつつ recognized だったキーもある。認証が要るセッション内の /doctor や、設定した値が実際の挙動をどう変えるかの全般までは見ていない。だが「貼ったものが読まれたか」を貼る前に潰すだけなら、この手順で足りる。

設定は「書いた」ではなく「読まれた」で初めて効く。おすすめの一覧を探すより先に、自分のバージョンがそのキーを知っているかを確かめるほうが早い。

関連書籍