This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Ansible roles collection for automating development environment setup across Ubuntu, macOS, and Debian. Contains ~78 roles for installing/configuring dev tools, languages, and applications.
poetry install --sync— install Python dependenciesansible-galaxy install -r requirements.yml— install Ansible collectionspoetry shell— enter virtual environment
poetry run ansible-playbook -i inventories/localhost playbook-desktop.yml- Run specific roles:
--tags git,shell - Dry run:
--check
- IMPORTANT: Always run
poetry run ansible-linton modified roles before committing - Lint specific role:
poetry run ansible-lint roles/ROLE_NAME/tasks/main.yml - Syntax check:
ansible-playbook --syntax-check playbook-desktop.yml - CI runs ansible-lint on
roles/via GitHub Actions on every PR
playbook-desktop.yml— Desktop environment (GUI apps, personal tools)playbook-devel.yml— Development environment (multi-play, uses host groups:all,webapp,devos,terraform)playbook-docker-service.yml— Docker-based servicesplaybook-gitlab.yml— GitLab server configuration
Roles are assigned in playbooks with: { role: NAME, tags: TAG, VAR: VALUE }
filter_plugins/shell_config.py provides the shell_config filter. Usage:
- ansible.builtin.set_fact:
shell_info: "{{ ansible_user_shell | shell_config }}"
# Returns: { name: 'bash', rc_file: '.bashrc', profile_path: '.bash_profile' }
# Or for zsh: { name: 'zsh', rc_file: '.zshrc', profile_path: '.zprofile' }Always use fully qualified collection names (FQCN): ansible.builtin.command, ansible.builtin.apt, etc.
UPPER_SNAKE_CASEwith role name as prefix:GOLANG_VERSION,DOCKER_USER,GIT_INSTALLER- Lint enforces:
^[a-z_][a-z0-9_]*$|[A-Z][A-Z0-9_]*$
Roles split OS-specific logic into separate files dispatched from tasks/main.yml:
- ansible.builtin.include_tasks: install_{{ ansible_distribution }}.ymlFile naming: install_Ubuntu.yml, install_MacOSX.yml (or install_MacOS.yml), install_Debian.yml
Check if a tool is installed before running install tasks:
- name: Check if TOOL installed
ansible.builtin.command: which TOOL
register: status_tool
changed_when: false
failed_when: false
- name: Install TOOL
ansible.builtin.include_tasks: install_{{ ansible_distribution }}.yml
when: status_tool.rc != 0For roles that manage tool versions (golang, nodejs, terraform, etc.):
- name: Check installed version
ansible.builtin.shell: /bin/bash -lc 'TOOL --version'
changed_when: false
failed_when: false
register: version_check
when: status_tool.rc == 0
- name: Install TOOL
ansible.builtin.include_tasks: install_{{ ansible_distribution }}.yml
when: status_tool.rc != 0 or
version_check.stdout is version(TOOL_VERSION, '<')Use become: yes on tasks requiring root (package installs, system config). Do not set become at play level.
When shell is required instead of command (e.g., for PATH-aware login shell execution), use inline noqa:
# noqa: command-instead-of-shell.ansible-lint: skips multiple legacy rules (see file), excludesroles/*/files/*.yamllint: line length max 160, truthy values["true", "false", "yes", "no"]
- Poetry for dependency management
- Python 3.11+ (< 3.14), ansible-core ~2.18.0
- Required collections:
community.general10.0.0,ansible.posix2.0.0