# Rash - Rust to Shell Transpiler
[](https://crates.io/crates/bashrs)
[](https://docs.rs/bashrs)
[](LICENSE)
[](https://github.com/paiml/bashrs/actions)
[](https://github.com/paiml/bashrs/actions)
[](https://github.com/paiml/bashrs/actions)
[-blue)](https://github.com/paiml/bashrs/blob/main/rash/tests/)
**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:
```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:
```bash
$ bashrs build install.rs -o install.sh
$ cat install.sh
#!/bin/sh
# Generated by Rash v0.4.0
# 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)
```bash
cargo install bashrs
```
### Binary Releases
Pre-built binaries are available for Linux and macOS:
```bash
# 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
### Using cargo-binstall
```bash
cargo binstall bashrs
```
### From Source
```bash
# 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
```bash
# 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
```bash
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
```rust
let name = "Alice"; // String literals
let count = 42; // Integers (including negatives: -42)
let flag = true; // Booleans
let user = env("USER"); // Environment variables
let result = capture("date"); // Command output
```
#### Arithmetic Operations
```rust
let x = 1 + 2; // Addition โ $((1 + 2))
let y = 10 - 3; // Subtraction โ $((10 - 3))
let z = 4 * 5; // Multiplication โ $((4 * 5))
let w = 20 / 4; // Division โ $((20 / 4))
```
#### Comparison Operators
```rust
if x > 0 { // Greater than โ [ "$x" -gt 0 ]
println!("Positive"); // println! macro supported
}
if y == 5 { ... } // Equal โ [ "$y" -eq 5 ]
if z < 10 { ... } // Less than โ [ "$z" -lt 10 ]
```
#### User-Defined Functions
```rust
fn add(a: i32, b: i32) -> i32 {
a + b // Return value via echo
}
fn main() {
let sum = add(1, 2); // Captured with $(add 1 2)
println!("Sum: {}", sum);
}
```
#### Built-in Functions
```rust
// I/O operations
echo("Hello, World!"); // Print to stdout
println!("Hello, World!"); // println! macro (Sprint 10)
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
```rust
// Conditionals
if condition {
// ...
} else if other {
// ...
} else {
// ...
}
// โ ๏ธ Pattern matching - Not yet supported (P2 backlog)
// match value {
// "linux" => echo("Linux detected"),
// "darwin" => echo("macOS detected"),
// _ => echo("Unknown OS"),
// }
```
#### Loops
```rust
// โ ๏ธ For loops - Not yet supported (P2 backlog)
// for i in 0..10 {
// echo("Iteration: {i}");
// }
// โ ๏ธ While loops - Not yet supported
// 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:
```rust
let user_input = env("UNTRUSTED");
exec("echo {user_input}"); // Safe: becomes echo "$user_input"
```
## Examples
See the [`examples/`](examples/) directory for complete examples:
- **Basic**
- [Hello World](examples/basic/hello_world.rs) - Simplest example
- [Variables](examples/basic/variables.rs) - Variable usage and escaping
- [Functions](examples/basic/functions.rs) - Built-in functions
- **Control Flow**
- [Conditionals](examples/control_flow/conditionals.rs) - If/else statements
- [Loops](examples/control_flow/loops.rs) - Bounded iteration
- **Safety**
- [Injection Prevention](examples/safety/injection_prevention.rs) - Security examples
- [String Escaping](examples/safety/escaping.rs) - Special character handling
- **Real-World**
- [Minimal Installer](examples/bootstrap/minimal_installer.rs) - Bootstrap script
## Shell Compatibility
Generated scripts are tested on:
| 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:
- **21.1ยตs** transpile time for simple scripts (100x better than target!)
- Memory usage <10MB for most scripts
- Generated scripts add minimal overhead (~20 lines boilerplate)
## Quality Metrics (v0.4.0)
| Tests | 520/520 โ
|
| Property Tests | 23 (~13,300 cases) โ
|
| Coverage | 85.36% โ
|
| Complexity | <10 cognitive โ
|
| Performance | 21ยตs โ
|
| ShellCheck | 24/24 pass โ
|
| Edge Cases Fixed | 7/11 (64%) ๐ก |
**Production Ready**: All P0 (critical) and P1 (high priority) edge cases resolved.
## Contributing
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
### Development Setup
```bash
# 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](LICENSE) for details.
## Acknowledgments
Rash is built with safety principles inspired by:
- [ShellCheck](https://www.shellcheck.net/) for shell script analysis
- [Oil Shell](https://www.oilshell.org/) for shell language design
- The Rust community for memory safety practices
## Roadmap
**Completed (v0.4.0)**:
- [x] Core transpilation engine
- [x] Basic safety validation
- [x] ShellCheck compliance (24/24 tests)
- [x] Property-based testing (23 properties, ~13,300 cases)
- [x] Arithmetic expressions (`$((expr))`)
- [x] Function return values
- [x] Negative integers
- [x] Integer comparisons
- [x] `println!` macro
- [x] Global function scope
- [x] MCP server (rash-mcp)
**In Progress**:
- [ ] For loops (P2 - parser work required)
- [ ] Match expressions (P2 - pattern matching)
**Future**:
- [ ] Language server (LSP)
- [ ] Incremental compilation
- [ ] More shell targets (fish, PowerShell)
- [ ] Package manager integration
See [ROADMAP.md](ROADMAP.md) for detailed sprint planning.