Skip to main content
Version: Next

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: [
platforms: [{name: "linux"}, {name: "macos"}]
{name: "native"}, // System shell
{name: "virtual"}, // Built-in POSIX shell
{name: "container", image: "debian:stable-slim"} // Container
]

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: [
platforms: [{name: "linux"}, {name: "macos"}]
{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