---
title: 4.2.0 — Self-hosted GitLab, panes that take the whole terminal, and worktrees that keep their colours
layout: default
parent: English
nav_order: 1014
description: Setup guide for MulmoTerminal 4.2.0 — declaring a self-hosted GitLab in gitlabHosts, expanding the Canvas and Tools panes over the terminal, worktrees that inherit their project's settings, and a terminal that repairs itself as you type.
---

# 4.2.0 — Self-hosted GitLab, panes that take the whole terminal, and worktrees that keep their colours

**A snapshot of 4.2.0 as released on 2026-08-03.** It will go out of date as the app moves on; that
is fine and expected. For the reference that is kept current, follow the links to the living guide
in each section.

```bash
npx mulmoterminal@latest
```

**One thing in this release needs configuring** — a self-hosted GitLab, which cannot be guessed and
has to be named. Everything else starts working on upgrade.

---

## Your company's GitLab, in the PRs & Issues view

Until now MulmoTerminal read exactly two forges: github.com and gitlab.com. A row for
`gitlab.yourcompany.com` got one sentence saying so, and stopped there. There was no way to tell the
app that the host was a GitLab at all — a self-hosted instance is not distinguishable from any other
domain by looking at it.

So you tell it. Open `~/.mulmoterminal/config.json` and add **`gitlabHosts`**:

```json
{
  "gitlabHosts": ["gitlab.yourcompany.com"],
  "prRepos": ["gitlab.yourcompany.com/group/project"]
}
```

Two keys, and they do different jobs. `gitlabHosts` says "this domain speaks GitLab". `prRepos` is
the list of repositories the **PRs & Issues** view reads, which you may already have — this is the
same list, with a host in front of the path.

**Restart the server after editing the file by hand.** The host list is read from the configuration
the server is holding in memory, so a change made through Settings applies immediately, while a
hand-edited `config.json` is only picked up at startup. This is the same rule `prRepos` has always
followed.

**How to tell it worked.** Open the **PRs & Issues** view. Before, the row for your host read:

> `gitlab.yourcompany.com is not supported yet — MulmoTerminal reads github.com and gitlab.com`

Now it lists your merge requests and issues. And if you have not added the key yet, that message
itself tells you which key to add and where — it was rewritten for this release, so you are not left
guessing.

A declared host then goes down the same path gitlab.com does: the cross-repo lists, starting work
from an issue, work comments on start and merge, and creating a merge request from the **Open PR**
button.

**You need `glab`**, GitLab's CLI, logged in to your instance — `npx mulmoterminal doctor` checks for
it. `gh` remains required for GitHub; `glab` is optional until you use a GitLab repo.

**What is not covered yet.** A host with a port (`gitlab.example.com:8443`) cannot be written,
because a `prRepos` entry has no place for a colon. Neither can an http-only instance, or GitHub
Enterprise. And `github.com` is rejected as a value on purpose — it is an easy thing to type by
mistake and an expensive one to get wrong.

There is no Settings screen for this yet; the config file is the whole interface for now.

Reference: [GitHub and GitLab](github.html) and [configuration](config.html) in the living guide.

---

## Canvas and Tools can take the whole terminal area

A document in the Canvas used to live in whatever width was left beside the terminal. For a wide
table, a Marp slide or a rendered page, that was not enough.

**Enlarge a session, open the Canvas, and press the expand button in the pane's header** — the
`open_in_full` icon at the top of the pane. The pane takes the entire row. Press it again
(`close_fullscreen`) to go back to the split.

![The split view — a wide table in the Canvas beside the terminal, with its last four columns cut off at the pane's edge](../images/v4.2.0-pane-split.png)

![The same table after pressing expand — the pane has the whole terminal row and every column fits, while the cockpit roster on the left has not moved](../images/v4.2.0-pane-full.png)

The **Tools** pane has the same pair of buttons in the same position. They share one slot, so
learning it once is the point.

**What it covers, and what it does not.** Only the enlarged terminal. The cockpit roster down the
left and the filmstrip along the bottom sit outside that row and stay exactly where they are, so you
can still see what the other sessions are doing while a document is open full width. The terminal
underneath is not destroyed — it is moved off-screen at full size, so it comes back the shape it
was.

**It is not remembered, and that is deliberate.** Close the pane and open it again and you get the
split view, every time. Switch panes, reload the page — always split. A pane that covers the terminal
is a surprise on every occasion except the one where you asked for it, and what it hides is the thing
you were working on. Which pane was open, and how wide it was in split view, are remembered as
before.

The Canvas header also gained a **Close** at its right end, matching Files and Tools. Its old tools
button is gone; the Tools pane still opens from each cell's own header.

Reference: [basics](basics.html) in the living guide.

---

## A new worktree keeps its project's colours

`.mulmoterminal.json` is normally gitignored, so `git worktree add` produced a directory with **no
configuration in it at all**. The cell lost the project's colours, its name badge, its model and its
grid rank — and being unranked, it fell to the end of the sort. Three cells of one project looked
like three unrelated ones.

**Nothing to switch on.** Make a worktree the way you already do — the launcher's **＋ New worktree**,
or starting work on an issue — and it arrives configured.

- `name`, `theme`, `colors`, `fontSize`, `fontFamily`, `provider` and `model` are copied as written.
- The seven chrome colours are rotated **12 degrees further around the hue wheel for each worktree**,
  so a project and its trees read as a gradient rather than as duplicates. Only the hue moves;
  saturation and lightness carry the contrast a colour was picked for. A grey such as
  `headerTextColor: "#ffffff"` has no hue to rotate and comes through untouched.
- `orderPriority` is the project's rank **+ 1**, so each tree sits directly after the project it was
  cut from.

**Three keys are deliberately not carried**: `sound`, `sounds` and `addDirs`. They name paths inside
the project directory that the worktree has no copy of, and `addDirs` resolves relative to whichever
directory holds the file — copying it would quietly grant a different set of folders.

**If you already have a config in a worktree, it is never overwritten.** And the file is only written
where git would ignore it: an untracked file in a worktree's `git status` is not merely untidy, since
MulmoTerminal refuses to remove a **dirty** worktree — the app would have blocked its own cleanup over
a file it wrote itself.

Reference: [scenarios](scenarios.html) in the living guide, and the `mulmoterminal-dirs` skill for
setting a project's colours in the first place.

---

## A finished turn is green everywhere

The four attention states are painted in two places — a grid tile paints its own chrome, a cockpit
roster row paints its own — and they disagreed about one of them. `done` was the theme **accent** on
a tile and **green** on a roster row.

That cost twice. `working` is also the accent, so on a tile the two blues were hard to tell apart at
the distance you actually scan a grid from; and enlarging a session changed the colour of "this one
finished" under you.

It is now **working = blue, done = green, waiting = amber**, in every view. Nothing to configure —
open the grid and the change is the thing you see. The roster is unchanged: its green is what
everything else moved to.

![A 3x3 grid with all three active states at once — five cells working in blue, two finished in green, two waiting on an answer in amber](../images/v4.2.0-done-green.png)

Reference: [basics](basics.html) in the living guide.

---

## A terminal that stops taking input

Two different faults look identical from your chair: you type, and nothing happens.

**The first repairs itself now.** xterm has an open bug where a resize can jam the write queue
permanently — keystrokes still reach the shell, but nothing that comes back is ever drawn. The repair
already existed, but it could only be triggered by a resize or by an incoming output frame, and an
**idle** cell gets neither. The cell most in need of repair was the one least able to ask for it.
Typing is now a third trigger, so the cell you are sitting in front of, typing into, fixes itself.

**The second explains itself now.** A keystroke sent while the socket is down — during reconnect,
or after the session was superseded — used to be discarded without a word. A banner now says so. It
reappears if the outage continues past the banner's lifetime, which matters because reconnection
retries indefinitely: a single disconnection can last hours, and the old banner spoke only once.

This also reaches the **header buttons and the Skill menu**, which previously did nothing at all when
pressed during an outage, and said nothing about why.

**How to tell you have the fix.** Stop the server while a session is open and press a header button.
You should get a banner saying what you sent was dropped — not silence.

Reference: [FAQ](faq.html) in the living guide.

---

## Everything else

No action required for any of it, but it is what most of the release is.

- **`gui-chat-protocol` 2.0.0** and the `@mulmoclaude/*` plugin set that goes with it.
- **407 unsafe-`any` findings are gone** and the rules that forbid them are errors, so they cannot
  come back. `noUncheckedIndexedAccess` is on. The `as` ban now reaches Vue templates, where it had
  never once fired despite being configured.
- **`yarn typecheck` now checks the whole repository.** It had been looking at two of the five
  projects — server and test were never checked at all.
- **The test suite got faster and steadier**: 153 server specs no longer stand up a browser
  environment they do not use, and the first test in a file no longer pays for loading the module
  under test.

The full detail, per pull request, is in the [changelog](https://github.com/receptron/mulmoterminal/blob/main/docs/ChangeLog.md).
