From aa8eb2e067e8de275b97b1e0ddf7246d6a0aa2e5 Mon Sep 17 00:00:00 2001 From: DotcomJack Date: Thu, 6 Aug 2026 18:00:03 -0400 Subject: [PATCH 1/3] Add claude-session-tint plugin --- .claude-plugin/marketplace.json | 17 + README.md | 1 + .../.claude-plugin/plugin.json | 14 + plugins/claude-session-tint/LICENSE | 21 + plugins/claude-session-tint/README.md | 27 ++ plugins/claude-session-tint/bin/tabtint | 18 + .../claude-session-tint/commands/tabtint.md | 17 + plugins/claude-session-tint/hooks/hooks.json | 34 ++ plugins/claude-session-tint/palette.conf | 35 ++ plugins/claude-session-tint/prompt-hook.sh | 108 +++++ plugins/claude-session-tint/tabtint.sh | 404 ++++++++++++++++++ 11 files changed, 696 insertions(+) create mode 100644 plugins/claude-session-tint/.claude-plugin/plugin.json create mode 100644 plugins/claude-session-tint/LICENSE create mode 100644 plugins/claude-session-tint/README.md create mode 100755 plugins/claude-session-tint/bin/tabtint create mode 100644 plugins/claude-session-tint/commands/tabtint.md create mode 100644 plugins/claude-session-tint/hooks/hooks.json create mode 100644 plugins/claude-session-tint/palette.conf create mode 100755 plugins/claude-session-tint/prompt-hook.sh create mode 100755 plugins/claude-session-tint/tabtint.sh diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 6f29b6b..f1f363d 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -1670,6 +1670,23 @@ "security", "compliance" ] + }, + { + "name": "claude-session-tint", + "source": "./plugins/claude-session-tint", + "description": "Tint a Terminal.app window by project and brighten it when a Claude Code response finishes unseen; includes a UserPromptSubmit hook that runs an input-box command without invoking the model.", + "version": "1.1.0", + "author": { + "name": "DotcomJack" + }, + "category": "Workflow Orchestration", + "homepage": "https://github.com/dotcomjack/claude-session-tint", + "keywords": [ + "terminal", + "macos", + "hooks", + "multi-session" + ] } ] } \ No newline at end of file diff --git a/README.md b/README.md index e4de615..db7390a 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Install or disable them dynamically with the `/plugin` command — enabling you - [angelos-symbo](./plugins/angelos-symbo) - [ceo-quality-controller-agent](./plugins/ceo-quality-controller-agent) - [claude-desktop-extension](./plugins/claude-desktop-extension) +- [claude-session-tint](./plugins/claude-session-tint) - [lyra](./plugins/lyra) - [model-context-protocol-mcp-expert](./plugins/model-context-protocol-mcp-expert) - [problem-solver-specialist](./plugins/problem-solver-specialist) diff --git a/plugins/claude-session-tint/.claude-plugin/plugin.json b/plugins/claude-session-tint/.claude-plugin/plugin.json new file mode 100644 index 0000000..6de1346 --- /dev/null +++ b/plugins/claude-session-tint/.claude-plugin/plugin.json @@ -0,0 +1,14 @@ +{ + "name": "claude-session-tint", + "displayName": "Claude Session Tint", + "version": "1.1.0", + "description": "Know which Claude Code session needs you. Tints a Terminal.app window by project and brightens it when a response lands unseen.", + "author": { + "name": "DotcomJack", + "url": "https://dotcomjack.com" + }, + "homepage": "https://github.com/dotcomjack/claude-session-tint", + "repository": "https://github.com/dotcomjack/claude-session-tint", + "license": "MIT", + "keywords": ["terminal", "macos", "hooks", "multi-session", "productivity"] +} diff --git a/plugins/claude-session-tint/LICENSE b/plugins/claude-session-tint/LICENSE new file mode 100644 index 0000000..e8bead3 --- /dev/null +++ b/plugins/claude-session-tint/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 DotcomJack + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/claude-session-tint/README.md b/plugins/claude-session-tint/README.md new file mode 100644 index 0000000..d3d5a96 --- /dev/null +++ b/plugins/claude-session-tint/README.md @@ -0,0 +1,27 @@ +# claude-session-tint + +Know which Claude Code session needs you. + +Tag a terminal window with a project. It wears that project's color quietly +while it works, brightens when a response lands while you are looking elsewhere, +and drops back the moment you focus it. + +``` +,api tag this window "API" (no turn, no tokens, no reply) +, show the palette +,off untag +``` + +Typing `,api` runs a command from inside a live session **without invoking the +model**: a `UserPromptSubmit` hook returns `decision:"block"` with +`suppressOriginalPrompt`, so Claude Code never queries the model. That pattern +works on any terminal and any OS. The window coloring itself is macOS +Terminal.app only, because Terminal.app is the one terminal with no native tab +colors. + +Edit your palette at `~/.claude/tabtint-palette.conf` (falls back to the bundled +`palette.conf`). Tune with `TABTINT_IDLE_PCT` and `TABTINT_ATTN_PCT`. + +Upstream, issues and full docs: https://github.com/dotcomjack/claude-session-tint + +MIT. diff --git a/plugins/claude-session-tint/bin/tabtint b/plugins/claude-session-tint/bin/tabtint new file mode 100755 index 0000000..e6c39f5 --- /dev/null +++ b/plugins/claude-session-tint/bin/tabtint @@ -0,0 +1,18 @@ +#!/bin/bash +# Tag this terminal window with a project color. +# tabtint show this window's tag and the palette +# tabtint api tag it (case insensitive, prefixes work) +# tabtint off untag, back to the original background +# tabtint list just the palette +# tabtint sync repaint every window (after editing colors) +# tabtint idle on|off resting tint on or off +# tabtint status what the hook currently sees +# +# Prefers tabtint.sh one level up (plugin layout: bin/ inside the plugin root), +# then falls back to a manual install under ~/.claude/hooks. +here=$(cd "$(dirname "$0")" 2>/dev/null && pwd) +for c in "$here/../tabtint.sh" "$HOME/.claude/hooks/tabtint.sh"; do + [ -x "$c" ] && exec "$c" tab "$@" +done +echo "tabtint: cannot find tabtint.sh (looked in $here/.. and ~/.claude/hooks)" >&2 +exit 1 diff --git a/plugins/claude-session-tint/commands/tabtint.md b/plugins/claude-session-tint/commands/tabtint.md new file mode 100644 index 0000000..4fe3d6e --- /dev/null +++ b/plugins/claude-session-tint/commands/tabtint.md @@ -0,0 +1,17 @@ +--- +description: Tint this terminal window with a project color. No argument shows the palette. +argument-hint: " | off | list | idle on|off | status (or just type ,project)" +allowed-tools: Bash(${CLAUDE_PLUGIN_ROOT}/tabtint.sh:*) +disable-model-invocation: true +model: haiku +effort: low +--- + +The window color command has already run during expansion. Its output: + +!`${CLAUDE_PLUGIN_ROOT}/tabtint.sh tab $ARGUMENTS` + +Print that output back verbatim, then on a final line print exactly: +`tip: , in the input box does the same thing with no turn.` + +No other commentary, no summary, no preamble, no tool calls. There is nothing left to do. diff --git a/plugins/claude-session-tint/hooks/hooks.json b/plugins/claude-session-tint/hooks/hooks.json new file mode 100644 index 0000000..7f552e8 --- /dev/null +++ b/plugins/claude-session-tint/hooks/hooks.json @@ -0,0 +1,34 @@ +{ + "hooks": { + "SessionStart": [ + { + "matcher": "", + "hooks": [ + { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/tabtint.sh rest", "timeout": 25, "async": true } + ] + } + ], + "UserPromptSubmit": [ + { + "matcher": "", + "hooks": [ + { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/prompt-hook.sh", "timeout": 10 } + ] + }, + { + "matcher": "", + "hooks": [ + { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/tabtint.sh clear", "timeout": 25, "async": true } + ] + } + ], + "Stop": [ + { + "matcher": "", + "hooks": [ + { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/tabtint.sh set", "timeout": 25, "async": true } + ] + } + ] + } +} diff --git a/plugins/claude-session-tint/palette.conf b/plugins/claude-session-tint/palette.conf new file mode 100644 index 0000000..ae686e9 --- /dev/null +++ b/plugins/claude-session-tint/palette.conf @@ -0,0 +1,35 @@ +# tabtint palette +# +# Format, TAB separated: +# HEX KEY LABEL EMOJI +# +# KEY is what you type: `tabtint api`. Matching is case insensitive and accepts +# a prefix, so `tabtint ap` works too. +# +# HEX is the identity color at full strength. It is never painted at full +# strength: it scales to a readable dark wash (22% at rest, 48% unread). +# +# EMOJI is optional. When set, tagging a window copies a ready-to-paste +# `/rename