# SynapsCAD parses OpenSCAD without running OpenSCAD, and admits compatibility is partial

> A Rust IDE that evaluates OpenSCAD source through its own parser and an exact CSG stack, keeping every numeric literal in a hyperreal type rather than converting to floating point. It also has an AI editing loop, ten provider integrations, and a documented prototype status it asks you to hold against.

**timschmidt/synaps-cad** — The AI-powered 3D CAD IDE — edit code, visualize in 3D, and reshape your designs with natural language.

- Repository: https://github.com/timschmidt/synaps-cad
- Stars: 370 · Forks: 24
- Language: Rust
- License: NOASSERTION
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/timschmidt-synaps-cad

## Compatibility is incomplete, and the project says so before you install

The caveat is in a blockquote near the top, before the feature list, and it is unusually specific about what kind of bug report is useful.

SynapsCAD is an early prototype. OpenSCAD compatibility is incomplete, and concise bug reports with a reproducing source file are welcome.

The second half is the useful instruction. A compatibility gap in a compiler front end is only actionable if it comes with the input that produces it, so asking for a reproducing source file rather than a description is the difference between a fixable report and a dead end.

The underlying reason for the incompleteness is architectural and is stated plainly elsewhere: SynapsCAD parses and evaluates OpenSCAD source without invoking the OpenSCAD executable. That is the whole premise. You are not wrapping a reference implementation, you are reimplementing the language, and a reimplementation of a language this size is going to have gaps.

It also ships a compatibility corpus. The directory holding it originates from OpenSCAD itself, and a script regenerates the bounding box and mesh count references the corpus tests compare against, using an installed OpenSCAD command line to produce them. So the gaps are measured rather than asserted, which is a stronger position than an early prototype normally manages.

## Every numeric literal stays exact, and floats are deferred to four places

This is the design decision that separates the project from every other OpenSCAD-compatible tool.

Every OpenSCAD numeric literal is parsed directly into the project's hyperreal real number type, with no intermediate floating point conversion. Decimal and scientific literals, fractions, arithmetic and math functions therefore keep exact rational or symbolic structure automatically. There is no precision setting, because there is no place where precision is lost.

What that buys is visible in the example the documentation gives. A variable is set to a third, and it is then used as a cube dimension alongside a two fifths and a three sevenths. Under a floating point evaluator those are approximations with error accumulated through the arithmetic. Here they are exact rationals, so the cube dimensions are what they say they are.

The language surface that operates on those values is wide: the standard degree-based trigonometric functions, inverse trigonometry, roots, exponentials, logarithms, powers, rounding, vector functions, primitive dimensions, polygons, polyhedra, text metrics, affine transformations, offsets and extrusion parameters.

And the escape hatch is enumerated rather than hidden. Primitive float approximation is deferred to four explicit boundaries: display colour, mesh buffers, exports, and third party file formats. So exactness holds everywhere it can and is given up only where a float is genuinely required.

## The compiler is a library first, and the IDE is a consumer of it

The entry point is a function, and its signature tells you what the design prioritises.

`compile_scad_code` takes source text, an optional global function definition override, and an optional atomic cancellation flag. It returns a result type that distinguishes three cases rather than two: success carrying the meshes, previews and warnings; an error; and cancellation.

That third variant is the interesting one. A cancellation flag on a compilation entry point matters when compilation happens on a background task that a user can cancel, which is exactly what the architecture describes. An evaluator that cannot be interrupted turns every cancel into a wait for the slowest possible compile.

The other types are named rather than implied. There is mesh data as an indexed triangle mesh in the engine's Y-up coordinate system, and a view type holding a labelled base64 encoded PNG preview. There is a convenience wrapper for callers who want previews but not meshes or recoverable warnings. There is the lower level evaluator and its runtime value type. There is a function that renders previews from mesh data that already exists. And there is the default scene loaded into a new workspace.

The binary and the library share the same pipeline, so there is no gap between what the IDE shows and what the library returns.

## The web build drops persistence, clipboard capture and model export

The architecture table names six layers and their main entry points, and then the paragraph after it is where the interesting constraint lives.

The engine owns the main thread. Native compilation and AI work run in background tasks and communicate through nonblocking channels, and the web build uses browser local tasks for the same purpose.

Then the omissions, listed in one sentence: the web target omits native persistence, clipboard image capture, and model export.

Those three are exactly the capabilities that need a filesystem, and naming them together tells you the web build is a viewer and editor rather than a full replacement for the desktop application. Your work is not saved to disk, you cannot grab an image out of the viewport to the system clipboard, and you cannot export a model file from the browser.

For a hosted demo, which is what the project publishes, that is the right trade. For actual modelling work it is the boundary that decides whether you use the desktop build, and it is worth knowing before you start sketching a design in a browser tab.

## Ten providers, and the browser has to be allowed to reach them

The provider table is long enough to be worth reading as a compatibility statement rather than a feature list.

There are ten entries. Nine read a key from an environment variable: Anthropic, OpenAI, Gemini, Groq, DeepSeek, Cohere, Fireworks, Together, xAI and ZAI. The tenth is Ollama, which reads no key because it runs locally.

The first entry has its own note. Ollama works locally without a key, and desktop cloud providers read those variables, which can also be set in the application's AI settings rather than only in the environment.

The sentence that will cost you an afternoon is about the browser: requests are sent directly, so a provider must permit browser cross origin requests, or be reached through an appropriate proxy. Most hosted model APIs do not send permissive cross origin headers for arbitrary origins, so the browser build and the desktop build have different practical provider support even though the table lists the same ten.

So the list is a capability table for the desktop application and an aspiration list for the web one. The AI layer in the architecture table reflects the same split, using a Rust client library natively and browser HTTP requests on the web.

## The dependencies are path references to sibling checkouts

The manifest is where the project's real constraints show, and it starts with a licence field that offers two options rather than picking one.

The licence is MIT or Apache-2.0, so downstream users choose. There is also a published flag set to false, which is consistent with the note that the crate is not yet published and downstream users should use a Git or path dependency for now.

Then the dependencies that shape how you set up. The geometry crate is a path reference to a sibling checkout, and a commented line beneath it shows the equivalent registry version a release could switch to. The hyperreal and hyperlattice crates are also path references. The parser is a path reference too, with the same pattern: use the sibling checkout while exact literal support is being developed, and the commented line shows what a release would use instead.

The quick start in the README says the same thing in one sentence: clone this repository beside the hyper dependencies named in the manifest.

That is a real cost to adopting this for a library user. You are not adding one crate, you are checking out a family of sibling repositories, and until releases switch to registry versions there is no published artifact to depend on.

## The CI checks are a fmt, a clippy, a script and a release build

The native checks are four commands, and the strictness is visible in the flags:

```sh
cargo fmt --all -- --check
cargo clippy --locked -- -D warnings
.github/scripts/test-ci.sh
cargo build --locked --release
```

Formatting is checked across the workspace. Linting runs with the lock file enforced and warnings promoted to errors, so a lint warning fails the build rather than scrolling past. Then a script under the GitHub directory runs the tests. Then a release build with the lock file enforced.

The two lock file flags are the part worth noting. Building without honouring the lock file in a project with exact arithmetic at its core would undermine the guarantee, so the lock is enforced twice.

The web build has its own constraint that is stated precisely: use the exact binding generator version recorded in the lock file. A mismatched generator version produces a module that the runtime rejects, and the lock file is the record of which version that is. The script creates and validates the output directory rather than assuming the build produced something usable.

There is also an end to end compiler benchmark, run from a named bench target, whose workload is selected by four environment variables covering the scene, the input file, a function override, and an iteration count.

## Unsigned macOS builds need a quarantine attribute removed by hand

Prebuilt artifacts are published for Linux, macOS and Windows on the releases page, which removes the build step from the evaluation loop.

The macOS caveat is specific and the fix is given as a command. Unsigned macOS builds may need their quarantine attribute removed, after the user has verified the download.

The ordering in that sentence is the instruction. Verify first, then remove the attribute. Removing quarantine is what disables the warning macOS shows for an unnotarised application, so doing it reflexively would suppress the only signal that the binary was not signed by a developer you can identify.

The releases themselves are pre 1.0, with the tag history showing patch releases inside a minor series rather than a stable line, and the manifest version sits one patch above the most recent tag. So the prebuilt path and the source path will occasionally differ slightly, which is worth knowing if you are comparing behaviour between them.

Two licence files sit at the repository root alongside the manifest's dual field, and there is a separate releasing document, which suggests the release process is written down rather than folklore.

## Conclusion

Use SynapsCAD if you write OpenSCAD, want a Rust compiler for it you can call as a library, and care that a literal like 1/3 stays exact rather than becoming a float. The hyperreal evaluator and the exact boolean stack are the substantive parts, and the compiler crate is the more durable artefact compared with the IDE around it. Do not plan on full OpenSCAD compatibility, since the project calls itself an early prototype, says compatibility is incomplete, and asks for concise bug reports with a reproducing source file. Four things to check before you commit. Whether you have sibling checkouts, because the parser and geometry crates are path dependencies rather than registry ones and the README tells you to clone beside them. Whether you want native or web, since the web target drops native persistence, clipboard image capture and model export. Whether your AI provider permits browser requests, since the browser build sends them directly and needs cross origin permission or a proxy. And how far you trust exact arithmetic in your models, since primitive float approximation is deliberately deferred to display colour, mesh buffers, exports and third party file formats. Licence is MIT or Apache-2.0 at your choice, and the last push to main is dated 25 July 2026.

## FAQ

### What is timschmidt/synaps-cad?

It is a Rust OpenSCAD IDE and exact CSG compiler with interactive 3D visualisation. It parses and evaluates OpenSCAD source without invoking the OpenSCAD executable, presents the result in a Bevy viewport, exports STL, OBJ and 3MF, and can ask local or hosted language models to revise the current design. The compiler is also available as a Rust library.

### Does SynapsCAD handle exact arithmetic?

Every OpenSCAD numeric literal is parsed directly into a hyperreal real number type with no intermediate floating point conversion, so fractions, arithmetic and math functions keep exact rational or symbolic structure. Primitive float approximation is deferred to four boundaries: display colour, mesh buffers, exports and third party file formats.

### Is SynapsCAD fully compatible with OpenSCAD?

No. The project calls itself an early prototype and says compatibility is incomplete, asking for concise bug reports with a reproducing source file. A compatibility corpus originating from OpenSCAD is included, with a script that regenerates bounding box and mesh count references from an installed OpenSCAD CLI.

### Can I use the SynapsCAD compiler as a Rust library?

The crate is not yet published, so downstream users should use a Git or path dependency. The manifest sets publish to false, and the parser, geometry and hyperreal dependencies are sibling path checkouts rather than registry versions, so you clone the family of repositories beside each other. Licence is MIT or Apache-2.0 at your choice.

### What can the SynapsCAD web build not do?

The web target omits native persistence, clipboard image capture and model export. It uses browser local tasks where the native build uses background tasks with nonblocking channels, and AI requests go directly from the browser, so a provider must permit browser cross origin requests or be reached through a proxy.

## Sources

- [Issues](https://github.com/timschmidt/synaps-cad/issues)
- [README](https://github.com/timschmidt/synaps-cad/blob/main/README.md)
- [Releases](https://github.com/timschmidt/synaps-cad/releases)
- [timschmidt/synaps-cad on GitHub](https://github.com/timschmidt/synaps-cad)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/timschmidt-synaps-cad
