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:
- Parses the script using the built-in shell parser
- Executes it in an embedded POSIX-like environment
- 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 --ivk-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:
| Utility | Description |
|---|---|
echo | Print text |
printf | Formatted output |
test / [ | Conditionals |
true / false | Exit with 0/1 |
pwd | Print working directory |
cd | Change directory |
read | Read input |
export | Set environment variables |
Extended Utilities (u-root)
When enabled in config (default: true), 28 additional POSIX-compliant utilities from the u-root library are available. These include 12 upstream u-root wrappers and 16 custom implementations.
// In your config file
virtual_shell: {
enable_uroot_utils: true
}
File Operations (14 utilities)
| Utility | Description | Common Flags |
|---|---|---|
base64 | Encode/decode base64 | -d (decode) |
cat | Concatenate and display files | -u (ignored, compatibility) |
cp | Copy files and directories | -r (recursive), -f (force) |
find | Search for files in a directory hierarchy | -name (pattern), -type (f, d, l) |
gzip | Compress or expand files | -d (decompress), -c (stdout), -f (force) |
ln | Create hard or symbolic links | -s (symbolic), -f (force) |
ls | List directory contents | -l (long), -a (all), -R (recursive) |
mkdir | Create directories | -p (create parents) |
mktemp | Create temporary files or directories | -d (directory), -p (prefix dir) |
mv | Move or rename files | -f (force), -n (no clobber) |
realpath | Resolve absolute path names | (none) |
rm | Remove files and directories | -r (recursive), -f (force) |
tar | Archive files | -c (create), -x (extract), -f (file) |
touch | Create or update file timestamps | -c (no create) |
Text Processing (10 utilities)
| Utility | Description | Common Flags |
|---|---|---|
basename | Strip directory and suffix from filenames | (none) |
cut | Select portions of lines | -d (delimiter), -f (fields) |
dirname | Strip last component from filenames | (none) |
grep | Search for patterns | -i (ignore case), -v (invert), -n (line numbers) |
head | Output first N lines | -n <num> (default 10) |
sort | Sort lines | -r (reverse), -n (numeric), -u (unique) |
tail | Output last N lines | -n <num> (default 10) |
tr | Translate characters | SET1 SET2 (character mapping) |
uniq | Filter adjacent duplicate lines | -c (count), -d (duplicates only) |
wc | Count lines, words, bytes | -l (lines), -w (words), -c (bytes) |
Other Utilities (4 utilities)
| Utility | Description | Common Flags |
|---|---|---|
seq | Generate number sequences | -s (separator), -w (equal width) |
shasum | Compute SHA message digests | -a (algorithm: 1, 256, 512) |
sleep | Delay for a specified time | (none — takes duration argument) |
tee | Duplicate standard input to files | -a (append) |
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", description: "Name to greet", 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!
// The "interpreter" field is not allowed on #RuntimeConfigVirtual —
// CUE schema validation will reject this at parse time.
{
name: "bad-example"
implementations: [{
script: """
#!/usr/bin/env python3
print("This won't work!")
"""
runtimes: [{
name: "virtual"
interpreter: "python3" // CUE validation error: field not allowed
}]
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%invowkconfig.cue (Windows)
virtual_shell: {
// Enable additional utilities from u-root
enable_uroot_utils: true
}
Next Steps
- Native Runtime - For full shell access
- Container Runtime - For isolated execution