Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 890cd08f57 | |||
| aabc95768c |
@@ -1,6 +1,6 @@
|
||||
# Claude Code Working Guide
|
||||
|
||||
_Last synced: v2.8.74 (2026-11-05) — a page published from its session's scratchpad keeps a viewable copy._ A change that makes any statement in this file, `AGENTS.md`, or a README wrong — a moved path, a new or changed extension point, a retired rule — updates that file in the same change-set and bumps this marker. **Bump = replace the version/date and a ≤ 1-line summary; never append a changelog here** — details belong in the commit message and `docs/`, because this whole file is loaded into every session.
|
||||
_Last synced: v2.8.76 (2026-11-05) — four colour themes (Sunset Cloud, Terminal, Night Sea, Sakura); `--ansi-blue` for a non-blue accent._ A change that makes any statement in this file, `AGENTS.md`, or a README wrong — a moved path, a new or changed extension point, a retired rule — updates that file in the same change-set and bumps this marker. **Bump = replace the version/date and a ≤ 1-line summary; never append a changelog here** — details belong in the commit message and `docs/`, because this whole file is loaded into every session.
|
||||
|
||||
## Project mission
|
||||
- Maintain a reliable local-first dashboard for Claude Code session monitoring.
|
||||
|
||||
@@ -60,6 +60,10 @@ export const THEME_LABELS: Record<string, string> = {
|
||||
canvas: "Canvas",
|
||||
"orca-dark": "Orca Dark",
|
||||
"orca-light": "Orca Light",
|
||||
"sunset-cloud": "Sunset Cloud",
|
||||
terminal: "Terminal",
|
||||
"night-sea": "Night Sea",
|
||||
sakura: "Sakura",
|
||||
};
|
||||
|
||||
const MODES: { mode: ThemeMode; Icon: typeof Moon }[] = [
|
||||
|
||||
@@ -53,6 +53,10 @@ describe("AppearanceSettings", () => {
|
||||
"Apple Light",
|
||||
"Canvas",
|
||||
"Orca Light",
|
||||
"Sunset Cloud",
|
||||
"Terminal",
|
||||
"Night Sea",
|
||||
"Sakura",
|
||||
]) {
|
||||
expect(screen.getByText(name)).toBeInTheDocument();
|
||||
}
|
||||
|
||||
@@ -103,6 +103,19 @@ describe("useTheme", () => {
|
||||
expect(document.documentElement.dataset.theme).toBe("orca-light");
|
||||
});
|
||||
|
||||
it("applies the ai-chat-themes palettes by id, each in its own mode only", () => {
|
||||
const { result } = renderHook(() => useTheme());
|
||||
for (const name of ["sunset-cloud", "terminal", "night-sea"]) {
|
||||
act(() => result.current.setThemeFor("dark", name));
|
||||
expect(document.documentElement.dataset.theme).toBe(name);
|
||||
}
|
||||
act(() => result.current.setThemeFor("dark", "sakura"));
|
||||
expect(result.current.themeFor.dark).toBe("night-sea");
|
||||
act(() => result.current.setThemeFor("light", "sakura"));
|
||||
act(() => result.current.toggleTheme());
|
||||
expect(document.documentElement.dataset.theme).toBe("sakura");
|
||||
});
|
||||
|
||||
it("the default theme carries no data-theme attribute", () => {
|
||||
const { result } = renderHook(() => useTheme());
|
||||
act(() => result.current.setThemeFor("dark", "darcula"));
|
||||
|
||||
@@ -22,8 +22,8 @@ export type ThemeMode = Theme | "system";
|
||||
|
||||
/** Named themes per mode, in picker order. `default` is the stock palette. */
|
||||
export const THEMES = {
|
||||
dark: ["default", "darcula", "apple-dark", "orca-dark"],
|
||||
light: ["default", "canvas", "apple-light", "orca-light"],
|
||||
dark: ["default", "darcula", "apple-dark", "orca-dark", "sunset-cloud", "terminal", "night-sea"],
|
||||
light: ["default", "canvas", "apple-light", "orca-light", "sakura"],
|
||||
} as const satisfies Record<Theme, readonly string[]>;
|
||||
|
||||
const MODE_KEY = "theme";
|
||||
|
||||
@@ -350,6 +350,106 @@
|
||||
--syn-del: 197 0 15; /* #c5000f */
|
||||
}
|
||||
|
||||
/* Sunset Cloud, Terminal, Night Sea (dark) and Sakura (light) — the colour
|
||||
* themes of ai-chat-themes (github.com/Aohkne/ai-chat-themes, MIT), which
|
||||
* gives only a background, a text and an accent colour per theme. Every
|
||||
* other token is derived from those three and held to the bar above: text
|
||||
* ≥ 4.5:1 on a card and on its hover lift, the text accent ≥ 4.5:1 on a card
|
||||
* and on its own /15 chip (Sakura's #e0567f and Sunset's #ff8a6b darkened /
|
||||
* lightened to get there), white ≥ 4.5:1 on `--accent-solid`, each status
|
||||
* label ≥ 4.5:1 on its /20 chip. Their fonts (a monospace UI, Georgia) are
|
||||
* not taken; syntax, diff and `--kept` colours are their mode's defaults.
|
||||
* `--ansi-blue` (read only by `lib/terminalTheme.ts`) keeps a terminal's
|
||||
* blue blue where the accent is green or coral. */
|
||||
.dark[data-theme="sunset-cloud"] {
|
||||
--surface-0: 32 24 36; /* #201824 */
|
||||
--surface-1: 48 37 52; /* #302534 */
|
||||
--surface-2: 54 43 58; /* #362b3a */
|
||||
--surface-3: 60 49 63; /* #3c313f */
|
||||
--surface-4: 67 56 69; /* #433845 */
|
||||
--surface-5: 75 63 76; /* #4b3f4c */
|
||||
--border: 76 64 76; /* #4c404c */
|
||||
--border-light: 88 76 87; /* #584c57 */
|
||||
--accent: 255 159 134; /* #ff9f86 */
|
||||
--accent-hover: 255 188 170; /* #ffbcaa */
|
||||
--accent-solid: 173 94 73; /* #ad5e49 */
|
||||
--accent-solid-hover: 149 81 63; /* #95513f */
|
||||
--fg-primary: 247 232 226; /* #f7e8e2 */
|
||||
--fg-secondary: 214 203 203; /* #d6cbcb */
|
||||
--fg-muted: 176 165 168; /* #b0a5a8 */
|
||||
--status-success: 88 220 156; /* #58dc9c */
|
||||
--status-danger: 255 176 173; /* #ffb0ad */
|
||||
--status-warning: 255 202 22; /* #ffca16 */
|
||||
/* ANSI blue in the terminal: the accent is not blue here. */
|
||||
--ansi-blue: 112 184 255; /* #70b8ff */
|
||||
}
|
||||
|
||||
.dark[data-theme="terminal"] {
|
||||
--surface-0: 8 13 9; /* #080d09 */
|
||||
--surface-1: 14 23 17; /* #0e1711 */
|
||||
--surface-2: 20 30 22; /* #141e16 */
|
||||
--surface-3: 25 36 28; /* #19241c */
|
||||
--surface-4: 31 44 34; /* #1f2c22 */
|
||||
--surface-5: 37 52 41; /* #253429 */
|
||||
--border: 38 54 42; /* #26362a */
|
||||
--border-light: 49 67 53; /* #314335 */
|
||||
--accent: 57 232 122; /* #39e87a */
|
||||
--accent-hover: 116 239 162; /* #74efa2 */
|
||||
--accent-solid: 32 132 70; /* #208446 */
|
||||
--accent-solid-hover: 28 114 60; /* #1c723c */
|
||||
--fg-primary: 185 246 198; /* #b9f6c6 */
|
||||
--fg-secondary: 147 196 157; /* #93c49d */
|
||||
--fg-muted: 117 154 125; /* #759a7d */
|
||||
--status-success: 61 214 140; /* #3dd68c */
|
||||
--status-danger: 255 149 146; /* #ff9592 */
|
||||
--status-warning: 255 202 22; /* #ffca16 */
|
||||
/* ANSI blue in the terminal: the accent is not blue here. */
|
||||
--ansi-blue: 112 184 255; /* #70b8ff */
|
||||
}
|
||||
|
||||
.dark[data-theme="night-sea"] {
|
||||
--surface-0: 11 20 33; /* #0b1421 */
|
||||
--surface-1: 20 31 49; /* #141f31 */
|
||||
--surface-2: 26 37 55; /* #1a2537 */
|
||||
--surface-3: 32 43 62; /* #202b3e */
|
||||
--surface-4: 40 50 69; /* #283245 */
|
||||
--surface-5: 47 58 76; /* #2f3a4c */
|
||||
--border: 48 59 77; /* #303b4d */
|
||||
--border-light: 60 71 89; /* #3c4759 */
|
||||
--accent: 92 175 255; /* #5cafff */
|
||||
--accent-hover: 141 199 255; /* #8dc7ff */
|
||||
--accent-solid: 62 120 176; /* #3e78b0 */
|
||||
--accent-solid-hover: 53 103 151; /* #356797 */
|
||||
--fg-primary: 220 230 250; /* #dce6fa */
|
||||
--fg-secondary: 183 192 210; /* #b7c0d2 */
|
||||
--fg-muted: 146 155 173; /* #929bad */
|
||||
--status-success: 61 214 140; /* #3dd68c */
|
||||
--status-danger: 255 155 153; /* #ff9b99 */
|
||||
--status-warning: 255 202 22; /* #ffca16 */
|
||||
}
|
||||
|
||||
[data-mode="light"][data-theme="sakura"] {
|
||||
--surface-0: 242 230 232; /* #f2e6e8 */
|
||||
--surface-1: 247 235 237; /* #f7ebed */
|
||||
--surface-2: 251 240 242; /* #fbf0f2 */
|
||||
--surface-3: 255 249 250; /* #fff9fa */
|
||||
--surface-4: 255 252 253; /* #fffcfd */
|
||||
--surface-5: 255 255 255; /* #ffffff */
|
||||
--border: 224 210 213; /* #e0d2d5 */
|
||||
--border-light: 237 224 227; /* #ede0e3 */
|
||||
--accent: 167 64 95; /* #a7405f */
|
||||
--accent-hover: 137 52 78; /* #89344e */
|
||||
--accent-solid: 195 75 110; /* #c34b6e */
|
||||
--accent-solid-hover: 168 65 95; /* #a8415f */
|
||||
--fg-primary: 75 42 53; /* #4b2a35 */
|
||||
--fg-secondary: 107 80 89; /* #6b5059 */
|
||||
--fg-muted: 120 97 105; /* #786169 */
|
||||
--status-success: 23 105 45; /* #17692d */
|
||||
--status-danger: 173 28 38; /* #ad1c26 */
|
||||
--status-warning: 124 82 0; /* #7c5200 */
|
||||
--shadow-card: 0 1px 2px rgb(75 42 53 / 0.06), 0 2px 6px rgb(75 42 53 / 0.07);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
body {
|
||||
font-weight: 500;
|
||||
|
||||
@@ -39,6 +39,11 @@ describe("buildTerminalTheme", () => {
|
||||
expect(t.brightWhite).toBe("#edeef0");
|
||||
});
|
||||
|
||||
it("takes ANSI blue from --ansi-blue when a theme's accent is not blue", () => {
|
||||
const t = buildTerminalTheme((n) => ({ ...vars, "--ansi-blue": "112 184 255" })[n] ?? "");
|
||||
expect(t.blue).toBe("#70b8ff");
|
||||
});
|
||||
|
||||
it("makes each bright twin lighter than its base colour", () => {
|
||||
const t = buildTerminalTheme((n) => vars[n] ?? "");
|
||||
const sum = (hex: string) =>
|
||||
|
||||
@@ -40,7 +40,9 @@ function lighten(hex: string | undefined, amount: number): string | undefined {
|
||||
|
||||
/**
|
||||
* Build an xterm theme from a theme's CSS variables. red/green/yellow come from
|
||||
* `--status-*`, blue from `--accent`, black/white from the surface/fg ramp.
|
||||
* `--status-*`, blue from `--ansi-blue` when a theme sets one (its accent is
|
||||
* not blue: Terminal's green, Sunset Cloud's coral) else `--accent`,
|
||||
* black/white from the surface/fg ramp.
|
||||
* Magenta and cyan stay the classic ANSI hues: no token keeps that hue in every
|
||||
* theme (darcula's keyword is orange), and a program printing "magenta" should
|
||||
* get magenta.
|
||||
@@ -50,7 +52,7 @@ export function buildTerminalTheme(read: VarReader): ITheme {
|
||||
const red = v("--status-danger");
|
||||
const green = v("--status-success");
|
||||
const yellow = v("--status-warning");
|
||||
const blue = v("--accent");
|
||||
const blue = v("--ansi-blue") ?? v("--accent");
|
||||
const magenta = "#c678dd";
|
||||
const cyan = "#56b6c2";
|
||||
return {
|
||||
|
||||
@@ -7316,7 +7316,7 @@ exports[`screen snapshots > Settings — about 1`] = `
|
||||
<span
|
||||
class="text-status-warning/90"
|
||||
>
|
||||
UI build v2.8.75 (rebuild client to match)
|
||||
UI build v2.8.76 (rebuild client to match)
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
+3
-2
@@ -84,8 +84,9 @@ Internal build — all rights reserved.
|
||||
- **Updates.** Release-based update detection with an in-UI **Update all**
|
||||
(marketplaces → every plugin → AgentHub last → one session reload).
|
||||
- **Appearance.** Settings → Appearance picks Dark / Light / System (follows the
|
||||
OS live) and a theme per mode — dark: Default, Darcula, Apple Dark, Orca Dark;
|
||||
light: Default, Apple Light, Canvas, Orca Light. Each mode
|
||||
OS live) and a theme per mode — dark: Default, Darcula, Apple Dark, Orca Dark,
|
||||
Sunset Cloud, Terminal, Night Sea; light: Default, Apple Light, Canvas, Orca
|
||||
Light, Sakura (the four last from ai-chat-themes, colours only). Each mode
|
||||
remembers its own theme, so the sidebar's quick toggle swaps between the two.
|
||||
It also picks the workspace terminals' font: JetBrains Mono (default), the
|
||||
rounded Maple Mono, or the browser's own fixed-width
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "agenthub",
|
||||
"version": "2.8.75",
|
||||
"version": "2.8.76",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "agenthub",
|
||||
"version": "2.8.75",
|
||||
"version": "2.8.76",
|
||||
"hasInstallScript": true,
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "agenthub",
|
||||
"version": "2.8.75",
|
||||
"version": "2.8.76",
|
||||
"bin": {
|
||||
"agenthub": "bin/agenthub.js"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user