# Niri Window Capture Skill

⚠️ **SECURITY NOTICE**: Read [SECURITY.md](./SECURITY.md) before using. This skill can invisibly capture ANY window, including those on other workspaces.

Invisibly capture screenshots of any window across all workspaces.

## What It Does

Capture windows from **any workspace** without switching views:

```bash
# Capture the window you're looking at
./scripts/capture-focused.sh

# Capture any Firefox window
./scripts/capture-by-title.sh "Firefox"

# Capture window #12 (even if on different workspace)
niri msg action screenshot-window --id 12 --write-to-disk true
```

**Zero flicker. Zero workspace switching. Completely invisible.**

## How It Works

niri compositor keeps window buffers in memory even when windows aren't visible. This skill uses niri's `screenshot-window` action to render those buffers directly to PNG files.

## Installation

```bash
# Claude Code
ln -s $(pwd)/skills/niri-window-capture ~/.claude/skills/niri-window-capture

# OpenCode
ln -s $(pwd)/skills/niri-window-capture ~/.config/opencode/skills/niri-window-capture
```

## Requirements

- niri compositor (25.08+)
- jq
- logger (util-linux)
- Screenshots enabled in niri config

## Security

**This skill has significant privacy implications:**

- ✅ All captures logged to systemd journal
- ⚠️ Can capture windows from ANY workspace invisibly
- ⚠️ Screenshots ALWAYS copied to clipboard (niri limitation)
- ✅ Protect sensitive apps via niri block-out rules

**View audit log:**
```bash
journalctl --user -t niri-capture
```

**Protect password managers:**
```kdl
# Add to ~/.config/niri/config.kdl
window-rule {
    match app-id=r#"^org\.keepassxc\.KeePassXC$"#
    block-out-from "screen-capture"
}
```

See [SECURITY.md](./SECURITY.md) for complete security analysis.

## Use Cases

**"Show me the focused window"**:
```bash
SCREENSHOT=$(./scripts/capture-focused.sh)
# AI analyzes the screenshot
```

**"Find the window with the error message"**:
```bash
# AI loops through all windows, captures each, searches for error
for id in $(niri msg --json windows | jq -r '.[].id'); do
    niri msg action screenshot-window --id "$id" --write-to-disk true
    sleep 0.1
    SCREENSHOT=$(ls -t ~/Pictures/Screenshots/*.png | head -1)
    # Analyze screenshot...
done
```

**"What's on workspace 2?"**:
```bash
# Capture all windows from workspace 2
niri msg --json windows | jq -r '.[] | select(.workspace_id == 2) | .id' | while read id; do
    niri msg action screenshot-window --id "$id" --write-to-disk true
    sleep 0.1
done
```

## Why This Is Useful

Before this skill, capturing windows from inactive workspaces required:
1. Toggle overview mode (~450ms flicker)
2. OR switch to workspace (visible change)

Now you can capture ANY window invisibly by using its window ID.

## Technical Note

This works because Wayland applications continuously render to their surface buffers. The compositor (niri) holds references to these buffers via `smithay::desktop::Window`. When you call `screenshot-window`, niri renders that buffer directly without compositing it to the screen.
