Tilt Cheat Sheet
Overview
Tilt is a development environment tool for teams building microservices on Kubernetes. It watches files, rebuilds containers, and updates running services in real-time. Tilt provides a web-based dashboard showing build status, logs, and resource health across all your services, making it easy to develop multi-service applications.
Tilt uses a Starlark-based configuration file (Tiltfile) that defines how to build, deploy, and manage services. It supports smart rebuilds that sync only changed files rather than rebuilding entire containers, live_update for sub-second code reload, and extensible functions for custom workflows.
Installation
# macOS
brew install tilt-dev/tap/tilt
# Linux
curl -fsSL https://raw.githubusercontent.com/tilt-dev/tilt/master/scripts/install.sh | bash
# Windows
scoop install tilt
# Go install
go install github.com/tilt-dev/tilt/cmd/tilt@latest
# Verify
tilt version
Core Commands
| Command | Description |
|---|---|
tilt up | Start Tilt (builds, deploys, watches) |
tilt down | Tear down all resources |
tilt ci | Run in CI mode (exits on completion) |
tilt demo | Run the demo project |
tilt logs | Stream logs from all services |
tilt get | Get resource status |
tilt trigger <name> | Manually trigger a resource update |
tilt disable <name> | Disable a resource |
tilt enable <name> | Enable a resource |
tilt doctor | Diagnose common issues |
Tiltfile Configuration
Basic Tiltfile
# Tiltfile
# Build a Docker image
docker_build('my-app', '.',
dockerfile='Dockerfile',
build_args={'NODE_ENV': 'development'})
# Deploy Kubernetes manifests
k8s_yaml('k8s/deployment.yaml')
# Set up port forwarding
k8s_resource('my-app', port_forwards='8080:8080')
Live Update (Hot Reload)
# Tiltfile with live_update for fast iteration
docker_build('my-app', '.',
live_update=[
# Sync changed files to container
sync('./src', '/app/src'),
sync('./package.json', '/app/package.json'),
# Run npm install when package.json changes
run('npm install', trigger=['package.json']),
# Restart process when config changes
restart_container(),
])
k8s_yaml('k8s/deployment.yaml')
k8s_resource('my-app', port_forwards='3000:3000')
Multi-Service Setup
# Tiltfile for microservices
# Frontend
docker_build('frontend', './frontend',
live_update=[
sync('./frontend/src', '/app/src'),
])
# Backend API
docker_build('backend', './backend',
live_update=[
sync('./backend/src', '/app/src'),
run('pip install -r requirements.txt', trigger=['requirements.txt']),
])
# Worker service
docker_build('worker', './worker')
# Deploy all manifests
k8s_yaml([
'k8s/frontend.yaml',
'k8s/backend.yaml',
'k8s/worker.yaml',
'k8s/database.yaml',
])
# Port forwarding
k8s_resource('frontend', port_forwards='3000:3000')
k8s_resource('backend', port_forwards='8000:8000')
k8s_resource('postgres', port_forwards='5432:5432')
Configuration
Helm Integration
# Deploy with Helm
k8s_yaml(helm(
'charts/my-app',
name='my-release',
namespace='dev',
values=['charts/my-app/values-dev.yaml'],
set=[
'image.repository=my-app',
'replicaCount=1',
]))
Kustomize Integration
# Deploy with Kustomize
k8s_yaml(kustomize('kustomize/overlays/dev'))
Resource Configuration
# Group and configure resources
k8s_resource('backend',
port_forwards='8000:8000',
labels=['api'],
resource_deps=['postgres'],
auto_init=True,
trigger_mode=TRIGGER_MODE_AUTO)
k8s_resource('postgres',
port_forwards='5432:5432',
labels=['database'])
# Custom resource grouping
k8s_resource('frontend', labels=['web'])
k8s_resource('nginx', labels=['web'])
Local Resources
# Run local commands (not in Kubernetes)
local_resource('compile-proto',
cmd='protoc --go_out=. proto/*.proto',
deps=['proto/'],
labels=['codegen'])
local_resource('npm-install',
cmd='cd frontend && npm install',
deps=['frontend/package.json'],
labels=['setup'])
# Serve local process
local_resource('docs',
serve_cmd='cd docs && mkdocs serve',
links=['http://localhost:8000'],
labels=['docs'])
Advanced Usage
Custom Build
# Custom build command (not Docker)
custom_build('my-app',
command='bazel build //app:image && bazel run //app:image',
deps=['app/'],
tag='dev')
# Build with ko (Go)
custom_build('my-go-app',
command='ko build ./cmd/server -B -t $EXPECTED_REF',
deps=['cmd/', 'pkg/'])
Extensions
# Load extensions from tilt-extensions repo
load('ext://restart_process', 'docker_build_with_restart')
load('ext://namespace', 'namespace_create')
load('ext://helm_remote', 'helm_remote')
load('ext://secret', 'secret_from_dict')
# Create namespace
namespace_create('dev')
# Deploy remote Helm chart
helm_remote('redis',
repo_name='bitnami',
repo_url='https://charts.bitnami.com/bitnami',
namespace='dev')
# Create Kubernetes secret
k8s_yaml(secret_from_dict('my-secret', inputs={
'api-key': os.environ.get('API_KEY', 'dev-key'),
}))
Buttons and UI Links
# Add custom buttons to Tilt UI
load('ext://uibutton', 'cmd_button')
cmd_button('seed-db',
argv=['python', 'scripts/seed.py'],
resource='backend',
text='Seed Database',
icon_name='database')
# Add links to resources
k8s_resource('frontend',
links=[
link('http://localhost:3000', 'App'),
link('http://localhost:3000/admin', 'Admin'),
])
CI Mode
# Tiltfile CI configuration
config.define_bool('ci')
cfg = config.parse()
if cfg.get('ci'):
# CI-specific settings
update_settings(max_parallel_updates=1)
analytics_settings(enable=False)
# Run in CI mode (exits after resources are ready)
tilt ci
# CI with timeout
tilt ci --timeout 10m
Troubleshooting
| Issue | Solution |
|---|---|
| Slow rebuilds | Use live_update to sync files instead of rebuilding |
| Port forward fails | Check port conflicts; verify service is running |
| Live update not triggering | Verify sync paths match your file structure |
| OOM on local cluster | Reduce replica counts; increase Docker memory |
| Extension not loading | Check load() path; run tilt doctor |
| Resource stuck pending | Check tilt logs <resource>; verify image pull |
# Diagnose issues
tilt doctor
# View all resource status
tilt get
# Stream logs for specific resource
tilt logs backend
# Trigger manual rebuild
tilt trigger backend
# Clean everything
tilt down --delete-namespaces
# Verbose mode
tilt up --verbose