it2 Plugin Development Guide

This guide covers developing plugins for the it2 command-line interface for iTerm2 automation.

See also: taxonomy.md for the authoritative definitions of plugins, hooks, and tools.

Overview

Plugins are external executables that extend it2 functionality. They are discovered automatically from your PATH and invoked programmatically by it2.

Plugins can:

  1. Enrich listings - Add metadata to session, tab, and window listings
  2. Automate responses - Monitor and respond to patterns
  3. Categorize entities - Apply context-specific logic for better organization

Plugins vs Hooks vs Tools

Concept Definition Invocation
Plugin Extends it2, auto-discovered By it2 (it2 plugin run <name>)
Hook Responds to external tool events By Claude Code, Gemini CLI, etc.
Tool Standalone CLI program Directly by user

Plugins are it2-facing: it2 discovers and invokes them. Hooks are external-tool-facing: Claude Code or other tools invoke them based on their configuration.

Plugin Architecture

it2 (core)
  ↓ Discovery
Plugin Registry (internal/plugins/)
  ↓ Execution
External Executables (it2-*)
  ↓ Integration
Enhanced Output

Plugin Types

it2 recognizes four plugin types based on executable naming:

  1. Session Enrichers (it2-session-*) - Add data to session listings
  2. Tab Enrichers (it2-tab-*) - Add data to tab listings
  3. Window Enrichers (it2-window-*) - Add data to window listings
  4. Session Process Enrichers (it2-session-process-*) - Add process data to sessions

Other it2-* executable names are not classified as enrichment plugins.

Runtime Contract

The executable prefix determines the plugin type. Enrichment plugins receive
the same context both as positional arguments and as JSON on standard input.
They return a concise value on standard output. A non-zero exit or empty output
omits that plugin's enrichment.

it2 filters the environment passed to plugins and applies the deadline from
IT2_PLUGIN_DEADLINE, which defaults to five seconds. The experimental
manifest data model is not loaded or enforced by the current runtime; see
Plugin Manifest Data Model.

Quick Start

1. Create a Simple Session Plugin

Create an executable named it2-session-example:

#!/bin/bash
# File: it2-session-example

SESSION_ID="$1"
SESSION_NAME="$2"

# Example: Show if session is running a specific tool
if pgrep -f "vim.*$SESSION_ID" >/dev/null; then
    echo "vim-active"
elif pgrep -f "git.*$SESSION_ID" >/dev/null; then
    echo "git-active"
else
    echo "shell"
fi

Make it executable:

chmod +x it2-session-example

Add to PATH:

export PATH="$PATH:$(pwd)"

2. Test Your Plugin

it2 session list

Your plugin output will appear in the session listing as additional metadata.

Plugin Interface

Session Enrichers

Input Arguments:

Expected Output:

Example:

#!/bin/bash
SESSION_ID="$1"
SESSION_NAME="$2"

# Check if this is a Claude Code session
if [ "$SESSION_NAME" = "Claude Code" ] || echo "$SESSION_NAME" | grep -q "claude"; then
    echo "claude-session"
fi

Tab Enrichers

Input Arguments:

Expected Output:

Window Enrichers

Input Arguments:

Expected Output:

Advanced Example

Configuration-Based Plugin

Create it2-session-classifier that reads from config:

#!/bin/bash
CONFIG_FILE="$HOME/.it2/plugins/classifier.yaml"

SESSION_ID="$1"
SESSION_NAME="$2"

if [ ! -f "$CONFIG_FILE" ]; then
    exit 0
fi

# Parse YAML config (requires yq or similar)
if command -v yq >/dev/null; then
    PATTERNS=$(yq eval '.patterns[]' "$CONFIG_FILE" 2>/dev/null)
    while IFS= read -r pattern; do
        if echo "$SESSION_NAME" | grep -qE "$pattern"; then
            LABEL=$(yq eval ".patterns | to_entries | .[] | select(.value == \"$pattern\") | .key" "$CONFIG_FILE")
            echo "$LABEL"
            exit 0
        fi
    done <<< "$PATTERNS"
fi

With config file ~/.it2/plugins/classifier.yaml:

patterns:
  development: "(vim|code|emacs|nvim)"
  git: "(git|gh|hub)"
  database: "(mysql|postgres|redis|mongo)"
  containers: "(docker|kubectl|k8s)"
  cloud: "(aws|gcp|azure|terraform)"

Plugin Discovery

it2 discovers plugins by:

  1. Scanning all directories in $PATH
  2. Looking for executable files with names starting with it2-
  3. Determining type based on naming pattern:
    • it2-session-* → Session enricher
    • it2-tab-* → Tab enricher
    • it2-window-* → Window enricher
    • it2-session-process-* → Session process enricher

Integration Points

Session Listings

Plugins add data to the PluginData field in session listings:

{
  "session_id": "sess123",
  "session_name": "vim-work",
  "plugin_data": {
    "example": "vim-active",
    "dev-tools": "vim-session"
  }
}

Tab Listings

Similar integration for tab metadata:

{
  "tab_id": "tab456",
  "sessions": [...],
  "plugin_data": {
    "dev-tools": "coding-tab"
  }
}

Best Practices

Performance

Error Handling

Naming Conventions

Output Formatting

Configuration

Debugging

Enable Debug Mode

export ITERM2_DEBUG=1
it2 session list

Test Plugin Directly

./it2-session-example "session-id" "session-name"
echo $?  # Should be 0

Common Issues

  1. Plugin not discovered: Check it's in PATH and executable
  2. No output: Verify plugin returns non-empty string
  3. Timeout: Plugin takes longer than 5 seconds
  4. Wrong arguments: Check argument handling for your plugin type

Distribution

Packaging

Example Structure

my-plugin/
├── it2-session-mystatus
├── it2-tab-mystatus
├── README.md
├── config.yaml.example
└── install.sh

Installation Methods

Method 1: PATH Installation

cp it2-session-mystatus /usr/local/bin/
chmod +x /usr/local/bin/it2-session-mystatus

Method 2: Plugin Directory

mkdir -p ~/.it2/plugins/mystatus
cp it2-session-mystatus ~/.it2/plugins/mystatus/
export PATH="$PATH:$HOME/.it2/plugins/mystatus"

Examples Repository

See internal/embedded/plugins/ for the plugins shipped with it2 and
examples/claude-session-monitor/ for a session-monitoring script.

Using the CLI

List Available Plugins

it2 plugin list

Run a Plugin

# Via it2 (automatic session ID injection)
it2 plugin run <name> [args...]

# Or directly (if in PATH)
it2-session-example <session-id> [args...]

The it2 plugin wrapper provides:

Install Claude Code Hooks

# Install to project settings (.claude/settings.json)
it2 plugin claude-code-hook --install

# Install to global settings (~/.claude/settings.json)
it2 plugin claude-code-hook --install --scope global

Contributing

To contribute plugins or improvements:

  1. Test thoroughly with various session types
  2. Follow naming conventions
  3. Include comprehensive documentation
  4. Add examples to the examples directory
  5. Submit pull requests with test cases

For complex plugins, consider:

Next steps