Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.
First time visiting? Here are some places to start:- Looking for a certain topic? Check out the categories filter or use Search (upper right).
- Need support? Ask a question to our Community Support category.
- Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
- Be respectful, on topic and if you see a problem, Flag it.
If you would like to contact our Community Manager personally, feel free to send a private message or an email.
Vibe-coding FeatureScript
karl_mochel
Member Posts: 53 ✭✭
Hi all,
I just finished a FeatureScript feature that lets you import an SVG (as a text blob) and convert it into sketch elements.
https://cad.onshape.com/documents/e37c5dc041b343cb6bde607d/w/f7b0bf8a214658dc31c353f6/e/7217f6a6f01abf2583a1d61c?renderMode=0&uiState=69388fdff20ff15b50aa8344
I created the attached guidelines to use with any LLM to improve its ability to generate appropriate FeatureScript.
Most of the work was done in Claude in the browser, with passes through ChatGPT, Gemini, and Grok, depending on how well they resolved issues, how strategically they thought, and how well they handled different aspects of coding. I also used Cursor for some of the work. All the models failed at some point, which is why I switched among them.
I also use Perplexity for general Onshape questions, development questions, and development environment questions. I mostly do this to separate these productivity questions to one place where I can get back to them, if needed.
In each of these LLMs, I create a space or project where I provide an overview of what I am trying to accomplish and…the guidelines. Also, I save every conversation (that I can remember) to feed an LLM at the end of the project to do a post mortem and generate learnings.
An overview from Notebook LLM from saved conversations:
Developing FeatureScript features for Onshape requires developers to master specific aspects of the language, prioritize performance within its constraints, and understand the unique requirements of CAD geometry modeling.
The primary lessons learned from building complex features like the SVG-to-Sketch converter fall into five categories:
1. FeatureScript Language Quirk and Syntax Strictness
FeatureScript operates with strict rules that differ significantly from common scripting languages:
- Strict Typing and Usage: Explicit parameter and return types are strictly required for all functions. Furthermore, all declarations must be used or removed, otherwise they trigger an error.
- Unsupported Operations: The language does not support many standard operations. For example, developers must manually implement basic helpers, such as a function to retrieve a character at an index (
chAt) and functions for safe digit checking (isDigit), as the core library may lack them. - String Comparison Limitations: FeatureScript strictly prohibits comparing strings using range checks like
>=or<=. Instead, checks must use explicit equality matching or thefind/indexOffunction within a defined whitelist string to check for valid characters or commands. - Variable Declarations: Follow the rule of one variable declaration per line for both
varandconst.
2. Performance Optimization: Avoiding O(n²) String Operations
The most significant performance bottleneck identified in FeatureScript parsing is string concatenation:
- Avoid Concatenation in Loops: Repeatedly building a string inside a loop (
result = result ~ c) leads to O(n²) complexity because a new string is created and copied in every iteration. For large inputs (e.g., a 10,000-character file), this translates to tens of millions of operations. - Use the Array + Join Pattern: The high-performance solution is to accumulate string fragments into an array (
var parts = [];) and then use the built-injoin(parts, "")function once at the end. This reduces the total complexity to the efficient O(n). This is critical for frequently called functions like number and path data parsers.
3. Handling CAD Geometry and Units
CAD modeling in FeatureScript introduces unique requirements for geometry creation and coordinate handling:
- Mandatory Units: Coordinates passed to geometry functions, as well as angles used in trigonometric functions (
cos,sin,atan2), must have explicit units (e.g.,* millimeteror* radian). Plain numbers cannot be used for trigonometric input. - Point Dimensionality: Onshape's sketch functions ultimately expect 3D vectors with a unit definition. The
toMMhelper function must ensure it creates the geometry point as a 3D vector, typically by adding az=0coordinate multiplied by the appropriate unit (vector(x, y, 0) * millimeter). - Coordinate System Inversion: SVG defines geometry using a Y-down coordinate system, while Onshape uses a Y-up system. Correct geometry conversion typically requires negating the Y coordinates during translation.
4. Robust SVG Parsing and Data Handling
Creating a reliable parser requires defensive coding against real-world file formats and FeatureScript's type system:
- Handling Metadata/Tags: Implement robust attribute parsing logic that does not rely on the attribute order. This prevents errors when attributes like
style="..."or other extraneous data appear before critical attributes liked="...". - XML Cleanliness: The parser must explicitly skip XML comments (
<!--...-->) and processing instructions, as the data inside them can otherwise be misinterpreted as elements, causing unexpected behavior. - Line Ending Compatibility: Since FeatureScript's string escape sequences (
"\r") may not reliably recognize Windows carriage return characters (\r), a robust solution involves using a whitelist approach to keep only valid characters (printable ASCII, newline, tab) and drop all other control characters during input preprocessing. - Relative Path Commands: To correctly parse SVG paths using lowercase (relative) commands (e.g.,
m,l,c), the parser must constantly calculate and update the "current position" (cur) based on the previous segment's endpoint.
5. CAD Topological Closure Paradox
Achieving reliably closed profiles in Onshape sketches is notoriously difficult and requires careful handling of the SVG Z command:
- Geometric vs. Topological Closure: Although an SVG path may be geometrically closed (the last point is mathematically identical to the first point), Onshape's sketch solver requires an explicit topological closing entity (a line segment) to recognize the profile as a closed loop.
- The Snapping/Hint Fix: The ideal solution to maintain the highest quality geometry (G1/G2 continuity) is to re-enable "snapping" logic for the final curve/line segment, ensuring the endpoint is mathematically identical to the starting point. Crucially, the script must then always emit a line segment for the Z command, even if it has zero length. This zero-length line acts as the necessary "hint" for the solver to recognize the loop without creating microscopic, non-coincident gaps that lead to continuity errors.
- State Management is Key: Because FeatureScript passes the mutable
Sketchobject by value, any function that adds geometry (emitPath) must return the updated sketch object, and the calling feature logic must reassign this object (sk = result.sketch;). Failure to do this means the finalskSolve()function runs on an incomplete sketch, which remains an open profile.
Comments
I'm impressed that you've been able to get this to work.
I am a little confused by your guide that you're using. For example, your notes say "No regex", but there is support in FeatureScript for regex. I would think there would be good ways to simplify the code a lot using some regex functions.
Here are some sample functions which use regExp in FeatureScript:
I am surprised that there's no built in way to do toLowerAscii. The
if/then/else if/then/else if… in the code seems unfortunate. Seems like there has to be a better way to do that. But it works, which is much better than not having a solution to importing SVG.Simon Gatrall | Product Development Specialist | Open For Work
The other thing I noticed AI doing a lot is cross products and dot products on vectors. Claude loves some clever vector logic. Unfortunately there are already queries and comparison operations baked into the standard library functions that cover the intended use case that they're reaching for so I've got it baked into my instructions that if they think about using either of those vector comparisons they should crack open the query.fs module and go find the appropriate operation instead.
Derek Van Allen | Engineering Consultant | MeddlerDude. That led me down a terrible rabbit hole that could've been solved if only ChatGPT knew what WorldToPlane was… It makes up some many damn functions, but the real ones though... Where's that Drake meme when you need it?
Ramon Yip | glassboard.com
Thanks for sharing the writeup! I've been experimenting with some vibe coding FS too and have gotten things to work, but it's certainly not a panacea, and the code it creates can be quite verbose because it's creating a ton of helper functions and workarounds for things that FS can already handle cleanly. I did a test to see how little code I could actually write myself (or even read and review), and I was able to get something done, but it was fairly painful and solidified to me that this is the wrong approach. The way I'll be using it is more about brainstorming a big-picture logical flow, then helping to create one function at a time that I fully audit, understand, and edit before moving on. That way I can still actually "own" the code if edits are needed. The way I did it in my test means that troubleshooting looks like telling ChatGPT it's still not working and hoping for the best, which takes a lot of iteration and accrues even more complexity as the result can sometimes be a series of band-aids on top of band-aids.
The Onsherpa | Reach peak Onshape productivity
www.theonsherpa.com