Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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 \
Expand Down
Loading