Image tooling: ripgrep, fd, kubectl, helm, flux, cloudflared, op, uv#4
Merged
Merged
Conversation
…red, op), uv
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.
2 tasks
claude-prodromou
added a commit
that referenced
this pull request
May 11, 2026
…#21) * codex-shell: AGENT_MODE=smoke-test for slot startup probe (WOVED-147) Second slice of WOVED-147 after the uid pin (#20). The slot model assumes auth credentials remain usable across image rotations — but four failure modes can break that silently. The uid pin defends one (#3); this script defends the other three at first-boot: #1 refresh token expired on the wall clock #2 CLI auth format changed incompatibly #4 stricter cred-format check on a newer CLI version bin/smoke_test.py: - Verifies the agent's CLI binary loads (`<binary> --version` exits 0 within 10s) — catches image regressions at the binary layer. - Verifies the credentials file exists at the expected path, is non-empty, and parses as JSON — cheapest "format sanity" check that catches #2 and #4 without making any network call. - Exits with structured codes: 0 (ready), 64 (CLI broken), 65 (creds missing — slot needs init), 66 (creds invalid — slot needs re-auth). Manager-side dispatch keys off these values; do not renumber without bumping Manager in lockstep. - Stdlib only — same constraint as worker.py + auth_init.py. The slot pod's startup probe runs early in boot, before any pip would have a chance to land. bin/entrypoint.sh: - Adds `smoke-test)` case to the AGENT_MODE dispatch. - Documents required env (WOVED_TASK_AGENT) + the four exit codes in the case body so an operator reading the entrypoint sees the contract without grepping for smoke_test.py. Dockerfile: - COPY the new script to /usr/local/bin alongside auth_init.py. Manifest-level wiring (kubernetes startupProbe on slot worker pods) lands in nprodromou/woved alongside WOVED-152 (worker-job slot mount), so the chart template has somewhere to attach the probe. Without WOVED-152 there are no slot worker pods to probe. Local end-to-end exercise on the dev machine confirmed all five exit-code paths (missing env / unmapped agent / creds missing / creds invalid / OK) — the OK path even picked up the real claude CLI's version string in the structured output. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * smoke-test: claude detection matches auth-init snapshot model Codex caught (codex-shell#21 review) that pinning the claude credential path to ~/.claude/credentials.json would false-fail healthy slots whose CLI wrote to e.g. ~/.claude/.credentials/session.json. auth_init.py deliberately does NOT pin a filename for exactly this reason — it uses snapshot-diff over the entire ~/.claude/ tree to detect "auth happened" robustly across CLI version changes. Smoke test now matches that model for claude: - Walk ~/.claude/ for any non-symlink regular file outside the entrypoint's pre-populated baseline (CLAUDE.md, config.toml, settings.json — names empirically copied in by entrypoint.sh BEFORE auth-init runs). - Any candidate file → creds-ok (exit 0). - No candidates → creds-missing (exit 65). - Walk failure (permission denied, etc.) → creds-invalid (exit 66, same shape as Codex stat() failure path). Codex CLI side stays pinned (~/.codex/auth.json) — Codex CLI contract is stable on that path AND the entrypoint writes there from CODEX_SESSION at first boot. Codex's review specifically flagged only the claude side. No JSON parse for claude — auth_init.py doesn't parse either, because the format may differ across CLI versions and a parse-failure on a real-but-unfamiliar artifact would be a worse failure than a false-pass on a corrupt one (which the next real task would catch immediately). Codex JSON parse stays because the codex CLI contract IS stable. Local exercise of all six cases (missing env / no ~/.claude / empty .claude / baseline-only / .credentials/session.json / legacy credentials.json) confirmed correct exit codes. The exact repro from Codex's review (a file at .credentials/session.json) now exits 0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Round-up of standard infra CLIs and search tools so codex and claude both have the right hammer when they need it. All single-binary installs from upstream pinned to specific versions.
Adds (apt)
`ripgrep`, `fd-find`, `dnsutils`, `iputils-ping`, `python3-venv`.
Adds (curl-installed binaries, pinned)
PATH update
`/home/${AGENT}/.agent-config/scripts` added to `PATH` — the wrapper scripts (`plane-create-ticket.sh`, `gh-pr-comment.sh`, etc.) the entrypoint pulls from `nprodromou/agent-config` are now callable by short name from the agent's bash tool.
Why now
Codex flagged `rg is not installed here`, fell back to recursive grep. claude.prodromou.com is about to come online and will reach for `kubectl`, `cloudflared`, etc. in the same way you would on the host. Image grows ~150 MB but eliminates a class of "tool not found" papercuts.
Out of scope (next PR)
Wiring `agent-config/mcp-servers/{n8n,plane}.json` into `
/.codex/config.toml` and `/.claude/.mcp.json` so the MCP servers register at boot. Needs `N8N_API_KEY` added to the ExternalSecret and entrypoint config-gen logic.🤖 Generated with Claude Code