Skip to content

Instantly share code, notes, and snippets.

@anthonywu
Created July 14, 2026 00:53
Show Gist options
  • Select an option

  • Save anthonywu/4b434c5f40bc23bd08d9e7f4ff9c9a85 to your computer and use it in GitHub Desktop.

Select an option

Save anthonywu/4b434c5f40bc23bd08d9e7f4ff9c9a85 to your computer and use it in GitHub Desktop.
Claude Code wrong-session-guard: hook + skill to catch a prompt pasted into the wrong terminal tab / PR session

Claude Code: wrong-session-guard

Catch the common mistake of pasting a prompt meant for one terminal tab / Claude Code session into a different one. If you run multiple Claude Code sessions side-by-side — tab 1 on the foo PR, tab 2 on the bar PR — it's easy to paste tab 2's prompt into tab 1 and have it start editing the wrong branch. This stops that before any work happens.

Two layers, both user-scoped (nothing project-specific required):

File Role
session-context.sh Hook (UserPromptSubmit). Injects the current tab's git identity — repo, branch, PR, files the branch touches — into context on every prompt. Makes the mispaste impossible to miss.
wrong-session-guard.SKILL.md Skill. Structured compare + halt. When a prompt clearly concerns different work than the injected context, it stops and asks whether you pasted into the wrong tab.

The hook auto-detects your repo's default branch (main / master / dev), so no config.

Install

# 1) Skill
mkdir -p ~/.claude/skills/wrong-session-guard
curl -fsSL <this-gist>/wrong-session-guard.SKILL.md -o ~/.claude/skills/wrong-session-guard/SKILL.md

# 2) Hook
mkdir -p ~/.claude/hooks
curl -fsSL <this-gist>/session-context.sh -o ~/.claude/hooks/session-context.sh
chmod +x ~/.claude/hooks/session-context.sh

Then register the hook in ~/.claude/settings.json (merge into any existing UserPromptSubmit array — don't replace it):

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          { "type": "command", "command": "bash $HOME/.claude/hooks/session-context.sh" }
        ]
      }
    ]
  }
}

Restart Claude Code (hooks load at startup).

Notes

  • The script carries no secrets. Its output, however, includes your live branch names, PR titles, and changed file paths — fine for normal use, just remember that if you share raw session logs from a private repo.
  • Requires git; gh (GitHub CLI) is optional and only used to show the bound PR.
  • Calibrated to bias toward proceeding — it only halts on a clear cross-wire, so the happy path stays frictionless.

Built with Claude Code.

#!/bin/bash
# UserPromptSubmit hook for Claude Code: inject THIS session's git context so a prompt
# pasted into the WRONG terminal tab (a different PR/branch) is caught before any work.
#
# stdout from a UserPromptSubmit hook is added to the model's context. Pair with the
# wrong-session-guard skill (see README) which reads this and halts on a clear mismatch.
#
# Install: put this at ~/.claude/hooks/session-context.sh, chmod +x, and add to
# ~/.claude/settings.json (see README.md).
set -euo pipefail
# Claude passes a JSON payload on stdin; pull cwd from it, fall back to PWD.
payload="$(cat 2>/dev/null || true)"
cwd="$(printf '%s' "$payload" | sed -n 's/.*"cwd"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
if [ -n "$cwd" ]; then cd "$cwd" 2>/dev/null || true; fi
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || exit 0
branch="$(git branch --show-current 2>/dev/null)"
[ -z "$branch" ] && branch="(detached)"
root="$(basename "$(git rev-parse --show-toplevel 2>/dev/null)")"
# Detect the repo's default branch (main / master / dev / …) instead of hardcoding.
base="$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null || true)"
[ -z "$base" ] && for c in origin/main origin/master origin/dev; do
git rev-parse --verify --quiet "$c" >/dev/null 2>&1 && { base="$c"; break; }
done
# Files this branch actually touches vs the default branch; fall back to recent commits.
files=""
[ -n "$base" ] && files="$(git diff --name-only "${base}...HEAD" 2>/dev/null | head -20)"
[ -z "$files" ] && files="$(git diff --name-only HEAD~5...HEAD 2>/dev/null | head -20)"
pr="$(gh pr view --json number,title --jq '"#\(.number) \(.title)"' 2>/dev/null || true)"
echo "<session-context> (injected by session-context.sh hook — this is where the CURRENT tab is working)"
echo "repo: ${root}"
echo "branch: ${branch}"
[ -n "$pr" ] && echo "PR: ${pr}"
if [ -n "$files" ]; then
echo "branch touches:"
printf '%s\n' "$files" | sed 's/^/ - /'
fi
echo "GUARD: If the new prompt clearly concerns different work than the above (another PR/branch/subsystem),"
echo "it was likely pasted into the wrong tab — invoke the wrong-session-guard skill and HALT before doing work."
echo "</session-context>"
exit 0
name wrong-session-guard
description Guard against a prompt pasted into the WRONG terminal tab / Claude session. Run this FIRST, before doing any work, whenever a new task prompt references a specific PR, branch, ticket, feature, file, module, or component. Compares the prompt's subject against this session's actual git branch and recent work; if they clearly describe different work (e.g. prompt is about "bar PR" but this session is the "foo PR"), HALT and ask the user to confirm they pasted into the right tab instead of proceeding. Skip only for trivial/context-free prompts (greetings, "what does this do", questions about the current diff).
allowed-tools Bash, AskUserQuestion

wrong-session-guard

Catches the common mistake of pasting a prompt meant for one Claude session (tab 2 = "bar PR") into a different session (tab 1 = "foo PR"). Each tab is pinned to its own branch/worktree, so a mispaste means doing real work in the wrong context. Fail loud and early — before any edits.

When to run

Run as the first action on a new task prompt that names specific work: a PR, branch, ticket, feature area, file path, module, function, table, or component.

Do not run for context-free prompts: greetings, "continue", "what does this do?", "explain this diff", or follow-ups that clearly build on the current conversation.

Step 1 — establish THIS session's context (cheap, always)

git rev-parse --show-toplevel
git branch --show-current
git log --oneline -8
# default branch (main/master/dev), then the files THIS branch touches vs it:
base="$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null)"
git diff --name-only "${base}...HEAD" 2>/dev/null | head -40
gh pr view --json number,title,headRefName 2>/dev/null || true  # PR bound to this branch, if any

Also fold in the current conversation: which files/subsystems have we been editing this session?

Step 2 — extract the incoming prompt's subject

From the pasted prompt, identify what it is actually about:

  • explicit anchors: branch name, PR #, ticket ID, file paths, directory, package, table, component
  • topical anchors: the feature/subsystem in prose (e.g. "the abuse-strikes ledger", "the landing redirect")

Step 3 — compare and score the mismatch

Strong mismatch (HALT) — any of:

  • Prompt names a branch / PR# / ticket that ≠ this session's branch/PR.
  • Prompt's file paths or directories don't exist on this branch's diff and are a different subsystem than what this session has been working on.
  • Prompt's feature area is disjoint from both the branch's diff and the conversation so far.

Weak / ambiguous (WARN, then proceed):

  • Overlapping area but different files, or the prompt is generic enough to plausibly belong here.

Match (proceed silently):

  • Prompt anchors line up with this branch's diff, PR, or the ongoing conversation. Do not mention the guard at all — no friction on the happy path.

Bias toward proceeding when signals are weak; only HALT on a clear cross-wire. False halts are more annoying than a rare miss.

Step 4 — on a strong mismatch, HALT

Do not read/edit/run anything toward the task. Report the collision plainly, then use AskUserQuestion to force an explicit choice:

⚠️ This looks like it was meant for a different tab.

  • This session is on foo/branch (PR #123 — "foo feature").
  • Your prompt is about "bar feature" (mentions path/to/bar, PR #456).

Did you paste into the wrong window?

Options:

  1. Wrong tab — stop (recommended): do nothing; user will re-paste in the correct session.
  2. Right tab — proceed anyway: intentional cross-branch work; continue with the task.

Only start the actual work if the user picks "proceed anyway". Never silently guess through a strong mismatch.

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