diff --git a/docs/assets/theme-tokyonight-dark.png b/docs/assets/theme-tokyonight-dark.png
new file mode 100644
index 0000000000..ebeec93548
Binary files /dev/null and b/docs/assets/theme-tokyonight-dark.png differ
diff --git a/docs/cli/themes.md b/docs/cli/themes.md
index 55acc75625..93912032c0 100644
--- a/docs/cli/themes.md
+++ b/docs/cli/themes.md
@@ -19,6 +19,7 @@ using the `/theme` command within Gemini CLI:
- `Holiday`
- `Shades Of Purple`
- `Solarized Dark`
+ - `Tokyo Night`
- **Light themes:**
- `ANSI Light`
- `Ayu Light`
@@ -252,6 +253,10 @@ identify their source, for example: `shades-of-green (green-extension)`.
+### Tokyo Night
+
+
+
## Light themes
### ANSI Light
diff --git a/packages/cli/src/ui/components/MainContent.test.tsx b/packages/cli/src/ui/components/MainContent.test.tsx
index 93d77e0dfe..2bc6ee27bc 100644
--- a/packages/cli/src/ui/components/MainContent.test.tsx
+++ b/packages/cli/src/ui/components/MainContent.test.tsx
@@ -27,6 +27,10 @@ import {
} from '../hooks/useConfirmingTool.js';
// Mock dependencies
+vi.mock('ink-spinner', () => ({
+ default: () => ⠋,
+}));
+
const mockUseSettings = vi.fn().mockReturnValue({
merged: {
ui: {
diff --git a/packages/cli/src/ui/components/__snapshots__/MainContent.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/MainContent.test.tsx.snap
index 07a28039d1..f0260ddc91 100644
--- a/packages/cli/src/ui/components/__snapshots__/MainContent.test.tsx.snap
+++ b/packages/cli/src/ui/components/__snapshots__/MainContent.test.tsx.snap
@@ -4,7 +4,7 @@ exports[`MainContent > MainContent Tool Output Height Logic > 'ASB mode - Focuse
"ScrollableList
AppHeader(full)
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
-│ ⊶ Shell Command Running a long command... │
+│ ⠋ Shell Command Running a long command... │
│ │
│ Line 11 │
│ Line 12 │
@@ -24,7 +24,7 @@ exports[`MainContent > MainContent Tool Output Height Logic > 'ASB mode - Unfocu
"ScrollableList
AppHeader(full)
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
-│ ⊶ Shell Command Running a long command... │
+│ ⠋ Shell Command Running a long command... │
│ │
│ Line 11 │
│ Line 12 │
@@ -43,7 +43,7 @@ AppHeader(full)
exports[`MainContent > MainContent Tool Output Height Logic > 'Normal mode - Constrained height' 1`] = `
"AppHeader(full)
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
-│ ⊶ Shell Command Running a long command... │
+│ ⠋ Shell Command Running a long command... │
│ │
│ ... first 11 lines hidden (Ctrl+O to show) ... │
│ Line 12 │
@@ -62,7 +62,7 @@ exports[`MainContent > MainContent Tool Output Height Logic > 'Normal mode - Con
exports[`MainContent > MainContent Tool Output Height Logic > 'Normal mode - Unconstrained height' 1`] = `
"AppHeader(full)
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
-│ ⊶ Shell Command Running a long command... │
+│ ⠋ Shell Command Running a long command... │
│ │
│ Line 1 │
│ Line 2 │
diff --git a/packages/cli/src/ui/components/__snapshots__/ThemeDialog.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/ThemeDialog.test.tsx.snap
index 4a5b30fc5c..2b9090e237 100644
--- a/packages/cli/src/ui/components/__snapshots__/ThemeDialog.test.tsx.snap
+++ b/packages/cli/src/ui/components/__snapshots__/ThemeDialog.test.tsx.snap
@@ -14,9 +14,9 @@ exports[`Initial Theme Selection > should default to a dark theme when terminal
│ 7. Holiday Dark │ 6 return a │ │
│ 8. Shades Of Purple Dark │ │ │
│ 9. Solarized Dark │ 1 - print("Hello, " + name) │ │
-│ 10. ANSI Light │ 1 + print(f"Hello, {name}!") │ │
-│ 11. Ayu Light │ │ │
-│ 12. Default Light └─────────────────────────────────────────────────┘ │
+│ 10. Tokyo Night Dark │ 1 + print(f"Hello, {name}!") │ │
+│ 11. ANSI Light │ │ │
+│ 12. Ayu Light └─────────────────────────────────────────────────┘ │
│ ▼ │
│ │
│ (Use Enter to select, Tab to configure scope, Esc to close) │
@@ -64,9 +64,9 @@ exports[`Initial Theme Selection > should use the theme from settings even if te
│ 7. Holiday Dark │ 6 return a │ │
│ 8. Shades Of Purple Dark │ │ │
│ 9. Solarized Dark │ 1 - print("Hello, " + name) │ │
-│ 10. ANSI Light │ 1 + print(f"Hello, {name}!") │ │
-│ 11. Ayu Light │ │ │
-│ 12. Default Light └─────────────────────────────────────────────────┘ │
+│ 10. Tokyo Night Dark │ 1 + print(f"Hello, {name}!") │ │
+│ 11. ANSI Light │ │ │
+│ 12. Ayu Light └─────────────────────────────────────────────────┘ │
│ ▼ │
│ │
│ (Use Enter to select, Tab to configure scope, Esc to close) │
@@ -103,9 +103,9 @@ exports[`ThemeDialog Snapshots > should render correctly in theme selection mode
│ 7. Holiday Dark │ 6 return a │ │
│ 8. Shades Of Purple Dark │ │ │
│ 9. Solarized Dark │ 1 - print("Hello, " + name) │ │
-│ 10. ANSI Light │ 1 + print(f"Hello, {name}!") │ │
-│ 11. Ayu Light │ │ │
-│ 12. Default Light └─────────────────────────────────────────────────┘ │
+│ 10. Tokyo Night Dark │ 1 + print(f"Hello, {name}!") │ │
+│ 11. ANSI Light │ │ │
+│ 12. Ayu Light └─────────────────────────────────────────────────┘ │
│ ▼ │
│ │
│ (Use Enter to select, Tab to configure scope, Esc to close) │
@@ -128,9 +128,9 @@ exports[`ThemeDialog Snapshots > should render correctly in theme selection mode
│ 7. Holiday Dark │ 6 return a │ │
│ 8. Shades Of Purple Dark │ │ │
│ 9. Solarized Dark │ 1 - print("Hello, " + name) │ │
-│ 10. ANSI Light │ 1 + print(f"Hello, {name}!") │ │
-│ 11. Ayu Light │ │ │
-│ 12. Default Light └─────────────────────────────────────────────────┘ │
+│ 10. Tokyo Night Dark │ 1 + print(f"Hello, {name}!") │ │
+│ 11. ANSI Light │ │ │
+│ 12. Ayu Light └─────────────────────────────────────────────────┘ │
│ ▼ │
│ ╭─────────────────────────────────────────────────╮ │
│ │ DEVELOPER TOOLS (Not visible to users) │ │
diff --git a/packages/cli/src/ui/themes/builtin/dark/tokyonight-dark.ts b/packages/cli/src/ui/themes/builtin/dark/tokyonight-dark.ts
new file mode 100644
index 0000000000..ca2c242eaa
--- /dev/null
+++ b/packages/cli/src/ui/themes/builtin/dark/tokyonight-dark.ts
@@ -0,0 +1,155 @@
+/**
+ * @license
+ * Copyright 2026 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { type ColorsTheme, Theme } from '../../theme.js';
+import { interpolateColor } from '../../color-utils.js';
+
+const palette = {
+ bg: '#1a1b26',
+ bg_dark: '#16161e',
+ bg_dark1: '#0C0E14',
+ bg_highlight: '#292e42',
+ blue: '#7aa2f7',
+ blue0: '#3d59a1',
+ blue1: '#2ac3de',
+ blue2: '#0db9d7',
+ blue5: '#89ddff',
+ blue6: '#b4f9f8',
+ blue7: '#394b70',
+ comment: '#565f89',
+ cyan: '#7dcfff',
+ fg: '#c0caf5',
+ fg_dark: '#a9b1d6',
+ fg_gutter: '#3b4261',
+ green: '#9ece6a',
+ green1: '#73daca',
+ green2: '#41a6b5',
+ magenta: '#bb9af7',
+ magenta2: '#ff007c',
+ orange: '#ff9e64',
+ purple: '#9d7cd8',
+ red: '#f7768e',
+ red1: '#db4b4b',
+ teal: '#1abc9c',
+ yellow: '#e0af68',
+ diff: {
+ add: '#243e4a',
+ change: '#1f2231',
+ delete: '#4a272f',
+ },
+};
+
+const tokyoNightColors: ColorsTheme = {
+ type: 'dark',
+ Background: palette.bg,
+ Foreground: palette.fg,
+ LightBlue: palette.purple,
+ AccentBlue: palette.magenta,
+ AccentPurple: palette.blue,
+ AccentCyan: palette.cyan,
+ AccentGreen: palette.teal,
+ AccentYellow: palette.yellow,
+ AccentRed: palette.red1,
+ DiffAdded: palette.diff.add,
+ DiffRemoved: palette.diff.delete,
+ Comment: palette.comment,
+ Gray: palette.fg_dark,
+ DarkGray: palette.fg_gutter,
+ FocusColor: palette.blue,
+ GradientColors: [palette.blue, palette.magenta, palette.cyan],
+};
+
+export const TokyoNight: Theme = new Theme(
+ 'Tokyo Night',
+ 'dark',
+ {
+ hljs: {
+ display: 'block',
+ overflowX: 'auto',
+ padding: '0.5em',
+ background: palette.bg,
+ color: palette.fg,
+ },
+ 'hljs-addition': { background: palette.diff.add },
+ 'hljs-attr': { color: palette.green1 },
+ 'hljs-attribute': { color: palette.green1 },
+ 'hljs-brace': { color: palette.fg_dark },
+ 'hljs-built_in': { color: palette.blue1 },
+ 'hljs-builtin-symbol': { color: palette.blue1 },
+ 'hljs-bullet': {
+ color: palette.orange,
+ fontWeight: 'bold',
+ },
+ 'hljs-char': { color: palette.green },
+ 'hljs-char-escape': { color: palette.magenta },
+ 'hljs-character': { color: palette.green },
+ 'hljs-class': { color: palette.blue1 },
+ 'hljs-class-title': { color: palette.blue1 },
+ 'hljs-code': { color: palette.green },
+ 'hljs-comment': {
+ color: palette.comment,
+ fontStyle: 'italic',
+ },
+ 'hljs-computation-expression': { color: palette.cyan },
+ 'hljs-deletion': { background: palette.diff.delete },
+ 'hljs-doctag': { color: palette.yellow },
+ 'hljs-emphasis': { fontStyle: 'italic' },
+ 'hljs-function': { color: palette.blue },
+ 'hljs-function-dispatch': { color: palette.blue },
+ 'hljs-keyword': {
+ color: palette.magenta,
+ fontStyle: 'italic',
+ },
+ 'hljs-label': { color: palette.blue },
+ 'hljs-link': { color: palette.teal },
+ 'hljs-literal': { color: palette.orange },
+ 'hljs-message-name': { color: palette.blue },
+ 'hljs-meta': { color: palette.cyan },
+ 'hljs-meta-prompt': { color: palette.fg_dark },
+ 'hljs-name': { color: palette.magenta },
+ 'hljs-named-character': { color: palette.blue1 },
+ 'hljs-number': { color: palette.orange },
+ 'hljs-operator': { color: palette.blue5 },
+ 'hljs-params': { color: palette.yellow },
+ 'hljs-property': { color: palette.green1 },
+ 'hljs-punctuation': { color: palette.fg_dark },
+ 'hljs-quote': {
+ color: palette.comment,
+ fontStyle: 'italic',
+ },
+ 'hljs-regex': { color: palette.blue6 },
+ 'hljs-regexp': { color: palette.blue6 },
+ 'hljs-rest_arg': {
+ color: interpolateColor(palette.yellow, palette.fg, 0.8),
+ },
+ 'hljs-section': {
+ color: palette.blue,
+ fontWeight: 'bold',
+ },
+ 'hljs-selector-attr': { color: palette.cyan },
+ 'hljs-selector-class': { color: palette.green1 },
+ 'hljs-selector-id': { color: palette.green1 },
+ 'hljs-selector-pseudo': { color: palette.cyan },
+ 'hljs-selector-tag': { color: palette.magenta },
+ 'hljs-string': { color: palette.green },
+ 'hljs-strong': { fontWeight: 'bold' },
+ 'hljs-subst': { color: palette.blue5 },
+ 'hljs-symbol': { color: palette.magenta },
+ 'hljs-tag': { color: palette.blue1 },
+ 'hljs-template-tag': { color: palette.blue5 },
+ 'hljs-template-variable': { color: palette.fg },
+ 'hljs-title': { color: palette.blue },
+ 'hljs-title-class': { color: palette.blue1 },
+ 'hljs-title-class-inherited': { color: palette.blue1 },
+ 'hljs-title-function': { color: palette.blue },
+ 'hljs-title-function-invoke': { color: palette.blue },
+ 'hljs-type': { color: palette.blue1 },
+ 'hljs-variable': { color: palette.fg },
+ 'hljs-variable-constant': { color: palette.orange },
+ 'hljs-variable-language': { color: palette.red },
+ },
+ tokyoNightColors,
+);
diff --git a/packages/cli/src/ui/themes/theme-manager.ts b/packages/cli/src/ui/themes/theme-manager.ts
index 96b4fea4e3..9f0a7e528a 100644
--- a/packages/cli/src/ui/themes/theme-manager.ts
+++ b/packages/cli/src/ui/themes/theme-manager.ts
@@ -18,6 +18,7 @@ import { ShadesOfPurple } from './builtin/dark/shades-of-purple-dark.js';
import { SolarizedDark } from './builtin/dark/solarized-dark.js';
import { SolarizedLight } from './builtin/light/solarized-light.js';
import { XCode } from './builtin/light/xcode-light.js';
+import { TokyoNight } from './builtin/dark/tokyonight-dark.js';
import * as fs from 'node:fs';
import * as path from 'node:path';
import type { Theme, ThemeType, ColorsTheme, CustomTheme } from './theme.js';
@@ -84,6 +85,7 @@ class ThemeManager {
SolarizedDark,
SolarizedLight,
XCode,
+ TokyoNight,
ANSI,
ANSILight,
];