Run Command
The utah run command compiles and immediately executes Utah (.shx) scripts or individual commands without creating persistent .sh files. This is ideal for development, testing, one-off script execution, and quick command testing.
You can now run .shx files and commands directly without the
runcommand! See Direct Execution for details.
Basic Usage
# Run a .shx file
utah run <file.shx>
# Run a .shx file with arguments
utah run <file.shx> -- [script-args...]
# Run a single command directly
utah run -c <command>
utah run --command <command>
# Direct execution (new, shorter syntax)
utah <file.shx>
utah <file.shx> -- [script-args...]
utah -c <command>
utah --command <command>
Examples
File Execution
# Traditional syntax
utah run hello.shx
# New direct execution syntax
utah hello.shx
# With arguments
utah run script.shx -- --name "John" --verbose
utah script.shx -- --config production.yml
Direct Command Execution
# Traditional syntax
utah run -c "console.log('Hello, World!')"
# New direct execution syntax
utah -c "console.log('Hello, World!')"
# Check if a package is installed
utah --command "os.isInstalled('git')"
# File operations
utah -c "console.log(fs.exists('/etc/passwd'))"
# JSON operations
utah --command "json.installDependencies()"
# Multiple statements (use quotes to wrap the entire command)
utah -c "let name: string = \"Utah\"; console.log(\"Hello from \${name}!\");"
With Arguments
Utah scripts can access command-line arguments through the args namespace. To pass arguments to your script, use the -- separator to distinguish between Utah CLI options and script arguments:
script.shx:
script.description("Example script with arguments");
args.define("--name", "-n", "Your name", "string", true);
args.define("--count", "-c", "Number of greetings", "number", false, 1);
let name: string = args.get("--name");
let count: number = args.get("--count");
for (let i: number = 0; i < count; i++) {
  console.log("Hello, ${name}!");
}
Running with arguments:
# Pass arguments to the script using -- separator
utah run script.shx -- --name "Alice" --count 3
# Direct execution syntax also supports arguments
utah script.shx -- --name "Bob" --count 2
# Show script help
utah run script.shx -- --help
Output:
Hello, Alice!
Hello, Alice!
Hello, Alice!
Important: The
--separator is required when passing arguments to scripts. Everything before--is treated as Utah CLI options, and everything after--is passed to your script.
Direct Command Benefits
The -c/--command option is particularly useful for:
Quick Testing:
# Test a function before adding to a script
utah run -c "console.log(os.platform())"
# Verify file operations
utah run --command "console.log(fs.dirname('/path/to/file.txt'))"
One-liners:
# Quick system checks
utah run -c "console.log(os.isInstalled('docker') ? 'Docker available' : 'Docker not found')"
# Inline calculations
utah run --command "console.log(utility.random(1, 100))"
Scripting Integration:
# Use in shell scripts or CI/CD
if utah run -c "os.isInstalled('node')" | grep -q "true"; then
  echo "Node.js is installed"
fi
Development Workflow:
# Quick prototyping without creating files
utah run -c "
let data: string[] = ['apple', 'banana', 'cherry'];
for (let item of data) {
  console.log(item.toUpperCase());
}
"
How It Works
1. Temporary Compilation
When you run utah run script.shx, Utah:
- Compiles the .shx file to bash in memory
 - Creates a temporary file in the system temp directory
 - Executes the temporary bash script
 - Streams output in real-time
 - Cleans up the temporary file automatically
 
2. Real-time Output
Unlike utah compile, the run command streams output as it happens:
// slow-script.shx
for (let i: number = 1; i <= 5; i++) {
  console.log("Step ${i} of 5");
  `$(sleep 1)`;  // Wait 1 second
}
console.log("Completed!");
utah run slow-script.shx
Step 1 of 5
Step 2 of 5
Step 3 of 5
Step 4 of 5
Step 5 of 5
Completed!
3. Error Propagation
Exit codes and errors are properly propagated:
// error-script.shx
console.log("Starting process...");
if (!fs.exists("required-file.txt")) {
  console.log("Error: required-file.txt not found");
  exit(1);
}
console.log("Process completed successfully");
utah run error-script.shx
echo "Exit code: $?"
Starting process...
Error: required-file.txt not found
Exit code: 1
Development Workflow
Quick Testing
Use utah run for rapid iteration during development:
# Edit script.shx
vim script.shx
# Test immediately
utah run script.shx
# Edit and test again
vim script.shx
utah run script.shx
Debug Output
Enable debug mode for detailed execution information:
export UTAH_DEBUG=1
utah run script.shx
This shows:
- Compilation progress
 - Temporary file location
 - Execution timing
 - Cleanup status
 
Interactive Development
Combine with file watching for automatic execution:
# Install inotify-tools (Linux)
sudo apt install inotify-tools
# Watch and auto-run
while inotifywait -e modify script.shx; do
  clear
  echo "File changed, running..."
  utah run script.shx
done
Advanced Features
Environment Variables
Scripts can access and modify environment variables:
// env-script.shx
console.log("Current PATH: ${PATH}");
console.log("Home directory: ${HOME}");
// Set environment variable for child processes
ENV["CUSTOM_VAR"] = "Hello from Utah";
`$(echo $CUSTOM_VAR)`;
Standard Input/Output
Scripts can read from stdin and write to stdout/stderr:
// input-script.shx
console.log("Enter your name:");
let name: string = console.prompt("Name: ");
console.log("Hello, ${name}!");
echo "Alice" | utah run input-script.shx
Process Management
Long-running scripts can be managed like normal processes:
# Run in background
utah run long-running-script.shx &
SCRIPT_PID=$!
# Check if still running
kill -0 $SCRIPT_PID 2>/dev/null && echo "Still running"
# Terminate if needed
kill $SCRIPT_PID
Performance Considerations
Compilation Overhead
Each utah run invocation includes compilation time:
| File Size | Compilation | Execution | Total | 
|---|---|---|---|
| < 100 lines | 50ms | Variable | 50ms + execution | 
| 100-500 lines | 150ms | Variable | 150ms + execution | 
| 500+ lines | 300ms+ | Variable | 300ms+ + execution | 
When to Use Run vs Compile
Use utah run for:
- Development and testing
 - One-off script execution
 - Interactive scripting
 - Scripts that change frequently
 
Use utah compile for:
- Production deployment
 - Scripts run multiple times
 - Performance-critical applications
 - When you need to inspect generated bash
 
Optimization Tips
- Minimize imports: Faster compilation
 - Use caching: For scripts with heavy imports
 - Profile execution: Identify bottlenecks
 
# Time the execution
time utah run script.shx
# Profile with detailed timing
UTAH_DEBUG=1 UTAH_PROFILE=1 utah run script.shx
Error Handling
Compilation Errors
If the script fails to compile, utah run stops with an error:
utah run broken.shx
❌ Compilation failed: Syntax error at line 5: Expected ';'
Runtime Errors
Runtime errors are shown with context:
// runtime-error.shx
let result: number = `$(date +%Y)` / 0;  // Division by zero
utah run runtime-error.shx
/tmp/utah_temp_12345.sh: line 3: division by 0 (error token is "0")
Signal Handling
Scripts can be interrupted with Ctrl+C:
utah run infinite-loop.shx
# Press Ctrl+C to stop
^C
The temporary file is still cleaned up even after interruption.
Integration Examples
Testing Framework
#!/bin/bash
# test-runner.sh
echo "Running Utah script tests..."
test_files=(
  "tests/unit/test-math.shx"
  "tests/unit/test-strings.shx"
  "tests/integration/test-api.shx"
)
failed=0
for test_file in "${test_files[@]}"; do
  echo "Running $test_file..."
  if utah run "$test_file"; then
    echo "✅ $test_file passed"
  else
    echo "❌ $test_file failed"
    ((failed++))
  fi
done
if [ $failed -eq 0 ]; then
  echo "All tests passed!"
else
  echo "$failed test(s) failed"
  exit 1
fi
Build Automation
#!/bin/bash
# dev-workflow.sh
set -e
echo "Development workflow starting..."
# Run linting
echo "Checking code formatting..."
utah format src/*.shx --check
# Run tests
echo "Running tests..."
for test in tests/*.shx; do
  utah run "$test"
done
# Run main script
echo "Running main application..."
utah run src/main.shx --env development
echo "Development workflow completed!"
Continuous Integration
# .github/workflows/utah-ci.yml
name: Utah CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Install Utah
      run: |
        curl -sL https://utahshx.com/install.sh | sudo bash
    - name: Run unit tests
      run: |
        for test in tests/unit/*.shx; do
          echo "Running $test"
          utah run "$test"
        done
    - name: Run integration tests
      run: |
        for test in tests/integration/*.shx; do
          echo "Running $test"
          utah run "$test"
        done
    - name: Run smoke tests
      run: |
        utah run scripts/server-health-check.shx
Troubleshooting
Common Issues
Issue: Script runs but produces no output
utah run silent-script.shx
# No output
Diagnosis: Check if script has console.log statements Solution: Add debug output to verify execution
Issue: Permission denied errors
utah run script.shx
# Permission denied accessing files
Diagnosis: Script may need elevated privileges Solution: Check file permissions or run with sudo if needed
Issue: Script hangs indefinitely
utah run hanging-script.shx
# Never terminates
Diagnosis: Infinite loop or waiting for input Solution: Use Ctrl+C to interrupt, check script logic
Debug Techniques
- Add logging:
 
console.log("Debug: Reached checkpoint 1");
console.log("Debug: Variable value is ${someVar}");
- Use temporary files:
 
fs.writeFile("/tmp/debug.log", "Current state: ${JSON.stringify(data)}");
- Check environment:
 
console.log("PWD: ${PWD}");
console.log("USER: ${USER}");
console.log("PATH: ${PATH}");
Performance Debugging
# Time compilation vs execution
time utah compile script.shx  # Compilation time
time ./script.sh             # Execution time
time utah run script.shx     # Total time
# Memory usage
/usr/bin/time -v utah run script.shx
Best Practices
1. Use for Development
# Good: Quick testing during development
utah run dev-test.shx
# Good: Interactive debugging
utah run debug-helper.shx --verbose
# Avoid: Production deployment
# utah run production-script.shx  # Use compile instead
2. Handle Arguments Properly
// Good: Validate arguments
if (!args.has("--required-param")) {
  console.log("Error: --required-param is required");
  args.showHelp();
  exit(1);
}
// Good: Provide defaults
let timeout: number = args.has("--timeout") ? args.get("--timeout") : 30;
3. Provide Clear Output
// Good: Clear progress indication
console.log("Starting data processing...");
console.log("Processing file 1 of 5...");
console.log("✅ Processing completed successfully");
// Avoid: Silent operation
// processData(); // No feedback
4. Exit Gracefully
// Good: Clean exit with status
if (errorOccurred) {
  console.log("❌ Operation failed: " + errorMessage);
  exit(1);
}
console.log("✅ Operation completed successfully");
exit(0);
The run command provides an excellent development experience for Utah scripts, enabling rapid iteration and testing without the overhead of managing compiled files.