Shell Integration

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}")
    }
}