CLI Commands

Global Options

--config-dir <PATH>    Config directory (default: ~/.config/laio)
-v, --verbose          Increase logging verbosity (repeat for more)
-q, --quiet            Decrease logging verbosity
-h, --help             Print help
-V, --version          Print version

--config-dir is a global option: every subcommand accepts it.

Commands from startup, shutdown, and scripts echo ❯ <command> and stream their output at every verbosity level. Internal multiplexer commands run silently. Detached commands (the zellij/herdr server spawn) echo only from -vvv (debug logging) upward. Verbosity levels: default = errors only, -v = warnings, -vv = info, -vvv = debug, -vvvv = trace.

laio start

Start a new session from a configuration.

Usage

laio start [OPTIONS] [NAME]

Arguments

[NAME] - Name of the configuration (optional)

  • If omitted, shows configuration picker
  • If .laio.yaml exists, uses it automatically
  • Use -p to skip local config and show picker

Options

-f, --file <PATH>      Use specific configuration file
-m, --muxer <MUXER>    Multiplexer to use (tmux, zellij, or herdr)
-p, --show-picker      Show config picker (skip .laio.yaml)
--skip-cmds            Skip startup commands/scripts
--skip-attach          Start session without attaching
--var <KEY=VALUE>      Template variable (repeatable)

Template Variables

Pass variables to your configuration templates using --var:

# Single variable
laio start myconfig --var project_name=webapp

# Multiple variables
laio start myconfig --var name=myapp --var env=dev

# Array variables (repeat same key)
laio start myconfig --var service=api --var service=web --var service=worker

# Inline array syntax (CSV)
laio start myconfig --var 'service[]=api,web,worker'

Auto-injected variables (session started by name):

  • session_name - Set to the session name (first argument)
  • path - Defaults to current working directory (override with --var path=...)
  • A --file start injects neither variable; pass --var session_name=... --var path=... when the config uses them

Variables can be used in your YAML configuration with Tera syntax:

name: {{ session_name }}  # Injected for name-based starts
path: {{ path }}          # Defaults to cwd
env:
  PROJECT: {{ project_name }}  # User-provided variable

See the YAML Reference for detailed template variable documentation.

Examples

# Start with auto-detection
laio start

# Start specific config
laio start myproject

# Start with variables
laio start template --var project=frontend --var env=dev

# Start with array variables for multiple services
laio start microservices \
  --var services=auth \
  --var services=api \
  --var services=frontend

# Start with inline CSV array syntax
laio start microservices --var 'services[]=auth,api,frontend'

# Start from custom file
laio start --file /path/to/config.yaml

# Start without startup commands
laio start myproject --skip-cmds

# Start without attaching
laio start myproject --skip-attach

# Force picker (ignore .laio.yaml)
laio start -p

laio stop

Stop a running session.

Usage

laio stop [OPTIONS] [NAME]

Arguments

[NAME] - Name of the multiplexer session to stop (optional)

  • If omitted inside a laio-managed session, laio stops the current session
  • If omitted outside a laio-managed session, laio exits with "Specify laio session you want to stop."
  • [NAME] is always the multiplexer session name; --var does not change its meaning

Options

-m, --muxer <MUXER>    Multiplexer to use (tmux, zellij, or herdr)
--skip-cmds            Skip shutdown commands/scripts
-a, --all              Stop all laio-managed sessions
-o, --others           Stop all sessions except current
--var <KEY=VALUE>      Template variable (repeatable)

Template Variables

When your session was started with template variables, provide the same variables to stop:

# Start session with variables
laio start myconfig --var env=dev --var region=us-east

# Stop session using same variables
laio stop myconfig --var env=dev --var region=us-east

Auto-injected variables:

  • session_name - Always set to the session name parameter
  • path - Defaults to current working directory

This is necessary when the shutdown commands depend on template variables. laio reads the config path from the session's LAIO_CONFIG variable. With --var, laio re-renders that config with the variables you pass; without --var, laio reuses the variables stored in the session's LAIO_VARS.

Examples

# Stop specific session (non-templated)
laio stop myproject

# Stop session started with template variables
laio stop template --var project=frontend --var env=dev

# Using inline CSV array syntax (same as start)
laio stop microservices --var 'services[]=auth,api,frontend'

# Stop without shutdown commands
laio stop myproject --skip-cmds

# Stop all laio sessions
laio stop --all

# Stop all except current
laio stop --others

laio list

List active and available sessions/configurations.

Usage

laio list [OPTIONS]

Alias: laio ls

Options

-m, --muxer <MUXER>    Multiplexer to use (tmux, zellij, or herdr)
-j, --json             Output as JSON

Examples

# List all (table format)
laio list

# List with JSON output
laio list --json

# Using alias
laio ls

Output

Each row shows a status icon and a name:

  • ● - attached (running, you are in it)
  • ○ - active (running, not attached)
  • · - inactive (configuration only)

laio config

Manage configurations.

laio config create

Create a new configuration.

Usage

laio config create [OPTIONS] [NAME]

Arguments

[NAME] - Name of the configuration (optional)

  • If omitted, creates .laio.yaml in current directory

Options

-c, --copy <NAME>      Copy from existing configuration
--var <KEY=VALUE>      Template variable (repeatable)

Template Variables

When creating configs, --var allows you to provide custom variables that will be rendered in your _default.yaml template:

# Create config with custom variables
laio config create myproject --var env=production --var region=us-east

Auto-injected variables:

  • session_name - Set from the config name parameter
  • path - Set to current working directory

For example, if your _default.yaml contains:

name: {{ session_name }}
path: {{ path }}

env:
  ENVIRONMENT: {{ env }}
  REGION: {{ region }}

Running laio config create myproject --var env=prod --var region=eu will create a config with those values rendered.

Examples

# Create new config
laio config create myproject

# Create with template variables
laio config create myproject --var env=production --var db=postgres

# Create with inline CSV array syntax
laio config create myproject --var 'features[]=auth,logging,metrics'

# Create from template
laio config create newproject --copy template

# Create local .laio.yaml
laio config create

# Create local .laio.yaml with variables
laio config create --var env=dev

laio config edit

Edit a configuration in $EDITOR.

Usage

laio config edit <NAME>

Arguments

<NAME> - Name of the configuration (required)

Examples

laio config edit myproject

Link local configuration to global config directory.

Usage

laio config link [OPTIONS] <NAME>

Arguments

<NAME> - Name for the symlink (required)

Options

-f, --file <PATH>      File to link (default: .laio.yaml)

Examples

# Link .laio.yaml
laio config link myproject

# Link custom file
laio config link myproject --file custom-config.yaml

laio config validate

Validate a configuration against the schema.

Usage

laio config validate [OPTIONS] [NAME]

Arguments

[NAME] - Name of the configuration (optional)

  • If omitted, validates the --file value, which defaults to .laio.yaml

Options

-f, --file <PATH>      File to validate (default: .laio.yaml)
--var <KEY=VALUE>      Template variable (repeatable)

Examples

# Validate named config
laio config validate myproject

# Validate with template variables
laio config validate mytemplate --var name=test --var path=/tmp

# Validate with inline CSV array syntax
laio config validate mytemplate --var 'items[]=a,b,c'

# Validate template with defaults (no variables needed)
laio config validate mytemplate

# Validate local file
laio config validate --file .laio.yaml

# Validate default local config
laio config validate

Template Validation

When validating templates:

  • session_name and path are auto-injected (don't need --var or defaults)
  • Other variables need --var flags unless they have default values
  • Tera syntax is always validated
  • Resulting YAML structure is validated after rendering

Validation checks:

  1. Tera template syntax (fails if invalid template syntax)
  2. Template rendering with variables or defaults
  3. YAML structure validation (fails if invalid YAML)
  4. Session schema validation (fails if missing required fields)

Example: Template requiring custom variable:

name: {{ session_name }}  # Auto-injected
path: {{ path }}          # Auto-injected
env:
  NODE_ENV: {{ env }}     # Requires --var env=...

Validate with required variable:

laio config validate mytemplate --var env=production

laio config delete

Delete a configuration.

Usage

laio config delete [OPTIONS] <NAME>

Alias: laio config rm

Arguments

<NAME> - Name of the configuration (required)

Options

-f, --force            Skip confirmation prompt

Examples

# Delete with confirmation
laio config delete myproject

# Force delete
laio config delete myproject --force

# Using alias
laio config rm myproject

laio config list

List all configurations.

Usage

laio config list [OPTIONS]

Alias: laio config ls

Options

-m, --muxer <MUXER>    Multiplexer to use (tmux, zellij, or herdr)
-j, --json             Output as JSON

Examples

# List all configs
laio config list

# List with JSON output
laio config list --json

# Using alias
laio config ls

laio session

Manage sessions.

laio session list

List active sessions.

Usage

laio session list [OPTIONS]

Alias: laio session ls

Options

-m, --muxer <MUXER>    Multiplexer to use (tmux, zellij, or herdr)
-j, --json             Output as JSON

Examples

# List active sessions
laio session list

# List with JSON output
laio session list --json

laio session yaml

Export current session to YAML format.

Usage

laio session yaml [OPTIONS]

Options

-m, --muxer <MUXER>    Multiplexer to use (tmux, zellij, or herdr)

Examples

# Print YAML to stdout
laio session yaml

# Save to file
laio session yaml > ~/.config/laio/newsession.yaml

# Save as local config
laio session yaml > .laio.yaml

Note: Must be run from within a tmux, zellij, or herdr session.

laio completion

Generate shell completion scripts.

Usage

laio completion <SHELL>

Arguments

<SHELL> - Shell to generate completions for

  • bash
  • elvish
  • fish
  • nushell
  • powershell
  • zsh

Examples

# Generate bash completions
laio completion bash

# Install bash completions
laio completion bash > ~/.local/share/bash-completion/completions/laio

# Generate zsh completions
laio completion zsh > ~/.zsh/completions/_laio

# Generate fish completions
laio completion fish > ~/.config/fish/completions/laio.fish

# Generate nushell completions (nushell syntax)
laio completion nushell | save ($env.HOME | path join ".config" "nushell" "completions" "laio.nu")

Environment Variables

LAIO_MUXER

Override the default multiplexer.

export LAIO_MUXER=tmux   # Use tmux (default)
export LAIO_MUXER=zellij # Use zellij (experimental)
export LAIO_MUXER=herdr  # Use herdr (experimental)

Equivalent to using --muxer flag on every command.

LAIO_CONFIG

Used internally by laio to pass configuration to sessions. Do not set manually.

Tmux Integration

Session Switching

Laio automatically configures a tmux key binding for quick session switching:

prefix M-l

This opens a popup with the configuration picker, which lists configurations and active sessions. Selecting an active session switches to it; selecting a configuration starts it. The binding is only available within sessions started by laio.

Known Limitations

Nested Panes

There are practical limits to nesting depth. Very deep nesting (5+ levels) may cause layout issues or unexpected behavior.

Recommendations:

  • Keep nesting to 2-3 levels maximum
  • Use multiple windows for complex multi-pane setups
  • Test configurations before committing to a workflow

Multiplexer Limitations

Zellij and herdr support is experimental and may have limitations compared to tmux. Use tmux for production workflows.

herdr (experimental)

herdr maps one laio config to one workspace inside the dedicated laio session. When laio runs inside a herdr pane, that pane's session hosts the workspaces instead.

Select herdr on every command. Multiplexer selection is per invocation and defaults to tmux. Pass --muxer herdr on each laio command, or set LAIO_MUXER=herdr. Without it, laio targets tmux.

  • laio start <config> creates the workspace and its windows, then attaches to the TUI and blocks until you detach. Starting a config that is already running focuses its workspace. --skip-attach skips the attach; the TUI is also reachable directly with herdr session attach laio. A stopped laio session left by an earlier interruption is cleaned on the next laio start.
  • laio stop <config> closes that workspace. Other laio-managed workspaces and the laio session keep running. When it was the last laio-managed workspace, the session is left stopped, not running, and the next laio start cleans the ~ workspace. laio stop --all closes every laio-managed workspace — including the one laio runs from — and leaves the session stopped. Anything in it laio does not own — herdr's fallback workspace or workspaces you create in the TUI — closes with the session stop.
  • laio stop --others closes the other laio-managed workspaces and keeps the current one running. Run it from inside a laio workspace; from a bare terminal it errors.
  • A failing shutdown hook surfaces an error but does not block the stop: the workspace still closes and the session still tears down.
  • laio list shows the laio-owned workspaces by config name. It marks ● only for the workspace of the pane laio runs in. herdr exposes no attached-client state, so from a bare terminal every row shows ○.
  • laio session yaml exports the workspace of the pane laio runs in. It requires HERDR_WORKSPACE_ID, which herdr sets in every pane.
  • laio marks ownership per workspace with the LAIO_CONFIG and LAIO_VARS metadata tokens.
  • Pane style is ignored on herdr.