Creates setup_env_windows.ps1 PowerShell script that: - Provisions full Hyper-V VMs (not WSL2) for complete isolation - Uses Ubuntu cloud images with cloud-init for automated setup - Generates SSH keys for passwordless access - Adds VMs to hosts file for easy <name>.local access - Disables integration services by default for security Hyper-V provides stronger isolation than WSL2: - Separate kernel per VM - Complete filesystem isolation (no /mnt/c mount) - Own network stack (no firewall bypass) - No ability to launch Windows programs from Linux Also updates README with cross-platform quick start guides and security comparison between WSL2 and Hyper-V. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
117 lines
6.5 KiB
Markdown
117 lines
6.5 KiB
Markdown
# CLAUDE.md
|
|
|
|
## Project Memory
|
|
|
|
This project uses three documentation files as persistent memory. **You must keep these files up to date when making changes:**
|
|
|
|
| File | Purpose | Update When |
|
|
|------|---------|-------------|
|
|
| `CLAUDE.md` | Technical context for Claude Code sessions | Adding new patterns, conventions, or implementation details |
|
|
| `CHANGELOG.md` | Version history following Keep a Changelog format | Every commit (add entry, bump version) |
|
|
| `README.md` | User-facing documentation | Changing user-visible behavior, adding features, or modifying usage |
|
|
|
|
### Versioning Rules
|
|
|
|
- Use semantic versioning (MAJOR.MINOR.PATCH)
|
|
- Increment PATCH for bug fixes and minor updates
|
|
- Increment MINOR for new features and enhancements
|
|
- Increment MAJOR for breaking changes
|
|
- Tag every commit with its version: `git tag -a vX.Y.Z -m "Description"`
|
|
|
|
## Project Overview
|
|
|
|
This repository provides scripts for creating isolated development sandboxes for Claude Code on macOS (OrbStack) and Windows (Hyper-V). Both platforms offer full VM isolation for safely running AI coding assistants with elevated permissions.
|
|
|
|
**Supported platforms:**
|
|
- **macOS**: OrbStack VMs (ARM64 Apple Silicon)
|
|
- **Windows**: Hyper-V VMs (maximum security, stronger than WSL2)
|
|
|
|
## Repository Structure
|
|
|
|
```
|
|
setup_env.sh - macOS script (OrbStack host mode + Linux VM provisioning)
|
|
setup_env_windows.ps1 - Windows script (Hyper-V with cloud-init)
|
|
config.env.example - Example credentials file
|
|
config.env - User credentials (gitignored, created on first run)
|
|
.gitignore - Ignores config.env
|
|
README.md - User-facing documentation
|
|
CHANGELOG.md - Version history (Keep a Changelog format)
|
|
CLAUDE.md - This file (context for Claude Code sessions)
|
|
```
|
|
|
|
## How the Script Works
|
|
|
|
The script has two modes, detected via `uname -s`:
|
|
|
|
- **Darwin (macOS)**: Orchestrator mode. Checks for OrbStack, reads/creates `config.env`, creates a VM, copies itself in, runs itself inside the VM with `--non-interactive`.
|
|
- **Linux (VM)**: Provisioning mode. Installs all tools, configures PostgreSQL, sets up VNC, installs Claude Code plugins.
|
|
|
|
This means `./setup_env.sh my-vm` on macOS does everything end-to-end.
|
|
|
|
## Key Technical Details
|
|
|
|
- **Target environment**: OrbStack Ubuntu VM on macOS Apple Silicon (ARM64)
|
|
- **Version manager**: mise (manages Node.js, Erlang, Elixir)
|
|
- **Versions**: All tools use latest by default. Erlang/Elixir versions can be configured at the top of `setup_env.sh` (`ERLANG_VERSION`, `ELIXIR_VERSION`) - set to "latest" or pin to specific versions
|
|
- **PostgreSQL auth**: Peer for local socket, scram-sha-256 for all TCP connections (localhost and network)
|
|
- **Browser**: Chromium (no Chrome ARM64 Linux builds exist), symlinked to `google-chrome`
|
|
- **VNC**: TigerVNC + XFCE on display :1 (port 5901), controlled via `vnc-start`/`vnc-stop` helpers in `~/bin`
|
|
- **Shared credentials**: `config.env` stores git name/email only; VNC password is prompted each time (never stored)
|
|
|
|
## Working on This Project
|
|
|
|
### Editing setup_env.sh
|
|
|
|
- The macOS host-mode block is at the top (inside the `if [[ "$(uname -s)" == "Darwin" ]]` block)
|
|
- The Linux VM-mode block is everything after that conditional
|
|
- Version numbers are defined as variables at the top (`ERLANG_VERSION`, `ELIXIR_VERSION`)
|
|
- All installation steps must be idempotent (safe to run multiple times)
|
|
- Use `log_info`, `log_warn`, `log_error` helpers for output
|
|
- New apt packages go in the base dependencies section
|
|
- New Claude plugins go in the appropriate array (`ANTHROPIC_PLUGINS` or `SUPERPOWERS_PLUGINS`)
|
|
- Redirect verbose output to `$LOG_FILE`, show only meaningful progress to the user
|
|
- The `LOG_FILE` variable is only set in VM mode (not available in macOS host mode)
|
|
- Each optional component is wrapped in `prompt_install "Name" "Description"` — this handles both interactive prompts and `--yes`/`--non-interactive` auto-accept
|
|
- Track dependency flags (`INSTALLED_NODE`, `INSTALLED_CHROMIUM`) to skip dependent components gracefully
|
|
|
|
### Script Conventions
|
|
|
|
- `set -euo pipefail` is enforced - handle potential failures with `|| true` or explicit checks
|
|
- Use `command_exists` to check for already-installed tools
|
|
- Use `apt-get` (not `apt`) for scripting reliability
|
|
- Quote all variable expansions
|
|
- Use `find` for PostgreSQL config paths (version-agnostic)
|
|
- The `--non-interactive` flag is for VM mode (implies `--yes`); macOS mode always uses config.env
|
|
- `--yes`/`-y` accepts all components without prompting but still allows interactive credential entry
|
|
- `MISE_GLOBAL_CONFIG_FILE` and `MISE_CONFIG_DIR` are set to prevent OrbStack host-mount config pollution
|
|
|
|
### Security Patterns
|
|
|
|
- **Input validation**: Use `validate_vm_name()`, `validate_vnc_password()`, `validate_safe_input()` for all user inputs
|
|
- **Safe config loading**: Use `load_config_safely()` which parses key=value pairs without shell execution (never `source`)
|
|
- **Credential passing**: Base64-encode values before passing to VM via `orb run` to prevent shell injection
|
|
- **Download helper**: Use `download_verified_binary()` for binary downloads (supports optional checksum verification)
|
|
- **Temp files**: Always use `mktemp` with restrictive permissions (`chmod 600`/`700`)
|
|
- **Symlinks**: Check with `[ ! -e path ]` (not `[ ! -L path ]`) to avoid overwriting existing files
|
|
- **Architecture detection**: Use `detect_architecture()` for portable binary downloads
|
|
|
|
### Testing
|
|
|
|
There are no automated tests. To test changes:
|
|
1. Remove an existing test VM: `orb delete test-sandbox`
|
|
2. Run: `./setup_env.sh test-sandbox`
|
|
3. Verify provisioning completes
|
|
4. Run again to verify idempotency: `ssh test-sandbox@orb -- bash /tmp/setup_env.sh --non-interactive` (will need env vars)
|
|
5. Test VNC: `ssh test-sandbox@orb -- vnc-start`, then `open vnc://test-sandbox.orb.local:5901`
|
|
6. Clean up: `orb delete test-sandbox`
|
|
|
|
### Security Considerations
|
|
|
|
- `config.env` is chmod 600 and gitignored (stores git name/email only, never VNC password)
|
|
- PostgreSQL uses scram-sha-256 for all TCP connections (peer auth for local socket)
|
|
- The script refuses to run as root inside the VM
|
|
- VNC password is required (min 6 chars), validated to block shell metacharacters, never stored
|
|
- VNC binds to all interfaces (`-localhost no`) to allow connections from the macOS host — this is intentional for the OrbStack use case and documented in the vnc-start script
|
|
- All user inputs are validated before use to prevent command injection
|
|
- External scripts (mise, ollama) are downloaded to temp files and validated before execution
|
|
- Host filesystem access is disabled inside the VM for isolation
|