Skip to main content
Version: 0.1.0-alpha.1

Your First Invkfile

Now that you've run your first command, let's build something more practical. We'll create an invkfile for a typical project with build, test, and deploy commands.

Understanding the Structure

An invkfile has a simple structure:

// invkfile.cue (commands only)
cmds: [ // Required: list of commands
// ... your commands here
]

Invkfiles define commands directly. If you want namespacing, use a module and set the module ID in invkmod.cue.

A Real-World Example

Let's create an invkfile for a Go project:

cmds: [
// Simple build command
{
name: "build"
description: "Build the project"
implementations: [
{
script: """
echo "Building..."
go build -o bin/app ./...
echo "Done! Binary at bin/app"
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}
]
},

// Test command with subcommand-style naming
{
name: "test unit"
description: "Run unit tests"
implementations: [
{
script: "go test -v ./..."
runtimes: [{name: "native"}, {name: "virtual"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}
]
},

// Test with coverage
{
name: "test coverage"
description: "Run tests with coverage"
implementations: [
{
script: """
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
echo "Coverage report: coverage.html"
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}
]
},

// Clean command
{
name: "clean"
description: "Remove build artifacts"
implementations: [
{
script: "rm -rf bin/ coverage.out coverage.html"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}
]
}
]

Save this as invkfile.cue and try:

invowk cmd

You'll see:

Available Commands
(* = default runtime)

From current directory:
build - Build the project [native*]
test unit - Run unit tests [native*, virtual]
test coverage - Run tests with coverage [native*]
clean - Remove build artifacts [native*] (linux, macos)

Subcommand-Style Names

Notice how test unit and test coverage create a hierarchy. You run them like:

invowk cmd test unit
invowk cmd test coverage

This is just naming convention - spaces in the name create a subcommand feel. It's great for organizing related commands!

Multiple Runtimes

The test unit command allows both native and virtual runtimes:

runtimes: [{name: "native"}, {name: "virtual"}]

The first one is the default. You can override it:

# Use the default (native)
invowk cmd test unit

# Explicitly use virtual runtime
invowk cmd test unit --invk-runtime virtual

Platform-Specific Commands

The clean command only works on Linux and macOS (because it uses rm -rf):

platforms: [{name: "linux"}, {name: "macos"}]

If you try to run it on Windows, Invowk will show a helpful error message explaining the command isn't available on your platform.

Adding Dependencies

Let's make our build command smarter by checking if Go is installed:

{
name: "build"
description: "Build the project"
implementations: [
{
script: """
echo "Building..."
go build -o bin/app ./...
echo "Done!"
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}
]
depends_on: {
tools: [
{alternatives: ["go"]}
]
filepaths: [
{alternatives: ["go.mod"], readable: true}
]
}
}

Now if you run invowk cmd build without Go installed, you'll get:

✗ Dependencies not satisfied

Command 'build' has unmet dependencies:

Missing Tools:
• go - not found in PATH

Install the missing tools and try again.

Environment Variables

You can set environment variables at different levels:

// Root-level env applies to ALL commands
env: {
vars: {
GO111MODULE: "on"
}
}

cmds: [
{
name: "build"
// Command-level env applies to this command
env: {
vars: {
CGO_ENABLED: "0"
}
}
implementations: [
{
script: "go build -o bin/app ./..."
// Implementation-level env is most specific
env: {
vars: {
GOOS: "linux"
GOARCH: "amd64"
}
}
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}
]
}
]

Environment variables merge with later levels overriding earlier ones.

What's Next?

You now know the basics of creating invkfiles! Continue learning about: