caproom 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +14 -0
  2. package/bin/caproom +40 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -58,6 +58,16 @@ Env var overrides: `CAPROOM_LIMIT_MB`, `CAPROOM_IMAGE`, `CAPROOM_INTERVAL`, `CAP
58
58
 
59
59
  On cap breach, the watchdog backend sends `SIGTERM` first and waits `--grace` seconds before `SIGKILL`. If the process exits cleanly during the grace window, `caproom` propagates its real exit code; only a hard `SIGKILL` (process ignored `SIGTERM`, or grace ran out) reports `137` (same convention as Docker's own OOM-kill exit code, which the docker backend always uses on breach since Docker itself sends the kill).
60
60
 
61
+ ## init — auto-cap a command on every launch
62
+
63
+ For a command you always want capped (e.g. an AI coding agent), don't type the wrapper every time — bake it into your shell so a new terminal tab is capped automatically:
64
+
65
+ ```bash
66
+ caproom init claude --limit 6144 --grace 10 >> ~/.zshrc && source ~/.zshrc
67
+ ```
68
+
69
+ This appends a shell function that wraps `claude` through the watchdog backend (host-native — no Docker isolation, so the wrapped command keeps its normal filesystem/auth/PATH access) and an alias so plain `claude` picks it up. Per-shell override without editing the rc file: `CAPROOM_LIMIT_MB=8192 claude ...`. Works for any command, not just `claude` — `caproom init npm --limit 2048` wraps `npm` the same way.
70
+
61
71
  ## park / wake — reclaim idle memory without killing
62
72
 
63
73
  Long-running agent sessions accumulate subprocesses that go idle but stay resident — old file watchers, finished tool-call children, stale servers. Killing them loses state; leaving them wastes RAM. `caproom park` freezes instead:
@@ -77,6 +87,10 @@ No daemon, no tracking file, no dependency — just `SIGSTOP`/`SIGCONT` wrapped
77
87
 
78
88
  **Caveat**: a parked process does zero work while stopped — no CPU, no I/O, no timers firing. Only park something actually idle (a background watcher, a finished subprocess kept around for reuse) — never park the process an agent is actively waiting on a response from, or you'll hang the agent, not save it memory.
79
89
 
90
+ ## What it never touches
91
+
92
+ caproom only watches OS-level RSS and sends signals (`SIGTERM`/`SIGKILL`/`SIGSTOP`/`SIGCONT`). The watchdog backend runs the wrapped command as a direct child with stdin/stdout/stderr passed straight through — no pipe, no buffering, no interception. The Docker backend passes stdio through the same way (`docker run -i`). caproom never reads, modifies, or truncates anything the wrapped process reads or writes — including an AI agent's own conversation/context stream. It manages RAM headroom only, nothing else.
93
+
80
94
  ## Limitations
81
95
 
82
96
  - Docker backend mounts `$PWD` into the container at `/work` and runs there — paths outside `$PWD` aren't visible to the command.
package/bin/caproom CHANGED
@@ -10,11 +10,15 @@
10
10
  set -euo pipefail
11
11
 
12
12
  usage() {
13
- cat >&2 << 'EOF'
13
+ local stream=/dev/stderr
14
+ local code=1
15
+ if [[ "${1:-}" == "help" ]]; then stream=/dev/stdout; code=0; fi
16
+ cat >"$stream" << 'EOF'
14
17
  usage: caproom [--limit <mb>] [--image <docker-image>] [--interval <sec>] -- <command> [args...]
15
18
  caproom park <pid>
16
19
  caproom wake <pid>
17
20
  caproom status <pid>
21
+ caproom init <command> [--limit <mb>] [--grace <sec>]
18
22
 
19
23
  --limit <mb> memory cap in MB (default: 4096)
20
24
  --image <name> docker image to run the command in, when using the docker
@@ -35,6 +39,12 @@ becomes eligible for compression under system memory pressure. `caproom wake
35
39
  Any agent can call these directly — they're just SIGSTOP/SIGCONT, no daemon,
36
40
  no tracking file required.
37
41
 
42
+ init <command> — print a shell snippet that auto-caps <command> on every
43
+ invocation, so a new terminal tab is capped with no extra typing. Append the
44
+ output to your shell rc (~/.zshrc, ~/.bashrc):
45
+
46
+ caproom init claude >> ~/.zshrc && source ~/.zshrc
47
+
38
48
  env vars (override flags): CAPROOM_LIMIT_MB, CAPROOM_IMAGE, CAPROOM_INTERVAL, CAPROOM_GRACE
39
49
 
40
50
  examples:
@@ -42,8 +52,33 @@ examples:
42
52
  caproom --limit 512 -- claude --dangerously-skip-permissions -p "task"
43
53
  caproom park 12345
44
54
  caproom wake 12345
55
+ caproom init claude --limit 6144 --grace 10
56
+ EOF
57
+ exit "$code"
58
+ }
59
+
60
+ cmd_init() {
61
+ local target="${1:-}"
62
+ [[ -z "$target" ]] && { echo "usage: caproom init <command> [--limit <mb>] [--grace <sec>]" >&2; exit 1; }
63
+ shift
64
+ local limit=4096
65
+ local grace=5
66
+ while [[ $# -gt 0 ]]; do
67
+ case "$1" in
68
+ --limit) limit="$2"; shift 2 ;;
69
+ --grace) grace="$2"; shift 2 ;;
70
+ *) echo "caproom: unknown init flag $1" >&2; exit 1 ;;
71
+ esac
72
+ done
73
+ local fn="${target}_capped"
74
+ cat << EOF
75
+ # caproom: auto-cap '$target' — added by 'caproom init $target'
76
+ # override per-shell: CAPROOM_LIMIT_MB=8192 $target ...
77
+ $fn() {
78
+ command caproom --limit "\${CAPROOM_LIMIT_MB:-$limit}" --force-watchdog --grace "\${CAPROOM_GRACE:-$grace}" -- command $target "\$@"
79
+ }
80
+ alias $target=$fn
45
81
  EOF
46
- exit 1
47
82
  }
48
83
 
49
84
  cmd_park() {
@@ -72,6 +107,8 @@ case "${1:-}" in
72
107
  park) shift; cmd_park "$@"; exit 0 ;;
73
108
  wake) shift; cmd_wake "$@"; exit 0 ;;
74
109
  status) shift; cmd_status "$@"; exit 0 ;;
110
+ init) shift; cmd_init "$@"; exit 0 ;;
111
+ help|-h|--help) usage help ;;
75
112
  esac
76
113
 
77
114
  LIMIT_MB="${CAPROOM_LIMIT_MB:-4096}"
@@ -88,7 +125,7 @@ while [[ $# -gt 0 ]]; do
88
125
  --grace) GRACE="$2"; shift 2 ;;
89
126
  --force-watchdog) FORCE_WATCHDOG=1; shift ;;
90
127
  --) shift; break ;;
91
- -h|--help) usage ;;
128
+ -h|--help) usage help ;;
92
129
  *) break ;;
93
130
  esac
94
131
  done
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "caproom",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Memory-cap any command (AI coding agents, builds, background jobs) on macOS/Linux — real enforcement via Docker cgroups or a polling watchdog, plus park/wake to reclaim idle process memory without killing.",
5
5
  "bin": {
6
6
  "caproom": "bin/caproom"