cross-platform-project-build-arch
Skill2 starsChanged 4 months agoMITView on GitHub
Design or migrate Nix-required cross-platform builds, canonical executable implementations, target-separated outputs and application bundles. Use for nix build integration, CANONICAL_IMPL, build canonize, implementation/platform scope flags, PF/VARIANT layouts and wrong-platform binaries. Not a mandate to restructure a project during unrelated work.
In this repository27 other files it gives its agents.
- capture-collaboration-evidenceSkill
- clarify-before-buildingSkill
- deep-code-reviewSkill
- dispatchSkill
- erect-agent-stackSkill
- fix-zig-deps-hashSkill
- gather-project-intentionsSkill
- handoffSkill
- i18nSkill
- lean4-developmentSkill
- llvm-guided-optimizationSkill
- mechatron-ciSkill
- memoriesSkill
- mficSkill
- no-ai-slopSkill
- onboardSkill
- performance-profilingSkill
- planning-workSkill
- scaffold-zig-projectSkill
- shipSkill
- test-isolationSkill
- universal-app-frontendSkill
- walking-decisionsSkill
- writing-bendSkill
- writing-nixSkill
- writing-rocSkill
- zig-microbenchmarksSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
16 rules. About 0 are common, 7 are distinctive, and 9 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
9
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 8
Use this convention when introducing or deliberately migrating a project's build/output layout.
- Very specific: line 27
Use ARCH, not CA, which is ambiguous with Certificate Authority.
- Distinctive: line 29
Use PF in project-controlled platform identifiers, artifact namespaces, build output directories and PATH-facing directories.
- Distinctive: line 33
Do not mechanically rename third-party identifiers or compiler-owned caches.
- Very specific: line 37
Every CLI's one-line --about output includes its description, version and canonical platform as PF=<OS>-<ARCH>.
- Very specific: line 54
When migrating a CLI, test its actual --about output for exact PF, optional VARIANT and one-line output.
- Very specific: line 77
Only the current platform's directory and generic bin/ belong in automatic project PATH discovery.
- Very specific: line 92
Keep compiled products out of generic bin/.
- Distinctive: line 136
Keep generated products and publication symlinks out of Git, using narrow ignore rules that preserve tracked portable scripts and …
- Distinctive: line 138
Use relative links for local products.
- Very specific: line 146
Treat a macOS .app directory as a complete product, retaining its executable, resources, Info.plist, helpers, frameworks, permissions, …
- Distinctive: line 151
Do not extract the inner executable as a substitute for the application.
- Very specific: line 171
Keep language build graphs (build.zig, Cargo, CMake, etc.) as implementation details called by derivations.
- Very specific: line 212
Test graph dependencies need not invoke the literal ./build script or package every platform.
- Distinctive: line 240
If implementing this fallback, test shell command hashing, missing directories, broken symlinks, concurrent first invocations and build …
- Very specific: line 245
No source-freshness polling on every normal CLI invocation.
≈ “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.
Files
Cross-platform project build architecture
Use this convention when introducing or deliberately migrating a project's build/output layout. Preserve intentional cross-build products. Loading this skill does not authorize a fleet migration, global PATH edits, deletion, or replacement of an upstream project's established build interface.
Canonical Mecha platform names
The fleet naming contract (2026-10-23) is:
OS:linux,macos, ormswin(all five characters).ARCH:amd64(AMD and Intel x86-64) orarm64(AArch64).PF:<OS>-<ARCH>, for examplelinux-amd64ormswin-arm64.VARIANT:gnuormuslwhere applicable; otherwise unset and omitted from paths. PF and PLATFORM remain OS-ARCH. VARIANT belongs to the selected build target, not necessarily the machine running the build.
The supported matrix is macos-arm64, linux-amd64, linux-arm64,
mswin-amd64, and mswin-arm64. A syntactically valid token is not proof that
the project supports that target. macos-amd64 is outside the default matrix.
Use ARCH, not CA, which is ambiguous with Certificate Authority.
Use PF in project-controlled platform identifiers, artifact namespaces, build
output directories and PATH-facing directories. Translate explicitly at tool
boundaries: compiler triples such as x86_64-linux-musl, Rust targets and Nix
system names such as x86_64-linux keep the spellings their tools require.
Do not mechanically rename third-party identifiers or compiler-owned caches.
CLI self-identification
Every CLI's one-line --about output includes its description, version and
canonical platform as PF=<OS>-<ARCH>. Include VARIANT=gnu or VARIANT=musl
separately where applicable; omit VARIANT entirely otherwise. For example:
tool 1.2.3 — Inspect records; PF=linux-amd64 VARIANT=musl
tool 1.2.3 — Inspect records; PF=macos-arm64Compiled executables derive these fields from the actual compilation target, not the build host or runtime OS/ARCH/PF/PLATFORM/VARIANT environment variables. This stays true under emulation and cross-compilation. Interpreted tools report their execution platform with the same mappings; do not claim a compiled target for portable source. Compiler triples may be supplementary diagnostic data but never substitute for canonical PF. Preserve the one-line contract and existing localization; platform tokens are stable identifiers, not translated text.
When migrating a CLI, test its actual --about output for exact PF, optional
VARIANT and one-line output. Include a conflicting runtime environment case for
compiled binaries, mapping cases across declared targets, and actual executable
checks on available native/emulated targets. Label cross-build-only evidence as
such; metadata tests alone do not prove a foreign executable runs.
Select the host once, when constructing PATH
Expose project commands through:
bin/<PF>/<command> # native executable or generated symlink
bin/<command> # portable script or optional Nix bootstrap fallbackFor a given project, its host-specific directory precedes generic bin/.
Normalize Linux to linux, Darwin to macos, and native Windows/MSYS/MinGW/
Cygwin environments to mswin; normalize x86_64/amd64/AMD64 to amd64,
and aarch64/arm64/ARM64 to arm64. WSL uses Linux outputs. Detect the
execution environment, not the remote client or physical machine underneath it.
Reject unsupported native mappings explicitly rather than guessing a platform;
portable scripts may remain available.
Only the current platform's directory and generic bin/ belong in automatic
project PATH discovery. Never recursively add bin/ children. Do not
automatically admit project result/bin, zig-out/bin, release directories,
foreign platform directories, or caches. Preserve unrelated system/profile
paths, existing project precedence, and explicit development environments.
Shell setup must be idempotent, quote paths, and avoid expensive recursive
scans, Nix evaluation, compilation, or executable-header inspection.
The normal compiled-command path executes directly, with no added host-selector
wrapper process or per-invocation compatibility checks. Validate outputs during
build/publication instead. A copied Mac symlink can remain valid on Linux;
putting it beneath bin/macos-arm64/ keeps it outside Linux PATH selection.
This is an accidental-misexecution control, not a sandbox or a guarantee against
explicitly invoking a foreign file.
Keep compiled products out of generic bin/. A script is portable only if its
interpreter and dependencies are portable too; a copied Nix store shebang is
not automatically valid on another machine. Native Windows entrypoints must
work with the intended shell and executable extensions; do not require Unix
symlink privileges or Bash merely to run a compiled Windows command.
Separate the entrypoint from the complete build product
Namespace project-controlled outputs by PF and profile. Where ABI variants apply,
use VARIANT below PF: <implementation>-out/<PF>/[<VARIANT>/]<profile>/.
Brackets mean optional, not literal. Do not create empty, none or default
variant directories. Do not add VARIANT to automatic PATH discovery. Other
coexisting minimum-OS or CPU configurations need explicit, documented separation;
do not quietly overload the agreed gnu/musl vocabulary. Record the actual
compiler target and compatibility requirements in build metadata. For example:
bin/linux-amd64/tool -> ../../zig-out/linux-amd64/musl/ReleaseFast/bin/tool
zig-out/linux-amd64/musl/ReleaseFast/
bin/tool
lib/
include/
share/
zig-out/macos-arm64/ReleaseFast/
Applications/Example.app/
.nix-out/<PF>/<profile> -> /nix/store/...-package
.build-work/<PF>/<profile>/
dist/<version>/<PF>/These are installation trees, not just loose compiler outputs. Retain compiler
caches separately (.zig-cache/, Cargo's cache/output tree, etc.). Mixed-language
projects assemble one product tree from their native build graphs. Zig's
--prefix selects its installation destination. Nix packages expose the same
product structure under $out; .nix-out/ is a retained output link. Never
point a writable scratch prefix through a link into the immutable store.
The PATH-facing PF deliberately hides ABI and profile details.
Publication selects a compatible artifact and records what was selected.
OS/architecture alone cannot prove loader, libc, CPU-feature, minimum-OS, or
runtime-dependency compatibility. Do not publish -mcpu=native outputs as
universally portable within an architecture. Check actual headers and closure
requirements, not only directory names or producer-written metadata.
Keep generated products and publication symlinks out of Git, using narrow
ignore rules that preserve tracked portable scripts and intentional launchers.
Use relative links for local products. Nix links need retained output GC roots;
foreign store paths copied from another machine are not guaranteed to exist.
Building a cross target must not retarget another platform's entrypoint.
Publish only after success, preserve the previous working selection on failure,
and serialize competing publications. Do not delete unrecognized bin/ files.
Preserve application bundles
Treat a macOS .app directory as a complete product, retaining its executable,
resources, Info.plist, helpers, frameworks, permissions, internal links, and
signatures. Keep it under Applications/ in its target/profile product tree.
A macOS-specific command in bin/macos-arm64/ can launch the selected bundle
through open; a separate CLI can have a direct executable entrypoint.
Do not extract the inner executable as a substitute for the application.
GUI launchers are a platform-specific necessity, not a reason to wrap all CLIs.
Likewise retain Windows DLL/resource adjacency and Linux runtime resources.
Signing/notarization follows final bundle assembly; verify the distributed
product, not just an intermediate executable. Keep settings outside immutable
products. Release archives/installers belong in dist/, never on PATH.
Cross-compiling a binary does not prove that its bundle runs or is signed;
declare native builder/SDK/signing requirements and untested platforms honestly.
Require Nix builds with thin commands
Owner decision, 2026-10-23: nix build is the canonical build operation.
Nix is required for development, CI and release builds, not an optional backend.
flake.nix and its lock file select toolchains, dependencies and package/check
outputs. Top-level ./build selects those outputs, invokes nix build, then
verifies and publishes the resulting artifacts. Remove --backend=direct,
automatic non-Nix fallback and a parallel contributor build recipe during
migration. Missing Nix is an actionable error, never a reason to switch builders.
Keep language build graphs (build.zig, Cargo, CMake, etc.) as implementation
details called by derivations. Derivations never call a wrapper that recursively
invokes Nix. nix develop supplies tools for editing, debugging and running
prepared artifacts; compiling inside a devShell alone does not satisfy this
build contract. Targeted compiler diagnostics are experiments, not an alternate
supported build backend or release qualification. Use writing-nix for Nix code.
Expose compiled test prerequisites as Nix outputs too. ./test prepares them
once through Nix, then runs the complete suite with disposable state; it must
not rebuild through a direct backend. Nix checks may run tests inside derivations
without recursively calling the outer preparation wrapper. Host-dependent GUI,
hardware and fresh performance checks can execute the Nix-built artifacts outside
the sandbox, with explicit results and the existing isolation/resource controls.
Build host and target remain distinct. Windows artifacts are built through Nix on WSL or a suitable remote/cross builder; native Windows runtime tests remain required where specified. Declare required macOS builders and SDKs honestly. Credentialed signing/notarization may be a separate release step over a staged Nix-built product; it cannot mutate the store or quietly replace the build. Requiring Nix for builders does not require end users of distributed applications to install Nix. Preserve portable release products and their runtime checks.
| Command | Contract |
./build | Invoke nix build for the canonical implementation/current platform and publish compatible commands; optimized by default, explicit debug/test modes |
./build canonize IMPL | Validate and record CANONICAL_IMPL, print confirmation, exit without building or switching commands |
./build --all-impls / --all-implementations | Build every declared implementation for the current platform |
./build --all-plats / --all-platforms | Build the canonical implementation for every declared platform |
./build --all | Expand both implementation and platform scopes; equivalent to combining the two flags |
./run | Ensure the selected host build is current, then launch that exact CLI or bundle |
./test | Prepare exact prerequisites with Nix, then run all required suites; never test a stale PATH installation or publish into live project state |
./build-and-run | Optional alias to ./run; no independent build logic |
For multiple executable implementations or migration from build-all, read
canonical implementations. It owns
selection-file handling, namespaced outputs, migration steps and acceptance
tests. Single-implementation projects need no artificial selection machinery.
--all covers declared supported combinations, not an invented full Cartesian
product and not every conceivable ABI. Report failures and unavailable required
builders explicitly; never silently present a partial matrix as complete.
Test graph dependencies need not invoke the literal ./build script or package
every platform. Preserve project-required safety profiles; optimized does not
automatically mean removing runtime safety checks. Benchmarks identify their
profile explicitly.
For executable commands we name, separate words with hyphens (build-all,
build-and-run), never underscores (build_all, build_and_run). Project
directory names use underscores; executable names do not inherit that convention.
Preserve established upstream command names. When deliberately migrating a
legacy script, update its callers, tests, documentation and packaging together;
preserve compatibility only when the project's users require it. Do not rewrite
historical receipts to claim a new command name was used in an earlier run.
Reserve root build for the executable script. Put Xcode/CMake intermediate
directories under .build-work/; root Build/ conflicts with build on
case-insensitive filesystems. Avoid all case-only filename distinctions.
Existing Make targets can delegate to the same graph. make install with a
configurable prefix/DESTDIR is compatible with Nix; do not assume /usr/bin.
Optional Nix bootstrap
Automatic build/download on explicit command invocation is allowed when Nix
controls it. It is not required, and must not occur during shell startup.
An optional generic bin/tool may bootstrap a missing product, with the ready
native entrypoint taking precedence. Report useful progress/errors to stderr,
preserve arguments/stdin/signals/exit status, and execute the resolved output
path explicitly to avoid recursion. Do not fetch a shell installer instead.
If implementing this fallback, test shell command hashing, missing directories,
broken symlinks, concurrent first invocations and build failure. A shell may
continue using its cached fallback after publication; clear the relevant cache
or let the fallback directly reuse the completed product without reevaluating
Nix. State that tradeoff rather than claiming every warm invocation is direct.
No source-freshness polling on every normal CLI invocation; use ./build or
./run when development requires a fresh build.
Adoption and proof
Read verification-and-migration before implementing this layout, migrating existing products or PATH, or claiming conformance. Start with a CLI and a bundled GUI pilot before a fleet rollout. Keep the approved design separate from implementation/test status.
Primary references
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.

