Release tracking starts at v1.5.0. Run ./setup.sh --version to identify
this checkout. See the release process for source freezes,
immutable release tags, pinned installations, and validation requirements.
Generic project creation now lives in
openRepoProject. workBenches
installs its project executable during setup and command installation:
python3 scripts/setup-project-command.py
project benches
project new MyApp --bench flutterBench --type flutter --dry-run
project status MyApp
project doctor MyApp
project update MyApponp NAME [PARENT] and scripts/new-project.sh NAME [PARENT] forward to
project new and accept its flags. The forwarders resolve the directory chosen
by command installation (including /usr/local/bin) and execute only a
project whose ownership marker and digest verify. Bench-specific generators
remain owned by their bench repositories. The creation list excludes update
scripts and reports configured scripts that are not installed.
config/openrepoproject-pin.json identifies an exact source commit and executable
SHA-256. The PATH-facing project command is a verifier launcher; the pinned
upstream executable is stored separately as .workbenches-project.payload, so
normal direct invocations perform the same ownership and digest check as legacy
forwarders. The launcher embeds the pinned source identity, not checkout or pin
file paths; it uses WORKBENCHES_ROOT or the local discovery marker only after
the executable payload verifies. The installer tries the authenticated GitHub API before raw download,
verifies bytes before replacing anything, journals publication so an
interrupted upgrade can resume, and rolls back ordinary partial multi-file
replacement failures. A persistent per-directory lock serializes installation,
removal, status, and legacy snapshot capture; launchers release it before
running the verified private snapshot so delegated setup operations can acquire
the writer lock. A failed download/digest
check preserves the existing executable. A symlink, directory,
read-only target, or unrelated existing project command refuses. After
reviewing a name collision, use --replace-existing to take ownership;
uninstall removes only an artifact whose ownership record and digest agree.
The user-writable PATH entry is not itself an integrity root: status and legacy
forwarders authenticate it against the installer template, while protection
against hostile same-user replacement before direct execution depends on host
filesystem permissions.
Python 3.10+ is required; YAML inspection needs PyYAML, available in the
development bench.
Use --source /path/to/openRepoProject/project for offline installation of the
same pinned bytes, --bin-dir PATH for another command directory, or
WORKBENCHES_SKIP_PROJECT_COMMAND=1 to skip. The installer records this checkout
in the host-local .workbenches-path beside the command and records the selected
command directory in ~/.config/workbenches/project-bin. Checkout legacy
entrypoints use that verified pointer when the custom directory is no longer on
PATH; WORKBENCHES_ROOT overrides checkout discovery at runtime.
When advancing the pin, first copy the current commit and sha256 pair into
the trusted_previous array. Then publish the tested source commit, obtain
project from that commit, compute its SHA-256, and update the top-level
commit and sha256 fields in the same change. Retain each previous pair only
for the upgrade window in which an existing installer-owned payload must be
recognized. If the source PR will squash-merge, re-pin to the resulting main
commit before landing the workBenches integration. Never adjust a digest to
accept drift.
Offline integration tests: python3 devcontainer.test/test-project-command.py
inside a Python workBench. Command behavior and migration notes live in
openRepoProject's README and docs/migration-review.md.
A layered Docker-based development environment system. Each "bench" is a self-contained devcontainer for a specific tech stack (Flutter, Java, .NET, Python, Frappe, C++, etc.) built on shared base images.
On the v1.6 development branch, setup adds a third Profiles page (G): personal email and verified GitHub linking, then any number of company profiles with separate organization sign-ins. See Profiles onboarding. This feature is outside the v1.5 release scope.
These commands follow main. For a frozen deployment, use the version-specific
bootstrap in the release guide.
On a new workstation, install Git and download the standalone bootstrap.
curl -fsSL https://raw.githubusercontent.com/opensoft/workBenches/main/bootstrap.sh -o workbenches-bootstrap.sh
bash workbenches-bootstrap.sh --setupBootstrap clones to ~/Projects/workBenches. Use --directory PATH to choose
another location, or omit --setup to clone without running setup. It prefers
SSH when your existing SSH configuration or agent can access the repository;
otherwise it falls back to HTTPS. SSH probes are noninteractive and require a
trusted host key, so a fresh workstation can download public repositories
without a GitHub login, token, or SSH key. Private repositories still require
authorized SSH access or HTTPS credentials.
The setup TUI, registry clones, and Wave installer use the same transport
selection. Existing checkout remotes and global Git/SSH settings are preserved.
Public bench URLs in the catalog and .gitmodules use HTTPS for compatibility
with ordinary Git commands. To initialize all pinned submodules with SSH
preference and HTTPS fallback, run bash bootstrap.sh --submodules "$PWD".
From an existing checkout:
./setup.shThis single command:
- Identifies the OS and checks required Docker access, Windows/WSL 2 readiness, and common dependencies. Missing requirements open a guided setup screen before component selection.
- Opens the TUI to select benches, AI assistants, and tools. Press P for Requirements, or G for Profiles, including personal/company identities and AI credential setup. An empty component selection finishes without component installs or image builds.
- Enter applies the selected changes immediately, with a compact install/update summary. Q cancels and an empty selection exits.
- Checks Node/npm only for selected tools that require them. A system-owned npm location falls back to
~/.local, with PATH configured for new terminals. - Installs AI tools without requiring sign-in. Open Profiles to configure identity-specific AI accounts or select AI accounts for existing account setup, using direct sign-in or guided vault recovery. Existing profiles and credentials are preserved. Organization sign-in is optional; Keycloak login requires organization-provided settings.
- Configures host shell settings only when Shell setup is selected. Org workspace explicitly initializes the workspace repository, after installing its pinned estate-command dependencies.
- Installs selected tools and builds only selected bench dependencies. Wave widgets and VPN setup follow the selected tools.
After setup, open any bench in VS Code → "Reopen in Container" to start developing.
Installed items show their status and default to no changes. Space selects an install/update and pressing it again undoes the selection. D selects removal and pressing it again undoes removal. Only explicit selections are applied; an unchanged selection exits without host setup or builds. Bench checkout deletion requires a focused confirmation and refuses local changes, untracked/ignored files, local-only commits, or use by a running container. Docker images, volumes, and credentials are preserved. For selected bench installs or organization workspace setup, the estate commands (openRepoShape, openRepoTools, park, resume, status and the five lane tools) are checked against workBenches' pin and are re-placed only when a host copy differs from it. The optional workspace repository step does nothing at all once you have one: it is a file test on ~/.agents/workspace.yaml, so that step skips an existing workspace without asking questions or contacting the network.
Layer 0: workbench-base:latest — Ubuntu 24.04 + git, zsh, curl, shared AI CLIs, bun
├─ Layer 1a: dev-bench-base:latest — Python, Node.js LTS, npm, dev tools, OpenSpec, spec-kit, testing tools, Playwright Chromium
│ ├─ Layer 2: cpp-bench:latest — GCC, CMake, vcpkg
│ ├─ Layer 2: dotnet-bench:latest — .NET SDK 8/9
│ ├─ Layer 2: flutter-bench:latest — Flutter SDK, Dart, Android tools
│ ├─ Layer 2: frappe-bench:latest — MariaDB client, Redis, Nginx, bench CLI (Node.js 20)
│ ├─ Layer 2: java-bench:latest — OpenJDK 25, Maven, Gradle, Spring CLI
│ ├─ Layer 2: php-bench:latest — PHP 8.3, Composer, PHPUnit, Xdebug
│ ├─ Layer 2: py-bench:latest — Python dev tools (thin layer on 1a)
│ └─ Layer 2: go-bench:latest — Go toolchain
├─ Layer 1b: sys-bench-base:latest — Kubernetes, Terraform, cloud CLIs
│ └─ Layer 2: cloud-bench:latest — Cloud admin tools
└─ Layer 1c: bio-bench-base:latest — Miniconda, Node.js, bioinformatics base
├─ Layer 2: gentec-bench:latest — BaseSpace CLI, bcftools, samtools, nextflow
└─ Layer 2: sim-bench:latest — ESMFold, AlphaFold, molecular dynamics
Layer 3 (:<username>): A thin user-personalization layer built on any Layer 2 image. Creates your user (matching host UID/GID) and copies shell configs from /etc/skel. Tagged as <bench>:<username> (e.g., java-bench:brett).
| Tag | Purpose | Example |
|---|---|---|
:latest |
Layer 2, user-agnostic bench tools | java-bench:latest |
:<username> |
Layer 3, user-personalized | java-bench:brett |
<project>-<service>:latest |
Docker-compose built (bioBenches) | sim-bench-gene_bench:latest |
Family base images use the canonical kebab-case repos dev-bench-base, sys-bench-base, and bio-bench-base. Legacy local aliases devbench-base, sysbench-base, and biobench-base are still tagged during the migration window.
Built automatically by ensure-layer3.sh (called from devcontainer initializeCommand) or manually:
bash scripts/ensure-layer3.sh --base java-bench:latestTo refresh all user-agnostic layers and verify the rebuilt bench images:
scripts/update-and-rebuild.sh --all --cascade --no-cache --user brettThe cascade verification probes the required shared CLI commands in every
rebuilt Layer 2 :latest image and reports the state of the related Layer 3
:<user> image. It does not create, replace, or restart a Layer 3 image or a
running bench. Add --write-manifest only when a durable version snapshot at
config/version-manifest.json is required; ordinary verification leaves the
checkout unchanged.
setup.sh
├── Immediate TUI with yellow Loading… states
├── Background OS / WSL 2 + Docker + Tools checks (containerized Python/jq/Git/curl)
│ └── Results update live; missing requirements offer Install / Start
├── Optional Vault Up: credential-access tools; provider sign-in when needed
├── Component TUI: Benches | AI Assistants | Tools | Requirements (P)
│ └── Enter applies; Q/EOF cancels; empty Enter finishes
├── Compact selected-change summary + selected Node/npm prerequisites
├── Reuse existing profiles; preserve host shell settings
├── Selected bench dependencies: shared commands → Layer 0 → family Layer 1
├── Install/update selected components
├── Optional Shell setup / Org workspace
├── Optional workBenches account: organization Keycloak browser approval
├── Optional AI accounts: profiles, direct login or confirmed vault recovery
└── Summary + authentication pending where applicable + log path
Docker verification runs before host installers and credential onboarding. Missing Docker prompts for installation in an interactive terminal; supported Linux package managers include apt, dnf, apk and Arch/Omarchy pacman. Local passwords are entered into sudo. A stopped local system Docker service can be started with the user's agreement. Declining, cancellation, installation failure or inaccessible Docker stops setup before later steps. Remote/rootless contexts use their configured daemon and local access policy. See Workstation requirements and optional accounts for Windows guidance and organization Keycloak configuration.
Your host's openRepoShape, openRepoTools, park, resume, status, lane, lanes, lane-handoff, lane-rename, lanes-edit.sh, lane-start, lane-end, link-estates, repos.tsv, claude-current and claude-restart-check come from workBenches' own pin (devBenches/base-image/upstream-pin.yaml). setup.sh places them from the vendored copies in devBenches/base-image/files/openreposhape/ and devBenches/base-image/files/openrepotools/, and re-places them whenever a host copy differs from the pin, in either direction — behind, ahead, or hand-edited. To move them to a new upstream commit, move the pin with update-upstream.py apply and re-run setup.sh; do not edit the vendored files or the installed commands directly. The step refuses to run over a symlinked, non-regular, or read-only target, and verifies the fifteen placed openRepoTools files (and openRepoShape's own) against the vendored copies before it reports success. It also holds openRepoShape on the release the pin names, the way the dev-bench image holds its own: the install writes the pin's openreposhape commit to openRepoShape.ref beside the placed command (${OPENREPOSHAPE_BIN_DIR:-~/.local/bin}/openRepoShape.ref), fetching nothing to do it, so the command fetches setup.sh and clones the standard at that commit instead of following openRepoShape's main, and openRepoShape --version prints it. A record already there — left by the one-line installer, by an earlier run of this step, or by a stray OPENREPOSHAPE_RECORD_REF=1 in your shell — is replaced, never removed, and this step does not read OPENREPOSHAPE_RECORD_REF or OPENREPOSHAPE_REF from your shell; it refuses a symlinked, non-regular or unreadable record, and refuses to report success unless the record holds the pin's commit. Set WORKBENCHES_SKIP_ESTATE_COMMANDS=1 to skip this step.
When Org workspace is selected, setup installs the estate commands and runs openRepoTools wip init — the fourth link in the onboarding chain of lane-collision-protocol Amendment 9(e):
gh repo clone opensoft/workBenches && cd workBenches && ./setup.sh # the host, and the estate commands
openRepoTools --install # (setup.sh already did this for you)
openRepoTools wip init # your workspace repository
pclaude <profile>
lane-start <repo> <n>
pclaude <profile> starts a profile session without a lane. It exports CLAUDE_NO_LANE=1 so the prompt name guard skips that process. Use lclaude <profile> to start or resume a lane; pclaude --lane <repo>-<n> <profile> remains supported. An explicit lane request clears an inherited no-lane marker, while explicit --no-lane wins over lane options. The hook stays installed in shared profile settings so concurrent lane sessions receive enforcement.
The workspace repository (<org>/<login>-wip) holds your lane register, your handoffs and your workspace manifests. It holds no code: the lane tooling is installed from opensoft/openRepoTools.
openRepoTools --install is the single writer of everything it places (lane-collision-protocol Amendment 9(b), adoption act 4b). It places fifteen files into ${OPENREPOTOOLS_BIN_DIR:-~/.local/bin} at 755 — openRepoTools, park, resume, status, lane, lanes, lane-handoff, lane-rename, lanes-edit.sh, lane-start, lane-end, link-estates, the shipped alias table repos.tsv, and the two Claude Code launch commands claude-current and claude-restart-check — plus fourteen artifacts that are not in that directory: the handoff, lane-swap and restart skills and the handoff, ctx and swap command files, each at ${CLAUDE_PROFILES_HOME:-~/.claude-profiles}/shared/skills/<name>/SKILL.md (or .../shared/commands/<name>.md), and a copy of each at ~/.claude/skills/<name>/SKILL.md (or ~/.claude/commands/<name>.md) for a bare claude outside the launcher, plus two merged entries in ~/.claude/settings.json — the SessionStart entry and lane-collision-protocol Amendment 12's UserPromptSubmit name guard. Those counts are not blindly trusted forever: scripts/setup-estate-commands.sh keeps its own TOOLS_FILES, SKILL_NAMES and COMMAND_NAMES — hand-kept mirrors of the pinned shim's INSTALLABLES, SKILLS and COMMANDS arrays, since there is no --list-installables to generate them from — but checks each one against the shim's own array before installing anything (check_shim_list, Copilot's review of workBenches#91), so a shim that grew past what this script lists refuses the whole install rather than silently installing the new file with no preflight or verification. Nothing else in this repository writes any of those twenty-nine: scripts/setup-claude-profiles.sh used to install the skill and ensure that hook entry, and adoption act 4b deleted both. The one SessionStart ensure that is NOT --install's is the launcher's own, in each profile's settings.json — a different file for a different run. That merge refuses — placing nothing at all, exit 2, bin directory untouched — on one condition only: a SessionStart entry that itself runs session-start under a different command string, which is a second program running the same hook verb and would fire it twice (R-A9-8, narrowed from lanes-edit.sh to the verb by R-A9-14). An unrelated SessionStart entry is merged beside it and the install exits 0.
This step asks you nothing. The login comes from gh api user -q .login, lowercased; the organisation is your home organisation (opensoft in this estate). There is no prompt in it in any path — where nothing can be derived it prints the one command that fixes that (gh auth login) and continues rather than asking you for what it could not read.
It does nothing on a host that already has one. ~/.agents/workspace.yaml naming a repository and a checkout of it is the whole of the idempotence, and it is a file test, not a network call. Re-run ./setup.sh as often as you like.
It never fails setup. setup.sh treats it as best-effort, exactly as it treats the estate command step above it. Run directly, scripts/setup-workspace-repo.sh exits 0 (done, or already done, or degraded and printed), 1 (openRepoTools wip init itself ran and refused — its own output above says why), or 2 (nothing was attempted: either no openRepoTools is installed, or a precondition wip init would refuse on — no gh, an unauthenticated gh, or a login that cannot form <login>-wip — is already known here and named instead of relayed from a doomed call).
Two things it cannot do for you, and says so rather than attempting. Where your account cannot create a repository in the organisation, wip init prints the exact gh repo create and the team-permission gh api --method PUT for an administrator; and a newly created workspace repository must be excluded from the organisation's PR-only ruleset before the lane register can be written at all. Both are administrator acts. This step never captures or summarises that output — it relays every byte of it to your terminal. Because that block can still scroll off screen under the headers that follow it, a non-zero exit here also leaves $AGENT_PROTOCOL_ROOT/.workspace-step-needs-attention behind; setup.sh's own SETUP COMPLETE summary checks for it and points back at this step's slice of the log, and a later clean run removes it.
wip init is live from the pin this repository carries. It arrived with Amendment 9's adoption act 3 in opensoft/openRepoTools, and adoption act 4b moved the pin to it. Against an openRepoTools that does not carry the subcommand the step still degrades rather than failing: it prints what you would run and continues, and capability is read from openRepoTools --help, never from an exit code.
| Variable | Effect |
|---|---|
WORKBENCHES_SKIP_WORKSPACE_REPO=1 |
Skip this step entirely |
WORKBENCHES_WORKSPACE_ORG=<org> |
The organisation (default: opensoft); passed through to wip init |
AGENT_PROTOCOL_ROOT=<dir> |
Where workspace.yaml lives (default: ~/.agents) |
Tests: devcontainer.test/test-setup-workspace-repo.sh (110 checks; fakes openRepoTools and gh, and also runs the real vendored openRepoTools to prove the degradation is live). Wired into CI in .github/workflows/speckit-git-bash.yml, alongside the sibling estate-commands suite.
setup.sh runs the Wave Terminal installer as a best-effort host setup step so
all workBenches checkouts get the same desktop shortcuts. The installer comes
from opensoft/Install-Wave-Terminal; setup prefers a sibling
../Install-Wave-Terminal checkout when present, then falls back to cloning it
into ~/.cache/workbenches/Install-Wave-Terminal.
Installed widgets include:
| Widget | Behavior |
|---|---|
terminal |
Overrides Wave's built-in terminal to open wsl://Ubuntu-24.04 instead of PowerShell |
projects |
Opens the Wave files view at $HOME/projects on the WSL connection |
pyBench |
Starts or repairs py-bench, then opens an interactive shell |
flutterBench |
Starts or repairs flutter-bench, then opens an interactive shell |
C++Bench |
Starts or repairs cpp-bench, then opens an interactive shell |
rustBench |
Starts or repairs rust-bench, then opens an interactive shell |
cloudBench |
Starts or repairs cloud-bench, then opens an interactive shell |
Opening a widget never recreates an already-running bench when mount
requirements drift. The launcher warns and preserves the live container. Use
scripts/wave-container-shell.sh --repair <bench> only when it is safe to
recreate that container; stopped containers with missing mounts are repaired
automatically.
First-run setup offers consent-based work and personal AI profile onboarding, including GitHub credential-registry discovery and a local manual fallback. See Shared AI provider profiles. Interactive profile setup asks whether AI tokens or profile credentials are in a vault and supports selecting Azure Key Vault, Bitwarden/Vaultwarden, and 1Password. Recovery uses temporary containers and approved mappings; see Credential recovery for supported login methods.
For common and per-option credential requirements, password-manager integrations
and the broader recovery roadmap, see
Credentials for installation and recovery.
Preview selected requirements without reading secrets:
python3 scripts/plan-setup-credentials.py --option dotNetBench --option codex_cli.
Multi-account Claude details remain in
Claude multi-account profiles.
OpenCode users who switch between OpenAI ChatGPT accounts while retaining the
same project sessions should read
OpenCode multi-account OpenAI profiles.
The cross-provider ownership and composition model is documented in
AI credential ownership and profile composition.
The WSL connection defaults to wsl://Ubuntu-24.04 and the projects widget
defaults to $HOME/projects. Override them with WAVE_WSL_CONNECTION and
WAVE_PROJECTS_ROOT. Widget font size defaults to 16; override it with
WAVE_WIDGET_FONT_SIZE. Set WORKBENCHES_SKIP_WAVE_WIDGETS=1 to skip this
step.
| State | Action |
|---|---|
| Installed images/container | Space selects an update; leaving it unchecked keeps it |
| Base bench image only, missing user runtime | Shows image only; Space completes setup, D removes the cached image |
| Checkout only, missing runtime | Shows needs setup; Space runs bench setup |
| Not installed | Space selects cloning and installation |
| Selected uninstall | D removes the selected runtime and verifies its absence |
| Docker inventory unavailable | Shows needs docker; install/removal selections verify Docker before applying |
| Different checkout/runtime ownership | Shows needs check; restore the expected checkout and refresh |
Run ./setup.sh again to manage installed components. Use Space to select
or undo an install/update, D to select or undo an uninstall, R to
refresh the installed state, Enter to apply, and Q to cancel.
Bench uninstall stops/removes only the selected bench's containers and removes
its latest and current-user image tags. The checkout, local work, mounted
projects, credentials, volumes, and shared base images remain available.
The source checkout then shows needs setup and can be installed again.
Host-tool removal uses the recognized native, npm, uv, Linux package, or Windows WinGet installation method. It preserves account/profile data and verifies that the tool is gone. An unknown installation or failed removal reports a failure with an actionable message. Saved terminal settings alone are not evidence that the terminal application is installed. Setup verifies required Docker access before selection, including host-only removal; removal does not install/update Node.js.
Shell setup, Org workspace, and AI accounts are configuration actions; they can be configured again without deleting shell settings, workspaces, or credentials.
workBenches/
├── setup.sh ← Main entry point
├── base-image/ ← Layer 0: workbench-base Dockerfile
├── user-layer/ ← Layer 3: User personalization Dockerfile
├── config/
│ └── bench-config.json ← Bench registry (URLs, paths, descriptions)
├── scripts/
│ ├── interactive-setup.sh ← Bash TUI for bench/tool selection
│ ├── ensure-layer3.sh ← Build Layer 3 user image if needed
│ ├── setup-vpn.sh ← VPN client checks and 0dcloud MTU patch
│ ├── setup-shell.sh ← Shell environment (zsh, p10k, plugins)
│ └── setup-ui/ ← OpenTUI TypeScript TUI (disabled, needs Bun upgrade)
├── devBenches/
│ ├── base-image/ ← Layer 1a: dev-bench-base Dockerfile
│ ├── cppBench/ ← C++ bench (opensoft/cppBench)
│ ├── dotNetBench/ ← .NET bench (opensoft/dotNetBench)
│ ├── flutterBench/ ← Flutter bench (opensoft/flutterBench)
│ ├── frappeBench/ ← Frappe/ERPNext bench (opensoft/frappeBench)
│ ├── goBench/ ← Go bench (opensoft/goBench)
│ ├── javaBench/ ← Java bench (opensoft/javaBench)
│ ├── phpBench/ ← PHP bench (opensoft/phpBench)
│ └── pyBench/ ← Python bench (opensoft/pyBench)
├── sysBenches/
│ ├── base-image/ ← Layer 1b: sys-bench-base Dockerfile
│ ├── cloudBench/ ← Cloud admin bench (opensoft/cloudBench)
│ └── opsBench/ ← Ops bench (deployment, CI/CD, security)
├── bioBenches/
│ ├── base-image/ ← Layer 1c: bio-bench-base Dockerfile
│ ├── gentecBench/ ← Genetics/genomics bench (opensoft/gentecBench)
│ └── simBench/ ← Molecular simulation bench (opensoft/simBench)
├── logs/ ← Setup logs (gitignored)
└── docs/
├── amnezia-vpn-architecture.md
├── setup-input-troubleshooting.md
└── vpn-setup.md
setup.sh offers VPN setup from the TUI Tools column. Users can select
AmneziaVPN and 0dcloud VPN independently; selecting 0dcloud also patches
the 0dcloud TUN MTU/GSO settings to 1400 to avoid large Git pack transfer
stalls on routed hotel/VPN networks.
See docs/vpn-setup.md for manual install steps, 0dcloud routing guidance, and
troubleshooting commands.
See docs/opensoft-aks-prod-test-plan.md for the AKS production-candidate test
plan, including the current PlanA1 node-pool shape, costs, validation findings,
and build/test/destroy loop. See docs/nopcommerce-aks-install-research.md for
the nopCommerce-on-AKS install research, including SQL connectivity, Redis, Blob
storage, and disk strategy. See docs/opensoft-nopcommerce-dr-runbook.md for
the cross-tenant disaster-recovery test plan, and
docs/opensoft-nopcommerce-backup-system-design.md for the backup system that
feeds that restore.
Benches are registered in config/bench-config.json:
{
"benches": {
"flutterBench": {
"url": "git@github.com:opensoft/flutterBench.git",
"path": "devBenches/flutterBench",
"description": "Flutter/Dart development environment and tools"
}
}
}Each bench repo typically contains:
Dockerfile.layer2— Bench-specific Docker imagesetup.sh— Setup script (builds image, starts container)scripts/build-layer.shorbuild-layer.sh— Full bench build (Layer 2 + Layer 3)scripts/build-layer2.shorbuild-layer2.sh— Layer 2 only.devcontainer/ordevcontainer.example/— VS Code devcontainer config
Installed and updated via the setup TUI:
| Tool | Install Method | Auth |
|---|---|---|
| Claude Code CLI | Native installer | claude login |
| GitHub Copilot CLI | npm | copilot auth login |
| OpenAI Codex CLI | npm | OPENAI_API_KEY, codex login, or isolated pcodex PROFILE logins |
| Google Gemini CLI | npm | Google login or isolated pgemini PROFILE login |
| Grok Build | Native installer | Isolated pgrok PROFILE login |
| OpenCode CLI with Z.AI GLM | Manual | Isolated pglm PROFILE Z.AI Coding Plan key |
| spec-kit | uv (pip) | None |
| OpenSpec | npm | None |
npm global packages install to ~/.npm-global (no sudo required).
The TUI Tools column includes editor, terminal, and local agent tooling:
| Tool | Install Method | Notes |
|---|---|---|
| Visual Studio Code | Windows/WSL winget, Linux/manual fallback | Dev Containers and WSL extension checks |
| Warp Terminal | Windows/WSL winget, Linux/manual fallback | Windows terminal |
| Wave Terminal | Windows/WSL winget, Linux/manual fallback | AI terminal |
| Pi Terminal | Windows and WSL/Linux npm | npm install -g --ignore-scripts @earendil-works/pi-coding-agent; use isolated ppi PROFILE or standard pi |
| AmneziaVPN | Windows/WSL winget | Amnezia/AmneziaWG client access |
| 0dcloud VPN | local installer/manual + local patch | 0dcloud detection and MTU fix |
On a Windows workstation running setup from WSL, the TUI calls
scripts/setup-windows-tools.sh so Windows apps are installed into Windows
rather than into the Linux distro.
The shared host-side Amnezia endpoint wrapper lives at
scripts/amnezia-endpoint. It fetches the CloudBench-published endpoint
manifest, keeps host-local state under ~/.workbenches/amnezia-endpoint/,
selects usable VPN endpoints, and can patch exported WireGuard/Amnezia-style
configs.
scripts/amnezia-endpoint list
scripts/amnezia-endpoint select --strategy round-robin --format env
scripts/amnezia-endpoint patch --config ~/vpn/amnezia.confSee docs/amnezia-endpoint-wrapper.md for the full workflow.
For GL.iNet/LuCI router setup, see docs/glinet-luci-amnezia-router.md.
Server-side Amnezia rebuild and operations docs are owned by the cloudBench submodule:
sysBenches/cloudBench/docs/amnezia-server-rebuild.md
sysBenches/cloudBench/docs/amnezia-server-runbook.md
- Logs written to
logs/setup-YYYYMMDD-HHMMSS.log - Section headers:
[SHELL SETUP],[DOCKER CHECK],[LAYER 0 BUILD],[INTERACTIVE SETUP],[LAYER 1 BUILDS] - Last 10 logs kept, older auto-cleaned
interactive-setup.shwrites its own detailed log with per-bench status
- frappeBench: Requires Node.js 20 (not 24). Dockerfile.layer2 pins it via nodesource. Uses
COREPACK_HOME=/tmp/corepackduring build to avoid permission errors. - OpenTUI: TypeScript TUI (
scripts/setup-ui/) disabled due to Bun 1.3.5 compatibility and keyboard bugs. Bash TUI used instead. Seedocs/setup-input-troubleshooting.md. - WSL Enter key: Bash TUI handles
\r,\n, and empty string for Enter detection.
| Bench | Repository |
|---|---|
| workBenches (this repo) | opensoft/workBenches |
| cloudBench | opensoft/cloudBench |
| cppBench | opensoft/cppBench |
| dotNetBench | opensoft/dotNetBench |
| flutterBench | opensoft/flutterBench |
| frappeBench | opensoft/frappeBench |
| goBench | opensoft/goBench |
| javaBench | opensoft/javaBench |
| phpBench | opensoft/phpBench |
| pyBench | opensoft/pyBench |
| gentecBench | opensoft/gentecBench |
| simBench | opensoft/simBench |
New Compose benches are created with the shared Wave mounts and must pass an ordinary launch check before setup reports them ready. Existing running benches are preserved; stop them before applying setup changes or use Wave's explicit repair command when appropriate.
Select AI accounts to open account setup after installation. At the authentication route prompt, use 2B for Bitwarden, 2V for Vaultwarden,
2P for 1Password, or 2A for Azure Key Vault. The compact password-manager flow
uses editable email defaults and infers unambiguous credential formats. Item and
destination confirmation remain explicit. Choose 2 for advanced imports,
multiple vaults, and automation authentication.
Shared base images are reused only when their source fingerprint, platform, and
parent image match. Otherwise setup tries a public release manifest with pinned
image digests, then builds locally if the matching release is unavailable.
Set WORKBENCHES_BUILD_LOCAL=1 to force local builds. Build spinners show elapsed
time and print the command to follow their log in another terminal.
Maintainers publish the first system/developer images by running Shared
workstation images with workflow_dispatch. New GHCR packages must be set to
public at their package settings. The workflow checks anonymous access before
publishing its immutable shared-images-… release manifest; a private package
cannot become the default download path. The initial release targets
linux/amd64; other platforms retain local builds. Publishing never includes
personalized Layer 3 or workstation credentials.