mirror of
https://github.com/anthropics/claude-code.git
synced 2026-02-19 04:27:33 -08:00
Compare commits
18 Commits
38f1f93052
...
claude/sla
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69585d4ffa | ||
|
|
19bb071fe0 | ||
|
|
85f2807991 | ||
|
|
e7f36bcdf0 | ||
|
|
2bc62d1456 | ||
|
|
ef1e0ac098 | ||
|
|
d7e3cfb31c | ||
|
|
bd78b216ed | ||
|
|
a4e0c5b4c8 | ||
|
|
36d9ee2c2e | ||
|
|
4936302293 | ||
|
|
43d0eac708 | ||
|
|
f298d940fa | ||
|
|
34f551fa91 | ||
|
|
90c07d1c7e | ||
|
|
f93f614768 | ||
|
|
e58014371b | ||
|
|
5862adf641 |
109
CHANGELOG.md
109
CHANGELOG.md
@@ -1,5 +1,114 @@
|
||||
# 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
|
||||
- Fixed a bug where commands excluded from sandboxing (via `sandbox.excludedCommands` or `dangerouslyDisableSandbox`) could bypass the Bash ask permission rule when `autoAllowBashIfSandboxed` was enabled
|
||||
|
||||
## 2.1.33
|
||||
|
||||
- Fixed agent teammate sessions in tmux to send and receive messages
|
||||
- Fixed warnings about agent teams not being available on your current plan
|
||||
- Added `TeammateIdle` and `TaskCompleted` hook events for multi-agent workflows
|
||||
- Added support for restricting which sub-agents can be spawned via `Task(agent_type)` syntax in agent "tools" frontmatter
|
||||
- Added `memory` frontmatter field support for agents, enabling persistent memory with `user`, `project`, or `local` scope
|
||||
- Added plugin name to skill descriptions and `/skills` menu for better discoverability
|
||||
- Fixed an issue where submitting a new message while the model was in extended thinking would interrupt the thinking phase
|
||||
- Fixed an API error that could occur when aborting mid-stream, where whitespace text combined with a thinking block would bypass normalization and produce an invalid request
|
||||
- Fixed API proxy compatibility issue where 404 errors on streaming endpoints no longer triggered non-streaming fallback
|
||||
- Fixed an issue where proxy settings configured via `settings.json` environment variables were not applied to WebFetch and other HTTP requests on the Node.js build
|
||||
- Fixed `/resume` session picker showing raw XML markup instead of clean titles for sessions started with slash commands
|
||||
- Improved error messages for API connection failures — now shows specific cause (e.g., ECONNREFUSED, SSL errors) instead of generic "Connection error"
|
||||
- Errors from invalid managed settings are now surfaced
|
||||
- VSCode: Added support for remote sessions, allowing OAuth users to browse and resume sessions from claude.ai
|
||||
- VSCode: Added git branch and message count to the session picker, with support for searching by branch name
|
||||
- VSCode: Fixed scroll-to-bottom under-scrolling on initial session load and session switch
|
||||
|
||||
## 2.1.32
|
||||
|
||||
- Claude Opus 4.6 is now available!
|
||||
- Added research preview agent teams feature for multi-agent collaboration (token-intensive feature, requires setting CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1)
|
||||
- Claude now automatically records and recalls memories as it works
|
||||
- Added "Summarize from here" to the message selector, allowing partial conversation summarization.
|
||||
- Skills defined in `.claude/skills/` within additional directories (`--add-dir`) are now loaded automatically.
|
||||
- Fixed `@` file completion showing incorrect relative paths when running from a subdirectory
|
||||
- Updated --resume to re-use --agent value specified in previous conversation by default.
|
||||
- Fixed: Bash tool no longer throws "Bad substitution" errors when heredocs contain JavaScript template literals like `${index + 1}`, which previously interrupted tool execution
|
||||
- Skill character budget now scales with context window (2% of context), so users with larger context windows can see more skill descriptions without truncation
|
||||
- Fixed Thai/Lao spacing vowels (สระ า, ำ) not rendering correctly in the input field
|
||||
- VSCode: Fixed slash commands incorrectly being executed when pressing Enter with preceding text in the input field
|
||||
- VSCode: Added spinner when loading past conversations list
|
||||
|
||||
## 2.1.31
|
||||
|
||||
- Added session resume hint on exit, showing how to continue your conversation later
|
||||
- Added support for full-width (zenkaku) space input from Japanese IME in checkbox selection
|
||||
- Fixed PDF too large errors permanently locking up sessions, requiring users to start a new conversation
|
||||
- Fixed bash commands incorrectly reporting failure with "Read-only file system" errors when sandbox mode was enabled
|
||||
- Fixed a crash that made sessions unusable after entering plan mode when project config in `~/.claude.json` was missing default fields
|
||||
- Fixed `temperatureOverride` being silently ignored in the streaming API path, causing all streaming requests to use the default temperature (1) regardless of the configured override
|
||||
- Fixed LSP shutdown/exit compatibility with strict language servers that reject null params
|
||||
- Improved system prompts to more clearly guide the model toward using dedicated tools (Read, Edit, Glob, Grep) instead of bash equivalents (`cat`, `sed`, `grep`, `find`), reducing unnecessary bash command usage
|
||||
- Improved PDF and request size error messages to show actual limits (100 pages, 20MB)
|
||||
- Reduced layout jitter in the terminal when the spinner appears and disappears during streaming
|
||||
- Removed misleading Anthropic API pricing from model selector for third-party provider (Bedrock, Vertex, Foundry) users
|
||||
|
||||
## 2.1.30
|
||||
|
||||
- Added `pages` parameter to the Read tool for PDFs, allowing specific page ranges to be read (e.g., `pages: "1-5"`). Large PDFs (>10 pages) now return a lightweight reference when `@` mentioned instead of being inlined into context.
|
||||
- Added pre-configured OAuth client credentials for MCP servers that don't support Dynamic Client Registration (e.g., Slack). Use `--client-id` and `--client-secret` with `claude mcp add`.
|
||||
- Added `/debug` for Claude to help troubleshoot the current session
|
||||
- Added support for additional `git log` and `git show` flags in read-only mode (e.g., `--topo-order`, `--cherry-pick`, `--format`, `--raw`)
|
||||
- Added token count, tool uses, and duration metrics to Task tool results
|
||||
- Added reduced motion mode to the config
|
||||
- Fixed phantom "(no content)" text blocks appearing in API conversation history, reducing token waste and potential model confusion
|
||||
- Fixed prompt cache not correctly invalidating when tool descriptions or input schemas changed, only when tool names changed
|
||||
- Fixed 400 errors that could occur after running `/login` when the conversation contained thinking blocks
|
||||
- Fixed a hang when resuming sessions with corrupted transcript files containing `parentUuid` cycles
|
||||
- Fixed rate limit message showing incorrect "/upgrade" suggestion for Max 20x users when extra-usage is unavailable
|
||||
- Fixed permission dialogs stealing focus while actively typing
|
||||
- Fixed subagents not being able to access SDK-provided MCP tools because they were not synced to the shared application state
|
||||
- Fixed a regression where Windows users with a `.bashrc` file could not run bash commands
|
||||
- Improved memory usage for `--resume` (68% reduction for users with many sessions) by replacing the session index with lightweight stat-based loading and progressive enrichment
|
||||
- Improved `TaskStop` tool to display the stopped command/task description in the result line instead of a generic "Task stopped" message
|
||||
- Changed `/model` to execute immediately instead of being queued
|
||||
- [VSCode] Added multiline input support to the "Other" text input in question dialogs (use Shift+Enter for new lines)
|
||||
- [VSCode] Fixed duplicate sessions appearing in the session list when starting a new conversation
|
||||
|
||||
## 2.1.29
|
||||
|
||||
- Fixed startup performance issues when resuming sessions that have `saved_hook_context`
|
||||
|
||||
## 2.1.27
|
||||
|
||||
- Added tool call failures and denials to debug logs
|
||||
- Fixed context management validation error for gateway users, ensuring `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` avoids the error
|
||||
- Added `--from-pr` flag to resume sessions linked to a specific GitHub PR number or URL
|
||||
- Sessions are now automatically linked to PRs when created via `gh pr create`
|
||||
- Fixed /context command not displaying colored output
|
||||
- Fixed status bar duplicating background task indicator when PR status was shown
|
||||
- Windows: Fixed bash command execution failing for users with `.bashrc` files
|
||||
- Windows: Fixed console windows flashing when spawning child processes
|
||||
- VSCode: Fixed OAuth token expiration causing 401 errors after extended sessions
|
||||
|
||||
## 2.1.25
|
||||
|
||||
- Fixed beta header validation error for gateway users on Bedrock and Vertex, ensuring `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` avoids the error
|
||||
|
||||
31
examples/settings/README.md
Normal file
31
examples/settings/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Settings Examples
|
||||
|
||||
Example Claude Code settings files, primarily intended for organization-wide deployments. Use these are starting points — adjust them to fit your needs.
|
||||
|
||||
These may be applied at any level of the [settings hierarchy](https://code.claude.com/docs/en/settings#settings-files), though certain properties only take effect if specified in enterprise settings (e.g. `strictKnownMarketplaces`, `allowManagedHooksOnly`, `allowManagedPermissionRulesOnly`).
|
||||
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
> [!WARNING]
|
||||
> These examples are community-maintained snippets which may be unsupported or incorrect. You are responsible for the correctness of your own settings configuration.
|
||||
|
||||
| Setting | [`settings-lax.json`](./settings-lax.json) | [`settings-strict.json`](./settings-strict.json) | [`settings-bash-sandbox.json`](./settings-bash-sandbox.json) |
|
||||
|---------|:---:|:---:|:---:|
|
||||
| Disable `--dangerously-skip-permissions` | ✅ | ✅ | |
|
||||
| Block plugin marketplaces | ✅ | ✅ | |
|
||||
| Block user and project-defined permission `allow` / `ask` / `deny` | | ✅ | ✅ |
|
||||
| Block user and project-defined hooks | | ✅ | |
|
||||
| Deny web fetch and search tools | | ✅ | |
|
||||
| Bash tool requires approval | | ✅ | |
|
||||
| Bash tool must run inside of sandbox | | | ✅ |
|
||||
|
||||
## Tips
|
||||
- Consider merging snippets of the above examples to reach your desired configuration
|
||||
- Settings files must be valid JSON
|
||||
- Before deploying configuration files to your organization, test them locally by applying to `managed-settings.json`, `settings.json` or `settings.local.json`
|
||||
- The `sandbox` property only applies to the `Bash` tool; it does not apply to other tools (like Read, Write, WebSearch, WebFetch, MCPs), hooks, or internal commands
|
||||
|
||||
## Full Documentation
|
||||
|
||||
See https://code.claude.com/docs/en/settings for complete documentation on all available managed settings.
|
||||
18
examples/settings/settings-bash-sandbox.json
Normal file
18
examples/settings/settings-bash-sandbox.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"allowManagedPermissionRulesOnly": true,
|
||||
"sandbox": {
|
||||
"enabled": true,
|
||||
"autoAllowBashIfSandboxed": false,
|
||||
"allowUnsandboxedCommands": false,
|
||||
"excludedCommands": [],
|
||||
"network": {
|
||||
"allowUnixSockets": [],
|
||||
"allowAllUnixSockets": false,
|
||||
"allowLocalBinding": false,
|
||||
"allowedDomains": [],
|
||||
"httpProxyPort": null,
|
||||
"socksProxyPort": null
|
||||
},
|
||||
"enableWeakerNestedSandbox": false
|
||||
}
|
||||
}
|
||||
6
examples/settings/settings-lax.json
Normal file
6
examples/settings/settings-lax.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"permissions": {
|
||||
"disableBypassPermissionsMode": "disable"
|
||||
},
|
||||
"strictKnownMarketplaces": []
|
||||
}
|
||||
28
examples/settings/settings-strict.json
Normal file
28
examples/settings/settings-strict.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"permissions": {
|
||||
"disableBypassPermissionsMode": "disable",
|
||||
"ask": [
|
||||
"Bash"
|
||||
],
|
||||
"deny": [
|
||||
"WebSearch",
|
||||
"WebFetch"
|
||||
]
|
||||
},
|
||||
"allowManagedPermissionRulesOnly": true,
|
||||
"allowManagedHooksOnly": true,
|
||||
"strictKnownMarketplaces": [],
|
||||
"sandbox": {
|
||||
"autoAllowBashIfSandboxed": false,
|
||||
"excludedCommands": [],
|
||||
"network": {
|
||||
"allowUnixSockets": [],
|
||||
"allowAllUnixSockets": false,
|
||||
"allowLocalBinding": false,
|
||||
"allowedDomains": [],
|
||||
"httpProxyPort": null,
|
||||
"socksProxyPort": null
|
||||
},
|
||||
"enableWeakerNestedSandbox": false
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
18
plugins/slack-quote-formatter/.claude-plugin/plugin.json
Normal file
18
plugins/slack-quote-formatter/.claude-plugin/plugin.json
Normal 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"
|
||||
}
|
||||
87
plugins/slack-quote-formatter/README.md
Normal file
87
plugins/slack-quote-formatter/README.md
Normal 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.
|
||||
185
plugins/slack-quote-formatter/hooks/format_slack_quotes.py
Executable file
185
plugins/slack-quote-formatter/hooks/format_slack_quotes.py
Executable 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()
|
||||
14
plugins/slack-quote-formatter/hooks/hooks.json
Normal file
14
plugins/slack-quote-formatter/hooks/hooks.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"UserPromptSubmit": [
|
||||
{
|
||||
"matcher": ".*",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/format_slack_quotes.py",
|
||||
"timeout": 5000
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user