From 461c6f8f2c91adfa76bb31802d75fc03f2a83482 Mon Sep 17 00:00:00 2001 From: nprodromou <73134621+nprodromou@users.noreply.github.com> Date: Wed, 6 May 2026 23:10:47 -0700 Subject: [PATCH] Dockerfile: add ripgrep/fd, infra CLIs (kubectl, helm, flux, cloudflared, op), uv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tooling round-up so codex and claude have the standard infra-CLI surface ready when they need it. All single-binary installs from upstream — no apt repos to babysit. System utilities (apt): - ripgrep, fd-find — codex tries `rg` and falls back to grep without it - dnsutils, iputils-ping — DNS / connectivity debugging from inside the pod - python3-venv — uv likes a venv around when invoking uvx tools Infra CLIs (single binaries, pinned versions): - kubectl 1.34.1 - helm 3.16.3 - flux 2.4.0 - cloudflared 2026.2.0 - op 2.31.1 (1Password CLI) Tool runners: - uv → /usr/local/bin (provides `uvx` for plane-mcp-server etc.) PATH update: - /home/${AGENT}/.agent-config/scripts on PATH so the wrapper scripts from agent-config (plane-create-ticket.sh, gh-pr-comment.sh, etc.) Just Work without invoking by full path. Image grows ~150 MB but the agent now has the right hammer for most apk8s / Cloudflare / Plane work without shell-out gymnastics. --- Dockerfile | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index f91d298..811fa6e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ ENV AGENT=${AGENT} \ LC_ALL=C.UTF-8 \ TZ=America/Los_Angeles \ HOME=/home/${AGENT} \ - PATH=/home/${AGENT}/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + PATH=/home/${AGENT}/.local/bin:/home/${AGENT}/.agent-config/scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # System deps + gh + tmux + Node + bubblewrap + standard CLI utilities. # ttyd is fetched separately below — Debian Bookworm doesn't carry it. @@ -37,7 +37,8 @@ RUN set -eux; \ apt-get install -y --no-install-recommends \ ca-certificates curl git gnupg jq less vim sudo tini \ bash-completion locales tmux unzip zip openssh-client \ - build-essential python3 python3-pip \ + build-essential python3 python3-pip python3-venv \ + ripgrep fd-find dnsutils iputils-ping \ bubblewrap \ passwd; \ # Node.js from NodeSource (pinned major version). NodeSource ships @@ -72,6 +73,55 @@ RUN set -eux; \ chmod +x /usr/local/bin/ttyd; \ ttyd --version +# uv — fast Python package manager and tool runner. `uvx` is what +# agent-config's mcp-servers/plane.json launches (`uvx plane-mcp-server`), +# and codex/claude generally benefit from having it on PATH. +RUN curl -fsSL https://astral.sh/uv/install.sh \ + | env UV_INSTALL_DIR=/usr/local/bin sh + +# Debian renames fd → fdfind; expose canonical name codex/claude expect. +RUN ln -sf /usr/bin/fdfind /usr/local/bin/fd + +# Infra CLIs the agent will reach for when working on apk8s / Cloudflare. +# All single-binary installs from upstream — no apt repos to babysit. +ARG KUBECTL_VERSION=v1.34.1 +ARG HELM_VERSION=v3.16.3 +ARG FLUX_VERSION=2.4.0 +ARG CLOUDFLARED_VERSION=2026.2.0 +ARG OP_VERSION=2.31.1 +RUN set -eux; \ + arch="$(dpkg --print-architecture)"; \ + # kubectl + curl -fsSL "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${arch}/kubectl" \ + -o /usr/local/bin/kubectl; \ + chmod +x /usr/local/bin/kubectl; \ + kubectl version --client=true --output=yaml | head -2; \ + # helm + curl -fsSL "https://get.helm.sh/helm-${HELM_VERSION}-linux-${arch}.tar.gz" \ + | tar -xz -C /tmp; \ + mv "/tmp/linux-${arch}/helm" /usr/local/bin/helm; \ + rm -rf "/tmp/linux-${arch}"; \ + helm version --short; \ + # flux CLI + curl -fsSL "https://github.com/fluxcd/flux2/releases/download/v${FLUX_VERSION}/flux_${FLUX_VERSION}_linux_${arch}.tar.gz" \ + | tar -xz -C /tmp; \ + mv /tmp/flux /usr/local/bin/flux; \ + flux --version; \ + # cloudflared + curl -fsSL "https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARED_VERSION}/cloudflared-linux-${arch}" \ + -o /usr/local/bin/cloudflared; \ + chmod +x /usr/local/bin/cloudflared; \ + cloudflared --version | head -1; \ + # 1Password CLI (op). Uses .deb because the static binary needs the + # .deb's apparmor / udev hooks for the desktop integration; on Linux + # the deb just drops a binary in /usr/bin. + curl -fsSL "https://cache.agilebits.com/dist/1P/op2/pkg/v${OP_VERSION}/op_linux_${arch}_v${OP_VERSION}.zip" \ + -o /tmp/op.zip; \ + unzip -d /tmp/op /tmp/op.zip; \ + mv /tmp/op/op /usr/local/bin/op; \ + rm -rf /tmp/op /tmp/op.zip; \ + op --version + # Per-agent CLI install. Both are npm packages; the global install puts # `codex` or `claude` on PATH for the non-root user. RUN case "$AGENT" in \