mnml 0.3.3

Release notes for mnml 0.3.3, the release a new user can install — the setup wizard on a first launch, one data root, and sessions you can number and take over.

mnml 0.3.3 is the release a new user can install. A first launch from your home folder now opens the setup wizard, and a build from source and an installed mnml keep one data root between them. Integrations add rows to each other's menus. SESSIONS reads Claude Code's own list of live sessions, can take one over from another terminal, and numbers its cards so one key reaches each. Claude tokens renew on macOS, Linux and Windows. A ticket key or pull request hovers with its title, from a recent-items cache the integrations fill as they poll. The terminal library and seven syntax grammars are brought current.

This release is 1 contributor over 207 commits since 0.3.2.

Highlights

Integrations add rows to each other's menus

An integration's manifest can now put rows in mnml's own right-click menus. A row aimed at ticket, pr, pipeline or link — or at one pane's rows, as pane:<id>:<kind> — joins the menu of every link of that kind and of a Jira ticket row, under a muted header with the contributing integration's name. Picking it runs that integration's command with the clicked row's {key}, {repo}, {n}, {id} and {url} filled in, and a when such as state=OPEN narrows where it shows. Older manifests with a plain string target still load. The sample integration contributes Echo ticket key and Echo pull request as the worked example. See Menus on links.

The setup wizard on a first launch

A first launch from your home folder — the way a new terminal window opens — shows the setup wizard. Until now it showed the "where to?" picker instead, and the wizard never came; the picker returns on later launches once the setup is done. A dialog already up on a first launch, such as the workspace trust question, no longer cancels the wizard: it opens as soon as that dialog closes. See The first launch.

One data root for every build

A build from source and an installed mnml now share one data root, ~/.config/mnml, one session file and one statusline. The dev profile is gone: MNML_PROFILE and --profile are no longer read, and the dev chip and the [dev] window title went with them. --sandbox, --demo and MNML_DATA_ROOT still pick a root of their own, and the new mnml paths prints where everything lives. See One data root.

Claude tokens renew on every system

A Claude account whose token is turned down renews it with the account's own refresh token — every account, on macOS, Linux and Windows — and the renewed login is written back to that account's file. The account's line reads expired — refreshing… meanwhile; only a refused renewal shows expired — Re-auth. Re-auth itself works on Linux and Windows now, reading the login claude login leaves in the CLI's credentials file. In the usage pane each account has its own state line and its own Re-auth, and a login for another account is never filed under the one being re-authed. See Spend and usage.

Sessions from Claude Code's registry, and taking one over

Sessions running in another terminal are listed from Claude Code's live-session registry as well as its transcripts: a session you named shows that name and its exact state — busy, idle or waiting — and one with no transcript yet is listed too. The registry is undocumented and may change, so an unreadable entry is skipped and the transcripts stay the listing; sessions.registry = false turns it off.

Two new verbs act on such a session. Ask what it is doing (sessions.ask_external) sends it one message asking what it is working on and whether it is safe to interrupt, and shows its reply as a toast within 60 seconds (not on Windows yet). Take over… (sessions.take_over) ends an idle or waiting session in its own terminal and resumes it in a pane here, after a confirm. A working session is refused, and a session that does not exit within 10 seconds of the request is left running. See Every session on the machine.

Sessions by number

Each of the first nine SESSIONS cards wears a muted digit to its left, and the sessions table has a # column with the same numbers. sessions.focus_1 … focus_9 go straight to that session — Space a 1 … Space a 9 under vim, Ctrl+Alt+1 … Ctrl+Alt+9 under standard — bringing up its tab page, or swapping it into the focused column in the sessions mode. In the sessions view, plain Ctrl+1 … Ctrl+9 do the same in both profiles; everywhere else they stay the tabs'. See Moving between sessions.

A ticket key says what it names

Hover a ticket key the Jira integration has lately polled — in a terminal, on a session card, anywhere it links — and it reads ACME-123 · Fix the login redirect · In Review; its right-click menu leads with the same line. A pull request does the same with its title, state and author. The titles come from a shared recent-items cache that the integrations write as a side effect of the polls they already make, so no request is made for a hover. Recent tickets and pull requests (picker.recent_items, Space f i under vim, Ctrl+K Ctrl+E under standard) lists what is cached, newest first, and mnml cache reads and clears it from a shell. recent_items.enabled = false turns all of it off.

mnml 0.3.3 reads the cache; the Jira and Bitbucket halves that write it ship as Jira and Bitbucket 0.2.3. An mnml 0.3.4 install lists them in its Marketplace, so a 0.3.3 install upgrades to 0.3.4 to see them. See What a link names.

Dependencies brought current

The terminal library behind every shell pane, ghostty, moved 366 commits on, to its current main. Nothing changed that we could see: colour, scrollback, selection and a long prompt redrawn through narrowing and widening behave as before. Seven syntax grammars were updated: Scala, Swift, Regex, Dockerfile/Containerfile, Protobuf, OCaml and Haskell. See Built on libghostty.

Changelog

What a 0.3.2 user notices. The full list is the v0.3.3 section of CHANGELOG.md and the GitHub release.

First launch and the data root

  • A first launch from your home folder shows the setup wizard, not the "where to?" picker; a dialog already up, such as the trust question, delays the wizard instead of cancelling it.
  • One data root (~/.config/mnml) and one session file (.mnml/session.zon) for every build. MNML_PROFILE, --profile, the first-launch seeding and mnml profile seed are gone.
  • mnml paths prints the data root, session file, IPC mailbox and running-instance marker. It replaces mnml profile; on Windows, run.ps1 paths.
  • --version reads mnml 0.3.3+g<sha> for a source build, and the start page shows mnml 0.3.3 · <sha>; a release reads its version alone.

Sessions

  • EXTERNAL rows read Claude Code's live-session registry for a session's name and state; sessions.registry = false turns it off.
  • Ask what it is doing (sessions.ask_external) and Take over… (sessions.take_over) on an external session. Take over checks the process is still claude and only ever asks it to exit; it never forces one.
  • sessions.focus_1 … focus_9, with a number on each of the first nine cards, a # column in the sessions table, and the chord in the card's hover. Past the last card it says so.
  • In the sessions view, plain Ctrl+1 … Ctrl+9 follow the card numbers. The sessions mode's old Ctrl+1 … Ctrl+9 counted sessions without the docked ones and could miss by one; sessions.show_1 … show_9 are gone with it.
  • A Claude Code or Codex session on the launcher dock wears its tab's look — the product's mark in the session's own colour — instead of the grey terminal glyph.
  • Open ×N ▸ Columns with something already on the page leaves it the width the first session's split gives it and shares only the rest between the N sessions; an open editor is no longer squeezed into an equal column.

Claude accounts

  • Each account in the Claude usage pane has a state line under its name — signed in · resets 3:20am, expired, keychain holds another account or no login yet — with a Re-auth button where it needs one. Re-auth is also on the account's right-click menu, the Claude chip's menu and ai.claude_reauth.
  • Re-auth opens claude login in a pane, watches for the login, and files it under the account when its email is that account's. The separate R capture step is no longer needed.
  • A login for another account on file is never filed under the one being re-authed: a box says whose it is and offers File under that account, or Cancel.
  • An expired account is re-captured on its own when the keychain holds that same account's login again, with one toast.
  • Tokens renew with the account's refresh token on macOS, Linux and Windows; on macOS the keychain is tried first when it holds that account's login.
  • Re-auth works on Linux and Windows, reading the CLI's credentials file (under ~/.claude, or CLAUDE_CONFIG_DIR).
  • Pasting a token by hand moved behind the account menu's Advanced ▸ Paste a token…; adding an account no longer opens it.
  • The compact meter's warning account shows its letter and percent in yellow or red on the chip's coral, then a !. The hover names the account and why; a click on a chip with a ! opens the usage pane at that account.

Claude Code's review and worktrees

  • A session's proposed change is drawn by the git panel's diff view, with the same Hunk / Inline / Split toolbar, cycled by t. Until you pick a view, a pane at least 80 cells wide opens in Split and a narrower one in Hunk. Each hunk header says [✓ accept] or [ skip ].
  • Y, the header's Accept all chip, or ai.apply_accept_all accepts every hunk and applies them in one step. Space or a still toggles one hunk.
  • The review no longer covers the session that asked for it: it opens in the split holding the file, else an editor split, else a new split beside the session, and accepting, rejecting or Esc puts the focus back on the session. ai.review_placement (.editor, .beside, or .tab for the old placement) and a row in Settings ▸ AI choose. See What the session can do.
  • A session started in a worktree of its own gets it in a shared .worktrees folder beside your repository, one folder per repository: a repository at ~/code/app puts its trees in ~/code/.worktrees/app/<name>. A repository at the top of a disk uses ~/.worktrees/app/<name>.
  • Existing worktrees stay where they are and keep working. To keep the old <repo>-worktrees folder, set ai.default_worktree_root to "../app-worktrees" with your repository's name in place of app. See A worktree per session.
  • A worktree name is one folder name: letters, digits, -, _ and .. A name with / is refused with the reason.
  • A ticket key or pull request that is in the recent-items cache hovers with its title, and its right-click menu leads with the same line. An old or failed poll keeps the title and adds as of 3h ago.
  • Recent tickets and pull requests (picker.recent_items) lists the cache newest first, a stale entry marked; Enter opens it where its link would.
  • mnml cache get <kind> <id>, mnml cache ls <kind> [--source S] [--limit N] and mnml cache clear [kind] [--yes] read and clear the cache from a shell.
  • recent_items.enabled = false turns the cache off: mnml reads none of it, and the integrations it starts write none.
  • recent_items.current_release names the release the cache calls current outright, instead of the nearest unreleased release date.
  • A bare Pull request 5505, PR #5505 or pipeline 10554 links to the repository whose numbers hold it, from ranges the Bitbucket integration publishes, allowing 50 above the highest. With several candidates the menu lists Open in <repo> for each; with none, no link. See Pull-request references.
  • What the cache holds is the shape of the record — key, summary, status, assignee's display name, priority, type and fix versions for a ticket — and never a description, an account id or an email.

As with the hover titles, the Jira and Bitbucket side of the cache and of the bare-number ranges ships as Jira and Bitbucket 0.2.3, which an mnml 0.3.4 install lists in its Marketplace.

Integrations and the SDK

  • A manifest's context_menu[] rows reach mnml's menus, as above.
  • The SDK's confirm box (confirmBox) let a click on its OK or Cancel chip land on the box behind it, so neither did anything; Jira's and Bitbucket's merge confirms both had it. The chips now win.
  • A mounted pane's hover can name the command its element's click runs (Help.runs(id) and Mount.hoverHelp), and the info view then ends with that command's Key: chord, as mnml's own controls do.
  • sdk.cache: put, failed, get and query over typed Ticket, Pr, Pipeline and Release records, with the file format documented as a contract.
  • A links[] entry may resolve against published ranges (.resolve = .range) and put {repo} in its address; Ipc.linkRanges publishes the table it reads.
  • sdk.pane.columns.fit takes each column's longest visible cell and a fixed flag, so a wide pane gives its spare width to the columns being cut instead of leaving it blank. A narrow pane gives way as before.
  • mnml hands every integration it starts its installed manifest's chip glyph as $MNML_CHIP_GLYPH, and a segment can write {chip} in its resting text for it. Installing an integration whose segment rests on a different private-use glyph than its chip now warns, naming both.
  • The Jira Work chip's icon is Atlassian's work-items card with a check, baked into MnmlSymbols.ttf at U+F1C19; run ./run.sh install-font to pick it up.

The SDK is documented in docs/SDK.md. The Jira and Bitbucket changes in this list — the measured tables, the confirm fix, the chip glyph — ship as Jira and Bitbucket 0.2.3, which an mnml 0.3.4 install lists in its Marketplace.

Tables and tab strips

  • A table no longer cuts a name with … while the right of the pane is empty. The requests log, the git graph's author and branch, a request's header and parameter tables and the Files listing follow the same rule.
  • A narrow pane keeps its tab's close button. The pager goes first, then the +; only then is the tab's name cut, down to six cells, and after that the pane buttons go from the left. The close is the last thing to go.

The statusline

  • Right-click the statusline between its chips for Segments ▸: every segment, ticked while shown. A row hides or shows its chip at once and writes .statusline.hidden to the home config. RESTRICTED and the sandbox chip never hide.
  • Every segment that can move ends its menu on Move left / Move right, and the row's own menu has Reset order; the order is written to .ui.statusline_segment_order. A chip that had no menu of its own gets one.
  • A theme can colour the segments: statusline_lsp, statusline_wrap, statusline_language and eleven more base_30 keys, each falling back to the colour the segment wore before.
  • The session pager has a ground of its own (statusline_pager), with its arrows and count in the dark ink the other coloured chips use.
  • The bell's right-click marks the unread warnings read and copies the last message or the whole log; the mode chip's offers Toggle keymap.
  • The spinner is eight-dot braille and sits on the text's centre.
  • mnml --demo pins the Jira and Bitbucket launchers to the activity rail.

Keys and hover help

  • Under vim, an Alt chord the keymap binds beats the menu bar's Alt+letter: Alt+H from an editor toggles NvChad's scratch terminal instead of opening Help, and Alt+R toggles regex search instead of opening Run. Unbound Alt letters still open their menus; standard keeps every letter for the menus, as VS Code does.
  • A button, chip, rail icon, launcher dock entry, menu or palette row whose click runs a command shows Key: … right under its info-view entry's title — that command's chord in your profile. See The Key: line.
  • A menu row that only says something, such as the sidebar divider's Width: 42 cells · 21%, is its own help instead of no help written yet.
  • The sidebar divider's right-click menu opens with the column's width, in cells and as a share of the window; the keyboard cursor starts on the first row below it.

Fixes

  • The now-playing chip's Beatport mark is in the MnmlSymbols.ttf mnml ships and installs; with the 0.3 face it showed a blank.
  • OCaml gains the OxCaml keywords and types and no longer paints a #! first line as a comment; Haskell paints cases as a keyword.

Tooling

  • .test scripts can click with a modifier: click X Y ctrl (or super, alt, shift).

Upgrading

Homebrew, winget and the installers move you to 0.3.3 on your next upgrade:

brew upgrade mnml
winget upgrade ChrisMcLennan.mnml

Or run the installer for your platform again, from Install. winget is Microsoft's community repository and merges each version on its own schedule, so 0.3.3 can reach it some time after the other channels.

0.3.3 no longer reads ~/.config/mnml-dev, or a workspace's .mnml/session-dev.zon. If an older build from source left them behind, they are ignored: delete them, or move what you want from them into ~/.config/mnml, by hand.

Edit on GitHub