cross-platform
Skill6 starsChanged 41 days agoMITView on GitHub
Use when code, tests, scripts or agents must work on both Windows and Linux (including WSL), when CI runs on an operating system the local gates do not, when a Windows-hosted agent edits files or runs shell commands, or when something passes on one OS and fails on the other. Covers running the targeted leg on both OSes in every local gate (CI's merge group runs the whole population), host-only witnesses (a filesystem CI lacks), one line-ending format (LF) enforced, path and build-path assumptions, shell and console encoding traps, and git across the Windows/WSL boundary (never export GIT_DIR to test processes). Not for platform-specific product features.
5 other projects use a version of this.
Adopted by
Most recently taken up by
- AxlZero21/Skillstheir own version, first seen Nov 8, 2026
- Kangentic/kangentictheir own version, first seen Nov 7, 2026
- Automattic/pocket-casts-iostheir own version, first seen Oct 8, 2026
- foxgeeek/adskillstheir own version, first seen Apr 24, 2026
- mylee04/code-notifytheir own version, first seen Feb 4, 2026
Other versions5 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 5
- Automattic/pocket-casts-ios★ 1.8ksame name
- mylee04/code-notify★ 288same name
- Kangentic/kangentic★ 140same name
- AxlZero21/Skills★ 1same name
- foxgeeek/adskills★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository14 other files it gives its agents.
- agent-fleetSkill
- architecture-auditSkill
- automating-agent-guardrailsSkill
- claude-cloud-sessionsSkill
- devlogSkill
- dotnet-engineeringSkill
- engineering-standardsSkill
- performance-diagnosisSkill
- reviewSkill
- roslyn-analysisSkill
- spec-compliance-auditSkill
- spec-oracleSkill
- test-gateSkill
- variant-analysisSkill
The file
We split this skill into the rules it gives an agent
2 rules. 0 are common, 2 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 5 edited versions we read keep these.
2
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 111
One normalization landing: add the rule, git add --renormalize ., commit, land it alone.
- Distinctive: line 120
Until a repository is normalized, edit a CRLF file as BYTES: read bytes, replace, write bytes, then check that the diff touches only the …
“Common” is measured: kept by at least 6 in 10 of the 5 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Cross-platform: Windows and Linux without surprises
A test that passes on one operating system proves nothing about the other. Paths, line endings, shells, console encodings, file locking and git configuration all differ, and each difference is invisible from the side you are on. Make the other side cheap to check for every change, and write code that never has to guess which side it's on.
Why: in one 24-hour stretch of a Windows-hosted, Linux-CI project, eight separate incidents came from these differences: a Windows path literal that was relative on Linux, build paths baked into binaries, git unable to read a worktree across the boundary, a line-ending setting visible to only one git, a git variable that let a test corrupt the shared repository, a text tool that silently rewrote a file's line endings, escapes mangled on their way into a shell, and a console that could not print a character. (Practice — not yet validated: the rules below each come from one incident.)
When to use
- CI runs on an OS your local gates don't (Linux CI with Windows development, or the reverse).
- A test, script or tool touches paths, processes, shells, files, git, environment variables or encodings.
- An agent on Windows edits files or composes shell commands.
- Something passes on one OS and fails on the other.
1. The targeted leg runs on both OSes; the whole population runs in CI
- Every local gate runs the TARGETED leg on both hosts the project supports: natively, then, under the same gate slot, the same targeted leg in a clone on the other OS (for a Windows host, a WSL clone), fail-fast native first. This holds for the implementer and for the landing (enqueue) step alike. Why: in one measured campaign (2026-10-10) 3 of 38 landed changes had reds only on Linux, all in the changes' OWN tests (a locale golden whose text differs by OS, a lock-race fix red 10 of 10 on Linux, a path-length test), and each was caught by the other-OS run before a CI round trip. A targeted leg there costs the clone and build (about 1–2 min) plus the leg. (Owner decision 2026-10-11; practice, not yet validated as a gate shape.)
- The WHOLE population runs in CI, on every OS, on the merge group — never as a local gate on either OS. Running CI's full legs locally (5–10 min for the other OS's legs in that campaign, much longer under load) is what goes; keep it only as the tool that REPRODUCES a CI red. Why: in the same campaign local whole-population runs were 41 % of the landing time, mostly red from the host's load, while CI ran the same population on 20 free runners in 13 min. (Validated 2026-10-11 (measurement); the redesign's effect is not yet measured.)
- Host-only witnesses run locally at every gate. Some tests reproduce only on the developer host, because its
FILESYSTEM differs from CI's runners: ReFS (a Windows Dev Drive) deletes differently from NTFS, and a race between
an open and a delete-pending file reproduced locally in 20 of 7,200 probes may never reproduce on a runner. Give
those test classes a trait naming the property (
Host=ReFS), put every test with it in the local targeted leg whatever the diff, derive the membership from the trait, never a list, and keep a drift test that the known witnesses carry it. List the filesystem in the local-versus-CI survey (1b). - Build and test a clone on the target OS. Clone the committed HEAD (
git clone --sharedborrows the object store read-only) onto the target's own filesystem, then build and test it there, the way CI does. Don't run binaries built on the other OS: anything that embeds build paths breaks (see 2). - Export nothing into the original tree. The gate's own reads pass their git settings inline (
git -c …). - Keep a drift test that holds the repro run's legs equal to the test projects the CI jobs run, and see it fail once on a planted gap.
Why the repro run is kept: a new test was green in every Windows gate and red in CI's Linux unit job, a ~30-minute
round trip and a dropped change; the local Linux legs reproduced exactly that one red in about 2.5 minutes.
agent-fleet/references/landing.md carries the fleet rule. (Practice — not yet validated.)
1b. CI's environment is a build input: pin it, declare it, reproduce it locally
The invariant, under a merge queue: a pull request the queue bounces is a defect fixed on its branch before it is enqueued again. CI's merge-group run is the whole-population regression net, so a red there in a test OUTSIDE the targeted scope is the net working. A red INSIDE the targeted scope is also a defect in the LOCAL process: find why the targeted gate did not see it and fix that in the same change (a missing leg, an unpinned tool, a setting CI has and the local run lacks, a filesystem difference), then sweep for the others like it. Keep a drift test that maps every CI job to a local leg or to a recorded reason it cannot run locally.
- Pin the runner image and keep the local environment the same release. A floating label (
ubuntu-latest) moves when the provider decides, so no local gate can match it. Pin the image (ubuntu-26.04) and keep the local distro on the same release (a WSL distro can be upgraded in place). The provider's own migration notice is the warning: read it. - A tool that reads text with the platform's default charset has a hidden input. A parser generator on the JVM read a
grammar as UTF-8 locally (Java 18+ defaults to UTF-8) and as Cp1252 on the Windows CI runner, so a set of Unicode
characters became repeated Latin characters: an error only in CI, invisible to every local gate. Declare the encoding in
the tool's invocation (
-encoding UTF-8) and use UTF-8 everywhere, rather than avoiding non-ASCII text. Reproduce the CI behaviour locally with the JVM option-Dfile.encoding=COMPAT, which makes the JVM use the native charset, and keep a drift test that the invocation passes the encoding. Write characters that do not display (controls, noncharacters) as Unicode escapes so a reader can see them. - Run every CI job that can run locally. A CI job with no local equivalent (here a guard job whose conformance loop ran only on CI) is the next CI-only red. Survey the differences once (runner image, SDK, JDK and shell patch versions, Debug versus Release, locale and time zone, compile caches, shard composition, jobs and audits with no local counterpart) and settle each as identical, reproduced locally, or irreducible with the reason recorded.
Why: two finished changes were dropped from landings in a day for failures that only CI could see (the charset, and the guard job), each costing a ~30-minute CI round trip. (Practice — not yet validated: two measured incidents; the pin and the survey are recent.)
2. Paths: never assume the host's shape
- Never feed a path literal from one OS to another OS's path API.
Path.GetFullPath(@"E:\repo\x")on Linux is a RELATIVE path under the current directory. A test that plants a path must plant the form that is real on the OS it runs on, so it proves the code on each OS rather than only on the author's. - Build paths are embedded.
[CallerFilePath], source-relative fixture lookups, debug symbols and some generators bake the BUILD machine's absolute paths into the binary. Binaries built on Windows and run on Linux resolveE:\…as relative. Measured: 363 false test failures. Build on the OS that runs the tests. - Case and separators. Linux file names are case-sensitive, and Windows accepts both separators. Compare paths with the platform's rules, and join them with the platform's API.
- Drive letters and backslashes in tests are the first thing to search for when a test fails only on Linux.
(Practice — not yet validated.)
3. One line-ending format, LF, enforced
Standardize on LF in the working tree on every OS, and enforce it. The measured shape of the problem in one
repository: the object database was already LF for 15,234 of 15,500 text files; only the WORKING TREE differed by OS,
under core.autocrlf=true, so a Windows gate and a Linux gate tested different bytes of the same commit, scripts died
on \r, a workflow script was refused as containing "control characters", and a single CRLF log needed a
byte-splicing insert tool. The owner's call (2026-10-11): "We should probably standardize on a single line-ending
format. CRLF vs others keeps biting us." (Practice — not yet validated: adopted 2026-10-11.)
.gitattributesfirst rule:* text=auto eol=lf. Name any file that must be CRLF explicitly, with its reason (*.bat text eol=crlf # cmd.exe needs CRLF). The attribute wins over every developer'score.autocrlf, so the setting no longer decides what a gate tests.- One normalization landing: add the rule,
git add --renormalize ., commit, land it alone. Documentgit config merge.renormalize truein the setup, so branches still open rebase across the normalization without conflicts. - Every tool and script that writes a tracked text file writes LF. On Windows, Python's
write_textemits CRLF: write bytes or passnewline="\n". PowerShell'sSet-Content/Out-Fileadd CRLF: use[IO.File]::WriteAllTextwith\njoins. A test fixture written in text mode on Windows is CRLF too. - A drift check, run by every gate and by CI, fails on a CR in any tracked text file (outside the files named CRLF):
git ls-files --eolshows the index and working-tree form of each file, or scangit grep -lI $'\r'. See it fail once on a planted CR. - Until a repository is normalized, edit a CRLF file as BYTES: read bytes, replace, write bytes, then check that
the diff touches only the intended lines. Line-oriented text tools can normalize every ending. Measured: a one-line
sededit to a CRLF log turned its whole top section into LF, a 493-line diff for a 2-line change. core.autocrlflives where the other git can't see it. Git for Windows sets it in its SYSTEM config, so Linux git on the same tree (through WSL) reports every CRLF-checked-out file as modified. Measured: 9,543 "changes" on a clean tree. Witheol=lfin.gitattributesthe difference disappears; before that, pass-c core.autocrlf=trueinline when reading a Windows checkout from Linux.- BOMs. An encoding that adds a byte-order mark (Python's
utf-8-sigwhen writing) changes the file's first bytes, and a parser or a diff sees them.
(Practice — not yet validated.)
4. Shells, commands and consoles
- Write per-OS commands explicitly; never translate one OS's command string into another's. A "cross-platform"
helper that replaced
>nulwith>/dev/nullleft the cmd-onlyexit /b 7untouched, and on Linuxshreturned exit code 2, not 7. A substitution covers only the tokens you thought of. - Don't send escape-heavy scripts through heredocs or nested quoting. Tool and shell layers each get a chance to rewrite backslashes. Write the script to a file with a file-writing tool and run the file.
- Console encoding. A Windows console's default code page (cp1252) cannot print many characters, and a script
that prints them crashes, not the code under test. Set
PYTHONIOENCODING=utf-8or reconfigure stdout to UTF-8 in the script. - Environment variables. Their names are case-insensitive on Windows and case-sensitive on Linux.
- Process semantics. Exit codes, signals and file locking differ: Windows locks an open file against deletion, and Linux does not. A test that depends on locking or ACLs is proven only on the OS it runs on — and, for deletes, only on the FILESYSTEM it runs on (ReFS versus NTFS; see the host-only witnesses in 1).
(Practice — not yet validated.)
5. Git across the Windows/WSL boundary
- A Windows worktree is not readable by Linux git as-is. Its
.gitis a file naming a Windows gitdir (gitdir: E:/repo/.git/worktrees/x), and a tree under/mnttrips git's ownership check (safe.directory). - ⛔ Never EXPORT
GIT_DIRorGIT_WORK_TREEinto processes that run tests. A test that creates its own scratch repository (git init, a commit,git worktree addin a temp directory) is silently redirected to the REAL repository.- Measured:
core.worktreewas written into the shared.git/config, and every git command in every checkout failed until a person removed it. An agent was (rightly) denied the permission to change shared config. - Pass git settings inline for your own reads, and run tests in a clone (1).
- Measured:
- Tests that create repositories must be hermetic. Drop every variable
git rev-parse --local-env-varslists before running git in a scratch repository. - A tripwire. A gate can snapshot the real repository's
HEADandcore.worktreebefore running and fail loudly if either changed.
(Practice — not yet validated.)
Checklist before pushing a change that touches paths, processes, files, shells or git
- The targeted leg ran on both OSes (native, then a clone built on the other OS) and is green, host-only witnesses included; the whole population is left to CI's merge-group run.
- CI's runner image is pinned and the local environment is the same release; tools that read text declare their encoding; every CI job that can run locally does.
- No path literal from one OS reaches another OS's path API; tests plant host-native paths.
- Nothing depends on build-machine paths, or the tests are built on the OS that runs them.
.gitattributesstarts with* text=auto eol=lf; every tool wrote LF; the CR drift check is green (a not-yet-normalized CRLF file was edited as bytes, and the diff touches only the intended lines).- Per-OS commands are written explicitly, not translated.
- No git variables are exported to child processes; scratch-repository tests scrub git's local variables.
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
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.

