Skip to main content
Version: Next

Positional Arguments

Positional arguments are values passed by position after the command name. They're ideal for required inputs where order is natural (like source and destination).

Defining Arguments

{
name: "copy"
args: [
{
name: "source"
description: "Source file or directory"
required: true
},
{
name: "destination"
description: "Destination path"
required: true
}
]
implementations: [...]
}

Usage:

invowk cmd copy ./src ./dest

Argument Properties

PropertyRequiredDescription
nameYesArgument name (alphanumeric, hyphens, underscores)
descriptionYesHelp text
typeNostring, int, float (default: string)
default_valueNoDefault if not provided
requiredNoMust be provided (can't have default)
validationNoRegex pattern for value
variadicNoAccept multiple values (last arg only)

Types

String (Default)

{name: "filename", description: "File to process", type: "string"}

Integer

{name: "count", description: "Number of items", type: "int", default_value: "10"}
invowk cmd generate 5

Float

{name: "ratio", description: "Scaling ratio", type: "float", default_value: "1.0"}
invowk cmd scale 0.5

Note: Boolean type is not supported for arguments. Use flags for boolean options.

Required vs Optional

Required Arguments

args: [
{name: "input", description: "Input file", required: true},
{name: "output", description: "Output file", required: true},
]
# Error: missing required argument
invowk cmd convert input.txt
# Error: argument 'output' is required

# Success
invowk cmd convert input.txt output.txt

Optional Arguments

args: [
{name: "input", description: "Input file", required: true},
{name: "format", description: "Output format", default_value: "json"},
]
# Uses default format (json)
invowk cmd parse input.txt

# Override format
invowk cmd parse input.txt yaml

Ordering Rule

Required arguments must come before optional arguments:

// Good
args: [
{name: "input", description: "Input file", required: true}, // Required first
{name: "output", description: "Output file", required: true}, // Required second
{name: "format", description: "Output format", default_value: "json"}, // Optional last
]

// Bad - will cause validation error
args: [
{name: "format", description: "Output format", default_value: "json"}, // Optional can't come first
{name: "input", description: "Input file", required: true},
]

Variadic Arguments

The last argument can accept multiple values:

{
name: "process"
args: [
{name: "output", description: "Output file", required: true},
{name: "inputs", description: "Input files", variadic: true},
]
implementations: [{
script: """
echo "Output: $INVOWK_ARG_OUTPUT"
echo "Inputs: $INVOWK_ARG_INPUTS"
echo "Count: $INVOWK_ARG_INPUTS_COUNT"

for i in $(seq 1 $INVOWK_ARG_INPUTS_COUNT); do
eval "file=$INVOWK_ARG_INPUTS_$i"
echo "Processing: $file"
done
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}
invowk cmd process out.txt a.txt b.txt c.txt
# Output: out.txt
# Inputs: a.txt b.txt c.txt
# Count: 3
# Processing: a.txt
# Processing: b.txt
# Processing: c.txt

Variadic Environment Variables

VariableDescription
INVOWK_ARG_INPUTSSpace-joined values
INVOWK_ARG_INPUTS_COUNTNumber of values
INVOWK_ARG_INPUTS_1First value
INVOWK_ARG_INPUTS_2Second value
...And so on

Validation Patterns

Validate argument values with regex:

args: [
{
name: "environment"
description: "Target environment"
required: true
validation: "^(dev|staging|prod)$"
},
{
name: "version"
description: "Version number"
validation: "^[0-9]+.[0-9]+.[0-9]+$"
}
]
# Valid
invowk cmd deploy prod 1.2.3

# Invalid
invowk cmd deploy production
# Error: argument 'environment' value 'production' does not match pattern '^(dev|staging|prod)$'

Accessing in Scripts

Environment Variables

{
name: "greet"
args: [
{name: "first-name", description: "First name", required: true},
{name: "last-name", description: "Last name", default_value: "User"},
]
implementations: [{
script: """
echo "Hello, $INVOWK_ARG_FIRST_NAME $INVOWK_ARG_LAST_NAME!"
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}

Naming Convention

Argument NameEnvironment Variable
nameINVOWK_ARG_NAME
file-pathINVOWK_ARG_FILE_PATH
outputDirINVOWK_ARG_OUTPUTDIR

Shell Positional Parameters

Arguments are also available as $1, $2, etc.:

{
name: "copy"
args: [
{name: "source", description: "Source path", required: true},
{name: "dest", description: "Destination path", required: true},
]
implementations: [{
script: """
# Using environment variables
cp "$INVOWK_ARG_SOURCE" "$INVOWK_ARG_DEST"

# Or positional parameters
cp "$1" "$2"

# All arguments
echo "Args: $@"
echo "Count: $#"
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}

Shell Compatibility

ShellPositional Access
bash, sh, zsh$1, $2, $@, $#
PowerShell$args[0], $args[1]
virtual runtime$1, $2, $@, $#
container$1, $2, $@, $#

Real-World Examples

File Processing

{
name: "convert"
description: "Convert file format"
args: [
{
name: "input"
description: "Input file"
required: true
},
{
name: "output"
description: "Output file"
required: true
},
{
name: "format"
description: "Output format"
default_value: "json"
validation: "^(json|yaml|toml|xml)$"
}
]
implementations: [{
script: """
echo "Converting $1 to $2 as $3"
./converter --input="$1" --output="$2" --format="$3"
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}

Multi-File Operation

{
name: "compress"
description: "Compress files into archive"
args: [
{
name: "archive"
description: "Output archive name"
required: true
validation: ".(zip|tar.gz|tgz)$"
},
{
name: "files"
description: "Files to compress"
variadic: true
}
]
implementations: [{
script: """
if [ -z "$INVOWK_ARG_FILES" ]; then
echo "No files specified!"
exit 1
fi

# Use the space-separated list
tar -czvf "$INVOWK_ARG_ARCHIVE" $INVOWK_ARG_FILES
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}

Deployment

{
name: "deploy"
description: "Deploy services"
args: [
{
name: "env"
description: "Target environment"
required: true
validation: "^(dev|staging|prod)$"
},
{
name: "replicas"
description: "Number of replicas"
type: "int"
default_value: "1"
},
{
name: "services"
description: "Services to deploy"
variadic: true
}
]
implementations: [{
script: """
echo "Deploying to $INVOWK_ARG_ENV with $INVOWK_ARG_REPLICAS replicas"

if [ -n "$INVOWK_ARG_SERVICES" ]; then
for i in $(seq 1 $INVOWK_ARG_SERVICES_COUNT); do
eval "service=$INVOWK_ARG_SERVICES_$i"
echo "Deploying $service..."
kubectl scale deployment/$service --replicas=$INVOWK_ARG_REPLICAS
done
else
echo "Deploying all services..."
kubectl scale deployment --all --replicas=$INVOWK_ARG_REPLICAS
fi
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}

Mixing with Flags

Flags can appear anywhere; arguments are positional:

# All equivalent
invowk cmd deploy prod 3 --dry-run
invowk cmd deploy --dry-run prod 3
invowk cmd deploy prod --dry-run 3

Arguments are extracted in order, regardless of flag positions.

Arguments vs Subcommands

A command cannot have both arguments and subcommands. If a command defines args but also has subcommands, invowk fails with an error:

✖ Invalid command structure

Command 'deploy' has both args and subcommands in invowkfile.cue
defined args: env
subcommands: deploy status, deploy logs

Remove either the 'args' field or the subcommands to resolve this conflict.

This restriction exists because CLI parsers interpret positional arguments after a command name as potential subcommand names, making the combination ambiguous.

Choose one approach:

  • Arguments: For leaf commands with direct inputs
  • Subcommands: For complex command hierarchies where users select an action

Best Practices

  1. Required args first: Follow ordering rules
  2. Use meaningful names: source and dest not arg1 and arg2
  3. Validate when possible: Catch errors early
  4. Document with descriptions: Help users understand
  5. Prefer flags for optional values: Easier to understand

Next Steps