quark-create-shapeshifter-pass
SkillDev toolsGuides your agent to write a new ShapeShifter graph-transformation pass for AMD Quark models.
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the quark-create-shapeshifter-pass skill
About this skill
Author a new ShapeShifter graph-transformation pass for AMD Quark (ONNX or PyTorch). Trigger for "add a ShapeShifter pass", "create a new onnx_ or pytorch_ pass", "write a custom Quark graph transform", "contribute a community ShapeShifter pass", or extending quark/shapeshifter/passes/. Covers namin
What this skill tells your AI
The instructions your AI receives, as published by amd/quark in skills/quark-create-shapeshifter-pass/SKILL.md and read by ahel’s review.
Purpose
Author a new ShapeShifter transformation pass that is correct on the first try. ShapeShifter is
Quark's pass-based graph-transformation framework (quark/shapeshifter/): each pass is a
self-contained unit that takes a model, applies one transformation, and returns it. Passes
auto-register by filename via a @register_pass decorator, so a new pass is usable from the CLI,
the Python API, and the ONNX quantizer's ShapeShifterYaml with zero manual wiring — if it
follows the naming, subclassing, and config conventions exactly. This skill replays those
conventions in authoring order and flags the non-obvious traps (defaults are not auto-applied;
class/file naming is load-bearing) so the developer focuses on the transformation logic.
Inputs
- Required: the transformation the pass performs (one sentence); the backend it targets
(ONNX
onnx.ModelProtoor PyTorch callable — a pass is one or the other, never both). - Required: a pass name in
snake_case, prefixedonnx_orpytorch_(this becomes the filename, the registry key, and the YAML key — pick it carefully). - Optional: config parameters the pass exposes (name, type, default, whether required);
whether it is a core pass (
quark/shapeshifter/passes/) or a community pass (quark/contrib/shapeshifter_community_passes/); a minimal model that exercises it (for the test).
Outputs: shapeshifter_pass.py
The primary artifact is the new pass module, written to
quark/shapeshifter/passes/<pass_name>.py (core) or
quark/contrib/shapeshifter_community_passes/<pass_name>.py (community). <pass_name> matches the
chosen name (e.g. onnx_drop_identity.py). Side-effect artifacts:
test/test_for_cli/test_shapeshifter_<pass_name>.py— one test per pass (project convention).- A documentation entry in
docs/source/quark_shapeshifter_onnx_passes.rst(ONNX) ordocs/source/quark_shapeshifter_torch_passes.rst(PyTorch).
No JSON schema — this artifact is Quark source code, not a cross-skill handoff artifact.
Interaction Flow
- Intake — capture the transformation, the backend, the pass name, and any config params. If the developer described the transform in prior conversation, extract these first.
- Route — confirm backend (ONNX vs PyTorch) and core-vs-community placement; derive the file path, class name, and YAML key from the name.
- Plan — present the file path, class skeleton,
_default_configparams, and the_run_for_configoutline before writing. Confirm the name does not collide with an existing registry entry (ls quark/shapeshifter/passes/). - Confirm — get explicit approval before writing source files under
quark/. - Execute or Summarize — write the pass, the test, and the doc entry; run the test and confirm the pass registers. Summarize what was created and how to invoke it.
Backend & Placement Decision
| Question | Choose |
|---|---|
Operates on onnx.ModelProto (a graph)? | ONNX pass → subclass ONNXPass, prefix onnx_ |
Operates on a PyTorch callable (nn.Module, function)? | PyTorch pass → subclass PytorchPass, prefix pytorch_ |
| Officially maintained / production? | Core → quark/shapeshifter/passes/ |
| Contributed / experimental? | Community → quark/contrib/shapeshifter_community_passes/ |
A workflow must be all-ONNX or all-PyTorch; the Engine raises ValueError on mixing.
Naming Rules (load-bearing)
- Filename = pass name = registry key = YAML key.
onnx_drop_identity.py→ pass nameonnx_drop_identity, used verbatim underpasses:in YAML. There is no separate name string. - Prefix
onnx_orpytorch_. - Files starting with
_(e.g.__init__.py) are skipped by discovery. - Class name must end in
Pass(only such classes are discovered / exported). Convention:ONNX<Thing>Pass/Pytorch<Thing>Pass. - Duplicate pass names raise
ValueErrorat import (with a core-vs-community conflict message).
Authoring the Pass
Two required methods (see quark/shapeshifter/pass_base.py):
_default_config(self) -> dict[str, PassConfigParam]— declare each config param withPassConfigParam(type_, default_value, required, description); end withconfig.update(self.config)(the convention every pass follows)._run_for_config(self, model, config) -> model— the transformation. ONNX: takes/returnsonnx.ModelProto. PyTorch: takes/returns anyCallable.
ONNX skeleton (quark/shapeshifter/passes/onnx_drop_identity.py):
#
# Copyright (C) 2025 - 2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
#
from typing import Any
import onnx
from onnx import ModelProto
from onnxruntime.quantization.onnx_model import ONNXModel # helpers: remove_nodes, etc.
from quark.common.utils.log import ScreenLogger
from quark.shapeshifter.pass_base import ONNXPass, register_pass
from quark.shapeshifter.pass_config import PassConfigParam
logger = ScreenLogger(__name__)
@register_pass
class ONNXDropIdentityPass(ONNXPass):
"""Remove Identity nodes from the graph."""
def _default_config(self) -> dict[str, PassConfigParam]:
config = {
"drop_identity": PassConfigParam(
type_=bool,
default_value=True,
required=True,
description="Whether to remove Identity nodes.",
),
}
config.update(self.config)
return config
def _run_for_config(self, model: ModelProto, config: dict[str, Any]) -> ModelProto:
# config is the RAW user dict from YAML — read values directly and
# supply your own default (see Critical Gotcha below).
if not config.get("drop_identity", True):
logger.warning("onnx_drop_identity: drop_identity is False, skipping.")
return model
onnx_model = ONNXModel(model)
# ... transform onnx_model.model, then clean up ...
onnx_model.topological_sort()
return onnx_model.model
PyTorch skeleton mirrors this: subclass PytorchPass, _run_for_config(self, model, config)
returns the (possibly mutated) callable. See quark/shapeshifter/passes/pytorch_remove_dropout.py.
Critical Gotcha: defaults are NOT auto-applied
The Engine calls _run_for_config directly with the raw YAML dict — it never calls run()
or _default_config() (see quark/shapeshifter/engine.py, the pass-execution loop:
pass_instance._run_for_config(model, pass_config)). Consequences the pass author MUST handle:
- The
configargument is exactly what the user wrote (e.g.{"drop_identity": True}), not a dict ofPassConfigParamobjects. - Apply defaults yourself inside
_run_for_config, e.g.config.get("drop_identity", True). Do not assume_default_config()populated anything. - Read flat values:
config["drop_identity"]— notconfig.get("x", {}).get("value", ...). (_default_configstill documents the schema and is good practice; it is just not the runtime source of defaults today.)
Registration & Usage (zero-config)
No manual registration. quark/shapeshifter/passes/__init__.py imports every non-_ module via
pkgutil, triggering @register_pass, which adds the class to the global REGISTRY. Importing
quark.shapeshifter registers the pass. Then it works everywhere:
CLI — quark-cli shapeshifter config.yaml:
input_model_path: /path/in.onnx
passes:
onnx_drop_identity:
drop_identity: true
output_model_path: /path/out.onnx
Python API:
from pathlib import Path
from quark.shapeshifter import shapeshifter, RunConfig, ONNXModelConfig
cfg = RunConfig(
input_model_config=ONNXModelConfig(input_model_path=Path("in.onnx")),
passes={"onnx_drop_identity": {"drop_identity": True}},
output_model_path="out.onnx",
)
shapeshifter(cfg) # file-based → returns None
new_model = shapeshifter(RunConfig(passes={"onnx_drop_identity": {}}), model=proto) # in-memory
Inside the ONNX quantizer — add it to a ShapeShifterYaml under preprocess_passes:
(runs on the float model before quantization) or postprocess_passes: (runs on the quantized
Q/DQ model), passed via extra_options={"ShapeShifterYaml": "config.yaml"}.
Test & Docs (required to ship)
- Test:
test/test_for_cli/test_shapeshifter_<pass_name>.py. Followtest_shapeshifter_onnx_convert_clip_to_relu_pass.py: build a tiny model withonnx.helper, write a YAML, runcli(["shapeshifter", yaml_path]), assert on the output graph. Use@use_temporary_directoryfromquark.common.utils.testing_utils. - Docs: add an option-by-option entry to
docs/source/quark_shapeshifter_onnx_passes.rst(ONNX) or..._torch_passes.rst(PyTorch), matching the existing style. CI (.github/workflows/ci_build_and_unittest_cli.yml) already triggers onquark/shapeshifter/**and these doc paths.
Recovery
- "Pass not registered" / KeyError on pass name — filename ≠ YAML key, file starts with
_, the class name does not end inPass, or@register_passis missing. Check all four. ValueError: ... already registered— name collides with a core or community pass. Rename.ValueError: ... is not an ONNX/PyTorch pass— the workflow mixes backends, or the class subclasses the wrong base. All passes in one run must share a backend.- Config value ignored / pass is a silent no-op — you relied on
_default_config()for defaults, or readconfig["x"]["value"]. Read flat values with an explicit default in_run_for_config(see Critical Gotcha). register_pass could not find __file__— the class was defined in a REPL/exec context; it must live in a real.pyfile under a discovered directory.
Notes
- Framework source:
quark/shapeshifter/pass_base.py(bases,REGISTRY,register_pass),quark/shapeshifter/engine.py(execution loop — proves defaults are not auto-applied),quark/shapeshifter/pass_config.py(PassConfigParam),quark/shapeshifter/passes/__init__.py(discovery). Worked examples:onnx_convert_clip_to_relu.py,pytorch_remove_dropout.py. - Adding conventions live in
docs/source/quark_shapeshifter.rst("Adding New Passes"). primary_artifactis.pysource (not a canonical handoff artifact), sovalidate_skill.pyemits a non-blocking WARN for it — expected.- Do not silently skip the test or doc entry; both are required by CI and project convention.
Signals
- GitHub stars
- 174
- Forks
- 35
- Last commit
- Sep 2026
Advanced
- Item type
- skill
- Key
quark-create-shapeshifter-pass- Source
- github.com/amd/quark