Permissions & sandbox
Every app runs with exactly the permissions it declared and no more. Permissions are capabilities; the sandbox enforces them and isolates each app at a level matched to its type. This is what makes installing apps safe.
Capabilities
A capability is a specific, scoped permission an app declares (and you approve at install). They cover the filesystem, network, hardware, system, the GUI, and agent control:
pub enum Capability {
FsRead(String), FsWrite(String),
NetworkOutbound, NetworkInbound(u16), NetworkStream,
AudioOutput, AudioInput, GpuCompute, GpuDisplay, UsbDevice(String),
ProcessSpawn, ProcessKill, SystemdUnit(String), KernelModule(String),
WaylandSurface, WaylandInput, AccessibilityTree,
AgentSpawn, AgentKill, FleetControl, SecretsRead(String),
}Capabilities that take a value (FsRead("/home/me/Projects/**"), SecretsRead("github-token")) are scoped — always a prefix or a specific resource, never "everything."
Enforcement
Before any tool action runs, the sandbox checks it against the app's granted capabilities. Anything beyond the grant fails cleanly:
This is in the path of every action, so an app physically cannot do what it didn't declare and you didn't approve.
Isolation tiers
The riskier the code, the stronger the boundary:
| App type | Mechanism |
|---|---|
cli-tool, mcp-tool | Linux namespaces + seccomp |
desktop-app | Namespaces + Wayland protocol filter |
headless-app | Namespaces + network namespace |
system-service | Explicit capabilities, no FS sandbox |
agent (external code) | Hardware-isolated MicroVM |
Externally-authored agent code gets a MicroVM because model-generated output is treated as hostile by default — a shared kernel is too weak a boundary for it. Apps you build with the SDK use lighter tiers because their surface is known at compile time.
What you see as a user
At install, Kiki shows exactly what an app is asking for, and you approve it. You can review or revoke in Settings, and centrally for a fleet via the dashboard. For the user-facing view, see Apps & the store.
For developers
Declare the minimum your app needs:
#[kiki::app(id = "io.kiki.player", type = DesktopApp)]
#[kiki::requires(Capability::AudioOutput)]
struct Player { /* ... */ }A tight capability set is approved faster and fails safe.