FreeCAD Automation is a FreeCAD-backed automation pipeline for CAD generation, TechDraw drawings, inspection, FEM, reporting, and manufacturing-review artifacts.
The repository has two public layers:
- a runtime-backed CLI for CAD, TechDraw, FEM, tolerance, inspection, and reporting
- a plain-Python/Node manufacturing-review layer for DFM, process planning, readiness review, stabilization review, and review-pack artifacts
Validation snapshot:
- verified locally by maintainers on macOS with FreeCAD 1.1.x for
check-runtime,create,draw --bom,inspect,fem, andreport - verified in hosted CI through explicit fast lanes:
test:node:contract,test:node:integration,test:snapshots, andtest:py; hosted CI does not install or launch FreeCAD - verified in repository-owned runtime CI through the
FreeCAD Runtime Smoke (self-hosted macOS)workflow for realcheck-runtime,create,draw --bom,inspect, andreport - experimental or not yet automated for live FreeCAD execution on Windows native, WSL -> Windows FreeCAD, and Linux; those paths remain compatibility paths, not equal-maturity claims
Run fcad check-runtime first on any new machine and before troubleshooting a FreeCAD-backed failure.
Execution model: bin/fcad.js -> lib/runner.js -> scripts/*.py -> scripts/_bootstrap.py -> import FreeCAD for the runtime-backed commands. The manufacturing-review layer uses the same configs and artifacts but often runs under plain python3 without launching FreeCAD.
Config lifecycle:
- user-facing configs are now treated as
config_version = 1 - unversioned configs still load, but
fcademits deprecation warnings when legacy fields are detected - new checked-in examples should be explicit canonical v1 unless they intentionally exist as compatibility fixtures
fcad validate-config <path>validates user-facing config shape and migration statefcad migrate-config <path> [--out <file>]writes a versioned config plus a change summary- supported config fields, compatibility aliases, and real example references are documented in docs/config-schema.md
For a first local verification:
npm install
npm link
fcad check-runtime
npm run test:node:contract
npm run test:node:integration
npm run test:snapshots
npm run test:runtime-smokeIf you are reviewing the repository on GitHub:
- Read the infotainment production readiness case study.
- Open the checked-in example artifact set.
- Review the parameter sweep gallery.
- Compare the Korea vs Mexico stabilization example.
- Read the before-vs-after improvement case.
- Skim the readiness report markdown.
- Inspect the example config and the command classification below.
npm run test:node:contract: fast hosted-safe Node contracts for config/runtime path/invocation boundariesnpm run test:node:integration: fast hosted-safe Node integration checks for local API/studio bridge routes, browserless studio and legacy serve smoke, sweep, draw/report service wiring, and rule profilesnpm run test:snapshots: normalized SVG/report snapshot regressionsnpm run test:py: Python 3.11+ lane for non-runtime Python and CLI-adjacent regressionsnpm run test:runtime-smoke: real FreeCAD-backed smoke forcheck-runtime,create,draw --bom,inspect, andreport
Deeper runtime-backed suites are available as npm run test:runtime:model, test:runtime:drawing, test:runtime:analysis, test:runtime:report, test:runtime:integration, and test:runtime:full.
Full details, workflow mapping, and local commands live in docs/testing.md.
The repository now keeps two explicit quality fixtures with different purposes:
configs/examples/ks_bracket.toml: intentional fail-demo for geometry, drawing-quality, and DFM blockers. Use it when you want to prove the gates still catch real issues. Its strict create/draw paths are expected to fail, and its report should stayReady for manufacturing review: No.configs/examples/quality_pass_bracket.toml: strict-pass happy path for the current quality stack. Use it when you want to prove create quality, drawing quality, DFM, and report readiness can all pass without weakening the gates.
Treat ks_bracket as the blocker-rich example and quality_pass_bracket as the clean regression target; they are not interchangeable.
- verified maintainer path: macOS +
FreeCAD.app1.1.x forcheck-runtime,create,draw --bom,inspect,fem, andreport - verified repository-owned runtime CI path: self-hosted macOS smoke for
check-runtime,create,draw --bom,inspect, andreport - verified hosted CI path: Node contract, Node integration, snapshots, and Python lanes without installing or launching FreeCAD
- compatibility paths only today: Windows native, WSL -> Windows FreeCAD, and Linux runtime execution
- parametric 3D model generation from TOML configs
- engineering drawing generation through TechDraw
- model inspection, FEM, tolerance, and PDF report generation
- manufacturability screening, process-plan support, and readiness reporting
- runtime-informed launch stabilization review from supplied runtime JSON
- draft generation of production-engineering standard documents
The repository also includes production-engineering workflows and infotainment-oriented examples, but those should be read as decision-support tooling layered on top of the core automation pipeline.
- Structure review: check wall thickness, connector-side clearance, fastening accessibility, and mounting-boss layout before tooling freeze.
- Process design support: infer rough process sequence, inspection points, and likely bottleneck candidates from geometry and manufacturing assumptions.
- Launch/stabilization support: compare supplied CT, FPY, rework, scrap, downtime, and changeover signals against planning assumptions.
- Quality-risk visibility: surface critical dimensions, quality gates, traceability capture points, and inspection-sensitive features.
- Standard-document support: generate draft process flow, control plan, checksheet, work instruction, and PFMEA seed artifacts.
Outputs are heuristic engineering aids. They are not full production-line simulations or a substitute for engineering sign-off.
This repository can also be presented as a DELMIA-adjacent manufacturing DX portfolio prototype for digital manufacturing, virtual twin review, MES/APS/SCM-aligned context modeling, and AI-assisted manufacturing review guidance.
- It stays additive to the existing FreeCAD + manufacturing-review stack.
- It does not claim official DELMIA or 3DEXPERIENCE API integration.
- New portfolio-facing materials live under:
The intent is to show how the repo's existing review, process-planning, line-planning, quality-linkage, and readiness artifacts can be reframed for manufacturing DX conversations without overclaiming product integration.
If you want Codex to drive the legacy CAD and drawing pipeline as a small orchestrated agent team, use:
Recommended stable starting flow:
fcad create configs/generated/cnc_motor_mount_bracket.toml
fcad draw configs/generated/cnc_motor_mount_bracket.toml --bom
fcad dfm configs/generated/cnc_motor_mount_bracket.toml --strict
fcad tolerance configs/generated/cnc_motor_mount_bracket.toml --recommendThis keeps Codex focused on the existing config -> create -> draw -> dfm -> tolerance/report loop without changing the repository runtime model.
Run fcad check-runtime before any FreeCAD-backed command on a new machine and as the first troubleshooting step for runtime-backed failures. It prints searched candidate paths, the selected runtime, active env overrides, detected FreeCAD/Python details, command classes, and remediation guidance. Add --json when a tool needs the same machine-readable runtime contract that the local API exposes from GET /health.
| Class | Commands | Runtime boundary |
|---|---|---|
| Diagnostics | check-runtime |
does not require FreeCAD to be present |
| FreeCAD-backed | create, draw, inspect, fem, tolerance, report |
requires a working FreeCAD runtime |
| Plain-Python / non-FreeCAD | dfm, review, process-plan, line-plan, quality-risk, investment-review, readiness-pack, readiness-report, pack, stabilization-review, generate-standard-docs, ingest, quality-link, review-pack, review-context, compare-rev, validate, validate-config, migrate-config, serve |
runs without launching FreeCAD; canonical readiness packaging consumes review_pack.json, keeps readiness_report.json as the source of truth, and treats readiness-report <config> as legacy compatibility rather than the flagship path |
| Mixed / conditional | analyze-part, design, sweep |
analyze-part can inspect CAD through FreeCAD when needed; design ends by calling create; sweep stays inside the existing create / cost / fem / report service wrappers selected by the matrix file |
fcad review <config.toml|json>
fcad process-plan <config.toml|json>
fcad process-plan --review-pack <review_pack.json>
fcad line-plan <config.toml|json>
fcad quality-risk <config.toml|json>
fcad quality-risk --review-pack <review_pack.json>
fcad investment-review <config.toml|json>
fcad readiness-pack --review-pack <review_pack.json> --out <readiness_report.json>
fcad readiness-report --review-pack <review_pack.json>
fcad readiness-report <config.toml|json> # legacy compatibility / non-canonical
fcad pack --readiness <readiness_report.json> --out <release_bundle.zip>
fcad stabilization-review <config.toml|json> --runtime <runtime.json>
fcad stabilization-review <baseline_readiness_report.json> <candidate_readiness_report.json>
fcad generate-standard-docs <config.toml|json> --readiness-report <readiness_report.json> [--out-dir <dir>]Use readiness-pack --review-pack ... or readiness-report --review-pack ... for canonical C output. readiness-report <config> remains available only as a legacy compatibility route and should not be treated as canonical D-backed readiness provenance.
mfg-agent is also installed as an alias for the same CLI.
fcad ingest --model <file> [--bom bom.csv] [--inspection inspection.csv] [--quality quality.csv] --out <context.json>
fcad analyze-part <context.json|model.step>
fcad quality-link --context <context.json> --geometry <geometry.json>
fcad review-pack --context <context.json> --geometry <geometry.json>
fcad review-context --model <file> [--bom bom.csv] [--inspection inspection.csv] [--quality quality.csv] --out <review_pack.json>
fcad compare-rev <baseline.json> <candidate.json>Imported STEP / FCStd intake is a bootstrap lane, not reverse-CAD magic.
- Preferred browser entry: Studio on
/or/studio, using the Start workspace import bootstrap gate. - Local API preview route:
POST /api/studio/import-bootstrap - Public goal: bring an existing STEP or FCStd into the review loop safely, quickly, and honestly
- Draft bootstrap artifacts:
import_diagnostics.json,bootstrap_summary.json,draft_config.toml,engineering_context.json,geometry_intelligence.json,bootstrap_warnings.json, andconfidence_map.json - Canonical downstream lineage remains unchanged:
review-context -> review_pack.json -> readiness-pack/readiness-report --review-pack -> readiness_report.json -> generate-standard-docs / pack
Low-confidence import findings stay visible as warnings and review-needed evidence. The bootstrap gate is designed to capture assumptions, allow human correction, and then hand off into the existing canonical review/readiness flow without inventing a parallel product surface.
fcad check-runtime
fcad check-runtime --json
fcad create <config.toml|json> [--strict-quality]
fcad draw <config.toml|json> [--bom] [--strict-quality] [--fail-under <number>]
fcad report <config.toml|json>
fcad inspect <model.step|fcstd> [--manifest-out <path>]
fcad fem <config.toml|json> [--manifest-out <path>]
fcad tolerance <config.toml|json> [--manifest-out <path>]
fcad dfm <config.toml|json> [--manifest-out <path>]
fcad sweep <config.toml|json> --matrix <matrix.toml|json> [--out-dir <dir>]report is still classified as runtime-backed because it runs inside the FreeCAD bundle on macOS even when it falls back from freecadcmd to the bundled FreeCAD Python executable.
--manifest-out <path> is the provenance escape hatch for stdout-heavy commands. It keeps the default human-readable stdout intact while letting tooling capture a stable manifest alongside inspect, fem, tolerance, or dfm.
Major runtime and analysis commands now also emit an additive output manifest named <base>_manifest.json. When a command writes a primary artifact, the output manifest is written beside it. When a command is stdout-first and has no primary artifact, the manifest is written beside the input file by default. The legacy artifact-manifest contract remains available where already documented, including --manifest-out.
fcad create also emits an additive <base>_create_quality.json report when it exports model artifacts. The create output manifest links that report through linked_artifacts.quality_json, and --strict-quality exits non-zero only when the quality report finds blocking export issues.
fcad draw also writes an additive <base>_drawing_quality.json summary beside the existing draw sidecars. It aggregates required-dimension coverage, conflict counts, layout overlap signals, BOM consistency, and traceability coverage into one status block. Default draw still completes with warnings, while --strict-quality exits non-zero when blocking draw-quality issues remain.
fcad report now also writes an additive <base>_report_summary.json beside the PDF. The summary keeps the first-page executive decision fields machine-readable:
overall_status:pass | warning | fail | incompleteoverall_scorewhen enough scored inputs existready_for_manufacturing_review:true | false | nulltop_risksrecommended_actionsinputs_consumedartifacts_referencedblocking_issueswarningsmissing_optional_artifacts
The PDF first page now mirrors those fields as an executive decision summary. It is intentionally honest about partial data:
- missing create/drawing/DFM decision inputs downgrade readiness to
unknown/incomplete - missing optional FEM or tolerance artifacts stay visible as
not_run/not_available, never pass - known upstream create-quality, drawing-quality, or DFM failures are surfaced as blockers instead of being silently repaired by the report step
Representative first-page fields:
Status: FAIL
Score: 78.5
Ready for manufacturing review: No
Top risks: Generated model shape is invalid.; Missing required drawing dimensions: HOLE_DIA.; DFM critical findings: 1.
Recommended actions: Repair the generated model geometry before proceeding to manufacturing review.; Add or map the missing required dimension intent(s): HOLE_DIA.; Increase wall thickness around the drilled feature.
fcad dfm now keeps the legacy checks, summary, and score fields while also emitting an additive issues array for actionable findings. Each non-pass issue can include:
rule_id/rule_nameseverity:critical | major | minor | infostatus:fail | warning | skippedpart_id/part_nameandfeature_id/feature_typewhen knownactual_value,required_value,delta, and matching units when measurableprocess,material,manufacturability_impact,suggested_fix,confidence, andevidence
Representative actionable DFM issue:
{
"rule_id": "DFM-01",
"rule_name": "Minimum wall thickness",
"severity": "critical",
"status": "fail",
"part_name": "thin_wall_part",
"feature_id": "hole1",
"feature_type": "hole",
"actual_value": 0.5,
"actual_unit": "mm",
"required_value": 1.5,
"required_unit": "mm",
"delta": -1.0,
"process": "machining",
"material": "unknown",
"manufacturability_impact": "Thin walls can distort, chatter, or break during manufacturing and reduce part robustness.",
"suggested_fix": "Increase wall thickness by at least 1.0 mm by moving hole 'hole1' inward 1.0 mm, reducing its diameter by 2.0 mm, or switching to a process/material profile that supports the current 0.5 mm wall.",
"confidence": "high",
"evidence": {
"measurement": "wall_thickness",
"hole_id": "hole1",
"wall_mm": 0.5,
"threshold_mm": 1.5
}
}Severity guidance:
critical: likely blocker for the selected manufacturing pathmajor: manufacturable only with meaningful redesign, process change, or closer reviewminor: quality-of-manufacture or robustness improvement recommendedinfo: context or confidence warning that should be reviewed but is not a direct blocker
See docs/output-manifest.md for the unified output-manifest fields, naming rules, and example JSON.
fcad sweep is the initial design-space exploration workflow. It does not create a separate optimization path. Instead, it expands deterministic numeric overrides and executes each variant through the existing service wrappers already used by the CLI.
Current sweep scope:
- numeric leaf overrides only, addressed by paths like
shapes[0].heightorfem.constraints[1].magnitude - discrete
values = [...]lists or inclusiverange = { start, stop, step } - sequential execution with per-variant
effective-config.*andresult.json - aggregate
summary.jsonandsummary.csv - objective summary for min mass, min cost, and FEM stress-threshold pass/fail when those metrics exist
Worked examples:
- docs/examples/parameter-sweep-gallery.md
- configs/examples/sweeps/ks_bracket_geometry_sweep.toml
- configs/examples/sweeps/bracket_fem_load_sweep.toml
Example:
fcad sweep configs/examples/ks_bracket.toml \
--matrix configs/examples/sweeps/ks_bracket_geometry_sweep.toml \
--out-dir output/sweeps/ks_bracket_geometryThe summary files capture exact per-variant runtime. Treat any time estimates in docs as planning guidance, not repository-verified benchmark claims.
fcad validate-config configs/examples/ks_bracket.toml
fcad validate-config configs/examples/ks_bracket.toml --strict
fcad validate-config configs/examples/ks_bracket.toml --json
fcad migrate-config configs/examples/ks_bracket.toml
fcad migrate-config configs/examples/ks_bracket.toml --out output/ks_bracket.v1.tomlvalidate-config checks the user-facing config, reports deprecated fields, and exits non-zero on schema errors. --strict also fails when warnings remain.
migrate-config writes a versioned config file and prints:
- changed fields applied automatically
- deprecated fields still present for compatibility
- manual follow-up when the migration intentionally keeps a legacy field to avoid breaking older flows
Legacy compatibility warnings currently cover:
- missing
config_version - top-level
materialandprocess [[operations]].typeinstead ofop- legacy
[export] step = true/stl = trueflags instead offormats = [...]
Upgrade notes:
- canonical v1 keeps
manufacturing.processandmanufacturing.materialas the preferred home for manufacturing metadata - legacy top-level
processandmaterialstill load today, but migration intentionally keeps them only as compatibility fields - existing sample configs remain valid inputs because
fcadauto-migrates them before command execution - new checked-in examples should default to explicit
config_version = 1plus canonical fields; use legacy-compatible examples only when they are intentionally covering migration/regression behavior - use
fcad migrate-configif you want to check in an explicit v1 config file after reviewing the reported manual follow-up items
The older fcad validate <plan-file> command is unchanged and still validates drawing_plan artifacts rather than user configs.
fcad serve now starts a local/dev-first HTTP API backed by the real Node CLI service layer and the existing Python/FreeCAD runtime path. It also makes FreeCAD Automation Studio the preferred browser UI on /, keeps the direct studio route at /studio, and exposes the API info page at /api.
fcad serve
fcad serve 3100
fcad serve 3100 --jobs-dir output/jobs-devStartup behavior:
- binds to
127.0.0.1only - defaults to port
3000 - stores jobs under
output/jobsunless--jobs-diris provided - keeps the existing CLI/runtime execution path:
POST /jobsschedules work through the same service layer used by the CLI, includingcreate,draw,inspect,report,review-context,compare-rev,readiness-pack,stabilization-review,generate-standard-docs, andpack - browser requests to
GET /now land inFreeCAD Automation Studio GET /apireturns the local API info page in HTML, JSON, or plain text depending onAcceptGET /studioremains the directFreeCAD Automation Studioroute- if
localhostresolves to a different listener on your machine, usehttp://127.0.0.1:<port>explicitly
Studio execution model:
Preview: fast request/response work for Model and Drawing. Preview routes are scratch-safe, keep the current workspace state local, and do not create/jobshistory.Tracked run:POST /api/studio/jobsqueuescreate,draw,inspect,report,compare-rev,readiness-pack,stabilization-review,generate-standard-docs, andpackinto/jobs, while directPOST /jobsJSON requests also coverreview-context.Artifact re-entry:ArtifactsandReviewcan reopen config artifacts inModel, rerun trackedreportfrom config-like artifacts, rerun trackedinspectfrom model artifacts, continuereadiness-packfrom canonicalreview_pack.jsonorrelease_bundle.zip, continuegenerate-standard-docsfrom canonical review/readiness inputs or release bundles, continuepackfrom canonical readiness inputs or release bundles, and stagecompare-revorstabilization-reviewfrom selected baseline/candidate canonical artifacts when both sides are present.- Browser-visible preview payloads are path-redacted too: tracked job payloads, artifact payloads, example payloads, and drawing preview responses all avoid raw filesystem paths.
Phase-3 tracked execution model:
| Concern | Public/browser-facing contract | Internal execution contract |
|---|---|---|
| Job request metadata | GET /jobs and GET /jobs/:id return sanitized request metadata only. Artifact-driven runs expose safe fields such as artifact_ref, source_job_id, source_artifact_id, source_artifact_type, and source_label. Absolute execution paths are stripped or reduced before they reach the browser. |
The raw executor request still persists in each job directory as request.json and remains available to the executor, retry flow, and job-store internals. |
| Queue controls | capabilities.cancellation_supported, capabilities.retry_supported, links.cancel, and links.retry tell the studio when to show queue actions. |
The queue stays in-process and dev-local. There is no distributed worker, forced kill path, or hidden retry daemon. |
| Monitor scope | The shell resumes and polls every queued/running job it knows about, not just a single active run. The jobs badge summarizes active counts, and the jobs center merges monitored jobs with recent history. | Polling still happens one job at a time through GET /jobs/:id, and completion routing is derived from persisted artifacts plus the tracked completion action. |
Queue control behavior:
| Job state | POST /jobs/:id/cancel |
POST /jobs/:id/retry |
|---|---|---|
queued |
Cancels deterministically before execution starts. Returns 200 with the cancelled job record. |
Rejected with 409. Queued jobs are not retry sources. |
running |
Rejected with 409 unless the active executor explicitly reports safe cooperative cancellation support. This phase does not add a forced kill path. |
Rejected with 409. Running jobs are not retry sources. |
succeeded |
Rejected with 409. Terminal successful jobs are immutable history. |
Rejected with 409. Successful jobs are not retry sources. |
failed |
Rejected with 409. Failed jobs stay inspectable as-is. |
Accepted. Returns 202 with a new queued job cloned from the original persisted request and retried_from_job_id pointing at the source job. |
cancelled |
Rejected with 409. Cancelled jobs stay inspectable as-is. |
Accepted. Returns 202 with a new queued job cloned from the original persisted request and retried_from_job_id pointing at the source job. |
Jobs center and completion behavior:
- The shell resumes all queued/running jobs returned by
GET /jobs, then keeps them in a multi-job monitor backed byGET /jobs/:id. - The jobs center surfaces narrow quick actions only:
Open Artifacts,Open Reviewwhen the job is reviewable,Cancelwhencapabilities.cancellation_supportedis true, andRetrywhencapabilities.retry_supportedis true. - Completion routing is artifact-aware:
createanddrawfinish intoArtifacts;reportprefersReviewonly when review-ready outputs exist;inspectprefersReviewonly when review-family results exist or the completion source family is already review-oriented. - If a job settles while other jobs are still active, the shell stays on the current workspace and shows a completion notice with deep-link actions instead of forcing a route jump.
- Selected-job deep links are
#artifacts?job=<job-id>and#review?job=<job-id>. Search-param fallback?job=<job-id>is accepted when those workspaces reopen directly, but unsupported routes ignore selected-job scope.
Endpoints:
GET /GET /apiGET /healthGET /studioPOST /api/studio/validate-configPOST /api/studio/model-previewGET /api/studio/model-previews/:id/modelGET /api/studio/model-previews/:id/parts/:indexPOST /api/studio/drawing-previewPOST /api/studio/drawing-previews/:id/dimensionsPOST /api/studio/jobsPOST /jobsGET /jobsGET /jobs/:idPOST /jobs/:id/cancelPOST /jobs/:id/retryGET /jobs/:id/artifactsGET /jobs/:id/artifacts/:artifactId/contentGET /artifacts/:jobId/:artifactIdGET /artifacts/:jobId/:artifactId/download
Supported job types:
POST /jobs:create,draw,inspect,report,review-context,compare-rev,readiness-pack,stabilization-review,generate-standard-docs,packPOST /api/studio/jobs:create,draw,inspect,report,compare-rev,readiness-pack,stabilization-review,generate-standard-docs,packreview-contextremains a direct/jobsor CLI path today; the Studio bridge does not yet accept raw review-context source-file submissions.
Endpoint usage:
GET /is the preferred browser entrypoint for the studio shell; JSON and text callers can still use/directlyGET /apireturns the local API info page and route discovery payloadGET /healthreturns API liveness plus the same shared runtime diagnostics contract used byfcad check-runtime --jsonPOST /api/studio/model-previewvalidates the current TOML and returns preview-only model assets for the Model workspacePOST /api/studio/drawing-previewreturns the fast sheet-first drawing preview;POST /api/studio/drawing-previews/:id/dimensionspreserves the HTTP edit loop for dimension changes while keeping preview-plan files server-side onlyPOST /api/studio/jobsis the studio bridge route: Model and Drawing submit tracked jobs here, and Studio-safe tracked continuation also covers inspect/report re-entry plus compare, readiness, stabilization, docs, and pack jobs from supported artifact references; canonical readiness-backedgenerate-standard-docscan rehydrate a config-like input automatically when the tracked lineage no longer carries a config copyPOST /jobsaccepts a JSON job request and returns202 Acceptedwith the queued job record forcreate,draw,inspect,report,review-context,compare-rev,readiness-pack,stabilization-review,generate-standard-docs, andpackGET /jobsreturns recent tracked jobs for shell resume and artifact timeline viewsGET /jobs/:idreturns the latest status, sanitized browser-visible request metadata, redacted result/manifest summaries, status history, and logical storage metadataPOST /jobs/:id/canceldeterministically cancels a queued job before the executor claims it; running-job cancellation returns a clear conflict unless the active executor explicitly supports safe cooperative stopPOST /jobs/:id/retrycreates a new queued tracked job from the original persisted internal request, but only when the source job is alreadyfailedorcancelledGET /jobs/:id/artifactsreturns the flattened public artifact list plus redacted manifest data and logical storage file metadataGET /jobs/:id/artifacts/:artifactId/contentis the compatibility alias for older API-shaped artifact opensGET /artifacts/:jobId/:artifactIdopens browser-safe artifact content inline when supportedGET /artifacts/:jobId/:artifactId/downloadforces a download for the same artifact
Request examples:
curl http://127.0.0.1:3000/health
curl -X POST http://127.0.0.1:3000/jobs \
-H 'content-type: application/json' \
-d '{
"type": "create",
"config_path": "configs/examples/ks_bracket.toml"
}'
curl -X POST http://127.0.0.1:3000/jobs \
-H 'content-type: application/json' \
-d '{
"type": "draw",
"config": {
"config_version": 1,
"name": "api_bracket",
"shapes": [
{ "id": "body", "type": "box", "length": 40, "width": 20, "height": 8 }
],
"drawing": { "views": ["front", "top", "right", "iso"] },
"export": { "formats": ["step"], "directory": "output" }
}
}'
curl -X POST http://127.0.0.1:3000/jobs \
-H 'content-type: application/json' \
-d '{
"type": "review-context",
"model_path": "output/example.step"
}'
curl http://127.0.0.1:3000/jobs/<job-id>
curl -X POST http://127.0.0.1:3000/jobs/<job-id>/cancel
curl -X POST http://127.0.0.1:3000/jobs/<job-id>/retry
curl http://127.0.0.1:3000/jobs/<job-id>/artifacts
curl http://127.0.0.1:3000/artifacts/<job-id>/<artifact-id>Studio bridge examples:
curl -X POST http://127.0.0.1:3000/api/studio/model-preview \
-H 'content-type: application/json' \
-d '{
"config_toml": "name = \"preview_bracket\"\n[[shapes]]\nid = \"body\"\ntype = \"box\"\nlength = 40\nwidth = 20\nheight = 8\n"
}'
curl -X POST http://127.0.0.1:3000/api/studio/jobs \
-H 'content-type: application/json' \
-d '{
"type": "report",
"artifact_ref": {
"job_id": "<job-id>",
"artifact_id": "<config-artifact-id>"
}
}'
curl -X POST http://127.0.0.1:3000/api/studio/jobs \
-H 'content-type: application/json' \
-d '{
"type": "pack",
"artifact_ref": {
"job_id": "<job-id>",
"artifact_id": "<readiness-or-release-bundle-artifact-id>"
}
}'
curl -X POST http://127.0.0.1:3000/api/studio/jobs \
-H 'content-type: application/json' \
-d '{
"type": "compare-rev",
"baseline_artifact_ref": {
"job_id": "<baseline-job-id>",
"artifact_id": "<baseline-review-pack-artifact-id>"
},
"candidate_artifact_ref": {
"job_id": "<candidate-job-id>",
"artifact_id": "<candidate-review-pack-artifact-id>"
}
}'The job store is filesystem-backed under output/jobs by default. Each job directory persists:
- request payload
- status transitions
- log output
- effective config when applicable
- artifact files and the manifest used by the executor/job store internally
Response notes:
- JSON API endpoints return JSON; browser-facing routes may return HTML, plain text, redirects, or artifact bytes depending on the route and
Accept - success responses always include
ok: true - error responses always include
ok: falseanderror.codepluserror.messages - job responses sanitize
requestbefore returning it to the browser: tracked artifact re-entry exposes safe metadata such asartifact_ref,source_job_id,source_artifact_id,source_artifact_type, andsource_labelinstead of rawfile_path,config_path, orsource_artifact_path - the raw execution request still persists internally in
request.jsonfor the executor and job-store flows; public job responses are intentionally not a byte-for-byte echo of that internal file - job responses include
retried_from_job_id,capabilities.cancellation_supported,capabilities.retry_supported, andlinks.cancel/links.retryso the studio can surface narrow queue controls without guessing - job responses include a
storageblock with logical file metadata only:storage.files.<name>.existsandstorage.files.<name>.size_bytes. Browser-visible responses do not includestorage.rootor per-filepathfields. - artifact list responses include browser-facing
links.openandlinks.downloadroutes, plus the compatibility alias inlinks.api - public manifest/result/artifact summaries keep stable browser-facing labels only. When internal values were absolute paths, the browser-visible payload reduces them to file names such as
effective-config.jsonorjob.log. /api/examplesreturns checked-in example records as{ id, name, content }and intentionally does not expose repository checkout paths- drawing preview responses expose safe provenance fields such as
preview_referenceandeditable_plan_referenceplus availability booleans and artifact capabilities; they do not exposeplan_path, preview working directories, or other raw preview sidecar paths - successful cancel/retry actions return
ok: true, anactionblock that names the operation and outcome, and the current job record for the cancelled or newly retried job
Browser-visible local API payload shape:
GET /jobsandGET /jobs/:idrequest: sanitized public metadata onlyartifacts: flattened artifact summary with file-name-style values instead of raw filesystem pathsmanifestandresult: browser-safe summaries; any absolute path-like values are redacted to safe labels/file namesstorage:{ files: { job, request, log, manifest } }records withexistsandsize_bytesonly
GET /jobs/:id/artifactsartifacts[*]:id,key,type,scope,stability,file_name,extension,content_type,exists,size_bytes,capabilities, andlinksmanifest: the same redacted browser-safe manifest view used on the job detail routestorage: logical file metadata only; no public filesystem paths
GET /api/examples{ id, name, content }for each checked-in example TOML
POST /api/studio/drawing-previewandPOST /api/studio/drawing-previews/:id/dimensionspreview: browser-safe drawing preview data includingid,preview_reference,editable_plan_referencewhen an editable plan exists,settings,overview,validation,svg,bom,views,scale,qa_summary,annotations,dimensions,editable_plan_available,dimension_editing_available,tracked_draw_bridge_available, andartifact_capabilities- server-only preview sidecars such as
plan_path, preview working directories,run_log, and other path-bearing preview files stay internal - internal preview-plan files remain available server-side where the HTTP dimension-edit loop and tracked-draw preservation need them
Internal executor/job-store payload shape:
request.json,job.json,job.log, andartifact-manifest.jsonremain path-bearing on disk where the executor and retry flow need them- artifact open/download routes still resolve against those internal paths server-side; the routes are public, the paths are not
Current limitations:
- this API is local/dev-first and does not add authentication
- jobs run in-process; there is no distributed queue, retry worker, or database
- queued-job cancellation is supported; running-job cancellation is intentionally rejected unless the active executor can stop work cooperatively and report that honestly
- retry is intentionally narrow and only supported from
failedorcancelledjobs job.logis best-effort and primarily captures orchestration events and stderr surfaced from underlying scriptsGET /jobs/:id/artifactsreports public artifact metadata and links, but it does not inline artifact contents inside the listing responsePOST /jobsandPOST /api/studio/jobsdo not expose every CLI path.review-contextis direct-JSON only today, while browser-native submit flows stay scoped to the tracked review-first and continuation job surface instead of trying to mirror every shell workflow.- preview smoke and legacy serve smoke are browserless HTTP checks only; they do not claim real browser automation or websocket interaction
Studio and legacy shell guide:
Legacy note:
fcad serve --legacy-viewerstill starts the older browser demo shell fromserver.jsnpm run serve:legacycontinues to point at that older shellfcad servenow opens the studio shell at/, keeps/studioas the direct studio route, and moves the API landing page to/api- prompt streaming and the original all-in-one websocket viewer loop still live on the legacy path
- if you need the working all-in-one browser demo, use the legacy viewer commands above until the remaining websocket-only flows are migrated
FAQ:
- If the browser opens
/, that is now the preferred studio shell. Open/apifor the API info page or usefcad serve --legacy-viewerfor the older browser demo UI.
fcad create accepts two canonical config styles.
- Single-part mode: top-level
shapesplus optional top-leveloperations - Assembly mode: top-level
partsandassemblymust both be present - The operation canonical key is
op type -> opis backward compatibility only- Shape aliases are not supported
- Assembly part operations are not identical to single-part operations
Minimal single-part example:
config_version = 1
name = "minimal_block"
final = "body_fillet"
[[shapes]]
id = "body"
type = "box"
length = 40
width = 20
height = 10
[[operations]]
op = "fillet"
target = "body"
radius = 1
result = "body_fillet"
[export]
formats = ["step"]
directory = "output"Minimal assembly example:
config_version = 1
name = "minimal_assembly"
[[parts]]
id = "base"
final = "base_body"
[[parts.shapes]]
id = "base_body"
type = "box"
length = 40
width = 20
height = 10
[[parts]]
id = "pin"
final = "pin_body"
[[parts.shapes]]
id = "pin_body"
type = "cylinder"
radius = 4
height = 20
[assembly]
[[assembly.parts]]
ref = "base"
position = [0, 0, 0]
[[assembly.parts]]
ref = "pin"
position = [20, 10, 0]
[export]
formats = ["step"]
directory = "output"
per_part_stl = trueNotes:
- In single-part mode, the final shape defaults to the last created result unless
finalis set. - In assembly mode, each part can define its own
final. - Assembly mode currently expects top-level
partsandassembly;partsalone does not activate assembly handling. - Assembly part operations currently follow the assembly builder's supported set and are not a drop-in match for every single-part operation.
- When
createexports STEP/STL/BREP artifacts, it also writes<base>_create_quality.jsonwith generated-model geometry, STEP/BREP re-import checks, STL mesh checks, thresholds, warnings, and blocking issues. --strict-qualitykeeps the exported files but fails the command if the quality report status isfail.
Legacy / compatibility note:
- Existing configs that use
typeinside[[operations]]may still load because the normalizer mapstype -> op. - New configs should use
opdirectly and should treattype -> opas compatibility-only behavior.
Real example configs:
- controller_housing.toml: production-readiness single-part model with manufacturing, quality, drawing, and export sections
- bracket_fem.toml: compact FEM-oriented single-part config
- ptu_assembly_mates.toml: assembly config for mates/tolerance-style workflows
Normalized snapshot baselines now live under:
tests/fixtures/snapshots/svg/for TechDraw SVG outputstests/fixtures/snapshots/report/for lightweight readiness-report preview snapshots
Use the standard test:
npm run test:snapshotsUpdate baselines intentionally:
UPDATE_SNAPSHOTS=1 npm run test:snapshots
# or
npm run test:snapshots:updateSnapshot updates are expected when you intentionally change drawing geometry, annotations, report wording, section order, or the representative fixtures themselves.
Snapshot updates are not expected for timestamp churn, runtime-specific absolute paths, UUID-like run IDs, or generated metadata that should normalize away. If a test fails only because of that kind of volatility, fix the normalizer instead of refreshing the baseline.
Review workflow:
- Run
npm run test:snapshots. - Inspect diffs under
tests/fixtures/snapshots/svg/andtests/fixtures/snapshots/report/. - Compare the changed baseline against the source fixture under
tests/fixtures/svg/ortests/fixtures/report/. - Regenerate with
npm run test:snapshots:updateonly after confirming the change is intentional.
The snapshot normalizers strip volatile timestamps, random SVG IDs, absolute paths, UUID-like run IDs, and similar generated metadata while preserving meaningful geometry and structural content changes.
Follow-on design notes for standards/material rule packs and parameter sweep live in docs/standards-and-sweep-roadmap.md.
# 1. Design-stage production engineering review
fcad review configs/examples/infotainment_display_bracket.toml \
--out output/infotainment_display_bracket_product_review.json
# 2. Rough process planning support
fcad process-plan configs/examples/infotainment_display_bracket.toml \
--out output/infotainment_display_bracket_process_plan.json
# 3. Consolidated production-readiness report
fcad readiness-report --review-pack output/infotainment_display_bracket_review_pack.json \
--out output/infotainment_display_bracket_readiness_report.json
# 4. Runtime-informed launch stabilization review
fcad stabilization-review configs/examples/infotainment_display_bracket.toml \
--runtime data/runtime_examples/display_bracket_runtime.json \
--profile configs/profiles/site_korea_ulsan.toml \
--out output/infotainment_display_bracket_stabilization_review.json
# 5. Canonical readiness packaging from review_pack.json
fcad readiness-pack --review-pack output/infotainment_display_bracket_review_pack.json \
--out output/infotainment_display_bracket_readiness_report.json
# 6. Draft production-engineering standard docs from an explicit readiness artifact
fcad generate-standard-docs configs/examples/controller_housing_eol.toml \
--readiness-report output/controller_housing_readiness_report.json \
--out-dir output/controller_housing_standard_docs
# 7. Draft production-engineering standard docs from canonical readiness JSON
fcad generate-standard-docs <matching_config.toml|json> \
--readiness-report <readiness_report.json> \
--out-dir output/standard_docs
# 8. Portable release bundle from canonical readiness JSON
fcad pack --readiness output/controller_housing_readiness_report.json \
--docs-manifest output/controller_housing_standard_docs/standard_docs_manifest.json \
--out output/controller_housing_release_bundle.zipThe canonical readiness workflow produces a JSON report and a Markdown summary that bundle:
- product review
- process plan
- line-layout support pack
- quality / traceability pack
- cost / investment review
- optional runtime-informed stabilization review
- decision summary for production engineering discussion
readiness_report.json is the canonical C artifact for this flow. Markdown, standard-doc manifests, and release-bundle packaging derive from that JSON contract instead of becoming the primary source of truth. The older readiness-report <config> route remains in the CLI as legacy compatibility and should not be used to describe canonical D-backed provenance. generate-standard-docs must consume canonical readiness JSON directly and requires the supplied config and readiness lineage to describe the same part/revision before it will render downstream docs.
For a checked-in example that can be reviewed without running the CLI, see:
- Infotainment production readiness case
- Checked-in example artifact set
- Korea vs Mexico stabilization comparison
- Before-vs-after improvement case
- Checked-in electronics assembly + standard docs example
This case study documents the older config-driven readiness workflow for infotainment-oriented scenarios. The canonical C packaging path on current master is review_pack.json -> readiness-pack/readiness-report --review-pack -> readiness_report.json -> standard docs / release bundle.
configs/examples/infotainment_display_bracket.tomlconfigs/examples/infotainment_display_bracket_before.tomlconfigs/examples/infotainment_display_bracket_after.tomlconfigs/examples/controller_housing.tomlconfigs/examples/controller_housing_eol.tomlconfigs/examples/pcb_mount_plate.tomlconfigs/examples/display_module_support.toml
These examples include manufacturing metadata such as:
- material and process assumptions
- cross-site launch scope
- annual volume and target cycle time placeholders
- connector clearance assumptions
- critical dimensions and quality gates
- automation-candidate notes
- electronics assembly metadata and EOL test assumptions
Runtime/profile examples:
data/runtime_examples/display_bracket_runtime.jsondata/runtime_examples/display_bracket_runtime_mexico.jsonconfigs/profiles/site_korea_ulsan.tomlconfigs/profiles/site_mexico_mty.toml
CLI (fcad / mfg-agent)
|
+-- legacy CAD / drawing / report commands
+-- review-pack workflow
+-- production-readiness workflow
|
+-- intent compiler
+-- DFM checker
+-- cost estimator
+-- product review agent
+-- process planning agent
+-- line layout support agent
+-- quality / traceability agent
+-- cost / investment review agent
bin/fcad.js: unified CLI entrypointsrc/workflows/canonical-readiness-builders.js: canonical D-backed C readiness packaging helperssrc/agents/: manufacturing-engineering agent modulessrc/workflows/readiness-report-workflow.js: legacy config-driven readiness compatibility flowsrc/workflows/standard-docs-workflow.js: draft standard-document generationscripts/dfm_checker.py: DFM manufacturability logicscripts/cost_estimator.py: cost breakdown and comparison logicscripts/intent_compiler.py: part-type inference and drawing-plan strategyschemas/: output contracts for review, process-plan, line-plan, quality-risk, investment-review, readiness-report, stabilization-review, and standard-doc manifests
See production-readiness-refactor.md for the codebase refactoring map.
- Node.js 18+
- Python 3.11+
- FreeCAD 1.1.x for the FreeCAD-backed commands
git clone https://github.com/dooosp/freecad-automation.git
cd freecad-automation
npm install
npm link
fcad check-runtimeResolution order for runtime-backed commands:
FREECAD_PYTHONFREECAD_BINFREECAD_CMDFREECAD_APPFREECAD_DIR(backward-compatible install-root fallback)
If none of those overrides are set, the resolver falls back to platform detection:
- macOS: prefer
FreeCAD.appbundle discovery from/Applications/FreeCAD.app,~/Applications/FreeCAD.app, and PATH-visible bundle/runtime executables - Windows native: look for PATH-visible
FreeCADCmd.exe,freecadcmd.exe, orFreeCAD.exe - WSL: no default bridge guess is assumed; explicit Windows paths are converted with
wslpathwhen available - Linux / other POSIX: look for PATH-visible
FreeCADCmd,freecadcmd,FreeCAD, orfreecad
Use fcad check-runtime or npm run check:runtime as the first troubleshooting step. It shows the resolved runtime, where it came from, which candidates were checked, and which commands are blocked if no runtime is available.
Commands that directly depend on the resolved FreeCAD runtime:
createdrawinspectfemtolerancereport
Conditional runtime usage:
analyze-part: can run from existing context/model metadata without FreeCAD, but uses FreeCAD when it needs live model inspection or STEP feature detectiondesign: generates TOML, then callscreate
Supported inputs for FREECAD_APP, FREECAD_BIN, FREECAD_PYTHON, FREECAD_CMD, and backward-compatible FREECAD_DIR include:
/Applications/FreeCAD.app~/Applications/FreeCAD.app.../FreeCAD.app/Contents.../FreeCAD.app/Contents/Resources.../FreeCAD.app/Contents/Resources/bin- explicit bundle-internal executables such as
.../Contents/MacOS/FreeCADor.../Contents/Resources/bin/python
The resolver canonicalizes those forms back to one FreeCAD.app bundle root, then derives:
- GUI launcher:
Contents/MacOS/FreeCAD - headless/script runtime: bundled
freecadcmd/freecadfirst, then bundled Python - bundled Python:
Contents/Resources/bin/python
Recommended macOS setup:
export FREECAD_APP="/Applications/FreeCAD.app"
fcad check-runtimeExplicit runtime overrides:
export FREECAD_PYTHON="/Applications/FreeCAD.app/Contents/Resources/bin/python"
export FREECAD_BIN="/Applications/FreeCAD.app/Contents/Resources/bin/freecadcmd"
fcad check-runtimeWindows compatibility remains available, but only through explicit configuration. FREECAD_DIR is still accepted for backward compatibility:
export FREECAD_DIR="C:\\Program Files\\FreeCAD 1.1"
fcad check-runtimeThis repository does not assume a default WSL -> Windows bridge anymore. If you do use WSL with a Windows FreeCAD install, set the Windows path explicitly as above.
- product_review.schema.json
- process_plan.schema.json
- line_plan.schema.json
- quality_risk.schema.json
- investment_review.schema.json
- readiness_report.schema.json
- stabilization_review.schema.json
- docs_manifest.schema.json
- release_bundle_manifest.schema.json
Legacy compatibility aliases remain available at quality_risk_pack.schema.json and standard_docs_manifest.schema.json.
Hosted contract checks:
npm run test:node:contractThese checks cover runtime discovery, command assembly, and path conversion logic. They do not install or execute FreeCAD.
Python and CLI checks:
npm run test:pynpm run test:py shells out to python3 -m pytest -q, so python3 should resolve to Python 3.11 or newer. Hosted CI currently pins Python 3.11 to match the documented minimum.
Layered integration runner:
npm test
npm run test:fullnpm test now runs the staged integration runner through the existing tests/test-runner.js compatibility shim. Internally the cases are split into runtime, model, drawing, analysis/report, and integration modules, while npm run test:full adds the advanced motion/design layer on top.
GitHub-hosted CI currently covers:
- Node runtime-contract tests on
ubuntu-24.04andmacos-14 - Python unit and CLI tests on
ubuntu-24.04
GitHub-hosted CI does not currently install or launch FreeCAD.
For a real runtime-backed smoke pass on a FreeCAD-capable machine:
npm run smoke:runtimeThe smoke script currently exercises:
fcad check-runtimefcad createfcad draw --bomfcad inspectfcad report
For CI, the repository also includes a self-hosted macOS workflow that uses the same smoke script and requires a runner labeled for FreeCAD with FreeCAD 1.1 installed.
Draft release notes for the first public release surface live at docs/releases/v1.1.0-draft.md.
If you want to run the smoke steps manually instead of the script, use:
cd /path/to/freecad-automation
export FREECAD_APP="/Applications/FreeCAD.app"
fcad check-runtime
npm run test:node:contract
node bin/fcad.js create configs/examples/ks_bracket.toml
node bin/fcad.js draw configs/examples/ks_bracket.toml --bom
node bin/fcad.js inspect output/ks_bracket.step
node bin/fcad.js fem configs/examples/bracket_fem.toml
node bin/fcad.js report configs/examples/ks_bracket.toml