Last active
December 29, 2025 12:55
-
-
Save cs50victor/279449337735c5fcd275c4d9d244cdf5 to your computer and use it in GitHub Desktop.
view, edit and and accept claude code diffs from your IDE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "$schema": "https://json.schemastore.org/claude-code-settings.json", | |
| "hooks": { | |
| "PostToolUse": [ | |
| { | |
| "matcher": "Write|Edit", | |
| "hooks": [ | |
| { | |
| "type": "command", | |
| "command": "<YOUR_HOME>/.claude/scripts/zed-diff-post.py" | |
| } | |
| ] | |
| } | |
| ], | |
| "PreToolUse": [ | |
| { | |
| "matcher": "Write|Edit", | |
| "hooks": [ | |
| { | |
| "type": "command", | |
| "command": "<YOUR_HOME>/.claude/scripts/zed-diff-pre.py", | |
| "timeout": 3600 | |
| } | |
| ] | |
| }, | |
| ] | |
| }, | |
| .... | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [ | |
| { | |
| "label": "Apply CC Diff", | |
| "command": "echo apply > /tmp/cc-diff-signal", | |
| "shell": { "with_arguments": { "program": "/bin/zsh", "args": ["--no-rcs"] } }, | |
| "hide": "on_success", | |
| "reveal": "never", | |
| "use_new_terminal": false, | |
| "allow_concurrent_runs": false | |
| }, | |
| { | |
| "label": "Reject CC Diff", | |
| "command": "echo reject > /tmp/cc-diff-signal", | |
| "shell": { "with_arguments": { "program": "/bin/zsh", "args": ["--no-rcs"] } }, | |
| "hide": "on_success", | |
| "reveal": "never", | |
| "use_new_terminal": false, | |
| "allow_concurrent_runs": false | |
| } | |
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| import json | |
| import sys | |
| from pathlib import Path | |
| LOCK_FILE = Path("/tmp/claude-zed-diff.lock") | |
| PROPOSED_FILE = Path("/tmp/cc-diff-proposed.txt") | |
| ORIGINAL_FILE = Path("/tmp/cc-diff-original.txt") | |
| def main(): | |
| input_data = json.load(sys.stdin) | |
| tool_name = input_data.get("tool_name", "") | |
| permission_mode = input_data.get("permission_mode", "default").lower() | |
| if permission_mode in ("bypasspermissions", "acceptedits"): | |
| sys.exit(0) | |
| if tool_name not in ("Write", "Edit"): | |
| sys.exit(0) | |
| result = {} | |
| if ORIGINAL_FILE.exists() and PROPOSED_FILE.exists(): | |
| original = ORIGINAL_FILE.read_text() | |
| proposed = PROPOSED_FILE.read_text() | |
| if original != proposed: | |
| result = { | |
| "hookSpecificOutput": { | |
| "hookEventName": "PostToolUse", | |
| "additionalContext": "User modified the proposed edit before applying. The final content differs from what you originally proposed." | |
| } | |
| } | |
| PROPOSED_FILE.unlink(missing_ok=True) | |
| ORIGINAL_FILE.unlink(missing_ok=True) | |
| LOCK_FILE.unlink(missing_ok=True) | |
| if result: | |
| print(json.dumps(result)) | |
| if __name__ == "__main__": | |
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| import json | |
| import sys | |
| import os | |
| import select | |
| import subprocess | |
| import fcntl | |
| from pathlib import Path | |
| LOCK_FILE = Path("/tmp/claude-zed-diff.lock") | |
| SIGNAL_FILE = Path("/tmp/cc-diff-signal") | |
| PROPOSED_FILE = Path("/tmp/cc-diff-proposed.txt") | |
| ORIGINAL_FILE = Path("/tmp/cc-diff-original.txt") | |
| def wait_for_signal(): | |
| """Wait for signal file to be written using kqueue (no polling).""" | |
| if not SIGNAL_FILE.exists(): | |
| SIGNAL_FILE.write_text("") | |
| fd = os.open(SIGNAL_FILE, os.O_RDONLY) | |
| kq = select.kqueue() | |
| event = select.kevent( | |
| fd, | |
| filter=select.KQ_FILTER_VNODE, | |
| flags=select.KQ_EV_ADD | select.KQ_EV_CLEAR, | |
| fflags=select.KQ_NOTE_WRITE | |
| ) | |
| kq.control([event], 0) | |
| kq.control(None, 1) | |
| os.close(fd) | |
| return SIGNAL_FILE.read_text().strip() | |
| LOG_FILE = Path("/tmp/zed-diff-pre.log") | |
| def log(msg): | |
| with open(LOG_FILE, "a") as f: | |
| f.write(f"{msg}\n") | |
| print(f"[zed-diff-pre] {msg}", file=sys.stderr) | |
| def main(): | |
| log("Starting") | |
| input_data = json.load(sys.stdin) | |
| tool_name = input_data.get("tool_name", "") | |
| log(f"tool_name={tool_name}") | |
| permission_mode = input_data.get("permission_mode", "default").lower() | |
| log(f"permission_mode={permission_mode}") | |
| if permission_mode in ("bypasspermissions", "acceptedits"): | |
| log("Exiting: autoaccept mode") | |
| sys.exit(0) | |
| if tool_name not in ("Write", "Edit"): | |
| log(f"Exiting: tool_name not Write/Edit") | |
| sys.exit(0) | |
| lock_fd = os.open(str(LOCK_FILE), os.O_RDWR | os.O_CREAT) | |
| log("Waiting for exclusive lock...") | |
| fcntl.flock(lock_fd, fcntl.LOCK_EX) | |
| log("Lock acquired") | |
| tool_input = input_data.get("tool_input", {}) | |
| file_path = Path(tool_input.get("file_path", "")) | |
| LOCK_FILE.write_text(str(file_path)) | |
| if tool_name == "Write": | |
| proposed_content = tool_input.get("content", "") | |
| else: | |
| old_string = tool_input.get("old_string", "") | |
| new_string = tool_input.get("new_string", "") | |
| if file_path.exists(): | |
| original = file_path.read_text() | |
| proposed_content = original.replace(old_string, new_string, 1) | |
| else: | |
| proposed_content = new_string | |
| PROPOSED_FILE.write_text(proposed_content) | |
| ORIGINAL_FILE.write_text(proposed_content) | |
| original_path = str(file_path) if file_path.exists() else "/dev/null" | |
| subprocess.Popen( | |
| ["zed", "-a", "--diff", original_path, str(PROPOSED_FILE)], | |
| stderr=subprocess.DEVNULL, | |
| stdout=subprocess.DEVNULL | |
| ) | |
| log("Waiting for signal (kqueue)...") | |
| action = wait_for_signal() | |
| log(f"Signal received: {action}") | |
| if action == "apply": | |
| modified_content = PROPOSED_FILE.read_text() | |
| if tool_name == "Write": | |
| updated_input = {"file_path": str(file_path), "content": modified_content} | |
| else: | |
| if file_path.exists(): | |
| original = file_path.read_text() | |
| if modified_content != ORIGINAL_FILE.read_text(): | |
| updated_input = { | |
| "file_path": str(file_path), | |
| "old_string": original, | |
| "new_string": modified_content | |
| } | |
| else: | |
| updated_input = { | |
| "file_path": str(file_path), | |
| "old_string": tool_input.get("old_string", ""), | |
| "new_string": tool_input.get("new_string", "") | |
| } | |
| else: | |
| updated_input = { | |
| "file_path": str(file_path), | |
| "old_string": "", | |
| "new_string": modified_content | |
| } | |
| result = { | |
| "hookSpecificOutput": { | |
| "hookEventName": "PreToolUse", | |
| "permissionDecision": "allow", | |
| "updatedInput": updated_input | |
| } | |
| } | |
| else: | |
| feedback = action[7:] if action.startswith("reject:") else "" | |
| reason = "User rejected the edit" | |
| if feedback: | |
| reason += f": {feedback}" | |
| result = { | |
| "hookSpecificOutput": { | |
| "hookEventName": "PreToolUse", | |
| "permissionDecision": "deny", | |
| "permissionDecisionReason": reason | |
| } | |
| } | |
| log(f"Returning result: {result}") | |
| print(json.dumps(result)) | |
| sys.exit(0) | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment