Repository navigation
Description
Summary
Ship v2.5.0 as the next stable release: everything currently on develop (including #5416), with an explicit minor bump so this is not published as 2.4.18.
GitVersion on both main and develop is increment: Patch. A blank Prepare Release will still tag v2.4.18. Use Version override = 2.5.0.
Shipped: v2.5.0-beta.1 (2026-09-03), then stable v2.5.0 (2026-09-11) via #5673. Back-merge #5674 open.
Why 2.5.0 (not 2.4.18, not 3.0.0)
| Option | Verdict |
|---|---|
| 2.5.0 | Recommended. Same pattern as v2.2.3 → v2.4.0. v2 is still the product generation. |
2.4.18 |
Do not. Patch with breaking API (View.Text, IAcceptTarget, CM deletion). |
3.0.0 |
Only if we want to honor Terminal.Gui/README.md literally (“MAJOR for breaking changes”) and start treating 2.x as frozen. Bigger product statement than 2.4.0 was. |
#5411 (MEC shims, [Obsolete]) already shipped in v2.4.17. 2.5.0 is the hard-removal / remaining-breaks train.
Beta vs stable: beta first — v2.5.0-beta.1 is live. Stable cut is the remaining user decision after soak.
Current state (2026-09-11)
| Surface | State |
|---|---|
| Latest stable | v2.5.0 on main / GitHub Release (2026-09-11 ~6:18am MT). NuGet push succeeded (indexing may lag). |
| Previous prerelease | v2.5.0-beta.1 (2026-09-03) |
| Release PR | #5673 merged ece73d25 (merge commit) |
| Back-merge | #5674 open (main → develop) |
| #5416 / #5656 | Merged earlier on the train |
| Ecosystem | All 10 canaries had validated on 2.5.0-beta.1; bump to stable 2.5.0 is follow-up |
Breaking changes in 2.5.0
On develop / in v2.5.0-beta.1
| PR | What broke | Consumer action |
|---|---|---|
| #5371 (fixes #5366) | View.Text is non-virtual; CWP TextChanging / OnTextChanging(string) / OnTextChanged() |
Replace override of Text with CWP overrides; TextField no longer hides Text with new |
| #5395 (fixes #5369) | IAcceptTarget moved to Terminal.Gui.Input |
Fix usings |
| #5416 (fixes #4367) | Deletes legacy ConfigurationManager / [ConfigurationProperty] / scope types that #5411 only marked [Obsolete]; nested config.json only |
Migrate to TuiConfigurationBuilder + Settings POCOs; run Tools/MigrateConfig on custom config.json |
Notable non-breaking already on develop
- Editable
NumericUpDowntext mode (Fixes #5469 - Add editable text mode to NumericUpDown #5587) - TableView wide-content horizontal scrolling (Fix TableView horizontal scrolling for wide content #5609)
- Platform detection simplification (Fixes #5604 - Fix and simplify platform detection #5600)
SynchronizationContextfix (Fixes #5579. SynchronizationContext is not correctly implemented in v2 #5588) + session-scoped context (Fixes #5636 - Scope MainLoopSyncContext to running sessions (await-before-RunAsync deadlock) #5641 / IApplication.RunAsync deadlocks after await on ambient SynchronizationContext #5636)- Native ANSI size detection (Fixes #5617. Prefer native ANSI size detection #5619)
- Kitty: preserve repeated legacy input after detection (Fixes #5616. Preserve repeated legacy input after kitty detection #5618)
- TextValidateField cursor (Fixes #5468. Fix TextValidateField cursor rendering #5620)
- Dirty-row flag sync (Fixes #5601. Synchronize dirty-row flags after output #5602)
- Release-workflow branch-name env fix (ci: read the release branch name from env instead of interpolating it #5603)
- DropDownList stale popover fix (Fixes #5635. Hide active popover on DeRegister to clear stale cells #5657 / DropDownList leaves stale popover contents after handled Enter #5635)
- NativeAOT
RuneJsonConverterIL2026 fix (Fixes NativeAOT IL2026 in RuneJsonConverter #5659)
Leave other open drafts out unless they merge first: #5606, #5456.
Workstream 1 — Finish #5416 (gate) — DONE
- Rebase / merge
origin/developintotig/remove-cm-followup; resolve conflicts - Phase D: nested
Resources/config.json, peek-and-warn for legacy flat keys, deleteScopeJsonConverter - Phase E: delete public CM types; port or delete leftover CM tests/benchmarks; update UICatalog/examples (
CM.Enable()) - Keep
Tools/MigrateConfigas a non-shipping aid; document it fromdocfx/docs/config.md - Measure NativeAOT size vs the A2 baseline (22.77 MB) recorded in FIXES #4367 - BREAKING CHANGE - Remove legacy ConfigurationManager after MEC migration #5416 — NativeAotSmoke win-arm64 23.50 MB → 23.08 MB (−1.78%)
- Mark FIXES #4367 - BREAKING CHANGE - Remove legacy ConfigurationManager after MEC migration #5416 ready for review, CI green, merge to
develop(8c9b818d, 2026-09-02 6:16pm MT) - Confirm a later
developpush published2.5.0-develop.N(see Workstream 2). The 5416 merge itself published2.4.18-develop.54.
Workstream 2 — Version bump on develop — DONE except stable override
GitVersion keeps increment: Patch on develop. #5656 landed +semver: minor (commit/PR title/merge message all minor-only; do not also put +semver: major in the message — GitVersion 6 major regex wins).
- Land a
developcommit whose message contains+semver: minor(Addresses #5630. Bump next version to 2.5.0 for breaking API +semver: minor #5656 /3b848938) - Confirm subsequent develop NuGet packages are
2.5.0-develop.N(2.5.0-develop.55….58on nuget.org) - Beta Prepare Release used Version override =
2.5.0→v2.5.0-beta.1 - At stable release time, Prepare Release Version override =
2.5.0again. Do not leave it blank - Do not add a permanent
next-version: 2.5.0toGitVersion.yml(the tag is the source of truth after release)
Note: Terminal.Gui/README.md says develop increments Minor, but GitVersion.yml actually increments Patch. Out of scope unless we want to fix it here; +semver: minor + version override are enough for 2.5.0.
Workstream 3 — Docs before the tag — DONE
Landed with #5416 unless noted.
- Rewrite
docfx/docs/config.mdaroundTuiConfigurationBuilder, Settings POCOs, nested JSON,Tools/MigrateConfig - Update
docfx/docs/newinv2.md(MEC samples; points leftover CM atmigrate-cm-to-mec.md) - Update
docfx/docs/migratingfromv1.md(point v1 CM users at MEC) — PR #5658 merged - Add a short 2.5.0 breaking-changes section (
View.TextCWP,IAcceptTargetnamespace, CM deletion,config.jsonshape) — PR #5658 (docfx/docs/breaking-changes-2.5.0.md) merged - Confirm
Terminal.Gui/README.mdversioning table vs what we actually ship — PR #5658 merged (table now Patch ++semver: minornote) - No remaining
ConfigurationManager.Enablecalls in UICatalog / examples (leftover mentions are specs + migrate table) -
docfx/docs/migrate-cm-to-mec.mdexists
API docs deploy from develop via api-docs.yml. Docs leftovers closed in #5658 before the beta tag.
Workstream 4 — Ecosystem validation (gate) — DONE
All dependents validated and merged against public Terminal.Gui 2.5.0-beta.1 (after earlier canaries on 2.5.0-develop.55 / winprint on .57).
Dependent tui-cs repos: Editor, cli, Terminal.Gui.templates, PSTui, TerminalGuiDesigner, Examples, ai, clet, mdv. Plus tig/winprint. Not TG-dependent: tuirec, VTTest, F7History, NStack.
Per-repo checklist (all done):
- Bump
Terminal.Guito public2.5.0-beta.1from nuget.org - Build clean, tests green (or no CI where the repo has none)
- Fix 2.5.0 breaks as encountered (
View.TextCWP,IAcceptTargetnamespace, CM deletion) - PR opened, DO NOT MERGE warning removed after public pin, merged
| Repo | PR | Result |
|---|---|---|
| Editor | #287 | merged |
| cli | #43 | merged |
| Terminal.Gui.templates | #39 | merged |
| PSTui | #30 | merged |
| TerminalGuiDesigner | #326 | merged |
| Examples | #4 | merged |
| ai | #3 | merged |
| clet | #202 | merged |
| mdv | #7 | merged |
| winprint | #272 | merged (incl. AOT after #5659) |
tig/winprint specifics:
- Bump to
2.5.0-beta.1(via2.5.0-develop.57for AOT proof, then public beta) - Replace
ConfigurationManager.EnablewithTuiConfigurationBuilder, preserving config locations - Build + tests green (
WinPrint.TUI.UnitTests,WinPrint.TUI.UITests); five AOT publishes green - Theming from
./.tui/wp.config.jsonpreserved in the port
Docs follow-up: ai-v2-primer.md / llms.txt Schemes.Resolve row — done in #5658 (SchemeManager.GetScheme; Schemes has no Resolve).
Issue tracker — close (or decide) before Prepare Release
Gate-found regressions:
- IApplication.RunAsync deadlocks after await on ambient SynchronizationContext #5636 —
IApplication.RunAsyncdeadlock afterawaiton ambientSynchronizationContext(fixed in Fixes #5636 - Scope MainLoopSyncContext to running sessions (await-before-RunAsync deadlock) #5641, shipped in FIXES #4367 - BREAKING CHANGE - Remove legacy ConfigurationManager after MEC migration #5416) - LinearRange legend renders stray characters (regression vs 2.4.5) #5637 —
LinearRangelegend stray characters (fixed in Fixes #5640. Prevent custom renderer text overdraw #5642) - ANSI printable-suppression window swallows real Tab within 50ms of Shift+Tab #5638 — ANSI suppression window swallows real Tab after Shift+Tab
- TextView new-Text setter: guard flag not cleared in finally — throwing TextChanged subscriber permanently breaks polymorphic Text sync #5639 —
TextViewnew-Text setter guard flag not cleared infinally(Fixes #5639. Harden TextView text synchronization #5645)
Train regressions:
- TextField with long Text expands vertically and overdraws following controls #5640 —
TextFieldlong-Text vertical expansion / overdraw (Fixes #5366 - BREAKING CHANGE - Make View.Text notifications CWP-compliant and non-virtual #5371 fallout; fixed in Fixes #5640. Prevent custom renderer text overdraw #5642 /e4ece860) - DropDownList leaves stale popover contents after handled Enter #5635 —
DropDownListstale popover contents after handled Enter (PR #5657 mergedb2b26ae7, 2026-09-03 12:53pm MT)
Release tasks:
- Update hosted tui-config-schema.json for nested MEC config shape #5631 — hosted
tui-config-schema.json→ nested MEC shape (in FIXES #4367 - BREAKING CHANGE - Remove legacy ConfigurationManager after MEC migration #5416)
Verify-and-close after #5416 merges:
- [ModuleInitializer] ConfigProperty.Initialize deadlocks against concurrent type loading (parallel xunit collections) #5624 — CM
[ModuleInitializer]deadlock (verified gone after FIXES #4367 - BREAKING CHANGE - Remove legacy ConfigurationManager after MEC migration #5416; remainingInitializeConfigurationonly binds known Settings POCOs, does not walk assemblies)
Decide (gate or explicitly defer to 2.6):
- V2 has severe performance regressions #5323 — v2 performance regressions — deferred to later 2.x (not a 2.5.0 gate). Performance Gate still red on ThemeSwitch on recent heads; not a merge blocker for beta/stable of this train. Behavior notes still worth documenting later: unknown
"Theme"now silently ignored (CM threw); text-field cursor now underline;Popovernow a screen-filling transparent overlay; ANSI driver sizes asynchronously;Selectorpads fixed-width labels; M.E.Configuration floor 10.0.11 → NU1605.
Workstream 5 — Release execution — BETA DONE; STABLE SHIPPED 2026-09-11
Follow CONTRIBUTING.md Release Process. Do not tag by hand. Prepare Release always checks out develop.
Pre-flight
- FIXES #4367 - BREAKING CHANGE - Remove legacy ConfigurationManager after MEC migration #5416 merged, not draft
-
developrequired CI green at beta cut (Build Validation, Unit Tests 3 OS, Integration Tests 3 OS). Performance Gate / V2 has severe performance regressions #5323 deferred — not a blocker - NativeAOT smoke on the 5416 train (−1.78%); Fixes NativeAOT IL2026 in RuneJsonConverter #5659 fixed IL2026 for consumer AOT (winprint)
- Develop NuGet was
2.5.0-develop.*before the beta tag - Conceptual docs updated (Workstream 3 leftovers) — Docs: 2.5.0 CM/MEC leftovers for #5630 #5658 merged
- Ecosystem validation complete: nine tui-cs dependents + winprint merged on
2.5.0-beta.1(Workstream 4) - Chose beta first (
v2.5.0-beta.1)
Prepare Release — beta (DONE 2026-09-03)
| Input | Value used |
|---|---|
| Release type | beta |
| Version override | 2.5.0 |
- Release PR opened into
main: PR #5660 (release/v2.5.0-beta.1) - Required CI green on that PR
- Title/tag is
v2.5.0-beta.1, notv2.4.18 -
GitVersion.ymlmain label set tobeta - Merged with a merge commit (not squash); Finalize keyed off
release/
After Finalize — beta (DONE)
- Annotated tag
v2.5.0-beta.1exists - GitHub Release exists (prerelease); breaking changes pasted at the top
- NuGet.org shows
Terminal.GuiandTerminal.Gui.Interop.Spectre2.5.0-beta.1 - Back-merge PR merged: PR #5661 (
main→develop,145585dd) - Confirm
developNuGet is2.5.1-develop.N(publish after Back-merge v2.5.0-beta.1 from main into develop #5661; check nuget.org) -
tui-cs/Terminal.Gui.templatesbumped via #39 -
tui-cs/Editorbumped via #287 - Docs site content for MEC / breaking changes landed in Docs: 2.5.0 CM/MEC leftovers for #5630 #5658 (deploy from develop)
Prepare Release — stable (DONE 2026-09-11)
Soak v2.5.0-beta.1, then:
| Input | Value |
|---|---|
| Release type | stable |
| Version override | 2.5.0 (required; never blank) |
- Release PR opened into
main: PR #5673 (release/v2.5.0) - CI green on that PR
- Title/tag is
v2.5.0, notv2.4.18/ not another beta -
GitVersion.ymlmain label is''(stable) - Merged with a merge commit (not squash):
ece73d25(2026-09-11 ~6:17am MT) - Annotated tag
v2.5.0exists - GitHub Release exists (stable); breaking changes at the top
- NuGet.org push succeeded for
Terminal.GuiandTerminal.Gui.Interop.Spectre2.5.0(workflow 34598229813; package page may lag a few minutes) - Back-merge PR opened: PR #5674 (
main→develop) — merge when CI green - Closing this issue — stable cut complete; NuGet publish in flight / confirm on nuget.org
GitHub Release notes (paste at top after finalize)
Already applied on v2.5.0-beta.1. Reuse for stable:
## Breaking changes
This is a minor bump because v2 still accepts planned API breaks. Apps that compiled against 2.4.17 may need source changes.
1. **`View.Text` is no longer virtual** (#5371 / #5366)
- Use `OnTextChanging(string proposedValue)` / `TextChanging` to validate or cancel.
- Use `OnTextChanged()` for post-change sync.
- `TextField` uses `View.Text` directly (no `new` hider).
2. **`IAcceptTarget` moved to `Terminal.Gui.Input`** (#5395 / #5369)
- Add `using Terminal.Gui.Input;`.
3. **Legacy `ConfigurationManager` removed** (#5416 / #4367)
- Replacement: `TuiConfigurationBuilder` and Settings POCOs (`ButtonSettings.Current`, etc.).
- `config.json` is nested only. Convert old flat-key files with `Tools/MigrateConfig`.
- Types marked `[Obsolete]` in 2.4.17 (#5411) are gone.
See the configuration deep dive and the 2.5.0 migration notes.
## Highlights
- Editable NumericUpDown
- TableView horizontal scrolling for wide content
- Native ANSI size detection; platform detection cleanup
- SynchronizationContext fix
- Kitty protocol: preserve repeated legacy input after detection
- DropDownList: hide active popover on DeRegister (#5635)
- NativeAOT: RuneJsonConverter no longer trips IL2026 (#5659)Sequence — DONE
v2.5.0-beta.1 → soak → Prepare Release stable → #5673 merge → tag v2.5.0 + GitHub Release → NuGet + #5674 back-merge → close #5630
Out of scope
- Changing GitVersion
developincrement from Patch → Minor (README already claims Minor) - Shipping Fix platform table and ARM64 ioctl guard defects following #5600 #5606 / Document app-first Terminal.Gui agent design loop, snapshot contract, and self-improvement pipeline #5456 in this train unless they merge first
- v1 branches
- Manual
git tag/ pushingmainfrom a stale localmain - Unlisting
2.4.18-develop.54unless we explicitly decide to - Fixing Performance Gate / V2 has severe performance regressions #5323 ThemeSwitch regressions in this train
Activity
tig commentedon Aug 22, 2026
Related: #5416 (gate), #5371, #5395, #5411 (already in v2.4.17), #4367, #5366, #5369.
[-]Release v2.5.0 — breaking-change minor[/-][+]Release v2.5.0 - breaking-change minor[/+]tig commentedon Sep 3, 2026
Status as of 2026-09-03 (America/Denver):
Done
develop(8c9b818d). Also closed Proposal (post v2) - Replace CM with MEC #4367, Update hosted tui-config-schema.json for nested MEC config shape #5631, IApplication.RunAsync deadlocks after await on ambient SynchronizationContext #5636 (via Fixes #5636 - Scope MainLoopSyncContext to running sessions (await-before-RunAsync deadlock) #5641).3b848938,+semver: minoronly). NuGet is2.5.0-develop.55(5416 had published the footgun2.4.18-develop.54).e4ece860; on2.5.0-develop.55).docfx/docs/config.mdon develop is MEC /TuiConfigurationBuilder; CM is documented as removed in 2.5.0.Still open
[ModuleInitializer]deadlock is gone after FIXES #4367 - BREAKING CHANGE - Remove legacy ConfigurationManager after MEC migration #5416 (code path deleted).2.5.0-develop.55(ConfigurationPropertygone,View.Textno longer virtual, MEC 10.0.11), then cli / templates / PSTui / TerminalGuiDesigner / Examples / ai / clet / mdv / winprint.2.5.0. Do not run it yet.Retarget Terminal.Gui pin to public 2.5.0-develop.55
Docs: 2.5.0 CM/MEC leftovers for #5630 (#5658)
tig commentedon Sep 3, 2026
Workstream 5 started: Prepare Release dispatched with
release_type=betaand Version override =2.5.0.2.5.0-beta.1/ tagv2.5.0-beta.1release/v2.5.0-beta.1→main)GitVersion.ymlmain label set tobetaEcosystem canaries stay unmerged until
Terminal.Gui 2.5.0-beta.1is on nuget.org.tig commentedon Sep 3, 2026
Workstream 5: v2.5.0-beta.1 is tagged.
main(merge commit60ce99db, 2026-09-03 2:48pm MT). Not squash.v2.5.0-beta.1+ GitHub pre-release: https://github.com/tui-cs/Terminal.Gui/releases/tag/v2.5.0-beta.1main→develop)Ecosystem canaries stay unmerged until
Terminal.Gui 2.5.0-beta.1is on nuget.org, then swap pins.tig commentedon Sep 3, 2026
Back-merge landed and the beta package is public.
develop(145585dd, 2026-09-03 3:06pm MT). Required tests green; Performance Gate still red (ThemeSwitch / deferred V2 has severe performance regressions #5323).Terminal.Gui2.5.0-beta.1 andTerminal.Gui.Interop.Spectre2.5.0-beta.12.5.1-develop.N): https://github.com/tui-cs/Terminal.Gui/actions/runs/33806083895Next: retarget ecosystem canaries from
2.5.0-develop.N→2.5.0-beta.1, then merge those PRs once CI is green.Update to TG 2.5.0-beta.1 (#7)
Update to TG 2.5.0-beta.1 (#3)
Update to TG 2.5.0-beta.1 (#326)
Update to TG 2.5.0-beta.1 (#43)
Update to TG 2.5.0-beta.1 (#202)
Update to TG 2.5.0-beta.1 (#287)
Update to TG 2.5.0-beta.1 (#30)
tig commentedon Sep 4, 2026
Workstream 4 complete: all ecosystem canaries merged on public
Terminal.Gui 2.5.0-beta.1.Workstream 5 already shipped: tag/NuGet/GitHub Release
v2.5.0-beta.1, back-merge #5661 on develop.Remaining for #5630: soak the beta, then Prepare Release again with
stable+ version override2.5.0when ready forv2.5.0. Performance Gate / #5323 stays deferred.[-]Release v2.5.0 - breaking-change minor[/-][+]Please Test v2.5 Beta! - breaking-change minor[/+]YourRobotOverlord commentedon Sep 5, 2026
@tig
Upgrading Xtimato to
2.5.0-beta.1gave me the incentive to finally migrate from my bespoke config system to TuiConfigurationBuilder.The transition was painless, and Astra one-shotted the changes across 33 files with zero issues.
I gotta say, this is a wonderful improvement over the old config system, which I found to be too inflexible to wrangle to my needs.
Now my config is simpler and easier to maintain.
Thanks, I love it!
tig commentedon Sep 11, 2026
Main is now 2.5.0. Release is publishing.
tig commentedon Sep 11, 2026
Stable v2.5.0 shipped 2026-09-11 via #5673 (merge commit
ece73d25). Tag + GitHub Release (breaking changes at top). NuGet publish workflow succeeded forTerminal.Gui/Terminal.Gui.Interop.Spectre2.5.0. Back-merge open: #5674.