Skip to content

Instantly share code, notes, and snippets.

@peterkc
Forked from ljw1004/you_are_not_right.sh
Last active November 27, 2025 12:48
Show Gist options
  • Select an option

  • Save peterkc/1a0e8a54d241561a10137eef7164372e to your computer and use it in GitHub Desktop.

Select an option

Save peterkc/1a0e8a54d241561a10137eef7164372e to your computer and use it in GitHub Desktop.
A UserPromptSubmit hook for Claude Code to stop it saying "You're right"
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/you_are_not_right.sh"
}
]
}
]
}
}
#!/usr/bin/env bash
set -euo pipefail
trap 'echo "at line $LINENO, exit code $? from $BASH_COMMAND" >&2; exit 1' ERR
# This is a Claude Code hook to stop it saying "you are right".
#
# Installation:
# 1. Save this script and chmod +x it to make it executable.
# 2. Within Claude Code, /hooks / UserPromptSubmit > Add a new hook (this file)
#
# How it works:
# This script checks whether the assistant has recently told the user they are right.
# If so, it appends a system-reminder to the following user prompt,
# reminding the assistant not to do that, and giving it constructive
# examples of how it should respond to the user instead.
stdin=$(cat)
transcript_path=$(echo "$stdin" | jq -r ".transcript_path")
# We'll look through the last 5 items in the transcript.
# Sometimes the final item will be assistant thinking,
# and the previous one will be "you're right".
# We'll look for any triggering phrase like "You're right"
# or "you are absolutely correct".
items=$(grep '"role":"assistant"' "$transcript_path" | tail -n 5)
needs_reminder=false
while IFS= read -r item; do
[[ "$(jq -r '.type // empty' <<< "$item")" == "assistant" ]] || continue
[[ "$(jq -r '.message.content[0].type // empty' <<< "$item")" == "text" ]] || continue
text=$(jq -r '.message.content[0].text' <<< "$item")
[[ "${text:0:80}" =~ .*[Yy]ou.*(right|correct) ]] && needs_reminder=true
[[ "${text:0:80}" =~ .*[Aa]bsolutely ]] && needs_reminder=true
[[ "${text:0:80}" =~ .*사용자가.*맞다 ]] && needs_reminder=true # Korean
[[ "${text:0:80}" =~ .*맞습니다 ]] && needs_reminder=true # Korean
done <<< "$items"
[[ "$needs_reminder" == "true" ]] || exit 0
# upon exit code 0, Claude Code will append stdout to the context
# and proceed.
cat <<'EOF'
<system-reminder>
Avoid reflexive agreement phrases like "you are right" or "absolutely correct."
Instead, engage thoughtfully: analyze the user's reasoning, identify potential improvements,
or provide substantive confirmation when their approach is sound.
When the user presents a valid solution:
- Acknowledge the correctness with specific technical reasoning
- Consider edge cases, alternative approaches, or potential optimizations
- Build collaboratively rather than merely agreeing
When the user's approach has issues:
- Identify specific problems or gaps
- Suggest concrete improvements
- Explain the technical reasoning behind your analysis
<example>
user: It's failing on empty inputs, so we should add a null-check.
assistant: That addresses the immediate null case. For robustness,
checking for all falsy values (null, undefined, empty string) would
handle the broader input validation concern more comprehensively.
</example>
<example>
user: I'm concerned that we haven't handled connection failure.
assistant: Good catch - the connection attempt on line 42 lacks error
handling. If that fails, the catch block on line 49 won't trigger.
Moving the try-catch around the connection attempt would resolve this.
</example>
<example>
user: We should use async/await here instead of promises.
assistant: Async/await would improve readability here. The current promise
chain handles errors correctly and the logic is sound - converting to
async/await maintains the same error handling while making the code
more maintainable.
</example>
</system-reminder>
EOF
exit 0
@wodin
Copy link

wodin commented Nov 2, 2025

e.g., Claude gave me this. Name the file you_are_not_right.ps1 and see if it works:

Here's the PowerShell equivalent of that bash script:

#Requires -Version 5.1

# Set strict mode and stop on errors (equivalent to set -euo pipefail)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest

try {
    # This is a Claude Code hook to stop it saying "you are right".
    #
    # Installation:
    # 1. Save this script as a .ps1 file
    # 2. Within Claude Code, /hooks / UserPromptSubmit > Add a new hook (this file)
    #
    # How it works:
    # This script checks whether the assistant has recently told the user they are right.
    # If so, it appends a system-reminder to the following user prompt,
    # reminding the assistant not to do that, and giving it constructive
    # examples of how it should respond to the user instead.

    # Read stdin
    $stdin = [Console]::In.ReadToEnd()
    
    # Parse JSON and extract transcript_path
    $inputJson = $stdin | ConvertFrom-Json
    $transcriptPath = $inputJson.transcript_path

    # Read transcript file and get last 5 assistant messages
    $transcriptContent = Get-Content -Path $transcriptPath -Raw
    $allLines = $transcriptContent -split "`n"
    $assistantLines = $allLines | Where-Object { $_ -match '"role":"assistant"' } | Select-Object -Last 5

    # Check for triggering phrases
    $needsReminder = $false
    foreach ($line in $assistantLines) {
        $item = $line | ConvertFrom-Json
        
        # Skip if not the right type
        if ($item.type -ne "assistant") { continue }
        if ($item.message.content[0].type -ne "text") { continue }
        
        $text = $item.message.content[0].text
        $first80 = $text.Substring(0, [Math]::Min(80, $text.Length))
        
        # Check for triggering patterns
        if ($first80 -match '[Yy]ou.*(right|correct)') { $needsReminder = $true }
        if ($first80 -match '[Aa]bsolutely') { $needsReminder = $true }
        if ($first80 -match '사용자가.*맞다') { $needsReminder = $true }  # Korean
        if ($first80 -match '맞습니다') { $needsReminder = $true }  # Korean
    }

    # If no reminder needed, exit successfully
    if (-not $needsReminder) { exit 0 }

    # Output the system reminder
    @'
<system-reminder>
Avoid reflexive agreement phrases like "you are right" or "absolutely correct."

Instead, engage thoughtfully: analyze the user's reasoning, identify potential improvements, 
or provide substantive confirmation when their approach is sound.

When the user presents a valid solution:
- Acknowledge the correctness with specific technical reasoning
- Consider edge cases, alternative approaches, or potential optimizations
- Build collaboratively rather than merely agreeing

When the user's approach has issues:
- Identify specific problems or gaps
- Suggest concrete improvements
- Explain the technical reasoning behind your analysis

<example>
user: It's failing on empty inputs, so we should add a null-check.
assistant: That addresses the immediate null case. For robustness, 
checking for all falsy values (null, undefined, empty string) would 
handle the broader input validation concern more comprehensively.
</example>

<example>
user: I'm concerned that we haven't handled connection failure.
assistant: Good catch - the connection attempt on line 42 lacks error 
handling. If that fails, the catch block on line 49 won't trigger. 
Moving the try-catch around the connection attempt would resolve this.
</example>

<example>
user: We should use async/await here instead of promises.
assistant: Async/await would improve readability here. The current promise 
chain handles errors correctly and the logic is sound - converting to 
async/await maintains the same error handling while making the code 
more maintainable.
</example>
</system-reminder>
'@

    exit 0
}
catch {
    Write-Error "Error at line $($_.InvocationInfo.ScriptLineNumber): $_"
    exit 1
}

Key changes from bash to PowerShell:

  1. Error handling: Replaced set -euo pipefail and trap with $ErrorActionPreference = 'Stop', Set-StrictMode, and a try-catch block
  2. stdin reading: Changed $(cat) to [Console]::In.ReadToEnd()
  3. JSON parsing: Replaced jq with PowerShell's built-in ConvertFrom-Json
  4. File reading: Used Get-Content instead of grep and tail
  5. Regex matching: Changed bash's [[ =~ ]] to PowerShell's -match operator
  6. Here-doc: Replaced cat <<'EOF' with PowerShell's @'...'@ here-string syntax

The script maintains the same logic and functionality as the original bash version.

@SpeedRanger
Copy link

I was able to figure out hooks on my Windows machine yesterday and today I saw this comment.
Thanks @wodin for the time to share the code and explain in detail!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment