Session Export

Overview

Laio can serialize existing tmux, zellij, and herdr sessions into YAML configuration format. This is useful for:

  • Capturing complex layouts built interactively
  • Creating configurations from working sessions
  • Documenting current session structure
  • Sharing team development environments
  • Creating templates from proven setups

Basic Export

From within a tmux, zellij, or herdr session, export to YAML:

laio session yaml

This outputs the current session structure to stdout.

Saving to File

Save the exported YAML to a configuration file:

laio session yaml > ~/.config/laio/mysession.yaml

Or create a local configuration:

laio session yaml > .laio.yaml

What Gets Exported

The export captures:

  • Session name - On tmux and zellij, the current session name; on herdr, the label of the workspace laio runs in, which equals the laio session name for laio-managed workspaces
  • Window structure - All windows and their names
  • Pane layout - Splits, sizes, and arrangement
  • Working directories - Current path for each pane
  • Session path - longest common directory prefix of all pane paths (home collapsed to ~)
  • Running commands - Active processes in panes (see limitations below)
  • Zellij command shape - On zellij the export reads the KDL layout, so a pane with commands exports the shell wrapper as one command: command: <shell> with args: [-c, "<commands>"]
  • Focus and zoom state - On herdr, the export captures the focused pane and the zoomed pane of each window
  • Pane names - On herdr, each pane label exports as the pane name

What Doesn't Get Exported

The following are not captured:

  • Environment variables (env)
  • Lifecycle hooks (startup, shutdown, startup_script, shutdown_script)
  • Pane styles (style)
  • Focus and zoom states (focus, zoom) on tmux and zellij exports

You'll need to add these manually after export.

Command Limitations

Important: Exported commands reflect actual running processes, not the wrapper scripts, aliases, or shell functions used to launch them.

Examples of Command Translation

You RanExported Command
vim (alias to nvim)nvim (actual binary)
dev (shell function)node server.js (underlying process)
npm run devnode --loader tsx src/index.ts (actual command)
Shell with no commandEmpty (no commands field)

Manual Editing Required

After export, you'll likely need to edit commands:

# Exported
panes:
  - commands:
      - command: /usr/local/bin/node
        args: [--loader, tsx, src/index.ts]

# Better for re-use
panes:
  - commands:
      - command: npm
        args: [run, dev]

Typical Workflow

1. Build Your Layout Interactively

Create panes and run commands manually in tmux:

tmux new -s experiment
# Create windows, split panes, run commands
# Adjust layout until satisfied

2. Export the Session

laio session yaml > ~/.config/laio/experiment.yaml

3. Edit the Configuration

laio config edit experiment

Add/fix:

  • Session path
  • Lifecycle hooks if needed
  • Correct command wrappers
  • Environment variables
  • Focus and zoom preferences

4. Test the Configuration

tmux kill-session -t experiment  # Stop the original
laio start experiment             # Test the config

5. Iterate

Refine the configuration based on testing.

Example Export

Interactive Session

Create a session manually:

tmux new -s myapp -c ~/projects/myapp
tmux split-window -h -c ~/projects/myapp
tmux split-window -v -c ~/projects/myapp
tmux select-pane -t 0
tmux split-window -v -c ~/projects/myapp
# Run various commands in panes

Exported YAML

laio session yaml

Produces something like:

name: myapp
path: ~/projects/myapp

windows:
  - name: myapp
    flex_direction: row
    panes:
      - flex: 1
        flex_direction: column
        panes:
          - flex: 1
          - flex: 1
            commands:
              - command: /usr/local/bin/node
                args: [server.js]
      - flex: 1
        flex_direction: column
        panes:
          - flex: 1
            commands:
              - command: /usr/bin/tail
                args: [-f, logs/app.log]
          - flex: 1

After Manual Cleanup

name: myapp
path: ~/projects/myapp

startup:
  - command: docker-compose
    args: [up, -d]

windows:
  - name: dev
    flex_direction: row
    panes:
      - flex: 1
        flex_direction: column
        panes:
          - flex: 1
            focus: true  # Added
          - flex: 1
            commands:
              - command: npm  # Fixed wrapper
                args: [run, dev]
      - flex: 1
        flex_direction: column
        panes:
          - flex: 1
            zoom: true  # Added
            commands:
              - command: npm  # Fixed
                args: [run, logs]
          - flex: 1

Best Practices

  1. Export as a starting point - Not as final configuration
  2. Review paths - Panes under the session root omit path and subdirectories export relative paths; replace any absolute paths (panes outside the session root) with relative or ~ forms
  3. Fix commands - Replace process commands with proper wrappers
  4. Add lifecycle hooks - Include startup/shutdown as needed
  5. Add metadata - Set focus, zoom, styles, env vars
  6. Test thoroughly - Exported configs may not work perfectly first try
  7. Document - Add comments for complex setups

Common Use Cases

Capture Complex Layout

Built a perfect 6-pane layout interactively? Export it:

laio session yaml > ~/.config/laio/dashboard.yaml

Team Onboarding

Show new team members the ideal dev environment:

# Senior developer with working setup
laio session yaml > .laio.yaml
git add .laio.yaml
git commit -m "Add team development session"

Multiple Environments

Create different configs for different contexts:

# Development layout
laio session yaml > ~/.config/laio/dev.yaml

# Switch to debugging layout
tmux kill-session -t dev
# ... set up debugging session ...
laio session yaml > ~/.config/laio/debug.yaml

# Switch to presentation layout
# ... set up clean layout ...
laio session yaml > ~/.config/laio/present.yaml

Now switch between them easily:

laio start dev
laio start debug
laio start present

Troubleshooting

Empty Commands

If panes show no commands:

  • The pane was running a shell with no active process
  • Add commands manually for what should run

Wrong Paths

Panes under the session root omit path (the session root is the default); panes in subdirectories export paths relative to the session root (e.g., src); only panes outside the session root keep absolute paths. Replace with:

  • Relative paths (e.g., ./src)
  • Home-relative (e.g., ~/projects/app)
  • Session root (.)

Binary Paths

Commands show full binary paths (e.g., /usr/local/bin/node):

  • Replace with simple command names (e.g., node)
  • Use wrapper scripts (e.g., npm run dev)

Layout Doesn't Match

The flex sizing is approximate:

  • Adjust flex values to get desired proportions
  • Test and iterate