diff --git a/README.md b/README.md
index 174069a..3e9504b 100644
--- a/README.md
+++ b/README.md
@@ -1,288 +1,102 @@
# π§π¦ squarebox
-**A curated set of modern CLI/TUI tools and AI coding assistants in a container. Batteries included.**
+**Modern CLI/TUI tools and AI coding assistants in a portable development Box.**
-*For developers who live in the terminal but need to work across
-multiple platforms and devices.*
-
-**squarebox** packages a complete terminal-based development environment
-into a single container (Docker; Podman experimental): modern CLI tools, AI coding
-assistants, language SDKs, and an opinionated set of shell aliases. Run the
-same box anywhere (desktop, VPS, or Codespace) and SSH in from your laptop,
-tablet, or phone (please don't).
-
-A playground for modern CLI/TUI tools, a Box for
-running AI agents, and a persistent terminal environment for remote development.
-One-line install, interactive first-run setup, sensible defaults.
-
-Upgrading an existing installation? Read the relevant
-[migration guide](docs/releases/) and [changelog](CHANGELOG.md).
+Run the same terminal environment on your desktop, server, or Codespace.
+One-line install, interactive setup, and persistent tools and settings.

-*(Actual setup may involve more staring at the screen.)*
-
-Prerequisites
--------------
-
-- [Docker](https://docs.docker.com/get-docker/) or [Podman](https://podman.io/getting-started/installation) (experimental β see one-line install below if you don't have either)
-- [Git](https://git-scm.com/) - on Windows, install [Git for Windows](https://gitforwindows.org/)
-
-The installer auto-detects which runtime is available. If both are installed, it
-asks which to use. Override with `SQUAREBOX_RUNTIME=docker` or
-`SQUAREBOX_RUNTIME=podman`.
-
-> **Podman (Experimental):** Docker is the primary tested runtime; Podman may
-> have rough edges around volume mounts, SSH agent forwarding, or rebuild
-> flows. The rootless adapter maps the host user to the image's `dev` account
-> and uses `--security-opt label=disable`: host SELinux labels are left
-> untouched, while SELinux container separation is disabled for this
-> development Box. Please file an issue if you hit a runtime-specific edge.
-
-
-Don't have Docker or Podman? One-line install
-
-**macOS** (via [Homebrew](https://brew.sh)):
-
- brew install --cask docker-desktop
-
-**Linux** (official convenience script - inspect it first at [get.docker.com](https://get.docker.com)):
-
- curl -fsSL https://get.docker.com | sh && sudo usermod -aG docker $USER
-
-Log out and back in (or run `newgrp docker`) so your shell picks up the new group.
-
-**Windows** (via [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), in PowerShell 7+):
-
- winget install --id Docker.DockerDesktop -e
-
-On macOS and Windows, start Docker Desktop once after install so the daemon is
-running before you continue.
-
-
Install
-------
-These commands install squarebox and drop you into the container (if possible).
-By default they **pull a prebuilt image** from GHCR β no local Docker build, no
-build toolchain β then clone the repo into `~/squarebox` for the config files
-and the `sqrbx` helper commands. On first login, a setup script runs
-automatically to configure git (pulling your name and email from the host's
-global git config if available), optionally sign in to GitHub CLI, your choice
-of AI coding assistant, and language SDKs.
-
-**Stable**
-
- curl -fsSL https://github.com/SquareWaveSystems/squarebox/releases/latest/download/install.sh | bash
-
-**Edge**
-
- curl -fsSL https://github.com/SquareWaveSystems/squarebox/releases/latest/download/install.sh | bash -s -- --edge
-
-Stable resolves the latest published GitHub Release and pulls the immutable
-image digest recorded in its `release.json`. Raw Git tags are not installable
-stable releases. An explicit `SQUAREBOX_TAG=vβ¦` resolves that published Release
-and its matching source revision. Edge builds the latest commit on `main`. To
-build a published Release from source instead of pulling, pass `--build`.
-
-If the install fails or you want to see the full build/pull and git output,
-re-run with `--verbose`.
-
-
-Advanced install options (flags & environment variables)
-
-Flags: `--build` (build from source), `--edge` (latest `main`), `--adopt`
-(one-time migration of a legacy installation), and `--verbose`.
-
-| Variable | Default | Purpose |
-|----------|---------|---------|
-| `SQUAREBOX_DIR` | `~/squarebox` | Install location (repo + workspace). Point at durable storage on hosts where `$HOME` is volatile β e.g. Unraid `/mnt/user/appdata/squarebox`. |
-| `SQUAREBOX_WORKSPACE` | `$SQUAREBOX_DIR/workspace` | Host path mounted as `/workspace`. |
-| `SQUAREBOX_TAG` | latest published stable | Published Release to install (for example `v1.2.1`). Tags use `vMAJOR.MINOR.PATCH[-prerelease]`; build metadata is not published. |
-| `SQUAREBOX_IMAGE` | value from `release.json` | Optional image-repository override for development/testing. |
-| `SQUAREBOX_BUILD` | `0` | `1` is equivalent to `--build`. |
-| `PUID` / `PGID` | invoking Linux user | Host uid/gid that should own bind-mounted files. Unprivileged Linux installs must match the invoking account. Root-run rootful runtimes, including Docker or Podman on NAS and Unraid, may override these (typically `99` / `100`); rootless Podman also requires the invoking host identity. |
-| `SQUAREBOX_RUNTIME` | auto | Force `docker` or `podman`. |
-| `SQUAREBOX_HOME_VOLUME` | `squarebox-home` | Name of the named volume backing `/home/dev`. |
-| `SQUAREBOX_EDGE` | `0` | `1` is equivalent to `--edge`. |
-| `SQUAREBOX_MOUNT_SSH` | `0` | `1` mounts your host `~/.ssh` directory, **private keys included**, read-only into the Box when no SSH agent is forwarded. Recorded for rebuilds; set `0` to turn it back off. See **SSH access** below. |
-
-**Non-interactive provisioning** β set any of these to a comma-separated list to
-pre-select a toolset and install it without prompts (handy for servers and
-scripted installs). Values use the same keys as `sqrbx-setup`:
-
-| Variable | Selects |
-|----------|---------|
-| `SQUAREBOX_AI` | AI assistants (`claude,copilot,gemini,codex,opencode,pi,omp`) |
-| `SQUAREBOX_SDKS` | language SDKs (`node,python,go,dotnet,rust`) |
-| `SQUAREBOX_EDITORS` | editors (`micro,edit,fresh,helix,nvim`; Helix launches as `hx`) |
-| `SQUAREBOX_TUIS` | TUI tools (`lazygit,gh-dash,yazi,elio`) |
-| `SQUAREBOX_MULTIPLEXERS` | multiplexers (`tmux,zellij,herdr`) |
-| `SQUAREBOX_GIT_NAME` / `SQUAREBOX_GIT_EMAIL` | git identity (when no host gitconfig) |
-
-Example:
+Requires [Docker](https://docs.docker.com/get-docker/) or
+[Podman](https://podman.io/getting-started/installation), plus
+[Git](https://git-scm.com/) ([Git for Windows](https://gitforwindows.org/)).
+The installer detects your runtime and asks which to use if both are installed.
+[Need Docker?](docs/usage.md#installing-docker)
+
+**Linux / macOS / Git Bash**
```bash
-curl -fsSL https://github.com/SquareWaveSystems/squarebox/releases/latest/download/install.sh \
- | env SQUAREBOX_AI=claude SQUAREBOX_SDKS=node,python bash
+curl -fsSL https://github.com/SquareWaveSystems/squarebox/releases/latest/download/install.sh | bash
```
-
-
-Each successful v1.1-or-newer install records its effective lifecycle settings at
-`/.squarebox/install-state` (mode 0600 on POSIX; inherited
-current-user install-directory ACL on native Windows). Rebuild and uninstall
-parse this file as data; they do not reconstruct defaults or source it as shell
-code. Release pulls record an immutable image digest; source/edge builds record
-their local image ID/reference. Existing pre-v1.1 checkouts require a one-time
-reviewed `--adopt`/`-Adopt`.
-
-**SSH access**
-
-The Box does not receive your SSH private-key files by default, because anything
-running inside it, including unattended `*-yolo` AI agents, could read them.
-
-- **SSH agent (recommended).** When `SSH_AUTH_SOCK` points at a running agent,
- the Bash/POSIX and Git Bash adapters forward the agent socket and mount only
- `~/.ssh/config` and `~/.ssh/known_hosts` read-only. Key files stay on the
- host, though Box processes can ask the agent to sign while the socket is
- available.
-- **No agent.** `~/.ssh` is not mounted, and install prints a note. To mount
- the directory read-only instead, opt in with `SQUAREBOX_MOUNT_SSH=1` (native
- PowerShell: `.\install.ps1 -MountSsh` or `$env:SQUAREBOX_MOUNT_SSH = '1'`).
- The choice is recorded in the Install identity and reused by
- `sqrbx-rebuild`; set `SQUAREBOX_MOUNT_SSH=0` (or `-MountSsh:$false`) on a
- rebuild to turn it back off.
-
**Windows (PowerShell 7+)**
-Windows users can install directly from PowerShell - no Git Bash required.
-This handles Release resolution, pull/build, Box creation, and PowerShell functions
-(`sqrbx`, `squarebox`, etc.) natively:
-
- irm https://github.com/SquareWaveSystems/squarebox/releases/latest/download/install.ps1 | iex
-
-Once installed, you can re-run or pass flags from the local copy:
-
- .\install.ps1 # re-install / update
- .\install.ps1 -Edge # latest main instead of latest release
- .\install.ps1 -Build # build the resolved source locally
- .\install.ps1 -Adopt # migrate a legacy pre-v1.1 installation
- .\install.ps1 -MountSsh # opt in to mounting %USERPROFILE%\.ssh read-only
-
-> **Note:** `irm ... | iex` does not support flags - PowerShell interprets them
-> as arguments to `Invoke-Expression`, not the script. Use the local
-> `.\install.ps1` form for `-Edge`, `-Build`, `-Adopt`, or `-MountSsh`.
-> PowerShell streams runtime and Git failures directly by default.
-
-> **Windows adapter boundary:** Keep install, rebuild, and uninstall on the
-> adapter that created the Install identity. Native PowerShell and Git Bash
-> use the same Install identity field names, but their native path and
-> shell-profile values are not interchangeable;
-> cross-adapter state consumption is rejected.
-> Native PowerShell does not forward `SSH_AUTH_SOCK` and mounts
-> `%USERPROFILE%\.ssh` read-only only when you opt in with `-MountSsh` or
-> `SQUAREBOX_MOUNT_SSH=1`. The separate Git Bash adapter supports SSH
-> agent-socket forwarding with its Bash lifecycle.
-> Use `./scripts/migrate-windows-adapter.ps1 -Target PowerShell` or
-> `-Target GitBash` from PowerShell 7 for an explicit cross-adapter migration.
-> Normal installers and uninstallers continue to reject foreign adapter state.
+```powershell
+irm https://github.com/SquareWaveSystems/squarebox/releases/latest/download/install.ps1 | iex
+```
+
+The installer pulls the latest stable Release and sets up `~/squarebox`.
+First login runs a wizard for Git identity, GitHub sign-in, and optional tools.
+Keep using the same adapter (Bash/Git Bash or PowerShell) for updates and uninstall.
+
+For edge builds, custom paths, scripted setup, or Windows flags, see the
+[usage reference](docs/usage.md#advanced-installation).
+Upgrading? Check the [migration guides](docs/releases/) and [changelog](CHANGELOG.md).
Start
-----
- squarebox # or: sqrbx
-
-These are shell functions wrapping `docker start -ai squarebox` (or
-`podman start -ai squarebox`), added automatically for Bash, Zsh, and
-PowerShell 7+.
-
-The Box suspends on exit and resumes on start, keeping its current filesystem
-between those starts. Box replacement discards that filesystem; selected
-Box-tier packages are reconciled automatically in the replacement. Your
-code lives on the host at `~/squarebox/workspace` (bind-mounted), and per-user
-state β shell history, GitHub CLI auth, claude-code data, mise toolchains β
-lives in a named Docker volume (`squarebox-home`) that survives replacement.
-Image-managed config is refreshed safely into that Managed home at startup;
-desktop source builds may instead use explicit managed bind mounts.
-
-Run as a long-lived server (Unraid / NAS / VPS)
------------------------------------------------
-
-The `curl | bash` installer is built around an interactive desktop shell. To run
-squarebox as a persistent server container you attach into on demand β on
-Unraid, a NAS, or a VPS β use the prebuilt image directly with the bundled
-`docker-compose.yml`:
-
- cp .env.example .env # set PUID/PGID, the workspace path, and a tag
- docker compose up -d
- docker compose exec -u dev squarebox bash
-
-Set `PUID`/`PGID` in `.env` to match your host so files squarebox writes to the
-workspace mount are owned correctly β on Unraid that's `99` / `100`. The `-u dev`
-on `exec` is needed because the container starts as root (to apply PUID/PGID)
-then drops to the `dev` user; `exec` bypasses that, so `-u dev` lands you where
-you want to be.
-
-Per-user state (shell history, gh auth, mise toolchains, AI-assistant state)
-lives in the `squarebox-home` named volume and survives image updates; your code
-lives on the host at the workspace path. To update, pull a newer tag and
-`docker compose up -d`. The published image is multi-arch (amd64 + arm64), so it
-also runs on ARM NAS/VPS hosts.
-
-> **Unraid note:** the host's `/root` is tmpfs and wiped on reboot, so a raw
-> `curl | bash` install there won't persist. Either use compose (above) with the
-> workspace path under `/mnt/user/appdata`, or run the installer with
-> `SQUAREBOX_DIR` and `SQUAREBOX_WORKSPACE` pointed at appdata.
+```bash
+squarebox # or: sqrbx
+```
+
+Your code lives in `~/squarebox/workspace`, mounted at `/workspace`.
+Shell history, credentials, assistant data, and SDKs live in the persistent
+`squarebox-home` volume. Both survive Box replacement. Selected system packages
+are reinstalled automatically; manually installed system packages are lost.
+
+For a persistent server or NAS, see [server deployment](docs/usage.md#server-deployment).
+For VS Code or GitHub Codespaces, see [Dev Containers and Codespaces](docs/usage.md#dev-containers-and-codespaces).
What's included
---------------
### CLI Tools
-| Name | Language | Description |
-|------|----------|-------------|
-| [bat](https://github.com/sharkdp/bat) | Rust | Cat clone with syntax highlighting |
-| [bubblewrap](https://github.com/containers/bubblewrap) | C | Unprivileged sandboxing tool (`bwrap`), used by the Codex CLI sandbox |
-| [curl](https://github.com/curl/curl) | C | URL data transfer |
-| [delta](https://github.com/dandavison/delta) | Rust | Syntax-highlighting pager for git diffs |
-| [difftastic](https://github.com/Wilfred/difftastic) | Rust | Syntax-aware structural diff tool (`difft`) |
-| [eza](https://github.com/eza-community/eza) | Rust | Modern ls replacement |
-| [fd](https://github.com/sharkdp/fd) | Rust | Fast, user-friendly find alternative |
-| [fzf](https://github.com/junegunn/fzf) | Go | Fuzzy finder |
-| [gh](https://github.com/cli/cli) | Go | GitHub CLI |
-| [glow](https://github.com/charmbracelet/glow) | Go | Terminal markdown renderer |
-| [gum](https://github.com/charmbracelet/gum) | Go | Tool for shell scripts and dotfiles |
-| [jq](https://github.com/jqlang/jq) | C | JSON processor |
-| [just](https://github.com/casey/just) | Rust | Command runner / modern make alternative |
-| [mise](https://github.com/jdx/mise) | Rust | Polyglot tool-version and SDK manager |
-| [nano](https://nano-editor.org) | C | Default text editor |
-| [ripgrep](https://github.com/BurntSushi/ripgrep) | Rust | Fast recursive grep |
-| [starship](https://github.com/starship/starship) | Rust | Cross-shell prompt |
-| [xh](https://github.com/ducaale/xh) | Rust | Friendly HTTP client |
-| [yq](https://github.com/mikefarah/yq) | Go | YAML/JSON/XML processor |
-| [zoxide](https://github.com/ajeetdsouza/zoxide) | Rust | Smarter cd command |
+| Name | Description |
+|------|-------------|
+| [bat](https://github.com/sharkdp/bat) | Cat clone with syntax highlighting |
+| [bubblewrap](https://github.com/containers/bubblewrap) | Unprivileged sandboxing tool (`bwrap`), used by the Codex CLI sandbox |
+| [curl](https://github.com/curl/curl) | URL data transfer |
+| [delta](https://github.com/dandavison/delta) | Syntax-highlighting pager for git diffs |
+| [difftastic](https://github.com/Wilfred/difftastic) | Syntax-aware structural diff tool (`difft`) |
+| [eza](https://github.com/eza-community/eza) | Modern ls replacement |
+| [fd](https://github.com/sharkdp/fd) | Fast, user-friendly find alternative |
+| [fzf](https://github.com/junegunn/fzf) | Fuzzy finder |
+| [gh](https://github.com/cli/cli) | GitHub CLI |
+| [glow](https://github.com/charmbracelet/glow) | Terminal markdown renderer |
+| [gum](https://github.com/charmbracelet/gum) | Tool for shell scripts and dotfiles |
+| [jq](https://github.com/jqlang/jq) | JSON processor |
+| [just](https://github.com/casey/just) | Command runner / modern make alternative |
+| [mise](https://github.com/jdx/mise) | Polyglot tool-version and SDK manager |
+| [nano](https://nano-editor.org) | Default text editor |
+| [ripgrep](https://github.com/BurntSushi/ripgrep) | Fast recursive grep |
+| [starship](https://github.com/starship/starship) | Cross-shell prompt |
+| [xh](https://github.com/ducaale/xh) | Friendly HTTP client |
+| [yq](https://github.com/mikefarah/yq) | YAML/JSON/XML processor |
+| [zoxide](https://github.com/ajeetdsouza/zoxide) | Smarter cd command |
What's optional
----------------
-Selected during first-run setup. Choose any combination, all, or none.
-Selections are saved under `/workspace/.squarebox` (on the host workspace bind
-mount) and reused automatically on container rebuilds. They can also be
-pre-selected non-interactively via the `SQUAREBOX_AI`/`SQUAREBOX_SDKS`/β¦ env vars
-(see *Advanced install options* above).
+Choose any combination during first-run setup. Your selections are saved and
+reused on rebuilds; change them anytime with `sqrbx-setup`.
### AI Coding Assistants
-| Name | Language | Description |
-|------|----------|-------------|
-| [Claude Code](https://github.com/anthropics/claude-code) | TypeScript | AI coding assistant |
-| [GitHub Copilot CLI](https://docs.github.com/en/copilot/how-tos/copilot-cli/cli-getting-started) | TypeScript | Supported GitHub Copilot terminal client (`copilot`) * |
-| [Google Gemini CLI](https://github.com/google-gemini/gemini-cli) | TypeScript | Google Gemini in the terminal * |
-| [OpenAI Codex CLI](https://github.com/openai/codex) | Rust | OpenAI Codex in the terminal * |
-| [opencode](https://github.com/anomalyco/opencode) | TypeScript/Bun | AI coding TUI |
-| [Pi Coding Agent](https://github.com/earendil-works/pi) | TypeScript | Minimal terminal coding harness (Earendil) * |
-| [Oh My Pi](https://github.com/can1357/oh-my-pi) | TypeScript/Rust | Batteries-included coding harness (`omp`), installed via mise |
+| Name | Description |
+|------|-------------|
+| [Claude Code](https://github.com/anthropics/claude-code) | AI coding assistant |
+| [GitHub Copilot CLI](https://docs.github.com/en/copilot/how-tos/copilot-cli/cli-getting-started) | Supported GitHub Copilot terminal client (`copilot`) * |
+| [Google Gemini CLI](https://github.com/google-gemini/gemini-cli) | Google Gemini in the terminal * |
+| [OpenAI Codex CLI](https://github.com/openai/codex) | OpenAI Codex in the terminal * |
+| [opencode](https://github.com/anomalyco/opencode) | AI coding TUI |
+| [Pi Coding Agent](https://github.com/earendil-works/pi) | Minimal terminal coding harness (Earendil) * |
+| [Oh My Pi](https://github.com/can1357/oh-my-pi) | Batteries-included coding harness (`omp`), installed via mise |
+
\* Requires Node.js (auto-installed if needed).
### Text Editors
@@ -290,391 +104,90 @@ pre-selected non-interactively via the `SQUAREBOX_AI`/`SQUAREBOX_SDKS`/β¦ env v
Nano is always available and remains the fallback default unless you choose an
installed editor instead.
-| Name | Language | Description |
-|------|----------|-------------|
-| [micro](https://github.com/micro-editor/micro) | Go | Modern, intuitive terminal editor |
-| [edit](https://github.com/microsoft/edit) | Rust | Terminal text editor (Microsoft) |
-| [fresh](https://github.com/sinelaw/fresh) | Rust | Modern terminal text editor |
-| [helix](https://github.com/helix-editor/helix) | Rust | Modal editor (Kakoune-inspired) |
-| [nvim](https://github.com/neovim/neovim) | C/Lua | Neovim |
+| Name | Description |
+|------|-------------|
+| [micro](https://github.com/micro-editor/micro) | Modern, intuitive terminal editor |
+| [edit](https://github.com/microsoft/edit) | Terminal text editor (Microsoft) |
+| [fresh](https://github.com/sinelaw/fresh) | Modern terminal text editor |
+| [helix](https://github.com/helix-editor/helix) | Modal editor (Kakoune-inspired) |
+| [nvim](https://github.com/neovim/neovim) | Neovim |
-Selecting **nvim** offers to install the [LazyVim](https://www.lazyvim.org/) starter config to `~/.config/nvim`, turning Neovim into a preconfigured IDE. Plugins sync on first launch and persist in the `squarebox-home` volume. A Nerd Font in your terminal is recommended for icons; the starter is skipped if `~/.config/nvim` already exists, so your own config is never overwritten.
+Selecting **nvim** offers a [LazyVim](https://www.lazyvim.org/) starter config.
+Existing Neovim configuration is preserved. See [editor configuration](docs/usage.md#editor-configuration).
### TUI Tools
-Installed during first-run setup. Choose any combination:
-
-| Name | Language | Description |
-|------|----------|-------------|
-| [lazygit](https://github.com/jesseduffield/lazygit) | Go | Git terminal UI |
-| [gh-dash](https://github.com/dlvhdr/gh-dash) | Go | GitHub dashboard for the terminal |
-| [yazi](https://github.com/sxyazi/yazi) | Rust | Terminal file manager |
-| [elio](https://github.com/elio-fm/elio) | Rust | Terminal file manager with rich previews, inline images, and trash support |
+| Name | Description |
+|------|-------------|
+| [lazygit](https://github.com/jesseduffield/lazygit) | Git terminal UI |
+| [gh-dash](https://github.com/dlvhdr/gh-dash) | GitHub dashboard for the terminal |
+| [yazi](https://github.com/sxyazi/yazi) | Terminal file manager |
+| [elio](https://github.com/elio-fm/elio) | Terminal file manager with rich previews, inline images, and trash support |
### Terminal Multiplexers
-Installed during first-run setup. Choose any combination, or none:
-
| Name | Description |
|------|-------------|
| [tmux](https://github.com/tmux/tmux) | Classic terminal multiplexer |
| [zellij](https://github.com/zellij-org/zellij) | Friendly terminal workspace |
| [herdr](https://herdr.dev) | Agent multiplexer β run multiple coding agents from one terminal |
-### Shell (Experimental)
+### Shells and SDKs
-By default, squarebox uses Bash. During first-run setup you can opt in to
-**Zsh**, **Fish**, or **PowerShell** instead.
+Bash is the default shell; choose Zsh, Fish, or PowerShell during setup.
+Node.js, Python, Go, .NET, and Rust are available through
+[mise](https://github.com/jdx/mise).
+See [shell configuration](docs/usage.md#shell-configuration) and
+[SDK configuration](docs/usage.md#sdk-configuration).
-**Zsh** installs:
+Everyday commands
+-----------------
-| Name | Description |
-|------|-------------|
-| [zsh](https://www.zsh.org) | Z shell (via apt) |
-| [Oh My Zsh](https://ohmyz.sh) | Community framework for managing zsh config |
-| [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions) | Fish-like history-based suggestions |
-| [zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting) | Inline command syntax highlighting |
-
-The generated `~/.zshrc` mirrors the default bashrc β same aliases, starship
-prompt, zoxide, and AI/editor/SDK sourcing β layered on top of Oh My Zsh.
-
-**Fish** installs [fish](https://fishshell.com) (via apt), which ships with
-autosuggestions and syntax highlighting built in. The generated
-`~/.config/fish/config.fish` mirrors the default bashrc in fish-native syntax;
-AI/editor/TUI/SDK selections are translated from their bash files into
-`~/.config/fish/conf.d/squarebox-selections.fish` at setup time.
-
-**PowerShell** installs PowerShell 7 (`pwsh`) from Microsoft's official
-[GitHub release](https://github.com/PowerShell/PowerShell/releases) `.deb`
-(asset SHA-256 verified against the release metadata before install). The
-generated `~/.config/powershell/profile.ps1` mirrors the default bashrc in
-PowerShell-native syntax β starship, zoxide, and mise activate, plus the
-standard aliases as functions (PowerShell `Set-Alias` cannot attach
-arguments); AI/editor/TUI selections are translated from their bash files into
-`~/.config/powershell/squarebox-selections.ps1` at setup time.
-
-> **Experimental:** the marker file `~/.squarebox-use-zsh`,
-> `~/.squarebox-use-fish`, or `~/.squarebox-use-pwsh` causes `~/.bashrc` to
-> `exec` the chosen shell on every interactive login, so the next shell start
-> picks up the new shell. Set `SQUAREBOX_NO_ZSH=1`, `SQUAREBOX_NO_FISH=1`, or
-> `SQUAREBOX_NO_PWSH=1` to force bash for a single session, or re-run
-> `sqrbx-setup shell` to switch back permanently. Tooling is primarily tested
-> against bash, so a few edge cases may need polish β please file an issue if
-> you hit one. SDK shims are wired into all four shells via
-> `mise activate {bash,zsh,fish,pwsh}`.
-
-### SDKs
-
-All SDKs are managed by [mise](https://github.com/jdx/mise) β a single
-polyglot version manager. Selections are written to `~/.config/mise/config.toml`
-and `mise activate` wires up shims and PATH automatically across bash, zsh,
-and fish.
-
-| SDK | mise tool |
-|-------|-----------|
-| Node.js | `node` |
-| Python | `python` |
-| Go | `go` |
-| .NET | `dotnet` |
-| Rust | `rust` |
-
-Getting help
-------------
-
-Run `sqrbx-help` inside the container for a one-screen overview of the
-`sqrbx-*` commands, Bash's fzf (`Ctrl+R`/`Ctrl+T`/`Alt+C`/`**`) bindings,
-and zoxide (`z`/`zi`) navigation. Zsh and Fish retain the `fzf`, `ff`, and
-`eff` commands but do not claim those Bash-specific bindings. The MOTD points
-to the help command on every shell start.
-
-Reconfiguring
--------------
-
-Re-run the first-run wizard at any time from inside the container with
-`sqrbx-setup`. With no arguments it walks every section; pass one or more
-section names to reconfigure just those: `git`, `github`, `ai`, `editors`,
-`tuis`, `multiplexers`, `sdks`, `shell`. `sqrbx-setup --list` shows your
-current selections and `sqrbx-setup --help` the usage.
-
-Aliases
--------
+Run these inside the Box:
-| Alias | Command | Description |
-|-------|---------|-------------|
-| `ls` | `eza --icons` | Modern ls with icons |
-| `ll` | `eza -la --icons` | Long listing with icons |
-| `lsa` | `ls -a` (resolves to `eza --icons -a`) | List all including hidden files |
-| `lt` | `eza --tree --level=2 --long --icons --git` | Tree view with git status |
-| `lta` | `lt -a` | Tree view including hidden files |
-| `cat` | `bat --paging=never` | Syntax-highlighted cat |
-| `ff` | `fzf --preview 'bat ...'` | Fuzzy find with preview |
-| `eff` | `$EDITOR "$(ff)"` | Fuzzy find and edit |
-| `..` | `cd ..` | Go up one directory |
-| `...` | `cd ../..` | Go up two directories |
-| `....` | `cd ../../..` | Go up three directories |
-| `c` | first selected AI tool | Launch selected AI assistant |
-| `g` | `git` | Git shorthand |
-| `gcm` | `git commit -m` | Commit with message |
-| `gcam` | `git commit -a -m` | Stage all and commit |
-| `gcad` | `git commit -a --amend` | Stage all and amend |
-| `lg` | `lazygit` | Launch lazygit (if installed) |
-| `claude-yolo` | `claude --dangerously-skip-permissions` | Claude without prompts |
-| `copilot-yolo` | `copilot --allow-all` | Copilot CLI without permission prompts |
-| `codex-yolo` | `codex --dangerously-bypass-approvals-and-sandbox` | Codex without prompts or sandboxing |
-| `gemini-yolo` | `gemini --approval-mode=yolo` | Gemini CLI without prompts |
-| `opencode-yolo` | `opencode --dangerously-skip-permissions` | OpenCode without prompts |
-| `omp-yolo` | `omp --approval-mode yolo` | Oh My Pi without prompts |
-
-The `*-yolo` aliases are generated only for selected AI tools that are
-installed. They disable that tool's normal approval prompts; `codex-yolo` also
-disables Codex's sandbox. Use them only in a workspace whose contents and
-commands you trust.
-
-### Shared Keyboard Language (Experimental)
-
-Squarebox builds on Omarchy's defaults with one portable rule: `Super` belongs
-to the OS/window manager, while `Ctrl` acts immediately in the focused app.
-Herdr uses `Ctrl+Alt` for direct letter chords because many terminals collapse
-`Ctrl+Shift+letter` into the unshifted control key. Its `F12` prefix remains
-available as a compatibility fallback.
-
-Herdr's generated default uses familiar app shortcuts:
-
-| Feature | Herdr |
-|---------|-------|
-| New / close | `Ctrl+T` / `Ctrl+W` |
-| Cycle / select tabs | `Ctrl+Tab`, `Ctrl+Shift+Tab` / `Ctrl+1-9` |
-| Focus / swap pane | `Ctrl+Arrow` / `Ctrl+Shift+Arrow` |
-| Sidebar / go to | `Ctrl+B` / `Ctrl+G` |
-| Split right / down | `Ctrl+\\` / `Ctrl+Alt+\\` |
-| Zoom / new workspace | `Ctrl+Alt+Z` / `Ctrl+Alt+N` |
-| Compatibility prefix | `F12` |
-
-These bindings intentionally take precedence over matching shell or nested-app
-shortcuts while Herdr is focused. Existing `~/.config/herdr/config.toml` files
-remain user-managed and are never replaced by setup.
-
-Tmux and Zellij retain their earlier Omarchy-inspired matching defaults:
-
-| Feature | Tmux | Zellij |
-|---------|------|--------|
-| Config path | `~/.config/tmux/tmux.conf` | `~/.config/zellij/config.kdl` |
-| Prefix | `Ctrl+Space` | `Ctrl+Space` (Tmux mode) |
-| Alternate prefix | `Ctrl+B` | `Ctrl+B` (Tmux mode) |
-| Prefix help | β | `prefix ?` |
-| Pane navigation | `Ctrl+Alt+Arrow` | `Ctrl+Alt+Arrow` |
-| Pane resizing | `Ctrl+Alt+Shift+Arrow` | `Ctrl+Alt+Shift+Arrow` |
-| Tab/window select | `Alt+1-9` | `Alt+1-9` |
-| Tab/window cycle | `Alt+Left/Right` | `Alt+Left/Right` |
-| Split horizontal | `prefix h` | `prefix h` |
-| Split vertical | `prefix v` | `prefix v` |
-| Scrollback | 50,000 lines | 50,000 lines |
-| Copy mode | Vi keys | Vi-style scroll |
-| Theme | Blue accent, top bar | Blue accent, compact layout |
-
-Update
-------
-
-### Quick update (from inside the container)
-
- sqrbx-update
-
-Checks installed registered tools against upstream releases. A dry run never
-installs absent optional tools; `--apply` updates the installed set only. Naming
-an absent tool explicitly is an install request. Failures are aggregated,
-reported with preserved logs, and return nonzero. Managed-home tools can advance
-in place. Image-tier tools advance only through a newer Squarebox Candidate and
-Box rebuild unless the current Candidate already authorizes the exact release
-asset; an unvetted upstream release is reported but never advertised as applyable.
-Broken version probes and incomplete Yazi, Helix, or Neovim output sets are
-reported as repairs; a failed post-install verification restores prior managed
-outputs.
-
- sqrbx-update # show available updates (dry run)
- sqrbx-update --apply # update all installed registered tools
- sqrbx-update lazygit # update, or explicitly install, one tool
- sqrbx-update --list # list all tools and current versions
-
-Setup and `sqrbx-update` read GitHub release metadata through the GitHub API,
-which allows only 60 unauthenticated requests per hour per IP address. On a
-shared NAT or CI runner, authenticate those requests to avoid HTTP 403 rate
-limits: export `GH_TOKEN` (or `GITHUB_TOKEN`), or run `gh auth login` inside
-the Box. The token is optional, is sent only to the GitHub API, and a rejected
-token falls back to unauthenticated requests.
-
-### Full rebuild (from the host)
-
- sqrbx-rebuild
-
-Resolves the requested published Release, pulls its immutable image digest, and
-replaces the Box. Installations created with `--build` retain that choice and
-build the matching source instead.
-Your code in ~/squarebox/workspace is safe since it lives on the host. Most
-in-container state (shell history, GitHub auth, SDK toolchains) survives
-because /home/dev is backed by the `squarebox-home` named Docker volume.
-Manually installed apt packages are still lost, since the image is rebuilt.
-
-#### What survives a rebuild
-
-| Survives | Reconciled or lost |
-|----------|--------------------|
-| Workspace code on the host | Selected tmux/Zsh/Fish packages are reconciled into the new Box |
-| Managed home: history, auth, assistant data, mise toolchains | Manually installed, unselected APT packages are lost |
-| Selection state in `/workspace/.squarebox` | Image-tier binaries are replaced by the Candidate digest |
-| Host SSH access (agent forwarding, or the recorded `SQUAREBOX_MOUNT_SSH` opt-in) | Image-managed dotfiles are safely refreshed |
-
-Use `sqrbx-uninstall --purge` to wipe recorded state. Do not remove a volume by
-name alone; lifecycle commands verify the Install identity and ownership
-labels before deleting a Managed resource.
-
-> **Tip:** Use `sqrbx-update` from inside the container for Managed-home tools.
-> Use `sqrbx-rebuild` for image-tier binaries, new APT packages, base-tool
-> changes, or any upstream release the current Candidate cannot authorize.
-
-Disk usage
-----------
-
-The reviewed amd64 v1.1 Candidate is approximately **900 MB** in
-`docker image ls` (about 638 MB of files in a running Box). Registry transfer,
-shared local layers, and unpacked filesystem size are different measurements;
-inspect the exact Release on your platform.
-
-First-run selections add to that:
-
-| Component | Adds |
-|-----------|------|
-| Claude Code | ~300 MB |
-| GitHub Copilot CLI | ~50 MB |
-| Google Gemini CLI | ~50 MB |
-| OpenAI Codex CLI | ~50 MB |
-| OpenCode | ~30 MB |
-| Pi Coding Agent | ~50 MB |
-| Oh My Pi | Varies by release |
-| lazygit / gh-dash / yazi | ~10 / ~10 / ~10 MB |
-| elio | ~14 MB |
-| micro / edit | ~12 / ~7 MB |
-| fresh / nvim | ~10 / ~45 MB |
-| Helix | Varies by release (binary plus runtime files) |
-| Node.js | ~90 MB |
-| Python | ~50 MB |
-| Go | ~500 MB |
-| .NET | ~800 MB |
-
-Optional sizes are approximate and change independently of Squarebox Releases.
+```bash
+sqrbx-help # commands and navigation shortcuts
+sqrbx-setup # rerun the setup wizard
+sqrbx-setup ai editors # reconfigure specific sections
+sqrbx-setup --list # show your selections
+sqrbx-update # check for tool updates
+sqrbx-update --apply # update installed registered tools
+sqrbx-update lazygit # update or install one named tool
+```
-Security
---------
+From the host, run `sqrbx-rebuild` to update the Box itself. This keeps your
+workspace and persistent home, and reuses your installation settings.
+Some bundled tools require a rebuild to update.
-Direct-download image-tier tools are pinned and fail closed against repository
-SHA-256 checksums. Published image bytes are immutable by digest; rebuilding
-later is not guaranteed to reproduce them because the Ubuntu base and APT
-repositories are external mutable inputs.
-
-Optional tools selected during first-run setup (editors, TUIs, OpenCode,
-zellij) install the latest upstream release at the time you run setup. For
-GitHub-hosted artifacts, Squarebox resolves one exact release tag and asset
-name, requires GitHub's SHA-256 release-asset digest, and verifies the bytes
-before extraction. Missing or mismatched digest metadata fails closed. These
-tools remain Managed-home selections rather than image-build pins. Setup
-installs an absent selection; `sqrbx-update --apply` is the explicit path for
-updating an already observed registered tool to a newer authorized release.
-
-SDKs (Node, Python, Go, .NET, Rust) are installed by [mise](https://github.com/jdx/mise),
-which is itself a Dockerfile-tier pinned binary. mise downloads each SDK
-toolchain from its upstream over HTTPS using its own integrity checks. npm-based
-AI tools (Copilot CLI, Gemini CLI, Codex CLI, and Pi) use npm's built-in
-integrity verification. Oh My Pi uses its official mise GitHub backend and
-follows mise's backend integrity policy.
-
-For the full trust model (what `install.sh` does on your machine, how each
-layer is verified, and how to inspect the script before running it) see
-[SECURITY.md](SECURITY.md).
-
-Devcontainer / Codespaces
--------------------------
-
-Open this repo in VS Code with the
-[Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers),
-or launch it in [GitHub Codespaces](https://github.com/features/codespaces).
-The included `.devcontainer/devcontainer.json` builds the full **squarebox** image
-automatically and mounts the cloned repository at `/workspace`, matching setup
-and Selection state. A per-Box named volume, derived from the stable
-Dev Container identity, mounts at `/home/dev` so authentication, history, and
-mise toolchains survive container rebuilds without being shared across
-unrelated workspaces.
-
-The interactive first-run wizard can't run in devcontainer mode (no TTY at
-create time), so a default toolset β **Claude Code + Node.js** β is installed
-non-interactively by `postCreateCommand`. Override the defaults with these
-container environment variables (set to an empty string to opt out of a tier):
-
-| Variable | Default | Selects |
-|----------|---------|---------|
-| `SQUAREBOX_DC_AI` | `claude` | AI assistants (`claude,copilot,gemini,codex,opencode,pi,omp`) |
-| `SQUAREBOX_DC_SDKS` | `node` | SDKs (`node,python,go,dotnet,rust`) |
-| `SQUAREBOX_DC_EDITORS` | _(none)_ | Editors (`micro,edit,fresh,helix,nvim`; Helix launches as `hx`) |
-| `SQUAREBOX_DC_TUIS` | _(none)_ | TUI tools (`lazygit,gh-dash,yazi,elio`) |
-| `SQUAREBOX_DC_MULTIPLEXERS` | _(none)_ | Multiplexers (`tmux,zellij,herdr`) |
-
-To add or change tools after the fact, run `sqrbx-setup` from the integrated
-terminal.
-
-You can also attach to a running codespace directly from your local terminal
-using `gh codespace ssh`. The official Dev Containers SSH server Feature is
-version- and digest-locked for this path. It is added only to the derived Dev
-Container image, not the published Squarebox Candidate, and remote-forwarded
-ports remain bound to loopback by default.
+See the [aliases](docs/usage.md#aliases),
+[keyboard shortcuts](docs/usage.md#keyboard-shortcuts), and
+[update details](docs/usage.md#updates-and-rebuilds).
Uninstall
---------
- sqrbx-uninstall
-
-Removes the recorded Box, owned image reference, and shell integration but **keeps**
-the install directory/Workspace and Managed-home volume
-(shell history, gh auth, mise toolchains) so your code and per-user state are
-safe by default. Pass `--purge` to remove the Managed home and recorded install
-directory. The default Workspace nested inside that directory is removed with
-it; a custom external Workspace is always preserved:
-
- sqrbx-uninstall --purge
-
-The confirmation summary lists a non-empty nested Workspace, with its item count,
-as something that will be deleted, and a second confirmation is required.
-Pass `-y` (or `-Yes` on PowerShell) to skip prompts for scripting. Unattended
-purge refuses, before removing anything, to delete a non-empty nested
-Workspace unless you also pass `--delete-workspace` (`-DeleteWorkspace` on
-PowerShell):
-
- sqrbx-uninstall --purge --yes --delete-workspace
-
-An empty Workspace or an external Workspace needs no extra flag.
-Idempotent for a valid Install identity. Legacy resources require `--adopt`;
-purging an adopted, unlabeled volume additionally requires `--force`.
+From the host:
-**Windows (PowerShell 7+):**
-
- sqrbx-uninstall # keep ~/squarebox
- sqrbx-uninstall -Purge # also remove ~/squarebox
- sqrbx-uninstall -Yes # skip confirmations
- sqrbx-uninstall -Purge -Yes -DeleteWorkspace # also delete a non-empty nested Workspace
+```bash
+sqrbx-uninstall
+```
-**Broken-state recovery** (e.g. shell functions are missing, or after partial
-install): run the script matching the adapter that created the Install identity
-directly from the install directory. PowerShell and Git Bash lifecycle state is
-not cross-consumed:
+This removes the Box and shell integration, keeping your workspace and
+persistent home. `sqrbx-uninstall --purge` (PowerShell: `-Purge`) also removes
+the persistent home and install directory, **including a workspace inside it**.
+A custom external workspace is preserved.
+See [uninstall options and recovery](docs/usage.md#uninstall-and-recovery).
- ~/squarebox/uninstall.sh # Linux / macOS / Git Bash
- ~/squarebox/uninstall.ps1 # Windows PowerShell
+Security
+--------
-Start a new shell afterwards (or `exec bash` / `exec zsh`) so the `sqrbx` and
-`squarebox` functions are dropped from the current session.
+The Box is a development environment with access to your mounted files and
+credentials. SSH-directory mounts require explicit opt-in.
+See [SECURITY.md](SECURITY.md) for SSH access, the trust model, artifact
+verification, and vulnerability reporting.
Make it your own
------------------
+----------------
-**squarebox** is meant to be a starting point, not a finished product. Fork it,
-swap out tools, add your own dotfiles, change the theme - build the dev
-environment that fits the way you work. The Dockerfile is intentionally
-straightforward and the tool registry (`scripts/lib/tools.yaml`) makes it easy
-to add or remove tools. Use it as a base, take what's useful, and make it yours.
+Fork it, swap tools, or add your own dotfiles. The [Dockerfile](Dockerfile) and
+[tool registry](scripts/lib/tools.yaml) define what's included.
diff --git a/SECURITY.md b/SECURITY.md
index 5e4a5c5..026b6b4 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -28,8 +28,8 @@ The Bash and PowerShell lifecycle adapters:
6. Mount the Workspace read-write, the private Git identity, optional SSH access,
and explicitly documented managed configuration. Bash/POSIX and Git Bash
adapters forward `SSH_AUTH_SOCK` when available and otherwise mount SSH files
- read-only; native PowerShell currently provides only the read-only SSH-file
- path.
+ read-only only on explicit opt-in; native PowerShell provides only the
+ opt-in read-only SSH-file path.
7. Add a sentinel-delimited shell integration block that reads the recorded
Install identity for launch, rebuild, and uninstall operations.
@@ -70,6 +70,23 @@ Before running a downloaded installer, inspect it:
Piping directly to Bash trusts GitHub and TLS to deliver the intended bootstrap
asset. Download-and-inspect is the safer default.
+## SSH access
+
+The Box does not receive your SSH private-key files by default, because anything
+running inside it, including unattended `*-yolo` AI agents, could read them.
+
+- **SSH agent (recommended).** When `SSH_AUTH_SOCK` points at a running agent,
+ the Bash/POSIX and Git Bash adapters forward the agent socket and mount only
+ `~/.ssh/config` and `~/.ssh/known_hosts` read-only. Key files stay on the
+ host, though Box processes can ask the agent to sign while the socket is
+ available.
+- **No agent.** `~/.ssh` is not mounted, and install prints a note. To mount
+ the directory read-only instead, opt in with `SQUAREBOX_MOUNT_SSH=1` (native
+ PowerShell: `.\install.ps1 -MountSsh` or `$env:SQUAREBOX_MOUNT_SSH = '1'`).
+ The choice is recorded in the Install identity and reused by
+ `sqrbx-rebuild`; set `SQUAREBOX_MOUNT_SSH=0` (or `-MountSsh:$false`) on a
+ rebuild to turn it back off.
+
## Release identity and verification
Every v1.1+ Release includes:
@@ -218,6 +235,10 @@ Post-install mismatch restores the prior complete output set. A broken version
probe or missing Yazi helper, Helix runtime, or Neovim tree/link is reported as
repairable incomplete state rather than βup to date.β
+Setup installs absent selections; `sqrbx-update --apply` explicitly updates
+already installed registered tools to newer authorized releases. Oh My Pi uses
+its official mise GitHub backend and follows miseβs backend integrity policy.
+
External installers and package managers are outside this artifact registry.
That includes npm assistants, Anthropic's Claude installer, mise SDK backends,
APT, and `dpkg`; their integrity and transaction behavior remain the upstream
diff --git a/docs/usage.md b/docs/usage.md
new file mode 100644
index 0000000..9b9dfc6
--- /dev/null
+++ b/docs/usage.md
@@ -0,0 +1,445 @@
+# Usage reference
+
+[Back to README](../README.md) Β· [Security](../SECURITY.md)
+
+- [Installing Docker](#installing-docker)
+- [Advanced installation](#advanced-installation)
+- [Windows installation](#windows-installation)
+- [Server deployment](#server-deployment)
+- [Shell configuration](#shell-configuration)
+- [Editor configuration](#editor-configuration)
+- [SDK configuration](#sdk-configuration)
+- [Help and reconfiguration](#help-and-reconfiguration)
+- [Aliases](#aliases)
+- [Keyboard shortcuts](#keyboard-shortcuts)
+- [Updates and rebuilds](#updates-and-rebuilds)
+- [Dev Containers and Codespaces](#dev-containers-and-codespaces)
+- [Uninstall and recovery](#uninstall-and-recovery)
+
+## Installing Docker
+
+**macOS** (via [Homebrew](https://brew.sh)):
+
+ brew install --cask docker-desktop
+
+**Linux** (official convenience script - inspect it first at [get.docker.com](https://get.docker.com)):
+
+ curl -fsSL https://get.docker.com | sh && sudo usermod -aG docker $USER
+
+Log out and back in (or run `newgrp docker`) so your shell picks up the new group.
+
+**Windows** (via [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), in PowerShell 7+):
+
+ winget install --id Docker.DockerDesktop -e
+
+On macOS and Windows, start Docker Desktop once after install so the daemon is
+running before you continue.
+
+## Advanced installation
+
+Stable resolves the latest published GitHub Release and pulls the immutable
+image digest recorded in its `release.json`. Raw Git tags are not installable
+stable releases. An explicit `SQUAREBOX_TAG=vβ¦` resolves that published Release
+and its matching source revision. Edge builds the latest commit on `main`. To
+build a published Release from source instead of pulling, pass `--build`.
+
+Install edge from Bash:
+
+```bash
+curl -fsSL https://github.com/SquareWaveSystems/squarebox/releases/latest/download/install.sh | bash -s -- --edge
+```
+
+If the install fails or you want to see the full build/pull and git output,
+re-run with `--verbose`.
+
+Flags: `--build` (build from source), `--edge` (latest `main`), `--adopt`
+(one-time migration of a legacy installation), and `--verbose`.
+
+| Variable | Default | Purpose |
+|----------|---------|---------|
+| `SQUAREBOX_DIR` | `~/squarebox` | Install location (repo + workspace). Point at durable storage on hosts where `$HOME` is volatile β e.g. Unraid `/mnt/user/appdata/squarebox`. |
+| `SQUAREBOX_WORKSPACE` | `$SQUAREBOX_DIR/workspace` | Host path mounted as `/workspace`. |
+| `SQUAREBOX_TAG` | latest published stable | Published Release to install (for example `v1.2.1`). Tags use `vMAJOR.MINOR.PATCH[-prerelease]`; build metadata is not published. |
+| `SQUAREBOX_IMAGE` | value from `release.json` | Optional image-repository override for development/testing. |
+| `SQUAREBOX_BUILD` | `0` | `1` is equivalent to `--build`. |
+| `PUID` / `PGID` | invoking Linux user | Host uid/gid that should own bind-mounted files. Unprivileged Linux installs must match the invoking account. Root-run rootful runtimes, including Docker or Podman on NAS and Unraid, may override these (typically `99` / `100`); rootless Podman also requires the invoking host identity. |
+| `SQUAREBOX_RUNTIME` | auto | Force `docker` or `podman`. |
+| `SQUAREBOX_HOME_VOLUME` | `squarebox-home` | Name of the named volume backing `/home/dev`. |
+| `SQUAREBOX_EDGE` | `0` | `1` is equivalent to `--edge`. |
+| `SQUAREBOX_MOUNT_SSH` | `0` | `1` mounts your host `~/.ssh` directory, **private keys included**, read-only into the Box when no SSH agent is forwarded. Recorded for rebuilds; set `0` to turn it back off. See [SSH access](../SECURITY.md#ssh-access). |
+
+**Non-interactive provisioning** β set any of these to a comma-separated list to
+pre-select a toolset and install it without prompts (handy for servers and
+scripted installs). Values use the same keys as `sqrbx-setup`:
+
+| Variable | Selects |
+|----------|---------|
+| `SQUAREBOX_AI` | AI assistants (`claude,copilot,gemini,codex,opencode,pi,omp`) |
+| `SQUAREBOX_SDKS` | language SDKs (`node,python,go,dotnet,rust`) |
+| `SQUAREBOX_EDITORS` | editors (`micro,edit,fresh,helix,nvim`; Helix launches as `hx`) |
+| `SQUAREBOX_TUIS` | TUI tools (`lazygit,gh-dash,yazi,elio`) |
+| `SQUAREBOX_MULTIPLEXERS` | multiplexers (`tmux,zellij,herdr`) |
+| `SQUAREBOX_GIT_NAME` / `SQUAREBOX_GIT_EMAIL` | git identity (when no host gitconfig) |
+
+Example:
+
+```bash
+curl -fsSL https://github.com/SquareWaveSystems/squarebox/releases/latest/download/install.sh \
+ | env SQUAREBOX_AI=claude SQUAREBOX_SDKS=node,python bash
+```
+
+Each successful v1.1-or-newer install records its effective lifecycle settings at
+`/.squarebox/install-state` (mode 0600 on POSIX; inherited
+current-user install-directory ACL on native Windows). Rebuild and uninstall
+parse this file as data; they do not reconstruct defaults or source it as shell
+code. Release pulls record an immutable image digest; source/edge builds record
+their local image ID/reference. Existing pre-v1.1 checkouts require a one-time
+reviewed `--adopt`/`-Adopt`.
+
+## Windows installation
+
+Windows users can install directly from PowerShell - no Git Bash required.
+This handles Release resolution, pull/build, Box creation, and PowerShell functions
+(`sqrbx`, `squarebox`, etc.) natively:
+
+ irm https://github.com/SquareWaveSystems/squarebox/releases/latest/download/install.ps1 | iex
+
+Once installed, you can re-run or pass flags from the local copy:
+
+ .\install.ps1 # re-install / update
+ .\install.ps1 -Edge # latest main instead of latest release
+ .\install.ps1 -Build # build the resolved source locally
+ .\install.ps1 -Adopt # migrate a legacy pre-v1.1 installation
+ .\install.ps1 -MountSsh # opt in to mounting %USERPROFILE%\.ssh read-only
+
+> **Note:** `irm ... | iex` does not support flags - PowerShell interprets them
+> as arguments to `Invoke-Expression`, not the script. Use the local
+> `.\install.ps1` form for `-Edge`, `-Build`, `-Adopt`, or `-MountSsh`.
+> PowerShell streams runtime and Git failures directly by default.
+
+> **Windows adapter boundary:** Keep install, rebuild, and uninstall on the
+> adapter that created the Install identity. Native PowerShell and Git Bash
+> use the same Install identity field names, but their native path and
+> shell-profile values are not interchangeable;
+> cross-adapter state consumption is rejected.
+> Native PowerShell does not forward `SSH_AUTH_SOCK` and mounts
+> `%USERPROFILE%\.ssh` read-only only when you opt in with `-MountSsh` or
+> `SQUAREBOX_MOUNT_SSH=1`. The separate Git Bash adapter supports SSH
+> agent-socket forwarding with its Bash lifecycle.
+> Use `./scripts/migrate-windows-adapter.ps1 -Target PowerShell` or
+> `-Target GitBash` from PowerShell 7 for an explicit cross-adapter migration.
+> Normal installers and uninstallers continue to reject foreign adapter state.
+
+## Server deployment
+
+The `curl | bash` installer is built around an interactive desktop shell. To run
+squarebox as a persistent server container you attach into on demand β on
+Unraid, a NAS, or a VPS β use the prebuilt image directly with the bundled
+`docker-compose.yml`:
+
+ cp .env.example .env # set PUID/PGID, the workspace path, and a tag
+ docker compose up -d
+ docker compose exec -u dev squarebox bash
+
+Set `PUID`/`PGID` in `.env` to match your host so files squarebox writes to the
+workspace mount are owned correctly β on Unraid that's `99` / `100`. The `-u dev`
+on `exec` is needed because the container starts as root (to apply PUID/PGID)
+then drops to the `dev` user; `exec` bypasses that, so `-u dev` lands you where
+you want to be.
+
+Per-user state (shell history, gh auth, mise toolchains, AI-assistant state)
+lives in the `squarebox-home` named volume and survives image updates; your code
+lives on the host at the workspace path. To update, pull a newer tag and
+`docker compose up -d`. The published image is multi-arch (amd64 + arm64), so it
+also runs on ARM NAS/VPS hosts.
+
+> **Unraid note:** the host's `/root` is tmpfs and wiped on reboot, so a raw
+> `curl | bash` install there won't persist. Either use compose (above) with the
+> workspace path under `/mnt/user/appdata`, or run the installer with
+> `SQUAREBOX_DIR` and `SQUAREBOX_WORKSPACE` pointed at appdata.
+
+## Shell configuration
+
+By default, squarebox uses Bash. During first-run setup you can opt in to
+**Zsh**, **Fish**, or **PowerShell** instead.
+
+**Zsh** installs:
+
+| Name | Description |
+|------|-------------|
+| [zsh](https://www.zsh.org) | Z shell (via apt) |
+| [Oh My Zsh](https://ohmyz.sh) | Community framework for managing zsh config |
+| [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions) | Fish-like history-based suggestions |
+| [zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting) | Inline command syntax highlighting |
+
+The generated `~/.zshrc` mirrors the default bashrc β same aliases, starship
+prompt, zoxide, and AI/editor/SDK sourcing β layered on top of Oh My Zsh.
+
+**Fish** installs [fish](https://fishshell.com) (via apt), which ships with
+autosuggestions and syntax highlighting built in. The generated
+`~/.config/fish/config.fish` mirrors the default bashrc in fish-native syntax;
+AI/editor/TUI/SDK selections are translated from their bash files into
+`~/.config/fish/conf.d/squarebox-selections.fish` at setup time.
+
+**PowerShell** installs PowerShell 7 (`pwsh`) from Microsoft's official
+[GitHub release](https://github.com/PowerShell/PowerShell/releases) `.deb`
+(asset SHA-256 verified against the release metadata before install). The
+generated `~/.config/powershell/profile.ps1` mirrors the default bashrc in
+PowerShell-native syntax β starship, zoxide, and mise activate, plus the
+standard aliases as functions (PowerShell `Set-Alias` cannot attach
+arguments); AI/editor/TUI selections are translated from their bash files into
+`~/.config/powershell/squarebox-selections.ps1` at setup time.
+
+> The marker file `~/.squarebox-use-zsh`,
+> `~/.squarebox-use-fish`, or `~/.squarebox-use-pwsh` causes `~/.bashrc` to
+> `exec` the chosen shell on every interactive login, so the next shell start
+> picks up the new shell. Set `SQUAREBOX_NO_ZSH=1`, `SQUAREBOX_NO_FISH=1`, or
+> `SQUAREBOX_NO_PWSH=1` to force bash for a single session, or re-run
+> `sqrbx-setup shell` to switch back permanently. Tooling is primarily tested
+> against bash, so a few edge cases may need polish β please file an issue if
+> you hit one. SDK shims are wired into all four shells via
+> `mise activate {bash,zsh,fish,pwsh}`.
+
+## Editor configuration
+
+Selecting **nvim** offers to install the [LazyVim](https://www.lazyvim.org/) starter config to `~/.config/nvim`, turning Neovim into a preconfigured IDE. Plugins sync on first launch and persist in the `squarebox-home` volume. A Nerd Font in your terminal is recommended for icons; the starter is skipped if `~/.config/nvim` already exists, so your own config is never overwritten.
+
+## SDK configuration
+
+All SDKs are managed by [mise](https://github.com/jdx/mise) β a single
+polyglot version manager. Selections are written to `~/.config/mise/config.toml`
+and `mise activate` wires up shims and PATH automatically across bash, zsh,
+and fish.
+
+| SDK | mise tool |
+|-------|-----------|
+| Node.js | `node` |
+| Python | `python` |
+| Go | `go` |
+| .NET | `dotnet` |
+| Rust | `rust` |
+
+## Help and reconfiguration
+
+Run `sqrbx-help` inside the container for a one-screen overview of the
+`sqrbx-*` commands, Bash's fzf (`Ctrl+R`/`Ctrl+T`/`Alt+C`/`**`) bindings,
+and zoxide (`z`/`zi`) navigation. Zsh and Fish retain the `fzf`, `ff`, and
+`eff` commands but do not claim those Bash-specific bindings. The MOTD points
+to the help command on every shell start.
+
+Re-run the first-run wizard at any time from inside the container with
+`sqrbx-setup`. With no arguments it walks every section; pass one or more
+section names to reconfigure just those: `git`, `github`, `ai`, `editors`,
+`tuis`, `multiplexers`, `sdks`, `shell`. `sqrbx-setup --list` shows your
+current selections and `sqrbx-setup --help` the usage.
+
+## Aliases
+
+| Alias | Command | Description |
+|-------|---------|-------------|
+| `ls` | `eza --icons` | Modern ls with icons |
+| `ll` | `eza -la --icons` | Long listing with icons |
+| `lsa` | `ls -a` (resolves to `eza --icons -a`) | List all including hidden files |
+| `lt` | `eza --tree --level=2 --long --icons --git` | Tree view with git status |
+| `lta` | `lt -a` | Tree view including hidden files |
+| `cat` | `bat --paging=never` | Syntax-highlighted cat |
+| `ff` | `fzf --preview 'bat ...'` | Fuzzy find with preview |
+| `eff` | `$EDITOR "$(ff)"` | Fuzzy find and edit |
+| `..` | `cd ..` | Go up one directory |
+| `...` | `cd ../..` | Go up two directories |
+| `....` | `cd ../../..` | Go up three directories |
+| `c` | first selected AI tool | Launch selected AI assistant |
+| `g` | `git` | Git shorthand |
+| `gcm` | `git commit -m` | Commit with message |
+| `gcam` | `git commit -a -m` | Stage all and commit |
+| `gcad` | `git commit -a --amend` | Stage all and amend |
+| `lg` | `lazygit` | Launch lazygit (if installed) |
+| `claude-yolo` | `claude --dangerously-skip-permissions` | Claude without prompts |
+| `copilot-yolo` | `copilot --allow-all` | Copilot CLI without permission prompts |
+| `codex-yolo` | `codex --dangerously-bypass-approvals-and-sandbox` | Codex without prompts or sandboxing |
+| `gemini-yolo` | `gemini --approval-mode=yolo` | Gemini CLI without prompts |
+| `opencode-yolo` | `opencode --dangerously-skip-permissions` | OpenCode without prompts |
+| `omp-yolo` | `omp --approval-mode yolo` | Oh My Pi without prompts |
+
+The `*-yolo` aliases are generated only for selected AI tools that are
+installed. They disable that tool's normal approval prompts; `codex-yolo` also
+disables Codex's sandbox. Use them only in a workspace whose contents and
+commands you trust.
+
+## Keyboard shortcuts
+
+Squarebox uses one portable rule: `Super` belongs
+to the OS/window manager, while `Ctrl` acts immediately in the focused app.
+Herdr uses `Ctrl+Alt` for direct letter chords because many terminals collapse
+`Ctrl+Shift+letter` into the unshifted control key. Its `F12` prefix remains
+available as a compatibility fallback.
+
+Herdr's generated default uses familiar app shortcuts:
+
+| Feature | Herdr |
+|---------|-------|
+| New / close | `Ctrl+T` / `Ctrl+W` |
+| Cycle / select tabs | `Ctrl+Tab`, `Ctrl+Shift+Tab` / `Ctrl+1-9` |
+| Focus / swap pane | `Ctrl+Arrow` / `Ctrl+Shift+Arrow` |
+| Sidebar / go to | `Ctrl+B` / `Ctrl+G` |
+| Split right / down | `Ctrl+\\` / `Ctrl+Alt+\\` |
+| Zoom / new workspace | `Ctrl+Alt+Z` / `Ctrl+Alt+N` |
+| Compatibility prefix | `F12` |
+
+These bindings intentionally take precedence over matching shell or nested-app
+shortcuts while Herdr is focused. Existing `~/.config/herdr/config.toml` files
+remain user-managed and are never replaced by setup.
+
+Tmux and Zellij use matching defaults:
+
+| Feature | Tmux | Zellij |
+|---------|------|--------|
+| Config path | `~/.config/tmux/tmux.conf` | `~/.config/zellij/config.kdl` |
+| Prefix | `Ctrl+Space` | `Ctrl+Space` (Tmux mode) |
+| Alternate prefix | `Ctrl+B` | `Ctrl+B` (Tmux mode) |
+| Prefix help | β | `prefix ?` |
+| Pane navigation | `Ctrl+Alt+Arrow` | `Ctrl+Alt+Arrow` |
+| Pane resizing | `Ctrl+Alt+Shift+Arrow` | `Ctrl+Alt+Shift+Arrow` |
+| Tab/window select | `Alt+1-9` | `Alt+1-9` |
+| Tab/window cycle | `Alt+Left/Right` | `Alt+Left/Right` |
+| Split horizontal | `prefix h` | `prefix h` |
+| Split vertical | `prefix v` | `prefix v` |
+| Scrollback | 50,000 lines | 50,000 lines |
+| Copy mode | Vi keys | Vi-style scroll |
+| Theme | Blue accent, top bar | Blue accent, compact layout |
+
+## Updates and rebuilds
+
+### Quick update (from inside the container)
+
+ sqrbx-update
+
+Checks installed registered tools against upstream releases. A dry run never
+installs absent optional tools; `--apply` updates the installed set only. Naming
+an absent tool explicitly is an install request. Failures are aggregated,
+reported with preserved logs, and return nonzero. Managed-home tools can advance
+in place. Image-tier tools advance only through a newer Squarebox Candidate and
+Box rebuild unless the current Candidate already authorizes the exact release
+asset; an unvetted upstream release is reported but never advertised as applyable.
+Broken version probes and incomplete Yazi, Helix, or Neovim output sets are
+reported as repairs; a failed post-install verification restores prior managed
+outputs.
+
+ sqrbx-update # show available updates (dry run)
+ sqrbx-update --apply # update all installed registered tools
+ sqrbx-update lazygit # update, or explicitly install, one tool
+ sqrbx-update --list # list all tools and current versions
+
+Setup and `sqrbx-update` read GitHub release metadata through the GitHub API,
+which allows only 60 unauthenticated requests per hour per IP address. On a
+shared NAT or CI runner, authenticate those requests to avoid HTTP 403 rate
+limits: export `GH_TOKEN` (or `GITHUB_TOKEN`), or run `gh auth login` inside
+the Box. The token is optional, is sent only to the GitHub API, and a rejected
+token falls back to unauthenticated requests.
+
+### Full rebuild (from the host)
+
+ sqrbx-rebuild
+
+Resolves the requested published Release, pulls its immutable image digest, and
+replaces the Box. Installations created with `--build` retain that choice and
+build the matching source instead.
+Your code in ~/squarebox/workspace is safe since it lives on the host. Most
+in-container state (shell history, GitHub auth, SDK toolchains) survives
+because /home/dev is backed by the `squarebox-home` named Docker volume.
+Manually installed apt packages are still lost, since the image is rebuilt.
+
+#### What survives a rebuild
+
+| Survives | Reconciled or lost |
+|----------|--------------------|
+| Workspace code on the host | Selected tmux/Zsh/Fish packages are reconciled into the new Box |
+| Managed home: history, auth, assistant data, mise toolchains | Manually installed, unselected APT packages are lost |
+| Selection state in `/workspace/.squarebox` | Image-tier binaries are replaced by the Candidate digest |
+| Host SSH access (agent forwarding, or the recorded `SQUAREBOX_MOUNT_SSH` opt-in) | Image-managed dotfiles are safely refreshed |
+
+Use `sqrbx-uninstall --purge` to wipe recorded state. Do not remove a volume by
+name alone; lifecycle commands verify the Install identity and ownership
+labels before deleting a Managed resource.
+
+> **Tip:** Use `sqrbx-update` from inside the container for Managed-home tools.
+> Use `sqrbx-rebuild` for image-tier binaries, new APT packages, base-tool
+> changes, or any upstream release the current Candidate cannot authorize.
+
+## Dev Containers and Codespaces
+
+Open this repo in VS Code with the
+[Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers),
+or launch it in [GitHub Codespaces](https://github.com/features/codespaces).
+The included `.devcontainer/devcontainer.json` builds the full **squarebox** image
+automatically and mounts the cloned repository at `/workspace`, matching setup
+and Selection state. A per-Box named volume, derived from the stable
+Dev Container identity, mounts at `/home/dev` so authentication, history, and
+mise toolchains survive container rebuilds without being shared across
+unrelated workspaces.
+
+The interactive first-run wizard can't run in devcontainer mode (no TTY at
+create time), so a default toolset β **Claude Code + Node.js** β is installed
+non-interactively by `postCreateCommand`. Override the defaults with these
+container environment variables (set to an empty string to opt out of a tier):
+
+| Variable | Default | Selects |
+|----------|---------|---------|
+| `SQUAREBOX_DC_AI` | `claude` | AI assistants (`claude,copilot,gemini,codex,opencode,pi,omp`) |
+| `SQUAREBOX_DC_SDKS` | `node` | SDKs (`node,python,go,dotnet,rust`) |
+| `SQUAREBOX_DC_EDITORS` | _(none)_ | Editors (`micro,edit,fresh,helix,nvim`; Helix launches as `hx`) |
+| `SQUAREBOX_DC_TUIS` | _(none)_ | TUI tools (`lazygit,gh-dash,yazi,elio`) |
+| `SQUAREBOX_DC_MULTIPLEXERS` | _(none)_ | Multiplexers (`tmux,zellij,herdr`) |
+
+To add or change tools after the fact, run `sqrbx-setup` from the integrated
+terminal.
+
+You can also attach to a running codespace directly from your local terminal
+using `gh codespace ssh`. The official Dev Containers SSH server Feature is
+version- and digest-locked for this path. It is added only to the derived Dev
+Container image, not the published Squarebox Candidate, and remote-forwarded
+ports remain bound to loopback by default.
+
+## Uninstall and recovery
+
+sqrbx-uninstall
+
+Removes the recorded Box, owned image reference, and shell integration but **keeps**
+the install directory/Workspace and Managed-home volume
+(shell history, gh auth, mise toolchains) so your code and per-user state are
+safe by default. Pass `--purge` to remove the Managed home and recorded install
+directory. The default Workspace nested inside that directory is removed with
+it; a custom external Workspace is always preserved:
+
+ sqrbx-uninstall --purge
+
+The confirmation summary lists a non-empty nested Workspace, with its item count,
+as something that will be deleted, and a second confirmation is required.
+Pass `-y` (or `-Yes` on PowerShell) to skip prompts for scripting. Unattended
+purge refuses, before removing anything, to delete a non-empty nested
+Workspace unless you also pass `--delete-workspace` (`-DeleteWorkspace` on
+PowerShell):
+
+ sqrbx-uninstall --purge --yes --delete-workspace
+
+An empty Workspace or an external Workspace needs no extra flag.
+Idempotent for a valid Install identity. Legacy resources require `--adopt`;
+purging an adopted, unlabeled volume additionally requires `--force`.
+
+**Windows (PowerShell 7+):**
+
+ sqrbx-uninstall # keep ~/squarebox
+ sqrbx-uninstall -Purge # also remove ~/squarebox
+ sqrbx-uninstall -Yes # skip confirmations
+ sqrbx-uninstall -Purge -Yes -DeleteWorkspace # also delete a non-empty nested Workspace
+
+**Broken-state recovery** (e.g. shell functions are missing, or after partial
+install): run the script matching the adapter that created the Install identity
+directly from the install directory. PowerShell and Git Bash lifecycle state is
+not cross-consumed:
+
+ ~/squarebox/uninstall.sh # Linux / macOS / Git Bash
+ ~/squarebox/uninstall.ps1 # Windows PowerShell
+
+Start a new shell afterwards (or `exec bash` / `exec zsh`) so the `sqrbx` and
+`squarebox` functions are dropped from the current session.
diff --git a/tests/test-repository-consistency.sh b/tests/test-repository-consistency.sh
index 394af8b..8690bc8 100755
--- a/tests/test-repository-consistency.sh
+++ b/tests/test-repository-consistency.sh
@@ -10,11 +10,11 @@ fail() {
}
if grep -E '(@githubnext/github-copilot-cli|github-copilot-cli)' \
- setup.sh README.md CLAUDE.md Dockerfile >/dev/null; then
+ setup.sh README.md docs/usage.md CLAUDE.md Dockerfile >/dev/null; then
fail "production surfaces still reference deprecated Copilot CLI"
fi
-if grep -Eqi 'paseo' setup.sh README.md CLAUDE.md uat-checklist.md \
+if grep -Eqi 'paseo' setup.sh README.md docs/usage.md CLAUDE.md uat-checklist.md \
demo/setup-demo.sh scripts/squarebox-setup.sh scripts/e2e-test.sh; then
fail "current product surfaces still reference removed Paseo support"
fi
@@ -98,14 +98,14 @@ grep -Fq 'uninstall.ps1' .github/workflows/e2e.yml \
|| fail "PowerShell uninstaller is missing from release assets"
grep -Fq 'release.json' .github/workflows/e2e.yml \
|| fail "release identity is missing from publication"
-grep -Fq 'env SQUAREBOX_AI=' README.md \
+grep -Fq 'env SQUAREBOX_AI=' docs/usage.md \
|| fail "noninteractive installer example does not pass variables to Bash"
-if grep -Eq '~370 MB|docker build.+reproducible' README.md SECURITY.md; then
+if grep -Eq '~370 MB|docker build.+reproducible' README.md docs/usage.md SECURITY.md; then
fail "stale image-size/reproducibility claim remains"
fi
-grep -Fq 'cross-adapter state consumption is rejected' README.md \
- || fail "README promises no Windows lifecycle-adapter boundary"
+grep -Fq 'cross-adapter state consumption is rejected' docs/usage.md \
+ || fail "usage reference promises no Windows lifecycle-adapter boundary"
grep -Fq 'adapter may consume that state' CLAUDE.md \
|| fail "agent guidance does not enforce adapter-native lifecycle state"
grep -Fq 'are not cross-consumed' docs/releases/v1.1.0.md \
@@ -113,7 +113,7 @@ grep -Fq 'are not cross-consumed' docs/releases/v1.1.0.md \
grep -Fq 'does not claim `SSH_AUTH_SOCK` forwarding' uat-checklist.md \
|| fail "PowerShell UAT still overclaims SSH-agent forwarding"
if grep -Fq 'Bash and PowerShell lifecycle state must remain compatible' \
- README.md CLAUDE.md docs/releases/v1.1.0.md uat-checklist.md; then
+ README.md docs/usage.md CLAUDE.md docs/releases/v1.1.0.md uat-checklist.md; then
fail "docs still promise unsupported cross-adapter lifecycle state"
fi