Uracil
A hardware-agnostic, rootless microkernel runtime for native services.
Uracil provides a minimal, capability-scoped execution environment for service bundles. Each bundle declares the permissions it needs; users grant only what they approve. The runtime refuses to execute any function whose requirements haven't been satisfied.
┌──────────────────────────────────────┐
│ uracil runtime │
├──────────────┬───────────────────────┤
│ permission │ bundle loader │
│ engine │ (JSON manifest → C) │
├──────────────┼───────────────────────┤
│ grant store │ subprocess executor │
│ ~/.uracil/ │ (fork+exec python3) │
├──────────────┴───────────────────────┤
│ host platform adapter │
│ (arch/host/) │
└──────────────────────────────────────┘
Features
- Permission model — services declare capabilities; users grant them explicitly
- Bundle manifest — JSON contract describing service identity, functions, and permissions
- External bundle loader — load any APS-installed service directory at runtime
- Subprocess executor — run function snippets as isolated child processes
- Built-in JSON parser — zero-dependency manifest loading
- Hot-swap metadata — versioned payload groups for safe service updates
- Runner metadata passthrough —
.urabundles can carry GGUF/API runner metadata for Athena-managed model services - Campaign kernel — persistent campaign-scoped state, artifact ownership, and cleanup under
~/.uracil/campaigns/ - Host-first — works on Linux x86_64 now, designed for additional ISAs later
- C11, zero external dependencies — only libc and POSIX
Build
Requires CMake 3.20+ and a C11 compiler (GCC or Clang).
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
Run the test suite:
ctest --test-dir build --output-on-failure
Usage
Built-in demo bundle
The binary ships with a compiled-in sample service so the runtime is usable immediately:
$ ./build/uracil describe
service: aps.sample.echo-service
version: 0.1.0
description: Sample APS-native service bundle running inside Uracil.
runtime abi: uracil.service.v1
hot-swap group: aps.sample.echo-service
payload rev: demo-001
rootless: true
requested perms: fs.read, net.client, clock.read
$ ./build/uracil grant fs.read clock.read
updated grant manifest: fs.read, clock.read
$ ./build/uracil run clock-now
virtual clock reading: 2026-04-17 12:00:00 UTC
External bundles (APS packages)
Load any service directory that contains a manifest.json:
# Describe an APS-installed service
./build/uracil --bundle ~/.aps/packages/weather-check-service describe
# Grant permissions
./build/uracil --bundle ~/.aps/packages/weather-check-service grant net.client
# Run a function (executes functions/current_weather.py as a subprocess)
./build/uracil --bundle ~/.aps/packages/weather-check-service run current-weather London
# Check permission state
./build/uracil --bundle ~/.aps/packages/weather-check-service permissions
The --bundle flag switches from the compiled demo to an external service. The runtime:
- Reads
manifest.jsonfrom the directory - Validates the bundle contract (name, version, ABI, functions)
- Applies the same permission model as compiled bundles
- Executes function snippets via
python3 functions/<name>.py - Sets
URACIL_*environment variables for the subprocess
Campaign kernel
Uracil exposes a persistent campaign-kernel surface for multi-step coordinators and agent harnesses. Each campaign gets its own runtime root under ~/.uracil/campaigns/<campaign-id>/, including an artifacts/ directory for owned binaries and payloads that are cleaned up when the campaign finishes.
# Bootstrap a campaign runtime root
./build/uracil campaign init demo-campaign keryx keryx-ami adeno-cauth
# Attach a generated artifact for later cleanup
./build/uracil campaign attach-artifact demo-campaign artifacts/writer.ura
# Transition to running
./build/uracil campaign start demo-campaign
# Complete the campaign and clean registered artifacts
./build/uracil campaign complete demo-campaign
# Remove the campaign kernel state entirely
./build/uracil campaign destroy demo-campaign
Permission Model
Uracil separates declared capabilities from user-granted permissions.
A service bundle's manifest lists every permission the service might need:
{
"permissions": {
"requested": ["fs.read", "net.client", "clock.read"]
}
}
Each function declares which subset it actually requires:
{
"name": "current-weather",
"description": "Fetch current weather for a city",
"required_permissions": ["net.client"]
}
The runtime will only execute a function if every permission in its required_permissions has been granted by the user. Grants are stored locally in ~/.uracil/grants/<service-name>.perm.
Available permissions
| Permission | Capability |
|---|---|
fs.read |
Read files from the host |
fs.write |
Write files to the host |
net.client |
Make outbound network connections |
net.server |
Listen for inbound connections |
proc.spawn |
Spawn child processes |
clock.read |
Read the system clock |
Grant lifecycle
# View what's requested vs. granted
uracil --bundle <dir> permissions
# Grant specific permissions
uracil --bundle <dir> grant net.client clock.read
# Revoke a permission
uracil --bundle <dir> revoke net.client
# The runtime refuses to run functions with unmet requirements
uracil --bundle <dir> run current-weather # → permission-denied
Bundle Manifest
Every service bundle carries a manifest.json at its root:
{
"name": "weather-check-service",
"version": "0.1.0",
"description": "Fetches weather through a permission-scoped function",
"runtime": {
"name": "uracil",
"abi": "uracil.service.v1",
"mode": "rootless",
"hotswap_group": "weather-check-service",
"payload_revision": "0.1.0",
"target_env": "keryx-ami"
},
"security": {
"cauth": {
"enabled": true,
"mode": "adeno-cauth",
"base_url": "https://adeno.ltd/cauth",
"issuer": "https://adeno.ltd/cauth",
"audience": "keryx",
"token_env": "KERYX_TRANSTOKEN",
"secret_key_env": "CAUTH_SECRET_KEY"
}
},
"service": {
"entry_function": "current-weather",
"functions": [
{
"name": "current-weather",
"description": "Fetch current weather for a city",
"snippet_path": "functions/current_weather.py",
"required_permissions": ["net.client"]
},
{
"name": "inspect-fs-native",
"description": "List the working directory with a native helper",
"snippet_path": "functions/inspect_fs.cpp",
"language": "cpp",
"build": { "standard": "c++20", "flags": ["-O3"] },
"required_permissions": ["fs.read"]
}
]
},
"permissions": {
"requested": ["fs.read", "net.client", "clock.read"]
}
}
Manifest fields
| Field | Required | Description |
|---|---|---|
name |
Yes | Globally unique service identifier |
version |
Yes | Semantic version |
description |
No | Human-readable summary |
runtime.name |
No | Runtime target (uracil) |
runtime.abi |
No | ABI version (uracil.service.v1) |
runtime.mode |
No | Execution mode (rootless) |
runtime.hotswap_group |
No | Group ID for safe payload updates |
runtime.payload_revision |
No | Current payload version |
runtime.target_env |
No | Deployment profile such as keryx-ami |
security.cauth |
No | CAuth runtime metadata projected as URACIL_CAUTH_* |
service.entry_function |
No | Default function to run |
service.functions[] |
No | Array of function descriptors |
service.functions[].language |
No | python (default) or cpp for native functions |
service.functions[].build |
No | Optional native compile options |
service.functions[].binary_path |
No | Prebuilt native binary path for compiled .ura bundles |
permissions.requested |
No | Union of all permissions the service needs |
Subprocess Execution
When running an external bundle, Uracil executes function payloads as child processes:
uracil --bundle <dir> run <function> [args...]
│
├── fork()
│
└── child:
chdir(<service_directory>)
setenv(URACIL_SERVICE_NAME, ...)
setenv(URACIL_GRANTED_PERMISSIONS, ...)
exec("python3", "functions/<function>.py", args...) # Python
exec("compiled/<function>", args...) # Native C++
Environment variables
| Variable | Description |
|---|---|
URACIL_SERVICE_NAME |
Service identifier from manifest |
URACIL_SERVICE_VERSION |
Version string |
URACIL_FUNCTION_NAME |
Name of the function being executed |
URACIL_RUNTIME_ABI |
ABI version |
URACIL_HOTSWAP_GROUP |
Hot-swap group identifier |
URACIL_PAYLOAD_REVISION |
Current payload revision |
URACIL_TARGET_ENV |
Deployment profile such as keryx-ami |
URACIL_SERVICE_DIR |
Absolute path to the service directory |
URACIL_STATE_DIR |
Path to ~/.uracil |
URACIL_ROOTLESS |
Always true in rootless mode |
URACIL_REQUESTED_PERMISSIONS |
Comma-separated list |
URACIL_GRANTED_PERMISSIONS |
Comma-separated list |
URACIL_CAUTH_* |
Adeno CAuth runtime contract for token and envelope metadata |
URACIL_RUNNER_* |
GGUF/API runner contract exposed to snippets and compiled .ura binaries |
APS Integration
Uracil is designed as a runtime target for the APS package ecosystem:
┌─────────────┐ codegen ┌────────────────┐
│ Keryx │──────────────→│ .aps archive │
│ (Devstral) │ │ manifest.json │
└─────────────┘ │ functions/*.py │
└───────┬────────┘
│ aps install service
▼
┌────────────────┐
│ APS registry │
│ ~/.aps/pkgs/ │
└───────┬────────┘
│ uracil --bundle
▼
┌────────────────┐
│ Uracil │
│ permission ──→ │ grant/deny
│ subprocess ──→ │ execute
└────────────────┘
Typical workflow:
aps install service weather-check-service
aps audit weather-check-service # inspect locally without exposing secrets
uracil --bundle ~/.aps/packages/weather-check-service describe
uracil --bundle ~/.aps/packages/weather-check-service grant net.client
uracil --bundle ~/.aps/packages/weather-check-service run current-weather London
GGUF service runners
Athena packages model-backed services as APS bundles first, then compiles them into .ura binaries. For GGUF-backed services, include runner metadata in the manifest so the URA artifact carries the model contract alongside the function definitions:
{
"runner": {
"kind": "gguf-http",
"protocol": "http",
"bind": "127.0.0.1:8088",
"model": {
"format": "gguf",
"uri": "corpus://athena/models/mistral-7b-instruct.gguf"
}
}
}
For virtualized accelerator targets, keep the source model in GGUF while declaring the runtime target separately:
{
"runner": {
"kind": "gguf-neuron",
"protocol": "http",
"bind": "127.0.0.1:8091",
"model": {
"format": "gguf",
"uri": "corpus://athena/models/mistral-7b-instruct.gguf"
},
"virtualization": {
"target": "aws-neuron-inf2",
"accelerator": "neuron",
"source_format": "gguf",
"runtime_format": "neff"
}
}
}
Both execution paths expose this contract to snippets via URACIL_RUNNER_* environment variables.
Architecture
Two-tier design
- C core (
kernel/+arch/host/) — compiled binary with embedded demo bundle demonstrating the permission engine, grant store, and function dispatch in native code. - External loader — loads service bundles from JSON manifests at runtime and executes function snippets as subprocesses. This is the path APS-installed packages take.
Both tiers share the same permission model (requested → granted → enforced), the same grant store, the same bundle descriptor structure, and the same CLI interface.
Design principles
- Capability-scoped — no ambient authority; every function must declare what it needs.
- Rootless — no elevated privileges; services run as the current user.
- Host-first — establish the contract on Linux, then port to other targets.
- Zero dependencies — the C runtime needs only libc and POSIX.
- Hot-swap ready — payload revisions within a group can be updated safely.