Skip to main content
Version: 0.11.0

Implementations

Every command needs at least one implementation - the actual code that runs when you invoke the command. Implementations define what runs, where it runs (platform), and how it runs (runtime).

Basic Structure​

An implementation has three main parts:

{
name: "build"
implementations: [
{
// 1. The script to run
script: "go build ./..."

// 2. Target constraints (runtime + platform)
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}
]
}

Scripts​

The script field contains the commands to execute. It can be inline or reference an external file.

Inline Scripts​

Single-line scripts are simple:

script: "echo 'Hello, World!'"

Multi-line scripts use triple quotes:

script: """
#!/bin/bash
set -e
echo "Building..."
go build -o bin/app ./...
echo "Done!"
"""

External Script Files​

Reference a script file instead of inline code:

// Relative to invowkfile location
script: "./scripts/build.sh"

// Just the filename (recognized extensions)
script: "deploy.sh"

Recognized extensions: .sh, .bash, .ps1, .bat, .cmd, .py, .rb, .pl, .zsh, .fish

When to Use External Scripts​

  • Inline: Quick, simple commands; keeps everything in one file
  • External: Complex scripts; reusable across commands; easier to edit with syntax highlighting

Runtime and Platform Constraints​

Each implementation specifies where and how it runs using the runtimes and platforms fields.

Runtimes​

Every implementation must specify at least one runtime:

runtimes: [
{name: "native"}, // System shell
{name: "virtual"}, // Built-in POSIX shell
{name: "container", image: "debian:stable-slim"} // Container
]
platforms: [{name: "linux"}, {name: "macos"}]

The first runtime is the default. Users can override with --ivk-runtime:

# Uses default runtime (first in list)
invowk cmd myproject build

# Override to use container runtime
invowk cmd myproject build --ivk-runtime container

See Runtime Modes for details on each runtime.

Platforms​

Specify which operating systems the implementation supports. Every implementation must declare at least one platform:

runtimes: [{name: "native"}]
platforms: [
{name: "linux"},
{name: "macos"},
{name: "windows"}
]

Available platforms: linux, macos, windows

Multiple Implementations​

Commands can have multiple implementations for different scenarios:

Platform-Specific Implementations​

{
name: "clean"
implementations: [
// Unix implementation
{
script: "rm -rf build/"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
},
// Windows implementation
{
script: "rmdir /s /q build"
runtimes: [{name: "native"}]
platforms: [{name: "windows"}]
}
]
}

Invowk™ automatically selects the right implementation for the current platform.

Runtime-Specific Implementations​

{
name: "build"
implementations: [
// Fast native build
{
script: "go build ./..."
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
},
// Reproducible container build
{
script: "go build -o /workspace/bin/app ./..."
runtimes: [{name: "container", image: "golang:1.26"}]
platforms: [{name: "linux"}]
}
]
}

Combined Platform + Runtime​

{
name: "build"
implementations: [
// Linux/macOS with multiple runtime options
{
script: "make build"
runtimes: [
{name: "native"},
{name: "container", image: "debian:stable-slim"}
]
platforms: [{name: "linux"}, {name: "macos"}]
},
// Windows native only
{
script: "msbuild /p:Configuration=Release"
runtimes: [{name: "native"}]
platforms: [{name: "windows"}]
}
]
}

Platform-Specific Environment​

For platform-specific environment variables, use separate implementations per platform, each with its own env:

{
name: "deploy"
implementations: [
// Linux implementation with platform-specific env
{
script: "echo "Deploying to $PLATFORM with config at $CONFIG_PATH""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}]
env: {
vars: {
PLATFORM: "Linux"
CONFIG_PATH: "/etc/app/config.yaml"
}
}
},
// macOS implementation with platform-specific env
{
script: "echo "Deploying to $PLATFORM with config at $CONFIG_PATH""
runtimes: [{name: "native"}]
platforms: [{name: "macos"}]
env: {
vars: {
PLATFORM: "macOS"
CONFIG_PATH: "/usr/local/etc/app/config.yaml"
}
}
}
]
}

Implementation-Level Settings​

Implementations can have their own environment, working directory, and dependencies:

{
name: "build"
implementations: [
{
script: "npm run build"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]

// Implementation-specific env
env: {
vars: {
NODE_ENV: "production"
}
}

// Implementation-specific workdir
workdir: "./frontend"

// Implementation-specific dependencies
depends_on: {
tools: [{alternatives: ["node", "npm"]}]
filepaths: [{alternatives: ["package.json"]}]
}
}
]
}

These override command-level settings when this implementation is selected.

Implementation Selection​

When you run a command, Invowk selects an implementation based on:

  1. Current platform - Filters to implementations supporting your OS
  2. Requested runtime - If --ivk-runtime specified, uses that; otherwise uses the default
  3. First match wins - Uses the first implementation matching both criteria

Selection Examples​

Given this command:

{
name: "build"
implementations: [
{
script: "make build"
runtimes: [{name: "native"}, {name: "virtual"}]
platforms: [{name: "linux"}, {name: "macos"}]
},
{
script: "msbuild"
runtimes: [{name: "native"}]
platforms: [{name: "windows"}]
}
]
}
PlatformCommandSelected
Linuxinvowk cmd myproject buildFirst impl, native runtime
Linuxinvowk cmd myproject build --ivk-runtime virtualFirst impl, virtual runtime
Windowsinvowk cmd myproject buildSecond impl, native runtime
Windowsinvowk cmd myproject build --ivk-runtime virtualError: no matching impl

Command Listing​

The invowk cmd output shows available runtimes and platforms:

Available Commands
(* = default runtime)

From invowkfile:
build - Build the project [native*, virtual] (linux, macos)
clean - Clean artifacts [native*] (linux, macos, windows)
docker-build - Container build [container*] (linux, macos, windows)
  • [native*, virtual] - Supports native (default) and virtual runtimes
  • (linux, macos) - Only available on Linux and macOS

Using CUE Templates​

Reduce repetition with CUE templates:

// Define reusable templates
_unixNative: {
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}

_allPlatforms: {
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}

cmds: [
{
name: "build"
implementations: [
_unixNative & {script: "make build"}
]
},
{
name: "test"
implementations: [
_unixNative & {script: "make test"}
]
},
{
name: "version"
implementations: [
_allPlatforms & {script: "cat VERSION"}
]
}
]

Best Practices​

  1. Start simple - One implementation is often enough
  2. Always specify platforms - Every implementation must declare at least one target platform
  3. Default runtime first - Put the most common runtime first in the list
  4. Use templates - Reduce repetition with CUE's templating
  5. Keep scripts focused - One task per command; chain with dependencies

Next Steps​

  • Runtime Modes - Deep dive into native, virtual, and container runtimes
  • Dependencies - Declare what your implementations need