Native Runtime
The native runtime executes commands using your system's default shell. It's the most straightforward option and the one you'll use most often during development.
How It Works
When you run a command with the native runtime, Invowk™:
- Detects your system's default shell
- Creates a temporary script file
- Executes it through the shell
- Streams output back to your terminal
Shell Detection
Invowk automatically detects the best available shell:
Linux/macOS
- Uses
$SHELLenvironment variable if set - Falls back to
bashif available - Falls back to
shas last resort
Windows
- Tries
pwsh(PowerShell Core) - Falls back to
powershell(Windows PowerShell) - Falls back to
cmd.exeas last resort
Basic Usage
{
name: "build"
implementations: [
{
script: "go build ./..."
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}
]
}
invowk cmd build
Overriding the Default Shell
You can override the shell at the invkfile level:
default_shell: "/bin/bash"
cmds: [
// Commands...
]
This is useful when:
- You need bash-specific features
- Your script relies on a specific shell
- You want consistent behavior across team machines
Shell-Specific Scripts
Bash/Zsh
{
name: "build"
implementations: [{
script: """
#!/bin/bash
set -euo pipefail # Bash strict mode
# Bash-specific features
declare -A config=(
["env"]="production"
["debug"]="false"
)
echo "Building for ${config[env]}..."
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}
PowerShell
{
name: "build"
implementations: [{
script: """
$ErrorActionPreference = "Stop"
Write-Host "Building..." -ForegroundColor Green
dotnet build --configuration Release
Write-Host "Done!" -ForegroundColor Green
"""
runtimes: [{name: "native"}]
platforms: [{name: "windows"}]
}]
}
cmd.exe (Windows Batch)
{
name: "build"
implementations: [{
script: """
@echo off
echo Building...
msbuild /p:Configuration=Release
echo Done!
"""
runtimes: [{name: "native"}]
platforms: [{name: "windows"}]
}]
}
Using Interpreters
The native runtime supports non-shell interpreters like Python, Ruby, or Node.js.
Auto-Detection from Shebang
{
name: "analyze"
implementations: [{
script: """
#!/usr/bin/env python3
import sys
import json
print(f"Python {sys.version}")
data = {"status": "ok", "items": [1, 2, 3]}
print(json.dumps(data, indent=2))
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}
Explicit Interpreter
{
name: "analyze"
implementations: [{
script: """
import sys
print(f"Hello from Python {sys.version_info.major}!")
"""
runtimes: [{
name: "native"
interpreter: "python3" // Explicit interpreter
}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}
Interpreter with Arguments
{
name: "script"
implementations: [{
script: """
print("Unbuffered output!")
"""
runtimes: [{
name: "native"
interpreter: "python3 -u" // With arguments
}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}
Environment Variables
Native runtime has full access to your environment:
{
name: "deploy"
env: {
vars: {
DEPLOY_ENV: "production"
}
}
implementations: [{
script: """
echo "Home: $HOME"
echo "User: $USER"
echo "Deploy to: $DEPLOY_ENV"
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}
Accessing Flags and Arguments
Flags and arguments are available as environment variables:
{
name: "greet"
flags: [
{name: "loud", type: "bool", default_value: "false"}
]
args: [
{name: "name", default_value: "World"}
]
implementations: [{
script: """
if [ "$INVOWK_FLAG_LOUD" = "true" ]; then
echo "HELLO, $INVOWK_ARG_NAME!"
else
echo "Hello, $INVOWK_ARG_NAME!"
fi
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}
invowk cmd greet Alice --loud
# Output: HELLO, ALICE!
Working Directory
By default, scripts run in the current directory. Override with workdir:
{
name: "build frontend"
workdir: "./frontend" // Run in frontend subdirectory
implementations: [{
script: "npm run build"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}
Dependencies
Native runtime validates dependencies against your host system:
{
name: "deploy"
depends_on: {
tools: [
{alternatives: ["docker", "podman"]},
{alternatives: ["kubectl"]}
]
filepaths: [
{alternatives: ["Dockerfile"]}
]
}
implementations: [{
script: "docker build -t myapp . && kubectl apply -f k8s/"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}
Advantages
- Performance: No overhead, direct shell execution
- Full access: All system tools and environment available
- Familiar: Use your preferred shell and its features
- Interactive: Can run interactive commands
Limitations
- Platform differences: Scripts may behave differently across OSes
- Environment dependency: Relies on installed tools
- Reproducibility: Results may vary between machines
When to Use Native
- Daily development: Fast iteration, familiar tools
- System integration: When you need access to system resources
- Interactive tasks: Prompts, editors, TUI applications
- Performance-critical: When container overhead matters
Next Steps
- Virtual Runtime - For cross-platform consistency
- Container Runtime - For reproducible builds