What the agent does
The agent clones https://github.com/terraform-aws-modules/terraform-aws-vpc into its sandbox and prices examples/complete, not the whole module in the abstract. That example's versions.tf requires Terraform >= 1.5.7 and hashicorp/aws >= 6.28. examples/complete/main.tf sets the provider region to eu-west-1, the VPC CIDR to 10.0.0.0/16, and azs to the first three names from data.aws_availability_zones.available. It passes private, public, database, elasticache, redshift and intra subnet lists, each built with cidrsubnet on that CIDR. The agent records those inputs before it counts resources, because the module's counts depend on them.
Billable objects are counted from the module, using the example's flags, and the agent does not run terraform apply. In main.tf, nat_gateway_count is 1 when single_nat_gateway is true, which the example sets, and aws_eip.nat is created once because enable_nat_gateway is true and reuse_nat_ips is not set (the EIP's domain is vpc). aws_vpn_gateway.this has count 1 because enable_vpn_gateway is true, with amazon_side_asn 64512. aws_customer_gateway.this is a for_each over customer_gateways, and the example defines IP1, IP2 and IP3, so three customer gateways. There is no aws_vpn_connection in the module, so the agent does not price a site-to-site VPN tunnel that this example never declares. module.disabled sets create_vpc = false and module.vpc_endpoints_nocreate sets create = false; both are left off the bill. ecs_telemetry sets create = false inside the endpoints map and is left off too.
VPC endpoints are the easy place to over-count. modules/vpc-endpoints/main.tf sets vpc_endpoint_type to the endpoint's service_type, defaulting to Interface when service_type is omitted. In the example, dynamodb sets service_type = Gateway and is one gateway endpoint. s3, ecs, ecr_api, ecr_dkr and rds omit service_type, so they are interface endpoints, and subnet_ids for those is module.vpc.private_subnets, three subnets in three AZs. A second module, vpc_endpoints_existing_sg, adds an sts interface endpoint. The example also calls terraform-aws-modules/security-group/aws ~> 6.0 to allow TCP 5432 from the VPC CIDR. That is a security group, not an RDS instance: the example contains no aws_db_instance, and the agent must not price a database that the configuration does not create.
Prices come from AWS's public pricing pages, opened in the sandbox browser, for eu-west-1, for one month. The agent writes the page URL and the figure it read next to each resource, and it states every assumption: hours in the month, data processed (this example launches no instances, so data is an assumption, not a measured quantity), and that interface endpoints are billed per AZ they are placed in. It does not apply the configuration. terraform init -backend=false and terraform validate are enough to confirm the example parses; a plan needs AWS credentials the sandbox does not have, and the report says so instead of pretending a plan ran.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "Clone https://github.com/terraform-aws-modules/terraform-aws-vpc. Price examples/complete only, for region eu-west-1. Read examples/complete/main.tf and the module resources it actually creates: NAT gateways and EIPs from single_nat_gateway, the VPN gateway, customer gateways, and VPC endpoints, using the default Interface type when service_type is omitted. Ignore module.disabled, vpc_endpoints_nocreate, and any endpoint with create = false. Do not run terraform apply and do not price a security group as an RDS instance. Open AWS's public pricing pages in the browser and write costs.md with each resource, the price you read, a monthly total, the assumptions, and the three biggest savings. If you cannot read a price, say so."
}- Get an API key. In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
- Send the request. POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
- Read what came back. Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.
What comes back
What comes back is costs.md, an artifact on the session, downloaded from the url on the session read (good for an hour, refreshed when you read the session again). The file is a table: resource address, count given the example's flags, the pricing-page URL, the unit price copied from that page, and the monthly line. A total follows, then the assumptions in a list, then three savings, each tied to a resource that is actually declared. Typical candidates a reviewer will see argued from this code, not asserted as fact, are the interface-typed S3 endpoint versus a gateway endpoint, the five other interface endpoints across three private subnets, and the VPN gateway created while no aws_vpn_connection exists.
Present tense: the report is a reading of public pages plus the HCL, not a bill. The transcript keeps the browser steps and any terraform validate output, so a number can be traced to the page the agent had open. Nothing is pushed and no pull request is opened. The clone stays in the sandbox.
A reviewer checks four things before using the total: the region is eu-west-1, disabled modules are absent, the S3 endpoint was priced as Interface because service_type is unset, and no line item is an RDS instance. They also check that data-processing charges are labeled as assumptions. If the pricing page has moved, a follow-up in the same session can ask the agent to re-read one URL; the parked sandbox still has the clone.
Run it on every change to the example or the module
Point this at your own Terraform, not only the public example. Replace the clone URL in the prompt with your repo, or send resources as [{"url": "https://github.com/your-org/your-app"}] so the Rush GitHub App clone is already there when the agent starts. One repository per run. A job on your server can POST the same body when the default branch changes, with the commit sha as the Idempotency-Key, so a retry returns the run already started.
Set webhook_url on the API key. Rush POSTs run.completed, run.failed or run.cancelled when the turn finishes, within about 30 seconds, with session_url. Your handler checks the Standard Webhooks signature and files costs.md on the pull request that changed the module. The webhook's result field holds the final answer only up to 16 KiB, so the cost table is taken from the artifact, not from result.
The use case this job follows, with its automation and trigger: Produce a report or file, no repo.
Why run it on Rush?
A cost reading on a laptop tends to become a spreadsheet that drifts from the HCL, and terraform apply against a sandbox account is how an estimate becomes a real NAT gateway. Here the agent is told not to apply. It reads the module's count expressions, opens the pricing pages in the sandbox browser, and leaves your AWS account untouched. The clone is discarded with the sandbox.
The proof is the pairing of a resource address with the page the price came from, kept in the transcript. You can disagree with an assumption without redoing the inventory. Several examples (complete, flow-log, ipam) can be separate runs at once, up to the key's max_concurrent, which defaults to 4; one more start is 429.
Frequently asked questions
Does it run terraform apply?
No. The prompt forbids apply. The agent may run terraform init -backend=false and terraform validate so it knows the example still parses. A plan needs credentials this request does not provide, and the report is supposed to say that rather than invent plan output. No resources are created in AWS.
Why is the S3 endpoint not treated as free?
Gateway endpoints and interface endpoints are different resources. dynamodb in examples/complete sets service_type = Gateway. The s3 endpoint does not set service_type, and modules/vpc-endpoints/main.tf defaults vpc_endpoint_type to Interface. The report prices that default. If you add service_type = Gateway, the line item changes.
Will the monthly total match my AWS bill?
No. The example creates network resources and no instances, so data-processing and idle-versus-busy are assumptions the file must list. The total is a reading of public list prices for eu-west-1 under those assumptions. Taxes, credits, Savings Plans and region differences are outside what this HCL says.
Can it price a private module in my organization?
Yes. Install the Rush GitHub App on the repository and pass it as resources with the repository URL. Leave the clone instruction out of the prompt in that case, because the agent starts with that repo already checked out. A repository no installation covers is 422 RESOURCE_NOT_ACCESSIBLE.