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.yamlexists, uses it automatically - Use
-pto 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
--filestart 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 -plaio 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;--vardoes 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 parameterpath- 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 --otherslaio 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 JSONExamples
# List all (table format)
laio list
# List with JSON output
laio list --json
# Using alias
laio lsOutput
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.yamlin 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 parameterpath- 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=devlaio config edit
Edit a configuration in $EDITOR.
Usage
laio config edit <NAME>Arguments
<NAME> - Name of the configuration (required)
Examples
laio config edit myprojectlaio config link
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.yamllaio 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
--filevalue, 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 validateTemplate Validation
When validating templates:
session_nameandpathare auto-injected (don't need--varor defaults)- Other variables need
--varflags unless they have default values - Tera syntax is always validated
- Resulting YAML structure is validated after rendering
Validation checks:
- Tera template syntax (fails if invalid template syntax)
- Template rendering with variables or defaults
- YAML structure validation (fails if invalid YAML)
- 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=productionlaio 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 promptExamples
# Delete with confirmation
laio config delete myproject
# Force delete
laio config delete myproject --force
# Using alias
laio config rm myprojectlaio 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 JSONExamples
# List all configs
laio config list
# List with JSON output
laio config list --json
# Using alias
laio config lslaio 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 JSONExamples
# List active sessions
laio session list
# List with JSON output
laio session list --jsonlaio 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
bashelvishfishnushellpowershellzsh
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-attachskips the attach; the TUI is also reachable directly withherdr session attach laio. A stoppedlaiosession left by an earlier interruption is cleaned on the nextlaio start.laio stop <config>closes that workspace. Other laio-managed workspaces and thelaiosession keep running. When it was the last laio-managed workspace, the session is left stopped, not running, and the nextlaio startcleans the~workspace.laio stop --allcloses 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 --otherscloses 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 listshows 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 yamlexports the workspace of the pane laio runs in. It requiresHERDR_WORKSPACE_ID, which herdr sets in every pane.- laio marks ownership per workspace with the
LAIO_CONFIGandLAIO_VARSmetadata tokens. - Pane
styleis ignored on herdr.