Tudo o que o ConstructCraft faz num modelo pode ser feito sem a interface. O motor (cc_engine) reúne as operações num catálogo de comandos nomeados, e três clientes usam esse mesmo catálogo:
┌──────────────────────────────┐
aplicativo ──▶│ │
ccad (CLI) ──▶│ cc_engine: Session + │──▶ o modelo (.ccad)
agentes (MCP) ──▶│ catálogo de comandos │
scripts Lua ──▶│ (+ comandos de plugins) │
└──────────────────────────────┘
Uma parede desenhada com o mouse, um ccad run wall_create …, um script Lua chamando ccad.run("wall_create", …) e um agente de IA chamando a ferramenta wall_create executam o mesmo código, com os mesmos padrões, verificações e desfazer. A lista completa de comandos e parâmetros está na referência de comandos (em inglês, gerada do próprio catálogo); plugins acrescentam seus próprios comandos ao catálogo.
Sessão. Um projeto aberto: o documento (com o histórico de desfazer) e a geometria e os desenhos derivados dele. A CLI abre uma por execução (ou script), o servidor MCP uma por conexão, o aplicativo uma por janela.
Comandos. Cada comando tem um nome em snake_case, um objeto JSON de parâmetros descrito por um esquema JSON e um resultado JSON. Tipos:
| Tipo | Faz | Exemplos |
|---|---|---|
| query | lê o modelo | elements_list, element_get, schedule_table |
| edit | altera o modelo: um passo de desfazer | wall_create, elements_move, element_set |
| file | trabalha com arquivos ou substitui o projeto | project_open, ifc_import, sheet_export |
Unidades e coordenadas. Comprimentos em metros, ângulos em graus, pontos [x, y] em planta. As cotas usam as coordenadas do desenho da sua vista (X/Y da planta nas plantas; posição horizontal e altura nas elevações e cortes). Áreas e volumes nos resultados vêm em m² e m³.
Referências. Níveis, tipos, vistas e materiais são indicados por id ou nome ("level": 3 ou "level": "Térreo"; maiúsculas e minúsculas não importam; um nome ambíguo dá erro pedindo o id). Folhas também podem ser indicadas pelo número ("A101"). Elementos são indicados por id, que elements_list e os resultados dos comandos de criação informam. Sem nível, vale o nível mais baixo; sem tipo, o tipo padrão da categoria.
Ler e alterar parâmetros. element_get, type_get e view_get mostram os params de um objeto; element_set, type_set e view_set recebem os campos a alterar no mesmo formato e os mesclam:
ccad -p casa.ccad run element_get id=42
ccad -p casa.ccad --save run element_set id=42 'params={"height": 2.7}'
ccad -p casa.ccad --save run element_set id=57 'params={"shape": {"Gable": {"slope": 0.5, "ridge_deg": 0}}}'
Objetos se mesclam campo a campo; listas e valores simples substituem; null limpa um valor opcional. material_set e units_set (no formato de material_get e units_get) funcionam do mesmo jeito.
Gráficos das vistas. O que uma vista mostra e como faz parte da vista: view_graphics_get lista a visibilidade e as sobreposições de cada categoria, os filtros aplicados e as sobreposições de elementos; view_graphics_set mostra ou oculta uma categoria e sobrepõe suas linhas em projeção e de corte (cor, espessura em mm de papel, padrão), preenchimentos de superfície e de corte (cor, padrão), meio-tom e transparência; element_override_set e element_hide_in_view fazem o mesmo para elementos numa vista. As sobreposições são objetos como {"cut_lines": {"color": [255, 0, 0], "weight": 0.5, "pattern": "Dash"}, "cut_fill": {"pattern": "Solid", "color": [200, 200, 200]}, "halftone": true, "transparency": 0.4} e se mesclam como params (null redefine um atributo, reset: true recomeça). Valem em plantas, plantas de forro, elevações, cortes, vistas 3D, folhas e exportações PDF/SVG.
ccad -p casa.ccad --save run view_graphics_set view=Térreo category=door visible=false
ccad -p casa.ccad --save run filter_create name=Longas 'categories=["wall"]' 'rules=[{"param": "length", "op": "greater", "value": 5}]'
ccad -p casa.ccad --save run view_filter_add view=Térreo filter=Longas 'overrides={"cut_lines": {"color": [255, 0, 0]}}'
ccad -p casa.ccad run filter_elements filter=Longas
Filtros (filter_create, filter_set, filter_delete, filters_list, filter_elements) selecionam elementos por categoria e regras sobre parâmetros — qualquer campo de tabela (type, mark, comments, level, material, system, structural, width, height, thickness, length, area, volume, diameter…) ou elevation (do nível do elemento) — com equals, not_equals, contains, not_contains, begins_with, not_begins_with, greater, greater_or_equal, less, less_or_equal, has_value e has_no_value, todas as regras (padrão) ou qualquer uma (any: true). Uma regra sobre um campo que nenhuma das categorias do filtro tem (width em paredes) é recusada, pois nunca passaria. Quantidades são comparadas em unidades do SI (metros); texto, sem diferenciar maiúsculas. Uma vista aplica filtros em ordem (view_filter_add, view_filter_set, view_filter_move, view_filter_remove): o primeiro filtro que corresponde vence em cada atributo, as sobreposições do próprio elemento vencem os filtros e os filtros vencem a categoria; um elemento fica oculto se estiver oculto na vista, se a categoria estiver desligada ou se algum filtro correspondente o ocultar.
Modelos de vista (template_create a partir de uma vista, template_set, template_delete, templates_list) guardam escala, gráficos das categorias, filtros, altura de corte das plantas, exibição de instalações (sobre a arquitetura esmaecida) e exibição estrutural, cada um com uma marca include. view_template_apply copia-os para vistas uma vez; view_template_assign faz as vistas seguirem o modelo: as propriedades incluídas são copiadas agora e a cada mudança do modelo (no mesmo passo de desfazer), e editá-las na vista é recusado. Excluir um modelo libera as vistas, que mantêm suas propriedades.
Ocultar/isolar temporário (view_temporary com action hide, isolate, hide_category, isolate_category ou reset) é estado de exibição da sessão, não uma mudança do modelo: não é salvo, não entra no desfazer e não é impresso (folhas e exportações mostram a vista inteira). view_temporary_apply o torna permanente (oculto na vista, categorias desligadas) como um passo de desfazer.
Fases de obra. Uma reforma é modelada em fases (phases_list; o modelo tem Existente e Construção nova): cada elemento do modelo é construído numa fase (phase_created) e pode ser demolido na mesma ou numa posterior (phase_demolished), como element_get mostra. phase_create (no fim ou antes de outra, before), phase_set (renomear, ou mover com index; uma mudança que demoliria elementos antes de construí-los é recusada) e phase_delete (uma fase em uso precisa de merge_into) as gerenciam. Elementos novos são construídos na fase de criação da sessão (phase_creation_set; a da vista ativa no aplicativo, senão a última), cópias também. elements_phase_set define created e demolished (null: de pé) e elements_demolish demole numa fase (phase) ou na fase de uma vista (view). Portas, janelas e armaduras seguem seus hospedeiros: nunca são mais antigas que eles e são demolidas com eles, a menos que demolidas antes. Cotas, textos e eixos não têm fase.
ccad -p casa.ccad --save run elements_phase_set 'ids=[12, 13]' created=Existente
ccad -p casa.ccad --save run elements_demolish 'ids=[13]' view=Térreo
ccad -p casa.ccad --save run view_set view=Térreo 'phase_filter=Mostrar anterior + demolição'
ccad -p casa.ccad run phases_list
Cada planta, elevação, corte, vista 3D e tabela mostra o modelo na sua fase (phase) com um filtro de fases (phase_filter, ambos com view_set; modelos de vista controlam o filtro, não a fase). Em relação à fase da vista um elemento é existente (construído antes, de pé), demolido (nesta fase), novo (construído nesta fase) ou temporário (construído e demolido nela); elementos construídos depois ou demolidos antes não aparecem. Os filtros de fases (phase_filters_list, phase_filter_create, phase_filter_set, phase_filter_delete; o modelo traz Mostrar tudo, Mostrar completo, Mostrar novo, Mostrar anterior + demolição, Mostrar anterior + novo, Mostrar fase anterior e Mostrar demolição + novo) dizem, para cada situação, not_displayed, by_category ou overridden, que usa os gráficos da situação definidos no projeto (phase_graphics_get, phase_graphics_set: existente esmaecido, demolido tracejado e sem hachura de corte, temporário esmaecido e tracejado), abaixo das sobreposições de elementos e dos filtros de vista e acima da categoria. Uma vista cuja fase deixa elementos de fora tem geometria própria: portas de fases posteriores não abrem paredes existentes e paredes só se unem com paredes da fase. Um ambiente é delimitado pelas paredes de pé ao fim da fase em que é criado, então paredes demolidas nessa fase ou antes não o delimitam. Tabelas listam o que sua fase e seu filtro mostram e oferecem os campos PhaseCreated e PhaseDemolished (que também servem em regras de filtros, como phase_created e phase_demolished).
Vistas de desenho. view_create com kind: "drafting" cria uma vista 2D independente do modelo (categoria drafting, 1:10 a menos que scale diga outra coisa): ela não desenha a geometria do modelo, só os elementos colocados nela — text_create, dimension_create (e as formas em cadeia e ordenada), cad_import e image_import a aceitam como view. view_get mostra sua scale e detail, view_set os altera (ela não tem fase nem estilo visual) e view_graphics_set oculta ou sobrepõe suas categorias. Vai para folhas com sheet_place_view e é exportada com view_export (PNG, SVG, PDF, DXF) como as outras vistas; view_delete exclui o que foi desenhado nela.
Chamadas de detalhe e vistas de detalhe. callout_create desenha uma chamada de detalhe numa planta, planta de forro, corte ou elevação (parent): rect são dois cantos opostos nas coordenadas de desenho da vista (metros; y é a altura em cortes e elevações). Ela cria uma vista de detalhe dessa região (chamada Detalhe N a menos que name diga outra coisa, na escala scale, por padrão uma escala usual cerca de cinco vezes maior que a da vista: 1:10 sob 1:50) do mesmo tipo da vista, que continua ligada ao modelo: segue o nível, a linha de corte ou a direção da vista mãe, mostra o modelo como ela (fase, nível de detalhe, estilo visual, gráficos) e é recortada pelo retângulo, e suas próprias linhas de detalhe, regiões, componentes de detalhe, textos e cotas são desenhados inteiros. Com drafting, a chamada aponta para essa vista de desenho existente (sem recorte; uma chamada por vista de desenho). A vista mãe desenha a chamada como um retângulo de cantos arredondados e uma marca: o número do detalhe na folha sobre o número da folha depois de colocado, senão a última palavra do nome sobre um traço. view_get mostra crop ([[x mín, y mín], [x máx, y máx]]) e callout (parent, parent_name, rect, drafting); view_set crop move ou redimensiona a chamada de uma vista de detalhe (são um só retângulo), recorta qualquer planta, corte ou elevação, ou com null volta a mostrar tudo (uma chamada precisa do seu retângulo); numa vista de desenho apontada por uma chamada, move essa chamada. callouts_list lista as chamadas desenhadas numa vista, callout_remove remove uma chamada e mantém a vista, view_delete de uma vista de detalhe remove sua chamada, e excluir a vista mãe deixa os detalhes como vistas recortadas comuns. As plantas não desenham a vista de detalhe de um corte ou elevação como outra marca de corte ou elevação. Arquivos cujas chamadas apontam para vistas inexistentes, ou cujos recortes não são retângulos válidos, são reparados ao abrir.
ccad -p casa.ccad --save run callout_create parent="Térreo" rect=[[2,3],[5,6]] scale=20
Linhas de detalhe. detail_line_create desenha linhas 2D próprias de uma vista numa planta, planta de forro, elevação, corte, legenda ou vista de desenho (view), nas coordenadas de desenho da vista em metros (como notas de texto e cotas): curves aceita as mesmas formas dos esboços (line, arc por bulge ou through, circle, ellipse ou parte dela, rectangle, polygon), cada curva um elemento (categoria detailline; uma polilinha são os seus segmentos), tudo num passo de desfazer, e style é um dos estilos de linha internos thin (padrão), medium, wide, hidden, dashed, center e dotted. Só a sua vista as desenha, por cima do modelo; view_delete as exclui com ela, e vistas 3D e a exportação IFC as deixam de fora. element_get mostra params.curve (a curva como Line, Arc, Circle ou Ellipse) e params.style ({"BuiltIn": "Wide"}), com os derivados length e style_name; element_set os altera ("style": "hidden" também vale). Os comandos genéricos as editam: elements_move, elements_copy, elements_rotate, elements_mirror, elements_delete, trim_corner (duas linhas de detalhe, que se encontram onde suas retas, círculos ou elipses se cruzam), trim_extend (até outra linha de detalhe ou a linha de uma parede, viga ou eixo), element_split e element_offset (arcos e círculos concêntricos; elipses não têm deslocamento). A exportação DXF as põe numa camada com o nome do seu estilo (THIN, CENTER…).
ccad -p casa.ccad --save run detail_line_create view=Térreo style=dashed 'curves=[{"kind":"circle","center":[2,3],"radius":0.5}]'
Estilos de linha. Além dos estilos internos, um projeto tem estilos de linha próprios (nome, espessura no papel em mm, cor, tracejado), guardados como configurações do projeto: line_styles_list lista os dois (internos pelo código, os do projeto pelo nome, com weight, color, pattern e used_by), line_style_create adiciona um (name único e diferente dos códigos internos, weight de 0,05 a 5 mm, padrão 0,25, color [r, g, b], pattern solid, dash, short_dash, dot ou dash_dot), line_style_set o altera (as linhas desenhadas com ele acompanham) e line_style_delete o exclui, passando as linhas de detalhe e contornos de regiões que o usam para replace_with (padrão thin) no mesmo passo de desfazer. Onde um comando aceita um estilo de linha (style de detail_line_create, boundary de uma região, element_set) um estilo do projeto é nomeado como um interno; params.style então mostra {"Project": <id>}. Um arquivo cujas linhas usam um estilo que não existe mais recebe o estilo fino ao ser aberto.
Regiões preenchidas e de máscara. filled_region_create desenha uma área 2D numa planta, planta de forro, elevação, corte, legenda ou vista de desenho (view), nas suas coordenadas de desenho em metros: as curves (como nos esboços) fecham laços, o maior é o contorno e os que estão dentro dele são aberturas, tudo num passo de desfazer. Ela é preenchida como o seu tipo diz e contornada no estilo de linha boundary (padrão thin; none para nenhum contorno); type escolhe um tipo de região preenchida, senão o primeiro do projeto, criado com a primeira região (linhas diagonais sobre branco). filled_region_type_create cria outro (padrões foreground e background — none, solid, diagonal, diagonal_back, crosshatch, horizontal, vertical, grid, brick, concrete, sand, insulation, earth — cada um com sua cor; um padrão solid preenche com a sua cor e um fundo none deixa o modelo visível entre as linhas do padrão); type_set altera o seu fill. masking_region_create desenha uma área branca opaca que esconde as linhas do modelo sob ela (sem contorno, a menos que boundary nomeie um estilo). As regiões são desenhadas só na sua vista, em ordem de id, por cima do modelo e sob as anotações da vista (linhas de detalhe, cotas, textos e, nas plantas, etiquetas, eixos e marcas de corte); vistas 3D e a exportação IFC as deixam de fora. element_get mostra params (outline, openings, sketch, boundary) com os derivados area, perimeter e boundary_name; element_set troca o tipo ou "boundary": "wide" / "none"; sketch_get e sketch_set leem e redesenham o contorno; os comandos de mover, copiar, girar, espelhar e excluir valem para elas, e view_delete as exclui com a sua vista. As exportações escrevem os preenchimentos: SVG, PDF e PNG como polígonos (uma região com aberturas como um só anel), DXF como triângulos SOLID e linhas do padrão numa camada com o nome do estilo do contorno (uma região sem contorno na da sua categoria, FILLEDREGION ou MASKINGREGION).
ccad -p casa.ccad --save run filled_region_create view=Térreo boundary=wide 'curves=[{"kind":"rectangle","corner":[0,0],"opposite":[4,3]}]'
Componentes de detalhe. Um componente de detalhe é um componente 2D reutilizável para detalhes construtivos (categoria detailcomponent, tipo de componente Detail): suas peças são as peças 2D dos carimbos — stroke (linhas e arcos por pontos, abertos ou fechados com closed, com espessura weight em milímetros de papel, color, tracejado pattern e, fechados, um preenchimento sólido fill ou um padrão) e text e image — mais peças nested que inserem outro componente de detalhe dentro dele (component, x, y, rotation, scale, mirrored), tudo em metros no seu próprio sistema (alturas de texto também) e como números ou expressões sobre os seus parâmetros. detail_component_create cria um como novo tipo chamado name (único entre tipos e componentes): a partir de pieces, ou de elements de uma vista view — linhas de detalhe mantêm a pena, regiões preenchidas e de máscara viram traços fechados com o seu preenchimento (aberturas como contornos), notas de texto viram textos na altura impressa (chamadas como linhas) e componentes de detalhe viram peças aninhadas — cujo ponto origin (padrão: o canto inferior esquerdo da sua extensão) vira a origem do componente; com replace (padrão true) esses elementos são excluídos e o componente é inserido onde estavam (placed), tudo num passo de desfazer. detail_component_place insere um tipo numa planta, planta de forro, elevação, corte, legenda ou vista de desenho (view): a origem em position, girado rotation graus, com tamanho scale (0,0001 a 10000) e, com mirrored, espelhado antes no próprio eixo X. Só essa vista o desenha, por cima do modelo e das regiões e sob as linhas de detalhe e anotações; view_delete o exclui com a vista, e vistas 3D e IFC o deixam de fora. element_get mostra params (view, position, rotation_deg, scale, mirrored, overrides) com os derivados component, pieces e nested; element_set os altera (menos a vista); os comandos de mover, copiar, girar, espelhar e excluir valem para ele. component_sheet_piece_add, component_sheet_piece_set e component_sheet_piece_delete editam as peças de um componente de detalhe (todos os inseridos acompanham), component_param_* os parâmetros. Uma peça aninhada nomeia um componente (usa os valores de parâmetro do primeiro tipo dele); nomear um que contém este componente (um ciclo) é recusado, e o desenho para em 8 níveis de aninhamento e num limite de peças de qualquer forma. component_save grava no arquivo .ccomp também os componentes aninhados, e component_load adiciona os que o projeto não tem; component_library_list lista componentes de detalhe com kind Detail e category detail_component. cad_import com blocks: true traz os blocos de um DWG ou DXF como componentes de detalhe em vez de explodi-los: cada bloco inserido por translação, rotação, escala uniforme ou espelhamento vira um tipo com o seu nome (os seus próprios blocos inseridos como peças aninhadas, referências que fechariam um ciclo descartadas), cada inserção desse tipo no desenho vira um componente de detalhe inserido, e o resto (outras inserções, cotas, entidades soltas) fica no desenho importado; o resultado lista os novos components.types e components.elements. A exportação DXF (view_export) grava os componentes de detalhe de uma vista como blocos (um por componente; um inserido com valores de parâmetro próprios tem o seu) e INSERTs na camada DETAILCOMPONENT, os aninhados como inserções dentro dos seus blocos.
ccad -p casa.ccad --save run detail_component_create name=Tijolo 'pieces=[{"kind":"stroke","closed":true,"fill":[200,80,60],"points":[{"u":0,"v":0},{"u":0.2,"v":0},{"u":0.2,"v":0.1},{"u":0,"v":0.1}]}]'
ccad -p casa.ccad --save run detail_component_place type=Tijolo view="Vista de desenho 1" position=[1,2] rotation=90
ccad -p casa.ccad --save run cad_import path=detalhes.dwg view="Vista de desenho 1" blocks=true
Desenhos CAD importados. cad_import lê um arquivo DWG (R12 até 2018 e posteriores, pela biblioteca acadrust) ou DXF (ASCII ou binário, lido pelo próprio ConstructCraft) para uma planta, planta de forro, elevação, corte, legenda ou vista de desenho, num passo de desfazer, e informa o que leu: format, version, units (e units_assumed), layers, entities, blocks, primitives, skipped (entidades não desenhadas, por tipo), truncated e a extensão na vista (extents). Blocos são inseridos (aninhados, escalados, girados, em matriz), arcos e círculos continuam arcos, elipses, splines e contornos de hachuras viram polilinhas, textos e MTEXT mantêm posição, altura e rotação; sólidos 3D, imagens, linhas infinitas e entidades parecidas são ignorados. position com align posiciona a origem do desenho (origin, o padrão), o centro da sua extensão (center) ou a origem, a menos que fique a mais de 1 km do conteúdo da vista (auto); units substitui as do arquivo (mm, cm, dm, m, km, in, ft, yd, mi), e arquivos sem unidades são lidos em metros quando pequenos, senão em milímetros. O elemento começa fixado e só a sua vista o desenha, sob o modelo (categoria cadimport; vistas 3D e exportação IFC o deixam de fora). element_get mostra o posicionamento em params (units, scale, position, rotation_deg, mirrored, hidden_layers, color_mode Grey/Layers/Black, halftone), mas não o desenho; element_set os altera; os comandos de mover, girar, espelhar, fixar e excluir valem para ele. cad_layers lista as camadas e cad_layers_set as mostra ou oculta. cad_explode o transforma em elementos nativos da sua vista num passo de desfazer: linhas, polilinhas (segmentos com bulge como arcos), arcos e círculos viram linhas de detalhe, um elemento por segmento (elipses, splines e contornos de hachuras, guardados como polilinhas, saem como seus segmentos); preenchimentos viram regiões preenchidas sem contorno, de um tipo de região preenchida sólido da cor do preenchimento (chamado Sólido #RRGGBB, reaproveitado quando um já preenche com essa cor); textos de uma linha viram notas de texto no mesmo lugar, altura, rotação e alinhamento, de um tipo de texto do seu tamanho no papel na escala da vista (reaproveitado quando um tem esse tamanho). Cada camada vira um estilo de linha do projeto com o nome e a cor da camada (cores claras escurecidas para o papel), reaproveitado quando já existe um estilo com esse nome; camadas ocultas no elemento ficam de fora (ele começa com as desligadas ou congeladas no arquivo ocultas), e o posicionamento é aplicado. Imagens continuam no elemento (sem as outras primitivas); sem elas o elemento é excluído. O modo de cor e o meio-tom não são levados. O resultado lista os elementos criados (created), as contagens detail_lines, filled_regions e texts, os novos line_styles e types, kept (o elemento quando as imagens ficam) e as primitivas ignoradas (skipped: pequenas demais ou fora dos limites); um desenho que geraria mais de 100.000 elementos, ou acrescentaria mais de 1.000 tipos, é recusado. Com cad_import blocks: true os blocos já são componentes de detalhe, e explodir os deixa como estão.
ccad -p casa.ccad --save run cad_import path=levantamento.dwg view=Térreo align=auto
ccad -p casa.ccad --save run element_set id=120 'params={"units": "Centimeters", "halftone": true}'
ccad -p casa.ccad --save run cad_layers_set id=120 'layers=["COTAS", "TEXTOS"]' visible=false
ccad -p casa.ccad --save run cad_explode id=120
Validação e desfazer. Cada edição é um passo de desfazer (undo, redo). Uma edição que deixaria o modelo inválido — uma porta numa parede inexistente, uma medida negativa, uma referência a nada — é recusada sem deixar rastro. Elementos fixados não são movidos, aparados nem excluídos.
Erros. Um comando que falha devolve {"error": {"code": …, "message": …}}, com a mensagem no idioma da sessão (--lang, language_set).
| Código | Significado |
|---|---|
unknown_command |
nenhum comando tem esse nome |
invalid_arguments |
os parâmetros não seguem o esquema ou não fazem sentido (comprimento zero, tipo desconhecido…) |
not_found |
o elemento, tipo, nível, vista ou material indicado não existe |
rejected |
a edição deixaria o modelo inválido ou não é permitida (fixado, em uso…) |
io |
falha ao ler ou gravar um arquivo |
internal |
um defeito; o projeto fica como estava |
script |
um script ou plugin Lua falhou: erro de sintaxe ou de execução, ou um limite atingido |
ccadO ccad é um programa separado, sem dependências gráficas (roda em servidores e na CI). Ele vem nos pacotes de release; a partir do código-fonte: cargo build --release -p cc_cli (o binário é target/release/ccad).
ccad [opções] commands lista os comandos
ccad [opções] schema <comando> o esquema JSON dos parâmetros de um comando
ccad reference a referência de comandos em Markdown
ccad [opções] run <comando> [args] executa um comando
ccad [opções] script <arquivo|-> executa um script de comandos
ccad [opções] lua <arquivo|-> [args] executa um script Lua
ccad [opções] plugins lista os plugins carregados com --plugins
ccad plugins install <zip> <pasta> instala um arquivo de plugin numa pasta de plugins
ccad plugins remove <id> <pasta> remove um plugin instalado
ccad [opções] mcp serve os comandos por MCP (stdio)
-p, --project <arquivo> abre um projeto antes (.ccad, ou .ifc para importar)
--save salva o projeto no fim (no próprio arquivo)
--save-as <arquivo> salva o projeto no fim em <arquivo>
--plugins <pasta> carrega o plugin da <pasta>, ou cada plugin das suas
subpastas (pode repetir)
--lang <código> idioma dos nomes padrão e mensagens (também CCAD_LANG):
en, pt-BR, es, fr, de, it, lo, pl, uk-UA, zh-TW, zh-CN ou ja
Os argumentos de run podem ser um objeto JSON, @arquivo.json, - (entrada padrão) ou pares chave=valor, cujos valores são lidos como JSON quando possível e como texto caso contrário:
ccad -p casa.ccad --save run wall_create start=[0,0] end=[5,0] height=2.8
ccad -p casa.ccad --save run wall_create start=[5,0] end=[5,4] mid=[6,2] # parede em arco passando por mid
ccad -p casa.ccad run elements_list category=door
ccad -p casa.ccad --save run view_set '{"view": "Corte 1", "scale": 100}'
ccad -p modelo.ifc --save-as modelo.ccad run project_info # importa um IFC
ccad -p casa.ccad run sheet_export sheet=A101 path=a101.pdf
ccad -p casa.ccad run view_export view="Corte 1" path=corte.png dpi=300 # qualquer vista em PNG, SVG ou PDF
ccad -p casa.ccad run view_export view="Térreo" path=terreo.dxf # ou em DXF, em tamanho real em mm
Os resultados saem como JSON na saída padrão. Erros vão para a saída de erro como JSON, com código de saída 1; erros de uso saem com 2. Sem --save ou --save-as, o arquivo do projeto não muda.
Os resultados se combinam com outras ferramentas; por exemplo, com jq:
parede=$(ccad -p casa.ccad --save run wall_create start=[0,0] end=[6,0] | jq .id)
ccad -p casa.ccad --save run door_create wall=$parede offset=1.5
Um script é uma lista de passos: um array JSON de objetos {"command": …, "args": {…}} ou um desses objetos por linha (linhas que começam com // são comentários). ccad script executa os passos em ordem numa mesma sessão e para no primeiro erro; cada passo é um passo de desfazer.
examples/small_house.ccmacro constrói uma casa pequena:
// A small house built with engine commands only.
{"command": "wall_create", "args": {"start": [0, 0], "end": [8, 0], "height": 2.8}}
…
{"command": "door_create", "args": {"point": [2, -0.5]}}
{"command": "floor_create", "args": {"from_walls": true}}
{"command": "room_create", "args": {"point": [2, 3], "name": "Living room"}}
ccad --save-as casa.ccad script examples/small_house.ccmacro
Pisos, forros, telhados, radiers e massas recebem o contorno como curves em vez de pontos: linhas, arcos (por bulge ou por um ponto through por onde passam), círculos, elipses (inteiras ou parte delas), retângulos e polígonos regulares (estes dois viram linhas). Laços dentro do contorno são aberturas de pisos e telhados. O elemento guarda as curvas: sketch_get as devolve (ou linhas ao longo do contorno de um elemento desenhado por pontos) e sketch_set desenha o contorno de novo; mover, girar e espelhar o elemento leva as curvas junto, e editar diretamente os pontos do contorno as descarta.
{"command": "mass_create", "args": {"curves": [{"kind": "circle", "center": [0, 0], "radius": 5}], "height": 9}}
{"command": "floor_create", "args": {"curves": [{"kind": "rectangle", "corner": [0, 0], "opposite": [10, 8]}, {"kind": "circle", "center": [5, 4], "radius": 1}]}}
topography_create cria uma superfície de terreno a partir de pontos medidos [x, y, z] (cotas acima do nível) dentro de um contorno boundary ou curves; sem nenhum dos dois, o contorno convexo dos pontos o limita. Os vértices do contorno recebem as cotas que os pontos lhes dão, e a terra fecha até uma base plana base_depth (2 m por padrão) abaixo do ponto mais baixo, então os cortes a cortam como um sólido. element_get mostra as cotas mínima e máxima, a base, a área, o volume e os avisos (few-points, collinear, boundary-crossing) em derived.topography. topography_points_set substitui os pontos ou altera, remove e adiciona pontos pelo índice; sketch_set redesenha o contorno e, com points, substitui os pontos no mesmo passo. Um tipo de terreno define o material da terra e o intervalo e as mestras das curvas de nível (topography_type_create, type_set).
{"command": "topography_create", "args": {"points": [[0, 0, 0], [20, 0, 2], [20, 10, 2.5], [0, 10, 0.5], [10, 5, 1.2]]}}
pad_create conforma um platô num terreno: uma área plana na cota elevation (metros acima do nível do terreno) dentro de um contorno outline ou curves, com talude de corte onde o terreno fica acima dele e talude de aterro onde fica abaixo, cada um descendo até o terreno natural. As inclinações são a distância horizontal por unidade de altura (cut_slope 1 é 1:1, fill_slope 1,5 é 1:1,5); sem elas, o platô usa as do seu tipo (pad_type_create, type_set). O terreno host, por padrão, é aquele cujo contorno contém o centro do platô. O platô fica no nível do terreno, move-se com ele e é excluído com ele; os platôs de um terreno se aplicam na ordem de criação. element_get mostra o cut (corte), o fill (aterro), o net (aterro − corte), a area e os avisos (off-terrain, coarse, failed) de um platô em derived.pad, e o derived.topography de um terreno soma o cut e o fill dos seus platôs. As tabelas de platôs têm Elevation, CutVolume e FillVolume, que somam como volumes.
{"command": "pad_create", "args": {"outline": [[6, 3], [14, 3], [14, 8], [6, 8]], "elevation": 1.2}}
Uma cortina de vidro é uma parede cujo tipo tem uma grade de cortina em vez de camadas: linhas verticais ao longo da parede e horizontais a partir da base (a uma distância fixa, em um número de divisões ou com um espaçamento máximo, justificadas no início, no centro ou no fim), um painel em cada célula (vidro, cego, vazio ou um componente, como uma porta) e montantes nas linhas e em volta da borda. curtain_type_create cria o tipo e wall_create posiciona paredes dele, retas ou em arco (painéis planos ao longo do arco). Cada parede pode ajustar a sua grade: curtain_grid_set acrescenta, move e remove linhas e remove trechos delas (as células vizinhas viram um só painel), curtain_panel_set troca painéis e curtain_get lista linhas e painéis. Uma cortina desenhada dentro de outra parede abre essa parede onde está. Tabelas de paredes têm PanelCount, GlazedArea e MullionLength. A exportação IFC as grava como IfcCurtainWall feitas de IfcPlate e IfcMember, e a importação as traz de volta com a grade; uma cortina de outro programa volta como cortina quando os painéis formam uma grade simples, senão como objetos separados.
{"command": "curtain_type_create", "args": {"name": "Vitrine", "curtain": {"vertical": {"spacing": 1.2}, "horizontal": {"layout": "FixedNumber", "count": 2}}}}
{"command": "wall_create", "args": {"start": [2, 0], "end": [6, 0], "type": "Vitrine", "height": 2.8}}
sheet_set altera uma folha: number, size ("A0"…"A4", ou {"width": …, "height": …} em milímetros), portrait, title_block (um tipo de carimbo, ou null para nenhum), fields (os valores da folha para os campos por folha do carimbo; null limpa um) e issue_date (AAAA-MM-DD, ou ""). sheet_fields mostra o que o carimbo da folha vai ler: cada campo com seu valor, os campos por folha com o valor desta folha e o padrão, e as peças que não se resolvem. project_info_set aceita fields (campos do projeto por nome, lidos como {project:Nome}).
Um carimbo é um componente cujas peças 2D desenham a folha inteira, em milímetros a partir do canto inferior esquerdo do papel. title_block_create copia o padrão (ou começa vazio com empty); component_sheet_piece_add, component_sheet_piece_set (um merge patch sobre a peça como component_get a mostra em def.sheet) e component_sheet_piece_delete editam seus traços, textos e imagens; várias peças são adicionadas (pieces), excluídas (indices) ou alteradas e adicionadas (add) em um só passo. Uma imagem não é alterada por patch: component_sheet_piece_set a substitui com image_path (um arquivo) ou image (base64), e component_get e type_get a mostram apenas como resumo (format, width, height, bytes), nunca em base64. title_block_create recusa um nome já usado por um tipo ou por um componente. A categoria é titleblock (types_list, categories_list). type_delete pode excluir o último tipo de carimbo: suas folhas ficam então sem carimbo, e uma folha sem carimbo é desenhada como papel em branco. As expressões leem os parâmetros e SheetWidth/SheetHeight, então um carimbo serve para qualquer papel; os textos têm {campos} (sheet_number, sheet_name, sheet_count, sheet_index, sheet_scale, paper, project_name, project_number, client, address, author, date, issue_date, project:<Nome>, param:<Nome>). Um campo por folha é um parâmetro de texto com instance.
{"command": "title_block_create", "args": {"name": "Escritório"}}
{"command": "component_param_add", "args": {"type": "Escritório", "name": "Desenho", "kind": "text", "instance": true, "text": "Equipe"}}
{"command": "component_sheet_piece_add", "args": {"type": "Escritório", "piece": {"kind": "text", "x": "SheetWidth - 60", "y": 8, "text": "{param:Desenho} · {sheet_index}/{sheet_count}", "size": 2.5}}}
{"command": "component_sheet_piece_add", "args": {"type": "Escritório", "piece": {"kind": "image", "x": 15, "y": 15, "width": 30, "height": 12, "image_path": "logo.png"}}}
{"command": "view_create", "args": {"kind": "sheet", "name": "Plantas gerais"}}
{"command": "sheet_set", "args": {"sheet": "Plantas gerais", "title_block": "Escritório", "size": "A1", "issue_date": "2026-11-06", "fields": {"Desenho": "Ana"}}}
{"command": "sheet_fields", "args": {"sheet": "Plantas gerais"}}
Scripts não têm variáveis: um passo não usa o id criado por um passo anterior. Os comandos ajudam aceitando posições onde isso importa (door_create e window_create encontram a parede mais próxima de point; pisos, forros e telhados acompanham as paredes com from_walls). Para lógica entre passos, escreva um script Lua, chame ccad run a partir de um script de shell ou use um agente via MCP.
ccad lua <arquivo> executa um script em Lua 5.4 sobre a sessão. O script chama comandos com ccad.run, guarda os resultados em variáveis e faz laços, então o id criado num passo pode ser usado no seguinte. Os argumentos (nas mesmas formas do run: pares chave=valor, um objeto JSON, @arquivo.json) ficam em ccad.args; o que ele imprime vai para a saída padrão e o que ele retorna é impresso como JSON.
examples/small_house.lua constrói a casa pequena acima, com as medidas dos argumentos:
local w = ccad.args.width or 8
local d = ccad.args.depth or 6
local corners = { { 0, 0 }, { w, 0 }, { w, d }, { 0, d } }
local outer = {}
for i = 1, 4 do
outer[i] = ccad.run("wall_create", { start = corners[i], ["end"] = corners[i % 4 + 1], height = 2.8 }).id
end
ccad.run("door_create", { wall = outer[1], offset = w / 4 })
…
ccad --save-as casa.ccad lua examples/small_house.lua width=10 depth=7
A tabela ccad:
ccad.run(nome, args) |
executa um comando e devolve o resultado como tabela Lua; gera um erro se ele falhar |
ccad.try(nome, args) |
o mesmo, mas devolve nil, err na falha (err.code, err.message; veja Erros) |
ccad.commands() |
os comandos: name, kind, group e description de cada um |
ccad.describe(nome) |
um comando, com o esquema JSON dos parâmetros em schema |
ccad.args |
os argumentos do script (também ...) |
ccad.null |
o null do JSON (o nil do Lua omite o campo) |
ccad.array(t) |
marca t como lista, para que uma tabela vazia vá como [] e não {} |
ccad.json.encode(v), ccad.json.decode(s) |
texto JSON de e para valores Lua |
ccad.version, ccad.api |
a versão do ConstructCraft e a da API de plugins (1) |
Argumentos e resultados são JSON: objetos são tabelas com chaves de texto, listas são sequências ({ 0, 0 } é um ponto), e end, palavra reservada do Lua, se escreve ["end"]. Um número inteiro calculado com / (que em Lua sempre dá um número real) vai como inteiro, então 10 / 2 funciona onde se espera um id ou uma contagem.
O sandbox. Os scripts rodam num Lua restrito: as bibliotecas table, string, math, utf8 e coroutine e as funções básicas, sem io, os, debug, package, require, load, dofile nem loadfile. Um script só chega ao projeto pelos comandos, e a arquivos só pelos comandos que os leem ou gravam. Cada execução tem um limite de 500 milhões de instruções Lua e 256 MB de memória; passando deles, ela para com um erro script (capturar esse erro com pcall não faz o script continuar). Cada comando que um script executa é um passo de desfazer.
Um grafo (.ccgraph, JSON) é um conjunto de nós ligados por fios e
executado como um fluxo de dados. Todo comando do motor é um nó: seus
parâmetros são as entradas do nó e o resultado é a saída result (mais
element, o id, nos comandos *_create). Os nós internos dão valores de
entrada (number, integer, slider, boolean, text,
select_elements, elements_of_category, levels), matemática, lógica,
listas, geometria nos valores que os comandos recebem (pontos [x, y],
line, arc, circle, rectangle, rectangle_points, polygon_points,
polyline_segments, divide_line…), parâmetros de elementos
(parameter_get, parameter_set) e saídas (watch, output). Um nó Lua
executa uma função das suas entradas no sandbox (sem acesso ao modelo); ele
retorna as saídas em ordem, ou uma tabela com os nomes delas. graph_nodes
lista todos os nós com suas portas e tipos.
lacing:
shortest, longest ou cross). Uma lista de 4 pontos iniciais e 4
finais em wall_create faz 4 paredes.graph_elements lista os elementos de um grafo, graph_release
os libera (a próxima execução cria outros).project_new, project_open, undo, redo,
language_set nem grafos, e só roda comandos de arquivo quando tem
allow_files (e nunca quando um plugin o executa).ccad --save-as casa.ccad graph examples/graphs/house.ccgraph width=12 depth=8
ccad run graph_check path=examples/graphs/house.ccgraph
ccad run graph_nodes search=wall
Nós de entrada com name são as entradas do grafo (chave=valor acima,
inputs de graph_run); nós output com name são seus resultados. Um
grafo mínimo:
{
"uid": "6f1c2a0e9b3d4c8a8e2f5a7b1c3d9e02",
"nodes": [
{ "id": 1, "kind": { "builtin": "range" }, "values": { "end": 15, "step": 5 } },
{ "id": 2, "kind": { "builtin": "point" } },
{ "id": 3, "kind": { "builtin": "point" }, "values": { "y": 4 } },
{ "id": 4, "kind": { "command": "wall_create" }, "values": { "height": 2.8 } }
],
"wires": [
{ "from": [1, "list"], "to": [2, "x"] },
{ "from": [1, "list"], "to": [3, "x"] },
{ "from": [2, "point"], "to": [4, "start"] },
{ "from": [3, "point"], "to": [4, "end"] }
]
}
Um plugin é uma pasta com um manifesto plugin.toml e código Lua que acrescenta comandos ao catálogo. Os comandos dele são listados e executados como os nativos, pelo ccad run, por scripts, por scripts Lua e por agentes MCP, e se chamam <id do plugin>__<comando> (dois sublinhados, que os nomes nativos nunca têm).
ccad --plugins examples/plugins commands # o catálogo, com os comandos dos plugins
ccad --plugins examples/plugins plugins # os plugins, as permissões e os comandos deles
ccad --plugins examples/plugins run quick_rooms__rectangle_room width=4 depth=3 name=Escritório door=south
claude mcp add constructcad -- ccad mcp --plugins /caminho/para/plugins
--plugins recebe a pasta de um plugin ou uma pasta de pastas de plugins, e pode ser repetido. Um plugin que não carrega é informado na saída de erro e fica de fora; o que os plugins imprimem também vai para a saída de erro.
examples/plugins/quick_rooms é um exemplo completo. plugin.toml:
id = "quick_rooms" # letras minúsculas, dígitos e sublinhados simples, até 32
name = "Quick rooms"
version = "0.1.0"
api = 1 # a API de plugins para a qual ele foi escrito
description = "Rectangular rooms in one step, and wall totals by type."
authors = ["…"]
license = "GPL-3.0-or-later"
homepage = "https://…"
main = "main.lua" # o padrão
permissions = [] # ou ["files"], veja abaixo
main.lua roda uma vez quando o plugin carrega e registra comandos com ccad.command:
local rect = require("lib.rect") -- lib/rect.lua na pasta do plugin
ccad.command {
name = "rectangle_room", -- o comando é quick_rooms__rectangle_room
title = "Rectangular room",
description = "Four walls around a rectangle, its floor and its room.",
kind = "edit", -- "query", "edit" (o padrão) ou "file"
params = { -- um esquema JSON dos argumentos
properties = { width = { type = "number" }, depth = { type = "number" } },
required = { "width", "depth" },
},
run = function(args)
local p = rect.corners(0, 0, args.width, args.depth)
for i = 1, 4 do ccad.run("wall_create", { start = p[i], ["end"] = p[i % 4 + 1] }) end
return { room = ccad.run("room_create", { point = { args.width / 2, args.depth / 2 } }).id }
end,
}
run recebe os argumentos numa tabela e devolve o resultado do comando (uma tabela, um valor ou nada). Argumentos required que faltam são recusados antes de ele rodar; error("mensagem", 0) faz o comando falhar com essa mensagem.ccad.run que falhou, um limite atingido) tudo o que ele fez é desfeito.query só consulta; um edit consulta e edita; comandos que leem ou gravam arquivos (importar, exportar, salvar) precisam da permissão files, e só com ela se declara um comando do tipo file. Abrir ou criar um projeto, undo, redo e language_set não rodam dentro de um comando de plugin, nem o comando de outro plugin.require("a.b") carrega a/b.lua da pasta do plugin (uma vez; arquivos fora da pasta são recusados), e ccad.plugin tem o id, o name e a version dele. ccad.run só funciona enquanto um comando roda, não enquanto o plugin carrega.ccad --plugins concede o que o manifesto pede, já que você indicou a pasta.Os plugins são compartilhados pelo índice da comunidade, constructcraft-plugins: uma entrada por plugin, com de onde baixar cada versão e o checksum dela, enviada por pull request. No aplicativo, Gerenciar → Plugins instala, atualiza, desativa e remove plugins (Plugins); sem ele, ccad plugins install <arquivo.zip> <pasta> instala um arquivo baixado (verificado do mesmo jeito: caminhos seguros, tamanhos e um plugin que carrega) e ccad plugins remove <id> <pasta> remove um.
Uma peça de componente pode ser um script: código Lua que declara os parâmetros e os hotspots do componente e monta as peças a partir dos valores deles. O script é puro: ele vê os valores e nada mais (nem comandos, nem arquivos, nem o modelo), então roda uma vez para cada conjunto de valores; mover ou girar um componente já colocado não o roda de novo. examples/components/cabinet.lua é um exemplo completo.
param.length { "depth", label = "Profundidade", default = 0.55 } -- compartilhado pelos elementos do tipo
param.choice { "handle", { { "bar", "Barra" }, { "none", "Nenhum" } } }
param.length { "width", label = "Largura", default = 0.8, instance = true } -- próprio de cada elemento
param.boolean { "worktop", default = true, instance = true }
param.material { "body", label = "Corpo", instance = true }
hotspot { "plinth", 0, 0.05, 0, label = "Rodapé", shape = "diamond", color = "#ff8800" }
function geometry(p)
local pieces = { box { 0, 0, 0, p.width, p.depth, 0.85, material = p.body } }
if p.worktop then pieces[#pieces + 1] = box { 0, 0, 0.85, p.width, p.depth + 0.02, 0.03 } end
return pieces
end
| Declaração | Valor em p |
|---|---|
param.length, param.angle, param.number { id, label=, default=0, instance= } |
um número (metros, graus) |
param.boolean { id, default=false } |
true ou false |
param.text { id, default="" } |
um texto |
param.choice { id, { {chave, rótulo}, … }, default=primeira chave } |
a chave escolhida |
param.material { id, default="" } |
o nome de um material do projeto (vazio: o material da peça) |
hotspot { id, x, y, z, label=, shape="circle", color="#00ffff" } |
{ x, y, z }, onde o elemento o tem |
As declarações ficam no corpo do script, nunca dentro de geometry. Os ids são nomes (letras, dígitos, _) e não se repetem; mudar um rótulo não renomeia o parâmetro. Um parâmetro sem instance = true é do tipo, e mudá-lo muda todos os elementos do tipo; com ele, cada elemento guarda o seu valor. As formas de hotspot são circle, square, triangle, diamond e triangle_down; as cores, #RRGGBB ou #RRGGBBAA. p também traz os outros parâmetros do componente, seus planos de referência e, em portas e janelas, WallThickness.
geometry(p) devolve uma lista de peças (listas de peças são achatadas), no referencial do componente (metros a partir do ponto de inserção, x para a direita, y para trás, z para cima). Cada construtor recebe os valores em ordem ou por nome, além de name, material, void, in_plan, plan_only e detail (uma lista de coarse, medium, fine):
| Construtor | Valores |
|---|---|
box |
x, y, z, width, depth, height |
cylinder |
x, y, z, radius, height |
extrusion |
points ({x, y} em planta), z, height |
profile |
points ({u, v}, ou {u, v, radius = r} para um arco até o próximo ponto), offset, depth, plane = "plan", "front" ou "side" |
revolution |
points, offset, axis, angle (padrão 360), plane |
sweep |
path, profile, offset, plane |
blend |
bottom, top, offset, depth, plane |
mesh |
vertices ({x, y, z}), faces (listas de números de vértice a partir de 1, no sentido anti-horário vistas de fora) |
Os scripts rodam no sandbox com limites menores (20 milhões de instruções, 64 MB, 10.000 peças, um milhão de pontos), e math.random repete os mesmos números. Quando um script falha, o elemento mantém as últimas peças que funcionaram, e o erro, com a linha, aparece em element_get (derived.script_errors), na paleta de propriedades e em component_params_get; corrigir o script ou o valor o recupera.
Comandos:
ccad run component_create name=Armario 'def={"items": [{"name": "Script", "shape": {"Script": {"source": ""}}}]}'
ccad run component_script_set type=Armario piece=Script source=@examples/components/cabinet.lua
ccad run component_params_get type=Armario
ccad run component_params_set type=Armario name=handle value='"none"'
ccad run component_params_set 'elements=[100, 101]' name=width value=1.2
ccad run component_hotspot_move element=100 name=plinth 'point=[0, 0.08, 0]'
component_script_set grava uma peça de script (ou acrescenta uma). Um script que não carrega (erro de sintaxe, declaração inválida) é recusado; as declarações viram os parâmetros e hotspots do componente, os que continuam declarados mantêm os valores quando o tipo ainda serve, e o resultado lista os erros da primeira execução. Um componente tem uma peça de script; seus parâmetros mudam no script, não com component_param_set ou component_param_delete.component_params_get mostra os parâmetros e hotspots de um tipo, ou de componentes colocados de um mesmo componente, com mixed onde diferem.component_params_set define o valor de um tipo, ou o valor de instância de vários elementos de uma vez: números, true/false, textos, a chave de uma opção ou o nome de um material. É um passo de desfazer, e nada muda quando algum elemento recusa o valor.component_hotspot_move move um hotspot no referencial do componente, ou em coordenadas do projeto com world=true.Um material citado por um parâmetro conta como usado: não pode ser excluído, e renomeá-lo renomeia os valores. A exportação IFC grava as peças que o script fez, como em qualquer componente.
Gerenciar → Macros → Gravar macro grava as alterações que você fizer até apertar Parar gravação; a macro é salva como script (.ccmacro, o formato acima). Executar macro roda uma macro ou qualquer script no projeto aberto; ccad script roda os mesmos arquivos. Com uma pasta de macros definida em Preferências → Locais de arquivos, os diálogos de arquivo de macro começam nela e Executar macro vira um menu dos arquivos .ccmacro dela (mais Procurar… para qualquer outro arquivo).
Ctrl+Shift+P (ou a lupa no fim das abas do ribbon) abre a paleta de comandos. Ela encontra comandos da interface, vistas para abrir ou criar e os comandos do motor pelo nome, pela descrição ou pelo atalho, sem diferenciar acentos nem maiúsculas. Comandos do motor abrem um formulário com os argumentos em JSON, já com os campos obrigatórios; Executar (Ctrl+Enter) os roda no projeto aberto, como um passo de desfazer, e mostra o resultado. Os comandos de arquivo (project_open, ifc_export…) ficam na aba Arquivo.
A dica de cada botão do ribbon mostra o comando do motor que ele executa, para que o que você faz à mão possa virar um script.
ccad mcp é um servidor Model Context Protocol na entrada/saída padrão. Cada comando é uma ferramenta com o mesmo nome, descrição e esquema de entrada; as consultas são marcadas como somente leitura. O servidor mantém uma sessão, então um agente abre ou cria um projeto, trabalha nele ao longo de várias chamadas e o salva.
Claude Code:
claude mcp add constructcad -- ccad mcp
# ou já com um projeto aberto
claude mcp add constructcad -- ccad mcp -p /caminho/para/casa.ccad
Claude Desktop e outros clientes (claude_desktop_config.json ou as configurações MCP do cliente; use o caminho completo do ccad):
{
"mcpServers": {
"constructcad": { "command": "/caminho/para/ccad", "args": ["mcp", "--lang", "pt-BR"] }
}
}
Exemplos de pedidos que um agente resolve com essas ferramentas: “abra casa.ccad, liste as portas sem marca e numere-as”, “importe modelo.ifc e diga o volume das paredes de concreto”, “crie um pavimento superior 3 m acima do térreo com as mesmas paredes externas”, “exporte a folha A101 em PDF”.
Observações:
ccad roda.isError e o objeto de erro, para que o modelo corrija a chamada.crates/cc_cli/src/mcp.rs (JSON-RPC 2.0, uma mensagem por linha).Toda funcionalidade de usuário nasce como comando do motor; o aplicativo chama o comando em vez de alterar o documento.
crates/cc_engine/src/commands/<área>.rs: #[derive(Debug, Deserialize, Serialize, JsonSchema)], #[serde(deny_unknown_fields)], um comentário de documentação (a descrição do comando) e um em cada campo (a descrição do parâmetro; um teste falha sem eles). O código e os comentários são em inglês.Command com NAME (snake_case), KIND e run. Resolva referências com refs, altere o modelo dentro de commands::edit (um passo de desfazer, recusado se o resultado precisar de reparo) e devolva JSON (created(s, id) para elementos). Use mensagens t! para erros que pessoas vão ler.registry.rs.crates/cc_engine/tests/commands.rs por Session::execute.cargo run -p cc_cli -- reference > docs/commands.md (um teste falha enquanto ela estiver desatualizada).Session::run(Comando { … }), actions::run_command ou os auxiliares de engine_edit (use Session::run_merged para valores arrastados). Isso também o torna gravável em macros.Comandos acrescentados durante a execução implementam cc_engine::Extension (crates/cc_engine/src/extension.rs) e são postos na sessão com Session::set_extension; cc_plugins::PluginHost é a dos plugins Lua. Session::commands, describe e kind_of cobrem os dois, e Session::execute roda um comando de extensão como um passo de desfazer (Document::squash_since).
Os detalhes de arquitetura estão em AGENTS.md.