Skip to main content
nono wraps any command with an OS-level sandbox. You specify what the command is allowed to access, and nono enforces those restrictions at the kernel level.

Your First Sandbox

nono run --allow . -- <COMMAND> [ARGS...]
The -- separator is recommended. Everything after it is the command to run.
# Grant read+write access to current directory, run claude
nono run --allow . -- claude
Or use a built-in profile that bundles the right permissions for a known tool:
nono run --profile claude-code -- claude
nono run --profile codex -- codex
See Profiles & Groups for all built-in profiles and how to create your own.

Commands

CommandDescription
nono runRun a command inside the sandbox (supervised, default)
nono shellStart an interactive shell inside the sandbox
nono wrapApply sandbox and exec into command (no parent process, minimal overhead)
nono whyCheck why a path/network operation would be allowed or denied
nono rollbackManage rollback sessions - list, show, restore, verify, cleanup snapshots
nono auditView audit trail - list and inspect past sandboxed sessions
nono learnDiscover required paths - trace a command to find what it accesses
nono trustManage instruction file trust - sign, verify, and manage attestation
nono setupSystem setup and verification - generate profiles, check shell integration

Permissions

nono provides three levels of filesystem access:
FlagAccess LevelUse Case
--allow / -aRead + WriteWorking directories, project folders
--read / -rRead OnlySource code, configuration
--write / -wWrite OnlyOutput directories, logs
Directory flags (--allow, --read, --write) grant recursive access. File flags (--allow-file, --read-file, --write-file) grant access to a single file.
# Recursive access to entire directory
nono run --allow ./project -- command

# Access to single config file only
nono run --read-file ./config.toml -- command

Network Access

Network is allowed by default. Use --block-net to disable outbound connections:
nono run --allow . --block-net -- cargo build
For granular control, use --network-profile for host-level filtering or --open-port for localhost IPC between sandboxes:
# Host-level filtering via proxy
nono run --allow . --network-profile claude-code -- my-agent

# Allow specific domains through the proxy
nono run --allow . --allow-domain api.openai.com -- my-agent

# Localhost IPC (e.g., MCP server on port 3000)
nono run --block-net --open-port 3000 --allow . -- my-agent
See Networking and CLI Reference for details.

Interactive Shell (nono shell)

Start a shell with the same sandbox permissions as nono run:
# Shell with access only to current directory
nono shell --allow .

# Shell with a named profile
nono shell --profile claude-code

# Override the shell binary
nono shell --allow-cwd --shell /bin/zsh
Exit the shell with Ctrl-D or exit.

Checking Path Access (nono why)

The why command checks if a path or network operation would be allowed or denied. It’s designed for both human debugging and programmatic use by AI agents.
# Check if a sensitive path would be blocked
nono why --path ~/.ssh/id_rsa --op read
# Output: DENIED - sensitive_path (SSH keys and config)

# Check with capability context
nono why --path ./src --op write --allow .
# Output: ALLOWED - Granted by: --allow .

# JSON output for AI agents
nono why --json --path ~/.aws --op read
# {"status":"denied","reason":"sensitive_path","category":"AWS credentials",...}

# From inside a sandbox, query own capabilities
nono run --allow-cwd -- nono why --self --path /tmp --op write --json
FlagDescription
--pathFilesystem path to check
--opOperation: read, write, or readwrite (default: read)
--hostNetwork host to check (instead of --path)
--portNetwork port (default: 443)
--jsonOutput JSON for programmatic use
--selfQuery current sandbox state (inside sandbox)
This is particularly useful for AI agents - when an operation fails, the agent can call nono why --self to get a structured JSON response explaining why and how to fix it.

What Happens at Runtime

  1. Parse - nono parses your capability flags
  2. Canonicalize - All paths are resolved to absolute paths (prevents symlink escapes)
  3. Apply Sandbox - Kernel sandbox is initialized (irreversible)
  4. Execute - nono exec()s into your command, inheriting the sandbox
  5. Enforce - Kernel blocks any unauthorized access attempts

Sensitive Paths

The following paths are always blocked by default to protect credentials:
  • ~/.ssh - SSH keys
  • ~/.aws, ~/.gcloud, ~/.azure - Cloud credentials
  • ~/.gnupg - GPG keys
  • ~/.kube, ~/.docker - Container credentials
  • ~/.zshrc, ~/.bashrc, ~/.profile - Shell configs (often contain secrets)
  • ~/.npmrc, ~/.git-credentials - Package manager tokens
Use nono why --path <path> --op read to check if a specific path is blocked and why. See Profiles & Groups for the full list and how group policy controls these.

Agent Integration

For setting up nono with a specific AI agent:
If there is an Agent you want supported please open an issue or PR to add it!

Next Steps