From ad573946182dd2c88890b8f40807e4ebd791858b Mon Sep 17 00:00:00 2001 From: Codeman maintainer Date: Fri, 9 Oct 2026 16:34:09 +0200 Subject: [PATCH 1/2] feat(tabs): a per-device switch to hide the CLI logos on tabs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since 1.40.0 every agent tab draws its CLI logo through the run-mode-dot slot, and there was no way to turn that off. App Settings → Appearance → Tabs now has "CLI Logos on Tabs" (showTabCliLogos), right after Tall Tabs. - Modelled on tabTwoRows: a per-device display key in the server-settings merge and an optional boolean in the .strict() SettingsUpdateSchema, loaded and saved by the id appSettingsShowTabCliLogos. Default ON on every device; only an explicit false turns it off (tabCliLogosEnabled). - CSS only, no tab re-render: applyTabOrientation() and the pre-paint script in index.html stamp html[data-tab-logos="on"|"off"] from the same stored blob (so a reload never flashes the logos), and one rule in styles.css hides .session-tab .tab-harness and .home-sessions-harness. The rows space their children with flex gap, so nothing is left behind. - A live flip resizes every agent tab with no render behind it, so applyTabOrientation() then re-takes the strip's one-row wrap decision (updateTabOverflowMode) and re-anchors the lines drawn from tab rects; a header that changes height reaches the PTY through the terminal container's ResizeObserver, as any header change does. - Covered: the header strip, vertical rail, sidebar, grouped rail, ledger and case clusters and phone chips (all render the same tab markup) and the desktop home rail. Untouched: tile and split headers, the Run menus, the welcome launchers. The phone overview rows, the command palette and the tab action menu draw no logo. The shell's SH pill and the status dot stay. - zh-CN for the label and the description. test/tab-cli-logos-setting.test.ts drives the real openAppSettings() and saveAppSettings() in JSDOM (the saved PUT body must pass the schema), the server-settings merge, the defaults on desktop and phone, the live stamp and its re-measure without a re-render, the real pre-paint script (on, off, the phone key, the catch fallback), the CSS rule's exact selectors, and the translations. Co-Authored-By: Claude Opus 5.5 (1M context) --- src/web/public/app.js | 4 +- src/web/public/home-sessions.js | 3 +- src/web/public/i18n.js | 3 + src/web/public/index.html | 9 +- src/web/public/settings-ui.js | 31 +- src/web/public/styles.css | 13 + src/web/schemas.ts | 7 + test/tab-cli-logos-setting.test.ts | 450 +++++++++++++++++++++++++++++ 8 files changed, 516 insertions(+), 4 deletions(-) create mode 100644 test/tab-cli-logos-setting.test.ts diff --git a/src/web/public/app.js b/src/web/public/app.js index 447a959e..1c945bd2 100644 --- a/src/web/public/app.js +++ b/src/web/public/app.js @@ -6709,7 +6709,9 @@ class CodemanApp { // every agent CLI, claude included, shows its logo through PR #532's // `run-mode-dot ` slot, the id as DATA, so the tab, the tile and split // headers and the Run menus draw the same mark. An id with no logo rule (a - // CLI added through ~/.codeman/clis.json) gets that slot's plain dot. + // CLI added through ~/.codeman/clis.json) gets that slot's plain dot. The + // span is always emitted: CLI Logos on Tabs (`showTabCliLogos`) hides it + // in CSS under html[data-tab-logos='off'], so a toggle never re-renders. const tabModeHtml = mode === 'shell' ? '' : ``; diff --git a/src/web/public/home-sessions.js b/src/web/public/home-sessions.js index a0fb9268..7865c08c 100644 --- a/src/web/public/home-sessions.js +++ b/src/web/public/home-sessions.js @@ -428,7 +428,8 @@ Object.assign(CodemanApp.prototype, { line1.appendChild(badge); } else { // The agent's logo: PR #532's slot, the mode id as data (an id with no - // logo rule gets the slot's plain dot). + // logo rule gets the slot's plain dot). CLI Logos on Tabs hides it in CSS + // (html[data-tab-logos='off']), exactly as it does on the tab strip. const logo = document.createElement('span'); logo.className = `home-sessions-harness run-mode-dot ${row.mode}`; logo.setAttribute('aria-hidden', 'true'); diff --git a/src/web/public/i18n.js b/src/web/public/i18n.js index ffdd8d86..dfa75f3e 100644 --- a/src/web/public/i18n.js +++ b/src/web/public/i18n.js @@ -369,6 +369,9 @@ '会话列表显示为顶栏横向标签条,或左侧可折叠侧边栏(Alt+B)。完整侧边栏为每个会话显示与主界面相同的详细信息。', 'Tall Tabs (Name + Folder)': '双行标签(名称 + 文件夹)', 'Pop-out Button on Tabs': '标签页弹出窗口按钮', + 'CLI Logos on Tabs': '标签页上的 CLI 图标', + "Show each agent's CLI logo before the session name on tabs and the home screen's tab list. Off leaves the status dot and the shell's SH badge. Tiles, split headers and the Run menus keep their logos.": + '在标签页和主界面的标签列表中,于会话名称前显示每个智能体的 CLI 图标。关闭后仍保留状态圆点和 Shell 的 SH 标记。平铺、分屏标题栏和运行菜单中的图标不受影响。', // Tab Layout and Header Stats Style (Discussion #426). The header style's // "Tiles" is 磁贴, never 平铺: that is the tile grid's word (the Tiles // button), and "Tiles (label over value)" must not read as the grid. diff --git a/src/web/public/index.html b/src/web/public/index.html index 335d3785..f2fdbee0 100644 --- a/src/web/public/index.html +++ b/src/web/public/index.html @@ -65,7 +65,7 @@ app.js, NOT the handheld storage-key test `m`. Use a different predicate here and boot will contradict this value, animating the drawer open by itself on every load between 768 and 1023px. --> - +