aibox-cli 0.1.0 → 0.3.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 (3) hide show
  1. package/README.md +13 -12
  2. package/bin/aibox +47 -21
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -88,7 +88,7 @@ aibox generates a `compose.dev.yaml` and configures your IDE on `aibox init` (or
88
88
  2. Run `aibox init` in your project
89
89
  3. Set the plugin's startup command to:
90
90
  ```
91
- /usr/local/bin/aibox claude --yolo
91
+ npx aibox claude --yolo
92
92
  ```
93
93
 
94
94
  The Node.js interpreter is also configured to use the container, so running/debugging from the IDE uses the same sandboxed environment.
@@ -147,17 +147,18 @@ SHARED_MODULES=false
147
147
 
148
148
  ## All Flags
149
149
 
150
- | Flag | Description |
151
- |------|-------------|
152
- | `--name NAME` | Named instance (multiple containers per project) |
153
- | `--image NAME` | Override base Docker image |
154
- | `--shared-modules` | Share node_modules between host and container |
155
- | `--copy` | Copy repo into Docker volume (full isolation) |
156
- | `--worktree` | Use git worktree (lightweight isolation) |
157
- | `--yolo` | Skip prompts, full sudo, no firewall |
158
- | `--safe` | Keep prompts, restricted sudo, firewall on |
159
- | `--all` | With `down`: stop all project containers |
160
- | `--clean` | With `down`: also remove copy volumes / worktrees |
150
+ | Short | Long | Description |
151
+ |-------|------|-------------|
152
+ | `-n` | `--name NAME` | Named instance (multiple containers per project) |
153
+ | `-d` | `--dir PATH` | Run in a different project directory |
154
+ | `-i` | `--image NAME` | Override base Docker image |
155
+ | `-c` | `--copy` | Copy repo into Docker volume (full isolation) |
156
+ | `-w` | `--worktree` | Use git worktree (lightweight isolation) |
157
+ | `-y` | `--yolo` | Skip prompts, full sudo, no firewall |
158
+ | `-s` | `--safe` | Keep prompts, restricted sudo, firewall on |
159
+ | | `--shared-modules` | Share node_modules between host and container |
160
+ | | `--all` | With `down`: stop all project containers |
161
+ | | `--clean` | With `down`: also remove copy volumes / worktrees |
161
162
 
162
163
  ## License
163
164
 
package/bin/aibox CHANGED
@@ -20,14 +20,15 @@
20
20
  # aibox help Show this help (default)
21
21
  #
22
22
  # Flags:
23
- # --name NAME Run a named instance (e.g. --name refactor)
23
+ # -n, --name NAME Run a named instance (e.g. -n refactor)
24
24
  # Allows multiple containers per project
25
- # --image NAME Override base Docker image (default: aibox:latest)
25
+ # -d, --dir PATH Run in a different project directory
26
+ # -i, --image NAME Override base Docker image (default: aibox:latest)
27
+ # -c, --copy Copy project into container (full isolation, no host sync)
28
+ # -w, --worktree Use git worktree (lightweight isolation, stays on host)
29
+ # -y, --yolo Yolo mode: skip permissions, full sudo, no firewall
30
+ # -s, --safe Safe mode: keep permissions, restricted sudo, firewall on
26
31
  # --shared-modules Share node_modules between host and container
27
- # --copy Copy project into container (full isolation, no host sync)
28
- # --worktree Use git worktree (lightweight isolation, stays on host)
29
- # --yolo Yolo mode: skip permissions, full sudo, no firewall
30
- # --safe Safe mode: keep permissions, restricted sudo, firewall on
31
32
  #
32
33
  # Network firewall:
33
34
  # Default: only allows Claude API, npm, GitHub, PyPI, SSH, DNS.
@@ -54,7 +55,7 @@ set -euo pipefail
54
55
 
55
56
  # ── Script identity ──────────────────────────────────────────────
56
57
  SCRIPT_NAME="$(basename "$0")"
57
- AIBOX_VERSION="5"
58
+ AIBOX_VERSION="6"
58
59
  CONFIG_DIR="${HOME}/.config/aibox"
59
60
  DEFAULT_IMAGE="aibox:latest"
60
61
  CONTAINER_PREFIX="aibox"
@@ -183,6 +184,7 @@ _check_deps() {
183
184
  IMAGE="$DEFAULT_IMAGE"
184
185
  SHARED_MODULES=false
185
186
  INSTANCE_NAME=""
187
+ PROJECT_DIR_FLAG=""
186
188
  DOWN_ALL=false
187
189
  DOWN_CLEAN=false
188
190
  SKIP_PERMISSIONS=false
@@ -193,24 +195,28 @@ POSITIONAL=()
193
195
  parse_flags() {
194
196
  while [[ $# -gt 0 ]]; do
195
197
  case "$1" in
196
- --image)
198
+ -i|--image)
197
199
  IMAGE="${2:?'--image requires a value'}"
198
200
  shift 2
199
201
  ;;
200
- --name)
202
+ -n|--name)
201
203
  INSTANCE_NAME="${2:?'--name requires a value'}"
202
204
  shift 2
203
205
  ;;
206
+ -d|--dir)
207
+ PROJECT_DIR_FLAG="${2:?'--dir requires a value'}"
208
+ shift 2
209
+ ;;
204
210
  --shared-modules)
205
211
  SHARED_MODULES=true
206
212
  shift
207
213
  ;;
208
- --copy)
214
+ -c|--copy)
209
215
  [[ -n "$ISOLATION" ]] && { echo "Error: --copy and --worktree are mutually exclusive" >&2; exit 1; }
210
216
  ISOLATION="copy"
211
217
  shift
212
218
  ;;
213
- --worktree)
219
+ -w|--worktree)
214
220
  [[ -n "$ISOLATION" ]] && { echo "Error: --copy and --worktree are mutually exclusive" >&2; exit 1; }
215
221
  ISOLATION="worktree"
216
222
  shift
@@ -223,11 +229,11 @@ parse_flags() {
223
229
  DOWN_CLEAN=true
224
230
  shift
225
231
  ;;
226
- --yolo)
232
+ -y|--yolo)
227
233
  SKIP_PERMISSIONS=true
228
234
  shift
229
235
  ;;
230
- --safe)
236
+ -s|--safe)
231
237
  SAFE_MODE=true
232
238
  shift
233
239
  ;;
@@ -254,7 +260,14 @@ elif [[ "$SAFE_MODE" == "true" ]]; then
254
260
  fi
255
261
 
256
262
  # ── Per-project config file (.aibox) ─────────────────────────────
257
- PROJECT_DIR="$(pwd)"
263
+ if [[ -n "$PROJECT_DIR_FLAG" ]]; then
264
+ PROJECT_DIR="$(cd "$PROJECT_DIR_FLAG" 2>/dev/null && pwd)" || {
265
+ echo "Error: directory not found: $PROJECT_DIR_FLAG" >&2
266
+ exit 1
267
+ }
268
+ else
269
+ PROJECT_DIR="$(pwd)"
270
+ fi
258
271
  PROJECT_CONF="${PROJECT_DIR}/.aibox"
259
272
 
260
273
  # ── Safety: refuse to run in dangerous directories ───────────────
@@ -334,7 +347,7 @@ if ! [[ "$INSTANCE_NAME" =~ ^[a-z0-9_-]+$ ]]; then
334
347
  exit 1
335
348
  fi
336
349
  CONTAINER_NAME="${BASE_CONTAINER_NAME}-${INSTANCE_NAME}"
337
- WORKSPACE_DIR="/${PROJECT_NAME}"
350
+ WORKSPACE_DIR="/workspace/${PROJECT_NAME}"
338
351
 
339
352
  # ── Isolation mode setup ─────────────────────────────────────────
340
353
  COPY_VOLUME=""
@@ -423,6 +436,16 @@ set -e
423
436
  # Fix auth volume ownership (Docker creates volumes as root)
424
437
  chown -R aibox:aibox /home/aibox/.claude 2>/dev/null || true
425
438
 
439
+ # ── IDE path symlink ─────────────────────────────────────────
440
+ # Create symlink so container paths match host paths for IDE integration.
441
+ # Claude Code reports cwd-based paths to the IDE plugin; if they don't
442
+ # match host paths, diffs break (empty left side, wrong file path).
443
+ if [[ -n "${AIBOX_HOST_DIR:-}" && -n "${AIBOX_WORKSPACE_DIR:-}" \
444
+ && "$AIBOX_HOST_DIR" != "$AIBOX_WORKSPACE_DIR" ]]; then
445
+ mkdir -p "$(dirname "$AIBOX_HOST_DIR")"
446
+ ln -sfn "$AIBOX_WORKSPACE_DIR" "$AIBOX_HOST_DIR"
447
+ fi
448
+
426
449
  # ── Mode-dependent setup ──────────────────────────────────────
427
450
  MODE="${AIBOX_MODE:-safe}"
428
451
 
@@ -522,7 +545,7 @@ _prepare_copy_volume() {
522
545
 
523
546
  # Check if volume already has content (--entrypoint bypasses su-exec drop)
524
547
  local has_content
525
- has_content=$(docker run --rm --entrypoint sh -v "${COPY_VOLUME}:/${PROJECT_NAME}" "$IMAGE" -c "ls -A /${PROJECT_NAME} 2>/dev/null | head -1" 2>/dev/null || true)
548
+ has_content=$(docker run --rm --entrypoint sh -v "${COPY_VOLUME}:${WORKSPACE_DIR}" "$IMAGE" -c "ls -A ${WORKSPACE_DIR} 2>/dev/null | head -1" 2>/dev/null || true)
526
549
 
527
550
  if [[ -n "$has_content" ]]; then
528
551
  echo "Copy volume already populated (${COPY_VOLUME}). Reusing."
@@ -542,14 +565,15 @@ _prepare_copy_volume() {
542
565
  fi
543
566
 
544
567
  if ! cat "$bundle_file" | docker run --rm -i --entrypoint sh \
545
- -v "${COPY_VOLUME}:/${PROJECT_NAME}" \
568
+ -v "${COPY_VOLUME}:${WORKSPACE_DIR}" \
546
569
  "$IMAGE" -c "
547
570
  cat > /tmp/repo.bundle
548
- cd /${PROJECT_NAME}
571
+ mkdir -p ${WORKSPACE_DIR}
572
+ cd ${WORKSPACE_DIR}
549
573
  git clone /tmp/repo.bundle .
550
574
  rm /tmp/repo.bundle
551
575
  git checkout -b '${branch_name}' 2>/dev/null || git checkout '${branch_name}'
552
- chown -R aibox:aibox /${PROJECT_NAME}
576
+ chown -R aibox:aibox ${WORKSPACE_DIR}
553
577
  "; then
554
578
  rm -f "$bundle_file"
555
579
  docker volume rm "$COPY_VOLUME" 2>/dev/null || true
@@ -635,6 +659,8 @@ _environment_yaml() {
635
659
  echo "${indent}- CLAUDE_CONFIG_DIR=/home/aibox/.claude"
636
660
  echo "${indent}- AIBOX_MODE=\${AIBOX_MODE:-safe}"
637
661
  echo "${indent}- AIBOX_EXTRA_DOMAINS=\${AIBOX_EXTRA_DOMAINS:-}"
662
+ echo "${indent}- AIBOX_HOST_DIR=${PROJECT_DIR}"
663
+ echo "${indent}- AIBOX_WORKSPACE_DIR=${WORKSPACE_DIR}"
638
664
  }
639
665
 
640
666
  # Build -e flags for docker exec from current terminal environment
@@ -696,7 +722,7 @@ services:
696
722
  $(_labels_yaml " ")
697
723
  volumes:
698
724
  $(_volumes_yaml " " "$PROJECT_DIR")
699
- working_dir: ${WORKSPACE_DIR}
725
+ working_dir: ${PROJECT_DIR}
700
726
  environment:
701
727
  $(_environment_yaml " ")
702
728
  stdin_open: true
@@ -724,7 +750,7 @@ services:
724
750
  $(_labels_yaml " ")
725
751
  volumes:
726
752
  $(_volumes_yaml " " ".")
727
- working_dir: ${WORKSPACE_DIR}
753
+ working_dir: ${PROJECT_DIR}
728
754
  environment:
729
755
  $(_environment_yaml " ")
730
756
  stdin_open: true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aibox-cli",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Run AI coding agents in isolated Docker containers",
5
5
  "author": "repalash <palash@shaders.app>",
6
6
  "license": "MIT",