Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save thedavidyoungblood/4cbec2bebd174561bc4ac320e8b7212f to your computer and use it in GitHub Desktop.

Select an option

Save thedavidyoungblood/4cbec2bebd174561bc4ac320e8b7212f to your computer and use it in GitHub Desktop.
Claude-Code_Issue-no.30524_Issue-Comment_and_Local-Patch-Pack.md

Sharing a short write-up in case it is useful:

[!TLDR] explores using PreToolUse hook function(s) as interim mitigation for ISSUE: #3024 (and related).

LINK-TO-GIST

Note

It includes:

  • an expanded issue-commentary
  • a PR-description draft
  • a narrow local workaround sketch for rewriting redundant cwd-equivalent cd <path> && ... wrappers rather than broadly auto-approving them

The examples are intentionally incomplete and should be reviewed before use. They are meant as discussion material and local testing notes, not as authoritative guidance.

If any of it is helpful, feel free to ignore the parts that are not.



Claude Code Issue #30524 Issue-Comment and Loacal-Patch Pack

Note

This gist is a cleaned, publication-ready monofile for individual study, adaptation, or possible upstream submission.

Nothing here should be treated as authoritative maintainer guidance. The examples below are intentionally incomplete, include placeholders, and are not safe to paste blindly. Use at your own discretion, test in a disposable environment first, and do your own due diligence.

As of 2026-04-11, the public issue anthropics/claude-code#30524 is open and describes a Windows Git Bash bug where Claude Code may prepend redundant cd <path> && wrappers because equivalent cwd spellings are treated as different strings rather than one canonical location.


What This File Includes

  • An expanded issue-comment with a narrow local-workaround sketch.
  • A PR-description draft framed as a normalization fix, not a permissions relaxation.
  • A source list tied to the public issue, docs, and changelog.



Expanded Issue Comment

Use at your own discretion. This is not maintainer guidance, legal advice, or security advice. Review Anthropic's current docs, test in a disposable environment first, and do your own due diligence before applying any hook or permission change locally.

As of 2026-04-11, this still appears open, and the public report in #30524 points to a plausible Windows Git Bash cwd-normalization bug: equivalent path forms appear to be compared as strings rather than canonicalized before command construction and permission evaluation.

The issue body calls out these equivalent forms:

  • D:\source\my-repo
  • D:/source/my-repo
  • /d/source/my-repo

The symptoms described in the report are consistent with that diagnosis:

  • unnecessary cd <path> && ... wrapping even when the shell is already in the target directory
  • unnecessary approval prompts because the permission system sees a compound command instead of the underlying command

Two public docs seem especially relevant here:

The changelog also shows adjacent work in the same general area, but I did not find an entry that clearly says this exact Git Bash cwd-equivalence bug is already fixed:

  • 1.0.106: Windows path permission matching was normalized to POSIX form
  • 1.0.117: Windows PATH comparison was made case-insensitive for drive letters
  • 2.1.9: PreToolUse hooks gained additionalContext
  • 2.1.7: wildcard permission rules were hardened around compound shell operators
  • 2.1.76: the Bash permission dialog handling for pipes and compound commands was refined

If a user-side workaround is needed in the meantime, the safest shape seems narrower than "allow every cd ... && ... command":

  1. Match only a leading pattern like cd <path> && <rest>.
  2. Canonicalize both cwd and <path> to one internal Windows form.
  3. If they are not equivalent, do nothing.
  4. If they are equivalent, rewrite the Bash input to just <rest>.
  5. Only return allow if <rest> is already low-risk under the user's normal policy.
  6. Otherwise return ask, so the prompt shows the real command instead of the synthetic wrapper.
  7. On ambiguity, no-op or return ask.

That seems more aligned with the documented security model than broad auto-approval because it corrects the redundant wrapper first and leaves normal permission evaluation intact.

Illustrative example only, with intentionally broken placeholders:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"<ABSOLUTE_PATH_TO_YOUR_LOCAL_HOOK_SCRIPT>\""
          }
        ]
      }
    ]
  }
}
#!/usr/bin/env bash
# <ABSOLUTE_PATH_TO_YOUR_LOCAL_HOOK_SCRIPT>
# Example only. Replace placeholders. Review carefully before use.

set -euo pipefail

payload="$(cat)"
cwd="<EXTRACT_CWD_FROM_HOOK_JSON>"
command="<EXTRACT_COMMAND_FROM_HOOK_JSON>"

# Keep the parser intentionally narrow.
# If the command is more complex than a leading `cd <path> && <rest>`, bail out.
if ! printf '%s' "$command" | grep -qE '^[[:space:]]*cd[[:space:]]+[^&]+&&[[:space:]]+'; then
  exit 0
fi

target_path="<PARSE_TARGET_PATH_SAFELY>"
rest_command="<PARSE_REMAINING_COMMAND_SAFELY>"

normalize_windows_git_bash_path() {
  local raw="$1"
  # Replace this stub with your own canonicalization logic:
  # - map /d/foo -> d:/foo
  # - replace backslashes with forward slashes
  # - lowercase drive letter only
  # - collapse dot segments
  # - preserve path semantics
  printf '%s' "<NORMALIZED_PATH>"
}

cwd_norm="$(normalize_windows_git_bash_path "$cwd")"
target_norm="$(normalize_windows_git_bash_path "$target_path")"

if [ "$cwd_norm" != "$target_norm" ]; then
  exit 0
fi

cat <<'JSON'
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "ask",
    "permissionDecisionReason": "Removed redundant cwd wrapper; showing underlying command for review",
    "updatedInput": {
      "command": "<REST_COMMAND_WITHOUT_REDUNDANT_CD>"
    },
    "additionalContext": "A redundant cwd-equivalent cd wrapper was removed on Windows. Avoid re-introducing it."
  }
}
JSON

If maintainers agree that the root cause is cwd equivalence across D:\, D:/, and /d/, the upstream fix seems like it should happen before command construction and before permission classification:

  • canonicalize the current cwd and target cwd first
  • suppress redundant cd
  • evaluate permissions against the real command, not the synthetic wrapper
  • add a Windows Git Bash regression test that covers all three equivalent forms

If there is already a fix or a design constraint that rules this out, a pointer would be appreciated.



PR Description

Use at your own discretion. This draft is for review, adaptation, and local testing. It is not maintainer-approved guidance. Verify the current branch state, coding conventions, and test expectations before submitting anything upstream.

Suggested Title

fix(bash): normalize equivalent Windows Git Bash cwd forms before prepending cd

Summary

This change proposes a narrow Windows Git Bash normalization fix for issue #30524.

The bug report describes Claude Code prepending redundant cd <path> && ... wrappers even when the Bash subprocess is already in the target directory. The reported equivalent cwd forms are:

  • D:\source\my-repo
  • D:/source/my-repo
  • /d/source/my-repo

When those equivalent forms are treated as different strings, two user-visible problems follow:

  1. unnecessary command wrapping such as cd <equivalent-path> && git diff
  2. unnecessary permission prompts because compound-command handling evaluates the synthetic wrapper instead of the underlying command

Why This Seems Worth Fixing

Proposed Behavior

Before deciding whether to prepend cd <target> &&, normalize both:

  • the shell's current working directory
  • the target working directory Claude Code intends to use

If they resolve to the same canonical Windows path, do not prepend cd.

This normalization should happen before:

  • command construction
  • compound-command permission classification
  • rule matching that depends on the final command string

Non-Goals

  • changing general Bash permission policy
  • auto-approving compound commands
  • altering non-Windows path behavior
  • adding Git-Bash-specific behavior beyond cwd equivalence normalization

Sketch of the Fix

Illustrative pseudo-code only. Replace placeholders and names with the actual code paths in the repo.

function normalizeWindowsGitBashPath(input: string): string {
  const raw = input.trim()

  // Example transformations only:
  // - D:\repo   -> d:/repo
  // - D:/repo   -> d:/repo
  // - /d/repo   -> d:/repo
  // - collapse "." and ".."
  // - preserve path semantics after normalization

  return "<CANONICAL_WINDOWS_PATH>"
}

function maybeWrapWithCd(
  currentCwd: string,
  requestedCwd: string,
  command: string,
  platform: string,
  shellFlavor: string,
): string {
  if (platform !== "win32" || shellFlavor !== "git-bash") {
    return "<EXISTING_BEHAVIOR>"
  }

  const currentNorm = normalizeWindowsGitBashPath(currentCwd)
  const requestedNorm = normalizeWindowsGitBashPath(requestedCwd)

  if (currentNorm === requestedNorm) {
    return command
  }

  return `cd <SHELL_ESCAPED_REQUESTED_CWD> && ${command}`
}

Suggested Tests

Add or adapt a Windows Git Bash path-equivalence regression matrix. For example:

  1. cwd = D:\source\my-repo, target = D:/source/my-repo -> no cd
  2. cwd = D:\source\my-repo, target = /d/source/my-repo -> no cd
  3. cwd = /d/source/my-repo, target = D:\source\my-repo -> no cd
  4. cwd = D:\source\my-repo, target = D:\source\other-repo -> cd preserved
  5. permission classification sees git diff, not cd ... && git diff, when cwd-equivalent paths normalize to the same location

Illustrative test skeleton only:

describe("<WINDOWS_GIT_BASH_CWD_NORMALIZATION>", () => {
  test.each([
    ["D:\\source\\my-repo", "D:/source/my-repo", false],
    ["D:\\source\\my-repo", "/d/source/my-repo", false],
    ["/d/source/my-repo", "D:\\source\\my-repo", false],
    ["D:\\source\\my-repo", "D:\\source\\other-repo", true],
  ])("cwd=%s target=%s requiresCd=%s", (cwd, target, requiresCd) => {
    const actual = <BUILD_COMMAND_UNDER_TEST>({ cwd, target, command: "git diff" })
    expect(actual.includes("cd ")).toBe(requiresCd)
  })
})

Notes for Reviewers

  • This should be treated as a normalization fix, not a permissions relaxation.
  • The key invariant is that equivalent cwd spellings should converge before command generation and permission evaluation.
  • If there is already a shared Windows or Git Bash normalization helper in the codebase, this change should reuse that helper rather than introduce a second path-canonicalization path.

Manual Validation Notes

Illustrative checklist only. Replace placeholders with real values before submitting:

  • Environment:
    • Windows version: <YOUR_WINDOWS_VERSION>
    • Claude Code version under test: <YOUR_CLAUDE_CODE_VERSION>
    • Shell: <YOUR_GIT_BASH_VARIANT>
  • Repro before patch:
    • cwd: <FORM_A>
    • requested command: <UNDERLYING_COMMAND>
    • actual emitted command: <REDUNDANT_CD_FORM>
  • Result after patch:
    • actual emitted command: <UNDERLYING_COMMAND_ONLY>
    • permission prompt behavior: <DESCRIBE_ACTUAL_RESULT>


Sources





NOTICE:

This is just provided as conceptual research, documentation, for informational-purposes only, etc., and has not been fully battle tested or vetted, however would appreciate hearing and learning about any implementations, and shared learnings. (Unless otherwise explicitly stated by the author.)


@TheDavidYoungblood

🤝 Let's Connect!

LinkedIn // GitHub // Medium // Twitter/X



A bit about David Youngblood...


David is a Partner, Father, Student, and Teacher, embodying the essence of a true polyoptic polymath and problem solver. As a Generative AI Prompt Engineer, Language Programmer, Context-Architect, and Artist, David seamlessly integrates technology, creativity, and strategic thinking to co-create systems of enablement and allowance that enhance experiences for everyone.

As a serial autodidact, David thrives on continuous learning and intellectual growth, constantly expanding his knowledge across diverse fields. His multifaceted career spans technology, sales, and the creative arts, showcasing his adaptability and relentless pursuit of excellence. At LouminAI Labs, David leads research initiatives that bridge the gap between advanced AI technologies and practical, impactful applications.

David's philosophy is rooted in thoughtful introspection and practical advice, guiding individuals to navigate the complexities of the digital age with self-awareness and intentionality. He passionately advocates for filtering out digital noise to focus on meaningful relationships, personal growth, and principled living. His work reflects a deep commitment to balance, resilience, and continuous improvement, inspiring others to live purposefully and authentically.


Personal Insights

David believes in the power of collaboration and principled responsibility in leveraging AI for the greater good. He challenges the status quo, inspired by the spirit of the "crazy ones" who push humanity forward. His commitment to meritocracy, excellence, and intelligence drives his approach to both personal and professional endeavors.

"Here’s to the crazy ones, the misfits, the rebels, the troublemakers, the round pegs in the square holes… the ones who see things differently; they’re not fond of rules, and they have no respect for the status quo… They push the human race forward, and while some may see them as the crazy ones, we see genius, because the people who are crazy enough to think that they can change the world, are the ones who do." — Apple, 1997


My Self-Q&A: A Work in Progress

Why I Exist? To experience life in every way, at every moment. To "BE".

What I Love to Do While Existing? Co-creating here, in our collective, combined, and interoperably shared experience.

How Do I Choose to Experience My Existence? I choose to do what I love. I love to co-create systems of enablement and allowance that help enhance anyone's experience.

Who Do I Love Creating for and With? Everyone of YOU! I seek to observe and appreciate the creativity and experiences made by, for, and from each of us.

When & Where Does All of This Take Place? Everywhere, in every moment, of every day. It's a very fulfilling place to be... I'm learning to be better about observing it as it occurs.

A Bit More...

I've learned a few overarching principles that now govern most of my day-to-day decision-making when it comes to how I choose to invest my time and who I choose to share it with:

  • Work/Life/Sleep (Health) Balance: Family first; does your schedule agree?
  • Love What You Do, and Do What You Love: If you have what you hold, what are YOU holding on to?
  • Response Over Reaction: Take pause and choose how to respond from the center, rather than simply react from habit, instinct, or emotion.
  • Progress Over Perfection: One of the greatest inhibitors of growth.
  • Inspired by "7 Habits of Highly Effective People": Integrating Covey’s principles into daily life.

Final Thoughts

David is dedicated to fostering meaningful connections and intentional living, leveraging his diverse skill set to make a positive impact in the world. Whether through his technical expertise, creative artistry, or philosophical insights, he strives to empower others to live their best lives by focusing on what truly matters.

David Youngblood



/#END!

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