Sudo usage warning
Flags privilege escalation before it hangs your loop
Non-blocking advisory whenever a Bash command reaches for sudo. Privilege escalation is rarely needed in a dev loop and a non-interactive password prompt can silently stall the agent — this surfaces it so a venv/--user/container path is considered first.
What does the Sudo usage warning hook do?
Sudo usage warning is a Claude Code PreToolUse hook matching Bash. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Flags privilege escalation before it hangs your loop.
As a PreToolUse hook it runs before the action completes, so it can block or adjust what Claude is about to do. Because it is a deterministic Node.js script, it executes on every matching event without relying on the model to remember — the guarantee that makes agentic workflows safe to automate.
Use cases
- Least-privilege dev
- Avoid blocked sessions
- Awareness
Tags
settings.json fragment
{
"hooks": {
"PreToolUse": [
{
"hooks": [
{
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/warn-sudo.mjs",
"type": "command"
}
],
"matcher": "Bash"
}
]
}
}Script · .claude/hooks/warn-sudo.mjs
#!/usr/bin/env node
// Avertit (sans bloquer) quand une commande Bash utilise sudo (PreToolUse Bash)
import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
function stripQuotedArgs(cmd) {
return cmd.replace(/"(?:[^"\\]|\\.)*"/g, '""').replace(/'(?:[^'\\]|\\.)*'/g, "''");
}
export function run(input) {
if (input.tool_name && input.tool_name !== 'Bash') return null;
const command = stripQuotedArgs(input.tool_input?.command ?? '');
// sudo en début de commande ou après un opérateur shell (; && || |).
if (!/(?:^|[;&|]|&&|\|\|)\s*sudo\s+/.test(command)) return null;
return {
message:
'[warn-sudo] Cette commande utilise sudo. Une élévation de privilèges est rarement nécessaire ' +
'dans une boucle de dev et peut bloquer sur une invite de mot de passe non interactive. ' +
'Vérifiez si une version sans sudo (venv, --user, conteneur) suffit.\n',
};
}
/* v8 ignore next 5 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
const input = JSON.parse(readFileSync(0, 'utf8'));
const result = run(input);
if (result?.message) process.stderr.write(result.message);
}
Learn more
Related hooks
- Secret detection before Bash executionCatch a leaked API key before it ever runs
- Destructive command blockingStops a disk-wiping shell command before it runs
- Sensitive file write protectionYour .env and keys stay untouched by the agent
- Lock file write protectionLock files stay intact - package manager only