fritzkit 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +12 -0
- package/.claude-plugin/plugin.json +13 -0
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/README.md +429 -2
- package/dist/cli/commands/doctor.d.ts +4 -0
- package/dist/cli/commands/doctor.js +7 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/export.d.ts +17 -0
- package/dist/cli/commands/export.js +81 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/kicad.d.ts +10 -0
- package/dist/cli/commands/kicad.js +22 -0
- package/dist/cli/commands/kicad.js.map +1 -0
- package/dist/cli/commands/parts.d.ts +22 -0
- package/dist/cli/commands/parts.js +46 -0
- package/dist/cli/commands/parts.js.map +1 -0
- package/dist/cli/commands/prune.d.ts +14 -0
- package/dist/cli/commands/prune.js +67 -0
- package/dist/cli/commands/prune.js.map +1 -0
- package/dist/cli/commands/render.d.ts +24 -0
- package/dist/cli/commands/render.js +62 -0
- package/dist/cli/commands/render.js.map +1 -0
- package/dist/cli/commands/schema.d.ts +10 -0
- package/dist/cli/commands/schema.js +35 -0
- package/dist/cli/commands/schema.js.map +1 -0
- package/dist/cli/commands/ui.d.ts +14 -0
- package/dist/cli/commands/ui.js +67 -0
- package/dist/cli/commands/ui.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +24 -0
- package/dist/cli/commands/validate.js +91 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/context.d.ts +81 -0
- package/dist/cli/context.js +139 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +8 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/program.d.ts +21 -0
- package/dist/cli/program.js +158 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/raster.d.ts +4 -0
- package/dist/cli/raster.js +9 -0
- package/dist/cli/raster.js.map +1 -0
- package/dist/core/compile/breadboard-util.d.ts +12 -0
- package/dist/core/compile/breadboard-util.js +107 -0
- package/dist/core/compile/breadboard-util.js.map +1 -0
- package/dist/core/compile/breadboard.d.ts +60 -0
- package/dist/core/compile/breadboard.js +513 -0
- package/dist/core/compile/breadboard.js.map +1 -0
- package/dist/core/compile/fzp.d.ts +12 -0
- package/dist/core/compile/fzp.js +183 -0
- package/dist/core/compile/fzp.js.map +1 -0
- package/dist/core/compile/icon.d.ts +17 -0
- package/dist/core/compile/icon.js +27 -0
- package/dist/core/compile/icon.js.map +1 -0
- package/dist/core/compile/index.d.ts +4 -0
- package/dist/core/compile/index.js +62 -0
- package/dist/core/compile/index.js.map +1 -0
- package/dist/core/compile/pcb.d.ts +39 -0
- package/dist/core/compile/pcb.js +164 -0
- package/dist/core/compile/pcb.js.map +1 -0
- package/dist/core/compile/schematic.d.ts +69 -0
- package/dist/core/compile/schematic.js +240 -0
- package/dist/core/compile/schematic.js.map +1 -0
- package/dist/core/compile/style.d.ts +52 -0
- package/dist/core/compile/style.js +72 -0
- package/dist/core/compile/style.js.map +1 -0
- package/dist/core/compile/types.d.ts +50 -0
- package/dist/core/compile/types.js +15 -0
- package/dist/core/compile/types.js.map +1 -0
- package/dist/core/export/bin.d.ts +61 -0
- package/dist/core/export/bin.js +221 -0
- package/dist/core/export/bin.js.map +1 -0
- package/dist/core/export/fzpz.d.ts +37 -0
- package/dist/core/export/fzpz.js +121 -0
- package/dist/core/export/fzpz.js.map +1 -0
- package/dist/core/export/index.d.ts +5 -0
- package/dist/core/export/index.js +6 -0
- package/dist/core/export/index.js.map +1 -0
- package/dist/core/export/install.d.ts +77 -0
- package/dist/core/export/install.js +183 -0
- package/dist/core/export/install.js.map +1 -0
- package/dist/core/export/prune.d.ts +72 -0
- package/dist/core/export/prune.js +165 -0
- package/dist/core/export/prune.js.map +1 -0
- package/dist/core/fritzing.d.ts +22 -0
- package/dist/core/fritzing.js +77 -0
- package/dist/core/fritzing.js.map +1 -0
- package/dist/core/identity.d.ts +29 -0
- package/dist/core/identity.js +70 -0
- package/dist/core/identity.js.map +1 -0
- package/dist/core/image/bbox.d.ts +27 -0
- package/dist/core/image/bbox.js +24 -0
- package/dist/core/image/bbox.js.map +1 -0
- package/dist/core/image/index.d.ts +8 -0
- package/dist/core/image/index.js +9 -0
- package/dist/core/image/index.js.map +1 -0
- package/dist/core/image/key.d.ts +72 -0
- package/dist/core/image/key.js +317 -0
- package/dist/core/image/key.js.map +1 -0
- package/dist/core/image/prepare.d.ts +31 -0
- package/dist/core/image/prepare.js +98 -0
- package/dist/core/image/prepare.js.map +1 -0
- package/dist/core/image/remover.d.ts +17 -0
- package/dist/core/image/remover.js +51 -0
- package/dist/core/image/remover.js.map +1 -0
- package/dist/core/index.d.ts +16 -0
- package/dist/core/index.js +17 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/kicad/footprint.d.ts +104 -0
- package/dist/core/kicad/footprint.js +317 -0
- package/dist/core/kicad/footprint.js.map +1 -0
- package/dist/core/kicad/index.d.ts +25 -0
- package/dist/core/kicad/index.js +197 -0
- package/dist/core/kicad/index.js.map +1 -0
- package/dist/core/kicad/sexpr.d.ts +35 -0
- package/dist/core/kicad/sexpr.js +163 -0
- package/dist/core/kicad/sexpr.js.map +1 -0
- package/dist/core/resolve.d.ts +113 -0
- package/dist/core/resolve.js +301 -0
- package/dist/core/resolve.js.map +1 -0
- package/dist/core/schema/part.d.ts +995 -0
- package/dist/core/schema/part.js +278 -0
- package/dist/core/schema/part.js.map +1 -0
- package/dist/core/schema/part.schema.json +1122 -0
- package/dist/core/svg.d.ts +20 -0
- package/dist/core/svg.js +56 -0
- package/dist/core/svg.js.map +1 -0
- package/dist/core/units.d.ts +28 -0
- package/dist/core/units.js +42 -0
- package/dist/core/units.js.map +1 -0
- package/dist/core/validate/checker.d.ts +46 -0
- package/dist/core/validate/checker.js +142 -0
- package/dist/core/validate/checker.js.map +1 -0
- package/dist/core/validate/doctor.d.ts +25 -0
- package/dist/core/validate/doctor.js +156 -0
- package/dist/core/validate/doctor.js.map +1 -0
- package/dist/core/validate/explain.d.ts +10 -0
- package/dist/core/validate/explain.js +135 -0
- package/dist/core/validate/explain.js.map +1 -0
- package/dist/core/validate/index.d.ts +21 -0
- package/dist/core/validate/index.js +96 -0
- package/dist/core/validate/index.js.map +1 -0
- package/dist/core/validate/structural.d.ts +74 -0
- package/dist/core/validate/structural.js +664 -0
- package/dist/core/validate/structural.js.map +1 -0
- package/dist/core/workspace.d.ts +69 -0
- package/dist/core/workspace.js +213 -0
- package/dist/core/workspace.js.map +1 -0
- package/dist/mcp/jsonpatch.d.ts +30 -0
- package/dist/mcp/jsonpatch.js +145 -0
- package/dist/mcp/jsonpatch.js.map +1 -0
- package/dist/mcp/main.d.ts +2 -0
- package/dist/mcp/main.js +5 -0
- package/dist/mcp/main.js.map +1 -0
- package/dist/mcp/server.d.ts +28 -0
- package/dist/mcp/server.js +310 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/server/api.d.ts +72 -0
- package/dist/server/api.js +507 -0
- package/dist/server/api.js.map +1 -0
- package/dist/server/events.d.ts +28 -0
- package/dist/server/events.js +134 -0
- package/dist/server/events.js.map +1 -0
- package/dist/server/http.d.ts +36 -0
- package/dist/server/http.js +127 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/index.d.ts +65 -0
- package/dist/server/index.js +193 -0
- package/dist/server/index.js.map +1 -0
- package/dist/ui/assets/index-DLU8opyI.js +63 -0
- package/dist/ui/assets/index-GhUA-T3b.css +1 -0
- package/dist/ui/index.html +14 -0
- package/package.json +89 -4
- package/skills/fritzkit/SKILL.md +690 -0
- package/skills/fritzkit/reference/examples.md +275 -0
- package/skills/fritzkit/reference/part-json.md +333 -0
- package/skills/fritzkit/scripts/measure.py +197 -0
- package/tools/fzp-checker/.python-version +1 -0
- package/tools/fzp-checker/README.md +45 -0
- package/tools/fzp-checker/check_fzp.py +48 -0
- package/tools/fzp-checker/pyproject.toml +26 -0
- package/tools/fzp-checker/uv.lock +266 -0
- package/tools/fzp-checker/vendor/LICENSE.txt +8 -0
- package/tools/fzp-checker/vendor/UPSTREAM.md +25 -0
- package/tools/fzp-checker/vendor/fzp_checker.py +14 -0
- package/tools/fzp-checker/vendor/scripts/checks/__init__.py +26 -0
- package/tools/fzp-checker/vendor/scripts/checks/check_missing_leg_ids.py +44 -0
- package/tools/fzp-checker/vendor/scripts/checks/checkascii.py +27 -0
- package/tools/fzp-checker/vendor/scripts/checks/checkcase.py +156 -0
- package/tools/fzp-checker/vendor/scripts/checks/checkcopies.py +104 -0
- package/tools/fzp-checker/vendor/scripts/checks/connector_numbering.py +79 -0
- package/tools/fzp-checker/vendor/scripts/checks/connectors_misnumbered.py +228 -0
- package/tools/fzp-checker/vendor/scripts/checks/explain_errors.md +95 -0
- package/tools/fzp-checker/vendor/scripts/checks/fzp_checker_runner.py +717 -0
- package/tools/fzp-checker/vendor/scripts/checks/fzp_checkers.py +1069 -0
- package/tools/fzp-checker/vendor/scripts/checks/fzp_svg_checkers.py +62 -0
- package/tools/fzp-checker/vendor/scripts/checks/fzp_utils.py +222 -0
- package/tools/fzp-checker/vendor/scripts/checks/inspector_fc51.png +0 -0
- package/tools/fzp-checker/vendor/scripts/checks/invisibleconnectors.py +118 -0
- package/tools/fzp-checker/vendor/scripts/checks/nolayeridcheck.txt +758 -0
- package/tools/fzp-checker/vendor/scripts/checks/requirements.txt +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/svg_checkers.py +953 -0
- package/tools/fzp-checker/vendor/scripts/checks/svg_utils.py +96 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_checkers.py +839 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/author_missing.fzp.test +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/author_present.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/buses_missing_id.fzp.test +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/buses_missing_node_members.fzp.test +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/buses_present_valid.fzp.test +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/connector_layers_missing_attributes.fzp.test +16 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/connector_layers_present_valid.fzp.test +14 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/connector_numbering_invalid.fzp.test +70 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/connector_numbering_valid.fzp.test +70 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/connector_refs_valid.fzp.test +53 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_invalid_mixed.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_invalid_silkscreen_nested.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_invalid_style_attr.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_invalid_white_stroke.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_invalid_wrong_color.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_valid_inherited.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_valid_legacy.fzp.test +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_valid_nested_copper.fzp.test +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_valid_none.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_valid_standard.fzp.test +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_valid_uppercase.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/css_connector.fzp.test +100 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/description_missing.fzp.test +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/description_present.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/duplicate_ids.fzp.test +27 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/family_property_missing.fzp.test +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/family_property_present_valid.fzp.test +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/font_size.fzp.test +46 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/fritzing_version_invalid_format.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/fritzing_version_missing.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/fritzing_version_present_valid.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/gorn_absent.fzp.test +15 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/gorn_present.fzp.test +15 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/hybrid_connectors.fzp.test +232 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/invalid_xml.fzp.test +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/layer_ids_match.fzp.test +29 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/layer_ids_mismatch.fzp.test +30 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/layer_nesting_invalid.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/layer_nesting_valid.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/matrix_transform.fzp.test +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/missing_connector_refs.fzp.test +63 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/missing_leg_ids.fzp.test +34 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/module_id_missing.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/module_id_non_alnum.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/module_id_present.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/module_id_special_chars_absent.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/module_id_special_chars_present.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/module_id_too_short.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/no_layer_invalid.fzp.test +19 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/no_layer_namedview.fzp.test +19 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/no_layer_valid.fzp.test +19 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/pcb_only.fzp.test +48 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/property_fields_missing_name.fzp.test +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/property_fields_missing_value.fzp.test +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/property_fields_present.fzp.test +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/required_tags_missing.fzp.test +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/required_tags_present.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/stroke_test.fzp.test +60 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/template_svgs.fzp.test +35 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/title_missing.fzp.test +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/title_present.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/unique_ids.fzp.test +27 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/unique_property_names_duplicates.fzp.test +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/unique_property_names_unique.fzp.test +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/valid_xml.fzp.test +249 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/version_invalid_format.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/version_missing.fzp.test +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/version_present_valid.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/views_missing.fzp.test +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/views_present.fzp.test +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/connector_refs_valid_breadboard.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/duplicate_ids_breadboard.svg +13 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/gorn_absent_breadboard.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/gorn_present_breadboard.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/hybrid_connectors_breadboard.svg +102 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/layer_nesting_invalid.svg +13 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/layer_nesting_valid.svg +13 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/matrix_transform.svg +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/missing_connector_refs_breadboard.svg +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/missing_leg_ids_breadboard.svg +9 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/test_layer_ids_match_breadboard.svg +9 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/test_layer_ids_mismatch_breadboard.svg +9 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/unique_ids_breadboard.svg +13 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/icon/hybrid_connectors_icon.svg +78 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/icon/no_layer_invalid.svg +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/icon/no_layer_namedview.svg +9 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/icon/no_layer_valid.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/icon/plain_pcb.svg +10 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/connector_refs_valid_pcb.svg +10 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_invalid_mixed.svg +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_invalid_silkscreen_nested.svg +10 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_invalid_style_attr.svg +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_invalid_white_stroke.svg +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_invalid_wrong_color.svg +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_valid_inherited.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_valid_legacy.svg +10 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_valid_nested_copper.svg +9 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_valid_none.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_valid_standard.svg +10 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_valid_uppercase.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/css_connector.svg +25 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/font_size.svg +54 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/hybrid_connectors_pcb.svg +35 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/missing_connector_refs_pcb.svg +14 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/pcb-arduino-shield.svg +25 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/stroke_test.svg +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/test_layer_ids_match_pcb.svg +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/test_layer_ids_mismatch_pcb.svg +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/schematic/connector_refs_valid_schematic.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/schematic/hybrid_connectors_schematic.svg +59 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/schematic/missing_connector_refs_schematic.svg +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/schematic/test_layer_ids_match_schematic.svg +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/schematic/test_layer_ids_mismatch_schematic.svg +6 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fritzkit",
|
|
3
|
+
"owner": { "name": "pmaxhogan" },
|
|
4
|
+
"description": "Claude Code marketplace for the fritzkit plugin",
|
|
5
|
+
"plugins": [
|
|
6
|
+
{
|
|
7
|
+
"name": "fritzkit",
|
|
8
|
+
"source": "./",
|
|
9
|
+
"description": "Build Fritzing parts from a product link: workflow skill plus the fritzkit MCP server"
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fritzkit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Build first-class Fritzing parts (.fzpz) from a product link, datasheet, photos or KiCad footprint: a skill for the research workflow plus the fritzkit MCP server that compiles, validates, renders, exports and installs the part.",
|
|
5
|
+
"author": { "name": "Max Hogan", "url": "https://github.com/pmaxhogan" },
|
|
6
|
+
"homepage": "https://github.com/pmaxhogan/fritzkit#readme",
|
|
7
|
+
"repository": "https://github.com/pmaxhogan/fritzkit",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"keywords": ["fritzing", "fzpz", "electronics", "parts", "breadboard", "mcp"],
|
|
10
|
+
"mcpServers": {
|
|
11
|
+
"fritzkit": { "command": "npx", "args": ["-y", "fritzkit", "mcp"] }
|
|
12
|
+
}
|
|
13
|
+
}
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Short notes per release. Releases are cut automatically on every green push to main.
|
|
4
|
+
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
- Scaffold from stack standards.
|
|
8
|
+
- Agent docs: Claude Code skill (skills/fritzkit), plugin manifest, README, docs/part-json.md field reference and docs/agent-workflow.md.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Max Hogan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,430 @@
|
|
|
1
|
-
#
|
|
1
|
+
# fritzkit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/pmaxhogan/fritzkit/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/pmaxhogan/fritzkit/actions/workflows/fzp-checker.yml)
|
|
5
|
+
|
|
6
|
+
fritzkit compiles a small JSON description of a board (`part.json`: outline in mm, every
|
|
7
|
+
pad and pin with its name, role and position, buses for shared nets) into a first-class
|
|
8
|
+
Fritzing part: breadboard, schematic, PCB and icon views that pass Fritzing's own part
|
|
9
|
+
checker, seat on the 0.1 in breadboard grid and keep their connector ids across versions so
|
|
10
|
+
placed parts can be swapped without losing wires. It ships as a CLI, an MCP server and a
|
|
11
|
+
Claude Code skill, so you can hand Claude a product link and get a `.fzpz` back in My Parts.
|
|
12
|
+
fritzkit itself is offline and deterministic; the agent does the reading and measuring.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
npx fritzkit --help # run without installing
|
|
18
|
+
npm i -g fritzkit # or install the `fritzkit` command globally
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Requirements:
|
|
22
|
+
|
|
23
|
+
- Node.js 22 or newer
|
|
24
|
+
- [Fritzing](https://fritzing.org/) 1.0.7 (to use the parts; `install` and `prune` manage its user parts folder)
|
|
25
|
+
- optional: [uv](https://docs.astral.sh/uv/) for `validate --checker`, which runs Fritzing's own part checker
|
|
26
|
+
|
|
27
|
+
`fritzkit doctor` checks all of these.
|
|
28
|
+
|
|
29
|
+
## 60-second quickstart
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
fritzkit init # create the workspace (~/fritzkit/parts)
|
|
33
|
+
fritzkit new my-breakout --title "My breakout" # <workspace>/my-breakout/part.json + assets/
|
|
34
|
+
# edit ~/fritzkit/parts/my-breakout/part.json (see the reference below)
|
|
35
|
+
fritzkit validate my-breakout # schema + structural checks
|
|
36
|
+
fritzkit render my-breakout --png # PNG of every view into my-breakout/build/
|
|
37
|
+
fritzkit export my-breakout # -> my-breakout/<moduleId>.fzpz
|
|
38
|
+
fritzkit install my-breakout # into Fritzing's My Parts (close Fritzing first)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then start Fritzing; the part is in the **My Parts** bin.
|
|
42
|
+
|
|
43
|
+
## Use it from Claude Code
|
|
44
|
+
|
|
45
|
+
As a plugin (skill + MCP server in one step):
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
claude plugin marketplace add pmaxhogan/fritzkit
|
|
49
|
+
claude plugin install fritzkit@fritzkit
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
(Inside a session: `/plugin marketplace add pmaxhogan/fritzkit`, then
|
|
53
|
+
`/plugin install fritzkit@fritzkit`.)
|
|
54
|
+
|
|
55
|
+
Or just the MCP server:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
claude mcp add --scope user fritzkit -- npx -y fritzkit mcp
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
and, for the workflow, copy `skills/fritzkit/` from this repo into `~/.claude/skills/fritzkit/`.
|
|
62
|
+
|
|
63
|
+
Then ask: "Make me a Fritzing part for https://www.amazon.com/dp/XXXXXXXXXX". The skill
|
|
64
|
+
tells Claude how to fetch the listing and images, measure the board, name every pad, write
|
|
65
|
+
`part.json`, check the render against the photo, and export/install the part.
|
|
66
|
+
|
|
67
|
+
## The agent workflow
|
|
68
|
+
|
|
69
|
+
1. Gather sources with the agent's own tools (listing via Amazon's mobile URL with a plain
|
|
70
|
+
`curl`, gallery images from the page's `hiRes` URLs, datasheet PDFs, manufacturer wiki, Digikey page, or a KiCad footprint).
|
|
71
|
+
2. Determine the outline in mm from dimension callouts or a drawing, cross-checked.
|
|
72
|
+
3. Identify every pad: silkscreen name, role, net (buses), connector kind, position measured
|
|
73
|
+
from the photo at a known px/mm.
|
|
74
|
+
4. Write `part.json`, `validate`, `render --png`, compare the render with the photo, fix,
|
|
75
|
+
repeat.
|
|
76
|
+
5. `export`, then `install` (Fritzing closed) or hand over the `.fzpz`; `prune` old versions.
|
|
77
|
+
6. Report what was measured, what was estimated, and what the user should verify.
|
|
78
|
+
|
|
79
|
+
Long form: [docs/agent-workflow.md](docs/agent-workflow.md). The skill itself:
|
|
80
|
+
[skills/fritzkit/SKILL.md](skills/fritzkit/SKILL.md).
|
|
81
|
+
|
|
82
|
+
## part.json reference
|
|
83
|
+
|
|
84
|
+
Every field, type, default and the coordinate frame: [docs/part-json.md](docs/part-json.md).
|
|
85
|
+
The JSON Schema is printed by `fritzkit schema`. In short: lengths in mm, origin at the
|
|
86
|
+
top-left corner of the outline, x right, y down (like a top-down photo), positions are pad
|
|
87
|
+
centres.
|
|
88
|
+
|
|
89
|
+
Example, the [Seeed Studio XIAO ESP32-C6](https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/)
|
|
90
|
+
(a portrait board: top view, USB-C at the TOP short edge, two columns of 7 castellated pads
|
|
91
|
+
down the long edges, a 2-pad BAT header on the back, GND pads tied by a bus). Trimmed; the
|
|
92
|
+
full, measured spec is [examples/xiao-esp32-c6](examples/xiao-esp32-c6/README.md):
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"$schema": "https://raw.githubusercontent.com/pmaxhogan/fritzkit/main/src/core/schema/part.schema.json",
|
|
97
|
+
"slug": "xiao-esp32-c6",
|
|
98
|
+
"title": "Seeed Studio XIAO ESP32-C6",
|
|
99
|
+
"version": 1,
|
|
100
|
+
"label": "U",
|
|
101
|
+
"tags": ["xiao", "esp32-c6", "seeed", "castellated"],
|
|
102
|
+
"description": "Seeed Studio XIAO ESP32-C6, 21 x 17.8 mm. Top (component) view, USB-C at the TOP short edge, the two columns of 7 castellated 0.1 in pads along the long edges: D0..D6 down the left edge, 5V/GND/3V3/D10/D9/D8/D7 down the right edge. BAT+ and BAT- are pads on the BACK, drawn where they sit seen through the board. BAT- and the side GND pad are the same net (Seeed's KiCad symbol names that pad GND), hence the GND bus.",
|
|
103
|
+
"sources": ["https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/"],
|
|
104
|
+
"properties": {
|
|
105
|
+
"mpn": "XIAO ESP32C6",
|
|
106
|
+
"type": "module",
|
|
107
|
+
"chip": "ESP32-C6"
|
|
108
|
+
},
|
|
109
|
+
"outline": {
|
|
110
|
+
"widthMm": 17.8,
|
|
111
|
+
"heightMm": 21,
|
|
112
|
+
"shape": "rounded",
|
|
113
|
+
"cornerRadiusMm": 1.5
|
|
114
|
+
},
|
|
115
|
+
"artwork": {
|
|
116
|
+
"style": "vector",
|
|
117
|
+
"boardColor": "#1A1A1A",
|
|
118
|
+
"components": [
|
|
119
|
+
{
|
|
120
|
+
"kind": "rect",
|
|
121
|
+
"xMm": 4.4,
|
|
122
|
+
"yMm": -1.5,
|
|
123
|
+
"wMm": 9,
|
|
124
|
+
"hMm": 7.4,
|
|
125
|
+
"color": "#B8B8B8",
|
|
126
|
+
"rxMm": 0.8,
|
|
127
|
+
"note": "USB-C receptacle, overhangs the top edge by 1.5 mm (KiCad footprint silk)"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"kind": "rect",
|
|
131
|
+
"xMm": 3,
|
|
132
|
+
"yMm": 6.8,
|
|
133
|
+
"wMm": 11.8,
|
|
134
|
+
"hMm": 10.4,
|
|
135
|
+
"color": "#6E6E6E",
|
|
136
|
+
"rxMm": 0.4,
|
|
137
|
+
"note": "ESP32-C6 RF shield can"
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
"headers": [
|
|
142
|
+
{
|
|
143
|
+
"key": "left",
|
|
144
|
+
"kind": "castellated",
|
|
145
|
+
"cols": 7,
|
|
146
|
+
"orientation": "vertical",
|
|
147
|
+
"xMm": 1.28,
|
|
148
|
+
"yMm": 2.88,
|
|
149
|
+
"pins": [
|
|
150
|
+
{
|
|
151
|
+
"key": "d0",
|
|
152
|
+
"name": "D0",
|
|
153
|
+
"role": "analog",
|
|
154
|
+
"description": "D0 / A0: GPIO0 (LP_GPIO0), ADC"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"key": "d1",
|
|
158
|
+
"name": "D1",
|
|
159
|
+
"role": "analog",
|
|
160
|
+
"description": "D1 / A1: GPIO1 (LP_GPIO1), ADC"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"key": "d2",
|
|
164
|
+
"name": "D2",
|
|
165
|
+
"role": "analog",
|
|
166
|
+
"description": "D2 / A2: GPIO2 (LP_GPIO2), ADC"
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"key": "d3",
|
|
170
|
+
"name": "D3",
|
|
171
|
+
"role": "io",
|
|
172
|
+
"description": "D3: GPIO21 (SDIO_DATA1)"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"key": "d4",
|
|
176
|
+
"name": "D4",
|
|
177
|
+
"role": "i2c",
|
|
178
|
+
"description": "D4 / SDA: GPIO22, I2C data (SDIO_DATA2)"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"key": "d5",
|
|
182
|
+
"name": "D5",
|
|
183
|
+
"role": "i2c",
|
|
184
|
+
"description": "D5 / SCL: GPIO23, I2C clock (SDIO_DATA3)"
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"key": "d6",
|
|
188
|
+
"name": "D6",
|
|
189
|
+
"role": "uart",
|
|
190
|
+
"description": "D6 / TX: GPIO16, UART transmit"
|
|
191
|
+
}
|
|
192
|
+
]
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"key": "right",
|
|
196
|
+
"kind": "castellated",
|
|
197
|
+
"cols": 7,
|
|
198
|
+
"orientation": "vertical",
|
|
199
|
+
"xMm": 16.52,
|
|
200
|
+
"yMm": 2.88,
|
|
201
|
+
"pins": [
|
|
202
|
+
{
|
|
203
|
+
"key": "5v",
|
|
204
|
+
"name": "5V",
|
|
205
|
+
"role": "power",
|
|
206
|
+
"description": "5V (VBUS): USB-C 5 V in/out. No voltage here when running from the battery"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"key": "gnd",
|
|
210
|
+
"name": "GND",
|
|
211
|
+
"role": "gnd",
|
|
212
|
+
"description": "Ground"
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"key": "3v3",
|
|
216
|
+
"name": "3V3",
|
|
217
|
+
"role": "power",
|
|
218
|
+
"description": "3V3 (3V3_OUT): 3.3 V regulator output"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"key": "d10",
|
|
222
|
+
"name": "D10",
|
|
223
|
+
"role": "spi",
|
|
224
|
+
"description": "D10 / MOSI: GPIO18, SPI data out"
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"key": "d9",
|
|
228
|
+
"name": "D9",
|
|
229
|
+
"role": "spi",
|
|
230
|
+
"description": "D9 / MISO: GPIO20, SPI data in"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"key": "d8",
|
|
234
|
+
"name": "D8",
|
|
235
|
+
"role": "spi",
|
|
236
|
+
"description": "D8 / SCK: GPIO19, SPI clock"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"key": "d7",
|
|
240
|
+
"name": "D7",
|
|
241
|
+
"role": "uart",
|
|
242
|
+
"description": "D7 / RX: GPIO17, UART receive"
|
|
243
|
+
}
|
|
244
|
+
]
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"key": "bat",
|
|
248
|
+
"kind": "castellated",
|
|
249
|
+
"cols": 2,
|
|
250
|
+
"orientation": "horizontal",
|
|
251
|
+
"xMm": 7.11,
|
|
252
|
+
"yMm": 16.03,
|
|
253
|
+
"pad": {
|
|
254
|
+
"shape": "rect",
|
|
255
|
+
"wMm": 1.1,
|
|
256
|
+
"hMm": 2.5,
|
|
257
|
+
"smd": true
|
|
258
|
+
},
|
|
259
|
+
"pins": [
|
|
260
|
+
{
|
|
261
|
+
"key": "bat+",
|
|
262
|
+
"name": "BAT+",
|
|
263
|
+
"label": "B+",
|
|
264
|
+
"role": "power",
|
|
265
|
+
"description": "Li-ion battery plus (VBAT), pad on the BACK; charged by the on-board SGM40567 charger"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"key": "bat-",
|
|
269
|
+
"name": "BAT-",
|
|
270
|
+
"label": "B-",
|
|
271
|
+
"role": "gnd",
|
|
272
|
+
"description": "Battery minus, pad on the BACK. Same net as GND"
|
|
273
|
+
}
|
|
274
|
+
]
|
|
275
|
+
}
|
|
276
|
+
],
|
|
277
|
+
"buses": [
|
|
278
|
+
{
|
|
279
|
+
"id": "GND",
|
|
280
|
+
"pins": ["gnd", "bat-"]
|
|
281
|
+
}
|
|
282
|
+
]
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
More examples (an ESC with wire leads, a relay module, a KiCad import):
|
|
287
|
+
[skills/fritzkit/reference/examples.md](skills/fritzkit/reference/examples.md).
|
|
288
|
+
|
|
289
|
+
## CLI reference
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
fritzkit [--workspace <dir>] [--json] <command>
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
`<part>` is a slug in the workspace (default `~/fritzkit/parts`, or `FRITZKIT_WORKSPACE`) or
|
|
296
|
+
a path to a part folder (`validate` and `render` also accept a `.fzpz`). `--json` prints machine-readable output.
|
|
297
|
+
|
|
298
|
+
| command | what it does |
|
|
299
|
+
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
300
|
+
| `init` | create the workspace folder |
|
|
301
|
+
| `new <slug> [--title <t>]` | create `<workspace>/<slug>/part.json` (a placeholder spec) and `assets/` |
|
|
302
|
+
| `list` | list the parts in the workspace |
|
|
303
|
+
| `validate <part> [--checker]` | schema and structural checks; `--checker` also runs Fritzing's part checker via uv and prints a `fzp checker: ran (...)` or `skipped - ...` line; a `.fzpz` path checks the package only |
|
|
304
|
+
| `render <part> [--view <v>] [--out <dir>] [--png]` | write `<view>.svg` for one view or all four (breadboard, schematic, pcb, icon) into `<part>/build/`; `--png` ALSO writes `<view>.png` at 300 dpi |
|
|
305
|
+
| `export <part> [--out <file>] [--install] [--force]` | build the `.fzpz` (next to part.json by default); refuses on validator errors unless `--force`; `--install` also installs it |
|
|
306
|
+
| `install <part> [--out <file>] [--force]` | same as `export --install`; refuses while Fritzing is running |
|
|
307
|
+
| `prune <family-or-slug> [--keep <moduleId>] [--yes]` | list older installed versions of a family (dry run); `--yes` deletes them, keeping the newest |
|
|
308
|
+
| `doctor` | check Node, uv, the Fritzing install and its parts folder, sharp |
|
|
309
|
+
| `schema [--out <file>]` | print or write the part.json JSON Schema |
|
|
310
|
+
| `import-kicad <file> --slug <slug>` | create a part from a `.kicad_mod` footprint with exact pad geometry |
|
|
311
|
+
| `mcp` | run the MCP server on stdio |
|
|
312
|
+
| `ui [part] [--port <n>]` | local web editor for part.json with live previews |
|
|
313
|
+
|
|
314
|
+
Exit codes: 0 ok, 1 error, 2 the `ui` app is not built (run `npm run ui:build`), 3 Fritzing is running (install/prune).
|
|
315
|
+
|
|
316
|
+
## MCP tools
|
|
317
|
+
|
|
318
|
+
Run with `npx -y fritzkit mcp` (stdio). Same core as the CLI.
|
|
319
|
+
|
|
320
|
+
| tool | purpose |
|
|
321
|
+
| ------------------------- | -------------------------------------------------------------- |
|
|
322
|
+
| `fritzkit_init_workspace` | create the workspace |
|
|
323
|
+
| `fritzkit_list_parts` | list parts |
|
|
324
|
+
| `fritzkit_new_part` | create a part folder with a placeholder spec |
|
|
325
|
+
| `fritzkit_get_part` | read a part's part.json |
|
|
326
|
+
| `fritzkit_set_part` | replace part.json with a whole spec |
|
|
327
|
+
| `fritzkit_patch_part` | apply JSON-patch operations to part.json |
|
|
328
|
+
| `fritzkit_add_pins` | append pins |
|
|
329
|
+
| `fritzkit_validate` | schema + structural checks (optionally the Fritzing checker) |
|
|
330
|
+
| `fritzkit_render` | render a view as SVG text or a PNG image the agent can look at |
|
|
331
|
+
| `fritzkit_export` | build the `.fzpz` |
|
|
332
|
+
| `fritzkit_install` | install into Fritzing's user parts folder (Fritzing closed) |
|
|
333
|
+
| `fritzkit_prune` | remove old installed versions of a family |
|
|
334
|
+
| `fritzkit_import_kicad` | create a part from a `.kicad_mod` |
|
|
335
|
+
| `fritzkit_schema` | the part.json JSON Schema |
|
|
336
|
+
| `fritzkit_doctor` | environment check |
|
|
337
|
+
|
|
338
|
+
## Acceptance
|
|
339
|
+
|
|
340
|
+
The part pipeline was verified end to end on a real product: a fresh agent built the
|
|
341
|
+
[HW-391 2S 20A balance board](examples/hw391-2s-20a-bms/README.md) from its Amazon listing
|
|
342
|
+
using only the skill and the CLI, every pad landed within 0.75 mm of a hidden golden table, and
|
|
343
|
+
the local acceptance run (`npm run e2e`) rendered it in Fritzing and wired it on a
|
|
344
|
+
breadboard. Screenshots of the GUI run (the part in My Parts, wired, saved) are in
|
|
345
|
+
[docs/acceptance/](docs/acceptance/); the example's own notes and measured-vs-golden table are in
|
|
346
|
+
[examples/hw391-2s-20a-bms/README.md](examples/hw391-2s-20a-bms/README.md).
|
|
347
|
+
|
|
348
|
+
## FAQ
|
|
349
|
+
|
|
350
|
+
**Why does every export get a new moduleId?** Fritzing refuses to import a part whose
|
|
351
|
+
moduleId it already has ("Part module ID must be unique"). The moduleId is
|
|
352
|
+
`fritzkit-<slug>-<hash8>`, where the hash covers part.json and the assets, so every change
|
|
353
|
+
imports cleanly. Use `fritzkit prune <family> --yes` to remove the old versions.
|
|
354
|
+
|
|
355
|
+
**How do I swap a placed part for a newer version?** All versions share a family (the slug)
|
|
356
|
+
and differ in the variant (`v<version> <hash8>`). Select the part in a sketch and pick the
|
|
357
|
+
newer variant in the Inspector. Connector ids come from the persistent `pinIds` map in
|
|
358
|
+
part.json, so pins that still exist keep their ids and wires stay attached.
|
|
359
|
+
|
|
360
|
+
**Why must Fritzing be closed for `install`?** Fritzing scans its user parts folder only at
|
|
361
|
+
startup, so a part copied in while it runs would not show up (and it may write the same
|
|
362
|
+
files). `install` and `prune` refuse while Fritzing is running and say why.
|
|
363
|
+
|
|
364
|
+
**Where are parts installed?** Into Fritzing's user parts folder, one folder per moduleId:
|
|
365
|
+
`%APPDATA%\Fritzing\Fritzing\local_parts\user\<moduleId>\` on Windows,
|
|
366
|
+
`~/Library/Application Support/Fritzing/Fritzing/local_parts/user/` on macOS,
|
|
367
|
+
`~/.local/share/Fritzing/Fritzing/local_parts/user/` on Linux. This is the same layout
|
|
368
|
+
Fritzing's own File > Open import writes; the part shows up in My Parts at the next start.
|
|
369
|
+
|
|
370
|
+
**Should I use the photo artwork style?** Usually not. The default vector style looks like
|
|
371
|
+
Fritzing's own parts, stays sharp, is small and survives Fritzing's Parts Editor. The photo
|
|
372
|
+
style (`artwork.style: "photo"`) embeds the listing photo with vector pads on top; Fritzing's
|
|
373
|
+
Parts Editor drops embedded rasters if you edit the part, it pixelates when zoomed, and
|
|
374
|
+
Gerber export strips images (the PCB view is always vector).
|
|
375
|
+
|
|
376
|
+
**Can it do the PCB view?** Yes: a real footprint from the pad table (through-hole pads on
|
|
377
|
+
both copper layers with their drill size, SMD and castellated pads on top copper, the
|
|
378
|
+
outline on silkscreen). Positions are only as good as the measurements in part.json, so
|
|
379
|
+
verify against a datasheet drawing or calipers before fabricating a board.
|
|
380
|
+
|
|
381
|
+
## Development
|
|
382
|
+
|
|
383
|
+
```
|
|
384
|
+
npm ci
|
|
385
|
+
npm test # vitest with coverage
|
|
386
|
+
npm run lint # eslint
|
|
387
|
+
npm run format:check # prettier
|
|
388
|
+
npm run check-ascii # every tracked file must be ASCII
|
|
389
|
+
npm run build # tsc to dist/
|
|
390
|
+
npm run fritzkit -- <args> # run the CLI from source
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
`tools/fzp-checker/` vendors Fritzing's `fzp_checker` (from fritzing-parts 1.0.7) for CI:
|
|
394
|
+
`uv run --project tools/fzp-checker check-fzp <file.fzpz>`. `npm run e2e` is a local-only
|
|
395
|
+
acceptance harness that drives a real Fritzing install; it needs a desktop session with
|
|
396
|
+
Fritzing 1.0.7 installed and is not run in CI. `.mcp.json` points Claude Code at the MCP
|
|
397
|
+
server from source when you work in this repo. Keep its server name `fritzkit`: the plugin
|
|
398
|
+
manifest declares a server with the same name, which replaces the dev entry when the plugin
|
|
399
|
+
is installed, so installers run `npx -y fritzkit mcp` and never the source checkout.
|
|
400
|
+
|
|
401
|
+
## Releasing
|
|
402
|
+
|
|
403
|
+
`release.yml` runs after every green CI run on `main` (plus a daily cron) and publishes a
|
|
404
|
+
patch release, the same setup as `pmaxhogan/tasker-mcp`. The version is computed from the
|
|
405
|
+
registry (latest published patch + 1, never below the `major.minor.0` floor in
|
|
406
|
+
`package.json`) and is not committed back. The job installs with `--ignore-scripts` and no
|
|
407
|
+
dependency cache, and npm attaches provenance.
|
|
408
|
+
|
|
409
|
+
Auth is npm trusted publishing (OIDC) only; no token is stored. Until the repository
|
|
410
|
+
variable `NPM_TRUSTED_PUBLISHING` is `true`, the job runs `npm publish --dry-run` and skips
|
|
411
|
+
the tag and the GitHub Release. One-time setup:
|
|
412
|
+
|
|
413
|
+
1. The package must exist before a trusted publisher can be attached. Publish the first
|
|
414
|
+
version by hand: `npm login`, `npm ci`, `npm run build`, `npm publish --access public`
|
|
415
|
+
(npm asks for 2FA once).
|
|
416
|
+
2. Attach the trusted publisher, allowing direct publishes (2FA once):
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
npm trust github fritzkit --repo pmaxhogan/fritzkit --file release.yml --allow-publish
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
3. Arm the workflow: `gh variable set NPM_TRUSTED_PUBLISHING --body true -R pmaxhogan/fritzkit`.
|
|
423
|
+
|
|
424
|
+
From then on every green push to `main` publishes `fritzkit@0.1.x`, tags `v0.1.x` and
|
|
425
|
+
creates a GitHub Release with the tarball.
|
|
426
|
+
|
|
427
|
+
## License
|
|
428
|
+
|
|
429
|
+
fritzkit itself is MIT (see [LICENSE](LICENSE)). Parts generated with fritzkit are
|
|
430
|
+
released under CC-BY-SA 3.0, the license of Fritzing's own parts library.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** `fritzkit doctor`: what this machine has and lacks. */
|
|
2
|
+
import { type DoctorReport } from "../../core/validate/index.js";
|
|
3
|
+
import type { CommandContext, CommandResult } from "../context.js";
|
|
4
|
+
export declare function doctorCommand(ctx: CommandContext): Promise<CommandResult<DoctorReport>>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** `fritzkit doctor`: what this machine has and lacks. */
|
|
2
|
+
import { doctor, formatDoctor } from "../../core/validate/index.js";
|
|
3
|
+
export async function doctorCommand(ctx) {
|
|
4
|
+
const report = await doctor({ env: ctx.env, ...(ctx.doctorOptions ?? {}) });
|
|
5
|
+
return { exitCode: report.ok ? 0 : 1, text: formatDoctor(report), data: report };
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,OAAO,EAAE,MAAM,EAAE,YAAY,EAAqB,MAAM,8BAA8B,CAAC;AAGvF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAmB;IACrD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IAC5E,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACnF,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type InstallResult } from "../../core/export/install.js";
|
|
2
|
+
import { type Issue } from "../../core/validate/index.js";
|
|
3
|
+
import { type CommandContext, type CommandResult } from "../context.js";
|
|
4
|
+
export interface ExportOptions {
|
|
5
|
+
out?: string;
|
|
6
|
+
install?: boolean;
|
|
7
|
+
/** Export (and install) even when the structural validator reports errors. */
|
|
8
|
+
force?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface ExportData {
|
|
11
|
+
moduleId: string;
|
|
12
|
+
fzpz: string;
|
|
13
|
+
issues: Issue[];
|
|
14
|
+
installed?: Pick<InstallResult, "installedDir" | "alreadyInstalled" | "files" | "warnings">;
|
|
15
|
+
}
|
|
16
|
+
export declare function exportCommand(part: string, opts: ExportOptions, ctx: CommandContext): Promise<CommandResult<ExportData>>;
|
|
17
|
+
export declare function installCommand(part: string, opts: Omit<ExportOptions, "install">, ctx: CommandContext): Promise<CommandResult<ExportData>>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/** `fritzkit export <part> [--out] [--install] [--force]` and `fritzkit install <part>`. */
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { writeFzpz } from "../../core/export/fzpz.js";
|
|
4
|
+
import { FritzingRunningError, installPart, } from "../../core/export/install.js";
|
|
5
|
+
import { formatIssues, validateCompiled, validateFzpzFile, } from "../../core/validate/index.js";
|
|
6
|
+
import { CliError, cwdOf, EXIT_FRITZING_RUNNING, fritzingPathsFor, fritzingRunningMessage, isRunningOf, resolveTarget, } from "../context.js";
|
|
7
|
+
import { compileDir, warningIssues } from "./validate.js";
|
|
8
|
+
async function install(source, fzpz, ctx) {
|
|
9
|
+
try {
|
|
10
|
+
return await installPart(source, {
|
|
11
|
+
paths: fritzingPathsFor(ctx.env),
|
|
12
|
+
isRunning: isRunningOf(ctx),
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
if (e instanceof FritzingRunningError) {
|
|
17
|
+
throw new CliError(`${fritzingRunningMessage("install")}\nThe .fzpz is ready at ${fzpz}.`, EXIT_FRITZING_RUNNING);
|
|
18
|
+
}
|
|
19
|
+
throw e;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export async function exportCommand(part, opts, ctx) {
|
|
23
|
+
if (opts.out !== undefined && !/\.fzpz$/i.test(opts.out)) {
|
|
24
|
+
throw new CliError(`--out must name a .fzpz file (got "${opts.out}")`);
|
|
25
|
+
}
|
|
26
|
+
const target = await resolveTarget(part, ctx);
|
|
27
|
+
let moduleId;
|
|
28
|
+
let fzpz;
|
|
29
|
+
let issues;
|
|
30
|
+
let source;
|
|
31
|
+
if (target.kind === "fzpz") {
|
|
32
|
+
if (!opts.install) {
|
|
33
|
+
throw new CliError(`${target.path} is already a .fzpz; use \`fritzkit install\` to install it`);
|
|
34
|
+
}
|
|
35
|
+
issues = validateFzpzFile(target.path);
|
|
36
|
+
fzpz = target.path;
|
|
37
|
+
source = target.path;
|
|
38
|
+
moduleId = "";
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const compiled = await compileDir(target.dir, ctx);
|
|
42
|
+
moduleId = compiled.identity.moduleId;
|
|
43
|
+
issues = [...validateCompiled(compiled), ...warningIssues(compiled.warnings)];
|
|
44
|
+
fzpz = opts.out ? resolve(cwdOf(ctx), opts.out) : join(target.dir, `${moduleId}.fzpz`);
|
|
45
|
+
source = compiled;
|
|
46
|
+
}
|
|
47
|
+
const errors = issues.filter((i) => i.level === "error");
|
|
48
|
+
if (errors.length > 0 && !opts.force) {
|
|
49
|
+
return {
|
|
50
|
+
exitCode: 1,
|
|
51
|
+
text: `${formatIssues(issues)}\nnot exported: fix the errors above or pass --force`,
|
|
52
|
+
data: { moduleId, fzpz: "", issues },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const lines = [];
|
|
56
|
+
if (issues.length > 0)
|
|
57
|
+
lines.push(formatIssues(issues));
|
|
58
|
+
if (target.kind === "dir") {
|
|
59
|
+
await writeFzpz(source, fzpz);
|
|
60
|
+
lines.push(`wrote ${fzpz}`, `moduleId ${moduleId}`);
|
|
61
|
+
}
|
|
62
|
+
const data = { moduleId, fzpz, issues };
|
|
63
|
+
if (opts.install) {
|
|
64
|
+
const r = await install(source, fzpz, ctx);
|
|
65
|
+
data.moduleId = r.moduleId;
|
|
66
|
+
data.installed = {
|
|
67
|
+
installedDir: r.installedDir,
|
|
68
|
+
alreadyInstalled: r.alreadyInstalled,
|
|
69
|
+
files: r.files,
|
|
70
|
+
warnings: r.warnings,
|
|
71
|
+
};
|
|
72
|
+
if (target.kind === "fzpz")
|
|
73
|
+
lines.push(`moduleId ${r.moduleId}`);
|
|
74
|
+
lines.push(...r.warnings.map((w) => `warning: ${w}`), `${r.alreadyInstalled ? "re-installed" : "installed"} to ${r.installedDir}`, "start Fritzing: the part is in the My Parts bin (search for its title)");
|
|
75
|
+
}
|
|
76
|
+
return { exitCode: 0, text: lines.join("\n"), data };
|
|
77
|
+
}
|
|
78
|
+
export function installCommand(part, opts, ctx) {
|
|
79
|
+
return exportCommand(part, { ...opts, install: true }, ctx);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../../src/cli/commands/export.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type CommandContext, type CommandResult } from "../context.js";
|
|
2
|
+
export declare function importKicadCommand(file: string, opts: {
|
|
3
|
+
slug: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
}, ctx: CommandContext): Promise<CommandResult<{
|
|
6
|
+
slug: string;
|
|
7
|
+
dir: string;
|
|
8
|
+
partJson: string;
|
|
9
|
+
pins: number;
|
|
10
|
+
}>>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** `fritzkit import-kicad <file.kicad_mod> --slug <slug> [--title <t>]`. */
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { importKicadFile } from "../../core/kicad/index.js";
|
|
4
|
+
import { partDir, SCHEMA_URL } from "../../core/workspace.js";
|
|
5
|
+
import { cwdOf, workspaceOf } from "../context.js";
|
|
6
|
+
import { createPartFolder } from "./parts.js";
|
|
7
|
+
export async function importKicadCommand(file, opts, ctx) {
|
|
8
|
+
const dir = partDir(workspaceOf(ctx), opts.slug);
|
|
9
|
+
const fragment = await importKicadFile(resolve(cwdOf(ctx), file), {
|
|
10
|
+
slug: opts.slug,
|
|
11
|
+
...(opts.title ? { title: opts.title } : {}),
|
|
12
|
+
});
|
|
13
|
+
const raw = { $schema: SCHEMA_URL, ...fragment };
|
|
14
|
+
const { partJson } = await createPartFolder(dir, raw);
|
|
15
|
+
const pins = raw.pins?.length ?? 0;
|
|
16
|
+
return {
|
|
17
|
+
exitCode: 0,
|
|
18
|
+
text: `created ${partJson} (${pins} pad${pins === 1 ? "" : "s"})\nnext: name the pins, then run: fritzkit validate ${opts.slug}`,
|
|
19
|
+
data: { slug: opts.slug, dir, partJson, pins },
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=kicad.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kicad.js","sourceRoot":"","sources":["../../../src/cli/commands/kicad.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,KAAK,EAAE,WAAW,EAA2C,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAY,EACZ,IAAsC,EACtC,GAAmB;IAEnB,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE;QAChE,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7C,CAAC,CAAC;IACH,MAAM,GAAG,GAAkB,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,QAAQ,EAAE,CAAC;IAChE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC;IACnC,OAAO;QACL,QAAQ,EAAE,CAAC;QACX,IAAI,EAAE,WAAW,QAAQ,KAAK,IAAI,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,uDAAuD,IAAI,CAAC,IAAI,EAAE;QAChI,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE;KAC/C,CAAC;AACJ,CAAC"}
|