Upgrade notes
Move a Tooee 0.12 app to 0.13, a Tooee 0.9 app to 0.12, and a Tooee 0.8 app to 0.9.
bun add @tooee/view@^0.13.0 @opentui/core@^0.5.12 @opentui/react@^0.5.12Upgrade every @tooee/* package to the same version. Each section lists the changes you can meet on the way, newest first.
Upgrade from 0.12 to 0.13
Read the value in onSubmit or onConfirm
Enter in Ask always calls onSubmit, and Enter in Choose always calls onConfirm. launch() from @tooee/ask and @tooee/choose now resolves with the value. Before, an action with the id submit took the place of the callback, and launch() resolved null. That action is now an ordinary command that runs from the palette or from its own hotkey. Move code that read the value in a submit action into onSubmit or onConfirm. Ask and Choose show the callbacks.
Expect ctx.exit() to close the app
The command context now uses the renderer's destroy as the default exit. ctx.exit() closes View and every launchCli app, where it did nothing before. A context source can still supply its own exit, as Ask and Choose do.
Move off the old directory keys
In the directory view, dir.next-file is now g n and dir.prev-file is g p. h and l only scroll wide blocks and diffs. To keep the old keys, set "dir.next-file": "l" and "dir.prev-file": "h" in keys.
Use @tooee/panels for panel overlays
OverlayRole is now "modal" | "passive". An overlay opened with role: "panel" never became active, and TypeScript now rejects it. Use PanelGroup and Panel from @tooee/panels for panel surfaces.
Check the router context from useRouter()
RouterProvider accepts a router made with createRouter({ context }). In return, useRouter() now returns RouterInstance<unknown>. Check useRouter().context before you use it.
Expect fallback q and r on route pending and error screens
Inside a CommandProvider, the router registers q (quit) and r (retry, error screen only) while a pending or error component shows. An app that binds those keys at the root keeps its own commands, because they register first. Routing describes the fallbacks.
Expect a config write to keep unknown keys
writeGlobalConfig now keeps keys that Tooee does not know. When the global config file is not valid JSON, the write leaves the file unchanged. Before, the write replaced it.
Check the result of copyToClipboard
copyToClipboard from @tooee/clipboard now resolves true or false. Copy commands show an error toast when no clipboard tool is installed. Code that typed the result as void still works.
Expect a one-row status bar
The status bar and the title bar no longer wrap onto a second row. When the items do not fit, the bar hides the items with the lowest priority first and shows ⋯. DocumentScreen now puts Mode: and Cursor: at the right edge, and Cursor: shortens to Ln on a narrow bar. Your statusItems default to the lowest priority after key hints, so give an item a priority from StatusPriority to keep it in view. Update frame snapshots of narrow screens, and tests that expect Mode: after your items. Items with only label and value look the same as before when they fit. Status bar lists the fitting rules.
Expect Escape to close an owned modal
dismissOnEscape now works on a modal overlay with its own command surface. Before, it had no effect there, so each modal registered its own Escape. Those commands still run first, so you can keep them or remove them. Overlays, dialogs, and toasts describes the order.
Expect n and N to land on selectable rows
In a nav-search store, n and N now move to the nearest row that isSelectable accepts. Before, they put the cursor on the match index. A match function that already returns only selectable rows behaves the same.
Check which project theme wins
When two .tooee/themes/ folders hold a theme with the same name, the folder nearest to the working directory now wins, as it does for config files. Before, the folder higher up the tree won.
Check custom themes for the search highlight keys
Themes gain searchMatchBg, searchCurrentMatchBg, searchMatchFg, and searchCurrentMatchFg. A theme that leaves them out gets values derived from warning and primary, so match rows look softer than before. Set the keys to keep the old full colours. Themes lists the derived values.
Drop onCancel from SearchBar
The onCancel prop of SearchBar is now optional and deprecated. The bar never calls it. Escape cancels through the search-cancel command.
Write + as a hotkey
The hotkey parser now accepts "+", "ctrl++", and + as one step of a sequence such as "z +". Before, "+" parsed to an empty key and never fired. "plus" still works.
Upgrade from 0.9 to 0.12
Install OpenTUI 0.5.12 or later
Every @tooee/* package now declares @opentui/core and @opentui/react ^0.5.12 as peers. Raise both in your package.json when you pin an older 0.5 release. Tooee builds and tests with React 19.3; the react peer range is unchanged.
The CLI installs OpenTUI and React as its own dependencies since 0.10.2. A global install of @tooee/cli needs no separate runtime packages.
Expect heading rows to copy the heading line alone
Markdown parsing moved to marked 18. A heading row in the Markdown view now searches and copies as the heading line, without the blank lines after it. Update tests or scripts that compare the text of a copied heading.
Expect documents to keep their scroll position
A document built on useDocumentController no longer scrolls back to the cursor row when its rows change. A wheel-scrolled view stays where it is while rows stream in or update. The view still follows the cursor when the cursor moves. Pass followTail: true for a log that stays on its newest row, or call revealRow to scroll a row into view. Documents covers both.
g g and G now scroll their row back into view when the cursor is already on it. The nav-search store of @tooee/search emits jumped for every jump that lands on a row, also when the cursor does not move. A subscriber to jumped gets these extra events.
Move app actions off the new View keys
Markdown content in View registers the fold keys z a, z c, z o, z z, z M, and z R, and g o for the heading outline, all in cursor mode. Give your own actions other keys. Keyboard basics lists what the keys do.
Upgrade from 0.8 to 0.9
Tooee 0.9 removes the compatibility APIs that were deprecated in 0.8. Update these calls before you install the new release.
Pass direct props to Choose
The Choose component now accepts chooser options as top-level props. Pass action definitions through actions:
<Choose contentProvider={provider} prompt="Pick" multi actions={actions} />The launch() function still takes its chooser fields under options. Lower-level chooser primitives still use commands for their extra actions.
Nest launchCli provider settings
Put provider settings under provider when you call launchCli or runCliSession:
await launchCli(<App />, {
provider: {
config,
initialMode: "insert",
leader: "space",
sequenceTimeoutMs: 500,
},
});The top-level aliases for config, initialMode, leader, and sequenceTimeoutMs have been removed.
Select the table renderer through View
The tooee table command has been removed. Use the View renderer option:
tooee view --renderer table data.csvPut AppLayout scrolling in one object
AppLayout now accepts its scrollbox ref and settings through scroll:
<AppLayout
scroll={{ ref: scrollRef, focused: false, stickyScroll: true, stickyStart: "bottom" }}
statusBar={{ items: [] }}
>
{content}
</AppLayout>The separate scrollRef and scrollProps props have been removed.
Import ColorMode from config
Replace the removed config Mode alias with ColorMode:
import type { ColorMode } from "@tooee/config";The command input type named Mode remains available from @tooee/commands.
Read commands with useSurfaceInvoke
Replace useCommandContext() with useSurfaceInvoke():
const { commands, invoke } = useSurfaceInvoke();It reads the commands and invocation function for the nearest command surface.
Keep overlay handles
Overlay controllers now use open, handles, and state hooks. Keep the handle returned by open() so you can close or update that entry:
import { overlayValue, useOverlay } from "@tooee/overlays";
const overlay = useOverlay();
const handle = overlay.open(
"details",
({ payload }) => <text content={payload} />,
"Initial details",
{ mode: null }
);
handle.update(overlayValue("Updated details"));
handle.close();Use useOverlayState().stack.includes(id) when a component needs to know whether a named overlay is open. Use useHasOverlay() when it only needs to know whether the stack has an entry. The controller still has update(id, next) and closeTop().
Reuse chooser behavior
@tooee/renderers now exports the chooser controller, store, source, filter, list, highlighting, and fuzzy-match primitives. The command palette and theme picker use these primitives, so their filtering, navigation, input, and selection behavior matches @tooee/choose.