spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

feat: Add slack-quote-formatter plugin for better quoted message displayBrowse files
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
Claude authored on Feb 10, 2026 parent 19bb071 · commit 69585d4ffab4
5 changed files+305 -0compared with 19bb071
Mplugins/README.md
Aplugins/slack-quote-formatter/.claude-plugin/plugin.json
Aplugins/slack-quote-formatter/README.md
Aplugins/slack-quote-formatter/hooks/format_slack_quotes.py
Aplugins/slack-quote-formatter/hooks/hooks.json
@@ -25,6 +25,7 @@
2525 | [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` |
2626 | [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 |
2727 | [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 |
28+| [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 |
2829
2930 ## Installation
3031
@@ -1,0 +1,18 @@
1+{
2+ "name": "slack-quote-formatter",
3+ "version": "1.0.0",
4+ "description": "Enhances visual display of Slack forwarded and quoted messages with distinctive formatting",
5+ "author": {
6+ "name": "Anthropic",
7+ "email": "support@anthropic.com"
8+ },
9+ "license": "MIT",
10+ "keywords": [
11+ "slack",
12+ "formatting",
13+ "quotes",
14+ "messages",
15+ "visual"
16+ ],
17+ "hooks": "./hooks/hooks.json"
18+}
@@ -1,0 +1,87 @@
1+# Slack Quote Formatter
2+
3+Enhances the visual display of Slack forwarded and quoted messages with distinctive Unicode box formatting.
4+
5+## Overview
6+
7+When Claude Code receives messages from Slack that include forwarded messages, they typically appear as plain text:
8+
9+```
10+[Forwarded Message]
11+From: Felix Klock
12+Message: I assume it would be a matter of reviewing the entries...
13+```
14+
15+This plugin transforms these plain blocks into visually distinctive formatted quotes:
16+
17+```
18+╔════════════════════════════════════════════════════════════════════╗
19+║ FORWARDED MESSAGE ║
20+╠════════════════════════════════════════════════════════════════════╣
21+║ From: Felix Klock ║
22+╟────────────────────────────────────────────────────────────────────╢
23+║ I assume it would be a matter of reviewing the entries... ║
24+╚════════════════════════════════════════════════════════════════════╝
25+```
26+
27+## Features
28+
29+- Unicode box drawing characters for clear visual boundaries
30+- Distinct header section highlighting "FORWARDED MESSAGE"
31+- Sender information prominently displayed
32+- Message content indented for quote-like appearance
33+- Automatic text wrapping for long messages
34+- Handles multiple forwarded messages in a single prompt
35+
36+## Installation
37+
38+This plugin is included in the Claude Code plugins repository. To enable it:
39+
40+1. Add the plugin to your project's `.claude/settings.json`:
41+ ```json
42+ {
43+ "plugins": [
44+ "path/to/plugins/slack-quote-formatter"
45+ ]
46+ }
47+ ```
48+
49+2. Or install via the Claude Code plugin command:
50+ ```
51+ /plugin add slack-quote-formatter
52+ ```
53+
54+## How It Works
55+
56+The plugin registers a `UserPromptSubmit` hook that:
57+
58+1. Intercepts incoming prompts
59+2. Detects `[Forwarded Message]` blocks in the Slack context
60+3. Transforms them into formatted boxes with visual distinction
61+4. Passes the transformed prompt to Claude
62+
63+## Configuration
64+
65+No configuration required. The plugin automatically activates when Slack forwarded messages are detected.
66+
67+## Plugin Structure
68+
69+```
70+slack-quote-formatter/
71+├── .claude-plugin/
72+│ └── plugin.json # Plugin metadata
73+├── hooks/
74+│ ├── hooks.json # Hook configuration
75+│ └── format_slack_quotes.py # Transformation logic
76+└── README.md
77+```
78+
79+## Why Visual Distinction Matters
80+
81+When working with Slack context in Claude Code, quoted messages can easily blend into the surrounding text, making it harder to:
82+
83+- Identify what content is quoted vs. original
84+- Understand the source of different pieces of information
85+- Parse complex threads with multiple forwarded messages
86+
87+This plugin makes quoted content immediately recognizable, improving readability and reducing confusion.
@@ -1,0 +1,185 @@
1+#!/usr/bin/env python3
2+"""
3+Slack Quote Formatter - UserPromptSubmit Hook
4+
5+Transforms plain Slack forwarded/quoted messages into visually distinctive
6+formatted blocks with Unicode box characters and better layout.
7+
8+Before:
9+ [Forwarded Message]
10+ From: John Doe
11+ Message: Here is some text...
12+
13+After:
14+ ╔═══════════════════════════════════════════════════════════╗
15+ ║ FORWARDED MESSAGE ║
16+ ╠═══════════════════════════════════════════════════════════╣
17+ ║ From: John Doe ║
18+ ╟───────────────────────────────────────────────────────────╢
19+ ║ Here is some text... ║
20+ ╚═══════════════════════════════════════════════════════════╝
21+"""
22+
23+import json
24+import re
25+import sys
26+
27+
28+def format_forwarded_message(from_line: str, message_content: str) -> str:
29+ """Format a single forwarded message with visual box styling."""
30+
31+ # Box drawing characters
32+ TOP_LEFT = "╔"
33+ TOP_RIGHT = "╗"
34+ BOTTOM_LEFT = "╚"
35+ BOTTOM_RIGHT = "╝"
36+ HORIZONTAL = "═"
37+ VERTICAL = "║"
38+ LEFT_T = "╠"
39+ RIGHT_T = "╣"
40+ LEFT_LIGHT = "╟"
41+ RIGHT_LIGHT = "╢"
42+ LIGHT_HORIZONTAL = "─"
43+
44+ # Configuration
45+ BOX_WIDTH = 70
46+ INNER_WIDTH = BOX_WIDTH - 4 # Account for "║ " and " ║"
47+
48+ def pad_line(text: str, width: int = INNER_WIDTH) -> str:
49+ """Pad a line to fill the box width."""
50+ if len(text) > width:
51+ return text[:width]
52+ return text + " " * (width - len(text))
53+
54+ def wrap_text(text: str, width: int) -> list:
55+ """Wrap text to fit within the specified width."""
56+ words = text.split()
57+ lines = []
58+ current_line = []
59+ current_length = 0
60+
61+ for word in words:
62+ word_len = len(word)
63+ if current_length + word_len + (1 if current_line else 0) <= width:
64+ current_line.append(word)
65+ current_length += word_len + (1 if len(current_line) > 1 else 0)
66+ else:
67+ if current_line:
68+ lines.append(" ".join(current_line))
69+ current_line = [word]
70+ current_length = word_len
71+
72+ if current_line:
73+ lines.append(" ".join(current_line))
74+
75+ return lines if lines else [""]
76+
77+ lines = []
78+
79+ # Top border with header
80+ lines.append(f"{TOP_LEFT}{HORIZONTAL * (BOX_WIDTH - 2)}{TOP_RIGHT}")
81+
82+ # Header line
83+ header = "FORWARDED MESSAGE"
84+ lines.append(f"{VERTICAL} {pad_line(header)}{VERTICAL}")
85+
86+ # Separator after header
87+ lines.append(f"{LEFT_T}{HORIZONTAL * (BOX_WIDTH - 2)}{RIGHT_T}")
88+
89+ # From line
90+ from_display = from_line.strip()
91+ lines.append(f"{VERTICAL} {pad_line(from_display)}{VERTICAL}")
92+
93+ # Light separator before message
94+ lines.append(f"{LEFT_LIGHT}{LIGHT_HORIZONTAL * (BOX_WIDTH - 2)}{RIGHT_LIGHT}")
95+
96+ # Message content (indented and wrapped)
97+ message_lines = message_content.strip().split("\n")
98+ for msg_line in message_lines:
99+ # Handle each line, wrapping if necessary
100+ wrapped = wrap_text(msg_line, INNER_WIDTH - 2) # Extra indent
101+ for wrapped_line in wrapped:
102+ indented = " " + wrapped_line # Add indent for quote appearance
103+ lines.append(f"{VERTICAL} {pad_line(indented)}{VERTICAL}")
104+
105+ # Bottom border
106+ lines.append(f"{BOTTOM_LEFT}{HORIZONTAL * (BOX_WIDTH - 2)}{BOTTOM_RIGHT}")
107+
108+ return "\n".join(lines)
109+
110+
111+def transform_slack_context(text: str) -> str:
112+ """
113+ Find and transform [Forwarded Message] blocks in the text.
114+
115+ Matches patterns like:
116+ [Forwarded Message]
117+ From: Name Here
118+ Message: Content here that may span
119+ multiple lines until we hit the next section
120+ """
121+
122+ # Pattern to match forwarded message blocks
123+ # This handles the common format from Slack context
124+ pattern = r'\[Forwarded Message\]\s*\n\s*From:\s*([^\n]+)\s*\nMessage:\s*(.+?)(?=\n\s*\[|\n\[pnkfelix\]|\n<|\Z)'
125+
126+ def replace_match(match):
127+ from_name = match.group(1).strip()
128+ message = match.group(2).strip()
129+
130+ formatted = format_forwarded_message(f"From: {from_name}", message)
131+ return f"\n{formatted}\n"
132+
133+ # Apply transformation
134+ result = re.sub(pattern, replace_match, text, flags=re.DOTALL)
135+
136+ return result
137+
138+
139+def main():
140+ """Main entry point for the UserPromptSubmit hook."""
141+ try:
142+ # Read input from stdin
143+ input_data = json.load(sys.stdin)
144+
145+ # Get the user prompt if available
146+ user_prompt = input_data.get("user_prompt", "")
147+
148+ if not user_prompt:
149+ # No prompt to transform, just pass through
150+ print(json.dumps({}))
151+ sys.exit(0)
152+
153+ # Check if there are forwarded messages to format
154+ if "[Forwarded Message]" not in user_prompt:
155+ # Nothing to transform
156+ print(json.dumps({}))
157+ sys.exit(0)
158+
159+ # Transform the prompt
160+ transformed_prompt = transform_slack_context(user_prompt)
161+
162+ # If we made changes, return the transformed prompt
163+ if transformed_prompt != user_prompt:
164+ result = {
165+ "transformedPrompt": transformed_prompt
166+ }
167+ print(json.dumps(result))
168+ else:
169+ print(json.dumps({}))
170+
171+ except json.JSONDecodeError:
172+ # No valid JSON input, pass through
173+ print(json.dumps({}))
174+ except Exception as e:
175+ # Log error but don't block
176+ error_output = {
177+ "systemMessage": f"[slack-quote-formatter] Warning: {str(e)}"
178+ }
179+ print(json.dumps(error_output))
180+
181+ sys.exit(0)
182+
183+
184+if __name__ == "__main__":
185+ main()
@@ -1,0 +1,14 @@
1+{
2+ "UserPromptSubmit": [
3+ {
4+ "matcher": ".*",
5+ "hooks": [
6+ {
7+ "type": "command",
8+ "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/format_slack_quotes.py",
9+ "timeout": 5000
10+ }
11+ ]
12+ }
13+ ]
14+}