Skip to main content
Version: 0.1.0-alpha.1

Tool Dependencies

Tool dependencies verify that required binaries are available in PATH before your command runs.

Basic Usage

depends_on: {
tools: [
{alternatives: ["go"]}
]
}

If go isn't found in PATH, the command fails with a clear error:

$ invowk cmd build

✗ Dependencies not satisfied

Command 'build' has unmet dependencies:

Missing Tools:
• go - not found in PATH

Install the missing tools and try again.

Alternatives (OR Semantics)

Specify multiple alternatives when any tool will work:

depends_on: {
tools: [
{alternatives: ["docker", "podman"]},
{alternatives: ["node", "nodejs"]}
]
}

Invowk™ checks alternatives in order and stops at the first match. This is useful for:

  • Tools with compatible alternatives (docker/podman)
  • Editor preferences (nvim/vim/vi)
  • Version variants (python3/python)

Multiple Tool Requirements

Each entry in tools is an AND requirement:

depends_on: {
tools: [
// Need (podman OR docker) AND kubectl AND helm
{alternatives: ["podman", "docker"]},
{alternatives: ["kubectl"]},
{alternatives: ["helm"]},
]
}

All three must be satisfied (though alternatives within each are OR).

Real-World Examples

Go Project

{
name: "build"
depends_on: {
tools: [
{alternatives: ["go"]},
{alternatives: ["git"]}, // For version info
]
}
implementations: [{
script: """
VERSION=$(git describe --tags --always)
go build -ldflags="-X main.version=$VERSION" ./...
"""
runtimes: [{name: "native"}]
}]
}

Node.js Project

{
name: "build"
depends_on: {
tools: [
// Prefer pnpm, but npm works too
{alternatives: ["pnpm", "npm", "yarn"]},
{alternatives: ["node"]},
]
}
implementations: [{
script: "pnpm run build || npm run build"
runtimes: [{name: "native"}]
}]
}

Kubernetes Deployment

{
name: "deploy"
depends_on: {
tools: [
{alternatives: ["kubectl"]},
{alternatives: ["helm"]},
{alternatives: ["podman", "docker"]},
]
}
implementations: [{
script: """
helm upgrade --install myapp ./charts/myapp
kubectl rollout status deployment/myapp
"""
runtimes: [{name: "native"}]
}]
}

Python Project

{
name: "run"
depends_on: {
tools: [
// Python 3 with various possible names
{alternatives: ["python3", "python"]},
// Virtual environment tool
{alternatives: ["poetry", "pipenv", "pip"]},
]
}
implementations: [{
script: "poetry run python main.py"
runtimes: [{name: "native"}]
}]
}

Runtime-Aware Validation

Tool checks are validated according to the runtime:

Native Runtime

Tools are checked on the host system:

{
name: "build"
depends_on: {
tools: [{alternatives: ["go"]}] // Checked on host
}
implementations: [{
script: "go build ./..."
runtimes: [{name: "native"}]
}]
}

Virtual Runtime

Tools are checked in the virtual shell environment:

{
name: "build"
depends_on: {
tools: [{alternatives: ["go"]}] // Checked in virtual shell
}
implementations: [{
script: "go build ./..."
runtimes: [{name: "virtual"}]
}]
}

Container Runtime

Tools are checked inside the container:

{
name: "build"
implementations: [{
script: "go build ./..."
runtimes: [{name: "container", image: "golang:1.21"}]
depends_on: {
// This checks for 'go' INSIDE the container
tools: [{alternatives: ["go"]}]
}
}]
}

This is especially useful because:

  • The host doesn't need Go installed
  • You're validating the actual execution environment
  • You catch missing tools in custom container images

Common Patterns

Check Before External Call

{
name: "upload"
depends_on: {
tools: [{alternatives: ["aws", "aws-cli"]}]
}
implementations: [{
script: "aws s3 sync ./dist s3://my-bucket"
runtimes: [{name: "native"}]
}]
}

Database Tools

{
name: "db migrate"
depends_on: {
tools: [
{alternatives: ["psql", "pgcli"]}, // PostgreSQL client
{alternatives: ["migrate", "goose", "flyway"]}, // Migration tool
]
}
implementations: [{
script: "migrate -path ./migrations -database $DATABASE_URL up"
runtimes: [{name: "native"}]
}]
}

Cross-Platform

{
name: "open docs"
depends_on: {
tools: [
// Platform-specific openers
{alternatives: ["xdg-open", "open", "start"]},
]
}
implementations: [{
script: "xdg-open http://localhost:3000/docs || open http://localhost:3000/docs"
runtimes: [{name: "native"}]
}]
}

Best Practices

  1. Use alternatives for compatible tools: {alternatives: ["podman", "docker"]}
  2. Order alternatives by preference: First alternative is checked first
  3. Keep tool lists minimal: Only require what's actually used
  4. Consider runtime context: Container tools are checked inside containers

Next Steps