From 61d013a3fea4dbb0e0606560bf9651507712208b Mon Sep 17 00:00:00 2001 From: minhn4 Date: Sun, 12 Jul 2026 20:58:42 +0700 Subject: [PATCH 1/5] feat(tui): use the smaller lowercase codev wordmark for the home banner Render the home banner with the lowercase "codev" wordmark (4 rows) in the brand teal instead of the taller all-caps block banner (6 rows), reusing upstream's shadow-mark rendering. The block banner stays in the CLI epilogue. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/tui/src/component/logo.tsx | 62 ++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/packages/tui/src/component/logo.tsx b/packages/tui/src/component/logo.tsx index 5ade5401a8..b2026b5e8a 100644 --- a/packages/tui/src/component/logo.tsx +++ b/packages/tui/src/component/logo.tsx @@ -1,19 +1,63 @@ import { RGBA, TextAttributes } from "@opentui/core" -import { For } from "solid-js" -import { banner } from "../logo" +import { For, type JSX } from "solid-js" +import { tint, useTheme } from "../context/theme" +import { logo } from "../logo" -// Fork: hub-style CODEV banner in uniform bold teal (Tailwind cyan-600), -// the codev brand color. +// Fork: lowercase "codev" wordmark (half the height of the block banner) in the +// codev brand teal (Tailwind cyan-600), rendered with upstream's shadow marks. const BRAND = RGBA.fromHex("#0891b2") export function Logo() { + const { theme } = useTheme() + + const renderLine = (line: string, bold: boolean): JSX.Element[] => { + const shadow = tint(theme.background, BRAND, 0.25) + const attrs = bold ? TextAttributes.BOLD : undefined + return Array.from(line).map((char) => { + if (char === "_") { + return ( + + {" "} + + ) + } + if (char === "^") { + return ( + + ▀ + + ) + } + if (char === "~") { + return ( + + ▀ + + ) + } + if (char === ",") { + return ( + + ▄ + + ) + } + return ( + + {char} + + ) + }) + } + return ( - - {(line) => ( - - {line} - + + {(line, index) => ( + + {renderLine(line, true)} + {renderLine(logo.right[index()], true)} + )} From d79f8f2f4b76d8574424fb4f329967ba136dcc9e Mon Sep 17 00:00:00 2001 From: minhn4 Date: Sun, 12 Jul 2026 21:07:12 +0700 Subject: [PATCH 2/5] feat(tui): shrink the CLI epilogue banner to the codev wordmark Render the session epilogue with the lowercase "codev" wordmark in brand teal instead of the taller all-caps block. Drop the now-unused block banner export from logo.ts. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/tui/src/logo.ts | 11 ----------- packages/tui/src/util/presentation.ts | 19 ++++++++++++++++--- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/packages/tui/src/logo.ts b/packages/tui/src/logo.ts index 6b76e302c8..d898ab051e 100644 --- a/packages/tui/src/logo.ts +++ b/packages/tui/src/logo.ts @@ -5,17 +5,6 @@ export const logo = { right: [" ▄ ", "█▀▀█ █▀▀█ █__█", "█__█ █^^^ █__█", "▀▀▀▀ ▀▀▀▀ ▀▀ "], } -// Fork: hub-style CODEV banner (same ANSI-Shadow art as the codev hub's -// src/components/Banner.tsx). Used by the TUI home banner and CLI help. -export const banner = [ - " ██████╗ ██████╗ ██████╗ ███████╗██╗ ██╗", - "██╔════╝██╔═══██╗██╔══██╗██╔════╝██║ ██║", - "██║ ██║ ██║██║ ██║█████╗ ██║ ██║", - "██║ ██║ ██║██║ ██║██╔══╝ ╚██╗ ██╔╝", - "╚██████╗╚██████╔╝██████╔╝███████╗ ╚████╔╝ ", - " ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═══╝ ", -] - export const go = { left: [" ", "█▀▀▀", "█_^█", "▀▀▀▀"], right: [" ", "█▀▀█", "█__█", "▀▀▀▀"], diff --git a/packages/tui/src/util/presentation.ts b/packages/tui/src/util/presentation.ts index 5ce0fbd398..c18ce73f8b 100644 --- a/packages/tui/src/util/presentation.ts +++ b/packages/tui/src/util/presentation.ts @@ -1,12 +1,25 @@ -import { banner } from "../logo" +import { logo } from "../logo" const reset = "\x1b[0m" const bold = "\x1b[1m" const dim = "\x1b[90m" +// Fork: codev brand teal (Tailwind cyan-600) as a truecolor foreground. +const teal = "\x1b[38;2;8;145;178m" function wordmark(pad = "") { - // Fork: hub-style CODEV banner in bold bright cyan. - return banner.map((line) => `${pad}${bold}\x1b[96m${line}${reset}`) + // Fork: lowercase "codev" wordmark in bold brand teal, with upstream's shadow marks. + const draw = (line: string) => + [...line] + .map((char) => { + if (char === "_") return " " + if (char === "^" || char === "~") return `${teal}▀${reset}` + if (char === ",") return `${teal}▄${reset}` + if (char === " ") return " " + return `${teal}${bold}${char}${reset}` + }) + .join("") + + return logo.left.map((line, index) => `${pad}${draw(line)} ${draw(logo.right[index] ?? "")}`) } export function sessionEpilogue(input: { title: string; sessionID?: string }) { From 2d8df549281ed43ce511284d351a8f66b8373e28 Mon Sep 17 00:00:00 2001 From: minhn4 Date: Sun, 12 Jul 2026 21:11:10 +0700 Subject: [PATCH 3/5] fix(opencode): render the lowercase wordmark in the CLI banner The opencode CLI re-exports @opencode-ai/tui/logo and rendered the removed block `banner`, breaking startup. Add a composed lowercase `wordmark` export and render it in brand teal from UI.logo. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/opencode/src/cli/ui.ts | 9 ++++----- packages/tui/src/logo.ts | 10 ++++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/opencode/src/cli/ui.ts b/packages/opencode/src/cli/ui.ts index 0eb6be187e..3e979f3771 100644 --- a/packages/opencode/src/cli/ui.ts +++ b/packages/opencode/src/cli/ui.ts @@ -1,9 +1,8 @@ import { EOL } from "os" import { Schema } from "effect" -import { banner } from "./logo" +import { wordmark } from "./logo" -// Fork: hub-style CODEV banner (see @opencode-ai/tui/logo). -const wordmark = banner +// Fork: lowercase "codev" wordmark (see @opencode-ai/tui/logo). export class CancelledError extends Schema.TaggedErrorClass()("UICancelledError", {}) {} @@ -45,8 +44,8 @@ export function logo(pad?: string) { if (!process.stdout.isTTY && !process.stderr.isTTY) { return wordmark.map((row) => (pad ?? "") + row).join(EOL) } - // Bold bright cyan, matching the codev hub CLI banner. - return wordmark.map((row) => (pad ?? "") + "\x1b[1m\x1b[96m" + row + "\x1b[0m").join(EOL) + // Bold codev brand teal (Tailwind cyan-600). + return wordmark.map((row) => (pad ?? "") + "\x1b[1m\x1b[38;2;8;145;178m" + row + "\x1b[0m").join(EOL) } export async function input(prompt: string): Promise { diff --git a/packages/tui/src/logo.ts b/packages/tui/src/logo.ts index d898ab051e..d0ca585a39 100644 --- a/packages/tui/src/logo.ts +++ b/packages/tui/src/logo.ts @@ -5,6 +5,16 @@ export const logo = { right: [" ▄ ", "█▀▀█ █▀▀█ █__█", "█__█ █^^^ █__█", "▀▀▀▀ ▀▀▀▀ ▀▀ "], } +// Fork: the lowercase "codev" wordmark composed into plain lines (shadow marks +// substituted to glyphs) for CLI banners that color each line uniformly. +const substituteMarks = (line: string) => + Array.from(line, (char) => + char === "_" ? " " : char === "^" || char === "~" ? "▀" : char === "," ? "▄" : char, + ).join("") +export const wordmark = logo.left.map( + (line, index) => `${substituteMarks(line)} ${substituteMarks(logo.right[index] ?? "")}`, +) + export const go = { left: [" ", "█▀▀▀", "█_^█", "▀▀▀▀"], right: [" ", "█▀▀█", "█__█", "▀▀▀▀"], From c40bcc0927fbee6279af56ee21be568f6cf47766 Mon Sep 17 00:00:00 2001 From: minhn4 Date: Sun, 12 Jul 2026 21:24:22 +0700 Subject: [PATCH 4/5] fix(tui): match the CLI wordmark shadow to the home banner Add a shared ansiWordmark renderer that draws the brand-teal drop shadow behind the mark cells, so the session epilogue and CLI help banners look like the TUI home banner instead of a flat wordmark. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/opencode/src/cli/ui.ts | 6 +++--- packages/tui/src/logo.ts | 20 ++++++++++++++++++++ packages/tui/src/util/presentation.ts | 22 ++-------------------- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/packages/opencode/src/cli/ui.ts b/packages/opencode/src/cli/ui.ts index 3e979f3771..05f0454b8f 100644 --- a/packages/opencode/src/cli/ui.ts +++ b/packages/opencode/src/cli/ui.ts @@ -1,6 +1,6 @@ import { EOL } from "os" import { Schema } from "effect" -import { wordmark } from "./logo" +import { ansiWordmark, wordmark } from "./logo" // Fork: lowercase "codev" wordmark (see @opencode-ai/tui/logo). @@ -44,8 +44,8 @@ export function logo(pad?: string) { if (!process.stdout.isTTY && !process.stderr.isTTY) { return wordmark.map((row) => (pad ?? "") + row).join(EOL) } - // Bold codev brand teal (Tailwind cyan-600). - return wordmark.map((row) => (pad ?? "") + "\x1b[1m\x1b[38;2;8;145;178m" + row + "\x1b[0m").join(EOL) + // Bold codev brand teal with the drop shadow, matching the TUI home banner. + return ansiWordmark(pad).join(EOL) } export async function input(prompt: string): Promise { diff --git a/packages/tui/src/logo.ts b/packages/tui/src/logo.ts index d0ca585a39..085f59e0eb 100644 --- a/packages/tui/src/logo.ts +++ b/packages/tui/src/logo.ts @@ -15,6 +15,26 @@ export const wordmark = logo.left.map( (line, index) => `${substituteMarks(line)} ${substituteMarks(logo.right[index] ?? "")}`, ) +// Fork: ANSI-colored lowercase wordmark for CLI banners, matching the TUI home +// banner: bold brand teal with a drop shadow behind the mark cells. The shadow +// is tint(theme dark background #0a0a0a, teal, 0.25) = #0a2c34. +export function ansiWordmark(pad = "") { + const reset = "\x1b[0m" + const teal = "\x1b[1m\x1b[38;2;8;145;178m" + const shadowFg = "\x1b[38;2;10;44;52m" + const shadowBg = "\x1b[48;2;10;44;52m" + const draw = (line: string) => + Array.from(line, (char) => { + if (char === "_") return `${shadowBg} ${reset}` + if (char === "^") return `${teal}${shadowBg}▀${reset}` + if (char === "~") return `${shadowFg}▀${reset}` + if (char === ",") return `${shadowFg}▄${reset}` + if (char === " ") return " " + return `${teal}${char}${reset}` + }).join("") + return logo.left.map((line, index) => `${pad}${draw(line)} ${draw(logo.right[index] ?? "")}`) +} + export const go = { left: [" ", "█▀▀▀", "█_^█", "▀▀▀▀"], right: [" ", "█▀▀█", "█__█", "▀▀▀▀"], diff --git a/packages/tui/src/util/presentation.ts b/packages/tui/src/util/presentation.ts index c18ce73f8b..409ad8007f 100644 --- a/packages/tui/src/util/presentation.ts +++ b/packages/tui/src/util/presentation.ts @@ -1,31 +1,13 @@ -import { logo } from "../logo" +import { ansiWordmark } from "../logo" const reset = "\x1b[0m" const bold = "\x1b[1m" const dim = "\x1b[90m" -// Fork: codev brand teal (Tailwind cyan-600) as a truecolor foreground. -const teal = "\x1b[38;2;8;145;178m" - -function wordmark(pad = "") { - // Fork: lowercase "codev" wordmark in bold brand teal, with upstream's shadow marks. - const draw = (line: string) => - [...line] - .map((char) => { - if (char === "_") return " " - if (char === "^" || char === "~") return `${teal}▀${reset}` - if (char === ",") return `${teal}▄${reset}` - if (char === " ") return " " - return `${teal}${bold}${char}${reset}` - }) - .join("") - - return logo.left.map((line, index) => `${pad}${draw(line)} ${draw(logo.right[index] ?? "")}`) -} export function sessionEpilogue(input: { title: string; sessionID?: string }) { const weak = (text: string) => `${dim}${text.padEnd(10, " ")}${reset}` return [ - ...wordmark(" "), + ...ansiWordmark(" "), "", ` ${weak("Session")}${bold}${input.title}${reset}`, ` ${weak("Continue")}${bold}codev -s ${input.sessionID}${reset}`, From 823388f73189611c119afd0a95980bb4fdb6e062 Mon Sep 17 00:00:00 2001 From: minhn4 Date: Sun, 12 Jul 2026 21:29:02 +0700 Subject: [PATCH 5/5] feat(tui): drive the home banner from the theme secondary color Render the home wordmark in theme.secondary (teal in dark, purple in light) instead of a hardcoded teal, so the banner matches the active theme's brand color in both modes. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/tui/src/component/logo.tsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/tui/src/component/logo.tsx b/packages/tui/src/component/logo.tsx index b2026b5e8a..07e9598d80 100644 --- a/packages/tui/src/component/logo.tsx +++ b/packages/tui/src/component/logo.tsx @@ -1,29 +1,28 @@ -import { RGBA, TextAttributes } from "@opentui/core" +import { TextAttributes } from "@opentui/core" import { For, type JSX } from "solid-js" import { tint, useTheme } from "../context/theme" import { logo } from "../logo" // Fork: lowercase "codev" wordmark (half the height of the block banner) in the -// codev brand teal (Tailwind cyan-600), rendered with upstream's shadow marks. -const BRAND = RGBA.fromHex("#0891b2") - +// theme's brand secondary (teal in dark, purple in light), with shadow marks. export function Logo() { const { theme } = useTheme() const renderLine = (line: string, bold: boolean): JSX.Element[] => { - const shadow = tint(theme.background, BRAND, 0.25) + const brand = theme.secondary + const shadow = tint(theme.background, brand, 0.25) const attrs = bold ? TextAttributes.BOLD : undefined return Array.from(line).map((char) => { if (char === "_") { return ( - + {" "} ) } if (char === "^") { return ( - + ▀ ) @@ -43,7 +42,7 @@ export function Logo() { ) } return ( - + {char} )