Skip to main content
Version: 0.12.0

Working Directory

Control where your commands execute with the workdir setting. This is especially useful for monorepos and projects with complex directory structures.

Default Behavior​

By default, commands from the root invowkfile run in the directory where the invowkfile is located. For modules, commands run in the module's root directory. Relative workdir paths are resolved from these locations.

Setting Working Directory​

Command Level​

{
name: "build frontend"
workdir: "./frontend" // Run in frontend subdirectory
implementations: [{
script: "npm run build"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}

Implementation Level​

{
name: "build"
implementations: [
{
script: "npm run build"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
workdir: "./web" // This implementation runs in ./web
},
{
script: "go build ./..."
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
workdir: "./api" // This implementation runs in ./api
}
]
}

Root Level​

workdir: "./src" // All commands default to ./src

cmds: [
{
name: "build"
// Inherits workdir: ./src
implementations: [...]
},
{
name: "test"
workdir: "./tests" // Override to ./tests
implementations: [...]
}
]

CLI Override​

Override the working directory at runtime:

invowk cmd build --ivk-workdir ./frontend

Path Types​

Relative Paths​

Relative to the invowkfile location:

workdir: "./frontend"
workdir: "../shared"
workdir: "src/app"

Absolute Paths​

Full system paths:

workdir: "/opt/myapp"
workdir: "/home/user/projects/myapp"

Environment Variables​

Expand variables in paths:

workdir: "${HOME}/projects/myapp"
workdir: "${PROJECT_ROOT}/src"

Precedence​

CLI override (--ivk-workdir) overrides implementation, which overrides command, which overrides root:

// --ivk-workdir (CLI) > implementation > command > root
workdir: "./root" // Lowest: ./root

cmds: [
{
name: "build"
workdir: "./command" // Override: ./command
implementations: [
{
script: "make"
workdir: "./implementation" // Override: ./implementation
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}
]
}
]

Monorepo Pattern​

Perfect for monorepos with multiple packages:

cmds: [
{
name: "web build"
workdir: "./packages/web"
implementations: [{
script: "npm run build"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
},
{
name: "api build"
workdir: "./packages/api"
implementations: [{
script: "go build ./..."
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
},
{
name: "mobile build"
workdir: "./packages/mobile"
implementations: [{
script: "flutter build"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}
]

Container Working Directory​

For containers, the current directory is mounted to /workspace:

{
name: "build"
implementations: [{
script: """
pwd # /workspace
ls # Shows your project files
"""
runtimes: [{name: "container", image: "debian:stable-slim"}]
platforms: [{name: "linux"}]
}]
}

With workdir, that subdirectory becomes the container's working directory:

{
name: "build package"
workdir: "./frontend"
implementations: [{
script: """
pwd # /workspace/frontend
./build.sh
"""
runtimes: [{name: "container", image: "debian:stable-slim"}]
platforms: [{name: "linux"}]
}]
}

Cross-Platform Paths​

Use forward slashes for cross-platform compatibility:

// Good - works everywhere
workdir: "./src/app"

// Avoid - Windows-specific
workdir: ".\\src\\app"

Invowk™ automatically converts to native path separators at runtime.

Real-World Examples​

Frontend/Backend Split​

cmds: [
{
name: "start frontend"
workdir: "./frontend"
implementations: [{
script: "npm run dev"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
},
{
name: "start backend"
workdir: "./backend"
implementations: [{
script: "go run ./cmd/server"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}
]

Test Organization​

cmds: [
{
name: "test unit"
workdir: "./tests/unit"
implementations: [{
script: "pytest"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
},
{
name: "test integration"
workdir: "./tests/integration"
implementations: [{
script: "pytest"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
},
{
name: "test e2e"
workdir: "./tests/e2e"
implementations: [{
script: "cypress run"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}
]

Build in Subdirectory​

{
name: "build"
workdir: "./src"
implementations: [{
script: """
# Now in ./src
go build -o ../bin/app ./...
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}

Best Practices​

  1. Use relative paths: More portable across machines
  2. Forward slashes: Cross-platform compatible
  3. Root level for defaults: Override where needed
  4. Keep paths short: Easier to understand

Next Steps​