Puppet — 18 Operations for AI Agents

Puppet manifests declare what whole fleets of machines should be — packages, services, files, in enforced order. act101 reads classes and resources as structure, so agents trace configuration intent across a sprawling control repo.

This page is the canonical reference an AI coding agent uses to refactor, query, and analyze Puppet code through the act MCP server. 18 operations available: 0 refactor, 18 query, 0 analysis. Each operation is callable from Claude Code, Cursor, Codex, OpenCode, or any MCP-compatible agent host. Click any operation for a stable anchor link suitable for citation.

18Query

Worked Puppet examples

act101 reads a Puppet manifest's class definitions, defined resource types, and function declarations as declarations — a defined resource type and a class definition are given the identical kind, class, so a reusable resource type is indistinguishable by kind from a real class. Nothing else in a Puppet file — a resource declaration (package/service/file), a variable assignment, a defined type's own parameters — is read by either query. symbols covers the identical three constructs one-for-one with skeleton; it adds nothing skeleton does not already show. Each example below is the verbatim output of the command shown, run against the file shown. Query outputs are pretty-printed with the timing block omitted.

Read the module's class, defined type, and function as a skeleton

nginx.pp packages an Nginx web-server module: the nginx class installs the package, runs the service, and manages its config file; nginx::vhost is a defined type instantiated once per virtual host; port_for picks the listening port for a given environment.

$ act query skeleton nginx.pp

Before

class nginx (
  String $package_name = 'nginx',
) {
  package { $package_name:
    ensure => installed,
  }

  service { 'nginx':
    ensure  => running,
    enable  => true,
    require => Package[$package_name],
  }

  file { '/etc/nginx/nginx.conf':
    ensure => file,
    source => 'puppet:///modules/nginx/nginx.conf',
    notify => Service['nginx'],
  }
}

define nginx::vhost (
  String $server_name,
  Integer $port = 80,
) {
  file { "/etc/nginx/sites-available/${server_name}":
    ensure  => file,
    content => template('nginx/vhost.erb'),
  }
}

function port_for($env) {
  if $env == 'production' {
    return(443)
  }
  return(80)
}

Output

{
    "type": "Skeleton",
    "declarations": [
        {
            "kind": "class",
            "name": "nginx",
            "range": {
                "start": {
                    "file": "nginx.pp",
                    "line": 1,
                    "column": 1,
                    "byte_offset": 0
                },
                "end": {
                    "file": "nginx.pp",
                    "line": 19,
                    "column": 2,
                    "byte_offset": 362
                }
            },
            "name_range": {
                "start": {
                    "file": "nginx.pp",
                    "line": 1,
                    "column": 7,
                    "byte_offset": 6
                },
                "end": {
                    "file": "nginx.pp",
                    "line": 1,
                    "column": 12,
                    "byte_offset": 11
                }
            }
        },
        {
            "kind": "class",
            "name": "nginx::vhost",
            "range": {
                "start": {
                    "file": "nginx.pp",
                    "line": 21,
                    "column": 1,
                    "byte_offset": 364
                },
                "end": {
                    "file": "nginx.pp",
                    "line": 29,
                    "column": 2,
                    "byte_offset": 559
                }
            },
            "name_range": {
                "start": {
                    "file": "nginx.pp",
                    "line": 21,
                    "column": 8,
                    "byte_offset": 371
                },
                "end": {
                    "file": "nginx.pp",
                    "line": 21,
                    "column": 20,
                    "byte_offset": 383
                }
            }
        },
        {
            "kind": "function",
            "name": "port_for",
            "range": {
                "start": {
                    "file": "nginx.pp",
                    "line": 31,
                    "column": 1,
                    "byte_offset": 561
                },
                "end": {
                    "file": "nginx.pp",
                    "line": 36,
                    "column": 2,
                    "byte_offset": 649
                }
            },
            "name_range": {
                "start": {
                    "file": "nginx.pp",
                    "line": 31,
                    "column": 10,
                    "byte_offset": 570
                },
                "end": {
                    "file": "nginx.pp",
                    "line": 31,
                    "column": 18,
                    "byte_offset": 578
                }
            }
        }
    ]
}

The skeleton reports three declarations: nginx and nginx::vhost both come back kind class — a class definition and a defined resource type are not distinguished — and port_for as function; the package/service/file resources nginx declares are not read.

List the same class, defined type, and function as symbols

port_for branches on $env, returning 443 for production and 80 otherwise.

$ act query symbols nginx.pp

Before

class nginx (
  String $package_name = 'nginx',
) {
  package { $package_name:
    ensure => installed,
  }

  service { 'nginx':
    ensure  => running,
    enable  => true,
    require => Package[$package_name],
  }

  file { '/etc/nginx/nginx.conf':
    ensure => file,
    source => 'puppet:///modules/nginx/nginx.conf',
    notify => Service['nginx'],
  }
}

define nginx::vhost (
  String $server_name,
  Integer $port = 80,
) {
  file { "/etc/nginx/sites-available/${server_name}":
    ensure  => file,
    content => template('nginx/vhost.erb'),
  }
}

function port_for($env) {
  if $env == 'production' {
    return(443)
  }
  return(80)
}

Output

{
    "type": "Symbols",
    "symbols": [
        {
            "name": "nginx",
            "kind": "class",
            "range": {
                "start": {
                    "file": "nginx.pp",
                    "line": 1,
                    "column": 7,
                    "byte_offset": 6
                },
                "end": {
                    "file": "nginx.pp",
                    "line": 1,
                    "column": 12,
                    "byte_offset": 11
                }
            },
            "visibility": "unknown"
        },
        {
            "name": "nginx::vhost",
            "kind": "class",
            "range": {
                "start": {
                    "file": "nginx.pp",
                    "line": 21,
                    "column": 8,
                    "byte_offset": 371
                },
                "end": {
                    "file": "nginx.pp",
                    "line": 21,
                    "column": 20,
                    "byte_offset": 383
                }
            },
            "visibility": "unknown"
        },
        {
            "name": "port_for",
            "kind": "function",
            "range": {
                "start": {
                    "file": "nginx.pp",
                    "line": 31,
                    "column": 10,
                    "byte_offset": 570
                },
                "end": {
                    "file": "nginx.pp",
                    "line": 31,
                    "column": 18,
                    "byte_offset": 578
                }
            },
            "visibility": "unknown"
        }
    ]
}

symbols reports the identical three entries with the identical kinds skeleton already showed — this grammar's symbols query adds nothing skeleton does not already surface.

Query

18 query tools, the same on every supported language. Descriptions live in the shared reference: /docs/query-tools.

callers control_flow data_flow definition diagnostics effect_closure effect_summary fix_auto get_type graph import_organize interface mutations references repo_outline skeleton symbols symbols_batch

← PRQLPython →