mirror of
https://github.com/anthropics/claude-code.git
synced 2026-04-19 01:52:42 +00:00
Compare commits
1 Commits
claude/sla
...
claude/sla
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
411381bf3e |
27
CHANGELOG.md
27
CHANGELOG.md
@@ -1,32 +1,5 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 2.0.71
|
|
||||||
|
|
||||||
- Added `blockedMarketplaces` to enterprise managed settings, allowing administrators to prevent specific plugin marketplaces from being installed
|
|
||||||
- Added /config toggle to enable/disable prompt suggestions
|
|
||||||
- Added `/settings` as an alias for the `/config` command
|
|
||||||
- Fixed @ file reference suggestions incorrectly triggering when cursor is in the middle of a path
|
|
||||||
- Fixed MCP servers from `.mcp.json` not loading when using `--dangerously-skip-permissions`
|
|
||||||
- Fixed permission rules incorrectly rejecting valid bash commands containing shell glob patterns (e.g., `ls *.txt`, `for f in *.png`)
|
|
||||||
- Bedrock: Environment variable `ANTHROPIC_BEDROCK_BASE_URL` is now respected for token counting and inference profile listing
|
|
||||||
- New syntax highlighting engine for native build
|
|
||||||
|
|
||||||
## 2.0.70
|
|
||||||
|
|
||||||
- Added Enter key to accept and submit prompt suggestions immediately (tab still accepts for editing)
|
|
||||||
- Added wildcard syntax `mcp__server__*` for MCP tool permissions to allow or deny all tools from a server
|
|
||||||
- Added auto-update toggle for plugin marketplaces, allowing per-marketplace control over automatic updates
|
|
||||||
- Added `plan_mode_required` spawn parameter for teammates to require plan approval before implementing changes
|
|
||||||
- Added `current_usage` field to status line input, enabling accurate context window percentage calculations
|
|
||||||
- Fixed input being cleared when processing queued commands while the user was typing
|
|
||||||
- Fixed prompt suggestions replacing typed input when pressing Tab
|
|
||||||
- Fixed diff view not updating when terminal is resized
|
|
||||||
- Improved memory usage by 3x for large conversations
|
|
||||||
- Improved resolution of stats screenshots copied to clipboard (Ctrl+S) for crisper images
|
|
||||||
- Removed # shortcut for quick memory entry (tell Claude to edit your CLAUDE.md instead)
|
|
||||||
- Fix thinking mode toggle in /config not persisting correctly
|
|
||||||
- Improve UI for file creation permission dialog
|
|
||||||
|
|
||||||
## 2.0.69
|
## 2.0.69
|
||||||
|
|
||||||
- Minor bugfixes
|
- Minor bugfixes
|
||||||
|
|||||||
@@ -22,29 +22,23 @@ Performs automated code review on a pull request using multiple specialized agen
|
|||||||
- **Agent #4**: Analyze git blame/history for context-based issues
|
- **Agent #4**: Analyze git blame/history for context-based issues
|
||||||
5. Scores each issue 0-100 for confidence level
|
5. Scores each issue 0-100 for confidence level
|
||||||
6. Filters out issues below 80 confidence threshold
|
6. Filters out issues below 80 confidence threshold
|
||||||
7. Outputs review (to terminal by default, or as PR comment with `--comment` flag)
|
7. Posts review comment with high-confidence issues only
|
||||||
|
|
||||||
**Usage:**
|
**Usage:**
|
||||||
```bash
|
```bash
|
||||||
/code-review [--comment]
|
/code-review
|
||||||
```
|
```
|
||||||
|
|
||||||
**Options:**
|
|
||||||
- `--comment`: Post the review as a comment on the pull request (default: outputs to terminal only)
|
|
||||||
|
|
||||||
**Example workflow:**
|
**Example workflow:**
|
||||||
```bash
|
```bash
|
||||||
# On a PR branch, run locally (outputs to terminal):
|
# On a PR branch, run:
|
||||||
/code-review
|
/code-review
|
||||||
|
|
||||||
# Post review as PR comment:
|
|
||||||
/code-review --comment
|
|
||||||
|
|
||||||
# Claude will:
|
# Claude will:
|
||||||
# - Launch 4 review agents in parallel
|
# - Launch 4 review agents in parallel
|
||||||
# - Score each issue for confidence
|
# - Score each issue for confidence
|
||||||
# - Output issues ≥80 confidence (to terminal or PR depending on flag)
|
# - Post comment with issues ≥80 confidence
|
||||||
# - Skip if no high-confidence issues found
|
# - Skip posting if no high-confidence issues found
|
||||||
```
|
```
|
||||||
|
|
||||||
**Features:**
|
**Features:**
|
||||||
@@ -120,23 +114,17 @@ This plugin is included in the Claude Code repository. The command is automatica
|
|||||||
### Standard PR review workflow:
|
### Standard PR review workflow:
|
||||||
```bash
|
```bash
|
||||||
# Create PR with changes
|
# Create PR with changes
|
||||||
# Run local review (outputs to terminal)
|
|
||||||
/code-review
|
/code-review
|
||||||
|
|
||||||
# Review the automated feedback
|
# Review the automated feedback
|
||||||
# Make any necessary fixes
|
# Make any necessary fixes
|
||||||
|
|
||||||
# Optionally post as PR comment
|
|
||||||
/code-review --comment
|
|
||||||
|
|
||||||
# Merge when ready
|
# Merge when ready
|
||||||
```
|
```
|
||||||
|
|
||||||
### As part of CI/CD:
|
### As part of CI/CD:
|
||||||
```bash
|
```bash
|
||||||
# Trigger on PR creation or update
|
# Trigger on PR creation or update
|
||||||
# Use --comment flag to post review comments
|
# Automatically posts review comments
|
||||||
/code-review --comment
|
|
||||||
# Skip if review already exists
|
# Skip if review already exists
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -52,9 +52,7 @@ Note: Still review Claude generated PR's.
|
|||||||
|
|
||||||
6. Filter out any issues that were not validated in step 5. This step will give us our list of high signal issues for our review.
|
6. Filter out any issues that were not validated in step 5. This step will give us our list of high signal issues for our review.
|
||||||
|
|
||||||
7. Finally, output the review.
|
7. Finally, comment on the pull request.
|
||||||
- If the `--comment` argument is provided, post the review as a comment on the pull request using `gh pr comment`
|
|
||||||
- Otherwise (default), output the review directly to the terminal for local viewing
|
|
||||||
When writing your comment, follow these guidelines:
|
When writing your comment, follow these guidelines:
|
||||||
a. Keep your output brief
|
a. Keep your output brief
|
||||||
b. Avoid emojis
|
b. Avoid emojis
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"hooks": {
|
"hooks": {
|
||||||
"SessionStart": [
|
"SessionStart": [
|
||||||
{
|
{
|
||||||
|
"matcher": "*",
|
||||||
"hooks": [
|
"hooks": [
|
||||||
{
|
{
|
||||||
"type": "command",
|
"type": "command",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"hooks": {
|
"hooks": {
|
||||||
"PreToolUse": [
|
"PreToolUse": [
|
||||||
{
|
{
|
||||||
|
"matcher": "*",
|
||||||
"hooks": [
|
"hooks": [
|
||||||
{
|
{
|
||||||
"type": "command",
|
"type": "command",
|
||||||
@@ -14,6 +15,7 @@
|
|||||||
],
|
],
|
||||||
"PostToolUse": [
|
"PostToolUse": [
|
||||||
{
|
{
|
||||||
|
"matcher": "*",
|
||||||
"hooks": [
|
"hooks": [
|
||||||
{
|
{
|
||||||
"type": "command",
|
"type": "command",
|
||||||
@@ -25,6 +27,7 @@
|
|||||||
],
|
],
|
||||||
"Stop": [
|
"Stop": [
|
||||||
{
|
{
|
||||||
|
"matcher": "*",
|
||||||
"hooks": [
|
"hooks": [
|
||||||
{
|
{
|
||||||
"type": "command",
|
"type": "command",
|
||||||
@@ -36,6 +39,7 @@
|
|||||||
],
|
],
|
||||||
"UserPromptSubmit": [
|
"UserPromptSubmit": [
|
||||||
{
|
{
|
||||||
|
"matcher": "*",
|
||||||
"hooks": [
|
"hooks": [
|
||||||
{
|
{
|
||||||
"type": "command",
|
"type": "command",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"hooks": {
|
"hooks": {
|
||||||
"SessionStart": [
|
"SessionStart": [
|
||||||
{
|
{
|
||||||
|
"matcher": "*",
|
||||||
"hooks": [
|
"hooks": [
|
||||||
{
|
{
|
||||||
"type": "command",
|
"type": "command",
|
||||||
|
|||||||
@@ -40,7 +40,27 @@ echo ""
|
|||||||
echo "Checking root structure..."
|
echo "Checking root structure..."
|
||||||
VALID_EVENTS=("PreToolUse" "PostToolUse" "UserPromptSubmit" "Stop" "SubagentStop" "SessionStart" "SessionEnd" "PreCompact" "Notification")
|
VALID_EVENTS=("PreToolUse" "PostToolUse" "UserPromptSubmit" "Stop" "SubagentStop" "SessionStart" "SessionEnd" "PreCompact" "Notification")
|
||||||
|
|
||||||
for event in $(jq -r 'keys[]' "$HOOKS_FILE"); do
|
# Detect format: plugin format has { description?, hooks: {...} } wrapper
|
||||||
|
# Settings format has events directly at root level
|
||||||
|
is_plugin_format=false
|
||||||
|
if jq -e '.hooks' "$HOOKS_FILE" >/dev/null 2>&1; then
|
||||||
|
is_plugin_format=true
|
||||||
|
HOOKS_PATH=".hooks"
|
||||||
|
echo "Detected plugin format (with 'hooks' wrapper)"
|
||||||
|
|
||||||
|
# Validate allowed root keys for plugin format
|
||||||
|
for key in $(jq -r 'keys[]' "$HOOKS_FILE"); do
|
||||||
|
if [ "$key" != "hooks" ] && [ "$key" != "description" ]; then
|
||||||
|
echo "⚠️ Unknown root key in plugin format: $key (expected: 'hooks', 'description')"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
HOOKS_PATH="."
|
||||||
|
echo "Detected settings format (events at root)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate event types
|
||||||
|
for event in $(jq -r "$HOOKS_PATH | keys[]" "$HOOKS_FILE"); do
|
||||||
found=false
|
found=false
|
||||||
for valid_event in "${VALID_EVENTS[@]}"; do
|
for valid_event in "${VALID_EVENTS[@]}"; do
|
||||||
if [ "$event" = "$valid_event" ]; then
|
if [ "$event" = "$valid_event" ]; then
|
||||||
@@ -62,12 +82,12 @@ echo "Validating individual hooks..."
|
|||||||
error_count=0
|
error_count=0
|
||||||
warning_count=0
|
warning_count=0
|
||||||
|
|
||||||
for event in $(jq -r 'keys[]' "$HOOKS_FILE"); do
|
for event in $(jq -r "$HOOKS_PATH | keys[]" "$HOOKS_FILE"); do
|
||||||
hook_count=$(jq -r ".\"$event\" | length" "$HOOKS_FILE")
|
hook_count=$(jq -r "$HOOKS_PATH.\"$event\" | length" "$HOOKS_FILE")
|
||||||
|
|
||||||
for ((i=0; i<hook_count; i++)); do
|
for ((i=0; i<hook_count; i++)); do
|
||||||
# Check matcher exists
|
# Check matcher exists
|
||||||
matcher=$(jq -r ".\"$event\"[$i].matcher // empty" "$HOOKS_FILE")
|
matcher=$(jq -r "$HOOKS_PATH.\"$event\"[$i].matcher // empty" "$HOOKS_FILE")
|
||||||
if [ -z "$matcher" ]; then
|
if [ -z "$matcher" ]; then
|
||||||
echo "❌ $event[$i]: Missing 'matcher' field"
|
echo "❌ $event[$i]: Missing 'matcher' field"
|
||||||
((error_count++))
|
((error_count++))
|
||||||
@@ -75,7 +95,7 @@ for event in $(jq -r 'keys[]' "$HOOKS_FILE"); do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Check hooks array exists
|
# Check hooks array exists
|
||||||
hooks=$(jq -r ".\"$event\"[$i].hooks // empty" "$HOOKS_FILE")
|
hooks=$(jq -r "$HOOKS_PATH.\"$event\"[$i].hooks // empty" "$HOOKS_FILE")
|
||||||
if [ -z "$hooks" ] || [ "$hooks" = "null" ]; then
|
if [ -z "$hooks" ] || [ "$hooks" = "null" ]; then
|
||||||
echo "❌ $event[$i]: Missing 'hooks' array"
|
echo "❌ $event[$i]: Missing 'hooks' array"
|
||||||
((error_count++))
|
((error_count++))
|
||||||
@@ -83,10 +103,10 @@ for event in $(jq -r 'keys[]' "$HOOKS_FILE"); do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Validate each hook in the array
|
# Validate each hook in the array
|
||||||
hook_array_count=$(jq -r ".\"$event\"[$i].hooks | length" "$HOOKS_FILE")
|
hook_array_count=$(jq -r "$HOOKS_PATH.\"$event\"[$i].hooks | length" "$HOOKS_FILE")
|
||||||
|
|
||||||
for ((j=0; j<hook_array_count; j++)); do
|
for ((j=0; j<hook_array_count; j++)); do
|
||||||
hook_type=$(jq -r ".\"$event\"[$i].hooks[$j].type // empty" "$HOOKS_FILE")
|
hook_type=$(jq -r "$HOOKS_PATH.\"$event\"[$i].hooks[$j].type // empty" "$HOOKS_FILE")
|
||||||
|
|
||||||
if [ -z "$hook_type" ]; then
|
if [ -z "$hook_type" ]; then
|
||||||
echo "❌ $event[$i].hooks[$j]: Missing 'type' field"
|
echo "❌ $event[$i].hooks[$j]: Missing 'type' field"
|
||||||
@@ -102,7 +122,7 @@ for event in $(jq -r 'keys[]' "$HOOKS_FILE"); do
|
|||||||
|
|
||||||
# Check type-specific fields
|
# Check type-specific fields
|
||||||
if [ "$hook_type" = "command" ]; then
|
if [ "$hook_type" = "command" ]; then
|
||||||
command=$(jq -r ".\"$event\"[$i].hooks[$j].command // empty" "$HOOKS_FILE")
|
command=$(jq -r "$HOOKS_PATH.\"$event\"[$i].hooks[$j].command // empty" "$HOOKS_FILE")
|
||||||
if [ -z "$command" ]; then
|
if [ -z "$command" ]; then
|
||||||
echo "❌ $event[$i].hooks[$j]: Command hooks must have 'command' field"
|
echo "❌ $event[$i].hooks[$j]: Command hooks must have 'command' field"
|
||||||
((error_count++))
|
((error_count++))
|
||||||
@@ -114,7 +134,7 @@ for event in $(jq -r 'keys[]' "$HOOKS_FILE"); do
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
elif [ "$hook_type" = "prompt" ]; then
|
elif [ "$hook_type" = "prompt" ]; then
|
||||||
prompt=$(jq -r ".\"$event\"[$i].hooks[$j].prompt // empty" "$HOOKS_FILE")
|
prompt=$(jq -r "$HOOKS_PATH.\"$event\"[$i].hooks[$j].prompt // empty" "$HOOKS_FILE")
|
||||||
if [ -z "$prompt" ]; then
|
if [ -z "$prompt" ]; then
|
||||||
echo "❌ $event[$i].hooks[$j]: Prompt hooks must have 'prompt' field"
|
echo "❌ $event[$i].hooks[$j]: Prompt hooks must have 'prompt' field"
|
||||||
((error_count++))
|
((error_count++))
|
||||||
@@ -128,7 +148,7 @@ for event in $(jq -r 'keys[]' "$HOOKS_FILE"); do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Check timeout
|
# Check timeout
|
||||||
timeout=$(jq -r ".\"$event\"[$i].hooks[$j].timeout // empty" "$HOOKS_FILE")
|
timeout=$(jq -r "$HOOKS_PATH.\"$event\"[$i].hooks[$j].timeout // empty" "$HOOKS_FILE")
|
||||||
if [ -n "$timeout" ] && [ "$timeout" != "null" ]; then
|
if [ -n "$timeout" ] && [ "$timeout" != "null" ]; then
|
||||||
if ! [[ "$timeout" =~ ^[0-9]+$ ]]; then
|
if ! [[ "$timeout" =~ ^[0-9]+$ ]]; then
|
||||||
echo "❌ $event[$i].hooks[$j]: Timeout must be a number"
|
echo "❌ $event[$i].hooks[$j]: Timeout must be a number"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"hooks": {
|
"hooks": {
|
||||||
"Stop": [
|
"Stop": [
|
||||||
{
|
{
|
||||||
|
"matcher": "*",
|
||||||
"hooks": [
|
"hooks": [
|
||||||
{
|
{
|
||||||
"type": "command",
|
"type": "command",
|
||||||
|
|||||||
49
scripts/validate-all-hooks.sh
Executable file
49
scripts/validate-all-hooks.sh
Executable file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Validate all hooks.json files in the repository
|
||||||
|
# This script can be run in CI to ensure all plugins have valid hook configurations
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||||
|
VALIDATOR="$REPO_ROOT/plugins/plugin-dev/skills/hook-development/scripts/validate-hook-schema.sh"
|
||||||
|
|
||||||
|
echo "🔍 Validating all hooks.json files in the repository..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Find all hooks.json files
|
||||||
|
mapfile -t HOOKS_FILES < <(find "$REPO_ROOT/plugins" -name "hooks.json" -type f 2>/dev/null)
|
||||||
|
|
||||||
|
if [ ${#HOOKS_FILES[@]} -eq 0 ]; then
|
||||||
|
echo "No hooks.json files found"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Found ${#HOOKS_FILES[@]} hooks.json file(s)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
errors=0
|
||||||
|
for hooks_file in "${HOOKS_FILES[@]}"; do
|
||||||
|
relative_path="${hooks_file#$REPO_ROOT/}"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo "📄 $relative_path"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if bash "$VALIDATOR" "$hooks_file"; then
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
((errors++))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ $errors -eq 0 ]; then
|
||||||
|
echo "✅ All ${#HOOKS_FILES[@]} hooks.json file(s) are valid!"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "❌ $errors hooks.json file(s) have validation errors"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user