CtrlK
BlogDocsLog inGet started
Tessl Logo

natron-maintainer

Domain knowledge for working on the Natron compositor's own C++ source code (Engine/Gui/HostSupport). Use when navigating, fixing, or extending the Natron codebase, doing Qt5/Qt6 work, building Natron, building its Sphinx docs, or triaging its GitHub issues.

75

Quality

93%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

Natron Maintainer

Overview

Natron is a node-based OpenFX-host video compositor. Its code is a stack: OpenFX host (HostSupport + libs/OpenFX) → engine (Engine) → Qt GUI (Gui), with thin App/Renderer entry points. Dependencies point downward only: Engine must never include a Gui header (so the headless NatronRenderer can link Engine without Gui).

Usage

Use this skill when:

  • Navigating or modifying the Natron C++ source (Engine/Gui/Global/HostSupport).
  • Adding or fixing a node, knob (parameter), render behavior, or the cache.
  • Doing Qt 5 / Qt 6 migration work or touching the Python (Shiboken/PySide) bindings.
  • Building Natron, running its tests, or building the Sphinx documentation.
  • Triaging or prioritizing Natron GitHub issues.

The authoritative long-form reference is the in-repo Maintainer Guide at Documentation/source/maintainers/*.rst. Read the relevant chapter there for depth; this skill is the quick map.

Core Concepts

  • Runtime object tree: appPTR (AppManager singleton) → AppInstance (one per project) → Project (a NodeCollection + KnobHolder) → NodeEffectInstance. A Node is the stable graph vertex; its EffectInstance is the (replaceable) behavior — either an OfxEffectInstance (an OpenFX plug-in) or a built-in C++ effect (ViewerInstance, RotoPaint, TrackerNode, ReadNode/WriteNode, NodeGroup, Backdrop, Dot, …).

  • Rendering is pull-based: an output effect calls EffectInstance::renderRoI(RenderRoIArgs&, …) which recurses upstream by region of interest, time, view and mip-map level; results are stored in a hashed RAM/disk Cache. Per-render context lives in thread-local ParallelRenderArgs installed by ParallelRenderArgsSetter.

  • Params are "knobs": KnobIKnobHelper → concrete KnobInt / KnobDouble / … ; owned by a KnobHolder; created via appPTR->getKnobFactory().createKnob<K>(...). Knobs are NOT QObject — each has a KnobSignalSlotHandler companion for signals.

  • Natron IS an OpenFX host: most nodes are OFX plug-ins; Engine/Ofx* glues the generic host in HostSupport/libs/OpenFX to Natron's node/knob/image model.

  • The two executables share the Engine (Gui links it; NatronRenderer links it without Gui). A third binary, natron-python, is a full Python interpreter with Natron's modules; it also installs PyPI packages into Natron's bundled Python via natron-python -m pip install <package>.

File-Naming Conventions (learn these first)

SuffixMeaning
FooFwd.hForward decls + FooPtr/FooWPtr typedefs. Engine/EngineFwd.h and Gui/GuiFwd.h are the master catalogs — start here for unknown types.
FooI.hAbstract interface (pure virtual). The Engine↔Gui seam: NodeGuiI, KnobGuiI, OpenGLViewerI, NodeGraphI, DockablePanelI. Engine holds these; Gui implements them.
FooPrivate.h/.cppPIMPL implementation of Foo (public header holds only _imp).
FooSerialization.hBoost.Serialization (XML) description; version with BOOST_CLASS_VERSION.
PyFoo.h/.cppPython-facing facade (Shiboken-bound).
OfxFoo.h/.cppOpenFX host glue.
Gui20.cpp, ViewerTab30.cppOne big class split across numbered files; numbers are grouping only.

Key Idioms

  • Everything is inside NATRON_NAMESPACE_ENTER/_EXIT (macros in Global/Macros.h); Python-exposed classes use NATRON_PYTHON_NAMESPACE.
  • Include <Python.h> first in every TU (the "PYTHON BLOCK"); it must precede standard headers.
  • std::shared_ptr/weak_ptr everywhere; parent→child is shared_ptr, child→parent is weak_ptr (avoid cycles). Add new types to the Fwd catalog.
  • QT_NO_CAST_FROM_ASCII is set: wrap literals in QString::fromUtf8("…") or tr().
  • Serialization and the Py* API are backward-compatibility-critical — version serialization changes; keep the Python API stable.

Quick Reference

Build (CMake, preferred; supports Qt6):

cmake -S . -B build -DNATRON_QT6=OFF          # Qt5+PySide2 (default)
cmake -S . -B build -DNATRON_QT6=ON           # Qt6.3+PySide6+OpenGLWidgets
cmake --build build -j
ctest --test-dir build                        # unit tests (or -DNATRON_BUILD_TESTS=OFF)

Build (qmake, Qt5 only today): qmake Project.pro && make (see INSTALL_*.md).

Code style (enforced by .git-hooks/pre-commit):

astyle -p -H -f -j -z2 -c -k3 -U -A8 -n path/to/File.cpp && git add path/to/File.cpp

Docs (Sphinx; sources in Documentation/source):

cd Documentation && sphinx-build -b html source html

Do NOT hand-edit index.rst (except to add a whole new guide to the toctree), _-prefixed files, or plugins/ (generated by tools/genStaticDocs.sh).

Qt 6 Migration Status (as of 2026)

  • Done: GL widgets already use QOpenGLWidget; CMake has NATRON_QT6 option (Qt6.3/Shiboken6/PySide6); QtCompat.h has version shims.
  • To do: QRegExpQRegularExpression (~16 files); QDesktopWidget/QApplication::desktop()QScreen (~6 files); setMarginsetContentsMargins; regenerate PySide6/Shiboken6 bindings (fixes enum/flag issue #854); bring qmake build to Qt6 parity.
  • Keep Qt 5.15 working: prefer APIs present in both; else shim in QtCompat.h; else guard with #if QT_VERSION >= QT_VERSION_CHECK(6,0,0).
  • Full plan: Documentation/source/maintainers/qt6-migration.rst.

Issue Triage Method

Fetch open issues via the GitHub API and aggregate by label:

curl -s "https://api.github.com/repos/NatronGitHub/Natron/issues?state=open&per_page=100&page=1"

Exclude items with a pull_request key (those are PRs). Labels: type:*, func:*, prio:*, difficulty:*, status:*. Prioritize: P0 stability/data-loss (crashes, cannot-launch, cannot-render), P1 sustainability (Qt6, CI, distribution), P2 confirmed functional bugs + popular features, P3 polish. Full analysis: Documentation/source/maintainers/issue-triage.rst.

Common Mistakes

  • Including a Gui header from Engine (breaks the headless renderer). Use a …I interface instead.
  • Reading live node state during a render instead of the captured hash/args in ParallelRenderArgs (causes inconsistent renders / stalls).
  • Changing a *Serialization struct without a version bump (breaks users' project files).
  • Making a core value-type a QObject for signals — use the KnobSignalSlotHandler companion pattern.
  • Editing only one of the two build systems (qmake and CMake must stay in sync).
Repository
NatronGitHub/Natron
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.