Stream Deck plugin to monitor and control your Claude Code instances with animated status icons and gesture controls.
- Real-time Status Display: Animated icons showing Claude Code state (idle, running, tool use, editing, question, permission, error)
- Gesture Controls:
- Single Press: Focus the terminal window
- Double Press: Cancel the current operation
- Hold (500ms): Approve pending permission requests
- Multi-instance Support: Assign each Stream Deck key to a different Claude Code session
- Node.js 20+
- Stream Deck software 6.6+
- Claude Code with hooks support
jqandcurl(for hook scripts)- Kitty Terminal (for terminal integration features)
AgentDeck uses Kitty's remote control API for terminal integration features like focusing windows, sending signals, and launching new Claude instances.
Add these lines to your ~/.config/kitty/kitty.conf:
allow_remote_control yes
listen_on unix:/tmp/kitty
After changing the config, restart Kitty for the settings to take effect.
- Socket Detection: AgentDeck automatically detects Kitty sockets at
/tmp/kittyor/tmp/kitty-*(PID-suffixed) - Full Binary Paths: On macOS, the plugin uses full paths to Kitty binaries (
/Applications/kitty.app/Contents/MacOS/kitten) since Stream Deck plugins run in a sandboxed environment without access to shell PATH - Interactive Shell: When launching new Claude instances, the plugin uses an interactive shell (
zsh -i -c claude) to ensure shell aliases are available
"Remote Control Not Available" in Property Inspector
- Ensure
allow_remote_control yesis in yourkitty.conf - Restart Kitty after changing the config
- Verify the socket exists:
ls /tmp/kitty*
Button press doesn't open new Claude window
- Test remote control manually:
kitten @ ls - Check plugin logs in
com.agentdeck.plugin.sdPlugin/logs/ - Verify Kitty is installed at
/Applications/kitty.app(macOS)
Claude command not found when launching
- The
claudecommand may be an alias in your shell config - AgentDeck launches with
-iflag to load interactive shell config (.zshrc) - Ensure your Claude alias is defined in
~/.zshrc(not just~/.zprofile)
-
Socket Path Priority:
KITTY_LISTEN_ONenvironment variable- Auto-detected
/tmp/kittyor/tmp/kitty-*sockets - Default fallback to
unix:/tmp/kitty
-
Launch Fallback: If remote control fails, AgentDeck falls back to launching Kitty directly via the binary path
cd AgentDeck
npm installnpm run buildstreamdeck link com.agentdeck.plugin.sdPluginOr manually copy the com.agentdeck.plugin.sdPlugin folder to:
- macOS:
~/Library/Application Support/com.elgato.StreamDeck/Plugins/ - Windows:
%appdata%\Elgato\StreamDeck\Plugins\
The hook script reports Claude Code status to the AgentDeck server.
# Copy the hook script to ~/.agentdeck/hooks/
mkdir -p ~/.agentdeck/hooks
cp hooks/status-reporter.sh ~/.agentdeck/hooks/
chmod +x ~/.agentdeck/hooks/status-reporter.shIMPORTANT: You must manually add the hooks to your Claude Code configuration. The installation does NOT modify your settings automatically.
Edit ~/.claude/settings.json and add the hooks configuration. If you have existing hooks, merge them carefully:
{
"hooks": {
"SessionStart": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "~/.agentdeck/hooks/status-reporter.sh",
"timeout": 5
}
]
}
],
"SessionEnd": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "~/.agentdeck/hooks/status-reporter.sh",
"timeout": 5
}
]
}
],
"PreToolUse": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "~/.agentdeck/hooks/status-reporter.sh",
"timeout": 5
}
]
}
],
"PostToolUse": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "~/.agentdeck/hooks/status-reporter.sh",
"timeout": 5
}
]
}
],
"Notification": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "~/.agentdeck/hooks/status-reporter.sh",
"timeout": 5
}
]
}
],
"Stop": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "~/.agentdeck/hooks/status-reporter.sh",
"timeout": 5
}
]
}
],
"PermissionRequest": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "~/.agentdeck/hooks/status-reporter.sh",
"timeout": 5
}
]
}
]
}
}See hooks/hooks.json for the complete configuration template.
Restart any running Claude Code instances to pick up the new hook configuration.
- Add a "Claude Instance" action to your Stream Deck
- In the Property Inspector, select which Claude Code session to monitor
- Optionally set a custom display name and terminal app
| Icon | State | Description |
|---|---|---|
| Green checkmark | Idle | Claude Code is ready for input |
| Blue spinner | Running | Processing a request |
| Orange gear | Tool Use | Executing a tool (Bash, Read, etc.) |
| Purple pencil | Editing | Modifying files |
| Cyan ? | Question | Waiting for user input |
| Red shield | Permission | Pending permission approval |
| Red ! | Error | An error occurred |
| Gray X | Disconnected | Session not connected |
| Gesture | Threshold | Action |
|---|---|---|
| Single Press | - | Focus the terminal window |
| Double Press | 300ms | Cancel current operation |
| Hold | 500ms | Approve pending permission |
Claude Code ──(hooks)──> Status Server ──(WebSocket)──> Stream Deck Plugin
localhost:19847
- Hook Scripts: Report status changes to the local server
- Status Server: HTTP+WebSocket server tracking all instances
- Plugin: Connects via WebSocket, displays animated icons
# Watch mode (auto-rebuild)
npm run watch
# One-time build
npm run build- Ensure the plugin is in the correct Plugins directory
- Restart the Stream Deck application
- Check plugin logs in
com.agentdeck.plugin.sdPlugin/logs/
- Verify hooks are configured in
~/.claude/settings.json - Check that
jqandcurlare installed - Test the hook script:
echo '{"session_id":"test","hook_event_name":"Stop"}' | ~/.agentdeck/hooks/status-reporter.sh - Check server is running:
curl http://127.0.0.1:19847/health
If port 19847 is in use, the plugin will assume the server is already running. Kill any existing processes on that port.
MIT