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 invkfile 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:bookworm-slim"} // Container
]
The first runtime is the default. Users can override with --invk-runtime:
# Uses default runtime (first in list)
invowk cmd myproject build
# Override to use container runtime
invowk cmd myproject build --invk-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.21"}]
platforms: [{name: "linux"}]
}
]
}
Combined Platform + Runtime
{
name: "build"
implementations: [
// Linux/macOS with multiple runtime options
{
script: "make build"
runtimes: [
{name: "native"},
{name: "container", image: "ubuntu:22.04"}
]
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:
- Current platform - Filters to implementations supporting your OS
- Requested runtime - If
--invk-runtimespecified, uses that; otherwise uses the default - 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"}]
}
]
}
| Platform | Command | Selected |
|---|---|---|
| Linux | invowk cmd myproject build | First impl, native runtime |
| Linux | invowk cmd myproject build --invk-runtime virtual | First impl, virtual runtime |
| Windows | invowk cmd myproject build | Second impl, native runtime |
| Windows | invowk cmd myproject build --invk-runtime virtual | Error: no matching impl |
Command Listing
The invowk cmd output shows available runtimes and platforms:
Available Commands
(* = default runtime)
From current directory:
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
- Start simple - One implementation is often enough
- Always specify platforms - Every implementation must declare at least one target platform
- Default runtime first - Put the most common runtime first in the list
- Use templates - Reduce repetition with CUE's templating
- 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