I often want to reload Claude Code mid-session to pick up changes to MCP servers, hooks, or other settings. The default workflow is a little clunky: I need to manually exit, then restart, then tell Claude that I restarted.
As a result, I wanted a /reload command that I could run to restart Claude and automatically continue the conversation. Also, by making it a command, Claude can actually invoke it itself when it detects a need to reload. This allows Claude to restart itself when needed without human intervention, so it can run more autonomously.
I figured this out when making (yet another) Google Drive MCP. I wanted to have Claude build it and automatically reload to test it.
Initial exploration
Since I was in Claude Code already, I worked on this with Claude. I figured we could find an approach that worked and then codify.
First attempt: Exit with a special code
Claude's initial idea was to have the skill exit Claude with some special exit code. Perhaps exit 42 to signal "please reload", and a wrapper script to listen for that code. This would work well since I already typically run Claude via short custom commands, so we could hook into that.
I asked about reasonable or semantic exit codes, and Claude suggested using 129 rather than an arbitrary code.
Exit code details
Claude says: SIGHUP (signal 1) is the Unix convention for "reload configuration". Daemons like nginx and Apache reload their config on SIGHUP rather than terminating. And exit code 128+N is the shell convention for "terminated by signal N." So 129 would mean "reload requested" -- semantically correct and following established Unix patterns.However, merely exiting from a Bash tool use doesn't work. Bash commands run in subprocesses, so exiting the subprocess with a special code just kills that subshell.
Second attempt: Find a built-in flag
We looked at Claude Code's docs and --help for a way to pass an exit code to /exit, but there's no /exit <code>, /reload, or /restart built-in.
Sending SIGHUP to the Claude process
Then I asked about the Bash command terminating the parent process, which would be Claude.
The key insight was that from within a bash command, $PPID would point to the Claude process. So then:
kill -HUP $PPID
sends SIGHUP (signal 1) to Claude, which causes it to exit with code 129 (128 + 1).
The Wrapper Function
The second part of this approach is to turn my short startup command into a Claude invocation that detects that special exit code and restarts.
Before I had:
alias CL="claude --dangerously-skip-permissions"
But we need to check for the special exit code and generally be a good Unix user (preserving exit codes, etc.):
function CL {
local continue_flag="" # Whether to continue or not
local restart_msg="" # Don't send restart message the first invocation
local rc
while true; do # Loop forever
claude \ # Start Claude
--dangerously-skip-permissions \ # Don't ask for permission >:D
$continue_flag \ # Second invocation? Pass `-c` to continue last session
"$@" \ # Pass along any original additional parameters
$restart_msg # On restarts, start Claude with a "restarted" message (see below)
rc=$? # Store the Claude exit code
[ $rc -eq 129 ] || return $rc # If Claude exited with code 129, restart.
# Otherwise, don't restart, and exit with the original exit code.
echo "Reloading Claude Code..." # Tell the human we're restarting
sleep 0.5 # Seems to somewhat improve restart likelihood?
continue_flag="-c" # Restart the previously used session
restart_msg="restarted" # Send this message to Claude when the session resumes
done
}
Sending the restart_msg message is quite helpful. Without it, Claude waits for user input after restart. So this allows it to continue working on whatever it was working on without needing user intervention. If you wanted to send a different message, I usually just hit esc to cancel the send when Claude starts up.
I have some other wrappers like:
CLCfor running with--dangerously-skip-permissionsand--continueCLRfor running with--dangerously-skip-permissionsand--resume
Claude was easily able to modify those as well. Note you'll need to reload config or start a new session to pick up wrapper changes, especially if going from alias to function.
I had a little trouble getting the restart consistently working and added the short sleep, and while it might not be necessary, it seems like it improves the likelihood that the restart works.
The Skill
The /reload skill is then just a markdown file that tells Claude to run kill -HUP $PPID. Simple, but it took a few iterations to arrive at.
First versions
I had Claude write the skill based on our learnings about the $PPID.
The initial working version was something like this:
# Reload Claude Code (restart Claude)
Reload Claude Code to pick up configuration changes (MCP servers, hooks, settings).
## Steps
Send SIGHUP to the Claude process (which is $PPID from bash):
```bash
kill -HUP $PPID
```
The user will let you know when the reload is complete.
This had Claude read the instruction and then decide to run the Bash command. That works, but it meant that Claude had to decide to call the Bash tool. Occasionally it would add commentary, ask me to restart, write current status to file (it would be reloaded soon anyway), or ask for confirmation first. This makes it less likely the restart actually happens, and it also takes longer when it does work.
Final Iteration: ! Prefix in Skill / Command file
To try to get around the non-determinism, I wanted to see if there was a way to execute a command directly from the skill.
It turns out that Claude Code supports a ! prefix in skill files for immediate command execution. So then the command can run directly without the LLM processing it at all.
The final version of ~/.claude/commands/reload.md is simply:
# Reload Claude Code (restart Claude)
!`kill -HUP $PPID`
The ! makes it fire instantly: you type /reload, the signal sends, and Claude restarts. The whole thing takes about a second, and either you or Claude can initiate.
Wrap up
This exploration was fun and educational. It has been really useful in the last couple of days when adding skills and MCP servers.
Want to install it for yourself? Just point your Claude Code instance to this blog post and have it add the skill and shell wrapper!