Skip to content

Generate

anvil generate writes the Go file that wires the application.

Terminal window
anvil generate .

The command accepts the scan directory as its first positional argument. It loads anvil.yaml or anvil.yml from that directory when one exists. Missing configuration is valid; Anvil falls back to command defaults.

Terminal window
anvil generate [project-dir] [output-file] [package-pattern...]
  • [project-dir] is where Anvil looks for anvil.yaml or anvil.yml.
  • [output-file] overrides configured output for this run. If it ends with .go, it is used as the generated file. Otherwise it is treated as a directory and Anvil writes anvil_autogenerated.go inside it.
  • [package-pattern...] overrides configured scan patterns for this run.
  • --profile <name> applies profiles.<name> from anvil.yaml.
  • --profile=<name> is accepted as the equals form.
  • -p <name> is the short profile flag.

ANVIL_PROFILE selects a profile for commands that load project config. A CLI profile flag overrides the environment variable.

Generation runs in this exact order:

  1. Parse CLI flags and positional arguments.
  2. Load anvil.yaml or anvil.yml.
  3. Apply the selected profile when --profile, -p, or ANVIL_PROFILE is provided.
  4. Resolve configured relative paths against the config file directory.
  5. Determine scan package patterns from scan.patterns, scan.dirs, or generator defaults.
  6. Create the output directory.
  7. Create an overlay for the generated output file so scanning does not fail before the file exists.
  8. Load and type-check the configured Go packages.
  9. Run parser scanners for supported SDK markers.
  10. Stop if the parser produced any diagnostic.
  11. Compile the manifest from parser output.
  12. Run built-in compiler rules and configured Starlark rules.
  13. Stop if any compiler rule returns an ERROR diagnostic.
  14. Compile HTTP, gRPC, GraphQL, and queue plans.
  15. Emit generated Go source.
  16. Write the generated file to disk.

The command has no hidden shortcuts. A protocol compiler can produce an empty plan when the project has no routes for that protocol, but the pipeline order stays the same.

The output path is chosen in this order:

  1. second positional CLI argument
  2. generator.output
  3. generate.output
  4. generator.output_dir
  5. generate.output_dir
  6. Anvil’s default generated file path

The default generated file path is <project-dir>/anvilgen/anvil_autogenerated.go.

The output package name is chosen in this order:

  1. generator.package
  2. generate.package
  3. package name derived from the output directory

Derived package names are sanitized from the output directory. Characters that are not letters, digits, or _ become _, and names starting with a digit are prefixed with anvilgen_.

Rule files come from:

  1. compiler.rules
  2. every configured stage’s rules, sorted by stage name

anvil lint also accepts additional --rule <file> flags. anvil generate uses rules from project configuration.

Rule warnings are reserved for anvil lint; generate continues after warning diagnostics and writes generated output when no errors exist.

Parser warnings are different. They come from the source scanner before a manifest exists, so generate stops on them the same way it stops on parser errors. Run anvil scan when you want parser warnings printed without writing generated output.

Generation fails before writing output when:

  • The project config cannot be parsed
  • Package loading or type-checking fails
  • The parser produced any diagnostic, including warnings
  • Manifest compilation fails
  • Built-in rules return ERROR
  • Starlark scripts fail to load or return invalid diagnostics
  • Configured Starlark rules return ERROR
  • Protocol compilation fails
  • The output directory or file cannot be written

Diagnostics include a level, code or rule name, message, file, line, and hint whenever Anvil can derive one.

Generated code can be consumed explicitly:

import "example.com/portal/internal/anvilgen"
app := anvil.New(driver)
app.Wire(anvilgen.Wiring())

Generated code can also register itself through init when the generated package is imported for side effects:

import _ "example.com/portal/internal/anvilgen"
app := anvil.New(driver)
app.Wire()

Use explicit wiring in tests when you want the package dependency visible in the file. Use blank imports when an application shell wants generated modules to self-register.