aibox-cli 0.2.0 → 0.4.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 +27 -16
  2. package/bin/aibox +58 -8
  3. package/package.json +4 -1
package/README.md CHANGED
@@ -19,11 +19,8 @@ On macOS, if Docker isn't installed, aibox will offer to install [Colima](https:
19
19
  ## Usage
20
20
 
21
21
  ```bash
22
- # first time (once)
23
- aibox build
24
-
25
22
  # in any project directory
26
- aibox up # start container
23
+ aibox up # start container (auto-builds image on first run)
27
24
  aibox claude --yolo # no prompts, full sudo, no firewall
28
25
  aibox claude --safe # keep prompts, restricted sudo, firewall on
29
26
  aibox claude # asks you each time
@@ -71,6 +68,17 @@ aibox down --all # stop all containers for this project
71
68
  aibox nuke # remove ALL aibox containers
72
69
  ```
73
70
 
71
+ ### From a Git Repo
72
+
73
+ Start directly from a repo URL — aibox clones it and runs:
74
+
75
+ ```bash
76
+ aibox --repo https://github.com/user/project.git claude --yolo
77
+ aibox --repo git@github.com:user/project.git --branch dev claude
78
+ ```
79
+
80
+ Repos are cloned to `~/.config/aibox/repos/` with `--recursive` (submodules included). On subsequent runs, the existing clone is reused.
81
+
74
82
  ### Custom Image
75
83
 
76
84
  ```bash
@@ -88,7 +96,7 @@ aibox generates a `compose.dev.yaml` and configures your IDE on `aibox init` (or
88
96
  2. Run `aibox init` in your project
89
97
  3. Set the plugin's startup command to:
90
98
  ```
91
- /usr/local/bin/aibox claude --yolo
99
+ npx aibox claude --yolo
92
100
  ```
93
101
 
94
102
  The Node.js interpreter is also configured to use the container, so running/debugging from the IDE uses the same sandboxed environment.
@@ -147,17 +155,20 @@ SHARED_MODULES=false
147
155
 
148
156
  ## All Flags
149
157
 
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 |
158
+ | Short | Long | Description |
159
+ |-------|------|-------------|
160
+ | `-n` | `--name NAME` | Named instance (multiple containers per project) |
161
+ | `-d` | `--dir PATH` | Run in a different project directory |
162
+ | `-r` | `--repo URL` | Clone a git repo and run in it |
163
+ | `-b` | `--branch NAME` | Branch to checkout (with `--repo`) |
164
+ | `-i` | `--image NAME` | Override base Docker image |
165
+ | `-c` | `--copy` | Copy repo into Docker volume (full isolation) |
166
+ | `-w` | `--worktree` | Use git worktree (lightweight isolation) |
167
+ | `-y` | `--yolo` | Skip prompts, full sudo, no firewall |
168
+ | `-s` | `--safe` | Keep prompts, restricted sudo, firewall on |
169
+ | | `--shared-modules` | Share node_modules between host and container |
170
+ | | `--all` | With `down`: stop all project containers |
171
+ | | `--clean` | With `down`: also remove copy volumes / worktrees |
161
172
 
162
173
  ## License
163
174
 
package/bin/aibox CHANGED
@@ -23,6 +23,8 @@
23
23
  # -n, --name NAME Run a named instance (e.g. -n refactor)
24
24
  # Allows multiple containers per project
25
25
  # -d, --dir PATH Run in a different project directory
26
+ # -r, --repo URL Clone a git repo and run in it
27
+ # -b, --branch NAME Branch to checkout (with --repo)
26
28
  # -i, --image NAME Override base Docker image (default: aibox:latest)
27
29
  # -c, --copy Copy project into container (full isolation, no host sync)
28
30
  # -w, --worktree Use git worktree (lightweight isolation, stays on host)
@@ -55,7 +57,7 @@ set -euo pipefail
55
57
 
56
58
  # ── Script identity ──────────────────────────────────────────────
57
59
  SCRIPT_NAME="$(basename "$0")"
58
- AIBOX_VERSION="5"
60
+ AIBOX_VERSION="6"
59
61
  CONFIG_DIR="${HOME}/.config/aibox"
60
62
  DEFAULT_IMAGE="aibox:latest"
61
63
  CONTAINER_PREFIX="aibox"
@@ -185,6 +187,8 @@ IMAGE="$DEFAULT_IMAGE"
185
187
  SHARED_MODULES=false
186
188
  INSTANCE_NAME=""
187
189
  PROJECT_DIR_FLAG=""
190
+ REPO_URL=""
191
+ REPO_BRANCH=""
188
192
  DOWN_ALL=false
189
193
  DOWN_CLEAN=false
190
194
  SKIP_PERMISSIONS=false
@@ -207,6 +211,14 @@ parse_flags() {
207
211
  PROJECT_DIR_FLAG="${2:?'--dir requires a value'}"
208
212
  shift 2
209
213
  ;;
214
+ -r|--repo)
215
+ REPO_URL="${2:?'--repo requires a value'}"
216
+ shift 2
217
+ ;;
218
+ -b|--branch)
219
+ REPO_BRANCH="${2:?'--branch requires a value'}"
220
+ shift 2
221
+ ;;
210
222
  --shared-modules)
211
223
  SHARED_MODULES=true
212
224
  shift
@@ -259,6 +271,31 @@ elif [[ "$SAFE_MODE" == "true" ]]; then
259
271
  export AIBOX_MODE="safe"
260
272
  fi
261
273
 
274
+ # ── Repo clone ───────────────────────────────────────────────────
275
+ if [[ -n "$REPO_URL" ]]; then
276
+ # Derive a directory name from the repo URL (hash prevents collisions)
277
+ _repo_name=$(basename "$REPO_URL" .git)
278
+ _repo_hash=$(printf '%s' "$REPO_URL" | shasum | cut -c1-6)
279
+ _repo_dir="${CONFIG_DIR}/repos/${_repo_name}-${_repo_hash}"
280
+
281
+ if [[ -d "$_repo_dir/.git" ]]; then
282
+ echo "Repo already cloned (${_repo_dir}). Reusing."
283
+ # Fetch latest and checkout branch if specified
284
+ if [[ -n "$REPO_BRANCH" ]]; then
285
+ git -C "$_repo_dir" fetch --all --quiet 2>/dev/null || true
286
+ git -C "$_repo_dir" checkout "$REPO_BRANCH" 2>/dev/null || true
287
+ fi
288
+ else
289
+ echo "Cloning ${REPO_URL}..."
290
+ mkdir -p "${CONFIG_DIR}/repos"
291
+ _clone_args=(--recursive)
292
+ [[ -n "$REPO_BRANCH" ]] && _clone_args+=(--branch "$REPO_BRANCH")
293
+ git clone "${_clone_args[@]}" "$REPO_URL" "$_repo_dir"
294
+ fi
295
+
296
+ PROJECT_DIR_FLAG="$_repo_dir"
297
+ fi
298
+
262
299
  # ── Per-project config file (.aibox) ─────────────────────────────
263
300
  if [[ -n "$PROJECT_DIR_FLAG" ]]; then
264
301
  PROJECT_DIR="$(cd "$PROJECT_DIR_FLAG" 2>/dev/null && pwd)" || {
@@ -347,7 +384,7 @@ if ! [[ "$INSTANCE_NAME" =~ ^[a-z0-9_-]+$ ]]; then
347
384
  exit 1
348
385
  fi
349
386
  CONTAINER_NAME="${BASE_CONTAINER_NAME}-${INSTANCE_NAME}"
350
- WORKSPACE_DIR="/${PROJECT_NAME}"
387
+ WORKSPACE_DIR="/workspace/${PROJECT_NAME}"
351
388
 
352
389
  # ── Isolation mode setup ─────────────────────────────────────────
353
390
  COPY_VOLUME=""
@@ -436,6 +473,16 @@ set -e
436
473
  # Fix auth volume ownership (Docker creates volumes as root)
437
474
  chown -R aibox:aibox /home/aibox/.claude 2>/dev/null || true
438
475
 
476
+ # ── IDE path symlink ─────────────────────────────────────────
477
+ # Create symlink so container paths match host paths for IDE integration.
478
+ # Claude Code reports cwd-based paths to the IDE plugin; if they don't
479
+ # match host paths, diffs break (empty left side, wrong file path).
480
+ if [[ -n "${AIBOX_HOST_DIR:-}" && -n "${AIBOX_WORKSPACE_DIR:-}" \
481
+ && "$AIBOX_HOST_DIR" != "$AIBOX_WORKSPACE_DIR" ]]; then
482
+ mkdir -p "$(dirname "$AIBOX_HOST_DIR")"
483
+ ln -sfn "$AIBOX_WORKSPACE_DIR" "$AIBOX_HOST_DIR"
484
+ fi
485
+
439
486
  # ── Mode-dependent setup ──────────────────────────────────────
440
487
  MODE="${AIBOX_MODE:-safe}"
441
488
 
@@ -535,7 +582,7 @@ _prepare_copy_volume() {
535
582
 
536
583
  # Check if volume already has content (--entrypoint bypasses su-exec drop)
537
584
  local has_content
538
- 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)
585
+ 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)
539
586
 
540
587
  if [[ -n "$has_content" ]]; then
541
588
  echo "Copy volume already populated (${COPY_VOLUME}). Reusing."
@@ -555,14 +602,15 @@ _prepare_copy_volume() {
555
602
  fi
556
603
 
557
604
  if ! cat "$bundle_file" | docker run --rm -i --entrypoint sh \
558
- -v "${COPY_VOLUME}:/${PROJECT_NAME}" \
605
+ -v "${COPY_VOLUME}:${WORKSPACE_DIR}" \
559
606
  "$IMAGE" -c "
560
607
  cat > /tmp/repo.bundle
561
- cd /${PROJECT_NAME}
608
+ mkdir -p ${WORKSPACE_DIR}
609
+ cd ${WORKSPACE_DIR}
562
610
  git clone /tmp/repo.bundle .
563
611
  rm /tmp/repo.bundle
564
612
  git checkout -b '${branch_name}' 2>/dev/null || git checkout '${branch_name}'
565
- chown -R aibox:aibox /${PROJECT_NAME}
613
+ chown -R aibox:aibox ${WORKSPACE_DIR}
566
614
  "; then
567
615
  rm -f "$bundle_file"
568
616
  docker volume rm "$COPY_VOLUME" 2>/dev/null || true
@@ -648,6 +696,8 @@ _environment_yaml() {
648
696
  echo "${indent}- CLAUDE_CONFIG_DIR=/home/aibox/.claude"
649
697
  echo "${indent}- AIBOX_MODE=\${AIBOX_MODE:-safe}"
650
698
  echo "${indent}- AIBOX_EXTRA_DOMAINS=\${AIBOX_EXTRA_DOMAINS:-}"
699
+ echo "${indent}- AIBOX_HOST_DIR=${PROJECT_DIR}"
700
+ echo "${indent}- AIBOX_WORKSPACE_DIR=${WORKSPACE_DIR}"
651
701
  }
652
702
 
653
703
  # Build -e flags for docker exec from current terminal environment
@@ -709,7 +759,7 @@ services:
709
759
  $(_labels_yaml " ")
710
760
  volumes:
711
761
  $(_volumes_yaml " " "$PROJECT_DIR")
712
- working_dir: ${WORKSPACE_DIR}
762
+ working_dir: ${PROJECT_DIR}
713
763
  environment:
714
764
  $(_environment_yaml " ")
715
765
  stdin_open: true
@@ -737,7 +787,7 @@ services:
737
787
  $(_labels_yaml " ")
738
788
  volumes:
739
789
  $(_volumes_yaml " " ".")
740
- working_dir: ${WORKSPACE_DIR}
790
+ working_dir: ${PROJECT_DIR}
741
791
  environment:
742
792
  $(_environment_yaml " ")
743
793
  stdin_open: true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aibox-cli",
3
- "version": "0.2.0",
3
+ "version": "0.4.1",
4
4
  "description": "Run AI coding agents in isolated Docker containers",
5
5
  "author": "repalash <palash@shaders.app>",
6
6
  "license": "MIT",
@@ -35,5 +35,8 @@
35
35
  ],
36
36
  "engines": {
37
37
  "node": ">=18"
38
+ },
39
+ "scripts": {
40
+ "release": "git tag v$npm_package_version && git push origin v$npm_package_version"
38
41
  }
39
42
  }