v2.0.0-beta.2
Pre-release
Pre-release
GTKX 2.0 beta 2 is a hardening release shaped by the first real-world GTKX 2 migrations. It aligns generated bindings with GIR and JavaScript member precedence, adds typed escape hatches for GObject signals and properties, and strengthens build, deployment, internationalization, headless, MCP, and project-creation workflows.
GTKX 2.0 beta 2 is a prerelease. The final GTKX 2.0 release is scheduled for December 1, 2026, after the migration and hardening period.
Breaking Changes and Migration
- Regenerate bindings after upgrading. GIR
shadowsmetadata now selects the canonical API name, so useGio.Subprocess.new(argv, flags)instead of the previously exposed inheritednewvmember. More-specific class and interface methods keep their natural camelCase names, includingGio.Socket.connect(...)andGUdev.Device.getProperty(...), instead of conflict-renamed variants. - Use explicit GObject escape hatches when names collide. Call
GObject.signalConnect,GObject.signalDisconnect, orGObject.signalEmitwhen a native method owns a usual signal-helper name. UseGObject.getObjectPropertyandGObject.setObjectPropertywhen a method owns a generated property name. - Rebuild before using
gtkx deploy --skip-build. Build metadata is now format 2 and records the selected configuration and its production digest; older or mismatched output is rejected. - Build and deployment output paths are safer. GTKX refuses unmanaged nonempty directories, symlink-reached paths, paths outside the project, and overlapping build/deploy destinations instead of erasing them.
- Static translation extraction is stricter. Recognized aliases, member calls, dynamic keys or source values, and unsupported plural forms now fail extraction instead of silently omitting messages. Rewrite them with literal keys and supported
torTransforms. - The existing Node.js 26.7.0 minimum is now enforced immediately at GTKX CLI, configuration, and Vitest entry points.
Generated Bindings and Runtime
- Generated APIs now follow GIR
shadowsmetadata and ordinary JavaScript precedence across classes and interfaces. Natural subclass methods win at runtime and in TypeScript while nominal inheritance remains intact. GObject.signalConnect,signalDisconnect, andsignalEmitinfer signal names, handlers, arguments, and results even when methods such asconnectoremitare shadowed. Registered-class and multi-interface signal precedence now matches the native GSignal owner.- Descriptor-free
GObject.getObjectPropertyandsetObjectPropertyinfer readable and writable property names and values from generated and registered property maps. They preserve native methods when a method and property share a name. - Promise generation now handles async/finish pairs with progress or side callbacks, retains callbacks until asynchronous completion, and leaves unsupported async shapes callback-based instead of generating an incorrect Promise wrapper.
- Native fixes cover first-use
GStrvregistration, nested null-terminated arrays, callback lifetimes, initable-only factories, GError virtual methods, and construction/type validation. - A GLib
CRITICALtrapped by a generated binding call no longer also prints through GLib's default logger; it remains catchable from the call or generated promise. - GTKX now diagnoses conflicting process-wide GLib main-context ownership when GI bindings are imported from another worker thread.
Build and Deployment
gtkx codegen,gtkx build, andgtkx deployshare a project-relative--config. Builds record the selected configuration sodeploy --skip-buildcannot package output produced for another config.- Build output replacement is transactional: failed builds restore the previous output, while successful builds remove stale managed files and preserve the output directory's identity, mode, and top-level
.gitdata. Repeated deployments safely clear stale files from GTKX-owned output directories. - Self-contained builds reject unresolved runtime package loads through
require,createRequire, aliases, namespace imports, and equivalent forms that would leave dependencies outside the artifact. gtkx build --outproduces an independently runnable output tree, whilegtkx deploy --outremains the deployment work and artifact directory.- Deployment adds shell-safe
deploy.launcherEnvanddeploy.nodeFlags, AppStreammetainfoExtra, hardenedextraFilespaths and modes, and repeat-deploy cleanup. - The bundled Node.js download is pinned independently of the host. Host and configured-path runtimes are version-checked, and an explicitly configured version must match the selected binary.
- Debian and RPM glibc requirements are derived from every staged ELF file, including the Node runtime,
gtkx.node, other native assets, and ELF files supplied throughdeploy.extraFiles.
Headless Development, Testing, and MCP
gtkx dev --headlessstarts an isolated Wayland display on machines without a graphical session.--size WIDTHxHEIGHTselects its resolution and defaults to1024x768; live MCP inspection and screenshots continue to work.- The detached parent-death guard now tracks the exact Sway and D-Bus process groups and their private runtime directory, so abrupt worker termination cleans them up.
- MCP widget tools wait for the requested application to register instead of failing during startup. Long
$XDG_RUNTIME_DIRpaths use a deterministic short socket in a private, user-owned directory. - MCP startup, handover, disconnect, socket replacement, and server-shutdown races were fixed without removing unrelated filesystem entries.
- Testing activation now explicitly uses GTK widget semantics when a subclass such as
Adw.ActionRowowns a naturalactivatemethod.
Internationalization
- Extraction validates the lexical identity of
t,useTranslation,Trans, andTransWithoutContext, including aliases, optional/member calls, tagged templates, prefixes, contexts, defaults, nested references, and option objects. - Unsupported cardinal categories and syntax that the upstream extractor cannot represent are rejected rather than disappearing from POT, resource, or generated TypeScript output.
- During
gtkx dev, a source save re-extracts the POT and regenerates i18n declarations before Fast Refresh while leaving translator-owned PO files unchanged until codegen or build. - Catalog creation and refresh remain transactional, so malformed input cannot leave only part of the translation output updated.
Project Creation
- The scaffold accepts a display name, propagates it safely into source and configuration, and creates a Node 26
mise.toml. --overwritereplaces only scaffold-owned files rather than deleting unrelated contents, rejects symlinked destinations, and joins an existing parent Git repository instead of nesting another repository.
(#611)
Full changelog: v2.0.0-beta.1...v2.0.0-beta.2