# aiac: turning a prompt into Terraform, Pulumi and kubectl commands

> aiac is a Go CLI and library that sends a natural-language request to OpenAI, Amazon Bedrock or Ollama and writes the generated IaC, config or shell command to a file or stdout. It is a prompt-to-file wrapper, not a validator.

**gofireflyio/aiac** — Artificial Intelligence Infrastructure-as-Code Generator.

- Repository: https://github.com/gofireflyio/aiac
- Stars: 3,787 · Forks: 295
- Language: Go
- License: Apache-2.0
- Published: 2026-09-14 · Updated: 2026-09-14 · Language: en
- Canonical page: https://hysenlabs.com/projects/gofireflyio-aiac

## What aiac actually removes from the workflow

The repetitive part of writing infrastructure code is not the syntax. It is the lookup: which resource type, which attribute name, which flag. aiac targets that step. You type a sentence such as `aiac terraform for a highly available eks`, and the tool composes a request to the LLM provider you selected, takes the response and writes it to a file or prints it to standard output.

The README frames the scope broadly: IaC templates, configuration files, CI/CD pipelines, policy as code, utilities and queries. The example prompts cover Terraform, Pulumi in Go, CloudFormation, Dockerfiles, Kubernetes manifests, Jenkins pipelines, GitHub Actions, OPA policies, Python and bash scripts, kubectl and awscli invocations, and Mongo, Elastic and SQL queries. That list is the honest description of the audience: platform engineers and SREs who know what they want to build and do not want to open a browser tab for the resource reference.

It is not an agent. There is no plan phase, no diff against live infrastructure, no apply. The README describes the CLI as asking a model to generate templates, composing a request to the selected provider, and storing the result. Everything after the file lands on disk is your problem.

## Backends, providers and how a request is routed

aiac is configured through a TOML file. Unless you pass a path, it looks in the XDG config directory, specifically `${XDG_CONFIG_HOME}/aiac/aiac.toml`, which on Unix-like systems defaults to `~/.config/aiac/aiac.toml`. The `--config` or `-c` flag overrides that path.

The file defines named backends. Each backend has a `type` naming the provider, and the README gives three: `openai`, `bedrock` and `ollama`. A top-level `default_backend` key names the backend used when you do not select one. Because backends are named, you can define two of the same type for different environments, which is exactly what the README's example does with `aws_staging` and `aws_prod`.

Provider configuration differs by type. OpenAI backends take `api_key`, optionally `default_model`, and for non-OpenAI endpoints a `url` plus `api_version` and an `auth_header` (the default is `Authorization`, and the example uses `api-key` for Azure). Bedrock backends take `aws_profile` and `aws_region` and let the AWS SDK resolve credentials. Ollama backends take only a `url`, defaulting to `http://localhost:11434/api`, and the README states that Ollama has no authentication mechanism, so a proxy in front of it is not supported.

One constraint is stated plainly: every backend can carry a `default_model`, and if it is absent, calls that do not name a model fail. There is no fallback model. The `go.mod` file shows the request layer is `github.com/ido50/requests` and the AWS path uses `aws-sdk-go-v2` with the `bedrock` and `bedrockruntime` service packages, so Bedrock traffic goes through the AWS SDK rather than a hand-rolled HTTP client.

## Installing aiac and generating your first file

The README lists four installation routes: a Homebrew tap, a container image, `go install`, and building from a clone. The Arch user repository also carries `aiac` and `aiac-bin`. Pick the one that matches how you already manage tools.

```bash
brew tap gofireflyio/aiac https://github.com/gofireflyio/aiac
brew install aiac
```

If you prefer Go, the module path carries the v5 major version, so the install command includes it:

```bash
 go install github.com/gofireflyio/aiac/v5@latest
```

The container image is pulled from GitHub's registry, and the Dockerfile shows the entrypoint is the `aiac` binary itself, so arguments you pass to `docker run` go straight to the CLI:

```bash
docker pull ghcr.io/gofireflyio/aiac
```

Before any of that is useful you need a configuration file and a provider credential. For OpenAI you need an API key, and for Azure OpenAI or another compatible endpoint you also need the API URL. For Bedrock you need an AWS account with Bedrock enabled and access to the models you intend to call. For Ollama you need the local API server URL.

A minimal file with one OpenAI backend looks like this. The README shows that `api_key` accepts either a literal value or a `$`-prefixed environment variable reference, and that `default_model` is what calls fall back to:

```toml
default_backend = "official_openai"

[backends.official_openai]
type = "openai"
api_key = "$OPENAI_API_KEY"
default_model = "gpt-4o"
```

With that in place, the README documents a `list` subcommand for showing the models available to your backends, which is the fastest way to confirm the file parsed and the provider responded. Then generate something small and inspect it before you generate anything large:

```bash
aiac list
aiac dockerfile for a secured nginx
```

The README states that the CLI stores the resulting code to a file and/or prints it to standard output, so the second command either writes a file in the working directory or shows the Dockerfile on screen depending on how you invoke it. Read the output. The model is answering a sentence, not reading your repository.

## Where the generated output stops being trustworthy

The failure mode is not a crash. It is a plausible file. A language model asked for a Terraform resource can produce an attribute that never existed, a provider argument in the wrong block, or a version constraint that resolves to nothing. aiac has no schema awareness: nothing in the README describes the tool consulting a provider schema, a Kubernetes API version, or a policy engine before writing the response to disk. The generated text is the model's output, formatted and saved.

That makes the tool a poor fit when the cost of a wrong file is high and the cost of reading it is also high. A fifty-line Dockerfile is reviewable by eye. A multi-resource Terraform module with variables, outputs and IAM policy documents is not, at least not quickly, and the review burden is the same work you were trying to avoid.

There is a second limitation in the configuration model. Ollama backends accept only a URL, and the README says explicitly that Ollama provides no authentication and that a proxy in front of it is not currently supported. So the local, no-API-key path is also the path with no way to put a credential or an authenticating gateway between aiac and the model server. If your threat model requires that, Ollama through aiac is the wrong backend.

The third constraint is that models are per-backend and there is no default at the provider level. If you configure a backend and forget `default_model`, every call that does not name a model fails. That is a deliberate choice, and it means a config that looks complete can still be unusable.

## How aiac compares with asking the model directly

The obvious alternative is to skip aiac and paste the same prompt into a chat interface or a provider's own CLI. The difference is mechanical rather than conceptual. aiac keeps the prompt in your shell history, selects a provider from a config file rather than from whichever tab is open, and writes the answer to a file in the directory you are standing in. If you work across several providers, or across staging and production Bedrock accounts, the named-backend model is the part that saves effort: you switch with a flag instead of re-authenticating.

If what you actually want is an agent that reads your existing repository and edits files in place, aiac is not that and the README does not claim it is. The library entry point is the other real alternative: `libaiac/` exists in the repository, and the README documents using aiac as a library, so a team that wants prompt-to-IaC inside its own Go service can import the module instead of shelling out. The `go.mod` module path is `github.com/gofireflyio/aiac/v5`, which is what an import would use.

Between the two, the CLI is the lower-commitment option. You get the provider plumbing and the file writing; you do not get a review step, and neither approach gives you one.

## Upgrade path, licence and what a v5 pin means

The README devotes a section to upgrading from v4 to v5 and splits it into changes in configuration, changes in CLI invocation, and changes in model usage and support. That structure tells you the v4 to v5 jump is not a drop-in: the config format and the command line both moved. If you are on v4, read that section before touching the binary, because a config file that parsed under v4 may not parse under v5.

The repository is licensed under Apache-2.0, and the `LICENSE` file sits at the top level. Apache-2.0 permits commercial use and modification and includes a patent grant; it also requires that you keep the licence and notice files when you redistribute. If you vendor `libaiac` into a product, that obligation travels with the code. This is a description of the licence text, not legal advice for your situation.

The module path is versioned as `/v5`, so Go's module system will treat v5 as a distinct major version. That is standard for Go and it means an existing v4 import will not silently resolve to v5. The most recent release listed is v5.3.0 from 2024-10-29, with v5.2.1 and v5.2.0 before it in July 2024. The last push to the repository was on 2026-03-24, so the codebase has moved since the last tagged release; if you need a release artifact rather than a build from `main`, check what the tag contains before assuming it matches the current README.

## Conclusion

Adopt aiac if you already have an LLM provider account and you want generated Terraform, Pulumi, Dockerfiles or CLI commands written straight to a file from a shell prompt, with several providers selectable through one TOML file. Do not adopt it if you need the tool to check what it produced: aiac writes model output and nothing in the README describes validation, plan or apply. Before relying on it, run aiac list to confirm your configured backends load, and generate one file you already know how to write by hand so you can compare the output against your own.

## FAQ

### Which LLM providers does aiac support?

The README documents three backend types: openai, bedrock and ollama. OpenAI backends can point at a non-OpenAI endpoint such as Azure OpenAI by setting url, api_version and auth_header.

### Where does aiac look for its configuration file?

It reads a TOML file at ${XDG_CONFIG_HOME}/aiac/aiac.toml, which defaults to ~/.config/aiac/aiac.toml on Unix-like systems. You can point it elsewhere with the --config or -c flag.

### Does aiac validate or apply the infrastructure code it generates?

The README describes composing a request to the selected provider and storing the resulting code to a file or printing it to standard output. It does not document schema validation, planning or applying.

## Sources

- [gofireflyio/aiac on GitHub](https://github.com/gofireflyio/aiac)
- [Issues](https://github.com/gofireflyio/aiac/issues)
- [License: Apache-2.0](https://github.com/gofireflyio/aiac/blob/main/LICENSE)
- [README](https://github.com/gofireflyio/aiac/blob/main/README.md)
- [Releases](https://github.com/gofireflyio/aiac/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gofireflyio-aiac
