Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 30 additions & 32 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,34 +52,34 @@ conversation with the agent. Every pixel must earn its place.

### Typography

| Role | Size | Weight | Tracking | Font Stack |
| -------------------------- | -------------------- | --------------- | --------- | ---------------------------- |
| Thread title (sidebar) | `text-xs` (0.75rem) | `font-normal` | default | Inter, system-ui, sans-serif |
| Thread subtitle / metadata | `text-[10px]` | `font-normal` | default | Inter, system-ui, sans-serif |
| Badge text | `text-[10px]` | `font-medium` | default | Inter, system-ui, sans-serif |
| Button text | `text-sm` (0.875rem) | `font-medium` | default | Inter, system-ui, sans-serif |
| Heading / dialog title | `text-lg` (1.125rem) | `font-semibold` | `-0.01em` | Inter, system-ui, sans-serif |
| Code / terminal | `text-sm` | `font-normal` | default | SF Mono, Consolas, monospace |
| Project name | `text-xs` | `font-semibold` | default | Inter, system-ui, sans-serif |
| Role | Size | Weight | Tracking | Font Stack |
|------|------|--------|----------|------------|
| Thread title (sidebar) | `text-xs` (0.75rem) | `font-normal` | default | Inter, system-ui, sans-serif |
| Thread subtitle / metadata | `text-[10px]` | `font-normal` | default | Inter, system-ui, sans-serif |
| Badge text | `text-[10px]` | `font-medium` | default | Inter, system-ui, sans-serif |
| Button text | `text-sm` (0.875rem) | `font-medium` | default | Inter, system-ui, sans-serif |
| Heading / dialog title | `text-lg` (1.125rem) | `font-semibold` | `-0.01em` | Inter, system-ui, sans-serif |
| Code / terminal | `text-sm` | `font-normal` | default | SF Mono, Consolas, monospace |
| Project name | `text-xs` | `font-semibold` | default | Inter, system-ui, sans-serif |

### Color Semantics

Colors are referenced through CSS custom properties, never hardcoded hex values.

| Token | Usage |
| -------------------------- | ------------------------------------------------- |
| `text-foreground` | Primary text |
| `text-muted-foreground` | Secondary/deemphasized text |
| Token | Usage |
|-------|-------|
| `text-foreground` | Primary text |
| `text-muted-foreground` | Secondary/deemphasized text |
| `text-muted-foreground/50` | Tertiary/metadata text (branch names, timestamps) |
| `bg-background` | Page background |
| `bg-accent` | Hover state, active row highlight |
| `bg-accent/60` | Active sidebar item |
| `bg-accent/40` | Selected sidebar item |
| `text-emerald-600` | Additions / success (green) |
| `text-rose-500` | Deletions / error (red) |
| `text-warning` | Warning states, behind-upstream |
| `text-destructive` | Destructive actions (delete) |
| `border-border/60` | Subtle badge borders |
| `bg-background` | Page background |
| `bg-accent` | Hover state, active row highlight |
| `bg-accent/60` | Active sidebar item |
| `bg-accent/40` | Selected sidebar item |
| `text-emerald-600` | Additions / success (green) |
| `text-rose-500` | Deletions / error (red) |
| `text-warning` | Warning states, behind-upstream |
| `text-destructive` | Destructive actions (delete) |
| `border-border/60` | Subtle badge borders |

### Spacing Rules

Expand All @@ -93,16 +93,15 @@ Colors are referenced through CSS custom properties, never hardcoded hex values.

### Themes

Six premium themes, each with light and dark variants:
Five premium themes, each with light and dark variants:

| Theme | Vibe |
| --------------------- | ------------------------------------- |
| **Iridescent Void** | Futuristic, expensive, slightly alien |
| **Solar Witch** | Magical, cozy, ritualistic |
| **Carbon** | Stark, modern, performance-focused |
| **Vapor** | Refined, fluid, purposeful |
| **Cotton Candy** | Sweet, dreamy, pink and blue |
| **Cathedral Circuit** | Sacred machine, techno-gothic |
| Theme | Vibe |
|-------|------|
| **Iridescent Void** | Futuristic, expensive, slightly alien |
| **Carbon** | Stark, modern, performance-focused |
| **Vapor** | Refined, fluid, purposeful |
| **Cotton Candy** | Sweet, dreamy, pink and blue |
| **Cathedral Circuit** | Sacred machine, techno-gothic |

All themes define the same set of CSS custom properties. Components must use semantic
tokens (`bg-accent`, `text-muted-foreground`) — never theme-specific values.
Expand Down Expand Up @@ -250,7 +249,6 @@ a single flow:
```

Quick action resolves automatically based on git state:

- Has changes + no PR → "Commit, push & PR"
- Has changes + existing PR → "Commit & push"
- No changes + ahead → "Push & create PR"
Expand Down
2 changes: 1 addition & 1 deletion apps/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"@anthropic-ai/claude-agent-sdk": "^0.2.77",
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@pierre/diffs": "^1.1.0-beta.16",
"@pierre/diffs": "1.1.13",
"effect": "catalog:",
"node-pty": "^1.1.0",
"open": "^10.1.0",
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/openclaw/GatewayClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ export class OpenclawGatewayClient {

if (frame.type === "event" && typeof frame.event === "string") {
let matchedWaiter = false;
for (const waiter of this.pendingEventWaiters) {
for (const waiter of [...this.pendingEventWaiters]) {
if (waiter.eventName === frame.event) {
matchedWaiter = true;
this.pendingEventWaiters.delete(waiter);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as Effect from "effect/Effect";
import * as SqlClient from "effect/unstable/sql/SqlClient";

export default Effect.gen(function* () {
const sql = yield* SqlClient.SqlClient;

yield* sql`
CREATE TABLE IF NOT EXISTS openclaw_gateway_config (
config_id TEXT PRIMARY KEY,
gateway_url TEXT NOT NULL,
encrypted_shared_secret TEXT NULL,
device_id TEXT NOT NULL,
device_public_key TEXT NOT NULL,
device_fingerprint TEXT NOT NULL,
encrypted_device_private_key TEXT NOT NULL,
encrypted_device_token TEXT NULL,
device_token_role TEXT NULL,
device_token_scopes_json TEXT NOT NULL DEFAULT '[]',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
)
`;
});
4 changes: 2 additions & 2 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"@lexical/react": "^0.41.0",
"@okcode/contracts": "workspace:*",
"@okcode/shared": "workspace:*",
"@pierre/diffs": "1.1.0-beta.16",
"@pierre/diffs": "1.1.13",
"@tanstack/react-pacer": "^0.19.4",
"@tanstack/react-query": "^5.90.0",
"@tanstack/react-router": "^1.160.2",
Expand All @@ -42,7 +42,7 @@
"html-to-image": "^1.11.13",
"lexical": "^0.41.0",
"lucide-react": "^0.564.0",
"oxfmt": "^0.42.0",
"oxfmt": "^0.44.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-intl": "^10.1.1",
Expand Down
185 changes: 51 additions & 134 deletions apps/web/src/themes.css
Original file line number Diff line number Diff line change
Expand Up @@ -122,37 +122,6 @@
--warning: #fbbf24;
--warning-foreground: #fcd34d;
}
/* ─── Solar Witch ─── mystical, radiant, high-contrast sunset magic ─── */

:root.theme-solar-witch {
color-scheme: light;
--background: #fff7ed;
--foreground: #3b0764;
--card: #ffedd5;
--card-foreground: #3b0764;
--popover: #fff7ed;
--popover-foreground: #3b0764;
--primary: oklch(0.68 0.23 35);
--primary-foreground: #ffffff;
--secondary: rgba(251, 146, 60, 0.12);
--secondary-foreground: #7c2d12;
--muted: rgba(245, 158, 11, 0.12);
--muted-foreground: #9a3412;
--accent: rgba(236, 72, 153, 0.12);
--accent-foreground: #831843;
--destructive: #dc2626;
--destructive-foreground: #b91c1c;
--border: rgba(234, 88, 12, 0.18);
--input: rgba(234, 88, 12, 0.14);
--ring: oklch(0.68 0.23 35);
--info: #7c3aed;
--info-foreground: #6d28d9;
--success: #16a34a;
--success-foreground: #15803d;
--warning: #f59e0b;
--warning-foreground: #b45309;
}

:root.theme-solar-witch.dark {
color-scheme: dark;
--background: #140b1f;
Expand Down Expand Up @@ -302,116 +271,64 @@
--warning-foreground: #e8b830;
}

/* ─── Cotton Candy ─── warm paper light, neon candy dark ─── */
/* ─── Cotton Candy ─── sweet, dreamy pink & blue ─── */

:root.theme-cotton-candy {
color-scheme: light;
--background: rgb(249, 249, 249);
--foreground: rgb(32, 32, 32);
--card: rgb(252, 252, 252);
--card-foreground: rgb(32, 32, 32);
--popover: rgb(252, 252, 252);
--popover-foreground: rgb(32, 32, 32);
--primary: rgb(107, 71, 57);
--primary-foreground: rgb(255, 255, 255);
--secondary: rgb(255, 223, 181);
--secondary-foreground: rgb(100, 40, 17);
--muted: rgb(239, 239, 239);
--muted-foreground: rgb(100, 100, 100);
--accent: rgb(232, 232, 232);
--accent-foreground: rgb(32, 32, 32);
--destructive: rgb(255, 60, 20);
--destructive-foreground: rgb(255, 255, 255);
--border: rgb(216, 216, 216);
--input: rgb(216, 216, 216);
--ring: rgb(107, 71, 57);
--chart-1: rgb(107, 71, 57);
--chart-2: rgb(255, 223, 181);
--chart-3: rgb(232, 232, 232);
--chart-4: rgb(255, 230, 196);
--chart-5: rgb(110, 69, 54);
--sidebar: rgb(251, 251, 251);
--sidebar-foreground: rgb(37, 37, 37);
--sidebar-primary: rgb(52, 52, 52);
--sidebar-primary-foreground: rgb(251, 251, 251);
--sidebar-accent: rgb(247, 247, 247);
--sidebar-accent-foreground: rgb(52, 52, 52);
--sidebar-border: rgb(235, 235, 235);
--sidebar-ring: rgb(181, 181, 181);
--font-sans: Oxanium, sans-serif;
--font-serif: "Space Grotesk", serif;
--font-mono: Oxanium, sans-serif;
--radius: 0.6rem;
--shadow-x: 0;
--shadow-y: 1px;
--shadow-blur: 3px;
--shadow-spread: 0px;
--shadow-opacity: 0.1;
--shadow-color: oklch(0 0 0);
--shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1);
--shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1);
--shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1);
--shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
--tracking-normal: 0em;
--spacing: 0.2rem;
--background: #fdf6f9;
--foreground: #2a1f2e;
--card: #fceef5;
--card-foreground: #2a1f2e;
--popover: #fceef5;
--popover-foreground: #2a1f2e;
--primary: oklch(0.72 0.14 350);
--primary-foreground: #ffffff;
--secondary: rgba(248, 185, 215, 0.12);
--secondary-foreground: #2a1f2e;
--muted: rgba(160, 210, 248, 0.1);
--muted-foreground: #8a7e94;
--accent: rgba(150, 212, 252, 0.14);
--accent-foreground: #2a1f2e;
--destructive: #e85475;
--destructive-foreground: #d03058;
--border: rgba(248, 180, 215, 0.2);
--input: rgba(248, 180, 215, 0.22);
--ring: oklch(0.72 0.14 350);
--info: #7ec8ee;
--info-foreground: #5aaedb;
--success: #6cc4a0;
--success-foreground: #4aaa82;
--warning: #f5baca;
--warning-foreground: #d8929e;
}

:root.theme-cotton-candy.dark {
color-scheme: dark;
--background: rgb(13, 13, 13);
--foreground: rgb(237, 237, 237);
--card: rgb(28, 28, 28);
--card-foreground: rgb(238, 238, 238);
--popover: rgb(26, 26, 26);
--popover-foreground: rgb(238, 238, 238);
--primary: rgb(255, 178, 238);
--primary-foreground: rgb(45, 6, 45);
--secondary: rgb(60, 37, 55);
--secondary-foreground: rgb(254, 194, 255);
--muted: rgb(28, 28, 28);
--muted-foreground: rgb(181, 181, 181);
--accent: rgb(13, 13, 13);
--accent-foreground: rgb(237, 237, 237);
--destructive: rgb(255, 60, 20);
--destructive-foreground: rgb(255, 255, 255);
--border: rgb(34, 22, 33);
--input: rgb(71, 71, 71);
--ring: rgb(255, 194, 244);
--chart-1: rgb(255, 194, 244);
--chart-2: rgb(60, 37, 56);
--chart-3: rgb(41, 41, 41);
--chart-4: rgb(70, 42, 65);
--chart-5: rgb(255, 194, 247);
--sidebar: rgb(23, 23, 28);
--sidebar-foreground: rgb(245, 244, 245);
--sidebar-primary: rgb(245, 0, 143);
--sidebar-primary-foreground: rgb(255, 255, 255);
--sidebar-accent: rgb(43, 38, 43);
--sidebar-accent-foreground: rgb(245, 244, 245);
--sidebar-border: rgb(43, 38, 43);
--sidebar-ring: rgb(217, 211, 216);
--font-sans: Oxanium, sans-serif;
--font-serif: "Space Grotesk", serif;
--font-mono: Oxanium, sans-serif;
--radius: 0.6rem;
--shadow-x: 0;
--shadow-y: 1px;
--shadow-blur: 3px;
--shadow-spread: 0px;
--shadow-opacity: 0.1;
--shadow-color: oklch(0 0 0);
--shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1);
--shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1);
--shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1);
--shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
--background: #170e1a;
--foreground: #f4e8f2;
--card: #1e1222;
--card-foreground: #f4e8f2;
--popover: #1e1222;
--popover-foreground: #f4e8f2;
--primary: oklch(0.75 0.14 350);
--primary-foreground: #170e1a;
--secondary: rgba(250, 170, 210, 0.08);
--secondary-foreground: #f4e8f2;
--muted: rgba(150, 210, 250, 0.08);
--muted-foreground: #a090aa;
--accent: rgba(150, 215, 255, 0.1);
--accent-foreground: #f4e8f2;
--destructive: #ff6b8a;
--destructive-foreground: #ff95aa;
--border: rgba(250, 170, 215, 0.1);
--input: rgba(250, 170, 215, 0.12);
--ring: oklch(0.75 0.14 350);
--info: #8ed4f5;
--info-foreground: #aee0f8;
--success: #7dd4b0;
--success-foreground: #90e0c0;
--warning: #f5bfcc;
--warning-foreground: #f8cdd8;
}

/* ─── Cathedral Circuit ─── sacred machine, techno-gothic ─── */
Expand Down
Loading
Loading