Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
fcff11a
feat(sdk): add SDK foundation — type declarations, errors, and utilities
Apr 23, 2026
3320446
fix(sdk): narrow assertFunction type from broad Function to callable …
Apr 24, 2026
5b03f77
fix(sdk): update sdk.d.ts header — manually maintained, not generated
Apr 24, 2026
6ce7b18
fix(sdk): align sdk.d.ts types with canonical coreTypes.generated.ts
Apr 24, 2026
14768a5
feat(sdk): wire existing code modules + SDK shared utilities
Apr 23, 2026
9633184
feat(sdk): add snake_case ↔ camelCase key mapping utilities
Apr 24, 2026
aa22fb0
test(sdk): add tests for snake_case ↔ camelCase mapping utilities
Apr 24, 2026
0a4efff
feat(sdk): add SDK runtime — query engine, sessions, build pipeline
Apr 23, 2026
92b13b0
fix(sdk): align internal SDK types with camelCase public contract
Apr 24, 2026
9344bed
fix(sdk): update runtime modules to use camelCase field names
Apr 24, 2026
d1a8d75
fix(test): update session tests to use camelCase field names
Apr 24, 2026
743dd1a
Merge branch 'main' into sdk/pr2-sdk-core
Apr 29, 2026
1a8abb7
fix(sdk): prevent permission timeout race condition with once-only re…
Apr 29, 2026
e35b940
fix(sdk): improve race condition test robustness
Apr 29, 2026
2d1db7e
fix(sdk): handle consecutive underscores in snakeToCamel conversion
Apr 29, 2026
e245d56
fix(sdk): include original error message in permission callback denial
Apr 29, 2026
93d3845
feat(sdk): add optional timeout to env mutex for deadlock prevention
Apr 29, 2026
7f8780f
fix(sdk): remove timed-out callback from mutex queue to prevent deadlock
Apr 29, 2026
113566f
test(sdk): add missing error path and timeout scenario tests
Apr 29, 2026
10ab0e2
fix(sdk): address code review issues - race conditions, validation, e…
Apr 29, 2026
a27127d
merge: sync with origin/main (context preloading, streaming token cou…
Apr 29, 2026
fe34e14
merge: sync with PR2 (race condition fixes, validation, error handling)
Apr 29, 2026
0f3aa7a
merge: sync sdk/pr3-sdk-runtime with origin/main (PR2 + upstream)
May 2, 2026
72d9add
fix(sdk): syntax fixes and MCP connection error handling
May 2, 2026
d0727e0
fix(sdk): syntax fixes, MCP error handling, and logic clarity
May 2, 2026
2cdd52b
fix(sdk): comprehensive error handling and resource cleanup
May 2, 2026
9f4863b
fix(sdk): address code review non-blocking issues
May 2, 2026
38b47e4
fix(sdk): address code review blocking and non-blocking issues
May 2, 2026
7c6f653
fix(sdk): address code review type consistency issues
May 2, 2026
bd8fcf4
fix: restore openclaude.json comment in REPL.tsx
May 2, 2026
f9f327a
fix(sdk): add missing type declarations to sdk.d.ts
May 2, 2026
2806a20
fix(sdk): resource leak and null safety in close/interrupt paths
May 2, 2026
9219e5a
fix(sdk): abort AbortController in SDKSessionImpl.close() to prevent …
May 2, 2026
38d4143
fix(sdk): index ALL entries in byUuid for compact preserved segment
May 2, 2026
cb1e74f
fix(sdk): complete preserved segment handling for compact resumes
May 2, 2026
b0b45ff
fix(sdk): MCP type:sdk tools properly convert SdkMcpToolDefinition to…
May 2, 2026
01b260a
test(sdk): strengthen preserved segment and MCP tools tests
May 2, 2026
41314e3
fix(sdk): published types complete, init errors fatal, permission ses…
May 2, 2026
9503ed1
fix(sdk): complete package types + dynamic permission session_id
May 2, 2026
83974f6
fix(sdk): fix sdk.d.ts for real TypeScript consumer compilation
May 2, 2026
8b7526b
fix(sdk): eliminate React/Ink imports from SDK bundle
May 2, 2026
5dc8c25
fix(sdk): wire disallowedTools through permission context
May 2, 2026
77d900a
fix(sdk): defer permission warning to execution time
May 2, 2026
2c86268
refactor(sdk): extract transcript helpers + fix permission typing
May 2, 2026
0d418e5
fix(sdk): resolve remaining TypeScript errors in SDK modules
May 3, 2026
638eec3
fix(sdk): correct init skip logic and test mocks
May 3, 2026
deb55b2
fix: address code review feedback for exports and build script
May 3, 2026
63a4f3b
feat(desktop): add Electron shell for desktop app (PR1)
May 3, 2026
603cfeb
fix(desktop): harden CSP — remove unsafe-eval from script-src (I10)
May 3, 2026
165a836
fix(desktop): externalize trpc-electron and superjson in main build
May 3, 2026
14235a2
chore(desktop): add macOS icon.icns placeholder for electron-builder
May 3, 2026
e310f54
chore: finalize remaining changes (bun.lock line endings, icon updates)
May 3, 2026
bbcf31b
merge: sync with origin/main (SDK Runtime + misc fixes)
May 4, 2026
f4be2fd
fix(desktop): address PR1 code review findings
May 4, 2026
77c6ee2
refactor(desktop): programmatic CSP and expanded test coverage
May 4, 2026
23b6437
chore: update bun.lock after removing @types/better-sqlite3
May 4, 2026
5ef9e3b
fix: restore lockfile from origin/main and regenerate with desktop wo…
May 4, 2026
a185014
fix: remove workspaces to prevent CLI build regression
May 4, 2026
ef85286
fix(desktop): add vitest-only guards to prevent bun test failures on CI
May 4, 2026
735dfb7
fix(desktop): rename tests to .vitest pattern to prevent bun test dis…
May 4, 2026
d45e0aa
docs: add desktop app design doc with Electron vs Tauri rationale
May 4, 2026
53375df
feat(ci): add dedicated desktop job for vitest tests
May 4, 2026
0daebba
fix(desktop): move dynamic imports into test body to prevent bun:test…
May 4, 2026
a6bfb18
docs: add comprehensive branding & design system section
May 5, 2026
5ca4548
docs(desktop): sync desktop-app-design.md with PR3 (971 lines)
May 6, 2026
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
18 changes: 18 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,21 @@ jobs:

- name: Build web
run: bun run --cwd web build

desktop:
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Set up Bun
uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1
with:
bun-version: 1.3.11

- name: Install desktop dependencies
run: bun install --cwd packages/desktop --frozen-lockfile

- name: Run desktop tests
run: bun run --cwd packages/desktop test
972 changes: 972 additions & 0 deletions docs/desktop-app-design.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions packages/desktop/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
out/
release/
node_modules/
dist/
Binary file added packages/desktop/build/icon.icns
Binary file not shown.
Binary file added packages/desktop/build/icon.ico
Binary file not shown.
Binary file added packages/desktop/build/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 48 additions & 0 deletions packages/desktop/electron.vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { defineConfig, externalizeDepsPlugin } from "electron-vite"
import { resolve } from "path"
import react from "@vitejs/plugin-react"

export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()],
build: {
lib: {
entry: resolve(__dirname, "src/main/index.ts"),
},
rollupOptions: {
output: {
format: "cjs",
},
},
},
},
preload: {
plugins: [externalizeDepsPlugin()],
build: {
lib: {
entry: resolve(__dirname, "src/preload/index.ts"),
},
rollupOptions: {
external: ["electron"],
output: {
format: "cjs",
},
},
},
},
renderer: {
plugins: [react()],
resolve: {
alias: {
"@": resolve(__dirname, "src/renderer"),
},
},
build: {
rollupOptions: {
input: {
index: resolve(__dirname, "src/renderer/index.html"),
},
},
},
},
})
71 changes: 71 additions & 0 deletions packages/desktop/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"name": "@openclaude/desktop",
"version": "0.1.0",
"private": true,
"author": {
"name": "OpenClaude",
"email": "support@openclaude.dev"
},
"description": "OpenClaude Desktop - AI coding assistant",
"type": "module",
"main": "out/main/index.cjs",
"scripts": {
"dev": "electron-vite dev",
"build": "electron-vite build",
"preview": "electron-vite preview",
"package": "electron-builder --dir",
"package:win": "electron-builder --win",
"package:mac": "electron-builder --mac",
"package:linux": "electron-builder --linux",
"dist": "electron-builder",
"ts:check": "tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest"
},
"dependencies": {},
"devDependencies": {
"@electron-toolkit/utils": "^4.0.0",
"@testing-library/react": "^16.3.0",
"@types/node": "^20.17.50",
"@types/react": "^19.1.0",
"@types/react-dom": "^19.1.0",
"@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.20",
"electron": "~39.4.0",
"electron-builder": "^25.1.8",
"electron-vite": "^3.0.0",
"jsdom": "^26.1.0",
"postcss": "^8.5.1",
"react": "19.2.4",
"react-dom": "19.2.4",
"tailwindcss": "^4.1.0",
"typescript": "^5.9.3",
"vite": "^6.3.4",
"vitest": "^3.2.1"
},
"build": {
"appId": "dev.openclaude.desktop",
"productName": "OpenClaude Desktop",
"directories": {
"buildResources": "build",
"output": "release"
},
"files": [
"out/**/*"
],
"mac": {
"category": "public.app-category.developer-tools",
"target": "dmg",
"icon": "build/icon.icns"
},
"win": {
"target": "nsis",
"icon": "build/icon.ico"
},
"linux": {
"target": "AppImage",
"icon": "build/icon.png",
"category": "Development"
}
}
}
75 changes: 75 additions & 0 deletions packages/desktop/src/main/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { app, BrowserWindow, shell, session } from "electron"
import { join } from "path"
import { electronApp, optimizer, is } from "@electron-toolkit/utils"

const CSP_PRODUCTION =
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self'; img-src 'self' data: blob: https:;"

const CSP_DEVELOPMENT =
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' ws://localhost:* http://localhost:*; img-src 'self' data: blob: https:;"

let mainWindow: BrowserWindow | null = null

function createWindow(): void {
mainWindow = new BrowserWindow({
width: 1280,
height: 800,
minWidth: 900,
minHeight: 600,
show: false,
title: "OpenClaude Desktop",
webPreferences: {
preload: join(__dirname, "../preload/index.cjs"),
sandbox: false,
contextIsolation: true,
nodeIntegration: false,
},
})

mainWindow.on("ready-to-show", () => {
mainWindow?.show()
})

mainWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url)
return { action: "deny" }
})

if (is.dev && process.env.ELECTRON_RENDERER_URL) {
mainWindow.loadURL(process.env.ELECTRON_RENDERER_URL)
} else {
mainWindow.loadFile(join(__dirname, "../renderer/index.html"))
}
}

app.whenReady().then(() => {
electronApp.setAppUserModelId("dev.openclaude.desktop")

// Inject CSP via session headers — dev mode allows Vite HMR WebSocket
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
"Content-Security-Policy": [is.dev ? CSP_DEVELOPMENT : CSP_PRODUCTION],
},
})
})

app.on("browser-window-created", (_, window) => {
optimizer.watchWindowShortcuts(window)
})

createWindow()

app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
}).catch(console.error)

app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit()
}
})
6 changes: 6 additions & 0 deletions packages/desktop/src/preload/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { contextBridge } from "electron"

contextBridge.exposeInMainWorld("platform", {
os: process.platform,
arch: process.arch,
})
14 changes: 14 additions & 0 deletions packages/desktop/src/renderer/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import "./styles/globals.css"

export function App() {
return (
<div className="app-shell">
<header className="app-header">
<h1>OpenClaude Desktop</h1>
</header>
<main className="app-main">
<p>Loading...</p>
</main>
</div>
)
}
10 changes: 10 additions & 0 deletions packages/desktop/src/renderer/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export {}

declare global {
interface Window {
platform: {
os: string
arch: string
}
}
}
13 changes: 13 additions & 0 deletions packages/desktop/src/renderer/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- CSP is injected from main process via session headers for dev/prod branching -->
<title>OpenClaude Desktop</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="./main.tsx"></script>
</body>
</html>
4 changes: 4 additions & 0 deletions packages/desktop/src/renderer/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import ReactDOM from "react-dom/client"
import { App } from "./App"

ReactDOM.createRoot(document.getElementById("root")!).render(<App />)
42 changes: 42 additions & 0 deletions packages/desktop/src/renderer/styles/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

html,
body,
#root {
height: 100%;
width: 100%;
}

body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #09090b;
color: #fafafa;
}

.app-shell {
display: flex;
flex-direction: column;
height: 100%;
}

.app-header {
padding: 12px 16px;
border-bottom: 1px solid #27272a;
}

.app-header h1 {
font-size: 14px;
font-weight: 600;
}

.app-main {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
color: #71717a;
}
Loading
Loading