Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/openagen/zeroclaw/llms.txt

Use this file to discover all available pages before exploring further.

ZeroClaw’s runtime is deliberately lightweight — common operations use under 5 MB of RAM — but compile-time requirements are significantly higher. This page explains the gap between runtime and build-time resource needs, documents the currently proposed resource-limit mechanisms, and covers the configuration schema under active design.
The resource limit configuration described on this page is a proposal / roadmap item and does not reflect current runtime behavior. For current runtime configuration, see the config reference, operations runbook, and troubleshooting guide.

Runtime vs. build-time resource requirements

PhaseRAMDisk
Runtime (common operations)<5 MBminimal
Full source build2 GB RAM + swap minimum, 4 GB+ recommended6+ GB free
The large build-time requirement comes from the Matrix E2EE stack (matrix-sdk, ruma, vodozemac), TLS and crypto native build scripts (aws-lc-sys, ring), and rusqlite’s bundled SQLite C compilation. The compiled binary itself is small; only the compilation process is expensive.
On constrained hosts, use ./install.sh --prefer-prebuilt to skip compilation entirely. See the troubleshooting guide for more detail.

The resource cap problem

ZeroClaw currently enforces rate limiting (20 actions/hour) but has no hard resource caps. A runaway agent could:
  • Exhaust available memory
  • Spin CPU at 100%
  • Fill disk with logs or output
The options below describe the approaches under consideration to address this.

Proposed resource limit mechanisms

Wrap async tasks with a timeout to prevent task starvation and runaway CPU usage.
use tokio::time::{timeout, Duration};

pub async fn execute_with_timeout<F, T>(
    fut: F,
    cpu_time_limit: Duration,
    memory_limit: usize,
) -> Result<T>
where
    F: Future<Output = Result<T>>,
{
    // CPU timeout
    timeout(cpu_time_limit, fut).await?
}
This is low-effort and high-impact for preventing individual tasks from running indefinitely.
Track heap usage with a custom GlobalAlloc implementation and abort the process if a configured limit is exceeded.
use std::alloc::{GlobalAlloc, Layout, System};

struct LimitedAllocator<A> {
    inner: A,
    max_bytes: usize,
    used: std::sync::atomic::AtomicUsize,
}

unsafe impl<A: GlobalAlloc> GlobalAlloc for LimitedAllocator<A> {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        let current = self.used.fetch_add(layout.size(), std::sync::atomic::Ordering::Relaxed);
        if current + layout.size() > self.max_bytes {
            std::process::abort();
        }
        self.inner.alloc(layout)
    }
}
This gives fine-grained control over heap growth without relying on OS-level mechanisms.

Proposed config schema

The following [resources] section is under design and not yet active in the runtime.
[resources]
# Memory limits (in MB)
max_memory_mb = 512
max_memory_per_command_mb = 128

# CPU limits
max_cpu_percent = 50
max_cpu_time_seconds = 60

# Disk I/O limits
max_log_size_mb = 100
max_temp_storage_mb = 500

# Process limits
max_subprocesses = 10
max_open_files = 100

Implementation priority

PhaseFeatureEffortImpact
P0Memory monitoring + killLowHigh
P1CPU timeout per commandLowHigh
P2cgroups integration (Linux)MediumVery High
P3Disk I/O limitsMediumMedium

Build docs developers (and LLMs) love