| name | niri |
| description | Niri Wayland compositor control via IPC - window management, workspace operations, output configuration, and compositor automation |
Niri Compositor Control
Use this skill when working with Niri compositor operations, window management, or workspace automation.
Activation Triggers
Activate this skill ONLY when the user explicitly mentions:
- Niri compositor operations
- Generic Window positioning or management
- Workspace control and organization
- Output/monitor configuration changes
- Niri IPC automation
- Compositor state queries
- You are running on Linux,
- Niri is installed and active
Do NOT activate automatically - this is an on-demand skill that requires explicit user request.
Capabilities
This skill provides:
- Window management (focus, move, resize, float/tile)
- Workspace operations (create, name, navigate, organize)
- Output configuration (resolution, scale, position, VRR)
- Column-based layout control (Niri's scrollable tiling)
- Real-time compositor state queries
- IPC automation and scripting
- Event stream monitoring
Available Tools
- niri msg: Primary IPC interface for compositor control
- distrobox-host-exec: Required wrapper to reach host compositor from containers
- JSON output: All commands support
--json flag for scripting
Context Awareness
Environment Detection
- Running in distrobox container - use
distrobox-host-exec niri msg
- Niri version 25.11+ with full IPC support
- KDL configuration format
- DMS (DankMaterialShell) integration present
Core Concepts
Niri's Layout Model
Scrollable Tiling: Unlike i3/sway, Niri uses horizontal scrolling columns:
- Windows are organized in columns
- Columns can contain multiple windows (stacked/tabbed)
- Scroll horizontally through columns
- Each workspace has independent columns
- Column index starts at 1 (not 0)
Key Differences from Traditional Tilers:
- Not binary split (no automatic right/left split)
- Navigate by scrolling, not by directional splits
- Columns can be repositioned by index
- Multiple windows per column form a vertical stack
Window States
- Tiled: Default state, in scrollable column layout
- Floating: Positioned absolutely, outside column flow
- Fullscreen: Takes entire output
- Maximized: Column fills available width
Workspace Model
- Multiple workspaces per output/monitor
- Workspaces can be named (optional)
- Reference by number (1, 2, 3...) or name
- Each workspace has independent column layout
- Empty workspaces will auto remove in a few seconds
Common Operations
Query Compositor State
distrobox-host-exec niri msg windows
distrobox-host-exec niri msg --json windows
distrobox-host-exec niri msg outputs
distrobox-host-exec niri msg workspaces
distrobox-host-exec niri msg focused-window
distrobox-host-exec niri msg focused-output
distrobox-host-exec niri msg overview-state
Window Management
distrobox-host-exec niri msg action focus-window --id <WINDOW_ID>
distrobox-host-exec niri msg action move-window-to-workspace --window-id <ID> --focus false <WORKSPACE_NUM>
distrobox-host-exec niri msg action toggle-window-floating --id <ID>
distrobox-host-exec niri msg action move-window-to-floating --id <ID>
distrobox-host-exec niri msg action move-window-to-tiling --id <ID>
distrobox-host-exec niri msg action set-window-width --id <ID> "50%"
distrobox-host-exec niri msg action set-window-height --id <ID> "30%"
distrobox-host-exec niri msg action close-window --id <ID>
distrobox-host-exec niri msg action fullscreen-window --id <ID>
Column Control (Niri-Specific)
distrobox-host-exec niri msg action focus-window --id <WINDOW_ID>
distrobox-host-exec niri msg action move-column-to-index <COLUMN_INDEX>
distrobox-host-exec niri msg action move-column-left
distrobox-host-exec niri msg action move-column-right
distrobox-host-exec niri msg action center-column
distrobox-host-exec niri msg action maximize-column
Workspace Operations
distrobox-host-exec niri msg action focus-workspace 1
distrobox-host-exec niri msg action focus-workspace "development"
distrobox-host-exec niri msg action set-workspace-name "myproject"
distrobox-host-exec niri msg action set-workspace-name --workspace 2 "email"
distrobox-host-exec niri msg action unset-workspace-name
distrobox-host-exec niri msg action unset-workspace-name 2
Floating Window Positioning
distrobox-host-exec niri msg action move-window-to-floating --id <ID>
distrobox-host-exec niri msg action move-floating-window --id <ID> --x 0 --y 1000
Output Configuration (Temporary)
distrobox-host-exec niri msg output "DP-1" mode 3440 1440 159.962
distrobox-host-exec niri msg output "DP-1" scale 1.5
distrobox-host-exec niri msg output "DP-2" position 3440 200
distrobox-host-exec niri msg output "DP-1" vrr on
distrobox-host-exec niri msg output "DP-2" off
distrobox-host-exec niri msg output "DP-2" on
Interactive Tools
distrobox-host-exec niri msg pick-window
distrobox-host-exec niri msg pick-color
Workflow Patterns
Organize Windows by App Type
windows=$(distrobox-host-exec niri msg --json windows)
Move All Windows to New Workspace
window_ids=$(distrobox-host-exec niri msg --json windows | \
grep -o '"id":[0-9]*.*"workspace_id":N' | \
grep -o '^"id":[0-9]*' | cut -d: -f2)
for id in $window_ids; do
distrobox-host-exec niri msg action move-window-to-workspace \
--window-id $id --focus false <TARGET_WORKSPACE>
done
Create Monitoring Workspace
distrobox-host-exec niri msg action focus-workspace 5
distrobox-host-exec niri msg action set-workspace-name "monitoring"
distrobox-host-exec niri msg action spawn -- alacritty -e btop
distrobox-host-exec niri msg action spawn -- alacritty -e htop
distrobox-host-exec niri msg action spawn -- alacritty -e top
Float and Corner Position
WINDOW_ID=<id>
distrobox-host-exec niri msg action move-window-to-floating --id $WINDOW_ID
distrobox-host-exec niri msg action set-window-width --id $WINDOW_ID "25%"
distrobox-host-exec niri msg action set-window-height --id $WINDOW_ID "30%"
distrobox-host-exec niri msg action move-floating-window --id $WINDOW_ID --x 0 --y 1000
Best Practices
Always Use distrobox-host-exec
Since you're running in a container, always wrap niri msg:
distrobox-host-exec niri msg <command>
Get Window IDs First
Before operating on windows, get their IDs:
distrobox-host-exec niri msg windows | grep "Window ID"
distrobox-host-exec niri msg --json windows | grep -o '"id":[0-9]*'
Use --focus Flag Appropriately
When moving windows:
--focus true (default): Follow window to new workspace
--focus false: Keep focus on current workspace
distrobox-host-exec niri msg action move-window-to-workspace \
--window-id 308 --focus false 2
Reference Workspaces Consistently
- Use numbers for unnamed workspaces:
1, 2, 3
- Use names for named workspaces:
"development", "monitoring"
- Don't mix - if workspace has name, use the name
Understand Column Indexing
- Column index starts at 1 (not 0)
- Higher index = further right in layout
- Moving to index beyond current columns appends to end
- Columns re-index automatically when one is removed
Validate Configuration
Before making config changes:
distrobox-host-exec niri validate
Monitor Events
For automation, use event stream:
distrobox-host-exec niri msg event-stream
Integration with Other Skills
With Containers Skill
Spawn containerized apps in specific workspaces:
distrobox-host-exec niri msg action focus-workspace "containers"
distrobox-host-exec niri msg action spawn -- \
distrobox enter dev -- firefox
With DMS Integration
Many operations go through DMS IPC:
dms ipc call spotlight toggle
dms ipc call clipboard toggle
distrobox-host-exec niri msg action spawn -- <command>
Limitations and Notes
Workspace Deletion
- Cannot delete workspaces - No IPC command exists, a workspace must be empty and unnamed to be cleaned up
- Can only unset names or ignore them
Configuration Changes
- Output changes via IPC are temporary
- Reset on config reload or compositor restart
- For permanent changes, edit
~/.config/niri/config.kdl with chezmoi
Window Identification
- Window IDs change across sessions
- Don't hardcode IDs - always query first
- Use app_id and title for matching if needed
Column Behavior
- Columns auto-collapse when last window removed
- Column indices shift when column removed
- Can't pre-create empty columns
JSON Parsing
- If you are missing
jq, run it via mise exec
Troubleshooting
Commands Not Working
Check compositor version:
distrobox-host-exec niri msg version
Window Not Moving
Verify window exists and get correct ID:
distrobox-host-exec niri msg windows | grep -A 5 "Window ID: <id>"
Workspace Issues
List all workspaces to see current state:
distrobox-host-exec niri msg workspaces
Output Configuration Not Applying
Remember changes are temporary:
distrobox-host-exec niri msg output "DP-1" mode 3440 1440 159.962
Related Documentation
Quick Reference
Most Common Commands
distrobox-host-exec niri msg windows
distrobox-host-exec niri msg workspaces
distrobox-host-exec niri msg outputs
distrobox-host-exec niri msg action focus-window --id <ID>
distrobox-host-exec niri msg action focus-workspace <NUM>
distrobox-host-exec niri msg action move-window-to-workspace --window-id <ID> <WORKSPACE>
distrobox-host-exec niri msg action move-column-to-index <INDEX>
distrobox-host-exec niri msg action toggle-window-floating --id <ID>
distrobox-host-exec niri msg action set-window-width --id <ID> "50%"
distrobox-host-exec niri msg action spawn -- <command>
Example: Complete Window Organization
distrobox-host-exec niri msg windows > /tmp/windows.txt
TERMINAL_IDS=$(grep -B2 "Alacritty" /tmp/windows.txt | grep "Window ID" | awk '{print $3}' | tr -d ':')
FIREFOX_IDS=$(grep -B2 "firefox" /tmp/windows.txt | grep "Window ID" | awk '{print $3}' | tr -d ':')
for id in $TERMINAL_IDS $FIREFOX_IDS; do
distrobox-host-exec niri msg action move-window-to-workspace --window-id $id --focus false 1
done
col=1
for id in $TERMINAL_IDS; do
distrobox-host-exec niri msg action focus-window --id $id
distrobox-host-exec niri msg action move-column-to-index $col
((col++))
done
distrobox-host-exec niri msg action focus-workspace 1
distrobox-host-exec niri msg action set-workspace-name "organized"
Skill Activation Reminder
This skill should ONLY be activated when explicitly requested by the user.
Do not automatically use this skill for general window management discussions. Wait for specific mentions of:
- "use niri msg"
- "control niri"
- "organize my windows"
- "move windows via IPC"
- Other explicit niri compositor operations
This prevents unnecessary invocation and keeps the skill focused on actual compositor automation tasks.