@alanbem/dclaude 0.0.13 → 0.0.14

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 +36 -3
  2. package/dclaude +389 -22
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -132,12 +132,15 @@ dclaude gh # Interactive GitHub login
132
132
  dclaude exec gh pr list # Use gh commands
133
133
  ```
134
134
 
135
- ### SSH Server for IDEs
135
+ ### SSH Key and Server Management
136
136
 
137
- Connect JetBrains Gateway, VS Code Remote, or any SSH client:
137
+ Load SSH keys and start SSH server for JetBrains Gateway, VS Code Remote, or any SSH client:
138
138
 
139
139
  ```bash
140
- dclaude ssh # Start SSH server, shows port
140
+ dclaude ssh # Load keys + start SSH server
141
+ dclaude ssh keys # Load SSH keys into agent
142
+ dclaude ssh server # Start SSH server, shows port
143
+ dclaude ssh server --stop # Stop SSH server
141
144
  # Connect: ssh claude@localhost -p <port>
142
145
  # Password: claude
143
146
  ```
@@ -151,6 +154,32 @@ dclaude chrome # Launch Chrome with DevTools
151
154
  dclaude # Claude can now interact with the browser
152
155
  ```
153
156
 
157
+ ### AWS CLI Integration
158
+
159
+ AWS CLI v2 is pre-installed in the container. Configure how AWS credentials are provided:
160
+
161
+ ```bash
162
+ # Auto (default): mounts ~/.aws from host if it exists, otherwise no config
163
+ dclaude
164
+
165
+ # Mount host's ~/.aws directory (read-write, shared with host)
166
+ DCLAUDE_AWS_CLI=mount dclaude
167
+
168
+ # Use isolated Docker volume (persists across container recreations)
169
+ DCLAUDE_AWS_CLI=volume dclaude
170
+
171
+ # No AWS config mounting
172
+ DCLAUDE_AWS_CLI=none dclaude
173
+ ```
174
+
175
+ **Volume mode** provides isolated AWS config per namespace:
176
+
177
+ ```bash
178
+ dclaude aws configure # Copy ~/.aws/config (profiles, regions) into container
179
+ dclaude aws login # Run 'aws login' in container
180
+ dclaude aws login --profile staging # Login with specific profile
181
+ ```
182
+
154
183
  ### iTerm2 Shell Integration
155
184
 
156
185
  If you use iTerm2 on macOS, dclaude automatically enables [iTerm2 Shell Integration](https://iterm2.com/documentation-shell-integration.html):
@@ -173,6 +202,7 @@ dclaude automatically tells Claude about its container environment so it can giv
173
202
  - **Network mode** - Whether `localhost` works or needs `host.docker.internal`
174
203
  - **Docker access** - Whether Docker commands are available
175
204
  - **SSH auth method** - How git authentication is configured
205
+ - **AWS CLI** - Whether and how AWS credentials are configured
176
206
  - **Path mirroring** - That file paths match the host
177
207
 
178
208
  This helps Claude understand its environment without you explaining it. Disable if needed:
@@ -195,6 +225,7 @@ DCLAUDE_SYSTEM_CONTEXT=false dclaude
195
225
  | `DCLAUDE_QUIET` | `false` | Suppress info messages |
196
226
  | `DCLAUDE_NO_UPDATE` | `false` | Skip image update check |
197
227
  | `DCLAUDE_SYSTEM_CONTEXT` | `true` | Inform Claude about container environment |
228
+ | `DCLAUDE_AWS_CLI` | `auto` | AWS config: `auto`, `mount`, `volume`, `none` |
198
229
  | `DCLAUDE_ITERM2` | `true` | Enable iTerm2 shell integration (only affects iTerm2) |
199
230
 
200
231
  ## Configuration File
@@ -220,6 +251,7 @@ dclaude walks up the directory tree to find `.dclaude` files. Any dclaude sessio
220
251
  | `MOUNT_ROOT` | Mount directory (relative to config file, or absolute path) |
221
252
  | `DEBUG` | Enable debug output (`true`, `false`) |
222
253
  | `CHROME_PORT` | Chrome DevTools port |
254
+ | `AWS_CLI` | AWS config mode (`mount`, `volume`, `none`) |
223
255
 
224
256
  **Precedence:** Environment variables override `.dclaude` file settings.
225
257
 
@@ -327,6 +359,7 @@ The container includes:
327
359
  - **Docker CLI** and **Docker Compose**
328
360
  - **Git**, **GitHub CLI** (`gh`), common dev tools
329
361
  - **tmux** for session management
362
+ - **AWS CLI v2** for cloud operations
330
363
  - **SSH server** for IDE integration
331
364
 
332
365
  ## Troubleshooting
package/dclaude CHANGED
@@ -135,6 +135,9 @@ load_config_file() {
135
135
  fi
136
136
  fi
137
137
  ;;
138
+ AWS_CLI)
139
+ [[ -z "${DCLAUDE_AWS_CLI:-}" ]] && DCLAUDE_AWS_CLI="$value"
140
+ ;;
138
141
  esac
139
142
  fi
140
143
  done < "$config_file"
@@ -151,6 +154,7 @@ readonly DEBUG="${DCLAUDE_DEBUG:-false}"
151
154
  readonly GIT_AUTH_MODE="${DCLAUDE_GIT_AUTH:-auto}" # auto, agent-forwarding, key-mount, none
152
155
  readonly NAMESPACE="${DCLAUDE_NAMESPACE:-}"
153
156
  CHROME_PORT="${DCLAUDE_CHROME_PORT:-9222}"
157
+ readonly AWS_CLI_MODE="${DCLAUDE_AWS_CLI:-auto}" # auto, mount, volume, none
154
158
 
155
159
  # Show config file if loaded (always at info level, details at debug)
156
160
  if [[ -n "$DCLAUDE_CONFIG_FILE" ]]; then
@@ -161,6 +165,7 @@ if [[ -n "$DCLAUDE_CONFIG_FILE" ]]; then
161
165
  [[ -n "${DCLAUDE_GIT_AUTH:-}" ]] && debug " GIT_AUTH=$DCLAUDE_GIT_AUTH"
162
166
  [[ -n "${DCLAUDE_CHROME_PORT:-}" ]] && debug " CHROME_PORT=$DCLAUDE_CHROME_PORT"
163
167
  [[ -n "${DCLAUDE_MOUNT_ROOT:-}" ]] && debug " MOUNT_ROOT=$DCLAUDE_MOUNT_ROOT"
168
+ [[ -n "${DCLAUDE_AWS_CLI:-}" ]] && debug " AWS_CLI=$DCLAUDE_AWS_CLI"
164
169
  fi
165
170
  fi
166
171
 
@@ -510,6 +515,36 @@ get_volume_name() {
510
515
  fi
511
516
  }
512
517
 
518
+ # Get AWS volume name (includes namespace if set)
519
+ get_aws_volume_name() {
520
+ if [[ -n "$NAMESPACE" ]]; then
521
+ echo "${VOLUME_PREFIX}-${NAMESPACE}-aws"
522
+ else
523
+ echo "${VOLUME_PREFIX}-aws"
524
+ fi
525
+ }
526
+
527
+ # Resolve AWS CLI mode from configured value
528
+ # auto → mount (if ~/.aws exists) or none
529
+ resolve_aws_cli_mode() {
530
+ case "$AWS_CLI_MODE" in
531
+ mount|volume|none)
532
+ echo "$AWS_CLI_MODE"
533
+ ;;
534
+ auto)
535
+ if [[ -d "${HOME}/.aws" ]]; then
536
+ echo "mount"
537
+ else
538
+ echo "none"
539
+ fi
540
+ ;;
541
+ *)
542
+ warning "Unknown AWS_CLI mode: $AWS_CLI_MODE (using none)"
543
+ echo "none"
544
+ ;;
545
+ esac
546
+ }
547
+
513
548
  # Create Docker volumes if they don't exist
514
549
  create_volumes() {
515
550
  # Create essential volume for Claude CLI persistence
@@ -526,6 +561,24 @@ create_volumes() {
526
561
  else
527
562
  debug "Volume exists: $volume"
528
563
  fi
564
+
565
+ # Create AWS volume if volume mode is active
566
+ local aws_mode
567
+ aws_mode=$(resolve_aws_cli_mode)
568
+ if [[ "$aws_mode" == "volume" ]]; then
569
+ local aws_volume
570
+ aws_volume=$(get_aws_volume_name)
571
+ if ! docker volume inspect "$aws_volume" &> /dev/null; then
572
+ info "Creating AWS volume: $aws_volume"
573
+ if ! docker volume create "$aws_volume" > /dev/null; then
574
+ error "Failed to create volume: $aws_volume"
575
+ exit 1
576
+ fi
577
+ debug "Volume created successfully: $aws_volume"
578
+ else
579
+ debug "Volume exists: $aws_volume"
580
+ fi
581
+ fi
529
582
  }
530
583
 
531
584
  # Pull or update the Docker image
@@ -660,6 +713,7 @@ generate_system_context() {
660
713
  local has_docker="${3:-false}"
661
714
  local platform="${4:-unknown}"
662
715
  local docker_socket="${5:-}"
716
+ local aws_cli_mode="${6:-none}"
663
717
 
664
718
  cat <<'EOF'
665
719
 
@@ -806,8 +860,36 @@ EOF
806
860
  ## Development Tools Available
807
861
  - **Languages**: Node.js 20+, Python 3
808
862
  - **Package Managers**: npm, pip, Homebrew/Linuxbrew
809
- - **Tools**: git, gh (GitHub CLI), docker, docker-compose, curl, tmux, nano
863
+ - **Tools**: git, gh (GitHub CLI), docker, docker-compose, aws (AWS CLI v2), curl, tmux, nano
810
864
  - **Shell**: bash (your commands execute in bash shell)
865
+ EOF
866
+
867
+ # AWS CLI context
868
+ case "$aws_cli_mode" in
869
+ mount)
870
+ cat <<'EOF'
871
+ - **AWS CLI**: Configured — credentials mounted from host's `~/.aws` directory
872
+ - All host AWS profiles, SSO config, and credentials are available
873
+ - Changes to AWS config (e.g., `aws sso login`) are shared with host
874
+ EOF
875
+ ;;
876
+ volume)
877
+ cat <<'EOF'
878
+ - **AWS CLI**: Configured — credentials stored in persistent Docker volume
879
+ - AWS config is isolated from host and persists across container recreations
880
+ - Run `aws configure` or `aws configure sso` to set up credentials
881
+ EOF
882
+ ;;
883
+ *)
884
+ cat <<'EOF'
885
+ - **AWS CLI**: Installed but no credentials configured
886
+ - User can set `DCLAUDE_AWS_CLI=mount` when launching dclaude to use host's `~/.aws` config
887
+ - User can set `DCLAUDE_AWS_CLI=volume` when launching dclaude for isolated persistent config
888
+ EOF
889
+ ;;
890
+ esac
891
+
892
+ cat <<'EOF'
811
893
 
812
894
  ## Git Configuration Requirements
813
895
  **IMPORTANT**: Before performing any git operations (commit, push, etc.), you MUST:
@@ -1573,14 +1655,27 @@ main() {
1573
1655
  debug "Git auth: $resolved_git_auth (user-specified)"
1574
1656
  fi
1575
1657
 
1658
+ # Warn if agent-forwarding is active but no keys are loaded
1659
+ if [[ "$resolved_git_auth" == "agent-forwarding" ]]; then
1660
+ local ssh_add_rc=0
1661
+ ssh-add -l >/dev/null 2>&1 || ssh_add_rc=$?
1662
+ if [[ $ssh_add_rc -eq 1 ]]; then
1663
+ warning "SSH agent has no keys loaded — SSH won't work inside container."
1664
+ warning "Run 'dclaude ssh keys' to load your keys."
1665
+ fi
1666
+ fi
1667
+
1576
1668
  # Generate system context for Claude (if enabled) - must be done early for all code paths
1577
1669
  local claude_args=()
1578
1670
  if [[ "$ENABLE_SYSTEM_CONTEXT" == "true" ]]; then
1579
1671
  local has_docker="false"
1580
1672
  [[ -n "$DOCKER_SOCKET" ]] && [[ -S "$DOCKER_SOCKET" ]] && has_docker="true"
1581
1673
 
1674
+ local resolved_aws_cli_mode
1675
+ resolved_aws_cli_mode=$(resolve_aws_cli_mode)
1676
+
1582
1677
  local system_context
1583
- system_context=$(generate_system_context "$network_mode" "$resolved_git_auth" "$has_docker" "$platform" "$DOCKER_SOCKET")
1678
+ system_context=$(generate_system_context "$network_mode" "$resolved_git_auth" "$has_docker" "$platform" "$DOCKER_SOCKET" "$resolved_aws_cli_mode")
1584
1679
 
1585
1680
  claude_args+=("--append-system-prompt" "$system_context")
1586
1681
  debug "System context enabled (${#system_context} chars, has_docker=$has_docker, git_auth=$resolved_git_auth, platform=$platform)"
@@ -1793,6 +1888,32 @@ main() {
1793
1888
  [[ -n "$ssh_arg" ]] && DOCKER_ARGS+=("$ssh_arg")
1794
1889
  done < <(handle_git_auth)
1795
1890
 
1891
+ # Handle AWS CLI configuration mounting
1892
+ local resolved_aws_mode
1893
+ resolved_aws_mode=$(resolve_aws_cli_mode)
1894
+ # Pass mode to entrypoint so it knows whether to chown .aws (volume only)
1895
+ DOCKER_ARGS+=(-e "DCLAUDE_AWS_CLI_MODE=${resolved_aws_mode}")
1896
+ case "$resolved_aws_mode" in
1897
+ mount)
1898
+ if [[ -d "${HOME}/.aws" ]]; then
1899
+ DOCKER_ARGS+=(-v "${HOME}/.aws:/home/claude/.aws")
1900
+ info "AWS CLI: mounting host ~/.aws"
1901
+ debug "AWS config mounted from host: ${HOME}/.aws"
1902
+ else
1903
+ warning "AWS_CLI=mount but ~/.aws not found, skipping"
1904
+ fi
1905
+ ;;
1906
+ volume)
1907
+ local aws_volume
1908
+ aws_volume=$(get_aws_volume_name)
1909
+ DOCKER_ARGS+=(-v "${aws_volume}:/home/claude/.aws")
1910
+ debug "AWS config using volume: $aws_volume"
1911
+ ;;
1912
+ none)
1913
+ debug "AWS CLI config mounting disabled"
1914
+ ;;
1915
+ esac
1916
+
1796
1917
  # Add any additional environment variables
1797
1918
  if [[ -n "${CLAUDE_MODEL:-}" ]]; then
1798
1919
  DOCKER_ARGS+=(-e "CLAUDE_MODEL=${CLAUDE_MODEL}")
@@ -2269,8 +2390,117 @@ cmd_stop() {
2269
2390
  exit 0
2270
2391
  }
2271
2392
 
2272
- # Subcommand: SSH server for remote access (JetBrains Gateway, debugging, etc.)
2393
+ # Subcommand: SSH dispatches to 'keys', 'server', or both
2273
2394
  cmd_ssh() {
2395
+ local rc=0
2396
+ case "${1:-}" in
2397
+ keys)
2398
+ shift
2399
+ cmd_ssh_keys "$@" || rc=$?
2400
+ ;;
2401
+ server)
2402
+ shift
2403
+ cmd_ssh_server "$@" || rc=$?
2404
+ ;;
2405
+ --help|-h)
2406
+ cat << 'SSH_HELP'
2407
+ dclaude ssh - SSH Key and Server Management
2408
+
2409
+ Usage:
2410
+ dclaude ssh Load SSH keys into agent and start SSH server
2411
+ dclaude ssh keys Load SSH keys into agent
2412
+ dclaude ssh server Start SSH server and show connection info
2413
+ dclaude ssh server --stop Stop SSH server
2414
+
2415
+ SSH_HELP
2416
+ exit 0
2417
+ ;;
2418
+ "")
2419
+ # Bare 'dclaude ssh': load keys (non-fatal), then start server
2420
+ cmd_ssh_keys "$@" || true
2421
+ echo ""
2422
+ cmd_ssh_server "$@" || rc=$?
2423
+ ;;
2424
+ *)
2425
+ error "Unknown subcommand: $1"
2426
+ info "Usage: dclaude ssh [keys | server]"
2427
+ exit 1
2428
+ ;;
2429
+ esac
2430
+ exit "$rc"
2431
+ }
2432
+
2433
+ # Subcommand: SSH key loading
2434
+ cmd_ssh_keys() {
2435
+ # Parse flags
2436
+ while [[ $# -gt 0 ]]; do
2437
+ case "$1" in
2438
+ --help|-h)
2439
+ cat << 'SSH_KEYS_HELP'
2440
+ dclaude ssh keys - Load SSH Keys into Agent
2441
+
2442
+ Usage:
2443
+ dclaude ssh keys Detect and load SSH keys from ~/.ssh/
2444
+
2445
+ Detects private keys (id_rsa, id_ed25519, etc.) in ~/.ssh/ and loads
2446
+ them into the SSH agent via ssh-add. May prompt for passphrases.
2447
+
2448
+ SSH_KEYS_HELP
2449
+ return 0
2450
+ ;;
2451
+ *)
2452
+ error "Unknown option: $1"
2453
+ info "Usage: dclaude ssh keys"
2454
+ return 1
2455
+ ;;
2456
+ esac
2457
+ done
2458
+
2459
+ local ssh_dir="${HOME}/.ssh"
2460
+ if [[ ! -d "$ssh_dir" ]]; then
2461
+ error "No ~/.ssh directory found"
2462
+ return 1
2463
+ fi
2464
+
2465
+ # Detect private key files
2466
+ local keys=()
2467
+ for key_file in "$ssh_dir"/id_*; do
2468
+ [[ -f "$key_file" ]] || continue
2469
+ # Skip public keys and certificates
2470
+ [[ "$key_file" == *.pub ]] && continue
2471
+ [[ "$key_file" == *-cert.pub ]] && continue
2472
+ keys+=("$key_file")
2473
+ done
2474
+
2475
+ if [[ ${#keys[@]} -eq 0 ]]; then
2476
+ warning "No SSH keys found in ~/.ssh/"
2477
+ info "Generate a key with: ssh-keygen -t ed25519"
2478
+ return 1
2479
+ fi
2480
+
2481
+ info "Loading SSH keys..."
2482
+ local loaded=0
2483
+ for key_file in "${keys[@]}"; do
2484
+ local display_path="~/.ssh/$(basename "$key_file")"
2485
+ if ssh-add "$key_file" 2>/dev/null; then
2486
+ success " $display_path"
2487
+ loaded=$((loaded + 1))
2488
+ else
2489
+ warning " $display_path (failed — wrong passphrase or unsupported key)"
2490
+ fi
2491
+ done
2492
+
2493
+ echo ""
2494
+ if [[ $loaded -gt 0 ]]; then
2495
+ success "$loaded key(s) loaded into SSH agent."
2496
+ else
2497
+ error "No keys were loaded"
2498
+ return 1
2499
+ fi
2500
+ }
2501
+
2502
+ # Subcommand: SSH server for remote access (JetBrains Gateway, debugging, etc.)
2503
+ cmd_ssh_server() {
2274
2504
  local action=""
2275
2505
 
2276
2506
  # Parse flags
@@ -2281,12 +2511,12 @@ cmd_ssh() {
2281
2511
  shift
2282
2512
  ;;
2283
2513
  --help|-h)
2284
- cat << 'SSH_HELP'
2285
- dclaude ssh - SSH Server for Remote Access
2514
+ cat << 'SSH_SERVER_HELP'
2515
+ dclaude ssh server - SSH Server for Remote Access
2286
2516
 
2287
2517
  Usage:
2288
- dclaude ssh Start SSH server and show connection info
2289
- dclaude ssh --stop Stop SSH server
2518
+ dclaude ssh server Start SSH server and show connection info
2519
+ dclaude ssh server --stop Stop SSH server
2290
2520
 
2291
2521
  Connection:
2292
2522
  ssh claude@localhost -p <port>
@@ -2301,20 +2531,20 @@ Use Cases:
2301
2531
 
2302
2532
  JetBrains Gateway Setup:
2303
2533
  1. Start container: dclaude
2304
- 2. Start SSH: dclaude ssh
2534
+ 2. Start SSH: dclaude ssh server
2305
2535
  3. Open JetBrains Gateway
2306
2536
  4. New Connection → SSH → localhost:<port shown above>
2307
2537
  5. Username: claude, Password: claude
2308
2538
  6. Gateway will download and install IDE backend automatically
2309
2539
  7. Select your project directory
2310
2540
 
2311
- SSH_HELP
2312
- exit 0
2541
+ SSH_SERVER_HELP
2542
+ return 0
2313
2543
  ;;
2314
2544
  *)
2315
2545
  error "Unknown option: $1"
2316
- info "Usage: dclaude ssh [--stop]"
2317
- exit 1
2546
+ info "Usage: dclaude ssh server [--stop]"
2547
+ return 1
2318
2548
  ;;
2319
2549
  esac
2320
2550
  done
@@ -2325,7 +2555,7 @@ SSH_HELP
2325
2555
  if ! docker ps -a --format '{{.Names}}' | grep -q "^${container_name}$"; then
2326
2556
  error "No container found for this directory"
2327
2557
  info "Run 'dclaude' first to create a persistent container"
2328
- exit 1
2558
+ return 1
2329
2559
  fi
2330
2560
 
2331
2561
  local container_status=$(docker inspect --format='{{.State.Status}}' "$container_name" 2>/dev/null)
@@ -2337,7 +2567,7 @@ SSH_HELP
2337
2567
  sleep 1
2338
2568
  else
2339
2569
  error "Container $container_name is in unexpected state: $container_status"
2340
- exit 1
2570
+ return 1
2341
2571
  fi
2342
2572
  fi
2343
2573
 
@@ -2353,9 +2583,9 @@ SSH_HELP
2353
2583
  echo ""
2354
2584
  echo " dclaude rm -f"
2355
2585
  echo " dclaude"
2356
- echo " dclaude ssh"
2586
+ echo " dclaude ssh server"
2357
2587
  echo ""
2358
- exit 1
2588
+ return 1
2359
2589
  fi
2360
2590
 
2361
2591
  case "$action" in
@@ -2397,8 +2627,6 @@ SSH_HELP
2397
2627
  echo ""
2398
2628
  ;;
2399
2629
  esac
2400
-
2401
- exit 0
2402
2630
  }
2403
2631
 
2404
2632
  # Subcommand: remove container for current directory
@@ -2477,6 +2705,133 @@ cmd_rm() {
2477
2705
  }
2478
2706
 
2479
2707
  # Subcommand: configure git identity
2708
+ cmd_aws_configure() {
2709
+ local container_name="$1"
2710
+
2711
+ # This subcommand only makes sense for volume mode
2712
+ local resolved_mode
2713
+ resolved_mode=$(resolve_aws_cli_mode)
2714
+ if [[ "$resolved_mode" != "volume" ]]; then
2715
+ error "dclaude aws configure is only for AWS_CLI=volume mode"
2716
+ if [[ "$resolved_mode" == "mount" ]]; then
2717
+ info "Current mode is 'mount' — host's ~/.aws is already available in the container"
2718
+ else
2719
+ info "Set DCLAUDE_AWS_CLI=volume to use persistent AWS volume"
2720
+ fi
2721
+ exit 1
2722
+ fi
2723
+
2724
+ echo ""
2725
+ echo "AWS CLI Configuration"
2726
+ echo "─────────────────────"
2727
+
2728
+ # Check existing config in container
2729
+ local existing_config
2730
+ existing_config=$(docker exec -u claude "$container_name" cat /home/claude/.aws/config 2>/dev/null || echo "")
2731
+
2732
+ if [[ -n "$existing_config" ]]; then
2733
+ echo "Current config in container:"
2734
+ echo "$existing_config" | sed 's/^/ /'
2735
+ echo ""
2736
+ read -p "Overwrite with host config? [y/N]: " overwrite
2737
+ if [[ "$overwrite" != "y" && "$overwrite" != "Y" ]]; then
2738
+ exit 0
2739
+ fi
2740
+ fi
2741
+
2742
+ # Check host config
2743
+ if [[ ! -f "${HOME}/.aws/config" ]]; then
2744
+ error "No ~/.aws/config found on host"
2745
+ info "Run 'aws configure sso' on your host first, then re-run this command"
2746
+ exit 1
2747
+ fi
2748
+
2749
+ echo "Found on host:"
2750
+ sed 's/^/ /' "${HOME}/.aws/config"
2751
+ echo ""
2752
+ info "Only config (profiles, regions, SSO URLs) will be copied — no credentials or tokens"
2753
+ echo ""
2754
+ read -p "Copy to container? [Y/n]: " copy
2755
+ if [[ "$copy" == "n" || "$copy" == "N" ]]; then
2756
+ exit 0
2757
+ fi
2758
+
2759
+ # Copy config file into container (docker cp copies as root, fix ownership after)
2760
+ docker exec -u claude "$container_name" mkdir -p /home/claude/.aws
2761
+ docker cp "${HOME}/.aws/config" "${container_name}:/home/claude/.aws/config"
2762
+ docker exec "$container_name" chown claude:claude /home/claude/.aws /home/claude/.aws/config
2763
+ docker exec "$container_name" chmod 600 /home/claude/.aws/config
2764
+
2765
+ echo ""
2766
+ success "AWS config copied to container"
2767
+ info "Run 'dclaude aws login' or 'aws login' inside dclaude to authenticate"
2768
+ exit 0
2769
+ }
2770
+
2771
+ cmd_aws_login() {
2772
+ local container_name="$1"
2773
+ shift
2774
+
2775
+ local tty_flags
2776
+ tty_flags=$(detect_tty_flags)
2777
+
2778
+ info "Starting AWS login..."
2779
+ # shellcheck disable=SC2086
2780
+ exec docker exec $tty_flags -u claude "$container_name" aws login "$@"
2781
+ }
2782
+
2783
+ cmd_aws() {
2784
+ local container_name=$(get_container_name "$HOST_PATH")
2785
+
2786
+ # Check if container exists
2787
+ if ! docker ps -a --format '{{.Names}}' | grep -q "^${container_name}$"; then
2788
+ error "No container found for this directory"
2789
+ info "Run 'dclaude' first to create a container"
2790
+ exit 1
2791
+ fi
2792
+
2793
+ # Check if container is running
2794
+ local container_status=$(docker inspect --format='{{.State.Status}}' "$container_name" 2>/dev/null)
2795
+ if [[ "$container_status" != "running" ]]; then
2796
+ if [[ "$container_status" == "exited" ]]; then
2797
+ info "Starting container: $container_name"
2798
+ docker start "$container_name" >/dev/null
2799
+ sleep 1
2800
+ else
2801
+ error "Container $container_name is in unexpected state: $container_status"
2802
+ exit 1
2803
+ fi
2804
+ fi
2805
+
2806
+ # Dispatch subcommands
2807
+ local subcmd="${1:-}"
2808
+ case "$subcmd" in
2809
+ configure)
2810
+ shift
2811
+ cmd_aws_configure "$container_name" "$@"
2812
+ ;;
2813
+ login)
2814
+ shift
2815
+ cmd_aws_login "$container_name" "$@"
2816
+ ;;
2817
+ --help|-h|"")
2818
+ echo "Usage:"
2819
+ echo " dclaude aws configure Copy AWS config from host (volume mode)"
2820
+ echo " dclaude aws login Run AWS login in container"
2821
+ echo " dclaude aws login --profile <name> Login with specific profile"
2822
+ exit 0
2823
+ ;;
2824
+ *)
2825
+ error "Unknown subcommand: $subcmd"
2826
+ echo "Usage:"
2827
+ echo " dclaude aws configure Copy AWS config from host (volume mode)"
2828
+ echo " dclaude aws login Run AWS login in container"
2829
+ echo " dclaude aws login --profile <name> Login with specific profile"
2830
+ exit 1
2831
+ ;;
2832
+ esac
2833
+ }
2834
+
2480
2835
  cmd_git() {
2481
2836
  local container_name=$(get_container_name "$HOST_PATH")
2482
2837
 
@@ -2616,6 +2971,10 @@ if [[ $# -gt 0 ]]; then
2616
2971
  shift
2617
2972
  cmd_git "$@"
2618
2973
  ;;
2974
+ aws)
2975
+ shift
2976
+ cmd_aws "$@"
2977
+ ;;
2619
2978
  --help|-h|help)
2620
2979
  cat << 'EOF'
2621
2980
  dclaude - Dockerized Claude Code Launcher
@@ -2628,8 +2987,12 @@ Usage:
2628
2987
  dclaude update Update Claude CLI inside container
2629
2988
  dclaude stop Stop container for current directory
2630
2989
  dclaude rm [-f] Remove container for current directory
2631
- dclaude ssh Start SSH server for remote access
2990
+ dclaude ssh Load SSH keys and start SSH server
2991
+ dclaude ssh keys Load SSH keys into agent
2992
+ dclaude ssh server Start SSH server for remote access
2632
2993
  dclaude git Configure git identity (name/email)
2994
+ dclaude aws configure Copy AWS config from host to container (volume mode)
2995
+ dclaude aws login Run AWS login in container
2633
2996
  dclaude chrome [options] Launch Chrome with DevTools and MCP integration
2634
2997
  dclaude gh Authenticate GitHub CLI (runs gh auth login)
2635
2998
  dclaude exec [command] Execute command in container (default: bash)
@@ -2644,6 +3007,7 @@ Environment Variables:
2644
3007
  DCLAUDE_GIT_AUTH SSH auth for Git: auto, agent-forwarding, key-mount, none
2645
3008
  DCLAUDE_NETWORK Network mode: auto, host, bridge
2646
3009
  DCLAUDE_MOUNT_ROOT Mount parent directory (absolute or relative path)
3010
+ DCLAUDE_AWS_CLI AWS config mode: auto, mount, volume, none
2647
3011
  DCLAUDE_DOCKER_SOCKET Override Docker socket path
2648
3012
  DCLAUDE_TMUX_SESSION Custom tmux session name (default: claude-TIMESTAMP)
2649
3013
  DCLAUDE_CHROME_BIN Chrome executable path (auto-detected if not set)
@@ -2655,6 +3019,7 @@ Configuration File (.dclaude):
2655
3019
  Create a .dclaude file at project root to configure dclaude for that tree:
2656
3020
  NAMESPACE=mycompany
2657
3021
  NETWORK=host
3022
+ AWS_CLI=mount
2658
3023
  DEBUG=true
2659
3024
  MOUNT_ROOT=. # Mount config file's directory
2660
3025
  MOUNT_ROOT=.. # Mount parent of config file's directory
@@ -2693,9 +3058,11 @@ Examples:
2693
3058
  dclaude rm # Remove stopped container
2694
3059
  dclaude rm -f # Force remove running container
2695
3060
 
2696
- # SSH server for remote access (JetBrains Gateway, VS Code Remote, etc.)
2697
- dclaude ssh # Start SSH server, show connection info
2698
- dclaude ssh --stop # Stop SSH server
3061
+ # SSH key and server management
3062
+ dclaude ssh # Load keys + start SSH server
3063
+ dclaude ssh keys # Load SSH keys into agent
3064
+ dclaude ssh server # Start SSH server, show connection info
3065
+ dclaude ssh server --stop # Stop SSH server
2699
3066
 
2700
3067
  # Launch Chrome with DevTools for MCP integration
2701
3068
  dclaude chrome
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alanbem/dclaude",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "description": "Dockerized Claude Code CLI launcher with MCP support",
5
5
  "main": "dclaude",
6
6
  "bin": {