diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..bc2fe69 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,184 @@ +# AGENTS.md + +Navigation guide for AI agents. Organized by the type of change being requested. + +## Architecture overview + +`group_vars/all.yml` — the user's configuration: a list of containers and global AWS SSO settings. +`roles/devcontainer_sync/defaults/main.yml` — role defaults: all plugin definitions, default image, and base container settings. + +Ansible merges in this order (last wins): `devcontainer_defaults` → merged plugin values → per-container config from `devcontainers[*]`. + +--- + +## Query: "add/change something for [language] containers" + +`rust`, `python`, `typescript`, `terraform`, `java`, etc. are **primary languages**. A primary language is just a plugin that also sets the container image automatically. + +**Global plugin config** (affects every container using that language): +``` +roles/devcontainer_sync/defaults/main.yml + devcontainer_plugins.: + install_steps: [...] + vscode_extensions: [...] + vscode_settings: {...} + features: {...} + mounts: [...] + post_create_commands: [...] + container_env: {...} +``` + +**Language → image mapping** (which base image a language container gets): +``` +roles/devcontainer_sync/defaults/main.yml + devcontainer_primary_language_images: + rust: ... + python: ... + typescript: ... + java: ... +``` + +**Per-container override** (affects only one container): +``` +group_vars/all.yml + devcontainers: + - name: + primary_language: rust # sets image + activates rust plugin + install_steps: [...] # appended to plugin's install_steps +``` + +--- + +## Query: "add/change something for all containers" + +Defaults applied to every container before plugins and per-container config: +``` +roles/devcontainer_sync/defaults/main.yml + devcontainer_defaults: + image: ... + install_steps: [...] + vscode_extensions: [...] + vscode_settings: {...} + features: {...} + mounts: [...] + post_create_commands: [...] + post_start_commands: [...] + post_attach_commands: [...] + initialize_commands: [...] + container_env: {...} + remote_env: {...} + run_args: [...] + plugins: [...] # plugins active on every container by default +``` + +--- + +## Query: "add a new plugin" + +Add an entry to: +``` +roles/devcontainer_sync/defaults/main.yml + devcontainer_plugins: + : + install_steps: [...] + vscode_extensions: [...] + ... +``` + +Containers opt in via: +``` +group_vars/all.yml + devcontainers: + - name: + plugins: + - +``` + +--- + +## Query: "add/modify a specific container" + +``` +group_vars/all.yml + devcontainers: + - name: # required; also the workspace subfolder name by default + path: # optional override if workspace path differs from name + primary_language: # optional; sets image + activates language plugin + image: # optional; overrides primary_language image + plugins: [...] # additional plugins beyond defaults + install_steps: [...] + vscode_extensions: [...] + vscode_settings: {...} + features: {...} + mounts: [...] + run_args: [...] + container_env: {...} + remote_env: {...} + post_create_commands: [...] + post_start_commands: [...] + post_attach_commands: [...] + initialize_commands: [...] + update_remote_user_uid: true # optional +``` + +--- + +## Query: "add/change VS Code extensions" + +| Scope | Path | +|---|---| +| All containers | `defaults/main.yml → devcontainer_defaults.vscode_extensions` | +| All rust containers | `defaults/main.yml → devcontainer_plugins.rust.vscode_extensions` | +| One container | `group_vars/all.yml → devcontainers[name=X].vscode_extensions` | + +--- + +## Query: "add/change mounts" + +| Scope | Path | +|---|---| +| All containers | `defaults/main.yml → devcontainer_defaults.mounts` | +| Language/plugin | `defaults/main.yml → devcontainer_plugins..mounts` | +| One container | `group_vars/all.yml → devcontainers[name=X].mounts` | + +Cache-related plugins (`cache_cargo`, `cache_node`, `cache_python`, etc.) manage their own mounts. + +--- + +## Query: "add an install step" + +| Scope | Path | +|---|---| +| All containers | `defaults/main.yml → devcontainer_defaults.install_steps` | +| Language/plugin | `defaults/main.yml → devcontainer_plugins..install_steps` | +| One container | `group_vars/all.yml → devcontainers[name=X].install_steps` | + +`install_steps` are rendered into `.devcontainer/install.sh` via `templates/install.sh.j2`. Lists from defaults, plugins, and per-container config are **appended** (not replaced). + +--- + +## Query: "add a devcontainer feature" + +``` +roles/devcontainer_sync/defaults/main.yml + devcontainer_plugins.: + features: + ghcr.io/devcontainers/features/:: + optionKey: value +``` + +Or per-container in `group_vars/all.yml → devcontainers[name=X].features`. + +--- + +## File map + +| File | Purpose | +|---|---| +| `group_vars/all.yml` | User config: container list, AWS SSO | +| `group_vars/all.example.yml` | Example showing all common patterns | +| `roles/devcontainer_sync/defaults/main.yml` | All plugin definitions, defaults, image map | +| `roles/devcontainer_sync/tasks/sync_devcontainer.yml` | Merge logic: how defaults + plugins + per-container combine | +| `roles/devcontainer_sync/templates/install.sh.j2` | Template for the generated install.sh | +| `roles/devcontainer_sync/templates/aws_configure.sh.j2` | Template for AWS SSO setup script | +| `files//` | Extra static files copied into a container's `.devcontainer/` | diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/roles/devcontainer_sync/defaults/main.yml b/roles/devcontainer_sync/defaults/main.yml index c3f3494..e2af723 100644 --- a/roles/devcontainer_sync/defaults/main.yml +++ b/roles/devcontainer_sync/defaults/main.yml @@ -74,6 +74,7 @@ devcontainer_plugins: rust: install_steps: + - sudo apt install -y python-is-python3 - cargo install --locked cargo-nextest vscode_settings: rust-analyzer.runnables.test.overrideCommand: @@ -153,6 +154,7 @@ devcontainer_plugins: typescript: install_steps: + - sudo apt update && sudo apt install -y npm --no-install-recommends - npm install github: diff --git a/tests/golden_output b/tests/golden_output index 018bde7..e12b1d7 100644 --- a/tests/golden_output +++ b/tests/golden_output @@ -180,6 +180,8 @@ sudo apt update && sudo apt install -y ripgrep sudo ln -sf /usr/share/zoneinfo/America/Chicago /etc/localtime && sudo dpkg-reconfigure -f noninteractive tzdata +sudo apt update && sudo apt install -y npm --no-install-recommends + npm install curl -fsSL https://chatgpt.com/codex/install.sh | CODEX_NON_INTERACTIVE=1 sh @@ -413,6 +415,8 @@ sudo apt update && sudo apt install -y ripgrep sudo ln -sf /usr/share/zoneinfo/America/Chicago /etc/localtime && sudo dpkg-reconfigure -f noninteractive tzdata +sudo apt install -y python-is-python3 + cargo install --locked cargo-nextest curl -fsSL https://chatgpt.com/codex/install.sh | CODEX_NON_INTERACTIVE=1 sh diff --git a/tests/node-example/.devcontainer/install.sh b/tests/node-example/.devcontainer/install.sh index 79c9937..c6e2156 100755 --- a/tests/node-example/.devcontainer/install.sh +++ b/tests/node-example/.devcontainer/install.sh @@ -9,6 +9,8 @@ sudo apt update && sudo apt install -y ripgrep sudo ln -sf /usr/share/zoneinfo/America/Chicago /etc/localtime && sudo dpkg-reconfigure -f noninteractive tzdata +sudo apt update && sudo apt install -y npm --no-install-recommends + npm install curl -fsSL https://chatgpt.com/codex/install.sh | CODEX_NON_INTERACTIVE=1 sh diff --git a/tests/rust-example/.devcontainer/install.sh b/tests/rust-example/.devcontainer/install.sh index bc3e9be..db679d4 100755 --- a/tests/rust-example/.devcontainer/install.sh +++ b/tests/rust-example/.devcontainer/install.sh @@ -9,6 +9,8 @@ sudo apt update && sudo apt install -y ripgrep sudo ln -sf /usr/share/zoneinfo/America/Chicago /etc/localtime && sudo dpkg-reconfigure -f noninteractive tzdata +sudo apt install -y python-is-python3 + cargo install --locked cargo-nextest curl -fsSL https://chatgpt.com/codex/install.sh | CODEX_NON_INTERACTIVE=1 sh