Running as root: --dangerously-skip-permissions exits with code 1, forcing dontAsk — no path to full autonomy as root

Resolved 💬 5 comments Opened May 11, 2026 by Halyxa Closed May 12, 2026

Summary

When running Claude Code as root (uid=0), there is no permission mode that allows full autonomous operation:

  • --dangerously-skip-permissions (bypassPermissions) → process.exit(1) with "cannot be used with root/sudo privileges"
  • --permission-mode dontAsk → Runs, but silently denies writes to protected paths (.claude/ directories, agent definitions, etc.) regardless of permissions.allow settings
  • --permission-mode default → Prompts for approval on every operation (not viable for unattended/autonomous use)

The result: operators running as root are forced into dontAsk, which silently denies operations the operator has explicitly pre-approved in settings.json.

Evidence from source (Claude Code 2.1.139, cli.js)

// Minified, reformatted for readability:
if (q === "bypassPermissions" || K) {
  if (process.platform !== "win32"
      && typeof process.getuid === "function"
      && process.getuid() === 0
      && process.env.IS_SANDBOX !== "1"
      && process.env.CLAUDE_CODE_BUBBLEWRAP !== "1") {
    console.error(
      "--dangerously-skip-permissions cannot be used with root/sudo privileges for security reasons"
    );
    process.exit(1);
  }
}

The check has two escape hatches (IS_SANDBOX=1 or CLAUDE_CODE_BUBBLEWRAP=1) but these are undocumented and it's unclear what behavioral side effects they trigger.

The dontAsk trap

From Claude Code docs: "In every mode except bypassPermissions, writes to protected paths are never auto-approved."

This means dontAsk mode silently denies writes to:

  • .claude/ directories (agent definitions, settings, hooks)
  • .bashrc, .mcp.json, and other protected dotfiles

The permissions.allow: ["Write(*)"] setting is irrelevant for protected paths in dontAsk mode. The only mode that respects the allow list for protected paths is bypassPermissions — which exits when running as root.

This creates a dead end: the only mode that works for full autonomy is the one mode that refuses to run as root.

Environment

  • Claude Code CLI 2.1.139, Ubuntu 24.04.4 LTS
  • Single-tenant dedicated server (Proxmox VM)
  • Root required for: ZFS pool management, systemd services, Traefik reverse proxy, UFW firewall, certbot SSL, port binding below 1024
  • Existing safety infrastructure: 12 explicit deny rules (rm -rf /, zpool destroy, dd, mkfs, etc.), ZFS snapshots for instant rollback

Why this matters

Infrastructure management inherently requires root. systemd, ZFS, firewall rules, privileged ports, SSL certificates — these are core sysadmin operations that require root or root-equivalent access. Any operator using Claude Code for server management on AWS EC2, DigitalOcean, GCP, Docker containers, or dedicated servers will hit this.

The workaround bypasses your safety instrumentation. When Write is denied, operators route through Bash(cat > file). This succeeds because Bash(*) is allowed and cat runs as root with full filesystem access. The result:

  • The same file gets written either way
  • But via Bash, Claude Code loses structured logging of file operations (target path, content, previous content)
  • Your safety monitoring, audit trail, and tool-level instrumentation are all blind to the actual writes
  • The "safer" mode produces less-safe observability

The deny list already handles the real risks. Claude Code has an elegant deny list system that blocks specific dangerous operations. This is the right safety architecture. The root override says "the deny list isn't sufficient as root" — but if that's true, it isn't sufficient for a non-root user with passwordless sudo either, and there's no sudo check. The safety model is inconsistent.

Request

In order of preference:

  1. Allow bypassPermissions as root when explicitly configured in settings.json. The operator has opted in at both the config level (settings.json) and the CLI level (--dangerously-skip-permissions). The deny list still catches destructive operations. This is informed, double-opt-in consent.
  1. Document the IS_SANDBOX and CLAUDE_CODE_BUBBLEWRAP escape hatches. If these env vars are the intended path for root users, document them — what they do, what side effects they have, whether they're stable API.
  1. Add a --trust-root flag following the dangerouslyDisableSandbox precedent (which already exists in the Bash tool schema). Named, scary, explicit.
  1. Document the root restriction. Currently undiscoverable — not in claude --help, not in the docs, not in the changelog. Operators find out only when process.exit(1) kills their session or when writes silently fail in dontAsk mode.

Reproduction

# As root:
claude --dangerously-skip-permissions
# → "cannot be used with root/sudo privileges for security reasons"
# → exit code 1

# Forced into dontAsk:
claude --permission-mode dontAsk
# → runs, but Write to .claude/ paths silently denied
# → Bash(cat > .claude/agents/foo.md) succeeds for the same file

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗