{
 "id": "puppet",
 "kind": "skill",
 "name": "Puppet",
 "description": "Write, validate, lint and dry-run Puppet code (manifests, modules, Hiera data, roles and profiles) safely.",
 "version": "1.0.0",
 "author": "Hexa Hub",
 "files": {
  "SKILL.md": "---\nname: puppet\ndescription: Write, validate, lint and dry-run Puppet code (manifests, modules, Hiera data, roles and profiles) safely.\ntitle: Puppet\nicon: tabler:server-cog\ncategory: Infrastructure as code\ntriggers: puppet, manifest, hiera, puppetfile, r10k, puppet agent, profile, epp, facter\nmarkers: puppet, puppet-lint\nrecipes: puppet.parser-validate, puppet.lint, puppet.noop, puppet.apply, puppet.agent-noop, puppet.agent-run, help.puppet-describe\nrelated: ansible, terraform\ncheck: *.pp => puppet.parser-validate manifest=$file\n---\n\n# Puppet\n\nRun the recipes where Puppet is installed: this PC, or `on: \"ssh:<name>\"` / `on: \"wsl:<name>\"` for a server or Linux environment. `toolchain` shows whether Puppet is installed here.\n\n**Check or review request**: read the code, run `puppet.parser-validate` and `puppet.lint`, then answer. Do not run noop or apply for a review.\n\n## Workflow for a change\n1. **Look first.** Find the class, the profile and the role involved and the Hiera data that feeds it (`find_code`, `search_files`). Puppet code is layered: **roles** (one per machine type) include **profiles** (one per technology) which use **modules**; **Hiera data** holds values, code holds logic.\n2. Edit. Keep modules small and parameters typed (`String`, `Integer`, `Optional[String]`, `Array[String]`).\n3. `puppet.parser-validate` on every changed `.pp` file, then `puppet.lint`. Fix errors; fix warnings unless the repo clearly ignores them.\n4. `puppet.noop` on the target (`puppet apply --noop`) or `puppet.agent-noop` on a node: shows what would change without changing it. **Read it to the user**: resources that would change, create or be removed, and notify/restart effects.\n5. Only if the user asks: `puppet.apply` or `puppet.agent-run`. Always asks, only right after the matching noop on unchanged files, blocked on prod.\n\nExample: `run_recipe {\"recipe\":\"puppet.noop\",\"args\":{\"manifest\":\"manifests/site.pp\"},\"on\":\"ssh:web01\"}`\n\n## Write idempotent, ordered code\n- Prefer native resource types (`package`, `file`, `service`, `user`, `ini_setting`) over `exec`. An `exec` needs `creates`, `unless` or `onlyif`, else it runs every time.\n- Order explicitly: `Package['nginx'] -> File['/etc/nginx/nginx.conf'] ~> Service['nginx']` (`->` order, `~>` order and notify). Dependency cycles and duplicate declarations are the common errors: read the error, it names both resources.\n- Facts come as `$facts['os']['family']`, not `$::osfamily`. Look up a resource type's parameters for the installed version with `help.puppet-describe` (type name); do not invent parameters.\n- Templates: EPP (`epp('module/file.epp', {...})`) over ERB for new code. Keep logic out of templates.\n- `include` a class when it needs no parameters; use resource-like declarations (`class { 'x': }`) only once per class, and prefer Hiera `lookup`/automatic parameter binding.\n\n## Secrets\nNever put passwords in manifests or Hiera plain text. Use `eyaml`-encrypted values or `Sensitive[String]` and ask the user for the encrypted data.\n\n## Report\nSay: files changed, validate and lint results, the noop summary, and whether anything was applied.\n"
 }
}
