Skip to main content
This guide takes you from zero to running infrastructure: install formae, start the agent, deploy a ready-made example to AWS, Azure, or GCP, verify it, and tear it back down.
Prefer to work through an AI assistant? Follow the Quick start with an AI assistant and describe what you want instead of writing Pkl by hand.
1

Install formae

Install the CLI and agent with one command:
Add the binary to your PATH:
Verify the install:
2

Start the formae agent

The agent runs the infrastructure operations and keeps state in sync with your cloud. Start it in its own terminal and leave it running:
It prints its banner, confirms it has started, and registers the bundled providers:
formae
2026-07-20T16:52:21-07:00 INF Starting agent id=37MG2qUmBGgcOdFOg2kaHU2xk6P
2026-07-20T16:52:21-07:00 INF Agent started
2026-07-20T16:52:21-07:00 INF Plugin registered: namespace=AZURE node=formae-azure-plugin@localhost rateLimit=10 resources=43 [pid=<8E428C64.0.1009>] [name=‘PluginCoordinator’] [behavior=plugin_coordinator.PluginCoordinator]
2026-07-20T16:52:21-07:00 INF Plugin registered: namespace=GCP node=formae-gcp-plugin@localhost rateLimit=10 resources=65 [pid=<8E428C64.0.1009>] [name=‘PluginCoordinator’] [behavior=plugin_coordinator.PluginCoordinator]
2026-07-20T16:52:23-07:00 INF Plugin registered: namespace=AWS node=formae-aws-plugin@localhost rateLimit=2 resources=239 [pid=<8E428C64.0.1009>] [name=‘PluginCoordinator’] [behavior=plugin_coordinator.PluginCoordinator]
2026-07-20T16:52:28-07:00 INF Plugin registered: namespace=K8S node=formae-k8s-plugin@localhost rateLimit=10 resources=575 [pid=<8E428C64.0.1009>] [name=‘PluginCoordinator’] [behavior=plugin_coordinator.PluginCoordinator]
Leave it running in this terminal, and open a second terminal for the remaining steps.
3

Copy an example to your workspace

formae ships runnable examples for each cloud. Copy one into a working directory, along with the PklProject files that declare its Pkl dependencies (the formae SDK and cloud schemas). Choose your cloud in the next step for the exact example.
4

Deploy to your cloud

Prerequisites: AWS credentials in your environment, for example via aws configure or AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.This example provisions a complete ECS stack: VPC and subnets, security groups, an ECS cluster, an Application Load Balancer, and a running service.Copy the example and its Pkl project files:
Apply the example. formae shows you the plan and waits for your confirmation before it changes anything, then opens a live view of the run. The example exposes --region as a property, so you can pick a region without editing any code:
apply runs for real, so formae first shows you the plan and asks you to confirm. Press y to continue, or q to abort. This is the AWS ecs-hello-world plan:
  formae apply · reconcile                                                                       ecs_hello_world.pkl
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  + 22 create

  ▌ Targets
  Operation ▲   Label
  + create      default-aws-target

  ▌ Stacks
  Operation ▲   Label
  + create      ecs-hello-world

  ▌ Resources
  Operation ▲   Label                                                       Type
  + create      ecs-vpc                                                     AWS::EC2::VPC
  + create      ecs-igw                                                     AWS::EC2::InternetGateway
  + create      ecs-igw-attachment                                          AWS::EC2::VPCGatewayAttachment
  + create      ecs-public-subnet-1                                         AWS::EC2::Subnet
  + create      ecs-public-subnet-2                                         AWS::EC2::Subnet
  + create      ecs-public-rt                                               AWS::EC2::RouteTable
  + create      ecs-public-route                                            AWS::EC2::Route
  + create      ecs-public-subnet-1-assoc                                   AWS::EC2::SubnetRouteTableAssociation
  + create      ecs-public-subnet-2-assoc                                   AWS::EC2::SubnetRouteTableAssociation
  + create      ecs-alb-sg                                                  AWS::EC2::SecurityGroup
      ↓ show 10 more (10 remaining)

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  ↑↓: select  space: expand  →←: column  s: sort  y: confirm  q: abort This operation will create 1 stack(s), create
1 target(s) and create 20 resource(s).  Do you want to continue? (y/N)  ?: help
Once you confirm, formae opens a live view of the run. Press q to leave the view at any time; the operation keeps running on the agent. To re-attach to it, run:
When the run finishes, every resource is applied:
  formae status command                                                                                     ↻ live
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
     ID                          Command   Mode        Progress                         ✓    ✗    ◐    ○    Time
✓    3Gmw76N43M4ysS54phFL3naR57p apply     reconcile   completed 22/22                  22   0    0    0    04:19
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  ▌ Targets
        Label ▲                                                                                   Operation   Time
       default-aws-target                                                                        create      00:00

  ▌ Stacks
        Label ▲                                                                                   Operation   Time
       ecs-hello-world                                                                           create      00:00

  ▌ Resources
        Label ▲                                               Type                                Operation   Time
       ecs-alb                                               AWS::ElasticLoadBalancingV2::Load…  create      02:45
       ecs-alb-sg                                            AWS::EC2::SecurityGroup             create      00:22
       ecs-alb-sg-ingress                                    AWS::EC2::SecurityGroupIngress      create      00:22
       ecs-hello-cluster2                                    AWS::ECS::Cluster                   create      00:23
       ecs-hello-task-def                                    AWS::ECS::TaskDefinition            create      00:24
       ecs-hello-world-cluster                               AWS::ECS::Cluster                   create      00:21
       ecs-igw                                               AWS::EC2::InternetGateway           create      00:23
       ecs-igw-attachment                                    AWS::EC2::VPCGatewayAttachment      create      00:22
       ecs-listener                                          AWS::ElasticLoadBalancingV2::List…  create      00:23
       ecs-public-route                                      AWS::EC2::Route                     create      00:02
       ecs-public-rt                                         AWS::EC2::RouteTable                create      00:21
       ecs-public-subnet-1                                   AWS::EC2::Subnet                    create      00:22
       ecs-public-subnet-1-assoc                             AWS::EC2::SubnetRouteTableAssocia…  create      00:24
       ecs-public-subnet-2                                   AWS::EC2::Subnet                    create      00:21
       ecs-public-subnet-2-assoc                             AWS::EC2::SubnetRouteTableAssocia…  create      00:23
       ecs-task-exec-role                                    AWS::IAM::Role                      create      00:22
       ecs-task-sg                                           AWS::EC2::SecurityGroup             create      00:21
       ecs-task-sg-ingress                                   AWS::EC2::SecurityGroupIngress      create      00:22
       ecs-tg                                                AWS::ElasticLoadBalancingV2::Targ…  create      00:21
       ecs-vpc                                               AWS::EC2::VPC                       create      00:23

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  →←: column  s: toggle sort  space: expand  d: details  q: quit                                           ?: help
--mode is required on apply. Learn the difference between reconcile and patch in Apply modes.
5

Verify your deployment

Confirm formae created the resources. Filter the inventory by the stack you just deployed:
For the AWS example, that lists the stack it just deployed:
  formae inventory
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 ╭─────────────╮
  1 Resources    2 Targets    3 Stacks    4 Policies 
─╯             ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Label ▲                           Stack                  Type                                   NativeID                                      
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
ecs-alb                           ecs-hello-world        AWS::ElasticLoadBalancingV2::LoadBalan…arn:aws:elasticloadbalancing:eu-central-1:897…
ecs-alb-sg                        ecs-hello-world        AWS::EC2::SecurityGroup                sg-0ce41bacf1d67b147                          
ecs-alb-sg-ingress                ecs-hello-world        AWS::EC2::SecurityGroupIngress         sgr-0fbb692f2f8d5636d                         
ecs-hello-cluster2                ecs-hello-world        AWS::ECS::Cluster                      ecs-hello-world-cluster2                      
ecs-hello-task-def                ecs-hello-world        AWS::ECS::TaskDefinition               arn:aws:ecs:eu-central-1:897722706215:task-de…
ecs-hello-world-cluster           ecs-hello-world        AWS::ECS::Cluster                      ecs-hello-world-cluster                       
ecs-igw                           ecs-hello-world        AWS::EC2::InternetGateway              igw-047bab59003537498                         
ecs-igw-attachment                ecs-hello-world        AWS::EC2::VPCGatewayAttachment         IGW|vpc-02e1b0b73a5730d65                     
ecs-listener                      ecs-hello-world        AWS::ElasticLoadBalancingV2::Listener  arn:aws:elasticloadbalancing:eu-central-1:897…
ecs-public-route                  ecs-hello-world        AWS::EC2::Route                        rtb-0bab9fbbf4c0010e5|0.0.0.0/0|GatewayId=igw…
ecs-public-rt                     ecs-hello-world        AWS::EC2::RouteTable                   rtb-0bab9fbbf4c0010e5                         
ecs-public-subnet-1               ecs-hello-world        AWS::EC2::Subnet                       subnet-0b38a309934e06276                      
ecs-public-subnet-1-assoc         ecs-hello-world        AWS::EC2::SubnetRouteTableAssociation  rtbassoc-013308e76c96ade7c                    
ecs-public-subnet-2               ecs-hello-world        AWS::EC2::Subnet                       subnet-08999cc2f4fb40e87                      
ecs-public-subnet-2-assoc         ecs-hello-world        AWS::EC2::SubnetRouteTableAssociation  rtbassoc-0d4512b6e49506eba                    
ecs-task-exec-role                ecs-hello-world        AWS::IAM::Role                         6cfPoszejP6KRJElRijPynvA8-SMXNaMlk1MfC        
ecs-task-sg                       ecs-hello-world        AWS::EC2::SecurityGroup                sg-075d33812aa776116                          
ecs-task-sg-ingress               ecs-hello-world        AWS::EC2::SecurityGroupIngress         sgr-068746b2de1bad0c0                         
ecs-tg                            ecs-hello-world        AWS::ElasticLoadBalancingV2::TargetGro…arn:aws:elasticloadbalancing:eu-central-1:897…
Showing 20 of 20 resources (filtered)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  / stack:ecs-hello-world                                                                                                              /: edit query
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  ↑↓/j/k: navigate  enter: detail  /: search  s: sort  r: refresh  1-4: tab  q: quit                                                         ?: help
Each example uses its own stack name. You can also check your cloud’s web console to see the created resources.
6

Clean up

To avoid ongoing charges, destroy what you created:
destroy shows a plan and asks you to confirm too; press y to proceed. The completed teardown looks like this:
  formae status command                                                                                     ↻ live
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
     ID                          Command   Mode        Progress                         ✓    ✗    ◐    ○    Time
✓    3Gmwiy52PNdn5rJiu3nWhLDPxJf destroy   -           completed 20/20                  20   0    0    0    02:35
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  ▌ Resources
        Label ▲                                               Type                                Operation   Time
       ecs-alb                                               AWS::ElasticLoadBalancingV2::Load…  delete      01:02
       ecs-alb-sg                                            AWS::EC2::SecurityGroup             delete      00:21
       ecs-alb-sg-ingress                                    AWS::EC2::SecurityGroupIngress      delete      00:21
       ecs-hello-cluster2                                    AWS::ECS::Cluster                   delete      00:21
       ecs-hello-task-def                                    AWS::ECS::TaskDefinition            delete      00:21
       ecs-hello-world-cluster                               AWS::ECS::Cluster                   delete      00:21
       ecs-igw                                               AWS::EC2::InternetGateway           delete      00:21
       ecs-igw-attachment                                    AWS::EC2::VPCGatewayAttachment      delete      01:02
       ecs-listener                                          AWS::ElasticLoadBalancingV2::List…  delete      00:22
       ecs-public-route                                      AWS::EC2::Route                     delete      00:01
       ecs-public-rt                                         AWS::EC2::RouteTable                delete      00:21
       ecs-public-subnet-1                                   AWS::EC2::Subnet                    delete      00:22
       ecs-public-subnet-1-assoc                             AWS::EC2::SubnetRouteTableAssocia…  delete      00:21
       ecs-public-subnet-2                                   AWS::EC2::Subnet                    delete      00:21
       ecs-public-subnet-2-assoc                             AWS::EC2::SubnetRouteTableAssocia…  delete      00:21
       ecs-task-exec-role                                    AWS::IAM::Role                      delete      00:21
       ecs-task-sg                                           AWS::EC2::SecurityGroup             delete      00:21
       ecs-task-sg-ingress                                   AWS::EC2::SecurityGroupIngress      delete      00:21
       ecs-tg                                                AWS::ElasticLoadBalancingV2::Targ…  delete      00:21
       ecs-vpc                                               AWS::EC2::VPC                       delete      00:22

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  →←: column  s: toggle sort  space: expand  d: details  esc: back  q: quit                                ?: help
destroy takes no --mode. It removes every resource in the forma, so there is nothing for reconcile or patch to differ on.

What’s next?

Write your first forma

Build a forma from scratch and learn how properties and resource references work.

Quick start with an AI assistant

Deploy by describing what you want to Claude Code, Codex, or another MCP client.

Core concepts

Understand labels, resources, stacks, targets, and formas.

Configure Pkl in your IDE

Set up your editor for Pkl authoring.

Architecture

See how the agent, CLI, and plugins fit together.