JC
Julissa Cotillo
Back to blog
terraformaideploymentinfrastructuregcpclaude-codeautomationmastra

From Vibe Code to Live: The Terraform Wrapper That Teaches Your Agent to Deploy

Jan 17, 2025/8 min read

Last month I built a Mastra AI app with Claude. The code flowed easily. Within hours I had a working application with vector search, tool integrations, and a polished frontend. I pushed to Vercel, hit deploy, and watched the build fail. The bundle was too big. The serverless functions timed out. My little side project had outgrown the free tier.

So I asked Claude to help me deploy to GCP Cloud Run instead. What followed was painful. I watched the agent burn through hundreds of tokens reading Terraform documentation from scratch. It asked me about regions I had already decided on in previous projects. It stumbled on GCP-specific gotchas like enabling APIs and setting up service accounts. Thirty minutes and a small fortune in tokens later, I had a working deployment.

Then it hit me: what if I taught the agent once and never had to teach it again?


The Problem: Vibe Code Does Not Deploy Itself

Vibe coding is real. Modern AI agents help you build fast. You describe what you want, the code appears, you refine it through conversation, and suddenly you have a working application. The creative friction has almost disappeared.

But deployment is where side projects go to die.

Every time you ask an agent to deploy your app, it starts from zero. It reads Terraform documentation like it has never seen it before. It makes decisions you have already made in other projects. Which region? What naming conventions? How should scaling work? Each session, you pay tokens for the agent to rediscover the same answers.

The GCP-specific problems are even worse. Did you enable the Cloud Run API? What about Artifact Registry? Do you have a service account with the right IAM bindings? These are not complex questions, but they require tribal knowledge that gets lost between sessions.

The irony is stark. You are paying real money for an AI agent to figure out the same deployment patterns you solved last week. And next week, you will pay again.

I knew there had to be a better way.


The Solution: A Terraform Skill Plus Module Pattern

The fix is a two-part system that gives your agent permanent deployment knowledge:

  1. Skill file - A markdown file that teaches the agent your patterns, conventions, and GCP project setup. It triggers automatically when you mention deployment.

  2. Terraform modules - Reusable infrastructure components the agent can invoke with minimal configuration. The heavy lifting is already done.

The key insight is simple: teach once, deploy forever. After a session or two of refinement, your agent knows exactly how to deploy any app to your infrastructure. No more re-reading docs. No more decision fatigue. No more burning tokens on boilerplate.

This pattern works natively with Claude Code skills, but the concept adapts to any agent system with custom instructions or context.


The Skill File: Teaching Your Agent

The skill file is where you encode your deployment knowledge. It lives alongside your Terraform modules and teaches the agent when to activate, what conventions to follow, and which modules to use.

Here is a complete example:

--- name: deploy-to-gcp triggers: - deploy - go live - ship to cloud - push to gcp - cloud run --- # GCP Deployment Skill When the user wants to deploy an application, use this skill to generate Terraform configuration for GCP Cloud Run. ## Conventions - **Project ID**: my-gcp-project-id - **Region**: us-central1 - **Naming**: {app-name}-{environment} (e.g., mastra-app-prod) - **Docker registry**: us-central1-docker.pkg.dev/my-gcp-project-id ## Required APIs (enable before first deploy) - run.googleapis.com - artifactregistry.googleapis.com - iam.googleapis.com ## Default Configuration - Min instances: 0 (scale to zero for cost savings) - Max instances: 10 - Memory: 512Mi - Timeout: 300s - Ingress: Allow all traffic ## Module Library Use the cloud-run module at `./modules/cloud-run` for deployments. The module handles: - Artifact Registry repository creation - Cloud Run v2 service with production defaults - Service account with minimal permissions - Public access configuration - GitHub Actions service account for CI/CD ## Usage Pattern 1. Ask the user for the app name and any custom settings 2. Generate a main.tf that calls the cloud-run module 3. Include backend configuration for state storage 4. Output the terraform commands to run
markdown

This file tells Claude Code exactly what to do when deployment comes up. The agent knows your project ID, your preferred region, your naming conventions, and which module to use. No more guessing. No more re-reading docs.


The Terraform Module: Cloud Run Deployment

The Terraform module does the actual infrastructure work. I based this on patterns from real deployments, handling all the GCP-specific complexity that trips up agents.

# modules/cloud-run/main.tf variable "app_name" { description = "Name of the application" type = string } variable "project_id" { description = "GCP project ID" type = string } variable "region" { description = "GCP region" type = string default = "us-central1" } variable "memory" { description = "Memory allocation" type = string default = "512Mi" } # Enable required APIs resource "google_project_service" "run" { project = var.project_id service = "run.googleapis.com" } resource "google_project_service" "artifactregistry" { project = var.project_id service = "artifactregistry.googleapis.com" } # Artifact Registry for Docker images resource "google_artifact_registry_repository" "app" { project = var.project_id location = var.region repository_id = var.app_name format = "DOCKER" depends_on = [google_project_service.artifactregistry] } # Service account for the Cloud Run service resource "google_service_account" "app" { project = var.project_id account_id = "${var.app_name}-sa" display_name = "Service account for ${var.app_name}" } # Cloud Run v2 service resource "google_cloud_run_v2_service" "app" { project = var.project_id name = var.app_name location = var.region ingress = "INGRESS_TRAFFIC_ALL" template { service_account = google_service_account.app.email containers { image = "${var.region}-docker.pkg.dev/${var.project_id}/${var.app_name}/${var.app_name}:latest" resources { limits = { memory = var.memory cpu = "1" } } } scaling { min_instance_count = 0 max_instance_count = 10 } } depends_on = [google_project_service.run] } # Allow unauthenticated access resource "google_cloud_run_v2_service_iam_member" "public" { project = var.project_id location = var.region name = google_cloud_run_v2_service.app.name role = "roles/run.invoker" member = "allUsers" } output "service_url" { value = google_cloud_run_v2_service.app.uri } output "registry_url" { value = "${var.region}-docker.pkg.dev/${var.project_id}/${var.app_name}" } output "next_steps" { value = <<-EOT Next steps: 1. Build your Docker image: docker build -t ${var.region}-docker.pkg.dev/${var.project_id}/${var.app_name}/${var.app_name}:latest . 2. Push to registry: docker push ${var.region}-docker.pkg.dev/${var.project_id}/${var.app_name}/${var.app_name}:latest 3. Your app will be live at: ${google_cloud_run_v2_service.app.uri} EOT }
hcl

This module handles everything: API enabling, registry creation, service accounts, IAM bindings, and Cloud Run configuration. When the agent calls this module, it just needs to provide the app name. Everything else uses sensible defaults that the skill file teaches it to customize when needed.


How It Works in Practice

With the skill and module in place, deployment becomes a conversation:

You: "Deploy this app to Cloud Run"

Agent: Reads the skill, understands the conventions, generates Terraform:

module "mastra_app" { source = "./modules/cloud-run" app_name = "mastra-app" project_id = "my-gcp-project-id" region = "us-central1" memory = "1Gi" }
hcl

You: terraform init && terraform apply

Result: Live app in minutes.

Here is the flow visualized:

graph LR A["Vibe Code Your App"] --> B["Say 'deploy to Cloud Run'"] B --> C["Agent Reads Skill File"] C --> D["Agent Generates Terraform"] D --> E["terraform apply"] E --> F["Live on Cloud Run"]
mermaid

The difference is dramatic:

BeforeAfter
500+ tokens per deployment50 tokens
30 minutes of back-and-forthWorks first try
Re-learns GCP quirks each timePermanent knowledge
Often fails on first attemptReliable every time

Wrapping It for Other Agents

This pattern is not locked to Claude Code. The core idea—encode deployment knowledge in accessible files—works anywhere.

For Gemini: Add the skill content to your system prompt or custom instructions. Reference the module documentation in your context window.

For Cursor: Use a rules file or mention the skill with @ syntax. The module lives in your codebase and gets indexed automatically.

For any agent: The key is knowledge transfer. Once you have documented your conventions and created reusable modules, any sufficiently capable agent can deploy your apps.

Consider open-sourcing your modules. The community benefits when we share deployment patterns. Your Cloud Run module might save someone else the same token-burning journey you went through.


Conclusion

Vibe coding gets you to a working prototype in hours. But prototypes do not pay bills or serve users. The gap between working locally and running in production is where projects stall.

The Terraform wrapper pattern closes that gap. Teach your agent once—your conventions, your cloud setup, your modules—and it deploys anything without relearning. My Mastra app is now live on Cloud Run, costing about five dollars a month and scaling automatically.

The pattern pays for itself immediately. Fewer tokens spent, faster deployments, more time building the things that matter.

Stop teaching your agent the same lessons every session. Write the skill once. Build the module once. Deploy forever.