bashrs 0.3.3

Rust-to-Shell transpiler for deterministic bootstrap scripts
Documentation

Rash - Rust to Shell Transpiler

Crates.io Documentation License CI Coverage Tests QuickCheck

Rash transpiles a safe subset of Rust to POSIX-compliant shell scripts, enabling you to write maintainable and type-safe shell scripts using familiar Rust syntax.

Why Rash?

  • 🛡️ Safety First: Automatic protection against shell injection attacks
  • 🔍 Compile-Time Verification: Catch errors before deployment
  • 📦 Zero Runtime Dependencies: Generated scripts work on any POSIX shell
  • 🎯 Deterministic Output: Same input always produces identical scripts
  • ShellCheck Compliant: All output passes strict linting

Quick Start

Write Rust:

// install.rs
#[rash::main]
fn main() {
    let version = env_var_or("VERSION", "1.0.0");
    let prefix = env_var_or("PREFIX", "/usr/local");
    
    echo("Installing MyApp {version} to {prefix}");
    
    // Create installation directories
    mkdir_p("{prefix}/bin");
    mkdir_p("{prefix}/share/myapp");
    
    // Copy files (with automatic quoting)
    if exec("cp myapp {prefix}/bin/") {
        echo("✓ Binary installed");
    } else {
        echo("✗ Failed to install binary");
        exit(1);
    }
}

Get POSIX shell:

$ bashrs build install.rs -o install.sh
$ cat install.sh
#!/bin/sh
# Generated by Rash v0.3.1
# POSIX-compliant shell script

set -euf
IFS=' 	
'
export LC_ALL=C

# Rash runtime functions
rash_require() {
    if ! "$@"; then
        echo "FATAL: Requirement failed: $*" >&2
        exit 1
    fi
}

# Main script begins
main() {
    VERSION="${VERSION:-1.0.0}"
    PREFIX="${PREFIX:-/usr/local}"
    
    echo "Installing MyApp $VERSION to $PREFIX"
    
    mkdir -p "$PREFIX/bin"
    mkdir -p "$PREFIX/share/myapp"
    
    if cp myapp "$PREFIX/bin/"; then
        echo "✓ Binary installed"
    else
        echo "✗ Failed to install binary"
        exit 1
    fi
}

# Execute main function
main "$@"

Installation

From crates.io (Recommended)

cargo install bashrs

Binary Releases

Pre-built binaries are available for Linux and macOS:

# Linux x86_64
curl -L https://github.com/paiml/bashrs/releases/latest/download/bashrs-x86_64-unknown-linux-musl.tar.gz | tar xz

# macOS x86_64
curl -L https://github.com/paiml/bashrs/releases/latest/download/bashrs-x86_64-apple-darwin.tar.gz | tar xz

# macOS ARM64
curl -L https://github.com/paiml/bashrs/releases/latest/download/bashrs-aarch64-apple-darwin.tar.gz | tar xz

Using cargo-binstall

cargo binstall bashrs

From Source

# Full build with all features
cargo install --git https://github.com/paiml/bashrs

# Minimal build (smaller binary, ~2MB)
cargo install --git https://github.com/paiml/bashrs --no-default-features --features minimal

Usage

Basic Commands

# Transpile a Rust file to shell
bashrs build input.rs -o output.sh

# Check if a file is valid Rash
bashrs check input.rs

# Verify safety properties
bashrs verify input.rs --verify strict

# Start interactive playground (if built with playground feature)
bashrs playground

CLI Options

USAGE:
    bashrs [OPTIONS] <COMMAND>

COMMANDS:
    build       Transpile Rust to shell script
    check       Validate Rust source without transpiling
    verify      Run formal verification
    inspect     Analyze AST and safety properties
    playground  Interactive development environment (requires feature)

OPTIONS:
    -v, --verbose    Enable verbose output
    -V, --version    Print version information
    -h, --help       Print help information

BUILD OPTIONS:
    -o, --output <FILE>      Output file (default: stdout)
    -O, --optimize <LEVEL>   Optimization level: none, size, readability (default: readability)
    -t, --target <SHELL>     Target shell: posix, bash, ash (default: posix)
    --verify <LEVEL>         Verification level: none, basic, strict, paranoid

Language Features

Supported Rust Subset

Rash supports a carefully chosen subset of Rust that maps cleanly to shell:

Variables and Types

let name = "Alice";              // String literals
let count = 42;                  // Integers  
let flag = true;                 // Booleans
let user = env("USER");          // Environment variables
let result = capture("date");    // Command output

Functions (Built-ins only)

// I/O operations
echo("Hello, World!");           // Print to stdout
eprint("Error!");                // Print to stderr

// File system
mkdir_p("/tmp/myapp");           // Create directory recursively
write_file("config.txt", data);  // Write file
let content = read_file("config.txt");  // Read file
if path_exists("/etc/config") { ... }   // Check path

// Process management  
exec("ls -la");                  // Run command
let output = capture("date");    // Capture command output
exit(0);                         // Exit with code

// Environment
set_env("KEY", "value");         // Set environment variable
let val = env("KEY");            // Get environment variable
let val = env_var_or("KEY", "default"); // With default

Control Flow

// Conditionals
if condition {
    // ...
} else if other {
    // ...  
} else {
    // ...
}

// Pattern matching (limited)
match value {
    "linux" => echo("Linux detected"),
    "darwin" => echo("macOS detected"),
    _ => echo("Unknown OS"),
}

Loops (requires loops feature)

// Bounded iteration only
for i in 0..10 {
    echo("Iteration: {i}");
}

// While loops must have explicit bounds
let mut count = 0;
while count < 10 {
    count = count + 1;
}

Safety Features

All generated scripts are protected against:

  • Command Injection: All variables are properly quoted
  • Path Traversal: Paths are validated and escaped
  • Glob Expansion: Glob patterns are quoted when needed
  • Word Splitting: IFS is set to safe value
  • Undefined Variables: set -u catches undefined vars

Example of automatic safety:

let user_input = env("UNTRUSTED");
exec("echo {user_input}");  // Safe: becomes echo "$user_input"

Examples

See the examples/ directory for complete examples:

Shell Compatibility

Generated scripts are tested on:

Shell Version Status
POSIX sh - ✅ Full support
dash 0.5.11+ ✅ Full support
bash 3.2+ ✅ Full support
ash (BusyBox) 1.30+ ✅ Full support
zsh 5.0+ ✅ Full support
mksh R59+ ✅ Full support

Performance

Rash is designed for fast transpilation:

  • Typical scripts transpile in <10ms
  • Memory usage <10MB for most scripts
  • Generated scripts add minimal overhead (~20 lines boilerplate)

Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

# Clone the repository
git clone https://github.com/paiml/rash.git
cd rash

# Run tests
make test

# Run with all checks
make validate

# Build release binary
make release

License

Rash is licensed under the MIT License. See LICENSE for details.

Acknowledgments

Rash is built with safety principles inspired by:

  • ShellCheck for shell script analysis
  • Oil Shell for shell language design
  • The Rust community for memory safety practices

Roadmap

  • Core transpilation engine
  • Basic safety validation
  • ShellCheck compliance
  • Property-based testing
  • Language server (LSP)
  • Incremental compilation
  • More shell targets (fish, PowerShell)
  • Package manager integration