claude-sudo¶
claude-sudo is a small wrapper that launches Claude Code with passwordless sudo for the
lifetime of that one Claude process, and takes the privilege away again the moment Claude exits.
Plain claude has no passwordless sudo. That is deliberate: an agent that can run sudo silently,
forever, in every session is a much larger blast radius than one that can only do so while you
knowingly started it that way.
The trade-off in one line
While claude-sudo is running, Claude can run any command as root without prompting.
Start it only for sessions that genuinely need server administration.
How it works¶
| Step | What happens |
|---|---|
| 1 | Clears any stale rule left behind by a previously killed session |
| 2 | Writes <user> ALL=(ALL) NOPASSWD:ALL to /etc/sudoers.d/49-claude-session (prompts for your password once, via sudo tee) |
| 3 | chmod 440 on the rule, then validates it with visudo -cf |
| 4 | Runs claude as your normal user, so files stay owned by you rather than root |
| 5 | On exit — including INT, TERM, HUP — a trap removes the rule |
The username is resolved at runtime with id -un, so the same script works unchanged on any
machine and for any user.
The rule survives a hard kill
The EXIT/INT/TERM/HUP trap covers normal exits and Ctrl-C, but not SIGKILL, a
power cut, or a crashed terminal. The next claude-sudo start clears the stale rule, but until
then the NOPASSWD grant is still live. To clean up by hand:
Check whether one is currently active:
The script¶
#!/usr/bin/env bash
#
# claude-sudo — launch Claude Code with passwordless sudo for THIS session only.
#
# On start it installs a NOPASSWD sudoers rule (prompting for your password once),
# runs Claude as your normal user, and removes the rule again the moment Claude
# exits. Plain `claude` has no passwordless sudo.
#
set -uo pipefail
RULE="/etc/sudoers.d/49-claude-session"
USER_NAME="$(id -un)"
revoke() { [ -e "$RULE" ] && sudo -n rm -f "$RULE" 2>/dev/null; }
trap revoke EXIT INT TERM HUP
# Clear any stale rule left by a previously killed session, then grant for this one.
sudo rm -f "$RULE"
printf '%s ALL=(ALL) NOPASSWD:ALL\n' "$USER_NAME" | sudo tee "$RULE" >/dev/null
sudo chmod 440 "$RULE"
# Validate the rule; a broken sudoers file would break sudo entirely.
if ! sudo visudo -cf "$RULE" >/dev/null; then
echo "claude-sudo: refusing to start, invalid sudoers rule" >&2
revoke
exit 1
fi
# Run Claude as the normal (non-root) user so files stay owned by you.
command claude "$@"
Two details worth keeping if you edit it:
command claude "$@"-
The
commandbuiltin bypasses shell aliases and functions, so analias claude=...in your rc file cannot hijack the launch."$@"forwards every flag you pass through to Claude Code. visudo -cf "$RULE"-
A syntactically broken file in
/etc/sudoers.d/breakssudoentirely — including thesudoyou would need to fix it. The check is cheap insurance; do not remove it.
Installation on a new machine¶
Requires: a working claude on your PATH, and your user already in sudo (or wheel).
1. Write the script¶
cat > ~/claude-sudo <<'EOF'
#!/usr/bin/env bash
#
# claude-sudo — launch Claude Code with passwordless sudo for THIS session only.
#
set -uo pipefail
RULE="/etc/sudoers.d/49-claude-session"
USER_NAME="$(id -un)"
revoke() { [ -e "$RULE" ] && sudo -n rm -f "$RULE" 2>/dev/null; }
trap revoke EXIT INT TERM HUP
sudo rm -f "$RULE"
printf '%s ALL=(ALL) NOPASSWD:ALL\n' "$USER_NAME" | sudo tee "$RULE" >/dev/null
sudo chmod 440 "$RULE"
if ! sudo visudo -cf "$RULE" >/dev/null; then
echo "claude-sudo: refusing to start, invalid sudoers rule" >&2
revoke
exit 1
fi
command claude "$@"
EOF
2. Install it¶
install runs in the directory you are standing in
sudo install ... claude-sudo ... with a bare filename only works from the directory holding
the file. Use ~/claude-sudo — or an absolute path — and it works from anywhere.
3. Verify¶
ls -l /usr/local/bin/claude-sudo # -rwxr-xr-x 1 root root
bash -n /usr/local/bin/claude-sudo # syntax check, runs nothing
4. Add the convenience alias¶
The server uses a single long-lived tmux session named cc, so a dropped SSH connection does not
kill the running Claude:
Then rc either reattaches to the existing session or starts a fresh claude-sudo inside a new
one. For Zsh, put the same line in ~/.zshrc.
Copying it between machines¶
The script is self-contained — it needs no config file, and it creates and removes its own sudoers rule at runtime. To move it to another host, such as a Raspberry Pi:
scp franz@franzvoid.is:/usr/local/bin/claude-sudo ~/claude-sudo
sudo install -m 755 -o root -g root ~/claude-sudo /usr/local/bin/claude-sudo
If you cannot read /usr/local/bin/claude-sudo over SFTP because of its ownership, copy it into
your home directory on the source machine first:
Or skip the transfer entirely and paste the heredoc from Installation on a new machine.
Using it¶
claude-sudo # same flags as `claude`
claude-sudo --resume
rc # via tmux, the normal way on this server
Inside the session, confirm the grant is live:
If sudo -n true fails inside a Claude session
Claude should not work around it. The correct responses are to relaunch with claude-sudo,
or to run the single command yourself from the Claude prompt with the ! prefix:
Don't background a long privileged task and then quit
claude-sudo removes the sudoers rule on exit. Anything still running that needs sudo —
a /new-wp provision and its rollback, for example — loses the grant mid-flight. See
Creating a new site from the template.
Common problems¶
install: cannot stat 'claude-sudo': No such file or directory¶
You are not in the directory holding the file. Use the full path:
It asks for a password every time¶
Expected — sudo tee on the first line of the script needs one password entry per session, because
the rule it is about to write does not exist yet. Everything after that is passwordless.
If it asks again during the session, the rule was removed or never validated. Check:
claude-sudo: refusing to start, invalid sudoers rule¶
visudo rejected the generated file. Almost always means id -un returned something unexpected,
such as a username with characters sudoers will not accept. The script removes the bad file before
exiting, so sudo is left intact.
sudo: command not found on a minimal Debian image¶
Fresh Debian installs do not always ship sudo, and the first user is not in the sudo group.
As root:
Log out and back in for the group change to take effect.
Claude is editing files as root¶
It should not — the script deliberately runs command claude as your normal user. If you find
root-owned files in your tree, something inside the session ran sudo on a write it did not need
to. Fix ownership with:
Final checklist¶
-
/usr/local/bin/claude-sudoexists, mode 755, owned byroot:root -
bash -n /usr/local/bin/claude-sudopasses -
clauderesolves on thePATH - Your user is in the
sudogroup - The
rcalias is in~/.bashrc(or~/.zshrc) -
sudo -n truesucceeds inside aclaude-sudosession -
sudo -n truefails inside a plainclaudesession -
/etc/sudoers.d/49-claude-sessionis gone after the session exits