README.md: - Add skip parameters example (-SkipVNC, -SkipOllama) - Document VNC password prompt and minimum length - Update requirements to show ISO creation fallbacks CLAUDE.md: - Add Windows script editing section - Add Windows security patterns section - Add Windows testing instructions - Update VNC password minimum from 6 to 8 chars - Document checksum verification for Windows Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
147 lines
8.2 KiB
Markdown
147 lines
8.2 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)
|
|
WINDOWS_PLAN.md - Windows implementation plan and security rationale
|
|
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 (macOS/Linux)
|
|
|
|
- **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
|
|
|
|
### Editing setup_env_windows.ps1
|
|
|
|
- PowerShell script for Windows Hyper-V VM creation
|
|
- Uses Ubuntu cloud images with cloud-init for automated provisioning
|
|
- Supports ARM64 architecture detection for Windows on ARM
|
|
- Skip parameters: `-SkipVNC`, `-SkipPostgreSQL`, `-SkipOllama`, `-SkipPlaywright`
|
|
- ISO creation fallback chain: oscdimg → WSL genisoimage → IMAPI2 COM
|
|
- Log file created at `$env:TEMP\setup_env_windows_<timestamp>.log`
|
|
|
|
### Security Patterns (Windows)
|
|
|
|
- **Input validation**: Use `Test-GitName`, `Test-GitEmail`, `Test-VMPassword`, `Test-VNCPassword` for all user inputs
|
|
- **Config file security**: ACL set to owner-only before writing content (no race condition)
|
|
- **Config validation**: Loaded config.env values are re-validated to detect tampering
|
|
- **Checksum verification**: Ubuntu image verified against SHA256 checksums from Canonical
|
|
- **Cleanup on failure**: `Invoke-Cleanup` removes partial VM, disk, and ISO on errors
|
|
- **Hosts file backup**: Created before modification, removed on success, kept on failure
|
|
- **Cloud-init ISO**: Contains passwords in plaintext; user reminded to remove after first boot
|
|
|
|
### Testing
|
|
|
|
There are no automated tests. To test changes:
|
|
|
|
**macOS:**
|
|
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`
|
|
|
|
**Windows:**
|
|
1. Remove existing test VM: `Stop-VM -Name test-sandbox -Force; Remove-VM -Name test-sandbox -Force`
|
|
2. Run: `.\setup_env_windows.ps1 -VMName test-sandbox`
|
|
3. Verify provisioning completes (check `/var/log/provision.log` in VM)
|
|
4. Test SSH: `ssh -i $env:USERPROFILE\.ssh\id_ed25519_test-sandbox dev@test-sandbox.local`
|
|
5. Clean up: `Stop-VM -Name test-sandbox -Force; Remove-VM -Name test-sandbox -Force`
|
|
|
|
### Security Considerations
|
|
|
|
- `config.env` is chmod 600 / owner-only ACL and gitignored (stores git name/email only, never passwords)
|
|
- 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 8 chars), validated to block shell metacharacters, never stored
|
|
- VNC binds to all interfaces (`-localhost no`) to allow connections from the host — this is intentional and documented
|
|
- 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
|
|
- Windows: Ubuntu image downloads are verified against SHA256 checksums
|