Skip to main content

Platforms

Kule runs on macOS and Linux. Windows is planned for a later version.

Support at a glance​

macOSLinux
VersionsmacOS 13 or laterx86_64 release files (built on Ubuntu 22.04, tested on Fedora); other architectures from source
Release filesUniversal .dmg (Apple silicon and Intel).deb, .rpm, kule alone as .tar.gz
SandboxSeatbeltLandlock (Linux 6.2 or later), seccomp, namespaces
Network rules in the sandboxYesLinux 6.7 or later
Sandbox refusals listedYes, after the command and in sandbox.jsonlNo (Landlock reports only to the audit log); the command still gets a permission error
The task's copyAPFS clone: almost no spaceReflinks on Btrfs and XFS; a full copy on ext4
Package caches at startnpm and cargo cloned from yoursEmpty: the first install downloads again
/tmpShared with the systemEach task's own
Processes of its own–Yes: a command sees and signals no other program
Network namespace of its own–Yes, with only the proxy in reach
Servers held to this computerNode, Python and Ruby pointed at loopback; other programs' ports shieldedEvery listening address turned into loopback
GPU offMetal (and OpenCL) gets no device/dev/dri and NVIDIA's devices read-only
Secret store keyKeychainSecret Service
Show in file managerFinderFiles (D-Bus FileManager1)

Linux: what the sandbox needs​

  • Landlock ABI 3 (Linux 6.2) at least: the first to cover truncation. On an older kernel the sandbox cannot be set up, and commands do not run.

  • Landlock ABI 4 (Linux 6.7) for network rules. On an older kernel, a command whose network must go through the proxy is refused rather than left open.

  • Unprivileged user namespaces, for a network, processes, System V IPC and a host name of the command's own. Ubuntu 24.04 refuses them by default:

    sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0

    Without them Kule runs no agent until you accept weaker isolation (see kule isolation), and says what is missing while you do.

Unix sockets outside the task's folders are out of reach through Landlock's rule for them (ABI 9). On older kernels, your runtime directory (/run/user/<uid>, where the session bus and Docker's and Podman's rootless sockets live) is covered with an empty one for the command, and each other socket that exists when the command starts is covered too.

An agent's settings inside its state directory are mounted read-only for the agent alone. Without user namespaces, and for settings that are links or do not exist yet, they are put back after the run instead; whatever a put-back replaces is moved to ~/.kule/kept/replaced, never lost.

Not yet​

  • Windows.
  • HTTP/2 through the proxy (clients fall back to HTTP/1.1), and WebSocket upgrades.
  • On macOS, tasks share the system's /tmp: the macOS sandbox cannot move a path.
  • On macOS, while a task's network goes through the proxy, the system's certificate service stays closed to its commands. A tool that checks certificates only through it cannot use HTTPS in a task. pip 24.2 and later works with --use-deprecated=legacy-certs (older pip refuses the option, so Kule does not set it). Go is told to use the roots SSL_CERT_FILE names.
  • NuGet's and Maven's tools on macOS trust the system's roots alone, so their registries pass through unseen, writes included, as Go's module proxy does.
  • Gemini needs an API key from AI Studio, stored in a file: GEMINI_FORCE_FILE_STORAGE=true gemini, then /auth.