Self-Documenting Scripts
Lambda Smalltalk's syntax reads like English. Your scripts become their own documentation.
The Problem with Traditional Scripts
Shell script:
#!/bin/bash
for h in $(cat hosts.txt); do
ssh $h "systemctl restart nginx" && \
curl -s -o /dev/null -w "%{http_code}" http://$h/health | grep -q 200 && \
echo "$h: OK" || echo "$h: FAILED"
done
What does this do? You need to parse the syntax mentally.
Python:
for host in open('hosts.txt'):
subprocess.run(['ssh', host.strip(), 'systemctl restart nginx'])
r = requests.get(f'http://{host.strip()}/health')
print(f"{host.strip()}: {'OK' if r.status_code == 200 else 'FAILED'}")
Better, but still requires programming knowledge to read.
The Smalltalk Way
"Restart nginx on all servers and verify health"
hosts := (File read: 'hosts.txt') lines.
hosts do: [:host |
host restart: 'nginx'.
(host healthCheck)
ifTrue: [ (host, ': OK') printNl ]
ifFalse: [ (host, ': FAILED') printNl ].
].
Read it aloud:
- "For each host, restart nginx"
- "If health check passes, print OK"
- "Otherwise, print FAILED"
The code is the documentation.
Why This Matters
1. Auditable Operations
When regulators ask "what does this script do?", you can show them the code directly:
"Daily backup procedure"
Database dump: 'production' to: '/backup/daily/'.
S3 upload: '/backup/daily/' to: 'company-backups' prefix: (Date today asString).
Slack notify: '#ops' message: 'Daily backup completed'.
No separate runbook needed. The script is the runbook.
2. Reduced Bus Factor
New team members can read and understand operations scripts immediately:
"Deploy to staging"
Git pull: 'origin/main'.
Docker build: '.' tag: 'app:staging'.
Kubernetes apply: 'k8s/staging.yaml'.
(App healthCheck: 'staging')
ifTrue: [ Slack notify: 'Staging deploy successful' ]
ifFalse: [ Slack notify: 'Staging deploy FAILED' ].
No tribal knowledge required.
3. Fewer Mistakes
When the intent is clear, mistakes are obvious:
"Archive old logs (WRONG - deletes instead of archiving!)"
Logs olderThan: 30 days delete.
"Archive old logs (CORRECT)"
Logs olderThan: 30 days moveTo: '/archive/'.
The bug is visible to anyone who reads the code.
Real-World Patterns
Health Monitoring
"Check all services every 5 minutes"
services := #('web-01' 'web-02' 'db-primary' 'cache-01').
services do: [:svc |
(svc isHealthy) ifFalse: [
PagerDuty alert: svc , ' is DOWN'.
svc restart.
(svc isHealthy)
ifTrue: [ PagerDuty resolve: svc , ' recovered after restart' ]
ifFalse: [ PagerDuty escalate: svc , ' still DOWN after restart' ].
].
].
Data Pipeline
"ETL: Extract from source, transform, load to warehouse"
data := Postgres query: 'SELECT * FROM events WHERE date = today()'.
data := data
select: [:row | row at: 'status' = 'completed']
collect: [:row | row transform: TransformRules].
BigQuery insert: data into: 'analytics.daily_events'.
('Processed ', data size asString, ' records') printNl.
Deployment with Rollback
"Blue-green deployment with automatic rollback"
| previousVersion |
previousVersion := App currentVersion.
App deploy: newVersion to: 'green'.
(App healthCheck: 'green')
ifTrue: [
LoadBalancer switchTo: 'green'.
Slack notify: 'Deployed ', newVersion, ' successfully'.
]
ifFalse: [
App rollbackTo: previousVersion.
Slack notify: 'Deploy failed, rolled back to ', previousVersion.
PagerDuty alert: 'Deployment failure'.
].
Getting Started
Lambda Smalltalk provides the building blocks. Combine them with:
- Shell integration:
System run: 'any shell command' - HTTP client:
Http get:,Http post:body: - File operations:
File read:,File write:content: - JSON/YAML/TOML:
Json parse:,Yaml parse: - Plugins: Extend with Rust for complex operations
See Examples for more patterns.