agentleFS
ericwood8ericwood8/skills/git-bash-editing/SKILL.md

git-bash-editing

Skill1 starsChanged 13 days agoMITView on GitHub

Use when writing a script or a file body from Git Bash (read this first; never put file contents in a heredoc, use the Write and Edit tools), editing source with sed, perl, python or heredocs, looping over sqlcmd output, or overwriting generated files that also hold hand edits. Trigger words - backslashes mangled, escape became a newline, unexpected EOF, CRLF pattern matches nothing, path rewritten, working directory reset, junction for a scratch copy.

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 3 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Never sed 's/\\d/.../' to fix a backslash: it matches every letter d.

    line 38
  2. Very specific:

    After a scripted edit of a string literal, grep -n the line.

    line 39
  3. Very specific:

    Verify regex edits by printing repr() of the text around a match before deciding the pattern is wrong.

    line 42
  4. Distinctive:

    Before overwriting files that may hold hand edits, confirm git status --short is clean.

    line 58
  5. Distinctive:

    Read this skill before scripting edits.

    line 63
  6. Distinctive:

    If a task is much bigger than its label ("small", "cheap"), say so and ask for the reduced or full version before starting.

    line 64

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Editing files from Git Bash on Windows

The rule

Do not carry a large file body or script in a Bash heredoc. Use Bash to run things. A small or medium heredoc (a short script or edit, up to about 40 lines) is fine when it holds no apostrophe, backslash, backtick or $ that must reach the file; larger bodies fail ("unexpected EOF", mangled escapes) and go through Write.

NeedDo this
Create or replace a file, or write a Python/JS scriptWrite tool (scripts to the scratchpad), then run python C:/.../file.py
Change one line or one short blockEdit tool, typing escapes exactly as they must appear in the file
The same replacement in many filesa script file made with Write: raw strings, assert text.count(old) == 1, read and write with newline=''
A short command with no ', \, backtick or $Bash is fine

A heredoc longer than about 40 lines, or one whose text needs an apostrophe, backslash, backtick or $ to survive, belongs in a file made with Write (the Edit tool for a short block). After every scripted edit, grep -n or sed -n the changed line before building; a script that "ran" proves nothing.

Shell rejections and rewrites

  • unexpected EOF while looking for matching ' rejects the whole command and nothing in it ran (check ls -la / git status before assuming a partial result). Cause: an apostrophe or quote inside a large heredoc, even with <<'EOF'. Fix: Write the file, then run it.
  • rm -f $TEMP/*.py (a variable in a wildcard path) is refused and the whole command line, including the commands before it, does not run. Clean up in its own call with literal paths, or leave scratch files.
  • A Windows path passed to a Windows program is rewritten. sqlcmd -i /c/x/y.sql fails with "Error occurred while opening ... C:" and the script silently did not run. A forward-slash path with a drive letter (-i C:/Users/me/y.sql) fails too: sqlcmd reads C: plus switches, /Users becomes -U, and the message is the misleading "The -E and the -U/-P options are mutually exclusive". A relative path or a backslash path works (see the mssql skill). Use the PowerShell tool with a backslash path, or "$(cygpath -w /c/x/y.sql)". An argument starting with / is also turned into a path: set MSYS_NO_PATHCONV=1. After DDL, query the catalog to confirm it took effect.
  • Python run from Git Bash cannot see /c/... either (FileNotFoundError): pass C:/... paths to python and to any Windows program. A multi-line edit script of more than a few lines goes in a file made with Write, even when it looks harmless (an apostrophe or a backslash inside a 90-line heredoc rejects the whole command).
  • Python run from Git Bash cannot see /tmp. Put scratch files in the session scratchpad with a C:/... path. A file that a Bash command already wrote to /tmp is reached with "$(cygpath -w /tmp/x.sql)" as an argument to python; a script that reads /tmp/x itself fails with FileNotFoundError before it changes anything (seen when appending a snippet to a SQL file).
  • The working directory resets between Bash calls: use absolute paths or cd in the same command. Environment variables do not persist either: export them in the command that starts the server.

Escapes: what reaches the file

  • Python/JS strings turn escapes into real characters. '\n', '\r\n', '\d', 'sql\functions' (a form feed), '8.0\bin' (a backspace) written into a file come out as a real line break, a lone letter or a control character. Symptoms: C# CS1010 Newline in constant, CS1009 Unrecognized escape sequence, a regex (\d{4}) arriving as (d{4}), a doc line printing sqlunctions. Python's SyntaxWarning: invalid escape sequence is the signal that the file content is now wrong.
    • Fixes in order: the Edit tool; a raw string r'...'; chr(92) for a backslash; in C# tests a verbatim string @"...\d{4}...".
    • In C# a test string "\'x\'" is just 'x': the backslash is an escape, not a character. A test to feed text that holds a backslash and a quote (MySQL's CHECK_CLAUSE shows _cp850\'open\') passed for the wrong reason until it was written @"\'open\'". Write the input as a verbatim string, and see the test fail once with the old behaviour before trusting it.
    • A Python replace written in a Bash heredoc (t.replace("_cp850\\'", ...)) and a sed with \\' both changed nothing or damaged the file (a stray quote was appended); after a backslash-and-quote edit, od -c the line, then redo it with a script made with Write that builds the backslash with chr(92).
    • Through the Bash tool a doubled \\n in a Python heredoc arrives as \n and is then read as a newline. Another reason not to use heredocs.
    • re.sub(pattern, "text with \n", s) interprets backslashes in the replacement: pass a function (lambda m: text).
    • Never sed 's/\\d/.../' to fix a backslash: it matches every letter d.
    • After a scripted edit of a string literal, grep -n the line; a quote followed by a line break means repair it with Edit. For a corrupted path, grep -c $'\x0c' and $'\x08' find form feeds and backspaces.
    • A JS template literal turns \` into a backtick and \\ into one backslash: write the content as it should appear, with no second layer.
  • perl -e, perl -pi -e, sed s/// lose backslashes ('\\' became '\', \. lost its dot). In perl, write a single quote as \x27 and a literal $ as \$; better, avoid perl and use Edit. sed -i replacement text containing | or & needs escaping: beyond one literal word, use Edit.
  • Verify regex edits by printing repr() of the text around a match before deciding the pattern is wrong.

CRLF, BOM and line endings

  • Most trees here are CRLF (core.autocrlf=true). A multi-line perl -0pi pattern with \n matches nothing and reports no error. Write \r?\n, emit \r\n, and check with git diff. The Edit tool also needs an exact match: on CRLF files edit single lines.
  • In a Python script: nl = '\r\n' if '\r\n' in s else '\n'; read and write with newline=''; keep a UTF-8 BOM (EF BB BF, utf-8-sig) if the file had one; assert s.count(old) == 1 before .replace. A file that mixes LF and CRLF: edit as bytes and match the line ending explicitly.
  • Compare generated (LF) output with a CRLF original: git diff -w --ignore-cr-at-eol --ignore-space-at-eol -U0 <files> | tr -d '\r' | grep '^[-+]'. The "LF will be replaced by CRLF" warnings are harmless.
  • The Edit and Write tools refuse a file not read in this conversation, or one changed since (by an IDE, a formatter, a sed pass): Read it again, then edit.

sqlcmd and loops

  • sqlcmd output ends each line with \r. for t in $(sqlcmd ... -h -1 -W -Q ...) then fails on every name but the last, and a grep error filter hides it. Pipe through tr -d '\r', and when a loop produces fewer results than items, rerun one iteration unfiltered.

Scratch copies and overwriting

  • Copy a Node project without reinstalling: tar --exclude=node_modules --exclude=.git --exclude=dist --exclude=.angular -cf - . | (cd DEST && tar xf -), then link node_modules with a junction made in PowerShell: New-Item -ItemType Junction -Path DEST\node_modules -Target SRC\node_modules (cmd //c mklink /J fails from Git Bash with "syntax incorrect").
  • Before overwriting files that may hold hand edits, confirm git status --short is clean. git checkout -- file undoes a generate but also discards earlier hand edits in the same file: generate and hand-fix different files in different passes, or diff first.
  • Program Files folders (such as the SQL Server Backup folder) may be unreadable and undeletable from the session: do not work around it with xp_cmdshell or bulk-delete procedures; tell the user the path.

Process

  • Read this skill before scripting edits; the rules were known and still skipped once.
  • If a task is much bigger than its label ("small", "cheap"), say so and ask for the reduced or full version before starting.
  • Real checks (an npm install and build per version, a database copy, a live API run) take minutes each: run them in one background job with a log file and a DONE marker, and read the log at the end.
  • A fix found by a live run also needs a unit test, or the next edit loses it.

Traps seen in sessions

The saved tools (edit_text.py and the others in C:\Github\tools) are listed in the global CLAUDE.md; check them before writing a scratch script.

  • A Windows Python does not understand Git Bash paths (/c/Github/x becomes C:\c\Github\x and "file not found"). Pass C:/Github/x; the saved tools convert /c/... themselves.
  • Run a long job with run_logged.py and run_in_background: true, not ( cmd > log; echo DONE ) &. The subshell form returns at once, so the completion notice arrives for the wrong thing; the harness already notifies when a background command exits. Use a new log name per run: after a rerun, notices (and Monitor events) of the earlier run still arrive and look like results. A foreground sleep and a chain of short sleeps are blocked; do not poll.
  • Do not make a "just in case" backup copy and delete it. The delete of a stray file in the drive root was refused by the safety check and nothing in the command ran, including the edit that followed it. Use git diff / git checkout for undo, and put scratch files in the scratchpad folder.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.