Make the port explain itself.
MLX Porter guides an agent or engineer through the evidence chain around a model port. It supplies routing, runbooks, static inspectors, validators, benchmark contracts, and publication gates. It does not contain a magic arbitrary-model converter.
Quick start
Run static inspection first. It reads local metadata and safe tensor headers, classifies the architecture, emits risk blockers, and recommends one or more runbooks. It does not execute project code.
python3 mlx-model-porting/scripts/inspect_model.py /path/to/model \
--output inspection.json \
--markdown inspection.md
python3 mlx-model-porting/scripts/make_port_plan.py inspection.json \
--artifact-root /path/to/model \
--output PORT_PLAN.md
inspection.json contains controlled family ids, architecture traits, routing status, risks, blockers, tensor metadata, source-format observations, and recommended runbooks. Ambiguity stays explicit.
For an existing MLX codebase, inspect that surface separately:
python3 mlx-model-porting/scripts/inspect_mlx_project.py /path/to/project \
--model /path/to/local/model \
--output mlx-inspection.json \
--markdown MLX_INSPECTION.md
Installation
Client presets select a documented destination and copy or symlink mode. Always dry-run first when the target matters; --force atomically replaces an existing target.
python3 mlx-model-porting/scripts/install_skill.py \
--client codex \
--dry-run
# Inspect the printed source, destination, target, and mode.
# Then repeat without --dry-run.
Preset clients
Claude Code, Codex, Cursor, Gemini CLI, Windsurf, and GitHub Copilot.
Explicit destination
Use --dest ~/.agents/skills --mode symlink when a product version or local convention differs.
The installer rejects recursive destinations, ancestor targets that contain the source, path escapes, and symlink cycles. It compares content and modes for idempotence.
The workflow contract
The order is a correctness device. A profiler cannot rescue a mismapped checkpoint, and a throughput number cannot replace task quality.
The repository validates the method and evidence around a conversion. The agent or engineer writes the eager MLX implementation and deterministic mapping for the target architecture.
Architecture routes
The registry declares 17 routes. Each has a golden scenario for routing, source-key coverage, seeded parity-bug detection, and optimization policy. That is not evidence of 17 completed real-checkpoint ports.
See the generated architecture registry. Interactive route cards require the local generated data file.
Qwen3-Next, Falcon-H1, Nemotron-H, Whisper, Qwen2-Audio, Moshi, RNN-T, Voxtral Realtime, and Gemma 3 vision-style compositions are routed through capability-aware profiles. Conflicting or weak signals remain ambiguous.
Static inspection
The inspector recognizes local directories, individual files, and Hugging Face ids. Network access is off by default. Local intake hashes every inventoried file into a portable SHA-256 tree identity and binds accepted license evidence to that same tree. Incomplete identity or missing evidence blocks recommendations. When network access is enabled, pin a revision; weight downloads are a separate opt-in.
python3 mlx-model-porting/scripts/inspect_model.py org/model \
--allow-network \
--revision 0123456789abcdef0123456789abcdef01234567 \
--output inspection.json
Safe metadata paths
Config JSON, tokenizer metadata, safetensors headers, bounded GGUF/ONNX/protobuf metadata, and preflighted archive tables.
Blocked confidence
Pickle weights, dynamic imports, custom model code, escaping symlinks, truncated inventories, missing license evidence, oversized structures, and conflicting identities.
ONNX, GGUF, Flax/Orbax, TensorFlow/Keras, and Core ML are intake and mapping surfaces here. Static recognition does not lower arbitrary graphs into executable MLX.
Build a source oracle
Freeze a small, representative fixture before porting. Record source revision, preprocessing, tokenizer or processor, seed, train/eval state, dtype, device, generation settings, and cache/state behavior.
- Capture embeddings or earliest feature transforms.
- Capture one block at the first non-trivial mask, routing, recurrence, or multimodal boundary.
- Capture final logits, waveform, image, embedding, forecast, or graph output.
- Capture mutable state: KV cache, convolution buffer, recurrent state, diffusion schedule, or streaming flush state.
- Define a task-quality metric before measuring speed.
A final-output mismatch tells you that something is wrong. A staged oracle tells you where semantics first diverged.
Validate the weight map
Author a mapping manifest that records each source key, target key, transform, expected shape, dtype decision, and reason for any intentionally unmapped value.
python3 mlx-model-porting/scripts/validate_weight_map.py \
--source source-manifest.json \
--target target-manifest.json \
--mapping WEIGHT_MAP.json \
--output weight-map-report.json
This validates key and shape-transform coverage. It does not prove operator semantics or numerical parity. --allow-unmapped weakens the default release gate.
Climb the parity ladder
python3 mlx-model-porting/scripts/compare_tensors.py \
source.npz target.npz \
--mapping mapping.json \
--atol 1e-5 --rtol 1e-4 --cosine-min 0.99 \
--output parity.json
| Level | Compare | Typical failure |
|---|---|---|
| Tensor | Shapes, dtypes, exact transforms | Transpose, split/merge, padding, layout |
| Block | Norm, attention/SSM, MLP/expert, residual | Axis, mask, router, recurrence, evaluation timing |
| Output | Logits, image latent, waveform, embedding | Head, denormalization, processor, decoder |
| State | Cache, buffer, recurrent state, streaming flush | Offset, window, mutation, boundary continuity |
| Task | Accuracy, WER/CER, perceptual or domain metric | Numerically close but behaviorally wrong |
--no-fail is report-only. --allow-empty must not be used as a release gate.
Optimization is a controlled experiment
The recommender matches controlled family, capability, workload, software, and hardware identifiers. Raw guidance numbers are scrubbed; the generated effective-claim catalog is the only numeric authority. It currently withholds all 9 numeric records. A future local promotion requires the full canonical TargetProfile.experiment_fingerprint, exact receipt-derived model, target, and workload descriptors, exact hardware and software, and a non-empty controlled workload set. A copied digest or generic profile cannot unlock a number.
python3 mlx-model-porting/scripts/recommend_optimizations.py inspection.json \
--target-profile target-profile.json \
--objective peak-memory \
--output recommendations.json \
--markdown OPTIMIZATIONS.md
| Advisor bucket | Meaning | Execution policy |
|---|---|---|
| Validated locally | A local parity fixture, benchmark, or skill gate reproduced the behavior in its captured scope. | Keep the exact model, inputs, target, and validation gate attached; do not generalize. |
| Validated by source or theory | Native MLX or official project path exists. | Confirm on the target; no portable speed promise. |
| Benchmark required | Prior MLX port evidence exists. | Profile and reproduce against the named baseline. |
| Experimental approach | Research candidate or incomplete MLX path. | Explicit user opt-in before implementation. |
| Rejected / do not use | Superseded, conflicting, regressing, or unsafe. | Cannot execute as a recommendation. |
Blocked intake holds candidates by default. --allow-blocked is a deliberate override, not a way to erase the blocker.
Benchmark receipts
A generic command benchmark can record bounded wall-time output and optional RSS. With --receipt-spec, the family-neutral external-command-wall-time adapter produces controlled observation evidence. Its exact argv template executes one digest-pinned Python runner at argv position 1 and binds models.target.id, models.target.revision, checked-in workload evidence, and semantic variant_config. The harness hashes the resolved interpreter and package metadata, sanitizes and binds the ambient environment, starts Python with -I -B, statically rejects symlink components, snapshots the quality contract before execution, and requires every measured run to recreate the declared output under quality/outputs/<label>/. Only parent-measured wall time counts; child stdout cannot attest performance.
A digest-pinned script can still ignore its model/workload arguments, and the legacy MLX-LM lane does not bind imported package bytes or per-run model output. The explicit execution_attested gate is therefore false for both lanes; receipts remain observations until a reviewed built-in adapter closes this boundary.
python3 mlx-model-porting/scripts/benchmark_command.py \
--warmup 1 --runs 5 --timeout 600 \
--output benchmark.json \
-- COMMAND ...
python3 mlx-model-porting/scripts/benchmark_command.py \
--receipt-spec bench/candidate-spec.json \
--quality-contract bench/quality-contract.json \
--baseline-receipt baseline.json \
--warmup 1 --runs 5 --timeout 600 \
--output bench/candidate.json
Family-neutral receipt spec
{
"schema_version": 1,
"label": "candidate",
"argv_template": [
{"literal": "python3"},
{"source": ["workload", "artifacts", 0, "path"]},
{"literal": "--model"},
{"source": ["models", "target", "id"]},
{"literal": "--revision"},
{"source": ["models", "target", "revision"]},
{"literal": "--input"},
{"source": ["workload", "artifacts", 1, "path"]},
{"literal": "--mode"},
{"source": ["variant_config", "mode"]},
{"literal": "--output"},
{"source": ["variant_config", "quality_output_path"]}
],
"models": {"target": {
"id": "owner/model", "revision": "<pinned 40-64 hex>",
"lineage_id": "controlled-lineage", "source_id": "owner/source-model",
"source_revision": "<pinned 40-64 hex>"
}},
"workload": {
"id": "controlled-workload",
"artifacts": [
{"role": "runner", "path": "runner.py", "sha256": "...", "size_bytes": 1234},
{"role": "input", "path": "input.bin", "sha256": "...", "size_bytes": 5678}
],
"parameters": {"shape": "fixed"}
},
"variant_config": {
"mode": "candidate",
"quality_output_path": "quality/outputs/candidate/result.txt"
},
"enabled_methods": ["method-id"],
"comparison_role": "candidate",
"rollback_condition": "Rollback on quality failure or a gain within noise."
}
Schema-2 candidate receipt shape (observation-only today)
python3 mlx-model-porting/scripts/benchmark_generation.py \
--label candidate \
--runs 5 --warmup 1 \
--target-model "$TARGET_MODEL" \
--target-revision "$TARGET_REVISION" \
--lineage-id "$LINEAGE_ID" \
--source-id "$SOURCE_MODEL" \
--source-revision "$SOURCE_REVISION" \
--workload-id deterministic-smoke-v1 \
--workload-artifact prompt=bench/prompt.txt \
--workload-params-json '{"max_tokens":128,"temperature":0.0,"seed":7}' \
--quality-contract bench/quality-contract.json \
--rollback-condition "Rollback on quality or throughput regression." \
--baseline-receipt bench/baseline.json \
--enabled-method native-low-bit-weight-quantization \
--output bench/candidate.json \
-- python3 -m mlx_lm generate \
--model "$TARGET_MODEL" --prompt "$PROMPT" \
--max-tokens 128 --temp 0.0 --seed 7
Current controlled quality contract
{
"schema_version": 2,
"validator": {"id": "mlx-benchmark-exact-output-parity", "version": 1},
"metric": "exact-output-parity",
"reference_artifact": {"path": "quality/reference.txt", "size_bytes": 123, "sha256": "..."},
"candidate_artifact": {"path": "quality/outputs/candidate/result.txt", "size_bytes": 123, "sha256": "..."}
}
The validator independently rereads two distinct, bounded, size- and digest-bound artifacts and compares their bytes. Schema-1 arbitrary JSON scores, legacy --quality-artifact, and Python --quality-evaluator inputs remain observations; they cannot authorize promotion. Lossy or task-specific candidates stay held until a controlled built-in metric exists.
Receipts can pool only when their exact baseline file and digest, warmup/run/timeout protocol, semantic experiment, and exact-output quality contract match. The lowest compatible ratio supplies any future range and its receipt-specific full fingerprint; missing, rejected, or heterogeneous repetitions withhold the number.
python3 mlx-model-porting/scripts/validate_benchmarks.py generate \
--root mlx-model-porting/assets/benchmarks
python3 mlx-model-porting/scripts/validate_benchmarks.py check \
--root mlx-model-porting/assets/benchmarks
Evidence states are separate axes
Review depth says how deeply a source has been read. Support scope says who maintains the implementation or whether it is paper-only. Benchmark classification says whether a local measurement can authorize a number. Do not collapse these into one “validated” badge.
| Axis | States | Safe public wording |
|---|---|---|
| Review depth | indexed, screened, synthesized | Catalogued; limitations reviewed; directly informed a rule/runbook. |
| Support scope | official_mlx, official_mlx_project, third_party_pinned, paper_only, context_only, local_reproduced | Apple framework; Apple project; pinned third-party prior art; research candidate; discovery context; captured local result. |
| Receipt class | Observation, promotion-ready, rejected | Historical measurement; all gates pass; negative or invalid evidence. |
11 total: 10 observations, 0 promotion-ready, and 1 rejected. No existing local number is presented here as a validated speedup.
Package validation
Run deterministic offline gates before any release. Live URL health and upstream pin drift are separate networked checks so a transient outage cannot corrupt prior evidence.
python3 mlx-model-porting/scripts/audit_skill.py --strict mlx-model-porting
python3 mlx-model-porting/scripts/validate_sources.py mlx-model-porting
python3 mlx-model-porting/scripts/validate_benchmarks.py check
python3 mlx-model-porting/scripts/generate_claim_catalog.py --check
python3 mlx-model-porting/scripts/generate_evidence_index.py --check
python3 mlx-model-porting/scripts/generate_site_data.py --check
python3 mlx-model-porting/scripts/manifest.py check
python3 -m unittest discover -s tests -v
Run validate_sources.py --check-urls only when network validation is intended. Missing or unhealthy URLs fail loudly without upgrading or rewriting evidence.
Registry-current primary sources
“Current” means the pinned registry snapshot reviewed on 2026-07-09, not an unverified claim about live upstream latest versions.
| Surface | Recorded immutable reference | Scope |
|---|---|---|
| Apple MLX | mlx-repo · 96296e9 ↗ | official_mlx |
| Apple MLX-LM | mlx-lm-repo · 2c008fd ↗ | Apple-maintained project; model/workload confirmation still required. |
| MLX source snapshot | Registered framework tree ↗ | Canonical mlx-repo snapshot; not a speed guarantee. |
| MLX-Audio | mlx-audio-repo · 412cf7c ↗ | third_party_pinned; not Apple-official. |
| MLX-VLM / vLLM-MLX | MLX-VLM 6a8cdff ↗ · vLLM-MLX batching source ↗ | Pinned third-party implementation evidence. |
The generated evidence index preserves every source id, URL, review depth, affected surface, and limitation.
Contribution flow
- Collect a candidate as review-only evidence. Daily automation may update candidates and open a PR; it cannot change supported guidance or merge itself.
- Pin the source and record review depth, classification, support scope, affected rule/runbook, limitations, and access date.
- Provide a reproducible MLX path, correctness or quality gate, benchmark metadata when performance is claimed, and rollback condition.
- Update the smallest concrete asset or runbook, regenerate derived artifacts, and add a test that fails if the requirement drifts.
- Keep rejected and superseded evidence visible. Never average contradictory sources into a vague compromise.
Limitations
Golden scenarios prove routing, guard behavior, source-key coverage, seeded parity failure, and recommendations; the broader tooling suite validates the weight-map command. Neither proves end-to-end conversion or parity for real checkpoints across every declared family.
- Forecasting coverage does not imply tabular, ranking, or recommender support.
- Current CV route coverage centers on backbone/classifier patterns; dense vision, promptable masks, OCR, depth, and pose remain candidate tracks.
- Graph coverage proves GCN-style message-passing routing, not point-cloud, equivariant, molecular, or scientific ML.
- Training is a supporting workflow for adapters, distillation, QAT, or architecture artifacts—not a generic port target.
- Legacy local benchmark observations lack one or more modern receipt gates; none is promotion-ready.
- Live Apple Silicon execution, external researcher agents, network collectors, URL health, and upstream revision drift are not proven by deterministic offline tests.
For the complete boundary, read VALIDATION.md and the generated benchmark assessment.