Skip to main content
Version: Next

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™:

  1. Detects your system's default shell
  2. Passes the script directly as a -c argument to the shell (no temporary file is created)
  3. Executes it through the shell
  4. Streams output back to your terminal
note

When a non-shell interpreter is specified (e.g., Python, Ruby), a temporary script file is created and passed to the interpreter instead.

Shell Detection

Invowk automatically detects the best available shell:

Linux/macOS

  1. Uses $SHELL environment variable if set
  2. Falls back to bash if available
  3. Falls back to sh as last resort

Windows

  1. Tries pwsh (PowerShell Core)
  2. Falls back to powershell (Windows PowerShell)
  3. Falls back to cmd.exe as 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 invowkfile 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", description: "Use uppercase greeting", type: "bool", default_value: "false"}
]
args: [
{name: "name", description: "Name to greet", 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