.claude/skills/fabll/SKILL.md
How FabLL (faebryk.core.node) maps Python node/trait declarations into the TypeGraph + instance graph, including field/trait invariants and instantiation patterns. Use when defining new components or traits, working with the Node API, or understanding type registration.
npx skillsauth add atopile/atopile fabllInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
fabll (primarily src/faebryk/core/node.py) is the high-level Python API for defining and working with hardware components. It bridges the gap between Python classes and the underlying TypeGraph and instance graph.
import faebryk.core.faebrykpy as fbrk
import faebryk.core.graph as graph
import faebryk.core.node as fabll
g = graph.GraphView.create()
tg = fbrk.TypeGraph.create(g=g)
class _App(fabll.Node):
pass
app = _App.bind_typegraph(tg=tg).create_instance(g=g)
src/faebryk/core/node.py (Node/Traits/fields, type registration, binding/instantiation helpers)src/faebryk/core/faebrykpy.py (edge types used by FabLL under the hood)src/faebryk/core/graph.py (GraphView wrapper used by instances)src/faebryk/library/): Every component (Resistor, Capacitor, etc.) inherits from Node.Node subclasses dynamically from ato files.Node instances to extract parameters and constraints.fabll.Node is constructed with a graph.BoundNode.SomeType.MakeChild(...)Traits.MakeEdge(SomeTrait.MakeChild().put_on_type()) (or similar)MyType.bind_typegraph(tg).create_instance(g)faebryk.library.*) intentionally have short identifiers (class name) for ato importsNode._register_type)src/faebryk/core/node.py (field system).__init_subclass__).ato dev test --llm test/core/test_node.py -q and ato dev test --llm test/library/test_traits.py -qNode subclasses if they can be a Trait. This allows them to be applied to different component families.Node.__init_subclass__).EdgeTrait.traverse(trait_type=...).MyNode() with no args: instances are created from a bound type via bind_typegraph(...).create_instance(...).import faebryk.core.graph as graph
import faebryk.core.faebrykpy as fbrk
g = graph.GraphView.create()
tg = fbrk.TypeGraph.create(g=g)
inst = MyNode.bind_typegraph(tg).create_instance(g=g)
Node.__init_subclass__ forbids “deeper than one level” inheritance for node types.Node subclasses that typically contain an ImplementsTrait edge.class MyTrait(Node):
is_trait = Traits.MakeEdge(ImplementsTrait.MakeChild().put_on_type())
node_instance.get_trait(TraitType) to retrieve a trait instance. This performs a graph traversal.EdgeComposition. add_child creates this edge. Large trees (10k+ nodes) should be constructed carefully to avoid Python loop overhead; the underlying graph is efficient, but Python interactions cost time.development
How the Faebryk parameter solver works (Sets/Literals, Parameters, Expressions), the core invariants enforced during mutation, and practical workflows for debugging and extending the solver. Use when implementing or modifying constraint solving, parameter bounds, or debugging expression simplification.
development
# SEXP Benchmark Strategy ## Goal Measure and improve S-expression pipeline performance with a focus on: - Throughput per stage - Peak memory per stage - End-to-end behavior on realistic KiCad PCB inputs ## Pipeline Stages Benchmark these layers separately: - `tokenizer` - `ast` - `parser` (typed decode) - `encode` (typed encode to raw SEXP) - `pretty` (formatting) ## Dataset Dimensions Use a matrix over: - `depth`: shallow vs deep nesting - `size`: small, medium, large Recommended size buck
development
How the Zig S-expression engine and typed KiCad models work, how they are exposed to Python (pyzig_sexp), and the invariants around parsing, formatting, and freeing. Use when working with KiCad file parsing, S-expression generation, or layout sync.
tools
How the Zig↔Python binding layer works (pyzig), including build-on-import, wrapper generation patterns, ownership rules, and where to add new exported APIs. Use when adding Zig-Python bindings, modifying native extensions, or debugging C-API interactions.