@forgememo-cli/aicap
v0.1.0
Published
Memory-cap any command (AI coding agents, builds, background jobs) on macOS/Linux — real enforcement via Docker cgroups or a polling watchdog, since macOS has no working per-process memory rlimit.
Maintainers
Readme
aicap
Memory-cap any command — AI coding agents, builds, background jobs — on macOS/Linux.
Why
macOS has no working per-process memory limit in userspace. Verified empirically:
setrlimit(RLIMIT_AS, ...),RLIMIT_DATA,RLIMIT_RSSall returnEINVALon modern macOS — the kernel rejects them outright,ulimit -vincluded.- launchd's own
HardResourceLimits.ResidentSetSizeis a no-op — a job capped at 100MB was observed running past 590MB, stillstate = active.
So a runaway process — a leaking build tool, an AI agent that gets stuck in a loop, a stray find / — has nothing standing between it and system OOM on macOS. aicap fills that gap with the two mechanisms that actually work.
What it does
aicap --limit <mb> -- <command> [args...]Two backends, auto-selected:
- Docker cgroup (
--memory) — used when Docker is installed and running. Hard cap, real kernel enforcement, zero race window. - Polling watchdog (
psRSS +SIGKILL) — fallback when Docker isn't available. No dependencies, works anywherepsexists. Has a small race window bounded by--interval(default 200ms) — a process can spike briefly past the cap between polls before being killed.
Both are honest about their mechanism: neither claims kernel-enforced rlimit, because that doesn't exist on macOS for arbitrary processes.
Install
npm install -g aicapor clone and symlink bin/aicap onto your PATH.
Usage
# cap a build at 2GB
aicap --limit 2048 -- npm run build
# cap an AI coding agent run at 512MB
aicap --limit 512 -- claude -p "refactor this module"
# force the watchdog even if Docker is available
aicap --limit 1024 --force-watchdog -- ./some-script.sh
# use a different docker image for the docker backend (default: node:22-slim)
aicap --limit 4096 --image python:3.12-slim -- python train.pyEnv var overrides: AICAP_LIMIT_MB, AICAP_IMAGE, AICAP_INTERVAL.
On cap breach, aicap kills the process and exits 137 (same convention as Docker's own OOM-kill exit code).
Limitations
- Docker backend mounts
$PWDinto the container at/workand runs there — paths outside$PWDaren't visible to the command. - Watchdog backend has a real (if small) race window; for a hard guarantee, use the Docker backend.
- Neither backend can cap a process that immediately forks and hides children under a different watched PID tree in unusual ways — the watchdog only tracks the direct child.
License
MIT
