Kernel-Level Isolation for AI Agents
nono uses Linux Landlock LSM and macOS Seatbelt to create irrevocable, kernel-enforced allow-lists. No root, no containers, no overhead.
Why kernel-level sandboxing
AI coding agents run as your user, with access to everything you have: SSH keys, cloud credentials, source code across every project. Traditional sandboxing approaches like Docker or VMs introduce significant overhead — a daemon, image management, networking configuration, and volume mounts just to let an agent edit a file.
nono takes a different approach. On Linux, it uses Landlock LSM to restrict filesystem access at the kernel level. On macOS, it uses Seatbelt (the same sandbox framework behind every App Store application). Both mechanisms are irrevocable once applied — the sandbox cannot be loosened, only tightened.
This means zero runtime overhead after sandbox initialization, no root privileges required, and automatic inheritance by all child processes. The AI agent and every subprocess it spawns are structurally unable to access anything outside the allow-list.
Composable JSON Profiles
Define exactly what an agent can access with declarative JSON profiles. Built-in security groups cover language runtimes, cache directories, and editor integrations. Profiles are version-controlled alongside your code.
See profile reference →$ nono run --allow-cwd --proxy-allow llmapi -- agent▄█▄ nono v0.7.0▀▄^▄▀ - Halo Nono!Capabilities:Filesystem:/Users/user/.claude [read+write] (dir)/Users/user/.local/share/claude [read] (dir)/Users/user/.claude.json [read+write] (file)/Users/user/.gitconfig [read] (file)/Users/user/dev/myproject [read+write] (dir)+ 45 system/group paths (use -v to show)Network:outbound: proxy (localhost:0)Supervised mode: child sandboxed, parent manages network proxy.Applying Kernel sandbox protections.
{"meta": {"name": "claude-code","version": "1.0.0","description": "Anthropic Claude Code CLI agent"},"security": {"groups": ["node_runtime", "python_runtime", "rust_runtime"]},"filesystem": {"allow": ["$HOME/.claude"],"read_file": ["$HOME/.gitconfig"]},"network": { "block": false },"workdir": { "access": "readwrite" },"undo": {"exclude_patterns": ["node_modules", ".next", "target"]},"interactive": true}
use landlock::{ABI, Access, AccessFs, AccessNet, BitFlags,PathBeneath, PathFd, Ruleset, RulesetAttr,RulesetCreatedAttr,};const TARGET_ABI: ABI = ABI::V5;pub fn apply_sandbox(caps: &CapabilitySet) -> Result<()> {let mut ruleset = Ruleset::default().handle_access(AccessFs::from_all(TARGET_ABI))?.create()?;for (path, access_mode) in caps.paths() {let flags = access_to_landlock(access_mode);let fd = PathFd::new(path)?;ruleset = ruleset.add_rule(PathBeneath::new(fd, flags))?;}// Irrevocable: cannot be loosened after this callruleset.restrict_self()?;Ok(())}
Key Properties
Irrevocable
Once applied, the sandbox cannot be loosened. Only tightened.
Unprivileged
No root, no capabilities, no suid binaries required.
Inherited
Child processes automatically inherit the sandbox restrictions.
Zero Overhead
Kernel-level enforcement. No runtime performance cost after init.
Get started with nono
Runtime safety infrastructure that works on macOS, Linux, and in CI.