Compare commits

...

4 Commits

Author SHA1 Message Date
Claude
69585d4ffa feat: Add slack-quote-formatter plugin for better quoted message display
Adds a new plugin that transforms plain Slack forwarded message blocks into
visually distinctive formatted boxes using Unicode box-drawing characters.

Before:
  [Forwarded Message]
  From: Felix Klock
  Message: Here is some text...

After:
  ╔════════════════════════════════════════════════════════════════════╗
  ║  FORWARDED MESSAGE                                                 ║
  ╠════════════════════════════════════════════════════════════════════╣
  ║  From: Felix Klock                                                 ║
  ╟────────────────────────────────────────────────────────────────────╢
  ║    Here is some text...                                            ║
  ╚════════════════════════════════════════════════════════════════════╝

The plugin uses a UserPromptSubmit hook to intercept prompts containing
[Forwarded Message] blocks and reformats them for better visual distinction.

https://claude.ai/code/session_01YNRC6p2gAMSQZPX2NGK5F1
2026-02-10 19:46:10 +00:00
GitHub Actions
19bb071fe0 chore: Update CHANGELOG.md 2026-02-10 00:52:42 +00:00
GitHub Actions
85f2807991 chore: Update CHANGELOG.md 2026-02-07 19:09:18 +00:00
GitHub Actions
e7f36bcdf0 chore: Update CHANGELOG.md 2026-02-07 18:01:26 +00:00
6 changed files with 323 additions and 0 deletions

View File

@@ -1,5 +1,23 @@
# Changelog
## 2.1.38
- Fixed VS Code terminal scroll-to-top regression introduced in 2.1.37
- Fixed Tab key queueing slash commands instead of autocompleting
- Fixed bash permission matching for commands using environment variable wrappers
- Fixed text between tool uses disappearing when not using streaming
- Fixed duplicate sessions when resuming in VS Code extension
- Improved heredoc delimiter parsing to prevent command smuggling
- Blocked writes to `.claude/skills` directory in sandbox mode
## 2.1.37
- Fixed an issue where /fast was not immediately available after enabling /extra-usage
## 2.1.36
- Fast mode is now available for Opus 4.6. Learn more at https://code.claude.com/docs/en/fast-mode
## 2.1.34
- Fixed a crash when agent teams setting changed between renders

View File

@@ -25,6 +25,7 @@ Learn more in the [official plugins documentation](https://docs.claude.com/en/do
| [pr-review-toolkit](./pr-review-toolkit/) | Comprehensive PR review agents specializing in comments, tests, error handling, type design, code quality, and code simplification | **Command:** `/pr-review-toolkit:review-pr` - Run with optional review aspects (comments, tests, errors, types, code, simplify, all)<br>**Agents:** `comment-analyzer`, `pr-test-analyzer`, `silent-failure-hunter`, `type-design-analyzer`, `code-reviewer`, `code-simplifier` |
| [ralph-wiggum](./ralph-wiggum/) | Interactive self-referential AI loops for iterative development. Claude works on the same task repeatedly until completion | **Commands:** `/ralph-loop`, `/cancel-ralph` - Start/stop autonomous iteration loops<br>**Hook:** Stop - Intercepts exit attempts to continue iteration |
| [security-guidance](./security-guidance/) | Security reminder hook that warns about potential security issues when editing files | **Hook:** PreToolUse - Monitors 9 security patterns including command injection, XSS, eval usage, dangerous HTML, pickle deserialization, and os.system calls |
| [slack-quote-formatter](./slack-quote-formatter/) | Enhances visual display of Slack forwarded and quoted messages with distinctive Unicode box formatting | **Hook:** UserPromptSubmit - Transforms `[Forwarded Message]` blocks into visually distinctive formatted boxes with clear boundaries and indentation |
## Installation

View File

@@ -0,0 +1,18 @@
{
"name": "slack-quote-formatter",
"version": "1.0.0",
"description": "Enhances visual display of Slack forwarded and quoted messages with distinctive formatting",
"author": {
"name": "Anthropic",
"email": "support@anthropic.com"
},
"license": "MIT",
"keywords": [
"slack",
"formatting",
"quotes",
"messages",
"visual"
],
"hooks": "./hooks/hooks.json"
}

View File

@@ -0,0 +1,87 @@
# Slack Quote Formatter
Enhances the visual display of Slack forwarded and quoted messages with distinctive Unicode box formatting.
## Overview
When Claude Code receives messages from Slack that include forwarded messages, they typically appear as plain text:
```
[Forwarded Message]
From: Felix Klock
Message: I assume it would be a matter of reviewing the entries...
```
This plugin transforms these plain blocks into visually distinctive formatted quotes:
```
╔════════════════════════════════════════════════════════════════════╗
║ FORWARDED MESSAGE ║
╠════════════════════════════════════════════════════════════════════╣
║ From: Felix Klock ║
╟────────────────────────────────────────────────────────────────────╢
║ I assume it would be a matter of reviewing the entries... ║
╚════════════════════════════════════════════════════════════════════╝
```
## Features
- Unicode box drawing characters for clear visual boundaries
- Distinct header section highlighting "FORWARDED MESSAGE"
- Sender information prominently displayed
- Message content indented for quote-like appearance
- Automatic text wrapping for long messages
- Handles multiple forwarded messages in a single prompt
## Installation
This plugin is included in the Claude Code plugins repository. To enable it:
1. Add the plugin to your project's `.claude/settings.json`:
```json
{
"plugins": [
"path/to/plugins/slack-quote-formatter"
]
}
```
2. Or install via the Claude Code plugin command:
```
/plugin add slack-quote-formatter
```
## How It Works
The plugin registers a `UserPromptSubmit` hook that:
1. Intercepts incoming prompts
2. Detects `[Forwarded Message]` blocks in the Slack context
3. Transforms them into formatted boxes with visual distinction
4. Passes the transformed prompt to Claude
## Configuration
No configuration required. The plugin automatically activates when Slack forwarded messages are detected.
## Plugin Structure
```
slack-quote-formatter/
├── .claude-plugin/
│ └── plugin.json # Plugin metadata
├── hooks/
│ ├── hooks.json # Hook configuration
│ └── format_slack_quotes.py # Transformation logic
└── README.md
```
## Why Visual Distinction Matters
When working with Slack context in Claude Code, quoted messages can easily blend into the surrounding text, making it harder to:
- Identify what content is quoted vs. original
- Understand the source of different pieces of information
- Parse complex threads with multiple forwarded messages
This plugin makes quoted content immediately recognizable, improving readability and reducing confusion.

View File

@@ -0,0 +1,185 @@
#!/usr/bin/env python3
"""
Slack Quote Formatter - UserPromptSubmit Hook
Transforms plain Slack forwarded/quoted messages into visually distinctive
formatted blocks with Unicode box characters and better layout.
Before:
[Forwarded Message]
From: John Doe
Message: Here is some text...
After:
╔═══════════════════════════════════════════════════════════╗
║ FORWARDED MESSAGE ║
╠═══════════════════════════════════════════════════════════╣
║ From: John Doe ║
╟───────────────────────────────────────────────────────────╢
║ Here is some text... ║
╚═══════════════════════════════════════════════════════════╝
"""
import json
import re
import sys
def format_forwarded_message(from_line: str, message_content: str) -> str:
"""Format a single forwarded message with visual box styling."""
# Box drawing characters
TOP_LEFT = ""
TOP_RIGHT = ""
BOTTOM_LEFT = ""
BOTTOM_RIGHT = ""
HORIZONTAL = ""
VERTICAL = ""
LEFT_T = ""
RIGHT_T = ""
LEFT_LIGHT = ""
RIGHT_LIGHT = ""
LIGHT_HORIZONTAL = ""
# Configuration
BOX_WIDTH = 70
INNER_WIDTH = BOX_WIDTH - 4 # Account for "║ " and " ║"
def pad_line(text: str, width: int = INNER_WIDTH) -> str:
"""Pad a line to fill the box width."""
if len(text) > width:
return text[:width]
return text + " " * (width - len(text))
def wrap_text(text: str, width: int) -> list:
"""Wrap text to fit within the specified width."""
words = text.split()
lines = []
current_line = []
current_length = 0
for word in words:
word_len = len(word)
if current_length + word_len + (1 if current_line else 0) <= width:
current_line.append(word)
current_length += word_len + (1 if len(current_line) > 1 else 0)
else:
if current_line:
lines.append(" ".join(current_line))
current_line = [word]
current_length = word_len
if current_line:
lines.append(" ".join(current_line))
return lines if lines else [""]
lines = []
# Top border with header
lines.append(f"{TOP_LEFT}{HORIZONTAL * (BOX_WIDTH - 2)}{TOP_RIGHT}")
# Header line
header = "FORWARDED MESSAGE"
lines.append(f"{VERTICAL} {pad_line(header)}{VERTICAL}")
# Separator after header
lines.append(f"{LEFT_T}{HORIZONTAL * (BOX_WIDTH - 2)}{RIGHT_T}")
# From line
from_display = from_line.strip()
lines.append(f"{VERTICAL} {pad_line(from_display)}{VERTICAL}")
# Light separator before message
lines.append(f"{LEFT_LIGHT}{LIGHT_HORIZONTAL * (BOX_WIDTH - 2)}{RIGHT_LIGHT}")
# Message content (indented and wrapped)
message_lines = message_content.strip().split("\n")
for msg_line in message_lines:
# Handle each line, wrapping if necessary
wrapped = wrap_text(msg_line, INNER_WIDTH - 2) # Extra indent
for wrapped_line in wrapped:
indented = " " + wrapped_line # Add indent for quote appearance
lines.append(f"{VERTICAL} {pad_line(indented)}{VERTICAL}")
# Bottom border
lines.append(f"{BOTTOM_LEFT}{HORIZONTAL * (BOX_WIDTH - 2)}{BOTTOM_RIGHT}")
return "\n".join(lines)
def transform_slack_context(text: str) -> str:
"""
Find and transform [Forwarded Message] blocks in the text.
Matches patterns like:
[Forwarded Message]
From: Name Here
Message: Content here that may span
multiple lines until we hit the next section
"""
# Pattern to match forwarded message blocks
# This handles the common format from Slack context
pattern = r'\[Forwarded Message\]\s*\n\s*From:\s*([^\n]+)\s*\nMessage:\s*(.+?)(?=\n\s*\[|\n\[pnkfelix\]|\n<|\Z)'
def replace_match(match):
from_name = match.group(1).strip()
message = match.group(2).strip()
formatted = format_forwarded_message(f"From: {from_name}", message)
return f"\n{formatted}\n"
# Apply transformation
result = re.sub(pattern, replace_match, text, flags=re.DOTALL)
return result
def main():
"""Main entry point for the UserPromptSubmit hook."""
try:
# Read input from stdin
input_data = json.load(sys.stdin)
# Get the user prompt if available
user_prompt = input_data.get("user_prompt", "")
if not user_prompt:
# No prompt to transform, just pass through
print(json.dumps({}))
sys.exit(0)
# Check if there are forwarded messages to format
if "[Forwarded Message]" not in user_prompt:
# Nothing to transform
print(json.dumps({}))
sys.exit(0)
# Transform the prompt
transformed_prompt = transform_slack_context(user_prompt)
# If we made changes, return the transformed prompt
if transformed_prompt != user_prompt:
result = {
"transformedPrompt": transformed_prompt
}
print(json.dumps(result))
else:
print(json.dumps({}))
except json.JSONDecodeError:
# No valid JSON input, pass through
print(json.dumps({}))
except Exception as e:
# Log error but don't block
error_output = {
"systemMessage": f"[slack-quote-formatter] Warning: {str(e)}"
}
print(json.dumps(error_output))
sys.exit(0)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,14 @@
{
"UserPromptSubmit": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/format_slack_quotes.py",
"timeout": 5000
}
]
}
]
}