FROM debian:stable-slim
ENV DEBIAN_FRONTEND=noninteractive \
RUSTUP_HOME=/usr/local/rustup \
CARGO_HOME=/usr/local/cargo \
PATH=/usr/local/cargo/bin:$PATH
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential pkg-config libssl-dev \
curl ca-certificates git sudo nodejs npm \
shellcheck \
&& rm -rf /var/lib/apt/lists/*
RUN groupadd -g 1000 dev \
&& useradd -m -u 1000 -g dev -s /usr/bin/bash dev \
&& echo "dev ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --no-modify-path --default-toolchain stable \
&& rustup component add clippy \
&& rustup component add rustfmt
RUN curl -L \
https://github.com/rust-lang/rust-analyzer/releases/latest/download/rust-analyzer-linux \
-o /usr/local/bin/rust-analyzer \
&& chmod +x /usr/local/bin/rust-analyzer
RUN npm install -g dockerfile-language-server-nodejs markdownlint-cli bash-language-server
RUN cargo install taplo-cli --locked --features lsp
# AGENTS.md §3's last gate line, `cargo deny check`. Every other line on that list is plain `cargo`,
# which is why this is the only one that needs installing. Unpinned to match CI, which resolves its
# own version inside `EmbarkStudios/cargo-deny-action@v2` rather than at a fixed one.
RUN cargo install cargo-deny --locked
# AGENTS.md §3's test lines run under nextest (process-per-test isolation, native flaky-test
# detection). Unpinned to match CI's `taiki-e/install-action@cargo-nextest`.
RUN cargo install cargo-nextest --locked
# Structural search/rewrite for Rust (`ast-grep run -p '$X.unwrap()'`), a syntax-aware complement
# to `rg` for edits a regex would silently under- or over-match (generics, async, macro calls).
# Not part of any gate — a workflow tool, like rust-analyzer above.
RUN cargo install ast-grep --locked
RUN curl -L \
https://github.com/artempyanykh/marksman/releases/latest/download/marksman-linux \
-o /usr/local/bin/marksman \
&& chmod +x /usr/local/bin/marksman
# These dirs were populated as root by the RUN steps above; the container runs as 'dev' below.
RUN chown -R dev:dev /usr/local/cargo /usr/local/rustup
WORKDIR /workspace
# Ensure that any interactive shell picks up Cargo/Rustup binaries
RUN echo 'export PATH="/usr/local/cargo/bin:$PATH"' >> /home/dev/.bashrc \
&& echo 'export PATH="/usr/local/cargo/bin:$PATH"' >> /home/dev/.profile
USER dev
ENTRYPOINT ["bash"]