Did your last agent commit survive a fresh Linux clone?
Mine often did not, and the chat never said why.
The laptop folded paths. The box did not.
I keep hearing the same claims in review threads.
They show up after a model edits a working tree.
They also show up when that tree hits a Linux server.
This is a myth-busting FAQ, not a tour.
You can run every check with git and a shell.
Skip any vendor if you already have Linux.
The claims I keep hearing
Developers repeat these like they were kernel facts:
- Git names are case-insensitive, so collisions cannot exist.
- A repo symlink is a real file on every host.
- The agent made the script executable, so CI will run it.
- If
lslooks clean on a Mac, the tree is unique. - A free remote box is just a slower laptop.
Which of those did you ship last month?
I will take them one by one.
Then you get a canary to run twice.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
I draft the canary with MonkeyCode's free model access.
I run the Linux half on MonkeyCode's free server option.
I still treat both reports as untrusted text.
Neither layer fixes core.ignorecase for you.
Myth 1: Git does not care about case
Claim
macOS and Windows fold case.
So a repo cannot hold Utils.js and utils.js.
The agent cannot create a collision. Right?
Evidence
Gather this in two minutes. Do not argue first.
git config --get core.ignorecase
uname -s
git ls-files | python3 -c '
import sys
from collections import defaultdict
buckets = defaultdict(list)
for line in sys.stdin:
path = line.rstrip("\n")
buckets[path.lower()].append(path)
for group in buckets.values():
if len(set(group)) > 1:
print("COLLISION", group)
'
On a default Mac, core.ignorecase is true.
Git will not shout when an agent adds utils.js.
The index may keep one path and hide the other.
Finder then shows a single file. You feel safe.
Corrected mental model
Git stores bytes. Your laptop folds some bytes.
Linux does not fold them. CI is usually Linux.
The agent wrote a second path. Your Mac displayed one.
After any agent session, run the collision script.
If it prints a group, do not merge yet.
Pick one spelling. Remove the other. Commit the rename.
# Label: example on a dirty tree, not a scored test.
git ls-files | grep -i utils.js
git mv -f utils.js Utils.js 2>/dev/null || true
git status --short
Did git record a rename, or only a working-tree mess?
git status is the answer. The chat log is not.
Myth 2: A symlink is just a shortcut
Claim
The agent linked config/current to config/dev.json.
Everyone can open it. We are fine.
Evidence
On APFS that link may look like a regular file.
On Linux it is a real symlink with a path string.
Broken targets fail only on the host that notices.
git ls-files -s | awk '$1 == "120000" {print}'
find . -type l -exec ls -l {} \;
find . -type l ! -exec test -e {} \; -print
The last command lists dangling links.
An agent loves dangling links.
It cannot feel a 404 on disk.
Corrected mental model
A git symlink is mode 120000 plus a target string.
It is not the contents of that target.
If the target is gitignored, Linux gets a hole.
Ask one question before you merge:
Does the target exist in a fresh clone?
If not, stop linking and commit a real file.
Myth 3: chmod in chat means +x in git
Claim
The model said it made scripts/canary.sh executable.
CI will run it. Why would git disagree?
Evidence
Did git record mode 100755?
Or did you only see a green phrase in the transcript?
git ls-files -s -- scripts/canary.sh
git diff --summary HEAD
stat -f '%A %N' scripts/canary.sh 2>/dev/null || stat -c '%a %n' scripts/canary.sh
On a Mac, core.filemode is often false.
Git ignores the executable bit you flipped locally.
A Linux clone then gets a non-executable file.
CI prints Permission denied. The chat printed success.
Corrected mental model
The transcript is not git update-index --chmod=+x.
If core.filemode is false, set the bit in the index.
git update-index --chmod=+x scripts/canary.sh
git ls-files -s -- scripts/canary.sh
You want 100755, not 100644.
Ask the agent to print that line.
Do not trust adjectives like "done" or "fixed".
Myth 4: ls on a Mac proves uniqueness
Claim
I listed the directory. Every name looks unique.
So the agent did not collide with Utils.js.
Evidence
ls on a case-insensitive volume is a fold.
It is not a proof. Two entries can share a display name.
Finder shows one. Linux readdir shows two.
git ls-files | wc -l
find . -iname 'utils.js'
python3 - <<'PY'
import os
for root, dirs, files in os.walk('.'):
if '.git' in dirs:
dirs.remove('.git')
names = dirs + files
folded = {}
for n in names:
folded.setdefault(n.lower(), []).append(n)
for key, group in folded.items():
if len(set(group)) > 1:
print(os.path.join(root, key), group)
PY
Corrected mental model
Uniqueness is a filesystem property, not an ls property.
Prove it on a case-sensitive volume.
That is what a throwaway Linux server is for.
Would you merge a tree you cannot list twice?
I would not. Not after an agent session.
Myth 5: A free Linux box is a slow laptop
Claim
Same repo. Same commands. Same results.
The remote box is only slower and poorer.
Evidence
No. The kernel is the test.
Case, filemode, symlink following, and path length change.
Your laptop is the special case.
Linux is the default for most CI.
I do not treat a free server as production.
I treat it as a second filesystem.
If the two canary reports disagree, the laptop lost.
The artifact: run this canary twice
Save this as scripts/repo-fs-canary.sh.
Run it on the laptop. Run it on Linux.
Diff the two reports. Do not eyeball them.
#!/usr/bin/env bash
# Label: local helper, not a published benchmark.
set -euo pipefail
echo "### host"
uname -a
git rev-parse --show-toplevel
git rev-parse HEAD
echo "ignorecase=$(git config --get core.ignorecase || echo unset)"
echo "filemode=$(git config --get core.filemode || echo unset)"
echo "symlinks=$(git config --get core.symlinks || echo unset)"
echo "### case collisions in the index"
git ls-files | python3 -c '
import sys
from collections import defaultdict
b = defaultdict(list)
for line in sys.stdin:
p = line.rstrip("\n")
b[p.lower()].append(p)
for g in b.values():
if len(set(g)) > 1:
print("COLLISION", g)
'
echo "### dangling symlinks"
git ls-files -s | awk '$1=="120000"{print $4}' | while read -r p; do
if [[ ! -e "$p" ]]; then
echo "DANGLING $p"
fi
done
echo "### shell scripts without +x in the index"
git ls-files -s | awk '/\.sh$/ && $1=="100644" {print $4}'
echo "### path length outliers"
git ls-files | awk 'length($0)>180 {print length($0), $0}'
Make it executable in the index, not only in your head.
chmod +x scripts/repo-fs-canary.sh
git update-index --chmod=+x scripts/repo-fs-canary.sh
bash scripts/repo-fs-canary.sh | tee /tmp/canary-laptop.txt
On the Linux side, clone a clean copy.
Do not rsync node_modules.
Do not copy APFS metadata.
git clone --no-local . /tmp/repo-linux-check
cd /tmp/repo-linux-check
bash scripts/repo-fs-canary.sh | tee /tmp/canary-linux.txt
diff -u /tmp/canary-laptop.txt /tmp/canary-linux.txt
If you lack a Linux laptop, use any throwaway Linux server.
That is the only reason a free server belongs in this workflow.
The model can draft the script. You still read the diff.
Decision table
| Symptom on Linux | Laptop lie | Fix in git, not in chat |
|---|---|---|
| Two files, one name on Mac | core.ignorecase=true |
Rename; keep one path |
Permission denied on .sh
|
core.filemode=false |
git update-index --chmod=+x |
| Missing config after clone | Symlink to an ignored target | Commit the target or stop linking |
| Agent "created" a file you had | Case fold in Finder | `git ls-files \ |
| Canary differs after clone | You copied local extra state | Fresh clone, no extra files |
Print the table in the pull request.
If a row fires, the model did not almost get it.
The filesystem rejected the tree.
What this does not prove
This canary does not prove tests pass.
It does not prove the model understood the patch.
It does not prove production matches Linux.
It also does not scan secrets.
Do not paste {% raw %}.env into a model prompt.
Do not leave credentials on a shared box.
APFS can be formatted case-sensitive.
Some USB disks are not.
Measure the host you actually run. Do not assume.
Windows has a third fold story.
This FAQ does not cover NTFS or WSL mounts.
If that is your world, add a third canary host.
Who should skip this workflow
Skip it if production is only macOS laptops.
Skip it if real CI already clones on Linux.
Skip it if you cannot read a twelve-line shell script.
A free model can draft the script.
It cannot own the rename.
You still pick Utils.js or utils.js.
Do not use a shared free server for private keys.
Do not use it as your only review.
Do not treat a green chat as git ls-files -s.
Closing
So which layer lied to you this week?
Was it Finder, core.ignorecase, or the transcript?
Run the canary on the laptop.
Run it again on a case-sensitive box.
If you already use MonkeyCode, the free server is one place for that second pass. Then read the diff yourself.
The agent can write files.
Only git and the kernel keep them.
Top comments (0)