AI가 CAD 코드를 써서 3D 프린터용 부품을 만든다, 별 2만 3천 개 text-to-cad
text-to-cad로 얇은 받침판 하나를 STEP으로 만들고 STL로 내보내 FDM 기준으로 벽 두께를 재고 고치는 한 바퀴를 따라 합니다. 설치, 통계 끄기, 종료 코드까지 담았습니다.
$ python scripts/dfam_tool.py measure STEP/bracket.step
{"error": "failed to load mesh: ..."}
$ echo $?
1
text-to-cad의 출력 검사 스킬에 STEP 파일을 그대로 넣으면 이렇게 끝납니다. 고장이 아니라 설계입니다. 이 검사기는 삼각형으로 된 메시만 읽고, STEP은 면과 치수를 정의로 들고 있는 CAD 모델이라 STL로 먼저 바꿔야 합니다. 에이전트가 모델을 만들고, STL로 내보내고, 벽 두께를 재고, 얇으면 숫자를 고쳐 다시 재는 한 바퀴를 따라가 보면 이 스킬 묶음이 어디서 어떻게 맞물리는지 보입니다.
GitHub의 earthtojake/text-to-cad는 2026-10-27 UTC 기준 별 23,284개, 포크 2,260개이고 MIT 라이선스입니다. 하루 전에 확인한 별 23,159개에서 125개가 늘었습니다. 가장 최근 릴리스는 10월 20일의 v0.7.26이고, 그 뒤로 이 글을 쓴 27일까지 새 릴리스는 없습니다. 이 글에서 따라 할 작업은 편집부가 만든 예시입니다. 폭 40mm, 높이 20mm, 두께 0.6mm의 얇은 받침판을 필라멘트 방식(FDM) 프린터로 뽑으려 합니다. 0.6mm는 검사에 걸리도록 일부러 고른 값이고, 아래 출력 그림은 실제로 돌린 화면이 아니라 문서에 적힌 필드와 종료 코드로 구성한 도식입니다.
uv가 있는지 보고, 설치는 에이전트에게 시킨다
README가 첫 번째로 권하는 방법은 에이전트에게 한 문장을 보내는 것입니다.
Install text-to-cad from https://github.com/earthtojake/text-to-cad
직접 하려면 순서가 세 가지입니다. CAD 실행이 uv를 거치므로 uv --version으로 깔려 있는지 보고, 없으면 uv의 설치 프로그램으로 먼저 설치합니다. 그다음 쓰는 앱의 항목에 있는 명령을 실행하고 앱을 다시 시작합니다. 첫 시작에 CAD 런타임을 내려받으므로 네트워크가 필요합니다. Claude Code는 두 줄입니다.
claude plugin marketplace add earthtojake/text-to-cad#latest
claude plugin install text-to-cad@earthtojake
나머지 앱은 설치와 갱신 명령이 아래와 같습니다. 갱신 뒤에는 모두 앱을 다시 시작합니다.
| 앱 | 설치 | 갱신 |
|---|---|---|
| Claude Desktop | 설정 > 개발자 > 설정 편집에서 MCP 서버(cadgen mcp) 추가 |
설정 args에 고정된 cadgen==0.7.26의 숫자를 새 릴리스로 변경 |
| Codex | 플러그인 디렉터리, 또는 codex plugin marketplace add earthtojake/text-to-cad --ref latest 후 codex plugin add text-to-cad@earthtojake |
codex plugin marketplace upgrade earthtojake |
| Cursor | git clone --depth 1 --branch latest … 을 ~/.cursor/plugins/local/text-to-cad로 |
그 폴더에서 git pull |
| Grok Build | grok plugin install earthtojake/text-to-cad@latest --trust 후 grok plugin enable text-to-cad |
grok plugin update text-to-cad |
| Gemini | gemini extensions install https://github.com/earthtojake/text-to-cad --ref latest --consent --auto-update |
gemini extensions update text-to-cad |
| 플러그인 없는 에이전트 | npx skills add earthtojake/text-to-cad#latest (스킬만) |
같은 add 명령을 다시 실행 |
설치에서 걸리는 곳은 정해져 있습니다. 플러그인과 스킬을 한 앱에 둘 다 설치하면 스킬이 두 벌 들어가므로 하나만 고릅니다. 명령 끝의 latest는 PyPI에 올라간 릴리스만 받는 브랜치이고, 생략하면 아직 릴리스되지 않은 변경이 있을 수 있는 main을 받습니다. npx skills update는 새로 생긴 스킬을 놓치므로 갱신은 add를 다시 실행하는 쪽이 맞습니다. 폐기된 cad-viewer와 cad-mcp-setup은 npx skills remove cad-viewer cad-mcp-setup으로 지우고, Codex 마켓플레이스 이름이 text-to-cad에서 earthtojake로 바뀌었으니 예전에 추가했다면 옛 항목부터 제거합니다.
Windows 11에서는 한 가지가 더 있습니다. CAD 커널인 OCP(OpenCascade의 파이썬 바인딩)의 휠에 서명되지 않은 네이티브 모듈이 들어 있어서, 스마트 앱 컨트롤이 켜져 있으면 모든 cadgen 명령이 ImportError: DLL load failed while importing OCP로 끝납니다. 이벤트 뷰어에는 이벤트 ID 3077로 남고 cadgen doctor가 원인을 짚어 줍니다. 앱별 예외는 없어서 기능을 끄거나 WSL에서 실행해야 하는데, 스마트 앱 컨트롤은 한 번 끄면 윈도를 다시 설치해야 켤 수 있습니다.
첫 명령이 켜 두는 통계 전송과 버전 확인
이 프로젝트는 사용 통계 전송이 기본으로 켜져 있습니다. 첫 cadgen 명령이 안내를 한 번 보여 주고, 그때부터 전송이 시작됩니다. 무작위 설치 ID가 붙어 나가는 것은 버전, 설치 출처, OS와 에이전트 앱, 도구별 호출 횟수, 호출이 실패한 이유(정해진 단어 중 하나), 빌드와 스냅숏의 횟수·결과·소요 시간, 쓴 기능입니다. cadgen 자체 코드가 실패하면 오류의 종류와 실패한 위치만 담은 크래시 보고서도 갑니다. 파일 이름, 경로, 내용, 프롬프트는 보내지 않는다고 README가 밝힙니다. 서버는 접속 주소로 국가를 추정하되 주소는 보관하지 않으며 데이터는 PostHog에 쌓입니다. CI와 개발용 설치에서는 기본으로 보내지 않고, 오프라인에서는 아무것도 나가지 않은 채 모든 기능이 동작합니다.
끄는 길은 넷입니다. uvx cadgen telemetry off는 끄면서 이미 보낸 데이터도 지웁니다. 앱 메뉴(왼쪽 위 로고)의 “Share usage stats”를 끄거나, 에이전트에게 꺼 달라고 요청해도 됩니다. 한 프로세스에서만 끄려면 DO_NOT_TRACK=1 또는 CADGEN_TELEMETRY=0을 씁니다. 전송이 첫 명령에서 시작되므로 편집부는 설치 직후, 첫 작업을 시키기 전에 이 한 줄부터 실행하는 순서를 권합니다.
별개로 새 버전 확인 요청이 하루 한 번 api.texttocad.dev/v1/versions로 나갑니다. ID도 경로도 없는 익명 요청이고 CI에서는 가지 않으며, CADGEN_UPDATE_CHECK=0으로 끕니다. 플러그인 디렉터리나 Cursor 마켓플레이스, Gemini 확장으로 설치한 복사본은 스토어가 갱신하므로 이 확인이 필요 없습니다.
폴더 모양과 스크립트 한 장
모델은 인자 없는 데코레이터 함수가 build123d 도형을 돌려주는 평범한 파이썬 스크립트입니다. 규칙은 짧습니다. 단위는 밀리미터, 좌표는 XY 평면과 +Z 방향이 기본이고, 의미 있는 치수는 이름 있는 상수로 드러냅니다. 시간, 난수, 환경 변수, 작업 폴더에 따라 모양이 달라지면 안 됩니다. 한 파일에는 모델 하나만 두고, 스크립트와 출력 파일은 같은 이름 줄기를 씁니다. 그래서 src/bracket.py는 STEP/bracket.step과 STL/bracket.stl을 만들고, 하위 폴더 구조도 그대로 대응합니다. 데코레이터의 out= 경로는 작업 폴더가 아니라 스크립트 기준 상대 경로입니다.
받침판 예시는 이렇습니다. WALL이 이 글 내내 고칠 숫자입니다.
from cadgen import build123d as bd
from cadgen import step, stl
WIDTH = 40.0
HEIGHT = 20.0
WALL = 0.6
@step(out="../STEP/bracket.step")
@stl(out="../STL/bracket.stl")
def bracket():
body = bd.Box(WIDTH, HEIGHT, WALL)
body.label = "bracket"
return body
if __name__ == "__main__":
bracket()
프로젝트 루트에서 python src/bracket.py를 실행하면 STEP과 STL이 함께 나옵니다. 스킬 문서에서 python은 uvx --no-config --managed-python --python 3.13 --from cadgen==0.7.26 python을 줄여 쓴 것이라 에이전트가 이 형태로 실행합니다. 입력이 같으면 다시 실행해도 아무것도 하지 않고, 지워졌거나 고쳐 쓴 출력은 다시 복원됩니다. 바뀐 것이 없는데 다시 빌드되는 것 같으면 cadgen store why src/bracket.py가 이유를 설명하고, 이 모델 본문을 강제로 돌리려면 python src/bracket.py --force를 씁니다. 한 바퀴를 돌고 나면 폴더는 아래처럼 됩니다.
그림 1. 사람이 고치는 파일은 bracket.py 하나. 나머지는 명령이 남기는 것(편집부가 이 글의 작업 순서로 그린 구성)
STEP 하나에서 STL 하나를 뽑는다
3D 모델은 두 종류로 갈립니다. STL과 3MF는 표면을 작은 삼각형으로 쪼갠 메시이고, STEP은 “이 면은 지름 5mm 원기둥”처럼 도형의 정의를 그대로 든 경계 표현(B-rep) 모델입니다. 프린터는 메시를 받고, 치수를 고치거나 조립하거나 도면을 뽑으려면 B-rep이 있어야 합니다. 이 스킬은 STEP을 원본으로 두고 STL·3MF·GLB를 파생 파일로 만듭니다.
위 스크립트처럼 @stl을 겹쳐 쓰면 실행할 때마다 STL이 유지됩니다. 이미 있는 STEP에서 한 번만 내보낼 때는 명령을 씁니다.
cadgen stl build STEP/bracket.step
cadgen 3mf build STEP/bracket.step
cadgen glb build STEP/bracket.step
출력 경로를 생략하면 입력 옆에 확장자만 바꾼 파일이 생깁니다. 이 명령은 저장된 STEP 문서를 읽을 뿐 스크립트를 다시 돌리지 않으므로, 모델 코드를 고쳤다면 python src/bracket.py가 먼저입니다. 해상도를 나눠 두려면 STL/draft/bracket.stl, STL/print/bracket.stl처럼 폴더를 나눠 선언합니다.
메시가 얼마나 곱게 나오는지는 두 숫자가 정합니다. --mesh-tolerance의 기본값은 1.5e-3이고 부품의 바운딩 대각선 길이에 대한 상대값입니다. --mesh-angular-tolerance의 기본값은 0.35라디안으로 삼각형 모서리에서 법선이 퍼지는 각도의 상한입니다. 같은 입력은 항상 같은 바이트를 내놓으니, 값을 바꿔 가며 비교해도 우연이 끼지 않습니다. 이 글의 받침판은 바운딩 대각선이 약 44.7mm이므로 기본값이 허용하는 현 오차는 약 0.07mm입니다(편집부 계산). 200mm 부품에서 0.1mm 오차를 원한다면 0.1을 200으로 나눈 5e-4를 넘깁니다. 0.05를 넘는 값은 거부됩니다.
메시를 눈으로만 보고 치수를 판단해서는 안 됩니다. 메시에는 CAD 위상 정보가 없어서 정확한 측정은 STEP에서만 됩니다. 형상 확인은 STEP 스냅숏으로 합니다.
cadgen step snapshot STEP/bracket.step tmp/review.png
플러그인을 설치했다면 CAD 뷰어가 붙습니다. Claude Desktop과 Codex 앱에서는 대화 안에서 돌려 볼 수 있는 카드로 보이고, Gemini·Grok·터미널에서는 브라우저로 여는 링크를 줍니다. 뷰어에서 고른 면은 STEP/assembly.step#o1.2.f7 같은 참조 문자열로 프롬프트에 붙습니다. 코드를 열지 않고도 “이 면의 구멍을 4mm로”라고 말할 수 있는 이유입니다. 번호는 저장된 한 판본에서만 유효해서, 다시 빌드하면 다시 골라야 합니다. 또 STL과 3MF에는 애니메이션을 담을 수 없고 GLB만 가능합니다.
검사기에 STEP을 넣으면 1이 돌아온다
DfAM Check 스킬의 도구 dfam_tool.py는 두 명령을 가집니다. measure는 벽 두께, 오버행, 지지대 부피 같은 사실을 JSON으로 내놓고, orientations는 축 방향 여섯 가지 자세를 비교합니다. --angle-limit에는 목표 공정이 스스로 서는 각도(FDM은 45도)를 줍니다. 공정이 바뀌면 지지 면적이 이 각도로 묶여 집계되므로 다시 재야 합니다. 도구는 사실만 내놓고 합격·불합격은 말하지 않습니다. 판정은 스킬의 작업 순서가 하고, 통과·실패·정보 부족 세 가지로만 보고합니다.
종료 코드가 이 도구의 말투입니다. 0은 보고서가 전부 계산됐다는 뜻이고, 1은 메시를 아예 읽지 못했다는 뜻입니다. 글 첫머리의 STEP 입력이 여기에 해당하며, 스킬 문서는 이것을 의존 패키지가 빠졌다는 신호가 아니라 잘못된 입력이라는 신호로 다룹니다. 그래서 메시 로더를 더 설치해 우회하지 말고 STL을 내보내는 쪽으로 가라고 합니다. 2는 일부만 계산된 부분 결과입니다. 필수 의존 패키지가 덜 깔려 벽 두께를 못 쟀다면 partial: true가 붙고 partial_sections에 빠진 항목이 적히며, 이 항목은 0이 아니라 “정보 부족”으로 취급합니다.
그림 2. 스킬 문서의 필드와 종료 코드로 구성한 도식이며 실제 실행 출력이 아니다. 0.6은 이 글 예시 모델의 벽 두께
보고서에서 먼저 볼 것도 정해져 있습니다. mesh.watertight가 false이면 모든 공정에서 슬라이싱이 막히므로 어떤 지적보다 앞에 둡니다. 단위도 확인합니다. 바운딩 상자 대각선으로 계산하는 scale.units_suspect가 true이면 원본이 미터나 인치일 가능성이 있고, 이때 오버행·지지대 값 0.0은 아무 뜻이 없습니다. 도구는 형상을 몰래 키우거나 줄이지 않고 단위부터 확인해 달라고 요청합니다.
벽 0.6mm가 걸리고 1.8mm가 통과하는 한 바퀴
이제 STL을 정상으로 재 봅니다. 이 단계에서 에이전트에게 알려 줘야 할 것은 공정, 재료, 층 높이입니다. 공정을 모르면 기본 45도로 한 번 재고 후보 공정별로 나눠 보고하게 됩니다. 아래 그림이 한 바퀴의 전체 모양입니다.
그림 3. 실패가 나오면 숫자를 고쳐 같은 순환을 다시 돈다. 정보가 모자란 항목은 0으로 치지 않고 점선 경로로 남는다
비교 단계의 규칙은 엄격합니다. 모든 지적은 기준표의 어느 행과 어느 측정값(JSON 필드 경로)을 맞댔는지 밝혀야 합니다. 벽 두께는 광선을 쏘아 표본을 뽑아 재므로 min_mm은 전수 최소가 아닙니다. 그래서 하위 5% 값인 p05_mm가 한계보다 작으면 min_mm이 이상치처럼 보여도 위반으로 보고, 두 값을 함께 적습니다. 조립품은 몸체별(per_body)로 재서, 맞물리는 틈을 벽으로 오해하지 않게 합니다. 실패 항목에는 “벽을 0.6mm에서 1.2mm 이상으로”처럼 수치가 든 재설계 지시를 붙입니다. 이 문서의 예시가 바로 0.6에서 1.2 이상으로 올리는 문장입니다.
- 부품과 쓰임새를 말하고 요청합니다. "src/bracket.py에 WIDTH 40, HEIGHT 20, WALL 0.6 상수로 받침판을 만들고 STEP과 STL을 내보내 줘."
- "STEP 스냅숏으로 형상을 확인해 줘"라고 시켜 모양과 치수를 눈으로 봅니다.
- "STL을 FDM 기준으로, 0.4mm 노즐에 층 높이 0.2mm로 검사해 줘"라고 요청합니다. 측정값과 비교한 기준표의 행이 함께 와야 합니다.
- 벽 0.6mm가 지지되는 벽 한계 1.2mm보다 얇아 실패로 나옵니다. 재설계 지시를
WALL상수에 반영하게 하되, 벽이 지지되지 않는 구간이면 한계가 1.6이므로 편집부 예시에서는 둘 다 넘는 1.8로 올립니다. python src/bracket.py로 STEP과 STL을 다시 만들고 같은 검사를 다시 돌립니다. 실패 항목이 사라지면 여기서 멈추고 결과를 눈으로 확인합니다.
네 번째 단계의 숫자는 한계에 딱 맞추기보다 여유를 두는 편이 재측정에서 덜 걸립니다(편집부 권장). 스킬은 CAD 스킬이 있으면 고쳐서 다시 재는 순환을 권하고, 실패 항목이 없어질 때까지 반복하게 합니다. 슬라이싱, 업로드, 출력 시작은 이 스킬이 하지 않습니다.
같은 벽을 SLA에 올리면 통과하는 이유
판정은 파일이 아니라 “어디서 뽑느냐”로 갈립니다. 기준표는 저장소의 process-limits.md에 있고, Hubs·Formlabs·HP·EOS의 설계 가이드를 참고해 ISO/ASTM 52910의 범주에 맞춘 보수적 기본값입니다. 사용자가 기기나 재료의 데이터시트를 주면 그것이 우선합니다.
| 항목(mm) | FDM | SLS(PA12) | SLA/DLP | 금속 분말 베드 | MJF |
|---|---|---|---|---|---|
| 지지되는 벽 | 1.2 | 0.7 | 0.5 | 0.4 | 0.5 |
| 지지되지 않는 벽 | 1.6 | 0.7 | 1.0 | 0.5 | 0.5 |
| 스스로 서는 각도(수평 기준) | 45도 | 해당 없음(분말이 받침) | 30도 | 45도 | 해당 없음(분말이 받침) |
| 최소 구멍 지름 | 2.0 | 1.5 | 0.5 | 1.5 | 1.0 |
| 최소 돌출 요소 | 0.8 | 0.8 | 0.2 | 0.4 | 0.5 |
| 최대 받침 없는 다리(브리지) | 10 | 해당 없음 | 5 | 2 | 해당 없음 |
벽이 1.0mm로 재진 휴대폰 거치대를 이 표에 대 봅니다. FDM이라면 지지되는 벽 한계 1.2mm보다 0.2mm 얇아 실패이고, 지시는 벽을 1.2mm 이상으로 올리라는 것입니다. SLA라면 한계가 0.5mm라 통과입니다. 다만 같은 SLA에서 지지되지 않는 벽의 한계는 1.0mm라 딱 경계선이고, 스스로 서는 각도는 30도라 오버행 판정도 FDM과 다르게 나옵니다. 그래서 공정을 정하지 못했다면 한 번 재고 후보별로 나눠 보고하라는 절차가 스킬에 들어 있습니다.
표에는 있지만 도구가 재지 않는 항목
표의 여섯 줄을 도구가 모두 재는 것은 아닙니다. 지금 측정되는 것은 지지되는 벽, 지지되지 않는 벽, 스스로 서는 각도 세 가지뿐입니다. 최소 구멍 지름, 최소 돌출 요소, 최대 브리지 길이는 보고서에 “검사하지 않음”으로 남고, 렌더링이나 바운딩 상자, 삼각형 수로 짐작해 채우지 않습니다. 이 글의 받침판에 나사 구멍을 뚫는다면 구멍 지름이 FDM 한계 2.0mm를 넘는지는 이 도구가 아니라 사람이 봐야 합니다. 측정값이 없는 한계는 지적이 아니라는 원칙입니다.
분말 방식에는 다른 빈칸이 있습니다. SLS와 MJF는 분말이 오버행을 받쳐 주므로 지지대 각도 규칙을 적용하지 않고, 대신 닫힌 공동에 갇힌 분말을 빼낼 구멍이 중요해지는데 도구는 이것을 재지 않습니다. 닫힌 공동이 보이면 “정보 부족”으로 보고합니다. 도구가 모르는 것을 통과로 적지 않는 설계입니다.
지지대 부피는 프리즘으로 잡은 거친 상한 추정이라 하드 실패가 아니라 비용 신호입니다. 부품 부피의 약 30%를 넘으면 자세를 바꾸거나 재설계를 고려하라고 안내하고, orientations가 후보로 내놓는 자세도 축 방향 여섯 가지에 한정됩니다. 후보가 지지 면적을 눈에 띄게 줄이면 출력 높이가 늘어나는 대가와 함께 보고합니다. 이 모든 것은 슬라이서 검증이 아니라 형상 측정이고, 벽이 한계보다 얇은지를 묻는 검사지 부품이 하중을 버티는지를 묻는 검사가 아닙니다. 힘이 걸리는 부품은 검사를 통과해도 따로 검토해야 합니다.
슬라이서 앞에서 멈추고 Print는 사람이 누른다
검사가 끝나면 슬라이싱이 남습니다. G-code 스킬은 OrcaSlicer로 STL·3MF를 슬라이스하지만 프린터에는 접속하지 않습니다. macOS에서는 brew install --cask orcaslicer로 설치하고, 에이전트는 먼저 사용자가 이미 쓰는 프린터·공정·필라멘트 프리셋을 찾습니다. 프리셋을 임의로 만들지 않는 것이 원칙입니다. 베드 크기나 온도가 틀리면 장비가 상할 수 있어서입니다.
python scripts/orca_presets.py --list machine --match "MK4S"
python scripts/orca_presets.py --printer "Prusa MK4S 0.4 nozzle" \
--process "0.20mm SPEED @MK4S 0.4" --filament "Prusa Generic PLA @MK4S" \
--out presets
프리셋이 준비되면 슬라이서 명령줄이 plate_1.gcode와 model.gcode.3mf를 만듭니다. 출력 폴더는 절대 경로로 줘야 합니다. 출력 전 확인도 명령으로 남아 있습니다. OrcaSlicer 명령에 --info를 붙이면 모델 크기가 나오므로 베드에 들어가는지 보고, G-code 끝에 적힌 설정을 훑습니다.
grep -E '^; (printer_model|nozzle_diameter|filament_type|nozzle_temperature|hot_plate_temp|bed_temperature) =|printing time' out/plate_1.gcode
노즐·재료·온도가 사용자의 프린터와 맞는지 사람이 대조합니다. 그다음은 프린터 제조사가 정합니다. Bambu Lab 프린터는 Bambu Labs 스킬이 이어받습니다. 슬라이스된 .gcode.3mf는 bambu-connect://import-file?path=…&name=…&version=1.0.0 링크로 Bambu Connect에서 열고, 슬라이스 전 모델은 Bambu Studio에서 엽니다. 여기까지가 에이전트의 일입니다. 출력 시작·일시정지·취소, 프린터 상태 읽기, 접근 코드 요청은 하지 않고, 프린터를 볼 수 없으므로 “출력을 시작했다”고 보고하지도 않습니다. Print 버튼을 누르기 전에 프린터, 플레이트 종류, 노즐, 필라멘트와 AMS 매핑, 베드가 비어 있는지, 첫 층을 지켜볼 사람이 있는지 확인하라고 안내합니다. Bambu Connect는 Windows 10 이상, macOS 13 이상에서 쓰고 리눅스에서는 Bambu Studio를 씁니다. 클라우드 연결이 끊기는 LAN 전용 개발자 모드는 다루지 않습니다.
프린터가 없어도 남는 스킬 아홉 개
12개 스킬 가운데 DfAM Check, G-code, Bambu Labs는 3D 프린팅 전용이고 나머지 아홉은 프린터가 없어도 쓸 수 있습니다. 위 한 바퀴에서 이미 CAD 스킬을 썼고, 모델을 만들 때 나사나 베어링이 필요하면 step.parts 스킬이 먼저 나섭니다. 이 스킬은 api.step.parts 카탈로그에서 규격 부품을 찾아 STEP을 내려받고 sha256 체크섬을 확인합니다. 에이전트가 대충 그린 자리표시자 대신 실제 부품 파일을 쓰게 하려는 장치이고, 네트워크가 막혀 검색이 실패한 것은 “없음”이 아니라서 한 번 더 시도하게 합니다. 직접 부르는 형태는 python scripts/download_step_part.py "M3 socket head 12" --download입니다.
도면 쪽은 두 갈래입니다. Engineering Drawing은 치수·숨은선·구멍 표기·표제란이 있는 PDF를 만듭니다. 치수 글자는 사람이 쓰지 않고 형상에서 측정해 채우며, 공차는 사용자가 준 값만 쓰고, 정사영 뷰만 지원해서 단면도와 상세도는 없고, 그리다 실패하면 틀린 파일을 남기지 않습니다. DXF 스킬은 2D 형상을 돌려주는 함수 하나로 파일을 만들어 절단·새김·스코어링을 레이어로 나누고, 닫히지 않은 절단선은 빌드 단계에서 거부하며 절단 폭(커프) 보정을 지원합니다.
제조 검토도 같은 틀입니다. DFM 스킬은 판금·CNC·사출 성형을 검토하고, 사출 성형은 mold_tool.py로 빼기 경사·언더컷·투영 면적을 잽니다. 판정은 통과·실패·검토 필요·검증 불가 네 가지로 나뉘고, 공급업체의 실제 사양이 일반 가이드보다 우선하며, 제조 가능성을 인증하는 것이 아니라 안내형 검토라고 스스로 밝힙니다. SendCutSend 스킬은 판금·레이저 절단 업체에 올리기 전에 DXF와 STEP을 점검하는 읽기 전용 스킬이라 업로드나 주문을 하지 않습니다. 마지막으로 URDF·SRDF·SDF 스킬은 로봇의 구조 파일, MoveIt 설정, 시뮬레이터 모델을 씁니다.
며칠마다 바뀌는 도구의 버전을 붙잡는 법
이 프로젝트의 변화 속도는 PyPI 업로드 기록에 그대로 남아 있습니다. 8월 11일의 0.4.1부터 10월 20일의 0.7.26까지 64개이고, 월별로는 8월 28개(11일부터), 9월 14개, 10월 22개(20일까지)입니다.
그림 4. 주별 릴리스 수(PyPI 업로드일 기준, 편집부 집계). 하루에 세 번 나온 날도 있고, 10월 26일 주는 27일 현재 0
주마다 들쭉날쭉해도 흐름은 읽힙니다. 8월 첫 두 주에 25개가 몰렸다가 9월 초 두 주는 하나씩으로 가라앉았고, 9월 28일 주와 10월 5일 주에 다시 열아홉 개가 쏟아졌습니다. 10월 8일부터 20일 사이에만 STEP 체크섬 검증, API를 PyPI를 읽는 별도 프로젝트로 옮긴 것(0.7.19), 뷰어 재설계(0.7.22)와 5개 언어 뷰어(0.7.24), 그리고 노드(Node)가 경로에 없을 때 메시 내보내기가 실패하던 오류의 수정(0.7.26)이 있었습니다. 마지막 수정은 이 글의 STL 내보내기 단계와 직결되는 것이라, 설치 후 cadgen stl build가 이상하면 버전부터 보는 편이 빠릅니다.
버전이 붙잡히는 자리는 세 곳입니다. CAD 스킬의 모든 명령은 cadgen==0.7.26처럼 릴리스를 고정해 실행합니다. Claude Desktop 설정의 args에도 같은 숫자가 들어 있어 갱신할 때 직접 바꿔야 합니다. 플러그인을 갱신하면 새 릴리스의 cadgen을 처음 실행할 때 내려받고, 이전 릴리스는 uv 캐시에 남아 uv cache prune으로 정리할 수 있습니다. 직접 설치한 복사본은 새 릴리스가 나오면 CAD 상단과 홈에 파란 업데이트 버튼을 띄우고, 누르면 갱신 요청 문장이 대화에 올라가 에이전트가 앱별 갱신 명령을 실행합니다.
- 설치 직후, 첫 작업 전에
uvx cadgen telemetry off를 실행했는가 - 한 앱에 플러그인과 스킬 중 하나만 설치했는가
- 설치 명령 끝에
latest브랜치를 붙였는가(main은 미릴리스 변경 포함) - 갱신 뒤 앱을 다시 시작했는가, Claude Desktop이라면
args의cadgen==숫자를 새 릴리스로 바꿨는가 - 스킬만 설치했다면 갱신에
npx skills update가 아니라add를 다시 실행했는가