diff --git a/plugins/amp/README.md b/plugins/amp/README.md new file mode 100644 index 0000000..518eaca --- /dev/null +++ b/plugins/amp/README.md @@ -0,0 +1,55 @@ +# Warp Notifications for Amp + +Warp terminal integration for [Amp](https://ampcode.com) — the coding agent by Sourcegraph. + +## Installation + +Copy the plugin file to Amp's global plugins directory: + +```bash +cp plugins/amp/warp-notify.ts ~/.config/amp/plugins/warp-notify.ts +``` + +Then run Amp with plugins enabled: + +```bash +PLUGINS=all amp +``` + +To enable permanently, add to your shell profile: + +```bash +echo 'export PLUGINS=all' >> ~/.zshrc +``` + +## Verify + +```bash +PLUGINS=all amp plugins list +``` + +You should see: +``` +✓ /Users/you/.config/amp/plugins/warp-notify.ts active + Events: session.start, agent.start, tool.call, tool.result, agent.end +``` + +## Requirements + +- [Warp terminal](https://warp.dev) +- [Amp CLI](https://ampcode.com) (binary install, not npm) +- `PLUGINS=all` environment variable + +## How It Works + +Uses Amp's TypeScript plugin API (`amp.on(...)`) to hook into 5 lifecycle events and emit the same `warp://cli-agent` OSC 777 structured notifications as the Claude Code plugin. + +| Amp Event | Warp Notification | +|---|---| +| `session.start` | `session_start` | +| `agent.start` | `prompt_submit` | +| `tool.call` | `permission_request` | +| `tool.result` | `tool_complete` | +| `agent.end` | `stop` | + +> **Note**: Amp's plugin API is experimental. Expect breaking changes. diff --git a/plugins/amp/warp-notify.ts b/plugins/amp/warp-notify.ts new file mode 100644 index 0000000..7febedd --- /dev/null +++ b/plugins/amp/warp-notify.ts @@ -0,0 +1,81 @@ +// @i-know-the-amp-plugin-api-is-wip-and-very-experimental-right-now +import type { PluginAPI } from '@ampcode/plugin' + +function shouldUseStructured(): boolean { + const proto = process.env.WARP_CLI_AGENT_PROTOCOL_VERSION + const client = process.env.WARP_CLIENT_VERSION + if (!proto || !client) return false + + const LAST_BROKEN_STABLE = 'v0.2026.03.25.08.24.stable_05' + const LAST_BROKEN_PREVIEW = 'v0.2026.03.25.08.24.preview_05' + + let threshold = '' + if (client.includes('stable')) threshold = LAST_BROKEN_STABLE + else if (client.includes('preview')) threshold = LAST_BROKEN_PREVIEW + + if (threshold && !(client > threshold)) return false + return true +} + +function warpNotify(payload: Record): void { + if (!shouldUseStructured()) return + const body = JSON.stringify(payload) + try { + const fs = require('fs') + fs.writeFileSync('/dev/tty', `\x1b]777;notify;warp://cli-agent;${body}\x07`) + } catch {} +} + +function buildPayload(event: string, extra: Record = {}): Record { + const cwd = process.cwd() + return { + v: 1, + agent: 'amp', + event, + cwd, + project: cwd.split('/').pop() || '', + ...extra, + } +} + +export default function (amp: PluginAPI) { + amp.on('session.start', (event) => { + warpNotify(buildPayload('session_start', { + session_id: event.thread?.id || 'unknown', + })) + }) + + amp.on('agent.start', (event) => { + const query = event.message.length > 200 ? event.message.slice(0, 197) + '...' : event.message + warpNotify(buildPayload('prompt_submit', { + session_id: event.thread.id, + query, + })) + }) + + amp.on('tool.call', (event, ctx) => { + const summary = `Wants to run ${event.tool}` + warpNotify(buildPayload('permission_request', { + session_id: event.thread.id, + summary, + tool_name: event.tool, + tool_input: event.input, + })) + return { action: 'allow' } + }) + + amp.on('tool.result', (event) => { + warpNotify(buildPayload('tool_complete', { + session_id: event.thread.id, + tool_name: event.tool, + })) + }) + + amp.on('agent.end', (event) => { + const query = event.message.length > 200 ? event.message.slice(0, 197) + '...' : event.message + warpNotify(buildPayload('stop', { + session_id: event.thread.id, + query, + })) + }) +} diff --git a/plugins/cline/README.md b/plugins/cline/README.md new file mode 100644 index 0000000..81a69bd --- /dev/null +++ b/plugins/cline/README.md @@ -0,0 +1,42 @@ +# Warp Notifications for Cline CLI + +Warp terminal integration for [Cline CLI](https://cline.bot) — the open-source AI coding agent. + +## Installation + +Copy the hook scripts to Cline's hooks directory: + +```bash +mkdir -p ~/Documents/Cline/Hooks +cp plugins/cline/hooks/*.sh ~/Documents/Cline/Hooks/ +chmod +x ~/Documents/Cline/Hooks/*.sh +``` + +Cline automatically discovers hooks from `~/Documents/Cline/Hooks/`. + +## Hooks + +| Hook File | Warp Notification | When | +|---|---|---| +| `TaskStart.sh` | `session_start` | Cline starts a new task | +| `TaskComplete.sh` | `stop` | Cline finishes a task | +| `TaskError.sh` | `stop` (with error) | Cline encounters an error | +| `PreToolUse.sh` | `permission_request` | Before a tool runs | +| `PostToolUse.sh` | `tool_complete` | After a tool finishes | +| `UserPromptSubmit.sh` | `prompt_submit` | User sends a prompt | + +## Requirements + +- [Warp terminal](https://warp.dev) +- [Cline CLI](https://cline.bot) v2.15+ +- `jq` for JSON parsing (`brew install jq`) + +## How It Works + +Each hook script is a self-contained bash script that: +1. Checks for Warp's `WARP_CLI_AGENT_PROTOCOL_VERSION` env var (exits silently if not in Warp) +2. Reads event data from stdin as JSON +3. Builds a structured notification payload +4. Emits it via OSC 777 escape sequence to `/dev/tty` + +The payloads use the same `warp://cli-agent` protocol as the Claude Code plugin. diff --git a/plugins/cline/hooks/PostToolUse.sh b/plugins/cline/hooks/PostToolUse.sh new file mode 100644 index 0000000..5abad34 --- /dev/null +++ b/plugins/cline/hooks/PostToolUse.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Warp notification on Cline post-tool-use + +[ -z "${WARP_CLI_AGENT_PROTOCOL_VERSION:-}" ] && exit 0 +[ -z "${WARP_CLIENT_VERSION:-}" ] && exit 0 + +command -v jq &>/dev/null || exit 0 + +INPUT=$(cat 2>/dev/null || echo '{}') +SESSION_ID=$(echo "$INPUT" | jq -r '.conversationId // .session_id // "unknown"' 2>/dev/null) +CWD=$(echo "$INPUT" | jq -r '.cwd // empty' 2>/dev/null) +[ -z "$CWD" ] && CWD="$(pwd)" +PROJECT=$(basename "$CWD") + +TOOL_NAME=$(echo "$INPUT" | jq -r '.tool // .tool_name // empty' 2>/dev/null) + +BODY=$(jq -nc \ + --argjson v 1 \ + --arg agent "cline" \ + --arg event "tool_complete" \ + --arg session_id "$SESSION_ID" \ + --arg cwd "$CWD" \ + --arg project "$PROJECT" \ + --arg tool_name "$TOOL_NAME" \ + '{v:$v, agent:$agent, event:$event, session_id:$session_id, cwd:$cwd, project:$project, tool_name:$tool_name}') + +printf '\033]777;notify;%s;%s\007' "warp://cli-agent" "$BODY" > /dev/tty 2>/dev/null || true diff --git a/plugins/cline/hooks/PreToolUse.sh b/plugins/cline/hooks/PreToolUse.sh new file mode 100644 index 0000000..3ea00a0 --- /dev/null +++ b/plugins/cline/hooks/PreToolUse.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Warp notification on Cline pre-tool-use (permission request) + +[ -z "${WARP_CLI_AGENT_PROTOCOL_VERSION:-}" ] && exit 0 +[ -z "${WARP_CLIENT_VERSION:-}" ] && exit 0 + +command -v jq &>/dev/null || exit 0 + +INPUT=$(cat 2>/dev/null || echo '{}') +SESSION_ID=$(echo "$INPUT" | jq -r '.conversationId // .session_id // "unknown"' 2>/dev/null) +CWD=$(echo "$INPUT" | jq -r '.cwd // empty' 2>/dev/null) +[ -z "$CWD" ] && CWD="$(pwd)" +PROJECT=$(basename "$CWD") + +TOOL_NAME=$(echo "$INPUT" | jq -r '.tool // .tool_name // "unknown"' 2>/dev/null) +TOOL_INPUT=$(echo "$INPUT" | jq -c '.input // .tool_input // {}' 2>/dev/null) +[ -z "$TOOL_INPUT" ] && TOOL_INPUT='{}' + +SUMMARY="Wants to run $TOOL_NAME" + +BODY=$(jq -nc \ + --argjson v 1 \ + --arg agent "cline" \ + --arg event "permission_request" \ + --arg session_id "$SESSION_ID" \ + --arg cwd "$CWD" \ + --arg project "$PROJECT" \ + --arg summary "$SUMMARY" \ + --arg tool_name "$TOOL_NAME" \ + --argjson tool_input "$TOOL_INPUT" \ + '{v:$v, agent:$agent, event:$event, session_id:$session_id, cwd:$cwd, project:$project, summary:$summary, tool_name:$tool_name, tool_input:$tool_input}') + +printf '\033]777;notify;%s;%s\007' "warp://cli-agent" "$BODY" > /dev/tty 2>/dev/null || true diff --git a/plugins/cline/hooks/TaskComplete.sh b/plugins/cline/hooks/TaskComplete.sh new file mode 100644 index 0000000..bc73786 --- /dev/null +++ b/plugins/cline/hooks/TaskComplete.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Warp notification on Cline task complete + +[ -z "${WARP_CLI_AGENT_PROTOCOL_VERSION:-}" ] && exit 0 +[ -z "${WARP_CLIENT_VERSION:-}" ] && exit 0 + +command -v jq &>/dev/null || exit 0 + +INPUT=$(cat 2>/dev/null || echo '{}') +SESSION_ID=$(echo "$INPUT" | jq -r '.conversationId // .session_id // "unknown"' 2>/dev/null) +CWD=$(echo "$INPUT" | jq -r '.cwd // empty' 2>/dev/null) +[ -z "$CWD" ] && CWD="$(pwd)" +PROJECT=$(basename "$CWD") + +QUERY=$(echo "$INPUT" | jq -r '.query // .prompt // empty' 2>/dev/null) +RESPONSE=$(echo "$INPUT" | jq -r '.response // empty' 2>/dev/null) +[ -n "$QUERY" ] && [ ${#QUERY} -gt 200 ] && QUERY="${QUERY:0:197}..." +[ -n "$RESPONSE" ] && [ ${#RESPONSE} -gt 200 ] && RESPONSE="${RESPONSE:0:197}..." + +BODY=$(jq -nc \ + --argjson v 1 \ + --arg agent "cline" \ + --arg event "stop" \ + --arg session_id "$SESSION_ID" \ + --arg cwd "$CWD" \ + --arg project "$PROJECT" \ + --arg query "$QUERY" \ + --arg response "$RESPONSE" \ + '{v:$v, agent:$agent, event:$event, session_id:$session_id, cwd:$cwd, project:$project, query:$query, response:$response}') + +printf '\033]777;notify;%s;%s\007' "warp://cli-agent" "$BODY" > /dev/tty 2>/dev/null || true diff --git a/plugins/cline/hooks/TaskError.sh b/plugins/cline/hooks/TaskError.sh new file mode 100644 index 0000000..258480d --- /dev/null +++ b/plugins/cline/hooks/TaskError.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Warp notification on Cline task error + +[ -z "${WARP_CLI_AGENT_PROTOCOL_VERSION:-}" ] && exit 0 +[ -z "${WARP_CLIENT_VERSION:-}" ] && exit 0 + +command -v jq &>/dev/null || exit 0 + +INPUT=$(cat 2>/dev/null || echo '{}') +SESSION_ID=$(echo "$INPUT" | jq -r '.conversationId // .session_id // "unknown"' 2>/dev/null) +CWD=$(echo "$INPUT" | jq -r '.cwd // empty' 2>/dev/null) +[ -z "$CWD" ] && CWD="$(pwd)" +PROJECT=$(basename "$CWD") + +BODY=$(jq -nc \ + --argjson v 1 \ + --arg agent "cline" \ + --arg event "stop" \ + --arg session_id "$SESSION_ID" \ + --arg cwd "$CWD" \ + --arg project "$PROJECT" \ + --arg summary "Task errored" \ + '{v:$v, agent:$agent, event:$event, session_id:$session_id, cwd:$cwd, project:$project, summary:$summary}') + +printf '\033]777;notify;%s;%s\007' "warp://cli-agent" "$BODY" > /dev/tty 2>/dev/null || true diff --git a/plugins/cline/hooks/TaskStart.sh b/plugins/cline/hooks/TaskStart.sh new file mode 100644 index 0000000..026e29a --- /dev/null +++ b/plugins/cline/hooks/TaskStart.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Warp notification on Cline task start + +[ -z "${WARP_CLI_AGENT_PROTOCOL_VERSION:-}" ] && exit 0 +[ -z "${WARP_CLIENT_VERSION:-}" ] && exit 0 + +command -v jq &>/dev/null || exit 0 + +INPUT=$(cat 2>/dev/null || echo '{}') +SESSION_ID=$(echo "$INPUT" | jq -r '.conversationId // .session_id // "unknown"' 2>/dev/null) +CWD=$(echo "$INPUT" | jq -r '.cwd // empty' 2>/dev/null) +[ -z "$CWD" ] && CWD="$(pwd)" +PROJECT=$(basename "$CWD") + +BODY=$(jq -nc \ + --argjson v 1 \ + --arg agent "cline" \ + --arg event "session_start" \ + --arg session_id "$SESSION_ID" \ + --arg cwd "$CWD" \ + --arg project "$PROJECT" \ + '{v:$v, agent:$agent, event:$event, session_id:$session_id, cwd:$cwd, project:$project}') + +printf '\033]777;notify;%s;%s\007' "warp://cli-agent" "$BODY" > /dev/tty 2>/dev/null || true diff --git a/plugins/cline/hooks/UserPromptSubmit.sh b/plugins/cline/hooks/UserPromptSubmit.sh new file mode 100644 index 0000000..371a956 --- /dev/null +++ b/plugins/cline/hooks/UserPromptSubmit.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# Warp notification on Cline user prompt submit + +[ -z "${WARP_CLI_AGENT_PROTOCOL_VERSION:-}" ] && exit 0 +[ -z "${WARP_CLIENT_VERSION:-}" ] && exit 0 + +command -v jq &>/dev/null || exit 0 + +INPUT=$(cat 2>/dev/null || echo '{}') +SESSION_ID=$(echo "$INPUT" | jq -r '.conversationId // .session_id // "unknown"' 2>/dev/null) +CWD=$(echo "$INPUT" | jq -r '.cwd // empty' 2>/dev/null) +[ -z "$CWD" ] && CWD="$(pwd)" +PROJECT=$(basename "$CWD") + +QUERY=$(echo "$INPUT" | jq -r '.prompt // empty' 2>/dev/null) +[ -n "$QUERY" ] && [ ${#QUERY} -gt 200 ] && QUERY="${QUERY:0:197}..." + +BODY=$(jq -nc \ + --argjson v 1 \ + --arg agent "cline" \ + --arg event "prompt_submit" \ + --arg session_id "$SESSION_ID" \ + --arg cwd "$CWD" \ + --arg project "$PROJECT" \ + --arg query "$QUERY" \ + '{v:$v, agent:$agent, event:$event, session_id:$session_id, cwd:$cwd, project:$project, query:$query}') + +printf '\033]777;notify;%s;%s\007' "warp://cli-agent" "$BODY" > /dev/tty 2>/dev/null || true