Agent Skills › ghbalf/freecad-ai

ghbalf/freecad-ai

GitHub

分析指定技能的SKILL.md,自动生成VALIDATION.md校验规则草稿。需人工复核体积公式、主体标签及容差,确保校验准确无误。

4 skills 366

Install All Skills

npx skills add ghbalf/freecad-ai --all -g -y
More Options

List skills in collection

npx skills add ghbalf/freecad-ai --list

Skills in Collection (4)

分析指定技能的SKILL.md,自动生成VALIDATION.md校验规则草稿。需人工复核体积公式、主体标签及容差,确保校验准确无误。
用户请求为技能生成校验文件 输入指令 /create-validation
skills/create-validation/SKILL.md
npx skills add ghbalf/freecad-ai --skill create-validation -g -y
SKILL.md
Frontmatter
{
    "name": "create-validation",
    "description": "Generate a draft VALIDATION.md for a skill by analyzing its SKILL.md construction steps"
}

Create Validation Rules

Generate a draft VALIDATION.md file for a skill by analyzing its SKILL.md.

WARNING — READ THIS FIRST

This skill generates a DRAFT, not a finished product. The generated VALIDATION.md will likely contain errors, especially in volume formulas. You MUST:

  1. Review every check — does it match what the skill actually builds?
  2. Verify all volume formulas by hand — volume calculations for complex geometry (shells with posts, lips, ridges) are easy to get wrong. Calculate the expected volume for one set of dimensions and compare with the formula.
  3. Test with --validate — run the skill with known-good parameters and --validate to see if the checks pass on correct geometry.
  4. Adjust tolerances — the defaults (0.5mm for bbox, 5% for volume) may be too tight or too loose for your skill.
  5. Check conditional rules — if your skill has variants, verify each when block covers the right checks.

Common errors in generated VALIDATION.md:

  • Volume formulas that forget to add/subtract features (posts, holes, lips, ridges)
  • Wrong body labels (FreeCAD may rename bodies)
  • Missing conditional branches for skill variants
  • Tolerances that are too tight for the geometry complexity

How to use

/create-validation skill-name

Where skill-name is the name of an existing skill (e.g., enclosure, gear).

What to do

  1. Read the specified skill's SKILL.md using execute_code:

    import os
    skills_dirs = [
        os.path.expanduser("~/.config/FreeCAD/FreeCADAI/skills"),
    ]
    # Also check built-in skills
    builtin = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "skills") if '__file__' in dir() else ""
    

    Or use get_document_state context to find the skill path.

  2. Analyze the SKILL.md to extract:

    • Parameters: from the "Parameters to extract" section. Note types and defaults.
    • Bodies: from create_body instructions. Note their labels.
    • Geometry steps: pad dimensions, pocket depths, post positions, etc.
    • Variants: different lid types, optional features, conditional construction steps.
  3. Generate VALIDATION.md with this structure:

# Validation Rules

## Parameters
(one line per parameter: name: type = default)

## Checks

### Body count
- total_bodies: N

### BodyLabel
- exists: true
- bbox: X_expr, Y_expr, Z_expr (tolerance 0.5)
- volume: formula (tolerance 5%)
- solid_count: 1
- valid_solid: true

#### when variant_param == "value"
- (variant-specific checks)
  1. Write the file to the skill directory as VALIDATION.md.

  2. IMPORTANT: After writing, display this message to the user:

Draft VALIDATION.md created. This is a starting point, NOT a finished file.

You must verify:

  • All volume formulas — calculate expected values by hand for at least one set of dimensions
  • Body labels match what FreeCAD actually creates (use get_document_state after running the skill)
  • Conditional when blocks cover all variants
  • Tolerances are appropriate (0.5mm bbox, 5% volume are defaults)

Test it: Run /skill-name args --validate to check against actual geometry.

Fix it: Edit the VALIDATION.md directly if checks fail on correct geometry.

Rules for generating volume formulas

  • Rectangular shell (box with hollow interior): L*W*H - (L-2*T)*(W-2*T)*(H-T)
    • This gives 4 walls + floor, open top
  • Cylindrical posts added to interior: + N * pi * R**2 * post_height
    • N = number of posts, R = post radius
  • Cylindrical holes subtracted: - N * pi * R**2 * depth
  • Solid slab (lid): L * W * T
  • Lid with lip: lip volume + slab volume
  • Use pi constant, not 3.14159 (the expression evaluator supports pi)
  • Use ** for power, not ^ (the evaluator uses Python's ast module)

Available check types

Check Value format When to use
exists: true Always, for each body
bbox: X, Y, Z (tolerance 0.5) Expressions, absolute mm Always, for each body
volume: expr (tolerance 5%) Expression, relative % When geometry has calculable volume
solid_count: N Integer Always (usually 1 per body)
valid_solid: true Always, for each body
total_bodies: N Integer Once, at document level
has_holes: N Integer When through-all pockets expected
has_feature: "Name" String When specific named features expected
min_children: N Integer When minimum feature count matters

Parameter type reference

Type Default syntax Example
float = 2.5 T: float = 2
int = 4 count: int = 4
str = value lid_type: str = screw
bool = false add_vents: bool = false
自动优化 FreeCAD AI 技能的 SKILL.md。通过运行测试用例、评估结果并利用 LLM 迭代改进指令,直至分数收敛或达到最大迭代次数,同时备份原始版本以确保安全。
用户输入 /optimize-skill 命令 用户输入 /optimize-skill skill-name 并指定技能名称
skills/optimize-skill/SKILL.md
npx skills add ghbalf/freecad-ai --skill optimize-skill -g -y
SKILL.md
Frontmatter
{
    "name": "optimize-skill",
    "description": "Automatically optimize a skill's SKILL.md by running test cases, scoring results, and iteratively improving instructions"
}

Skill Optimizer

Optimizes a FreeCAD AI skill by iteratively running it against test cases, evaluating the results, and using the LLM to improve the SKILL.md instructions.

Inspired by autoresearch.

Usage

Type /optimize-skill to open the configuration dialog, or /optimize-skill skill-name to pre-select a skill.

How It Works

  1. Select a skill and define test cases
  2. The optimizer runs each test case, collects metrics (errors, completions, measurements)
  3. The LLM analyzes failures and modifies the SKILL.md
  4. Repeat until the score converges or iterations are exhausted
  5. The best version is saved; the original is always backed up
将图像转换为FreeCAD草图,识别几何形状并生成等效2D草图。需用户提供尺寸、平面和主体名称,支持矩形、圆形等形状提取与缩放,输出JSON后调用工具创建草图。
用户要求从图像创建草图 用户希望基于视觉参考开始CAD工作
skills/sketch-from-image/SKILL.md
npx skills add ghbalf/freecad-ai --skill sketch-from-image -g -y
SKILL.md
Frontmatter
{
    "name": "sketch-from-image",
    "description": "Extract 2D geometry from an attached image and create a FreeCAD sketch from it."
}

Sketch from Image

Convert an image (drawing, sketch, reference photo, technical drawing) into a FreeCAD sketch by identifying its geometric shapes and creating a sketch with equivalent geometry.

When to use

  • User has attached an image and says "create a sketch from this", "trace this shape", "make a sketch of this", or similar.
  • User wants a starting point for CAD work from a visual reference.

Required user inputs (ask if missing)

  1. Bounding size in mm — the real-world size the sketch should occupy. Ask as: "What size (in mm) should this sketch be? Provide either the overall width or height." Example: "width 40mm" or "height 25mm".
  2. Plane — default XY if not specified. Accept XY, XZ, YZ.
  3. Body name — if the user wants the sketch on an existing body. Default: no body (standalone sketch).

Do NOT guess the size. Without a real dimension, the sketch is useless for CAD.

Extraction procedure

Look at the attached image (or the textual description if no image is present) and identify the 2D shapes. For each shape, record:

  • Shape type: rect, circle, polygon, or line
  • Position and size, scaled so that the overall bounding box matches the user-provided dimension (width OR height; preserve aspect ratio)

Scaling rule

  1. Measure the image's apparent bounding box in pixels (or relative units).
  2. Compute scale = user_dimension_mm / measured_dimension_pixels.
  3. Multiply every coordinate and radius by scale.
  4. Flip Y-axis if the source uses Y-down (SVG, screen pixels, most image formats). FreeCAD sketches use Y-up. Negate all Y coordinates after scaling.
  5. Translate so the sketch is centered around origin (or anchored at 0,0 — state which).

Shape JSON schema (internal — use this shape before calling the tool)

{
  "shapes": [
    {"type": "rect",    "x": 0, "y": 0, "width": 40, "height": 25},
    {"type": "circle",  "cx": 20, "cy": 12.5, "r": 3},
    {"type": "polygon", "points": [[0,0], [10,0], [5,8]]},
    {"type": "line",    "x1": 0, "y1": 0, "x2": 10, "y2": 10}
  ],
  "dimensions": [],
  "notes": "brief description of what was recognized"
}

The dimensions array is reserved for future use (auto-constraint from measured values in technical drawings). Leave it [] for now.

Output

After deriving the JSON, call create_sketch with the shapes. Do NOT add constraints — rectangles and circles are auto-constrained. Example:

create_sketch(
  plane="XY",
  geometries=[
    {"type": "rectangle", "x": 0, "y": 0, "width": 40, "height": 25},
    {"type": "circle", "cx": 20, "cy": 12.5, "radius": 3}
  ]
)

For line shapes, emit them as polygons with two points, since create_sketch groups connected line segments into a polygon.

After creating the sketch

Briefly report:

  • Shapes created (count per type)
  • Final bounding size
  • Any shapes you couldn't confidently identify — list them so the user can clarify or re-attach a clearer image.

Do NOT pad, pocket, or otherwise extrude the sketch unless the user explicitly asks — this skill only produces the 2D profile.

Iterating on the sketch

If the user wants to adjust the sketch after initial creation, use edit_sketch.

For resizing, moving, or replacing geometry (most common), use clear_all=true and provide the complete updated geometry:

edit_sketch(sketch_name="MySketch", clear_all=true, add_geometries=[
    {"type": "rectangle", "x": 0, "y": 0, "width": 50, "height": 30},
    {"type": "circle", "cx": 6, "cy": 6, "radius": 3}
])

This clears all old geometry and constraints, then adds fresh geometry — no over-constraint issues. The sketch object, plane attachment, and body membership are preserved.

For adding new geometry to existing (e.g. "add a second hole"): edit_sketch(sketch_name, add_geometries=[...])

For changing dimensions (e.g. "make it 50mm wide"): use clear_all=true with updated geometry coordinates — dimensions are auto-constrained from the geometry. Do NOT manually add DistanceX/DistanceY/Radius constraints.

Limitations (mention if relevant)

  • Curves and splines are approximated as polygons; for complex curves the user should trace manually or use a dedicated tracing tool.
  • Dimension lines and annotations in the image are ignored in v1 (will be supported in a future version via the dimensions array).
  • Hidden lines, section lines, and construction lines are treated as regular geometry. If the image uses drafting conventions, warn the user.
用于创建、修改和优化 FreeCAD AI 技能。通过访谈明确意图、参数及边缘情况,生成 SKILL.md 和可选的 handler.py,并支持迭代测试直至用户满意。适用于从零构建或改进现有技能。
用户希望从头创建一个新技能 用户想要更新或优化现有技能 用户希望将工作流保存为可复用的技能 用户说“把这个变成技能”或类似表述
skills/skill-creator/SKILL.md
npx skills add ghbalf/freecad-ai --skill skill-creator -g -y
SKILL.md
Frontmatter
{
    "name": "skill-creator",
    "description": "Create new FreeCAD AI skills, modify existing skills, and iteratively improve them. Use when users want to create a skill from scratch, update or optimize an existing skill, capture a workflow as a reusable skill, or improve an existing skill's instructions. Also trigger when the user says \"turn this into a skill\", \"make a skill for X\", \"save this as a command\", or similar."
}

Skill Creator

A skill for creating new FreeCAD AI skills and iteratively improving them.

At a high level, the process goes like this:

  • Understand what the user wants the skill to do
  • Interview for details — parameters, edge cases, construction approach
  • Write a draft of the skill (SKILL.md + optional handler.py)
  • Test it by running the /command and evaluating the result
  • Improve based on what worked and what didn't
  • Repeat until the user is satisfied

Your job is to figure out where the user is in this process and help them move forward. Maybe they say "I want a skill for X" — help them scope it, write the draft, and test it. Or maybe they already have a skill that needs fixing — jump straight to the improvement loop.

Be flexible. If the user says "just write it, I'll test it myself", do that. If they want to iterate 5 times, do that too.

Communicating with the user

FreeCAD AI users range from experienced CAD engineers to hobbyists who just discovered parametric modeling. Pay attention to context cues — if they use terms like "involute" and "datum plane", match that level. If they say "I want to make a box thing with holes", keep things simple.


Creating a skill

Step 1: Capture intent

Start by understanding what the user wants. The current conversation may already contain a workflow worth capturing (e.g., they say "turn this into a skill"). If so, extract what you can from the conversation — the tools used, the sequence of steps, corrections the user made, dimensions and parameters observed. The user may need to fill gaps, and should confirm before you proceed.

Ask (skip questions they already answered):

  1. What should the skill do? — e.g., "generate a mounting bracket", "create a gear train"
  2. What parameters should the user provide? — dimensions, counts, materials, tolerances
  3. When should someone use this? — what would they type to invoke it?
  4. What's the construction approach? — which FreeCAD operations, in what order?
  5. Are there edge cases? — minimum wall thickness, maximum overhang angle, material constraints
  6. Should it have a Python handler? — for skills that need deterministic logic (calculations, lookups) rather than just LLM instructions

Step 2: Interview and research

Proactively ask about things the user might not think of:

  • Standard dimensions — are there industry standards to reference? (bolt sizes, bearing bores, thread pitches)
  • FreeCAD pitfalls — coplanar boolean failures, unclosed sketches, Revolution crashes with full-circle profiles
  • Parameter validation — what ranges are reasonable? What breaks?
  • Construction order — does the workflow depend on features being created in a specific sequence?

If the current document has relevant objects, inspect them with get_document_state and measure to understand the context.

Step 3: Choose a name

Pick a short, hyphenated name based on what the skill does. Confirm with the user. The skill will live at: ~/.config/FreeCAD/FreeCADAI/skills/<name>/ The user invokes it with /<name>.

Step 4: Write the SKILL.md

Anatomy of a skill

skill-name/
├── SKILL.md          (required — instructions injected into LLM prompt)
├── handler.py        (optional — Python handler with execute(args) function)
└── references/       (optional — additional docs loaded as needed)
    ├── dimensions.md
    └── materials.md

Progressive disclosure

Skills use a layered loading system:

  1. Name + first line — always visible in the skills list (~10 words)
  2. SKILL.md body — loaded when the skill is invoked (<200 lines ideal)
  3. References — loaded on demand when the skill tells the LLM to read them

Keep SKILL.md under 200 lines. If you need more detail (dimension tables, material properties, multi-variant instructions), put it in references/ and point to it from SKILL.md:

For standard metric thread dimensions, read `references/thread-tables.md`.

SKILL.md structure

A good SKILL.md includes:

  • Title and one-line description
  • Parameters the user should provide (with sensible defaults)
  • Step-by-step construction instructions using the tool calling system
  • Important notes — gotchas, tolerances, material considerations
  • Reference data — standard dimensions, lookup tables (or pointers to reference files)

Writing style

Explain the why behind instructions, not just the what. The LLM is smart — if it understands the reasoning, it can adapt to situations the instructions don't cover explicitly.

Instead of:

ALWAYS use offset=H on the pocket sketch. NEVER pocket from z=0.

Write:

Place the pocket sketch at offset=H (top face of the solid). Pocketing from z=0
creates a hollow that opens upward with no floor — the pocket cuts from the sketch
plane downward into the solid, so starting from the top gives you a proper floor
at the bottom.

More guidance:

  • Be specific about FreeCAD operations — name the exact tool, feature type, and property names
  • Include default values — so the user can invoke with minimal arguments
  • Use the tool namescreate_sketch, pad_sketch, pocket_sketch, etc. The LLM knows all 33 tools
  • Warn about pitfalls — but explain why they're pitfalls, not just "don't do this"

Step 5: Write handler.py (optional)

If the skill benefits from a Python handler, write one with an execute(args) function:

def execute(args):
    """
    Args:
        args: string with the user's arguments after the /command

    Returns:
        dict with one of:
          {"inject_prompt": "text"} — inject into LLM prompt
          {"output": "text"} — display directly to user
          {"error": "text"} — show error
    """

Use a handler when the skill needs:

  • Calculations (gear tooth profiles, thread geometry, stress analysis)
  • Lookup tables that are easier in Python than in prose
  • File I/O (reading templates, writing config)
  • Validation of user parameters before sending to the LLM

Step 6: Save the files

Use the execute_code tool to create the skill directory and write the files:

import os
skill_dir = os.path.expanduser("~/.config/FreeCAD/FreeCADAI/skills/<name>")
os.makedirs(skill_dir, exist_ok=True)

with open(os.path.join(skill_dir, "SKILL.md"), "w") as f:
    f.write(skill_md_content)

# Optional:
with open(os.path.join(skill_dir, "handler.py"), "w") as f:
    f.write(handler_content)

Tell the user the skill is ready and they can invoke it with /<name>.


Testing and improving

After writing the draft, test it. Come up with 2–3 realistic invocations — the kind of thing a real user would type:

/bracket 80x40mm, 4 mounting holes M4, 3mm thick aluminum
/bracket 30x20mm, 2 holes M3
/bracket — just use defaults

Share them with the user: "Here are a few test cases I'd like to try. Do these look right, or would you change any?"

Then run them one at a time. After each run:

  • Check the result with get_document_state and measure
  • Note what worked and what didn't
  • Ask the user for feedback

How to think about improvements

  1. Generalize from the feedback. The skill will be used many times with different parameters. Don't overfit to the test cases — if a fix only works for one specific set of dimensions, it's probably too narrow. Think about what principle the fix represents and express that in the instructions.

  2. Keep the prompt lean. Remove instructions that aren't pulling their weight. If the LLM is spending time on unnecessary steps, cut them. Read the actual tool call sequence to see where time is wasted.

  3. Explain the why. If you find yourself writing ALWAYS or NEVER in all caps, that's a sign the instruction needs a reason, not more emphasis. Explain why the thing matters and the LLM will follow through more reliably.

  4. Look for repeated patterns. If every test run independently arrives at the same multi-step workaround, that's a signal the skill should include that approach explicitly — or bundle it in a handler.

The iteration loop

  1. Improve the skill based on feedback
  2. Re-run the test cases
  3. Check results, ask user for feedback
  4. Repeat until the user is happy or improvements plateau

Improving an existing skill

If the user already has a skill they want to improve:

  1. Read the current SKILL.md
  2. Ask what's not working — specific failures, edge cases, quality issues
  3. Run it on a few test cases to reproduce the problems
  4. Apply improvements following the same principles above
  5. Re-test and iterate

Reference files

For skills that need reference data (dimension tables, material properties, standard specifications), create a references/ directory alongside SKILL.md. Keep each reference file focused on one topic and under 300 lines. Include a brief table of contents at the top of long files.

Example structure for a fastener skill:

fastener/
├── SKILL.md
└── references/
    ├── metric-bolts.md      # M2–M24 dimensions
    ├── imperial-bolts.md    # #2–1" dimensions
    └── materials.md         # Strength grades, torque specs

Accueil - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-07-17 01:12
浙ICP备14020137号-1 $Carte des visiteurs$