v0.1.0-alpha · core works end-to-end
AGPL-3.0-or-later Python 3.11 747 tests · all green github ↗
Karakulak — Anatolian caracal mark
Karakulak

Visual scripting for structural engineers — without renting Rhino, Revit, or anyone else's host.

An open-source node graph that builds parametric structural models and pushes them into Tekla, ETABS and SAP2000 as native elements, runs gravity analysis through bundled PyNite (or OpenSees), and exports IFC4 on every cycle.

6
backends
747
tests passing
17
ADRs
0.1.0
alpha
§ 01 / why

A gap commercial tooling refuses to fill.

Grasshopper–Tekla Live Link, CSiXRevit, Speckle — all assume you already own Rhino, Revit, or a Tekla maintenance contract. Engineering offices that don't have no good open-source alternative for visually authoring parametric structural models that round-trip to FEA and detailing software. Karakulak is that alternative.

01 / standalone

No host required.

A Python desktop application — its own first-class node editor, not a plugin renting space inside Rhino, Blender or Revit.

pyside6 · nodegraphqt
02 / native push

Models become real elements.

Beams, columns and slabs land in Tekla, ETABS and SAP2000 as their actual element types — through OAPI and the Tekla .NET API — not as reference geometry a detailer has to redraw.

tekla · etabs · sap2000
03 / analysis bundled

PyNite ships in the box.

Pure-Python linear-static analysis runs in-process — no external tool, no binary, no environment variable. Press Push, get displacement and reactions back on the canvas.

pynitefea · mit · default
04 / turkish-codes-aware

TBDY 2018 in the core.

Beam flexure (§7.4), column axial (§7.3) and strong-column-weak-beam (§7.3.5) check nodes. ρ_min, confinement zones, cover, bar spacing inline; deep helpers via [tbdy_full].

tbdy 2018 · ts 500
05 / persistent live-link

Updates, not duplicates.

Change a parameter and re-push. IFC GlobalId, ETABS label and Tekla GUID survive save / load / reopen — the same element is rewritten, not cloned next to itself.

guid · label · globalid
06 / ifc first-class

BIM is a side-channel, not an afterthought.

Every model emits IFC4 alongside its native push — validated, opens in BIMVision. Even when the receiver isn't Tekla or CSI, the data still lands somewhere.

ifcopenshell
§ 02 / six backends

One graph. Six places the model can go.

Four push backends drop native elements into Tekla, ETABS, SAP2000 or IFC4. Two analysis backends run linear-static, self-weight gravity analysis — PyNite is bundled and the default; OpenSees is an optional, more powerful alternative invoked through a Tcl subprocess.

Backend What it does Tracked identity Kind
ETABSv23 +
Native frames, sections and materials via the CSI COM OAPI. Frame label push
SAP2000v25 +
Same API as ETABS — 99 % shared code path. Frame label push
Teklastructures 2023 +
Native beams and columns via the .NET OAPI; round-trips through GUID. GUID push
IFC4ifcopenshell
Validated IFC4 export — opens cleanly in BIMVision and downstream BIM stacks. GlobalId push
PyNitedefault
Gravity linear-static analysis, in-process. No install, no environment variable. CI-tested every push. — analysis only bundled analyse
OpenSeesoptional
Same scope and result format as PyNite, via Tcl-script subprocess. The generated .tcl is reproducible standalone. — analysis only analyse
analysis scope · v0.1.0 — linear static, self-weight loading only.
results · node + element counts, max abs displacement (mm), Σ vertical support reactions (N).
validated against closed-form Euler–Bernoulli (cantilever δ = wL⁴ / 8 EI · simply-supported δ = 5 wL⁴ / 384 EI).
§ 03 / what's in the box

Today, not someday.

F 01

Visual node-graph editor.

Drag-and-drop parametric canvas with topological evaluation, dirty propagation and per-node error display. Nodes turn red on failure; the rest of the graph keeps running.

nodegraphqt · pyside6
F 02

TBDY 2018 / TS 500 check nodes.

Beam flexure check (§ 7.4), column axial check (§ 7.3), strong-column-weak-beam check (§ 7.3.5). Five core formulas inline; shear capacity, anchorage and Pn–Mn surface via the optional turkrebar extra.

core · [tbdy_full]
F 03

Persistent live-link state.

Parameter changes update existing backend elements instead of creating duplicates. IFC GlobalId, ETABS label and Tekla GUID are preserved across save / load / reopen. Bake All freezes state; per-backend Reset Live Link clears it.

round-trip · guid · label
F 04

Inline 3D IFC preview.

Three.js r168 viewer embedded in the application window via QWebEngineView. Updates after every evaluation cycle — no Alt-Tab to a BIM viewer to confirm geometry.

three.js · [web_preview]
F 05

European profile catalog.

IPE and HEA series (EN 10365) with searchable picker dialogs. Pushed via PropFrame.SetISection rather than ETABS catalog-file import — cross-version and cross-machine reproducible.

en 10365 · ipe · hea
F 06

Five support patterns.

FIXED, PINNED, PINNED_RX, ROLLER_Z, ROLLER_YZ. PINNED_RX + ROLLER_YZ is the stable pair for 3D simply-supported beams; FIXED for cantilevers and column bases — selectable on the canvas Support node.

support · 5 patterns
§ 04 / quick start

From open to ETABS in six steps.

  1. Launch.

    python -m karakulak — opens the node editor.

  2. Open the example.

    File → Open examples/03_tbdy_3story_frame.karakulak.

  3. Evaluate.

    Press Ctrl+E — the DAG runs; the 3D preview updates.

  4. Push to PyNite.

    Switch the Push node backend to PYNITE and press Push. Analysis runs in-process; results appear on the canvas node.

  5. Push to ETABS.

    With ETABS running, switch to ETABS and push again to create native frame elements.

  6. Edit and re-push.

    Change a column from 400×400 to 500×500. Press Ctrl+E, push — the same ETABS frames update in place.

§ 05 / architecture

Three layers. Dependencies flow downward only.

L 01
UI
no domain knowledge
PySide6 · NodeGraphQt
L 02
Engine
DAG · dirty propagation · evaluation
no UI · no Tekla · no IFC
L 03
Domain + Backends
pure python · headless · scriptable from a CLI
writers + analysis
  • data  Beam · Column · Slab · Section · Material · Support
  • codes  TBDY 2018 · TS 500 · TS profile catalog
  • writers  Tekla · ETABS · SAP2000 · IFC
  • analysis  PyNite (in-process) · OpenSees (Tcl subprocess)

Each layer is independently testable. The engine doesn't know what a beam is. The UI doesn't know what TBDY is. The domain doesn't know whether it's being rendered or pushed to a CAD process — or solved by PyNite.

dependency direction ▾
ui  →  engine  →  domain  →  backends

The dependency arrow never bends back. A backend writer can't reach up into the graph; the graph can't reach down into a writer's COM apartment — which is what keeps apartment-conflict-prone bridges (Tekla's MTA vs CSI's STA) from poisoning the rest of the codebase. 17 ADRs cover every non-obvious choice we've made, from NodeGraphQt selection to analysis-backend licensing.

docs / ARCHITECTURE.md ↗    docs / DECISIONS.md ↗

§ 06 / install

Clone, install, run pytest747 green.

Core install includes the UI, engine, domain primitives, all four push backends, PyNite analysis, and IFC export. Web preview, the full turkrebar TBDY helpers, and dev tooling are opt-in extras.

REQUIREMENTS
  • Windows 10 or 11 (macOS / Linux: UI + IFC only)
  • Python 3.11.x (not 3.12+ — pythonnet / comtypes)
  • Git
  • For OAPI: Tekla 2023+ and/or ETABS v23+ / SAP2000 v25+ — installed, licensed, and launched at least once so the COM server registers.
PyNite is bundled. OpenSees is optional — set KARAKULAK_OPENSEES_EXE if you install to a non-standard path.
Extra
What you get
pip install -e .
core — UI, engine, four push backends, PyNite, IFC, inline TBDY.
pip install -e ".[web_preview]"
PySide6-WebEngine for the inline 3D IFC preview panel.
pip install -e ".[tbdy_full]"
turkrebar — deep TBDY 2018 / TS 500 helpers (shear, anchorage, Pn–Mn).
pip install -e ".[dev]"
pytest · ruff · mypy · pytest-qt.
# clone & enter
$ git clone https://github.com/ogunc/karakulak.git
$ cd karakulak

# virtualenv
$ python -m venv .venv
$ .venv\Scripts\activate              # windows
$ source .venv/bin/activate           # linux / macOS

# dev install — pytest, ruff, mypy
$ pip install -e ".[dev]"

# run the 747-test suite
$ pytest
  ======== 747 passed in 38.4s ========

# launch the node editor
$ python -m karakulak
§ 07 / known limitations

What v0.1.0 does not do, yet.

Karakulak is alpha. Core works end-to-end, but the API, file format and feature set are still moving. Pin to a specific commit for anything production-shaped — and read the limits below before pinning expectations to them.

!

Alpha software.

API, file format and behaviour may change between commits before v0.1.0 is tagged final.

pin to a commit
!

Analysis is linear static, self-weight only.

PyNite and OpenSees apply self-weight distributed loads and run a single linear static analysis. Non-linear, dynamic, modal and imposed-load cases are not implemented.

non-linear · v0.2.0+
!

One backend family per session.

CSI and Tekla can't coexist in the same Python process — pythonnet's MTA and comtypes' STA collide with WinError −2147417850. Restart Karakulak to switch families. PyNite, OpenSees and IFC are exempt.

ADR-011 · subprocess v0.2.0
!

Per-element bake deferred.

"Bake All (IFC)" bakes every tracked element at once. Per-node bake controls and per-node live-link status indicators on element bodies are v0.2.0 scope.

bake all · today
!

Tekla cross-session regenerate — manual only.

No Windows + Tekla CI runner yet. test_regenerate_preserves_tekla_guid stays xfail(strict=True) pending one.

manual verification
!

ETABS Model Explorer may need a manual refresh.

No documented OAPI call repaints the Model Explorer tree independently of the 3D viewport. If the tree shows stale state, use View → Refresh Displays in ETABS.

workaround documented
§ 08 / license

AGPL-3.0-or-later. Or commercial, if AGPL doesn't fit.

Free as in freedom — and as in beer.

Karakulak is free software: use, study, modify and distribute under the GNU Affero General Public License v3 or later. If you run a modified version as a networked service, you must publish the modified source.

Karakulak links dynamically to LGPL-3.0 libraries (PySide6, IfcOpenShell). Dynamic linking under LGPL is permitted; users retain the right to swap LGPL libraries independently.

Default
AGPL-3.0-or-later
For open-source projects, internal tooling and research. Source disclosure required for modified networked versions.
Opt-in
Commercial license
If AGPL is incompatible — proprietary redistribution or SaaS without source disclosure — contact the maintainer. Get in touch ↗
§ 09 / the name
Caracal caracal · Anatolia, Central Asia

A karakulak is the Anatolian caracal — a stealthy, precise, agile predator. The name follows the AEC parametric-tool tradition of small-animal nicknames.

Naming kin
~
Sverchok
cricket
Beaver
beaver
Pangolin
pangolin
HoaryFox
hoary fox
Mosquito
mosquito
Karamba
— inspiration