CLI Examples
These examples demonstrate using the salata CLI binary to process .slt files and output text to stdout. All examples live in the examples/cli/ directory of the repository.
To run any example:
salata --config examples/cli/<example>/config.toml examples/cli/<example>/<file>.slt
hello-world/
The simplest possible examples -- one .slt file per runtime, each printing a greeting. These are the best starting point for verifying that your runtimes are installed and configured correctly.
python.slt:
<python>
print("Hello from Python!")
</python>
ruby.slt:
<ruby>
puts "Hello from Ruby!"
</ruby>
javascript.slt:
<javascript>
println("Hello from JavaScript!");
</javascript>
typescript.slt:
<typescript>
const greeting: string = "Hello from TypeScript!";
println(greeting);
</typescript>
php.slt:
<php>
echo "Hello from PHP!\n";
</php>
shell.slt:
<shell>
echo "Hello from Shell!"
</shell>
Run all of them:
salata --config examples/cli/hello-world/config.toml examples/cli/hello-world/python.slt
salata --config examples/cli/hello-world/config.toml examples/cli/hello-world/ruby.slt
salata --config examples/cli/hello-world/config.toml examples/cli/hello-world/javascript.slt
salata --config examples/cli/hello-world/config.toml examples/cli/hello-world/typescript.slt
salata --config examples/cli/hello-world/config.toml examples/cli/hello-world/php.slt
salata --config examples/cli/hello-world/config.toml examples/cli/hello-world/shell.slt
data-processing/
Three examples demonstrating Salata as a data processing tool, producing formatted text output rather than HTML.
csv-table.slt -- Python processes inline CSV data into a formatted ASCII table:
<python>
import csv
import io
data = """name,role,department
Alice,Engineer,Backend
Bob,Designer,Frontend
Charlie,Manager,Operations
Diana,Engineer,Frontend
Eve,Analyst,Data"""
reader = csv.DictReader(io.StringIO(data))
rows = list(reader)
headers = rows[0].keys()
# Calculate column widths
widths = {h: max(len(h), max(len(r[h]) for r in rows)) for h in headers}
# Print header
header_line = " | ".join(h.ljust(widths[h]) for h in headers)
print(header_line)
print("-+-".join("-" * widths[h] for h in headers))
# Print rows
for row in rows:
print(" | ".join(row[h].ljust(widths[h]) for h in headers))
print(f"\nTotal: {len(rows)} records")
</python>
json-filter.slt -- Ruby filters and sorts an inline JSON array:
<ruby>
require 'json'
data = JSON.parse('[
{"name": "Alice", "age": 30, "city": "New York"},
{"name": "Bob", "age": 25, "city": "London"},
{"name": "Charlie", "age": 35, "city": "Tokyo"},
{"name": "Diana", "age": 28, "city": "Paris"},
{"name": "Eve", "age": 32, "city": "Berlin"}
]')
# Filter: age >= 28, sort by name
filtered = data
.select { |p| p["age"] >= 28 }
.sort_by { |p| p["name"] }
puts "People aged 28 and older (sorted by name):"
puts "=" * 40
filtered.each do |person|
puts " #{person['name']} (#{person['age']}) — #{person['city']}"
end
puts "=" * 40
puts "#{filtered.length} of #{data.length} matched"
</ruby>
system-report.slt -- Shell generates a system information report:
<shell>
echo "=== System Report ==="
echo ""
echo "Hostname: $(hostname)"
echo "Kernel: $(uname -sr)"
echo "Arch: $(uname -m)"
echo "Date: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
echo "--- Disk Usage ---"
df -h / | tail -1 | awk '{printf " Root: %s used of %s (%s)\n", $3, $2, $5}'
echo ""
echo "=== End Report ==="
</shell>
config-generator/
Demonstrates using Salata to generate configuration files. Multiple runtimes collaborate to produce a complete nginx configuration.
nginx.slt -- Shell detects the CPU count, Python computes upstream servers and outputs a full nginx.conf:
<shell>
# Detect available CPU cores for worker_processes
CORES=$(nproc || echo 2)
echo "$CORES"
</shell>
<python>
# Define upstream application servers
upstreams = [
("app1", "127.0.0.1", 8001),
("app2", "127.0.0.1", 8002),
("app3", "127.0.0.1", 8003),
]
cores = 2
print(f"""# Auto-generated nginx.conf
# Generated by Salata config-generator example
worker_processes {cores};
events {{
worker_connections 1024;
}}
http {{
upstream backend {{""")
for name, host, port in upstreams:
print(f" server {host}:{port}; # {name}")
print(""" }
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static/ {
root /var/www/html;
expires 30d;
}
}
}""")
</python>
Usage:
salata --config examples/cli/config-generator/config.toml examples/cli/config-generator/nginx.slt > nginx.conf
markdown-report/
Shows how to generate Markdown output using multiple runtimes, with cross-runtime data sharing via #set/#get.
report.slt -- Python computes project statistics, Ruby formats a Markdown table, Shell adds build metadata:
<python>
# Compute some statistics
projects = [
{"name": "Alpha", "status": "Complete", "tasks": 24, "done": 24},
{"name": "Beta", "status": "In Progress", "tasks": 18, "done": 12},
{"name": "Gamma", "status": "In Progress", "tasks": 30, "done": 21},
{"name": "Delta", "status": "Planning", "tasks": 15, "done": 0},
]
total_tasks = sum(p["tasks"] for p in projects)
total_done = sum(p["done"] for p in projects)
overall_pct = round(total_done / total_tasks * 100, 1)
#set("projects", projects)
#set("total_tasks", total_tasks)
#set("total_done", total_done)
#set("overall_pct", overall_pct)
</python>
<ruby>
projects = #get("projects")
total_tasks = #get("total_tasks")
total_done = #get("total_done")
overall_pct = #get("overall_pct")
puts "# Project Status Report"
puts ""
puts "**Overall Progress:** #{total_done}/#{total_tasks} tasks (#{overall_pct}%)"
puts ""
puts "| Project | Status | Progress |"
puts "|---------|-------------|-----------------|"
projects.each do |p|
pct = p["tasks"] > 0 ? (p["done"].to_f / p["tasks"] * 100).round(0) : 0
bar = "#" * (pct / 10) + "." * (10 - pct / 10)
puts "| #{p['name'].ljust(7)} | #{p['status'].ljust(11)} | #{p['done']}/#{p['tasks'].to_s.ljust(2)} [#{bar}] |"
end
puts ""
</ruby>
<shell>
echo "## Build Info"
echo ""
echo "- **Generated:** $(date '+%Y-%m-%d %H:%M:%S')"
echo "- **Host:** $(hostname)"
echo "- **Platform:** $(uname -s) $(uname -m)"
</shell>
Usage:
salata --config examples/cli/markdown-report/config.toml examples/cli/markdown-report/report.slt > report.md
cross-runtime-pipeline/
The flagship cross-runtime example: Python generates data, Ruby transforms it, JavaScript formats the output. This example has its own dedicated chapter -- see Cross-Runtime Pipeline for a full walkthrough.
scope-demo/
Two files demonstrating the difference between shared and isolated scope.
shared-scope.slt -- Two Python blocks that share a process. The second block can access variables defined in the first:
<python>
# First block: define variables
message = "Hello from the first block"
counter = 42
items = ["apple", "banana", "cherry"]
print(f"Block 1: Set message='{message}', counter={counter}")
</python>
Text between blocks — the Python process is still alive.
<python>
# Second block: access variables from the first block
# These variables are available because shared_scope = true (default)
print(f"Block 2: message='{message}'")
print(f"Block 2: counter={counter}")
print(f"Block 2: items={items}")
counter += 1
print(f"Block 2: incremented counter to {counter}")
</python>
isolated-scope.slt -- Two Python blocks with scope="isolated", each running in its own process. The second block cannot access the first block's variables:
<python scope="isolated">
# First block (isolated): define variables
message = "Hello from the first block"
counter = 42
print(f"Block 1: Set message='{message}', counter={counter}")
</python>
Text between blocks — each block gets a fresh Python process.
<python scope="isolated">
# Second block (isolated): try to access variables from block 1
# This will fail because scope="isolated" means a new process
try:
print(f"Block 2: message='{message}'")
except NameError as e:
print(f"Block 2: Cannot access 'message' — {e}")
try:
print(f"Block 2: counter={counter}")
except NameError as e:
print(f"Block 2: Cannot access 'counter' — {e}")
print("Block 2: Each isolated block starts fresh!")
</python>
json-api-mock/
Demonstrates using Salata to generate JSON output with the #content-type directive and cross-runtime data sharing.
api.slt:
#content-type application/json
<python>
import json
# Build the API response data
users = [
{"id": 1, "name": "Alice", "email": "alice@example.com", "role": "admin"},
{"id": 2, "name": "Bob", "email": "bob@example.com", "role": "user"},
{"id": 3, "name": "Charlie", "email": "charlie@example.com", "role": "user"},
]
#set("users", users)
</python>
<javascript>
const users = #get("users");
const response = {
status: "ok",
data: users,
meta: {
total: users.length,
page: 1,
per_page: 10
}
};
print(JSON.stringify(response, null, 2));
</javascript>
multi-format/
Three .slt files that take the same product inventory data and output it in three different formats: plain text, CSV, and YAML.
report.txt.slt -- Plain text table:
<python>
products = [
{"name": "Laptop", "price": 999.99, "stock": 45},
{"name": "Mouse", "price": 29.99, "stock": 200},
{"name": "Keyboard", "price": 79.99, "stock": 120},
{"name": "Monitor", "price": 449.99, "stock": 30},
]
print("PRODUCT INVENTORY REPORT")
print("=" * 45)
for p in products:
status = "LOW" if p["stock"] < 50 else "OK"
print(f" {p['name']:<12} ${p['price']:>8.2f} Stock: {p['stock']:>3} [{status}]")
print("=" * 45)
print(f" Total items: {sum(p['stock'] for p in products)}")
print(f" Total value: ${sum(p['price'] * p['stock'] for p in products):,.2f}")
</python>
report.csv.slt -- CSV format:
<python>
products = [
{"name": "Laptop", "price": 999.99, "stock": 45},
{"name": "Mouse", "price": 29.99, "stock": 200},
{"name": "Keyboard", "price": 79.99, "stock": 120},
{"name": "Monitor", "price": 449.99, "stock": 30},
]
print("name,price,stock,status")
for p in products:
status = "LOW" if p["stock"] < 50 else "OK"
print(f"{p['name']},{p['price']},{p['stock']},{status}")
</python>
report.yaml.slt -- YAML format:
<python>
products = [
{"name": "Laptop", "price": 999.99, "stock": 45},
{"name": "Mouse", "price": 29.99, "stock": 200},
{"name": "Keyboard", "price": 79.99, "stock": 120},
{"name": "Monitor", "price": 449.99, "stock": 30},
]
print("inventory:")
print(f" total_items: {sum(p['stock'] for p in products)}")
print(f" total_value: {sum(p['price'] * p['stock'] for p in products):.2f}")
print(" products:")
for p in products:
status = "low" if p["stock"] < 50 else "ok"
print(f" - name: {p['name']}")
print(f" price: {p['price']}")
print(f" stock: {p['stock']}")
print(f" status: {status}")
</python>
Usage:
salata --config examples/cli/multi-format/config.toml examples/cli/multi-format/report.txt.slt
salata --config examples/cli/multi-format/config.toml examples/cli/multi-format/report.csv.slt > report.csv
salata --config examples/cli/multi-format/config.toml examples/cli/multi-format/report.yaml.slt > report.yaml