Skip to main content
Version: 0.1.0-alpha.3

Virtual Runtime

The virtual runtime uses Invowk™'s built-in POSIX-compatible shell interpreter (powered by mvdan/sh). It provides consistent shell behavior across all platforms without requiring an external shell.

How It Works

When you run a command with the virtual runtime, Invowk:

  1. Parses the script using the built-in shell parser
  2. Executes it in an embedded POSIX-like environment
  3. Provides core utilities (echo, test, etc.) built-in

Basic Usage

{
name: "build"
implementations: [{
script: """
echo "Building..."
go build -o bin/app ./...
echo "Done!"
"""
runtimes: [{name: "virtual"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}
invowk cmd build --invk-runtime virtual

Cross-Platform Consistency

The virtual runtime behaves identically on Linux, macOS, and Windows:

{
name: "setup"
implementations: [{
script: """
# This works the same everywhere!
if [ -d "node_modules" ]; then
echo "Dependencies already installed"
else
echo "Installing dependencies..."
npm install
fi
"""
runtimes: [{name: "virtual"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}

No more "works on my machine" for shell scripts!

Built-in Utilities

The virtual shell includes core POSIX utilities:

UtilityDescription
echoPrint text
printfFormatted output
test / [Conditionals
true / falseExit with 0/1
pwdPrint working directory
cdChange directory
readRead input
exportSet environment variables

Extended Utilities (u-root)

When enabled in config (default: true), additional utilities from the u-root library are available:

// In your config file
virtual_shell: {
enable_uroot_utils: true
}

File Operations (7 utilities)

UtilityDescriptionCommon Flags
catConcatenate and display files-n (number lines)
cpCopy files and directories-r (recursive), -f (force)
lsList directory contents-l (long), -a (all), -R (recursive)
mkdirCreate directories-p (create parents)
mvMove or rename files-f (force), -n (no clobber)
rmRemove files and directories-r (recursive), -f (force)
touchCreate or update file timestamps-c (no create)

Text Processing (8 utilities)

UtilityDescriptionCommon Flags
headOutput first N lines-n <num> (default 10)
tailOutput last N lines-n <num> (default 10)
wcCount lines, words, bytes-l (lines), -w (words), -c (bytes)
grepSearch for patterns-i (ignore case), -v (invert), -n (line numbers)
sortSort lines-r (reverse), -n (numeric)
uniqFilter adjacent duplicate lines-c (count), -d (duplicates only)
cutSelect portions of lines-d (delimiter), -f (fields)
trTranslate charactersSET1 SET2 (character mapping)
note

These utilities implement POSIX behavior. GNU-specific flags (like --color, --time-style) are silently ignored for compatibility.

Error Identification

Errors from u-root utilities are prefixed with [uroot] for easy identification:

[uroot] cp: /source/file: no such file or directory
[uroot] rm: /protected: permission denied

No Silent Fallback

If a u-root command fails, it returns an error immediately. The system does not fall back to host binaries, ensuring bugs are caught rather than masked

POSIX Shell Features

The virtual shell supports standard POSIX constructs:

Variables

script: """
NAME="World"
echo "Hello, $NAME!"

# Parameter expansion
echo "${NAME:-default}"
echo "${#NAME}" # Length
"""

Conditionals

script: """
if [ "$ENV" = "production" ]; then
echo "Production mode"
elif [ "$ENV" = "staging" ]; then
echo "Staging mode"
else
echo "Development mode"
fi
"""

Loops

script: """
# For loop
for file in *.go; do
echo "Processing $file"
done

# While loop
count=0
while [ $count -lt 5 ]; do
echo "Count: $count"
count=$((count + 1))
done
"""

Functions

script: """
greet() {
echo "Hello, $1!"
}

greet "World"
greet "Invowk"
"""

Subshells and Command Substitution

script: """
# Command substitution
current_date=$(date +%Y-%m-%d)
echo "Today is $current_date"

# Subshell
(cd /tmp && echo "In temp: $(pwd)")
echo "Still in: $(pwd)"
"""

Calling External Commands

The virtual shell can call external commands installed on your system:

script: """
# Calls the real 'go' binary
go version

# Calls the real 'git' binary
git status
"""

External commands are found using the system's PATH.

Environment Variables

Environment variables work the same as in native:

{
name: "build"
env: {
vars: {
BUILD_MODE: "release"
}
}
implementations: [{
script: """
echo "Building in $BUILD_MODE mode"
go build -ldflags="-s -w" ./...
"""
runtimes: [{name: "virtual"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}

Flags and Arguments

Access flags and arguments the same way:

{
name: "greet"
args: [{name: "name", default_value: "World"}]
implementations: [{
script: """
# Using environment variable
echo "Hello, $INVOWK_ARG_NAME!"

# Or positional parameter
echo "Hello, $1!"
"""
runtimes: [{name: "virtual"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}

Limitations

No Interpreter Support

The virtual runtime cannot use non-shell interpreters:

// This will NOT work with virtual runtime!
{
name: "bad-example"
implementations: [{
script: """
#!/usr/bin/env python3
print("This won't work!")
"""
runtimes: [{
name: "virtual"
interpreter: "python3" // ERROR: Not supported
}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}

For Python, Ruby, or other interpreters, use the native or container runtime.

Bash-Specific Features

Some bash-specific features are not available:

// These won't work in virtual runtime:
script: """
# Bash arrays (use $@ instead)
declare -a arr=(1 2 3) # Not supported

# Bash-specific parameter expansion
${var^^} # Uppercase - not supported
${var,,} # Lowercase - not supported

# Process substitution
diff <(cmd1) <(cmd2) # Not supported
"""

Stick to POSIX-compatible constructs for virtual runtime.

Dependency Validation

Dependencies are validated against the virtual shell's capabilities:

{
name: "build"
depends_on: {
tools: [
// These will be checked in the virtual shell environment
{alternatives: ["go"]},
{alternatives: ["git"]}
]
}
implementations: [{
script: "go build ./..."
runtimes: [{name: "virtual"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}

Advantages

  • Consistency: Same behavior on Linux, macOS, and Windows
  • No shell dependency: Works even if system shell is unavailable
  • Portability: Scripts work across all platforms
  • Built-in utilities: Core utilities always available
  • Faster startup: No shell process to spawn

When to Use Virtual

  • Cross-platform scripts: When the same script must work everywhere
  • CI/CD pipelines: Consistent behavior across build agents
  • Simple shell scripts: When you don't need bash-specific features
  • Embedded environments: When external shells aren't available

Configuration

Configure the virtual shell in your Invowk config file:

// ~/.config/invowk/config.cue (Linux)
// ~/Library/Application Support/invowk/config.cue (macOS)
// %APPDATA%\invowk\config.cue (Windows)

virtual_shell: {
// Enable additional utilities from u-root
enable_uroot_utils: true
}

Next Steps