[FEATURE] Mid-session settings reload (slash command + hook output flag)
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Claude Code reads .claude/settings.local.json into a session's
in-memory state once at session-init, and there's no exposed mechanism
to make that state refresh during the session's lifetime. The
lifecycle ordering also appears to put this read beforeSessionStart hooks fire, which makes SessionStart hooks structurally
unable to influence the session's allowlist — they can write to the
file, but the in-memory state is already fixed.
Concrete symptom — multi-worktree workflow:
A user's permissions.allow list lives in the main checkout'ssettings.local.json and is propagated to each worktree by aSessionStart hook. When a brand-new session opens in a worktree:
- Claude reads worktree's
settings.local.json— empty or minimal. - In-memory allowlist = whatever was on disk just now.
SessionStarthook fires → overwrites the worktree file with the
main checkout's content.
- File is now correct; in-memory is still empty.
- User runs a command that is in the main allowlist. Picker fires
because in-memory doesn't know about the rule.
There's no recovery within the session — the user has to approve the
rule (re-prompt), or quit and restart Claude. The re-prompt itself is
poor UX; what's worse is that the picker's atomic-rename write
produces a minimal settings.local.json containing only the newly
approved rule, dropping everything the SessionStart hook had written.
So the next session start in that worktree also begins from minimal.
Beyond worktree-permission propagation, the same load-order /
no-reload issue blocks several other workflows:
| Workflow | Blocked because |
| --- | --- |
| External edit while a session is open | User edits settings.local.json in their editor; session keeps using pre-edit allowlist until restart. |
| Team allowlist sync | Background job pulls team-approved rules into settings.local.json; user can't pick up new rules without restart. |
| Rule revocation | Admin removes a rule from the file; existing sessions retain it in memory; a picker write in any of those sessions can resurrect it via ConfigChange re-unioning the stale in-memory state back. |
| MCP server enable/disable | Toggling enabledMcpjsonServers requires session restart. |
Proposed Solution
Expose a mid-session settings reload mechanism with two surfaces,
same underlying machinery:
1. User-invokable slash command — e.g. /reload-settings.
Re-reads ~/.claude/settings.json, the project's.claude/settings.json, and .claude/settings.local.json from disk
and replaces the session's in-memory state for the reloadable keys.
2. Hook-triggered reload — any hook returns a flag in itshookSpecificOutput:
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"reloadSettings": true
}
}
After the hook returns successfully, Claude Code re-reads settings
before proceeding. Valid for hook events that aren't mid-tool-call
(SessionStart, ConfigChange, UserPromptSubmit, etc.). ForPreToolUse the reload happens before the tool call resumes.
Scope of reload — "all settings except hooks": reloadpermissions.{allow,deny,defaultMode}, enabledMcpjsonServers,outputStyle, editorMode, and other static configuration. Thehooks block stays frozen for the session's lifetime — avoids the
"what happens to a hook that's currently running" edge case and
matches existing user-visible behavior (you can't add/remove hooks
mid-session by editing settings.json today either, so this isn't a
regression).
Explicit-only, no auto-reload on file change. A sync tool or
editor saving settings.local.json shouldn't trigger surprise
behavior changes mid-session. Auto-reload could be a follow-up FR if
the explicit version proves out.
Alternative Solutions
In rough order from smallest to largest surface change — any of
these would partially address the same workflows:
- (a) Document the lifecycle. State explicitly when
settings.local.json is read relative to SessionStart. Even
just a documentation change gives userspace tooling a real
contract to design against. (Current docs at
code.claude.com/docs/en/hooks don't say.)
- **(b) Auto re-read
settings.local.jsonafterSessionStart
returns.** No new event, no new hook payload — just move the
read to after SessionStart returns. Fixes the worktree
first-session case automatically. Smallest behavior change.
This is effectively the proposed reload, fired
unconditionally after SessionStart, without the slash command
surface.
- (c) A
PreSessionStart/SettingsLoadhook event. Hooks
normalize the file before Claude reads it. Heavier — new event
type, new contract.
The primary proposal subsumes all three. (b) is a strict subset of
the proposed reload and is the fallback if the team pushes back on
the slash-command surface.
Current workaround in use: symlink each worktree's.claude/settings.local.json to the main checkout's file at
worktree-creation time, so Claude reads through the symlink at
session-init and the in-memory allowlist starts populated. ASessionStart hook then un-symlinks the file in place so picker
writes (atomic rename, won't follow a symlink) land in a regular
file. This works but is fragile — it relies on the worktree being
symlinked at exactly the right moment, breaks for any worktree that
wasn't created via the user's wrapper, and doesn't help the
external-edit / live-revocation / MCP-toggle workflows above.
Priority
Medium - Would be very helpful
Feature Category
Configuration and settings
Use Case Example
(Worktree permission propagation — the motivating case.)
A developer keeps their permission allowlist in the main checkout's.claude/settings.local.json. A SessionStart hook syncs each
worktree's local file to match. Today:
git worktree add ../worktrees/feature-x→ fresh worktree, no
settings file (or stale from a prior session).
claudeinworktrees/feature-x→ session loads empty (or
stale) allowlist in memory.
SessionStarthook writes the full allowlist to the worktree
file (correct content on disk).
- User runs
git log --oneline→ in-memory doesn't have
Bash(git log *) → picker fires.
- User approves → picker writes a
settings.local.json
containing only Bash(git log *), dropping everything the
hook had written. Next session in this worktree also starts
from minimal.
With the proposed reload:
- As above through step 3.
SessionStarthook returns
{"hookSpecificOutput": {"reloadSettings": true}}.
- Claude re-reads the (correct, just-written) file before the
first user prompt. In-memory now matches canonical.
- User runs
git log --oneline→ auto-approved, no picker. The
on-disk file stays the full union; future sessions in this
worktree continue to start from the full union.
Additional Context
Related issues (closed but unresolved):
- #13019 *Tool permissions not recognized when running commands in
git worktrees* — closed not planned on 2026-02-03 by
github-actions due to "60 days of inactivity." Multiple comments
asking to reopen.
- #28248 *Permission scoping shows main worktree path instead of
current worktree path* — closed not planned on 2026-05-18, also
by github-actions for inactivity.
- #28041 .claude/ subdirectories not copied to worktrees — sister
issue, same family (different file, same root cause around
.claude/ not following git worktrees).
Related but distinct:
- #61085 *Expose permission picker decisions (rule + option kind) to
hooks* — open. Adjacent: observing picker decisions, not changing
the load order.
On the inactivity-autoclose pattern: #16497 documents that the
60-days-of-inactivity autoclose has wrongly closed live bug reports.
Both #13019 and #28248 are closed by this bot with no human triage
record. Filing this fresh issue partly because the closed ones never
got human attention.
Observed evidence for the load-order claim (not a controlled repro):
- Trace log from a user-level
SessionStarthook on a worktree:
hook stdin received at T₀.
- Worktree's
settings.local.jsonmtime:T₀ + ~90s. Content at
T₀ + ~90s was minimal (one rule, just approved), even though
canonical had ~150 rules and the SessionStart hook had unioned
them into the file shortly after T₀.
- The picker firing at all for a command whose rule existed in
canonical at T₀ is consistent with Claude's in-memory state
being loaded before the SessionStart hook's write. It would
also be consistent with the in-memory state never reading the
file at all, but the existing
hooks docs describe
SessionStart as "useful for loading development context,"
implying settings are already loaded by then.
Maintainers' confirmation of the actual load order would let
userspace tooling design with certainty either way.
Docs check (code.claude.com/docs/en/hooks):
- No documented ordering between settings load and
SessionStart. - No pre-settings-load hook exists.
- No documented mechanism for mid-session reload.
ConfigChangeis the only file-change signal, and it has not
reliably fired for picker writes in worktrees in our experience
(separate observation — may be another bug worth filing).
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗