Shell Integration
Weave integrates with shell commands using backtick syntax, giving you proper data structures to work with instead of raw text.
Running Commands
Surround a shell command with backticks:
result = `ls -la`The result is a container with three keys:
| Key | Description |
|---|---|
:success |
Boolean — did the command exit with code 0? |
:output |
String — stdout content |
:exit_code |
Number — the exit code |
result = `ls *.csv`
if result[:success] {
puts("CSV files:")
puts(result[:output])
} else {
puts("Command failed with code: " + result[:exit_code])
}String Interpolation in Commands
Weave’s {expr} interpolation works inside backticks:
dir = "/tmp"
files = `ls {dir}`
filename = "data.csv"
line_count = `wc -l {filename}`[:output]Shell Pipes
Standard shell pipes work inside backticks — the entire expression between the backticks is sent to the shell:
first_csvs = `ls *.csv | sort | head -n2`[:output]Processing Command Output
Combine shell output with Weave’s pipeline operators to process results:
# Get each line as a separate item
split(`ls *.csv`[:output], "\n")
*> ^(f) { puts("Found: " + f) }
# Find largest log files
result = `ls -lS /var/log/*.log 2>/dev/null | head -5`
if result[:success] {
split(result[:output], "\n")
*> ^(line) { split(line, " ")[-1] }
|> print
}Full Example: Log Analysis
Find the top 5 IP addresses by request count from access logs:
fn extract_ip(line) { split(line, " ")[0] }
fn count_occurrences(items) {
counts = []
items *> ^(item) {
current = if !counts[item] { 0 } else { counts[item] }
counts[item] = current + 1
}
counts
}
split(`cat /var/log/nginx/access.log`[:output], "\n")
*> extract_ip
|> count_occurrences
|> ^(c) { c.sort(:desc) }
|> ^(counts) {
i = 0
while i < 5 {
ip = counts.keys[i]
puts(ip + ": " + counts[ip])
i += 1
}
}When to Use Shell vs Native Weave
Use shell commands when you need to call external tools, leverage existing CLI pipelines, or interact with the system (processes, network, filesystem operations beyond read/write).
Use native Weave for data transformation, structured format handling, and anything where you want typed data instead of string parsing.
The two combine naturally:
# Shell to get the data, Weave to process it
raw_output = `kubectl get pods -o json`
if raw_output[:success] {
pods = read(raw_output[:output], :json)[:items]
pods *> ^(p) {
name = p[:metadata][:name]
status = p[:status][:phase]
puts("{name}: {status}")
}
}