mirror of
https://github.com/anthropics/claude-code.git
synced 2026-02-19 04:27:33 -08:00
Compare commits
10 Commits
claude/sla
...
claude/sla
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
34994ca273 | ||
|
|
ea2608cf85 | ||
|
|
c27c6f4e4a | ||
|
|
0dde1fef97 | ||
|
|
e4f682030b | ||
|
|
eb87245010 | ||
|
|
3680637065 | ||
|
|
2192c86c20 | ||
|
|
dfd3494132 | ||
|
|
e8cca9a7af |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
.DS_Store
|
||||
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
43
CHANGELOG.md
43
CHANGELOG.md
@@ -1,5 +1,48 @@
|
||||
# Changelog
|
||||
|
||||
## 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
|
||||
|
||||
- Minor bugfixes
|
||||
|
||||
## 2.0.68
|
||||
|
||||
- Fixed IME (Input Method Editor) support for languages like Chinese, Japanese, and Korean by correctly positioning the composition window at the cursor
|
||||
- Fixed a bug where disallowed MCP tools were visible to the model
|
||||
- Fixed an issue where steering messages could be lost while a subagent is working
|
||||
- Fixed Option+Arrow word navigation treating entire CJK (Chinese, Japanese, Korean) text sequences as a single word instead of navigating by word boundaries
|
||||
- Improved plan mode exit UX: show simplified yes/no dialog when exiting with empty or missing plan instead of throwing an error
|
||||
- Add support for enterprise managed settings. Contact your Anthropic account team to enable this feature.
|
||||
|
||||
## 2.0.67
|
||||
|
||||
- Thinking mode is now enabled by default for Opus 4.5
|
||||
- Thinking mode configuration has moved to /config
|
||||
- Added search functionality to `/permissions` command with `/` keyboard shortcut for filtering rules by tool name
|
||||
- Show reason why autoupdater is disabled in `/doctor`
|
||||
- Fixed false "Another process is currently updating Claude" error when running `claude update` while another instance is already on the latest version
|
||||
- Fixed MCP servers from `.mcp.json` being stuck in pending state when running in non-interactive mode (`-p` flag or piped input)
|
||||
- Fixed scroll position resetting after deleting a permission rule in `/permissions`
|
||||
- Fixed word deletion (opt+delete) and word navigation (opt+arrow) not working correctly with non-Latin text such as Cyrillic, Greek, Arabic, Hebrew, Thai, and Chinese
|
||||
- Fixed `claude install --force` not bypassing stale lock files
|
||||
- Fixed consecutive @~/ file references in CLAUDE.md being incorrectly parsed due to markdown strikethrough interference
|
||||
- Windows: Fixed plugin MCP servers failing due to colons in log directory paths
|
||||
|
||||
## 2.0.65
|
||||
|
||||
- Added ability to switch models while writing a prompt using alt+p (linux, windows), option+p (macos).
|
||||
|
||||
163
examples/hooks/fix_file_permissions_example.py
Executable file
163
examples/hooks/fix_file_permissions_example.py
Executable file
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Claude Code Hook: Fix File Permissions After Write
|
||||
===================================================
|
||||
This hook runs as a PostToolUse hook for the Write and Edit tools.
|
||||
It fixes file permissions to respect the system's umask setting.
|
||||
|
||||
This addresses the issue where Claude Code's Write tool creates files with
|
||||
restrictive 0600 permissions, ignoring the user's umask setting.
|
||||
|
||||
Read more about hooks here: https://docs.anthropic.com/en/docs/claude-code/hooks
|
||||
|
||||
Configuration example for ~/.claude/settings.json or .claude/settings.local.json:
|
||||
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 /path/to/claude-code/examples/hooks/fix_file_permissions_example.py"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
How it works:
|
||||
- After Write or Edit tool completes, this hook runs
|
||||
- Gets the file path from the tool input
|
||||
- Calculates the correct permissions based on the current umask
|
||||
- Applies the umask-respecting permissions to the file
|
||||
|
||||
For example:
|
||||
- With umask 022: files become 0644 (rw-r--r--)
|
||||
- With umask 002: files become 0664 (rw-rw-r--)
|
||||
- With umask 077: files remain 0600 (rw-------)
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import stat
|
||||
import sys
|
||||
|
||||
|
||||
def get_umask() -> int:
|
||||
"""Get the current umask value.
|
||||
|
||||
We temporarily set umask to get the current value, then restore it.
|
||||
This is the standard way to read umask in Python.
|
||||
"""
|
||||
current_umask = os.umask(0)
|
||||
os.umask(current_umask)
|
||||
return current_umask
|
||||
|
||||
|
||||
def calculate_file_permissions(umask_value: int) -> int:
|
||||
"""Calculate file permissions based on umask.
|
||||
|
||||
Standard Unix behavior: new files start with 0666 base permissions,
|
||||
then umask is applied to remove bits.
|
||||
|
||||
Args:
|
||||
umask_value: The current umask value (e.g., 0o022)
|
||||
|
||||
Returns:
|
||||
The file permissions after applying umask (e.g., 0o644)
|
||||
"""
|
||||
base_permissions = 0o666 # rw-rw-rw-
|
||||
return base_permissions & ~umask_value
|
||||
|
||||
|
||||
def fix_file_permissions(file_path: str) -> dict:
|
||||
"""Fix permissions for a file to respect umask.
|
||||
|
||||
Args:
|
||||
file_path: Path to the file to fix
|
||||
|
||||
Returns:
|
||||
Dict with status information
|
||||
"""
|
||||
if not file_path:
|
||||
return {"status": "skipped", "reason": "no file path provided"}
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
return {"status": "skipped", "reason": "file does not exist"}
|
||||
|
||||
if not os.path.isfile(file_path):
|
||||
return {"status": "skipped", "reason": "path is not a file"}
|
||||
|
||||
try:
|
||||
# Get current permissions
|
||||
current_mode = stat.S_IMODE(os.stat(file_path).st_mode)
|
||||
|
||||
# Calculate expected permissions based on umask
|
||||
umask_value = get_umask()
|
||||
expected_mode = calculate_file_permissions(umask_value)
|
||||
|
||||
# Only change if current permissions are more restrictive than expected
|
||||
# This handles the case where Write tool sets 0600 instead of umask-based perms
|
||||
if current_mode == 0o600 and expected_mode != 0o600:
|
||||
os.chmod(file_path, expected_mode)
|
||||
return {
|
||||
"status": "fixed",
|
||||
"file": file_path,
|
||||
"old_mode": oct(current_mode),
|
||||
"new_mode": oct(expected_mode),
|
||||
"umask": oct(umask_value),
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"status": "unchanged",
|
||||
"file": file_path,
|
||||
"current_mode": oct(current_mode),
|
||||
"expected_mode": oct(expected_mode),
|
||||
}
|
||||
|
||||
except PermissionError as e:
|
||||
return {"status": "error", "reason": f"permission denied: {e}"}
|
||||
except OSError as e:
|
||||
return {"status": "error", "reason": f"OS error: {e}"}
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point for the PostToolUse hook."""
|
||||
try:
|
||||
input_data = json.load(sys.stdin)
|
||||
except json.JSONDecodeError as e:
|
||||
# Exit 0 - don't block on invalid input, just log to stderr
|
||||
print(f"Warning: Invalid JSON input: {e}", file=sys.stderr)
|
||||
sys.exit(0)
|
||||
|
||||
tool_name = input_data.get("tool_name", "")
|
||||
|
||||
# Only process Write and Edit tools
|
||||
if tool_name not in ("Write", "Edit"):
|
||||
sys.exit(0)
|
||||
|
||||
tool_input = input_data.get("tool_input", {})
|
||||
file_path = tool_input.get("file_path", "")
|
||||
|
||||
if not file_path:
|
||||
sys.exit(0)
|
||||
|
||||
result = fix_file_permissions(file_path)
|
||||
|
||||
# Output result as JSON for logging/debugging
|
||||
# This will appear in the transcript when running with --debug
|
||||
if result.get("status") == "fixed":
|
||||
output = {
|
||||
"systemMessage": f"Fixed file permissions for {file_path}: {result['old_mode']} -> {result['new_mode']} (umask: {result['umask']})"
|
||||
}
|
||||
print(json.dumps(output))
|
||||
|
||||
# Always exit 0 - this is a PostToolUse hook, we don't want to block
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
278
examples/hooks/test_fix_file_permissions.py
Executable file
278
examples/hooks/test_fix_file_permissions.py
Executable file
@@ -0,0 +1,278 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Tests for the fix_file_permissions_example.py hook.
|
||||
|
||||
Run these tests with:
|
||||
python3 examples/hooks/test_fix_file_permissions.py
|
||||
|
||||
Or with pytest:
|
||||
pytest examples/hooks/test_fix_file_permissions.py -v
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
# Path to the hook script
|
||||
HOOK_SCRIPT = Path(__file__).parent / "fix_file_permissions_example.py"
|
||||
|
||||
|
||||
class TestFixFilePermissionsHook(unittest.TestCase):
|
||||
"""Test cases for the file permissions fix hook."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test fixtures."""
|
||||
self.temp_dir = tempfile.mkdtemp()
|
||||
self.test_file = os.path.join(self.temp_dir, "test_file.txt")
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up test files."""
|
||||
if os.path.exists(self.test_file):
|
||||
os.remove(self.test_file)
|
||||
if os.path.exists(self.temp_dir):
|
||||
os.rmdir(self.temp_dir)
|
||||
|
||||
def run_hook(self, tool_name: str, file_path: str) -> subprocess.CompletedProcess:
|
||||
"""Run the hook script with given input."""
|
||||
input_data = {
|
||||
"tool_name": tool_name,
|
||||
"tool_input": {"file_path": file_path},
|
||||
"session_id": "test-session",
|
||||
"cwd": os.getcwd(),
|
||||
}
|
||||
|
||||
result = subprocess.run(
|
||||
[sys.executable, str(HOOK_SCRIPT)],
|
||||
input=json.dumps(input_data),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
return result
|
||||
|
||||
def create_file_with_permissions(self, path: str, mode: int) -> None:
|
||||
"""Create a test file with specific permissions."""
|
||||
with open(path, "w") as f:
|
||||
f.write("test content")
|
||||
os.chmod(path, mode)
|
||||
|
||||
def get_file_permissions(self, path: str) -> int:
|
||||
"""Get the permission bits of a file."""
|
||||
return stat.S_IMODE(os.stat(path).st_mode)
|
||||
|
||||
def test_fixes_restrictive_permissions_with_umask_022(self):
|
||||
"""Test that 0600 permissions are fixed to 0644 with umask 022."""
|
||||
# Save and set umask
|
||||
old_umask = os.umask(0o022)
|
||||
try:
|
||||
# Create file with restrictive permissions (simulating Write tool bug)
|
||||
self.create_file_with_permissions(self.test_file, 0o600)
|
||||
self.assertEqual(self.get_file_permissions(self.test_file), 0o600)
|
||||
|
||||
# Run the hook
|
||||
result = self.run_hook("Write", self.test_file)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
|
||||
# Check permissions were fixed
|
||||
expected_mode = 0o644 # 0666 & ~0022
|
||||
self.assertEqual(
|
||||
self.get_file_permissions(self.test_file),
|
||||
expected_mode,
|
||||
f"Expected {oct(expected_mode)}, got {oct(self.get_file_permissions(self.test_file))}",
|
||||
)
|
||||
finally:
|
||||
os.umask(old_umask)
|
||||
|
||||
def test_fixes_restrictive_permissions_with_umask_002(self):
|
||||
"""Test that 0600 permissions are fixed to 0664 with umask 002."""
|
||||
# Save and set umask
|
||||
old_umask = os.umask(0o002)
|
||||
try:
|
||||
# Create file with restrictive permissions
|
||||
self.create_file_with_permissions(self.test_file, 0o600)
|
||||
self.assertEqual(self.get_file_permissions(self.test_file), 0o600)
|
||||
|
||||
# Run the hook
|
||||
result = self.run_hook("Write", self.test_file)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
|
||||
# Check permissions were fixed
|
||||
expected_mode = 0o664 # 0666 & ~0002
|
||||
self.assertEqual(
|
||||
self.get_file_permissions(self.test_file),
|
||||
expected_mode,
|
||||
f"Expected {oct(expected_mode)}, got {oct(self.get_file_permissions(self.test_file))}",
|
||||
)
|
||||
finally:
|
||||
os.umask(old_umask)
|
||||
|
||||
def test_preserves_permissions_matching_umask(self):
|
||||
"""Test that permissions already matching umask are not changed."""
|
||||
old_umask = os.umask(0o022)
|
||||
try:
|
||||
# Create file with correct permissions already
|
||||
self.create_file_with_permissions(self.test_file, 0o644)
|
||||
|
||||
# Run the hook
|
||||
result = self.run_hook("Write", self.test_file)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
|
||||
# Permissions should be unchanged
|
||||
self.assertEqual(self.get_file_permissions(self.test_file), 0o644)
|
||||
finally:
|
||||
os.umask(old_umask)
|
||||
|
||||
def test_respects_umask_077(self):
|
||||
"""Test that umask 077 results in 0600 (no change needed)."""
|
||||
old_umask = os.umask(0o077)
|
||||
try:
|
||||
# Create file with 0600 permissions
|
||||
self.create_file_with_permissions(self.test_file, 0o600)
|
||||
|
||||
# Run the hook
|
||||
result = self.run_hook("Write", self.test_file)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
|
||||
# With umask 077, 0600 is correct - should remain unchanged
|
||||
self.assertEqual(self.get_file_permissions(self.test_file), 0o600)
|
||||
finally:
|
||||
os.umask(old_umask)
|
||||
|
||||
def test_handles_edit_tool(self):
|
||||
"""Test that the hook also works for the Edit tool."""
|
||||
old_umask = os.umask(0o022)
|
||||
try:
|
||||
self.create_file_with_permissions(self.test_file, 0o600)
|
||||
|
||||
result = self.run_hook("Edit", self.test_file)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
|
||||
self.assertEqual(self.get_file_permissions(self.test_file), 0o644)
|
||||
finally:
|
||||
os.umask(old_umask)
|
||||
|
||||
def test_ignores_other_tools(self):
|
||||
"""Test that the hook ignores non-Write/Edit tools."""
|
||||
old_umask = os.umask(0o022)
|
||||
try:
|
||||
self.create_file_with_permissions(self.test_file, 0o600)
|
||||
|
||||
result = self.run_hook("Read", self.test_file)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
|
||||
# Permissions should be unchanged for Read tool
|
||||
self.assertEqual(self.get_file_permissions(self.test_file), 0o600)
|
||||
finally:
|
||||
os.umask(old_umask)
|
||||
|
||||
def test_handles_nonexistent_file(self):
|
||||
"""Test that the hook handles non-existent files gracefully."""
|
||||
result = self.run_hook("Write", "/nonexistent/path/file.txt")
|
||||
self.assertEqual(result.returncode, 0)
|
||||
|
||||
def test_handles_empty_file_path(self):
|
||||
"""Test that the hook handles empty file path gracefully."""
|
||||
input_data = {
|
||||
"tool_name": "Write",
|
||||
"tool_input": {},
|
||||
"session_id": "test-session",
|
||||
}
|
||||
|
||||
result = subprocess.run(
|
||||
[sys.executable, str(HOOK_SCRIPT)],
|
||||
input=json.dumps(input_data),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
|
||||
def test_handles_invalid_json(self):
|
||||
"""Test that the hook handles invalid JSON input gracefully."""
|
||||
result = subprocess.run(
|
||||
[sys.executable, str(HOOK_SCRIPT)],
|
||||
input="not valid json",
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
# Should exit 0 even with invalid input (don't block the workflow)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
self.assertIn("Invalid JSON", result.stderr)
|
||||
|
||||
def test_handles_directory_path(self):
|
||||
"""Test that the hook ignores directory paths."""
|
||||
result = self.run_hook("Write", self.temp_dir)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
|
||||
def test_outputs_system_message_on_fix(self):
|
||||
"""Test that the hook outputs a systemMessage when fixing permissions."""
|
||||
old_umask = os.umask(0o022)
|
||||
try:
|
||||
self.create_file_with_permissions(self.test_file, 0o600)
|
||||
|
||||
result = self.run_hook("Write", self.test_file)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
|
||||
# Check that stdout contains the systemMessage JSON
|
||||
if result.stdout.strip():
|
||||
output = json.loads(result.stdout)
|
||||
self.assertIn("systemMessage", output)
|
||||
self.assertIn("Fixed file permissions", output["systemMessage"])
|
||||
finally:
|
||||
os.umask(old_umask)
|
||||
|
||||
|
||||
class TestCalculateFilePermissions(unittest.TestCase):
|
||||
"""Test the calculate_file_permissions function directly."""
|
||||
|
||||
def test_umask_022(self):
|
||||
"""Test permission calculation with umask 022."""
|
||||
# Import the function from the hook script
|
||||
import importlib.util
|
||||
|
||||
spec = importlib.util.spec_from_file_location("hook", HOOK_SCRIPT)
|
||||
hook = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(hook)
|
||||
|
||||
result = hook.calculate_file_permissions(0o022)
|
||||
self.assertEqual(result, 0o644)
|
||||
|
||||
def test_umask_002(self):
|
||||
"""Test permission calculation with umask 002."""
|
||||
import importlib.util
|
||||
|
||||
spec = importlib.util.spec_from_file_location("hook", HOOK_SCRIPT)
|
||||
hook = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(hook)
|
||||
|
||||
result = hook.calculate_file_permissions(0o002)
|
||||
self.assertEqual(result, 0o664)
|
||||
|
||||
def test_umask_077(self):
|
||||
"""Test permission calculation with umask 077."""
|
||||
import importlib.util
|
||||
|
||||
spec = importlib.util.spec_from_file_location("hook", HOOK_SCRIPT)
|
||||
hook = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(hook)
|
||||
|
||||
result = hook.calculate_file_permissions(0o077)
|
||||
self.assertEqual(result, 0o600)
|
||||
|
||||
def test_umask_000(self):
|
||||
"""Test permission calculation with umask 000."""
|
||||
import importlib.util
|
||||
|
||||
spec = importlib.util.spec_from_file_location("hook", HOOK_SCRIPT)
|
||||
hook = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(hook)
|
||||
|
||||
result = hook.calculate_file_permissions(0o000)
|
||||
self.assertEqual(result, 0o666)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -22,23 +22,29 @@ Performs automated code review on a pull request using multiple specialized agen
|
||||
- **Agent #4**: Analyze git blame/history for context-based issues
|
||||
5. Scores each issue 0-100 for confidence level
|
||||
6. Filters out issues below 80 confidence threshold
|
||||
7. Posts review comment with high-confidence issues only
|
||||
7. Outputs review (to terminal by default, or as PR comment with `--comment` flag)
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
/code-review
|
||||
/code-review [--comment]
|
||||
```
|
||||
|
||||
**Options:**
|
||||
- `--comment`: Post the review as a comment on the pull request (default: outputs to terminal only)
|
||||
|
||||
**Example workflow:**
|
||||
```bash
|
||||
# On a PR branch, run:
|
||||
# On a PR branch, run locally (outputs to terminal):
|
||||
/code-review
|
||||
|
||||
# Post review as PR comment:
|
||||
/code-review --comment
|
||||
|
||||
# Claude will:
|
||||
# - Launch 4 review agents in parallel
|
||||
# - Score each issue for confidence
|
||||
# - Post comment with issues ≥80 confidence
|
||||
# - Skip posting if no high-confidence issues found
|
||||
# - Output issues ≥80 confidence (to terminal or PR depending on flag)
|
||||
# - Skip if no high-confidence issues found
|
||||
```
|
||||
|
||||
**Features:**
|
||||
@@ -114,17 +120,23 @@ This plugin is included in the Claude Code repository. The command is automatica
|
||||
### Standard PR review workflow:
|
||||
```bash
|
||||
# Create PR with changes
|
||||
# Run local review (outputs to terminal)
|
||||
/code-review
|
||||
|
||||
# Review the automated feedback
|
||||
# Make any necessary fixes
|
||||
|
||||
# Optionally post as PR comment
|
||||
/code-review --comment
|
||||
|
||||
# Merge when ready
|
||||
```
|
||||
|
||||
### As part of CI/CD:
|
||||
```bash
|
||||
# Trigger on PR creation or update
|
||||
# Automatically posts review comments
|
||||
# Use --comment flag to post review comments
|
||||
/code-review --comment
|
||||
# Skip if review already exists
|
||||
```
|
||||
|
||||
|
||||
@@ -52,7 +52,9 @@ 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.
|
||||
|
||||
7. Finally, comment on the pull request.
|
||||
7. Finally, output the review.
|
||||
- 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:
|
||||
a. Keep your output brief
|
||||
b. Avoid emojis
|
||||
@@ -93,11 +95,6 @@ Found 3 issues:
|
||||
|
||||
<link to file and line with full sha1 + line range for context>
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.ai/code)
|
||||
|
||||
|
||||
<sub>- If this code review was useful, please react with 👍. Otherwise, react with 👎.</sub>
|
||||
|
||||
---
|
||||
|
||||
- Or, if you found no issues:
|
||||
@@ -108,8 +105,6 @@ Found 3 issues:
|
||||
|
||||
No issues found. Checked for bugs and CLAUDE.md compliance.
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.ai/code)
|
||||
|
||||
---
|
||||
|
||||
- When linking to code, follow the following format precisely, otherwise the Markdown preview won't render correctly: https://github.com/anthropics/claude-code/blob/c21d3c10bc8e898b7ac1a2d745bdc9bc4e423afe/package.json#L10-L15
|
||||
|
||||
Reference in New Issue
Block a user