agentleFS
FoxsterDevFoxsterDev/xuunity-mcp/skills/cross_platform_python/SKILL.md

cross-platform-python

Skill3 starsChanged 4 months agoMITView on GitHub

Rules for Python host code (templates/*.py, root launchers, tests) so every change runs identically on Windows, Ubuntu, and macOS the first time — host detection, path flavor, subprocess discipline, UTF-8, process replacement, and platform-portable test expectations.

The file

We split this skill into the rules it gives an agent

5 rules. About 0 are common, 1 is distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

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

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

    Never branch on sys.platform == "darwin" as an implicit "POSIX else Windows" split.

    line 16
  2. Very specific:

    Every helper spawn (tasklist, taskkill, PowerShell, ps, lsof, wslpath, git, open, refresh helpers) must pass:

    line 27
  3. Very specific:

    Call server_core.reconfigure_stdio_utf8() first in every Python entrypoint.

    line 38
  4. Very specific:

    Use server_core.write_json (temp + os.replace) for anything the editor or another process polls.

    line 48
  5. Distinctive:

    Never compare full path strings (cross-platform-shell skill rule 9).

    line 61

≈ “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

Cross-Platform Python Guidelines

The Python host runs on macOS daily and on Windows/Linux only when a colleague or CI executes it. Every rule below was earned from a real Windows failure that macOS could not reproduce (2026-07 deep review: docs/archive/reports/2026-07-10_windows_platform_deep_review.md). Load this skill before writing or editing any Python in templates/, the root *.py launchers, or tests.


1. Host Detection Goes Through server_core

  • server_core.is_windows_like_host() for user-facing flavor decisions (rendered commands, launcher names, quoting). It is env-based and covers native cmd/PowerShell, MSYS/Git Bash, and Cygwin — os.name alone does not.
  • server_host_platform.host_platform_kind() for adapter routing (process listing, liveness).
  • Never branch on sys.platform == "darwin" as an implicit "POSIX else Windows" split; Linux must land in the POSIX branch deliberately.

2. Path Flavor Is Part of the Contract

  • Shell-facing strings: server_core.quoted_shell_path() / render_launcher_cli() — native form + quotes on Windows-like hosts, as_posix() elsewhere. Never embed bare str(path) in a command template (see cross-platform-shell skill rule 8).
  • The launcher token is the exception: launcher_command_prefix() always renders the absolute launcher path with forward slashes, because bash treats a command word as a path only when it contains /, while cmd accepts it quoted. Route every rendered command (and the bridge-enable recipe via bridge_enable_recovery_command()) through it; never format a launcher-less verb.
  • Preserve PurePath flavor in helpers: wrapping an incoming PureWindowsPath in Path(...) on a POSIX host silently rewrites separators.
  • Durable values read later by native Windows tools must be host-native; values read by Git Bash must be POSIX (cross-platform-shell skill rule 7).

3. Subprocess Discipline (enforced by AST sweep)

Every helper spawn (tasklist, taskkill, PowerShell, ps, lsof, wslpath, git, open, refresh helpers) must pass:

  • timeout= — a hung probe otherwise blocks the MCP server forever with zero diagnostics;
  • explicit subprocess.TimeoutExpired handling — it is not an OSError; an except OSError guard silently lets the timeout escape and crash the caller (this bug shipped in the PowerShell process-listing path);
  • encoding="utf-8", errors="replace" — never locale/ANSI decode (cp1251/cp866 hosts corrupt output);
  • **server_core.hidden_window_subprocess_kwargs() when the spawn can run on a Windows host — GUI-hosted servers must not flash console windows.

The only legitimate no-timeout spawns are children that ARE the workload (delegated server run, batch self-invocations). tests/test_subprocess_timeout_contract.py sweeps every subprocess.run call via AST and holds the explicit allowlist — extend the allowlist consciously; never drop timeout= silently.

4. UTF-8 End to End

  • Call server_core.reconfigure_stdio_utf8() first in every Python entrypoint; Windows pipes default to the ANSI codepage and a Cyrillic project path kills stdio mid-decode otherwise.
  • Launchers default PYTHONUTF8=1; keep protocol JSON ensure_ascii=True.
  • File reads accept BOM/UTF-16 where the writer may be PowerShell (server_core.read_json).

5. os.execv Is POSIX-Only Behavior

On Windows os.execv spawns a new process and kills the parent — an MCP client watching the parent sees its server die. On os.name == "nt" use subprocess.run and propagate the exit code (exec_python_script, refresh exec_run are the reference shape).

6. Files Other Processes Poll Are Published Atomically

Use server_core.write_json (temp + os.replace) for anything the editor or another process polls. Never ad-hoc open(...).write for polled files. Full co-design rules: atomic-ipc-files skill.

7. POSIX-Only Tools Need a Windows Answer

lsof, ps, open have no Windows presence. Any feature built on them needs a Windows counterpart (tasklist, CIM listing, Hub secondaryInstallPath.json discovery) or a documented safe degradation — silent [] on Windows turns a safety check into a no-op.

8. Platform-Portable Test Expectations

Windows CI failures from this repo's history were mostly test-pinning bugs, not product bugs. When writing tests:

  • Pin the flavor when asserting rendered commands: mock.patch.object(server_core, "is_windows_like_host", return_value=False) — otherwise the Windows leg correctly renders .cmd + native paths and the assert breaks.
  • Derive path expectations from the platform: expect str(Path("/x/y")), not a hard-coded "/x/y".
  • Case-insensitive usage asserts: the wrapper prints Usage:, argparse prints usage: — compare on .lower().
  • Never compare full path strings (cross-platform-shell skill rule 9).
  • Patch through the facade, call through the facade: server_editor_host re-syncs owner modules per call; patches applied via the facade leak into owner modules until the next facade call, so direct owner-module calls in later tests see stale mocks (tests/test_subprocess_timeout_contract.py TaskkillContractTest documents the shape).
  • New cross-module name in a star-import module: verify it resolves in the defining module (hasattr probe) AND add a test that executes the new call path — a latent NameError on an untested branch passed a 340-test suite here once (render_launcher_cli in the lifecycle module).

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.