From edfc3878b48e245607de32ed8a962c29472afcb2 Mon Sep 17 00:00:00 2001 From: gabemeola <14303404+gabemeola@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:17:29 +0000 Subject: [PATCH 1/9] feat: migrate from brew to zerobrew mise backend - Install zerobrew v0.3.2 as a faster Homebrew alternative - Replace woutermont/mise-brew plugin with kennyg/mise-zerobrew - Switch all pre-approved tools from brew: to zerobrew: prefix - Add zerobrew binaries and data to final image - Update PATH with zerobrew prefix bin directory - Update README references --- Dockerfile | 18 ++++++++++++++---- README.md | 28 ++++++++++++++-------------- mise-config.toml | 22 +++++++++++----------- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/Dockerfile b/Dockerfile index c99b617..d7dab25 100644 --- a/Dockerfile +++ b/Dockerfile @@ -63,10 +63,15 @@ RUN mkdir -p /home/linuxbrew \ && rm -rf /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core # 1.5. mise — dev tool manager; pre-approved tools defined in the global config -# auto-install via Homebrew backend on first use at runtime. +# auto-install via zerobrew backend on first use at runtime. RUN curl -fsSL https://mise.run | MISE_INSTALL_PATH=/usr/local/bin/mise sh \ && mkdir -p /opt/mise \ - && MISE_DATA_DIR=/opt/mise mise plugins install brew https://github.com/woutermont/mise-brew + && MISE_DATA_DIR=/opt/mise mise plugins install zerobrew https://github.com/kennyg/mise-zerobrew + +# 1.6. zerobrew — fast Homebrew alternative; used as mise backend +RUN sudo -u opencode HOME=/home/opencode NONINTERACTIVE=1 /bin/bash -c " \ + curl -fsSL https://zerobrew.rs/install | bash -s -- --no-modify-path \ +" ARG OPENCODE_VERSION @@ -85,7 +90,7 @@ FROM base ARG OPENCODE_VERSION ARG IMAGE_CREATED -ENV PATH=/home/opencode/.local/bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/opt/auto-install-shims:${PATH} +ENV PATH=/home/opencode/.local/bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/home/opencode/.local/share/zerobrew/prefix/bin:/opt/auto-install-shims:${PATH} ENV HOMEBREW_NO_AUTO_UPDATE=1 ENV HOMEBREW_INSTALL_FROM_API=1 ENV MISE_DATA_DIR=/opt/mise @@ -114,9 +119,14 @@ COPY --from=builder /usr/local/bin/mise /usr/local/bin/mise COPY --from=builder --chown=opencode:opencode /opt/mise /opt/mise COPY mise-config.toml /etc/mise/config.toml +# Zerobrew — fast Homebrew alternative; mise zerobrew backend. +COPY --from=builder /home/opencode/.local/bin/zb /usr/local/bin/zb +COPY --from=builder /home/opencode/.local/bin/zbx /usr/local/bin/zbx +COPY --from=builder --chown=opencode:opencode /home/opencode/.local/share/zerobrew /home/opencode/.local/share/zerobrew + # Verify runtime and set up login-shell PATH and auto-install handler RUN opencode --version \ - && printf 'for d in "$HOME/.local/bin" "/home/linuxbrew/.linuxbrew/bin" "/home/linuxbrew/.linuxbrew/sbin"; do case ":$PATH:" in *":$d:"*) ;; *) PATH="$d:$PATH";; esac; done\nexport PATH\n' > /etc/profile.d/brew-path.sh \ + && printf 'for d in "$HOME/.local/bin" "/home/linuxbrew/.linuxbrew/bin" "/home/linuxbrew/.linuxbrew/sbin" "$HOME/.local/share/zerobrew/prefix/bin"; do case ":$PATH:" in *":$d:"*) ;; *) PATH="$d:$PATH";; esac; done\nexport PATH\n' > /etc/profile.d/brew-path.sh \ && chmod 0644 /etc/profile.d/brew-path.sh \ && printf '\neval "$(mise activate bash)"\n' >> /home/opencode/.bashrc \ && printf '\neval "$(mise activate zsh)"\n' >> /home/opencode/.zshrc \ diff --git a/README.md b/README.md index ccecad6..1383ef4 100644 --- a/README.md +++ b/README.md @@ -17,27 +17,27 @@ A general-purpose Ubuntu Docker image for running [opencode](https://github.com/ | **Build tools** | `build-essential`, `pkg-config` (for native npm addons, pip source builds) | | **Python 3** | Lazy-installed via mise (see table below) | | **Homebrew** | Linux-native Homebrew (`/home/linuxbrew/.linuxbrew`) — `brew` on PATH | -| **mise** | Dev tool manager — tools listed below install on first use via `brew` backend | +| **mise** | Dev tool manager — tools listed below install on first use via `zerobrew` backend | | **CLI utilities** | git, curl, jq, less, unzip, ssh client | | **Init** | tini as PID 1 (zombie reaping, clean shutdown) | ### Lazy-installed tools -These tools install on first use (via mise → Homebrew): +These tools install on first use (via mise → zerobrew): | Tool | Command | Backend | |---|---|---| -| GitHub CLI | `gh` | brew | -| GitLab CLI | `glab` | brew | -| Ruby | `ruby` | brew | -| ripgrep | `rg` | brew | -| fd | `fd` | brew | -| Wget | `wget` | brew | -| Vim | `vim` | brew | -| Micro | `micro` | brew | -| Nano | `nano` | brew | -| Python 3 | `python3` | brew | -| Node.js | `node` | brew | +| GitHub CLI | `gh` | zerobrew | +| GitLab CLI | `glab` | zerobrew | +| Ruby | `ruby` | zerobrew | +| ripgrep | `rg` | zerobrew | +| fd | `fd` | zerobrew | +| Wget | `wget` | zerobrew | +| Vim | `vim` | zerobrew | +| Micro | `micro` | zerobrew | +| Nano | `nano` | zerobrew | +| Python 3 | `python3` | zerobrew | +| Node.js | `node` | zerobrew | The image ships with a system config at `/etc/mise/config.toml` with these pre-approved tools. Users can add or override tools by creating `~/.config/mise/config.toml` — mise merges both. @@ -109,4 +109,4 @@ Fetches the latest release from [anomalyco/opencode](https://github.com/anomalyc - `~/.local/bin` is on PATH and user-writable, useful for dropping custom tools at runtime. - Node version can be switched at runtime with `n ` (e.g. `n lts`). - Homebrew is installed under `/home/linuxbrew/.linuxbrew` (outside the persistent volume). It uses its bundled portable Ruby — no system Ruby needed. -- **Lazy-installed tools** (see table above): run any listed tool and mise auto-installs it via Homebrew on first use. The image ships defaults in `/etc/mise/config.toml`; create `~/.config/mise/config.toml` to add your own — mise merges both. +- **Lazy-installed tools** (see table above): run any listed tool and mise auto-installs it via zerobrew on first use. The image ships defaults in `/etc/mise/config.toml`; create `~/.config/mise/config.toml` to add your own — mise merges both. diff --git a/mise-config.toml b/mise-config.toml index 356b97e..b176497 100644 --- a/mise-config.toml +++ b/mise-config.toml @@ -1,12 +1,12 @@ [tools] -"brew:gh" = "latest" -"brew:glab" = "latest" -"brew:ruby" = "latest" -"brew:ripgrep" = "latest" -"brew:fd" = "latest" -"brew:wget" = "latest" -"brew:vim" = "latest" -"brew:micro" = "latest" -"brew:nano" = "latest" -"brew:python" = "latest" -"brew:node" = "latest" +"zerobrew:gh" = "latest" +"zerobrew:glab" = "latest" +"zerobrew:ruby" = "latest" +"zerobrew:ripgrep" = "latest" +"zerobrew:fd" = "latest" +"zerobrew:wget" = "latest" +"zerobrew:vim" = "latest" +"zerobrew:micro" = "latest" +"zerobrew:nano" = "latest" +"zerobrew:python" = "latest" +"zerobrew:node" = "latest" From 17f89a8fd273700cdd667aa11d2d119c3cb1e0a4 Mon Sep 17 00:00:00 2001 From: gabemeola <14303404+gabemeola@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:22:36 +0000 Subject: [PATCH 2/9] docs: add zerobrew to installed tool list in README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 1383ef4..98f552a 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ A general-purpose Ubuntu Docker image for running [opencode](https://github.com/ | **Build tools** | `build-essential`, `pkg-config` (for native npm addons, pip source builds) | | **Python 3** | Lazy-installed via mise (see table below) | | **Homebrew** | Linux-native Homebrew (`/home/linuxbrew/.linuxbrew`) — `brew` on PATH | +| **zerobrew** | Faster Homebrew alternative (`zb` on PATH) -- used as mise backend for lazy-installed tools | | **mise** | Dev tool manager — tools listed below install on first use via `zerobrew` backend | | **CLI utilities** | git, curl, jq, less, unzip, ssh client | | **Init** | tini as PID 1 (zombie reaping, clean shutdown) | @@ -109,4 +110,5 @@ Fetches the latest release from [anomalyco/opencode](https://github.com/anomalyc - `~/.local/bin` is on PATH and user-writable, useful for dropping custom tools at runtime. - Node version can be switched at runtime with `n ` (e.g. `n lts`). - Homebrew is installed under `/home/linuxbrew/.linuxbrew` (outside the persistent volume). It uses its bundled portable Ruby — no system Ruby needed. +- Zerobrew (`zb`) is installed at `/usr/local/bin/zb` with its prefix at `~/.local/share/zerobrew/prefix` on PATH for accessing formula binaries. - **Lazy-installed tools** (see table above): run any listed tool and mise auto-installs it via zerobrew on first use. The image ships defaults in `/etc/mise/config.toml`; create `~/.config/mise/config.toml` to add your own — mise merges both. From 678edeed05bf30a09a61383cd4041e681029edb7 Mon Sep 17 00:00:00 2001 From: gabemeola <14303404+gabemeola@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:29:39 +0000 Subject: [PATCH 3/9] fix: initialize zerobrew root before install in mise plugin The mise zerobrew plugin calls zb --root install on an uninitialized root, causing 'store corruption: Initialization required'. Add zb init before install to ensure the root is ready. --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d7dab25..7ac0f15 100644 --- a/Dockerfile +++ b/Dockerfile @@ -66,7 +66,8 @@ RUN mkdir -p /home/linuxbrew \ # auto-install via zerobrew backend on first use at runtime. RUN curl -fsSL https://mise.run | MISE_INSTALL_PATH=/usr/local/bin/mise sh \ && mkdir -p /opt/mise \ - && MISE_DATA_DIR=/opt/mise mise plugins install zerobrew https://github.com/kennyg/mise-zerobrew + && MISE_DATA_DIR=/opt/mise mise plugins install zerobrew https://github.com/kennyg/mise-zerobrew \ + && sed -i '/quoted_path .. " install /i\ cmd.exec(quoted_zb .. " --root " .. quoted_path .. " init")' /opt/mise/plugins/zerobrew/hooks/backend_install.lua # 1.6. zerobrew — fast Homebrew alternative; used as mise backend RUN sudo -u opencode HOME=/home/opencode NONINTERACTIVE=1 /bin/bash -c " \ From 5eaf6fa94dcc229f523ffa4e5579b8aa03d88696 Mon Sep 17 00:00:00 2001 From: gabemeola <14303404+gabemeola@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:52:24 +0000 Subject: [PATCH 4/9] feat: add sapling (sl) to pre-approved tools --- README.md | 1 + mise-config.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 98f552a..4bd2c1a 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ These tools install on first use (via mise → zerobrew): | Nano | `nano` | zerobrew | | Python 3 | `python3` | zerobrew | | Node.js | `node` | zerobrew | +| Sapling | `sl` | zerobrew | The image ships with a system config at `/etc/mise/config.toml` with these pre-approved tools. Users can add or override tools by creating `~/.config/mise/config.toml` — mise merges both. diff --git a/mise-config.toml b/mise-config.toml index b176497..8890bbf 100644 --- a/mise-config.toml +++ b/mise-config.toml @@ -10,3 +10,4 @@ "zerobrew:nano" = "latest" "zerobrew:python" = "latest" "zerobrew:node" = "latest" +"zerobrew:sapling" = "latest" From df7a3e632f38a1be427d97fbc27a85568dfbd30a Mon Sep 17 00:00:00 2001 From: gabemeola <14303404+gabemeola@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:56:31 +0000 Subject: [PATCH 5/9] feat: replace sapling mise entry with prebuilt binary zerobrew's sapling bottle has a broken Python stdlib path. Install the official Facebook prebuilt release at /opt/sapling instead. --- Dockerfile | 14 ++++++++++++-- README.md | 3 ++- mise-config.toml | 1 - 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7ac0f15..af629b0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -74,6 +74,13 @@ RUN sudo -u opencode HOME=/home/opencode NONINTERACTIVE=1 /bin/bash -c " \ curl -fsSL https://zerobrew.rs/install | bash -s -- --no-modify-path \ " +# 1.7. sapling (sl) — prebuilt binary (zerobrew bottle has broken Python stdlib) +RUN arch="$(uname -m | sed 's/x86_64/x64/;s/aarch64/arm64/')" \ + && version="0.2.20260522-084851+1e764c94" \ + && mkdir -p /opt/sapling \ + && curl -fsSL "https://github.com/facebook/sapling/releases/download/${version}/sapling-${version}-linux-${arch}.tar.xz" \ + | tar xJf - -C /opt/sapling --strip-components=1 + ARG OPENCODE_VERSION # 2. opencode server binary — changes on every version bump (most frequent) @@ -91,7 +98,7 @@ FROM base ARG OPENCODE_VERSION ARG IMAGE_CREATED -ENV PATH=/home/opencode/.local/bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/home/opencode/.local/share/zerobrew/prefix/bin:/opt/auto-install-shims:${PATH} +ENV PATH=/opt/sapling:/home/opencode/.local/bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/home/opencode/.local/share/zerobrew/prefix/bin:/opt/auto-install-shims:${PATH} ENV HOMEBREW_NO_AUTO_UPDATE=1 ENV HOMEBREW_INSTALL_FROM_API=1 ENV MISE_DATA_DIR=/opt/mise @@ -125,9 +132,12 @@ COPY --from=builder /home/opencode/.local/bin/zb /usr/local/bin/zb COPY --from=builder /home/opencode/.local/bin/zbx /usr/local/bin/zbx COPY --from=builder --chown=opencode:opencode /home/opencode/.local/share/zerobrew /home/opencode/.local/share/zerobrew +# Sapling (sl) — prebuilt binary from Facebook Releases. +COPY --from=builder /opt/sapling /opt/sapling + # Verify runtime and set up login-shell PATH and auto-install handler RUN opencode --version \ - && printf 'for d in "$HOME/.local/bin" "/home/linuxbrew/.linuxbrew/bin" "/home/linuxbrew/.linuxbrew/sbin" "$HOME/.local/share/zerobrew/prefix/bin"; do case ":$PATH:" in *":$d:"*) ;; *) PATH="$d:$PATH";; esac; done\nexport PATH\n' > /etc/profile.d/brew-path.sh \ + && printf 'for d in "/opt/sapling" "$HOME/.local/bin" "/home/linuxbrew/.linuxbrew/bin" "/home/linuxbrew/.linuxbrew/sbin" "$HOME/.local/share/zerobrew/prefix/bin"; do case ":$PATH:" in *":$d:"*) ;; *) PATH="$d:$PATH";; esac; done\nexport PATH\n' > /etc/profile.d/brew-path.sh \ && chmod 0644 /etc/profile.d/brew-path.sh \ && printf '\neval "$(mise activate bash)"\n' >> /home/opencode/.bashrc \ && printf '\neval "$(mise activate zsh)"\n' >> /home/opencode/.zshrc \ diff --git a/README.md b/README.md index 4bd2c1a..5a981e8 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ A general-purpose Ubuntu Docker image for running [opencode](https://github.com/ | **zerobrew** | Faster Homebrew alternative (`zb` on PATH) -- used as mise backend for lazy-installed tools | | **mise** | Dev tool manager — tools listed below install on first use via `zerobrew` backend | | **CLI utilities** | git, curl, jq, less, unzip, ssh client | +| **Sapling** | Prebuilt `sl` binary from Facebook Releases at `/opt/sapling` | | **Init** | tini as PID 1 (zombie reaping, clean shutdown) | ### Lazy-installed tools @@ -39,7 +40,6 @@ These tools install on first use (via mise → zerobrew): | Nano | `nano` | zerobrew | | Python 3 | `python3` | zerobrew | | Node.js | `node` | zerobrew | -| Sapling | `sl` | zerobrew | The image ships with a system config at `/etc/mise/config.toml` with these pre-approved tools. Users can add or override tools by creating `~/.config/mise/config.toml` — mise merges both. @@ -112,4 +112,5 @@ Fetches the latest release from [anomalyco/opencode](https://github.com/anomalyc - Node version can be switched at runtime with `n ` (e.g. `n lts`). - Homebrew is installed under `/home/linuxbrew/.linuxbrew` (outside the persistent volume). It uses its bundled portable Ruby — no system Ruby needed. - Zerobrew (`zb`) is installed at `/usr/local/bin/zb` with its prefix at `~/.local/share/zerobrew/prefix` on PATH for accessing formula binaries. +- Sapling (`sl`) is installed at `/opt/sapling` from the official Facebook prebuilt release. - **Lazy-installed tools** (see table above): run any listed tool and mise auto-installs it via zerobrew on first use. The image ships defaults in `/etc/mise/config.toml`; create `~/.config/mise/config.toml` to add your own — mise merges both. diff --git a/mise-config.toml b/mise-config.toml index 8890bbf..b176497 100644 --- a/mise-config.toml +++ b/mise-config.toml @@ -10,4 +10,3 @@ "zerobrew:nano" = "latest" "zerobrew:python" = "latest" "zerobrew:node" = "latest" -"zerobrew:sapling" = "latest" From 4266e71e682df82b9ce0b842d73dae6acb1f3a4d Mon Sep 17 00:00:00 2001 From: gabemeola <14303404+gabemeola@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:58:48 +0000 Subject: [PATCH 6/9] revert: remove prebuilt sapling, use mise github: backend instead --- Dockerfile | 14 ++------------ README.md | 7 +++---- mise-config.toml | 1 + 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/Dockerfile b/Dockerfile index af629b0..7ac0f15 100644 --- a/Dockerfile +++ b/Dockerfile @@ -74,13 +74,6 @@ RUN sudo -u opencode HOME=/home/opencode NONINTERACTIVE=1 /bin/bash -c " \ curl -fsSL https://zerobrew.rs/install | bash -s -- --no-modify-path \ " -# 1.7. sapling (sl) — prebuilt binary (zerobrew bottle has broken Python stdlib) -RUN arch="$(uname -m | sed 's/x86_64/x64/;s/aarch64/arm64/')" \ - && version="0.2.20260522-084851+1e764c94" \ - && mkdir -p /opt/sapling \ - && curl -fsSL "https://github.com/facebook/sapling/releases/download/${version}/sapling-${version}-linux-${arch}.tar.xz" \ - | tar xJf - -C /opt/sapling --strip-components=1 - ARG OPENCODE_VERSION # 2. opencode server binary — changes on every version bump (most frequent) @@ -98,7 +91,7 @@ FROM base ARG OPENCODE_VERSION ARG IMAGE_CREATED -ENV PATH=/opt/sapling:/home/opencode/.local/bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/home/opencode/.local/share/zerobrew/prefix/bin:/opt/auto-install-shims:${PATH} +ENV PATH=/home/opencode/.local/bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/home/opencode/.local/share/zerobrew/prefix/bin:/opt/auto-install-shims:${PATH} ENV HOMEBREW_NO_AUTO_UPDATE=1 ENV HOMEBREW_INSTALL_FROM_API=1 ENV MISE_DATA_DIR=/opt/mise @@ -132,12 +125,9 @@ COPY --from=builder /home/opencode/.local/bin/zb /usr/local/bin/zb COPY --from=builder /home/opencode/.local/bin/zbx /usr/local/bin/zbx COPY --from=builder --chown=opencode:opencode /home/opencode/.local/share/zerobrew /home/opencode/.local/share/zerobrew -# Sapling (sl) — prebuilt binary from Facebook Releases. -COPY --from=builder /opt/sapling /opt/sapling - # Verify runtime and set up login-shell PATH and auto-install handler RUN opencode --version \ - && printf 'for d in "/opt/sapling" "$HOME/.local/bin" "/home/linuxbrew/.linuxbrew/bin" "/home/linuxbrew/.linuxbrew/sbin" "$HOME/.local/share/zerobrew/prefix/bin"; do case ":$PATH:" in *":$d:"*) ;; *) PATH="$d:$PATH";; esac; done\nexport PATH\n' > /etc/profile.d/brew-path.sh \ + && printf 'for d in "$HOME/.local/bin" "/home/linuxbrew/.linuxbrew/bin" "/home/linuxbrew/.linuxbrew/sbin" "$HOME/.local/share/zerobrew/prefix/bin"; do case ":$PATH:" in *":$d:"*) ;; *) PATH="$d:$PATH";; esac; done\nexport PATH\n' > /etc/profile.d/brew-path.sh \ && chmod 0644 /etc/profile.d/brew-path.sh \ && printf '\neval "$(mise activate bash)"\n' >> /home/opencode/.bashrc \ && printf '\neval "$(mise activate zsh)"\n' >> /home/opencode/.zshrc \ diff --git a/README.md b/README.md index 5a981e8..94934e0 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,11 @@ A general-purpose Ubuntu Docker image for running [opencode](https://github.com/ | **zerobrew** | Faster Homebrew alternative (`zb` on PATH) -- used as mise backend for lazy-installed tools | | **mise** | Dev tool manager — tools listed below install on first use via `zerobrew` backend | | **CLI utilities** | git, curl, jq, less, unzip, ssh client | -| **Sapling** | Prebuilt `sl` binary from Facebook Releases at `/opt/sapling` | | **Init** | tini as PID 1 (zombie reaping, clean shutdown) | ### Lazy-installed tools -These tools install on first use (via mise → zerobrew): +These tools install on first use (via mise → github/zerobrew): | Tool | Command | Backend | |---|---|---| @@ -40,6 +39,7 @@ These tools install on first use (via mise → zerobrew): | Nano | `nano` | zerobrew | | Python 3 | `python3` | zerobrew | | Node.js | `node` | zerobrew | +| Sapling | `sl` | github | The image ships with a system config at `/etc/mise/config.toml` with these pre-approved tools. Users can add or override tools by creating `~/.config/mise/config.toml` — mise merges both. @@ -112,5 +112,4 @@ Fetches the latest release from [anomalyco/opencode](https://github.com/anomalyc - Node version can be switched at runtime with `n ` (e.g. `n lts`). - Homebrew is installed under `/home/linuxbrew/.linuxbrew` (outside the persistent volume). It uses its bundled portable Ruby — no system Ruby needed. - Zerobrew (`zb`) is installed at `/usr/local/bin/zb` with its prefix at `~/.local/share/zerobrew/prefix` on PATH for accessing formula binaries. -- Sapling (`sl`) is installed at `/opt/sapling` from the official Facebook prebuilt release. -- **Lazy-installed tools** (see table above): run any listed tool and mise auto-installs it via zerobrew on first use. The image ships defaults in `/etc/mise/config.toml`; create `~/.config/mise/config.toml` to add your own — mise merges both. +- **Lazy-installed tools** (see table above): run any listed tool and mise auto-installs it via zerobrew or github backend on first use. The image ships defaults in `/etc/mise/config.toml`; create `~/.config/mise/config.toml` to add your own — mise merges both. diff --git a/mise-config.toml b/mise-config.toml index b176497..40218ac 100644 --- a/mise-config.toml +++ b/mise-config.toml @@ -10,3 +10,4 @@ "zerobrew:nano" = "latest" "zerobrew:python" = "latest" "zerobrew:node" = "latest" +"github:facebook/sapling" = "latest" From 026fd224cf5b0206ac77cefff825d28db2793636 Mon Sep 17 00:00:00 2001 From: gabemeola <14303404+gabemeola@users.noreply.github.com> Date: Thu, 2 Jul 2026 17:02:29 +0000 Subject: [PATCH 7/9] fix: switch gh/rg/fd/micro/node to github: backend, fix shim generator - Move 5 tools (gh, ripgrep, fd, micro, node) from zerobrew: to github: - Fix shim generator grep to only match zerobrew: entries, avoiding broken shim paths for github:owner/repo keys - Update README backend column --- Dockerfile | 2 +- README.md | 10 +++++----- mise-config.toml | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7ac0f15..2f37bbb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -135,7 +135,7 @@ RUN opencode --version \ && printf '\nmise activate fish | source\n' >> /home/opencode/.config/fish/config.fish \ && printf '\neval "$(mise activate sh)"\n' >> /home/opencode/.profile \ && mkdir -p /opt/auto-install-shims \ - && grep -E '^\s*"' /etc/mise/config.toml | while IFS='=' read -r key value; do \ + && grep -E '^\s*"zerobrew:' /etc/mise/config.toml | while IFS='=' read -r key value; do \ key="$(echo "$key" | tr -d ' "')" \ && shim="${key#*:}" \ && printf '#!/usr/bin/env bash\nexec /usr/local/bin/mise exec "%s" -- %s "$@"\n' "$key" "$shim" > "/opt/auto-install-shims/$shim" \ diff --git a/README.md b/README.md index 94934e0..88739d5 100644 --- a/README.md +++ b/README.md @@ -28,17 +28,17 @@ These tools install on first use (via mise → github/zerobrew): | Tool | Command | Backend | |---|---|---| -| GitHub CLI | `gh` | zerobrew | +| GitHub CLI | `gh` | github | | GitLab CLI | `glab` | zerobrew | | Ruby | `ruby` | zerobrew | -| ripgrep | `rg` | zerobrew | -| fd | `fd` | zerobrew | +| ripgrep | `rg` | github | +| fd | `fd` | github | | Wget | `wget` | zerobrew | | Vim | `vim` | zerobrew | -| Micro | `micro` | zerobrew | +| Micro | `micro` | github | | Nano | `nano` | zerobrew | | Python 3 | `python3` | zerobrew | -| Node.js | `node` | zerobrew | +| Node.js | `node` | github | | Sapling | `sl` | github | The image ships with a system config at `/etc/mise/config.toml` with these pre-approved tools. Users can add or override tools by creating `~/.config/mise/config.toml` — mise merges both. diff --git a/mise-config.toml b/mise-config.toml index 40218ac..a3e2db8 100644 --- a/mise-config.toml +++ b/mise-config.toml @@ -1,13 +1,13 @@ [tools] -"zerobrew:gh" = "latest" +"github:cli/cli" = "latest" "zerobrew:glab" = "latest" "zerobrew:ruby" = "latest" -"zerobrew:ripgrep" = "latest" -"zerobrew:fd" = "latest" +"github:BurntSushi/ripgrep" = "latest" +"github:sharkdp/fd" = "latest" "zerobrew:wget" = "latest" "zerobrew:vim" = "latest" -"zerobrew:micro" = "latest" +"github:zyedidia/micro" = "latest" "zerobrew:nano" = "latest" "zerobrew:python" = "latest" -"zerobrew:node" = "latest" +"github:nodejs/node" = "latest" "github:facebook/sapling" = "latest" From 67a2b2cc88329913cb664ab6232aa1916fd5ed29 Mon Sep 17 00:00:00 2001 From: gabemeola <14303404+gabemeola@users.noreply.github.com> Date: Thu, 2 Jul 2026 17:03:42 +0000 Subject: [PATCH 8/9] fix: generate auto-install shims for all preregistered tools Handle github:owner/repo keys with explicit binary name overrides for entries where the binary differs from the repo name (gh, rg, sl). --- Dockerfile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2f37bbb..34eb6c9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -135,9 +135,15 @@ RUN opencode --version \ && printf '\nmise activate fish | source\n' >> /home/opencode/.config/fish/config.fish \ && printf '\neval "$(mise activate sh)"\n' >> /home/opencode/.profile \ && mkdir -p /opt/auto-install-shims \ - && grep -E '^\s*"zerobrew:' /etc/mise/config.toml | while IFS='=' read -r key value; do \ + && grep -E '^\s*"' /etc/mise/config.toml | while IFS='=' read -r key value; do \ key="$(echo "$key" | tr -d ' "')" \ - && shim="${key#*:}" \ + && case "$key" in \ + github:cli/cli) shim="gh" ;; \ + github:BurntSushi/ripgrep) shim="rg" ;; \ + github:facebook/sapling) shim="sl" ;; \ + github:*) shim="${key##*/}" ;; \ + *) shim="${key#*:}" ;; \ + esac \ && printf '#!/usr/bin/env bash\nexec /usr/local/bin/mise exec "%s" -- %s "$@"\n' "$key" "$shim" > "/opt/auto-install-shims/$shim" \ && chmod 0755 "/opt/auto-install-shims/$shim"; \ done \ From a0ddad964db1cf0759c6f69731e05756191a688d Mon Sep 17 00:00:00 2001 From: gabemeola <14303404+gabemeola@users.noreply.github.com> Date: Thu, 2 Jul 2026 17:05:18 +0000 Subject: [PATCH 9/9] refactor: auto-install shim names via # shim: comments in config Instead of hardcoding binary name overrides in the Dockerfile, tool entries in mise-config.toml can specify the shim name with a trailing # shim: comment. Falls back to repo name for github: entries or stripped prefix for simple backends. --- Dockerfile | 14 +++++++------- mise-config.toml | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 34eb6c9..a2f57b9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -137,13 +137,13 @@ RUN opencode --version \ && mkdir -p /opt/auto-install-shims \ && grep -E '^\s*"' /etc/mise/config.toml | while IFS='=' read -r key value; do \ key="$(echo "$key" | tr -d ' "')" \ - && case "$key" in \ - github:cli/cli) shim="gh" ;; \ - github:BurntSushi/ripgrep) shim="rg" ;; \ - github:facebook/sapling) shim="sl" ;; \ - github:*) shim="${key##*/}" ;; \ - *) shim="${key#*:}" ;; \ - esac \ + && shim="$(echo "$value" | sed -n 's/.*# shim:\([^ ]*\).*/\1/p')" \ + && if [ -z "$shim" ]; then \ + case "$key" in \ + github:*) shim="${key##*/}" ;; \ + *) shim="${key#*:}" ;; \ + esac; \ + fi \ && printf '#!/usr/bin/env bash\nexec /usr/local/bin/mise exec "%s" -- %s "$@"\n' "$key" "$shim" > "/opt/auto-install-shims/$shim" \ && chmod 0755 "/opt/auto-install-shims/$shim"; \ done \ diff --git a/mise-config.toml b/mise-config.toml index a3e2db8..646d0aa 100644 --- a/mise-config.toml +++ b/mise-config.toml @@ -1,8 +1,8 @@ [tools] -"github:cli/cli" = "latest" +"github:cli/cli" = "latest" # shim:gh "zerobrew:glab" = "latest" "zerobrew:ruby" = "latest" -"github:BurntSushi/ripgrep" = "latest" +"github:BurntSushi/ripgrep" = "latest" # shim:rg "github:sharkdp/fd" = "latest" "zerobrew:wget" = "latest" "zerobrew:vim" = "latest" @@ -10,4 +10,4 @@ "zerobrew:nano" = "latest" "zerobrew:python" = "latest" "github:nodejs/node" = "latest" -"github:facebook/sapling" = "latest" +"github:facebook/sapling" = "latest" # shim:sl