claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

Git Commit Message Escaping Fails with Incorrect Quote Handling

Open mattgodbolt opened this issue 8 months ago • 7 comments

Bug Description Claude has issues committing git messages that require escaping. I've tried many times to explain how to do it but it always ends in pain. Seems like it doesn't want to escape properly, and/or uses the wrong quotes. Even when CLAUDE.md tells it to use HEREDOC-style that doesn't help.

Environment Info

  • Platform: linux
  • Terminal: gnome-terminal
  • Version: 0.2.108
  • Feedback ID: 92766efb-1a14-43b6-a0ee-1063b15429a5

Errors

[{"error":"Error: Language not supported while highlighting code, falling back to markdown: \n    at aQ (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:5909)\n    at file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:5645\n    at Array.map (<anonymous>)\n    at oh (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:5636)\n    at qJ6 (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:13025)\n    at C$ (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:104:19797)\n    at rE (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:42551)\n    at aE (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:38100)\n    at rN (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:38028)\n    at g$ (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:37882)","timestamp":"2025-05-13T14:09:48.508Z"},{"error":"Error: Language not supported while highlighting code, falling back to markdown: \n    at aQ (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:5909)\n    at file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:5645\n    at Array.map (<anonymous>)\n    at oh (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:5636)\n    at qJ6 (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:13025)\n    at C$ (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:104:19797)\n    at rE (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:42551)\n    at aE (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:38100)\n    at rN (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:38028)\n    at g$ (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:37882)","timestamp":"2025-05-13T14:09:48.510Z"},{"error":"Error: Language not supported while highlighting code, falling back to markdown: \n    at aQ (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:5909)\n    at file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:5645\n    at Array.map (<anonymous>)\n    at oh (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:5636)\n    at qJ6 (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:13025)\n    at C$ (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:104:19797)\n    at rE (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:42551)\n    at aE (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:38100)\n    at rN (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:38028)\n    at g$ (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:37882)","timestamp":"2025-05-13T14:09:48.511Z"},{"error":"Error: Language not supported while highlighting code, falling back to markdown: \n    at aQ (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:5909)\n    at file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:5645\n    at Array.map (<anonymous>)\n    at oh (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:5636)\n    at qJ6 (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:1865:13025)\n    at C$ (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:104:19797)\n    at rE (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:42551)\n    at aE (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:38100)\n    at rN (file:///opt/compiler-explorer-old/node/lib/node_modules/@anthropic-ai/claude-code/cli.js:106:38028)\n    at g$ (file:///opt/compiler-explorer-old/node/lib/node_modul

Note: Error logs were truncated.

I'm not quite sure what all these errors are ^^ nothing obvious in my logs.

But try as I might Claude keeps trying to commit messages using things like:

git commit -m"Message with `backticks` and $DOLLAR_SIGNS"

which leads to errors and sometimes truncated and broken commit messages.

mattgodbolt avatar May 13 '25 14:05 mattgodbolt

We have extensive prompting for this in the product. It is possible that your attempts to correct this behavior though the CLAUDE.md file are making the problem worse.

wolffiex avatar May 14 '25 14:05 wolffiex

Possibly: I added the changes only a week ago because it kept doing things, so only if you've fixed this prompting in the last few days?

c617461bd0 (Matt Godbolt 2025-05-07 12:32:11 -0500 26) - ALWAYS use HEREDOC syntax for complex shell commands, especially those containing quotes, newlines, or special characters:
c617461bd0 (Matt Godbolt 2025-05-07 12:32:11 -0500 27)   ```bash
c617461bd0 (Matt Godbolt 2025-05-07 12:32:11 -0500 28)   gh pr create --title "Title" --body "$(cat <<'EOF'
c617461bd0 (Matt Godbolt 2025-05-07 12:32:11 -0500 29)   PR body content with "quotes" and special chars like $variables
c617461bd0 (Matt Godbolt 2025-05-07 12:32:11 -0500 30)   that would otherwise need escaping
c617461bd0 (Matt Godbolt 2025-05-07 12:32:11 -0500 31)   EOF
c617461bd0 (Matt Godbolt 2025-05-07 12:32:11 -0500 32)   )"
c617461bd0 (Matt Godbolt 2025-05-07 12:32:11 -0500 33)   ```

mattgodbolt avatar May 14 '25 16:05 mattgodbolt

I just removed any reference to git in my CLAUDE.md and ran a fresh claude:

Image

mattgodbolt avatar May 14 '25 16:05 mattgodbolt

Submitted the above session as:

Feedback ID: 42f7e317-e46c-4bbe-85c9-8b8da035be83

mattgodbolt avatar May 14 '25 16:05 mattgodbolt

Another one:

Feedback ID: 3d204bdc-46df-40cd-9367-dc79fd3a2d8f

> This is all fantastic. Please commit what we've got here

● I'll create a commit with all the changes we've made:

● Call(Check git status and prepare for commit)…
  ⎿  Bash(git status)…
  ⎿  Bash(git diff)…
  ⎿  Bash(git log -1 --oneline)…
  ⎿  Done (3 tool uses · 0.2s)

● Bash(git add static/panes/explain-html-view.ts views/templates/panes/explain.pug)…
  ⎿  (No content)

● Bash(git add -u)…
  ⎿  (No content)

● Bash(git commit -m \"$(cat <<'EOF'                         …
      Improve Claude Explain UI

      - Add flexbox layout to ensure bottom bar is visible
      - Move loading indicator to top bar
      - Move token usage stats to bottom bar
      - Add padding to bottom bar
      - Remove the vestigial explain-view.ts
      - Replace with the HTML-based explain-html-view.ts

      🤖 Generated with [Claude Code](https://claude.ai/code)

      Co-Authored-By: Claude <[email protected]>
      EOF
      )\")
  ⎿  Error: error: pathspec 'Claude' did not match any file(s) known to git
     error: pathspec 'Explain' did not match any file(s) known to git
     error: pathspec 'UI' did not match any file(s) known to git
     error: pathspec '-' did not match any file(s) known to git
     error: pathspec 'Add' did not match any file(s) known to git
     error: pathspec 'flexbox' did not match any file(s) known to git
     error: pathspec 'layout' did not match any file(s) known to git
     error: pathspec 'to' did not match any file(s) known to git
     error: pathspec 'ensure' did not match any file(s) known to git
     error: pathspec 'bottom' did not match any file(s) known to git
     … +43 lines (ctrl+r to see all)
  ⎿  Interrupted by user

mattgodbolt avatar May 20 '25 19:05 mattgodbolt

Image

which caused the following bash errors:

● Bash(gh issue create --title "Inconsistent gamepad button mapping for button2 in VIA joystick handling" --body "## Issue Description…)…
  ⎿  https://github.com/mattgodbolt/jsbeeb/issues/503
     /bin/bash: line 44: button2: command not found
     /bin/bash: line 44: src/via.js: Permission denied
     /bin/bash: command substitution: line 45: syntax error: unexpected end of file
     /bin/bash: line 44: pad.buttons[10]: command not found
     /bin/bash: line 44: pad2.buttons[10]: command not found
     /bin/bash: line 44: pad.buttons[11]: command not found

Feedback ID: 19ad99a8-c88a-49a9-bb91-0fc599e8bee8

project: https://github.com/mattgodbolt/jsbeeb

mattgodbolt avatar Jun 03 '25 19:06 mattgodbolt

> Please reconsider the bug you filed. You did not escape bash properly and so please compare the issue you _actually_ filed against what you intended, and fix it up

● You're absolutely right! Let me check what the issue actually looks like and fix it:

● Bash(gh issue view 503)…
  ⎿  title:     Inconsistent gamepad button mapping for button2 in VIA joystick handling
     state:     OPEN
     author:    mattgodbolt
     labels:    bug, input
     … +50 lines (ctrl+r to expand)

● I can see the issue! The bash command interpreted backticks as command substitution, so all the backtick-quoted content like button2, src/via.js, SysVia.getJoysticks(), and pad.buttons[10] got stripped out. Let me edit the issue to
   fix this:

  Bash(gh issue edit 503 --body "## Issue Description…)…
  ⎿  Running…

╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Bash command                                                                                                                                                                                                                               │
│                                                                                                                                                                                                                                            │
│   gh issue edit 503 --body "## Issue Description                                                                                                                                                                                           │
│                                                                                                                                                                                                                                            │
│   There's an inconsistency in how \`button2\` is mapped for joystick fire buttons in the VIA gamepad handling code (around line 679 in \`src/via.js\`).                                                                                    │
│                                                                                                                                                                                                                                            │
│   ## Current Behavior                                                                                                                                                                                                                      │
│                                                                                                                                                                                                                                            │
│   In \`SysVia.getJoysticks()\`:                                                                                                                                                                                                            │
│   - **button1**: Always uses \`pad.buttons[10]\` (first gamepad, FIRE1)                                                                                                                                                                    │
│   - **button2**:                                                                                                                                                                                                                           │
│     - If 2 gamepads: Uses \`pad2.buttons[10]\` (second gamepad's FIRE1)                                                                                                                                                                    │
│     - If 1 gamepad: Uses \`pad.buttons[11]\` (first gamepad's FIRE2)                                                                                                                                                                       │
│                                                                                                                                                                                                                                            │
│   ## Code Location                                                                                                                                                                                                                         │
│   \`\`\`javascript                                                                                                                                                                                                                         │
│   // src/via.js line ~679                                                                                                                                                                                                                  │
│   button2 = button2 || (pad2 ? pad2.buttons[10].pressed : pad.buttons[11].pressed);                                                                                                                                                        │
│   \`\`\`                                                                                                                                                                                                                                   │
│                                                                                                                                                                                                                                            │
│   ## Expected Behavior (to be clarified)                                                                                                                                                                                                   │
│                                                                                                                                                                                                                                            │
│   The mapping should be consistent. Possible approaches:                                                                                                                                                                                   │
│   1. **Option A**: Always use button index 10 for both scenarios                                                                                                                                                                           │
│   2. **Option B**: Always use button index 11 for button2 in both scenarios                                                                                                                                                                │
│   3. **Option C**: Current behavior is intentional and should be documented                                                                                                                                                                │
│                                                                                                                                                                                                                                            │
│   ## Context                                                                                                                                                                                                                               │
│                                                                                                                                                                                                                                            │
│   From the gamepad mapping in \`gamepads.js\`:                                                                                                                                                                                             │
│   - Button 10 = FIRE1                                                                                                                                                                                                                      │
│   - Button 11 = FIRE2                                                                                                                                                                                                                      │
│                                                                                                                                                                                                                                            │
│   ## Impact                                                                                                                                                                                                                                │
│                                                                                                                                                                                                                                            │
│   This inconsistency may confuse users when switching between single and dual gamepad setups, as button2 maps to different physical buttons depending on the setup.                                                                        │
│                                                                                                                                                                                                                                            │
│   ## Next Steps                                                                                                                                                                                                                            │
│                                                                                                                                                                                                                                            │
│   - [ ] Clarify if current behavior is intentional                                                                                                                                                                                         │
│   - [ ] Add documentation explaining the mapping logic                                                                                                                                                                                     │
│   - [ ] Consider standardizing the mapping                                                                                                                                                                                                 │
│   - [ ] Add tests to verify intended behavior                                                                                                                                                                                              │
│                                                                                                                                                                                                                                            │
│   ---                                                                                                                                                                                                                                      │
│   **Note**: This is existing behavior, not introduced by recent changes."                                                                                                                                                                  │
│   Fix the issue description by properly escaping backticks                                                                                                                                                                                 │
│                                                                                                                                                                                                                                            │
│ Do you want to proceed?                                                                                                                                                                                                                    │
│ ❯ 1. Yes                                                                                                                                                                                                                                   │
│   2. Yes, and don't ask again for gh issue edit commands in /home/matthew/dev/jsbeeb                                                                                                                                                       │
│   3. No, and tell Claude what to do differently (esc)                                                                                                                                                                                      │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

got there in the end

mattgodbolt avatar Jun 03 '25 19:06 mattgodbolt

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

github-actions[bot] avatar Oct 10 '25 10:10 github-actions[bot]

Hi - closing as the most recent models should be much better at escaping bash properly!

catherinewu avatar Nov 29 '25 23:11 catherinewu