No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Andreas Neue 8534806eac README: translate to English, expand Portability section
- Translate entire README from German to English
- Expand Portability section to mention Linux support (Landlock)
- Mention Seatbelt as macOS's sandboxing mechanism
2026-09-17 03:16:56 +02:00
.gitignore Fix idempotent setup.sh wrapper detection and unify env var names 2026-09-02 13:32:10 +02:00
nonoblock fix: error on calling nonoblock cline 2026-09-16 23:22:07 +02:00
nonoblock_permissions fix: nonoblock_permissions for cline 2026-09-11 13:57:51 +02:00
README.md README: translate to English, expand Portability section 2026-09-17 03:16:56 +02:00
setup.sh feat: passe install- und update-Parameter in setup.sh an 2026-09-04 07:47:57 +02:00

nonoblock

Runs AI agents (claude, aider, opencode, cline) inside the nono sandbox.

nonoblock claude
nonoblock aider -m gpt-4o
nonoblock opencode
nonoblock cline

nonoblock extends nono's built-in claude-code profile (which already contains deny-rules for credentials, browser data, keychains, and shell history) with additional grants for the tools we actually use. The goal is "allow most things, block the dangerous ones" not full isolation.

On Linux, nono sandboxes via Landlock; on macOS via Seatbelt. The script only builds the nono wrap argument list, so it covers both platforms with a single script.


Prerequisites

Dependency Required for
nono (≥ 0.41) Sandbox execution
jq Only for cmd-default / cmd-allow / cmd-deny lines
bash Runs on macOS's stock /bin/bash (3.2)

Installation

./setup.sh

Installs nonoblock to ~/.local/bin/nonoblock, creates the shared permissions file, and installs missing agent binaries (sandboxed via nono).

Manual

install -m755 nonoblock ~/.local/bin/nonoblock

Make sure ~/.local/bin is on your $PATH:

# ~/.zshrc or ~/.bashrc
export PATH="$HOME/.local/bin:$PATH"

Permissions file

nonoblock expects one shared permissions file for all agents (no per-agent split). Default path:

Platform Path
Linux ~/.local/etc/nonoblock_permissions
macOS ~/Library/Application Support/nonoblock/nonoblock_permissions

Alternatively, via environment variables:

export NONOBLOCK_PERMISSIONS_FILE=/path/to/file   # canonical
export AGENT_PERMISSIONS_FILE=/path/to/file       # legacy, also accepted

Upgrade

Update the repository

git pull

Reinstall the script

install -m755 nonoblock ~/.local/bin/nonoblock

Everything at once (incl. agent updates)

./setup.sh update

This:

  1. Runs git pull --ff-only in the repository.
  2. Reinstalls nonoblock.
  3. Updates the permissions file from the template.
  4. Runs each agent's own update mechanism sandboxed:
    • claudeclaude update
    • aideruv tool upgrade / pipx upgrade / pip install --user --upgrade
    • opencodego install github.com/opencode-ai/opencode@latest
    • clinenpm install -g @anthropic-ai/cline

Only specific agents

./setup.sh claude aider update

Usage

Basic invocations

nonoblock claude
nonoblock aider -m gpt-4o
nonoblock opencode
nonoblock cline

All arguments after the agent name are passed through to the agent unchanged.

Starting from $HOME

Landlock/Seatbelt cannot sandbox $HOME with --allow-cwd. nonoblock detects this case automatically, switches to a temporary directory, and cleans it up on exit:

Running from $HOME; using tmpdir /tmp/tmp.XXXXXX (Landlock/Seatbelt can't sandbox $HOME with --allow-cwd)

Manually specifying the agent binary

If the agent is not found by name on $PATH:

AGENT_REAL_BIN=/path/to/binary nonoblock myagent

Configuration

Permissions file format

Each line: <type> <path>. Comments (#) and blank lines are skipped. Paths are evaluated, so ~ and brace expansion ({a,b}) work.

Type Meaning
rw Read-write access to directory
ro Read-only access to directory
ro-file Read-only access to file
bypass-ro-file Bypass protection + read-only on file
bypass-rw-file Bypass protection + read/write on file
cmd-default Default policy: <exe> <allow|deny>
cmd-allow Allow argv prefix: <exe> <argv-prefix...>
cmd-deny Deny argv prefix: <exe> <argv-prefix...>

Example

# Directories
rw ~/projects
ro ~/.cache/{pnpm,gh,deno}
ro ~/.config

# Files
ro-file ~/.gitconfig
bypass-rw-file ~/.aws/credentials

# Command Policies (requires jq)
cmd-default kubectl deny
cmd-allow kubectl get
cmd-allow kubectl describe
cmd-deny kubectl apply
cmd-deny kubectl delete

Environment variables

Variable Purpose
NONOBLOCK_PERMISSIONS_FILE Path to the permissions file (canonical)
AGENT_PERMISSIONS_FILE Legacy name, also accepted
AGENT_REAL_BIN Explicit path to the agent binary (overrides $PATH lookup)
NONOBLOCK_BIN Install path for nonoblock (default: ~/.local/bin/nonoblock)
XDG_RUNTIME_DIR Runtime directory (Linux); fallback: $TMPDIR or /tmp
XDG_CONFIG_HOME Base for generated nono profiles (default: ~/.config)

Auto-detected tools

nonoblock adds grants when certain tools are found on the system:

  • Docker: ~/.docker is allowed, the Unix socket is exposed, credential files (config.json, daemon.json) receive --bypass-protection.
  • Go: GOPATH/bin (read), GOPATH/pkg and GOCACHE (rw).
  • just: A private tmpdir under the runtime directory is allowed.

Agent-specific behavior

  • cline: The cline binary is a Node.js resolver that spawns a hidden .cline binary. nonoblock detects this and launches .cline directly so nono only has to sandbox a single process. CLINE_WRAPPER_PATH is set so cline resolves its package-manager detection and webview search correctly.

  • claude: Uses nono's built-in claude-code profile directly.

  • other agents (e.g. aider, opencode): nonoblock checks whether a per-agent generated profile <agent>-code exists and uses it if present.

Shebang interpreters

If the agent binary is a script (e.g. a uv-managed Python tool), nonoblock follows the #! line (including symlink resolution) and grants read access to the interpreter's directory. Without this grant, execve() of the interpreter would be blocked by Landlock/Seatbelt.


Generated profiles

If cmd-default / cmd-allow / cmd-deny lines are present in the permissions file, nonoblock generates a profile <agent>-nono-cmdpolicy.json under $XDG_CONFIG_HOME/nono/profiles/ (default: ~/.config/nono/profiles/).

This profile is regenerated on every invocation treat the file as a build artifact and do not edit it manually. Changes belong in the permissions file.


Debugging

# Shows what the base profile allows:
nono profile show claude-code

# Shows resolved caps without actually launching:
nono wrap --dry-run ... -- /bin/true

# Explains a denial (from inside the sandbox):
nono why --self --path <path> --op read

Full schema and patterns: nono profile guide


Portability

The script runs on both Linux and macOS each with the tools standardly installed on that platform. On macOS that means stock /bin/bash (Bash 3.2, the last GPLv2 release) and the Apple toolchain. The following constraints are therefore observed:

  • No array+=(...) syntax (Bash 4.0+) arrays are rebuilt instead: arr=("${arr[@]}" new)
  • No /run/user/<uid> (systemd-only) fallback via $TMPDIR
  • No dependency on GNU readlink -f or realpath

On Linux, nonoblock uses the kernel's Landlock mechanism (kernel ≥ 5.13) for file-access sandboxing no additional tooling required. nono ≥ 0.41 wraps the Landlock rules; nonoblock itself installs nothing extra. The constraints above primarily concern macOS, where the stock toolchain (Bash 3.2, BSD tools) is older or different from typical Linux distributions.

On macOS, Seatbelt (XNU's sandbox implementation) handles the same role also with no additional tooling.