cidx v2.0.0 ships two fixes found while running cidx init on a Rust+React monorepo: rustfmt crashed because the base image doesn’t ship the component, and prettier silently ran against an empty directory because preset mount paths were inconsistent across language families. Both bugs are fixed same-day. The mount-path fix is a clean breaking change — hence v2.0.0.

What shipped

rustfmt component install (closes #150, PR #152)

The rustfmt preset ran cargo fmt -- --check directly. The rust:1.95.0 base image doesn’t ship rustfmt by default. This is the same setup the clippy preset already handled correctly — clippy opens with sh -c 'rustup component add clippy && ...'. The fix matches that pattern:

Before: cargo fmt -- --check
After:  sh -c 'rustup component add rustfmt && cargo fmt -- --check'

One line. No config change needed from users.

Unified preset mount paths at /work — BREAKING (closes #151, PR #153)

40+ built-in presets used six different in-container mount paths: /src (Rust), /work (Node.js/prettier), /scan (Trivy), /repo (Gitleaks), /app and /workspace elsewhere. Each tracked its upstream image convention. That’s consistent at the preset level, but it meant: any workdir override in cidx.toml required knowing the specific preset’s internal path. A wrong guess silently succeeded — no volume for that path → container starts in an empty directory → confusing “no files found” output:

[error] No supported files were found in the directory: "."
All matched files use Prettier code style!
Error: container exited with code 2

That last line was the real symptom: prettier saying “all files look fine” because there were no files to check.

The fix picks one path (/work) and applies it to every built-in preset. Two additions:

  1. Runtime guardrail: the runner now refuses to start a container whose workdir isn’t covered by any volume mount target. It lists the available mounts in the error so the user knows exactly what to fix — no guessing.
  2. cidx preset info documents the contract: the mount path is now surfaced in the preset info output, so users don’t need to read the preset source.

Migration (only affects cidx.toml with explicit workdir overrides):

# Before v2.0.0 — if you had a Rust workdir override
[containers.rustfmt]
workdir = "/src/my-crate"   # /src was the Rust preset path

# After v2.0.0 — all presets mount at /work
[containers.rustfmt]
workdir = "/work/my-crate"

# Or drop the override entirely — cidx will run in /work by default

If your cidx.toml doesn’t pin a workdir, nothing changes. If it does, and the path was one of the legacy paths (/src, /scan, /repo, /app, /workspace) without a matching volumes entry, cidx will now fail fast with a clear message.

Why it matters

Both bugs were discovered on the first cidx run code of a real external project. The cidx init happy path worked correctly (v1.8.0 feature — fullstack monorepo detection); running the generated config failed immediately. rustfmt crashed before running a single check. When a workdir override was applied to scope prettier to the React subdirectory, prettier reported success on zero files.

The mount-path unification removes a class of silent failures that can’t be caught by cidx validate. Knowing the preset’s in-container path was implicit knowledge; it’s now a documented, enforced contract.

What’s next

cidx v2.0.0 is at HEAD. No unreleased commits. Clean state: 0 open PRs, 0 open issues.