@madarco/agentbox 0.1.0

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 (33) hide show
  1. package/LICENSE +21 -0
  2. package/dist/chunk-IDR4HVIC.js +106 -0
  3. package/dist/chunk-IDR4HVIC.js.map +1 -0
  4. package/dist/chunk-J35IH7W5.js +200 -0
  5. package/dist/chunk-J35IH7W5.js.map +1 -0
  6. package/dist/chunk-O5HS3QHW.js +2164 -0
  7. package/dist/chunk-O5HS3QHW.js.map +1 -0
  8. package/dist/chunk-OOOKFFR5.js +496 -0
  9. package/dist/chunk-OOOKFFR5.js.map +1 -0
  10. package/dist/chunk-RWJE6AER.js +515 -0
  11. package/dist/chunk-RWJE6AER.js.map +1 -0
  12. package/dist/chunk-SOMIKEN2.js +1651 -0
  13. package/dist/chunk-SOMIKEN2.js.map +1 -0
  14. package/dist/create-LSSO7H4I-GWNALUMF.js +15 -0
  15. package/dist/create-LSSO7H4I-GWNALUMF.js.map +1 -0
  16. package/dist/index.js +4067 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/lifecycle-P4FSKGR2-3466P54Y.js +38 -0
  19. package/dist/lifecycle-P4FSKGR2-3466P54Y.js.map +1 -0
  20. package/dist/state-ZSP3ORXW-WI6KOIG3.js +26 -0
  21. package/dist/state-ZSP3ORXW-WI6KOIG3.js.map +1 -0
  22. package/dist/stats-GZFLPYTU-DBJ2DVBJ.js +19 -0
  23. package/dist/stats-GZFLPYTU-DBJ2DVBJ.js.map +1 -0
  24. package/package.json +73 -0
  25. package/runtime/docker/Dockerfile.box +316 -0
  26. package/runtime/docker/apps/cli/share/agentbox-setup/SKILL.md +188 -0
  27. package/runtime/docker/packages/ctl/dist/bin.cjs +12770 -0
  28. package/runtime/docker/packages/sandbox-docker/scripts/agentbox-dockerd-start +52 -0
  29. package/runtime/docker/packages/sandbox-docker/scripts/agentbox-vnc-start +77 -0
  30. package/runtime/docker/packages/sandbox-docker/scripts/claude-managed-settings.json +54 -0
  31. package/runtime/docker/packages/sandbox-docker/scripts/custom-system-CLAUDE.md +21 -0
  32. package/runtime/relay/bin.cjs +11467 -0
  33. package/share/agentbox-setup/SKILL.md +188 -0
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env bash
2
+ # Start the in-box dockerd. Launched by the host via
3
+ # `docker exec -d --user root` after the FUSE overlay is up. Idempotent — safe
4
+ # to call again on `agentbox start`. Storage driver is fuse-overlayfs (set in
5
+ # /etc/docker/daemon.json baked into the image) so the inner daemon doesn't
6
+ # need the kernel `overlay` driver, which an unprivileged container can't load.
7
+
8
+ set -euo pipefail
9
+
10
+ if pgrep -x dockerd >/dev/null; then
11
+ exit 0
12
+ fi
13
+
14
+ mkdir -p /var/lib/docker /var/run /var/log/agentbox
15
+
16
+ # /var/run lives in the container's writable layer (not a volume), so files
17
+ # written by the previous dockerd run survive `docker stop`/`start`. dockerd
18
+ # refuses to start if `/var/run/docker.pid` exists with a PID in /proc — and
19
+ # after restart, that PID number has been reassigned to (probably) the new
20
+ # `sleep infinity`. Wipe both the pidfile and the stale socket here; pgrep
21
+ # above already confirmed no real dockerd is running.
22
+ rm -f /var/run/docker.pid /var/run/docker.sock
23
+
24
+ # Cgroup v2 + unprivileged DinD on OrbStack/Docker Desktop: the outer
25
+ # container has /sys/fs/cgroup and /proc/sys bind-mounted RO from the host
26
+ # (Docker's standard hardening). We need both writable for dockerd to:
27
+ # * mkdir /sys/fs/cgroup/docker (its own cgroup slice for child containers)
28
+ # * write /proc/sys/net/ipv6/conf/<veth>/disable_ipv6 (default bridge setup)
29
+ # Without these, `docker run` fails with EROFS or "failed to disable IPv6".
30
+ # SYS_ADMIN + the private cgroup namespace let us remount these RW; the
31
+ # writes only affect the box's own namespaces (not the host). Failure is
32
+ # tolerable — some hosts already mount these RW.
33
+ mount -o remount,rw /sys/fs/cgroup 2>/dev/null || true
34
+ mount -o remount,rw /proc/sys 2>/dev/null || true
35
+
36
+ # nohup + & + disown lets us survive the `docker exec -d` returning. dockerd
37
+ # reads /etc/docker/daemon.json on its own; no flags here keeps the start path
38
+ # debuggable from inside the container (just edit the file and restart).
39
+ nohup dockerd >/var/log/agentbox/dockerd.log 2>&1 &
40
+
41
+ # Wait for the socket to become accept()-able. Bound by ~30s — first start has
42
+ # to initialize iptables chains and the fuse-overlayfs graphdriver, which is
43
+ # noticeably slower than overlay2.
44
+ for _ in $(seq 1 300); do
45
+ if [ -S /var/run/docker.sock ] \
46
+ && docker -H unix:///var/run/docker.sock info >/dev/null 2>&1; then
47
+ break
48
+ fi
49
+ sleep 0.1
50
+ done
51
+
52
+ disown -a
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env bash
2
+ # Start the per-box VNC stack: Xvnc on :1 (loopback inside container) +
3
+ # websockify on 0.0.0.0:6080 serving noVNC's HTML5 client and proxying RFB.
4
+ # Launched by the host via `docker exec -d --user vscode` after the container
5
+ # is up. Idempotent — re-running while the daemons are alive is a no-op, so
6
+ # `agentbox start` can blindly call us again.
7
+
8
+ set -euo pipefail
9
+
10
+ PASS="${AGENTBOX_VNC_PASSWORD:-}"
11
+ if [[ -z "$PASS" ]]; then
12
+ echo "agentbox-vnc-start: AGENTBOX_VNC_PASSWORD is not set" >&2
13
+ exit 64
14
+ fi
15
+
16
+ if pgrep -u "$(id -u)" -x Xvnc >/dev/null \
17
+ && pgrep -u "$(id -u)" -f "websockify.*6080" >/dev/null; then
18
+ exit 0
19
+ fi
20
+
21
+ mkdir -p "$HOME/.vnc"
22
+ # vncpasswd's -f mode reads plaintext on stdin, writes the DES blob to stdout.
23
+ # VncAuth truncates >8 chars at compare time, which is fine — the host writes
24
+ # an 8-char password. Write to a temp file + rename so a failure (e.g.,
25
+ # vncpasswd missing) doesn't leave an empty file that Xvnc would then reject.
26
+ TMP_PASSWD="$(mktemp "$HOME/.vnc/passwd.XXXXXX")"
27
+ printf '%s\n' "$PASS" | vncpasswd -f > "$TMP_PASSWD"
28
+ chmod 600 "$TMP_PASSWD"
29
+ mv "$TMP_PASSWD" "$HOME/.vnc/passwd"
30
+
31
+ mkdir -p /var/log/agentbox 2>/dev/null || true
32
+
33
+ # Xvnc on display :1, loopback-only (websockify is the only public ingress).
34
+ # 1280x800x24 is a sensible laptop-browser viewport.
35
+ # The clipboard params are on-by-default in TigerVNC 1.13 but pinned here so a
36
+ # base-image bump can't silently break host->box paste, and to document intent:
37
+ # accept cut-text from noVNC, set both the X CLIPBOARD and PRIMARY selections.
38
+ Xvnc :1 \
39
+ -localhost \
40
+ -SecurityTypes VncAuth \
41
+ -PasswordFile "$HOME/.vnc/passwd" \
42
+ -geometry 1280x800 \
43
+ -depth 24 \
44
+ -AlwaysShared \
45
+ -AcceptCutText=1 \
46
+ -SendCutText=1 \
47
+ -SetPrimary=1 \
48
+ -SendPrimary=1 \
49
+ >/var/log/agentbox/xvnc.log 2>&1 &
50
+
51
+ # Wait for Xvnc's RFB socket (5901). bash's /dev/tcp pseudo-device makes the
52
+ # probe a one-liner without needing netcat in the image.
53
+ for _ in $(seq 1 50); do
54
+ if (echo > /dev/tcp/127.0.0.1/5901) 2>/dev/null; then break; fi
55
+ sleep 0.1
56
+ done
57
+
58
+ # With no window manager, nothing owns the X selections, so Xvnc's RFB cut-text
59
+ # isn't reliably handed to Chromium on Ctrl+V. autocutsel (one daemon per
60
+ # selection) keeps CLIPBOARD and PRIMARY populated and synced. Best-effort: a
61
+ # clipboard failure must never abort VNC, and the pgrep guard keeps a stray
62
+ # re-entry from spawning duplicates (Xvnc is up now, so DISPLAY=:1 resolves).
63
+ if ! pgrep -u "$(id -u)" -x autocutsel >/dev/null; then
64
+ DISPLAY=:1 autocutsel -selection CLIPBOARD -fork >/dev/null 2>&1 || true
65
+ DISPLAY=:1 autocutsel -selection PRIMARY -fork >/dev/null 2>&1 || true
66
+ fi
67
+
68
+ # websockify serves noVNC at /vnc.html (--web) and tunnels WS frames to Xvnc's
69
+ # RFB. Bind 0.0.0.0:6080 so both Docker `-p` mappings and OrbStack's
70
+ # <name>.orb.local routing reach it.
71
+ websockify \
72
+ --web=/usr/share/novnc \
73
+ 0.0.0.0:6080 \
74
+ 127.0.0.1:5901 \
75
+ >/var/log/agentbox/websockify.log 2>&1 &
76
+
77
+ disown -a
@@ -0,0 +1,54 @@
1
+ {
2
+ "$comment": "AgentBox enterprise-managed Claude Code settings, baked into the box image at /etc/claude-code/managed-settings.json. Highest precedence and NOT synced from the host ~/.claude, so claude-hooks-filter.ts never touches it; per Claude Code, hook arrays MERGE across settings sources, so the user's own hooks still run. These hooks report Claude's activity to the box supervisor (agentbox-ctl claude-state -> ctl socket -> relay -> ~/.agentbox/boxes/<id>/status.json) so `agentbox status/list/inspect` can show it even when the box is paused. Each command is exit-0 fast and shell-backgrounded so a hook can never block or fail a Claude turn.",
3
+ "hooks": {
4
+ "UserPromptSubmit": [
5
+ {
6
+ "hooks": [
7
+ { "type": "command", "command": "agentbox-ctl claude-state working >/dev/null 2>&1 &", "timeout": 3 }
8
+ ]
9
+ }
10
+ ],
11
+ "PreToolUse": [
12
+ {
13
+ "hooks": [
14
+ { "type": "command", "command": "agentbox-ctl claude-state working >/dev/null 2>&1 &", "timeout": 3 }
15
+ ]
16
+ }
17
+ ],
18
+ "Stop": [
19
+ {
20
+ "hooks": [
21
+ { "type": "command", "command": "agentbox-ctl claude-state idle >/dev/null 2>&1 &", "timeout": 3 }
22
+ ]
23
+ }
24
+ ],
25
+ "Notification": [
26
+ {
27
+ "matcher": "permission_prompt",
28
+ "hooks": [
29
+ { "type": "command", "command": "agentbox-ctl claude-state waiting >/dev/null 2>&1 &", "timeout": 3 }
30
+ ]
31
+ },
32
+ {
33
+ "matcher": "idle_prompt",
34
+ "hooks": [
35
+ { "type": "command", "command": "agentbox-ctl claude-state idle >/dev/null 2>&1 &", "timeout": 3 }
36
+ ]
37
+ }
38
+ ],
39
+ "SessionStart": [
40
+ {
41
+ "hooks": [
42
+ { "type": "command", "command": "agentbox-ctl claude-state idle >/dev/null 2>&1 &", "timeout": 3 }
43
+ ]
44
+ }
45
+ ],
46
+ "SessionEnd": [
47
+ {
48
+ "hooks": [
49
+ { "type": "command", "command": "agentbox-ctl claude-state idle >/dev/null 2>&1 &", "timeout": 3 }
50
+ ]
51
+ }
52
+ ]
53
+ }
54
+ }
@@ -0,0 +1,21 @@
1
+ # AgentBox sandbox
2
+
3
+ You are running inside an AgentBox sandbox: a Linux Docker container with
4
+ docker-in-docker (run `docker` directly, no sudo). The host filesystem is
5
+ mounted read-only at /host-src; /workspace is a FUSE overlay where your
6
+ writes go to a per-box volume.
7
+
8
+ This container has no SSH credentials and no host gitconfig identity.
9
+ For git operations that need the user (push, pull from private remotes),
10
+ use `agentbox-ctl git pull|push -- <args>` — it RPCs to the host, which
11
+ runs git with the real SSH agent and gitconfig. Local commits work as
12
+ normal because the main `.git/` is bind-mounted at the same absolute
13
+ path as on the host.
14
+
15
+ Your `~/.claude` and `/workspace` env files live only in this box. If
16
+ you install a skill/plugin (or otherwise change `~/.claude`), tell the
17
+ user to run `agentbox pull claude` on the host to copy it back. If you
18
+ create or change `.env`/`.envrc`/secrets files, tell them to run
19
+ `agentbox pull env`. Both are additive and never overwrite host files.
20
+
21
+ Box identity is in /etc/agentbox/box.env and the AGENTBOX_* env vars.