Skip to content
Development
Agent

modules

**Scope**: Module selection patterns, builtin vs command/shell decisions, collection modules, and version-specific module changes **Version range**: ansible-core 2.14+ / Ansible Collections (community.general 7.0+) **Generated**: 2026-04-04 — verify against current Ansible

From plugin
vexjoy-agent
449198 skills198 agents12 commands83 hooks

Claude Code

$ npx -y skills add notque/vexjoy-agent --agent claude-code

Agent definition

modules.md

Ansible Modules Reference

> **Scope**: Module selection patterns, builtin vs command/shell decisions, collection modules, and version-specific module changes > **Version range**: ansible-core 2.14+ / Ansible Collections (community.general 7.0+) > **Generated**: 2026-04-04 — verify against current Ansible module documentation

---

Overview

The most common Ansible failure mode is using `command` or `shell` when an idempotent module exists. Module selection determines whether playbooks are idempotent, properly report changes, and work across environments. The hierarchy is: builtin module > collection module > command/shell with explicit `changed_when`.

---

Pattern Table: Module Selection by Task Type

| Task | Wrong Approach | Correct Module | Notes | |------|---------------|----------------|-------| | Install package (Debian) | `command: apt-get install nginx` | `ansible.builtin.apt` | Handles idempotency, state management | | Install package (RHEL) | `command: yum install nginx` | `ansible.builtin.dnf` | `dnf` preferred over `yum` on RHEL 8+ | | Install package (any OS) | `shell: {{pkg_mgr}} install` | `ansible.builtin.package` | Cross-platform, uses detected pkg manager | | Manage service | `command: systemctl start nginx` | `ansible.builtin.systemd` | Reports enabled/started/stopped state | | Copy file | `command: cp src dst` | `ansible.builtin.copy` | Detects changes by checksum | | Template | `command: sed 's/VAR/val/g' > /etc/conf` | `ansible.builtin.template` | Jinja2, detects changes, `--diff` support | | Create dir | `command: mkdir -p /path` | `ansible.builtin.file` | state=directory, handles permissions | | Download file | `command: wget url -O dest` | `ansible.builtin.get_url` | Checksum validation, change detection | | Run script once | `shell: /path/to/setup.sh` | `command` + `creates:` | `creates:` makes it idempotent | | Git checkout | `command: git clone` | `ansible.builtin.git` | Version-aware, detects changes | | Manage user | `command: useradd -m user` | `ansible.builtin.user` | Full lifecycle, idempotent | | Manage cron | `command: crontab -e` | `ansible.builtin.cron` | Named entries, idempotent |

---

Correct Patterns

Package Installation Across OS Families

# Use package module for cross-platform playbooks
- name: Install common packages
  ansible.builtin.package:
    name: "{{ item }}"
    state: present
  loop:
    - nginx
    - python3
    - curl

# Use platform-specific modules when you need platform features
- name: Install nginx with apt options (Debian/Ubuntu)
  ansible.builtin.apt:
    name: nginx
    state: present
    install_recommends: false  # apt-specific option
  when: ansible_os_family == "Debian"

- name: Install nginx with dnf options (RHEL 8+)
  ansible.builtin.dnf:
    name: nginx
    state: present
    enablerepo: epel  # dnf-specific option
  when: ansible_distribution_major_version | int >= 8 and ansible_os_family == "RedHat"

**Why**: `package` abstracts over OS differences. Use `apt`/`dnf` only when platform-specific options (repos, recommends, module streams) are needed.

---

Service Management with systemd

# Start and enable in one task
- name: Enable and start nginx
  ansible.builtin.systemd:
    name: nginx
    state: started
    enabled: true
    daemon_reload: true  # Required when unit files change

# Restart via handler (triggered by config change)
- name: Deploy nginx config
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    mode: '0644'
  notify: Restart nginx

# handlers/main.yml
- name: Restart nginx
  ansible.builtin.systemd:
    name: nginx
    state: restarted

**Why**: Handlers ensure services restart only when the triggering resource actually changed. Using `state: restarted` directly in tasks causes restarts on every run.

---

Making `command` Idempotent with `creates`

# When no module exists, use command with creates/removes
- name: Run database migration
  ansible.builtin.command:
    cmd: /app/bin/migrate up
    chdir: /app
    creates: /app/.migrations-complete  # Skip if this file exists

# After migration, create the sentinel file
- name: Mark migrations complete
  ansible.builtin.file:
    path: /app/.migrations-complete
    state: touch
    mode: '0644'

# For scripts that can be re-run safely
- name: Check if cluster is initialized
  ansible.builtin.command: kubectl get nodes
  register: cluster_check
  changed_when: false
  failed_when: false

- name: Initialize cluster
  ansible.builtin.command: kubeadm init --config /etc/kubeadm/config.yml
  when: cluster_check.rc != 0

---

Pattern Catalog

Use Package Modules for Installation

**Detection**:

# Find shell/command used for package installation
grep -rn "command:\|shell:" playbooks/ roles/ \
  | grep -E "apt-get|yum|dnf|pip install|npm install"

rg -t yaml '(command|shell):.*\b(apt-get|yum|dnf|pip)\b' roles/ playbooks/

**Signal**:

- name: Install nginx
  shell: apt-get install -y nginx

- name: Update packages
  command: yum update -y

**Why this matters**: `shell`/`command` always report `changed` regardless of whether nginx was already installed. Running twice installs twice (or errors). No change tracking. Breaks `--check` mode (would show false changes).

**Preferred action**:

- name: Install nginx
  ansible.builtin.apt:
    name: nginx
    state: present
    update_cache: true
    cache_valid_time: 3600  # Only update cache if older than 1 hour

---

Use the systemd Module for Service Management

**Detection**:

grep -rn "command:\|shell:" roles/ playbooks/ \
  | grep "systemctl"

rg -t yaml '(command|shell):.*systemctl' roles/ playbooks/

**Signal**:

- name: Start nginx
  command: systemctl start nginx

- name: Enable nginx on boot
  shell: systemctl enable nginx

**Why this matters**: Doesn't report the service state as a change properly. Can't use `--check` mode (would actually run `s

Read more
@notque
Ships withvexjoy-agent

Essays and writing behind this toolkit live at vexjoy.com. VexJoy Agent connects plain-English requests to specialist agents, skills, and workflows. /do selects the knowledge and tools needed for your task.

44964 skills198 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
449
Star history of notque/vexjoy-agent on GitHub, a chart by star-history.com

Other agents on vexjoy-agent.

testing

testing

Agent

**Scope**: Molecule test scenarios, ansible-lint rules, idempotency validation, and check-mode patterns **Version range**:…

@notque@notqueInstall Agent
communication-patterns

communication-patterns

Agent

**Scope**: Failure modes in agent output style — over-reporting, self-congratulation, verbose narration, and hedging. Covers what…

@notque@notqueInstall Agent
css-3d-card-transforms

css-3d-card-transforms

Agent

<!-- Loaded by combat-effects-upgrade when task involves card tilt, backface-visibility, CSS perspective, or Framer Motion + CSS…

@notque@notqueInstall Agent

More agents from other plugins.

a11y-architect
Auto-invoked

a11y-architect

Agent

Accessibility Architect specializing in WCAG 2.2 compliance for Web and Native platforms. Use PROACTIVELY when designing UI…

ecc13d293k
@affaan-m@affaan-mInstall Agent
analyze-pass-impact

analyze-pass-impact

Agent

Analyzes how a specific topic affects a group of compiler passes. Used by the /plan-update skill to parallelize research across…

react2d252k
@facebook@facebookInstall Agent
orchestrator

orchestrator

Agent

- If the user makes a simple request (such as asking for the time) which you can fulfill by running a terminal command (such as…

codex2d135k
@openai@openaiInstall Agent
cavecrew-builder

cavecrew-builder

Agent

Surgical 1-2 file edit. Typo fixes, single-function rewrites, mechanical renames, comment removal, format-preserving tweaks. Hard…

caveman3d119k
@juliusbrussee@juliusbrusseeInstall Agent

Questions about modules.

Which coding agents can use modules?
modules installs in Claude Code and Cursor: each loads subagents from .claude/agents, so copy the file there. Flowy's auto-invocation runs in Claude Code only.