Skip to content
Open
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
20 changes: 15 additions & 5 deletions docs/IDE_BUILD_PLAN.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Custom AI-Integrated IDE — Build Plan

> **Project codename:** _aIDE_
> **Last updated:** April 2, 2026
> **Last updated:** April 8, 2026
> **Status:** Active development

---
Expand Down Expand Up @@ -98,7 +98,7 @@ A desktop IDE built specifically for the workflow of running multiple AI coding

### Nice-to-have (v2+)

- [x] Agent chat panel UI — Dockview `chatPane` with Ask/Edit/Agent modes, streaming message display, tool call approval cards, working set picker, markdown rendering with syntax highlighting
- [x] Agent chat panel UI — Dockview `chatPane` with Ask/Edit/Agent modes, streaming message display, tool call approval cards, working set picker, markdown rendering with syntax highlighting, shared `@file` context mentions, and slash-command autocomplete
- [ ] Cursor-style agent panel UI (structured diffs, progress, pause/resume)
- [x] Claude Agent SDK integration (replacing raw Claude Code CLI subprocess spawning with `@anthropic-ai/claude-agent-sdk` `query()` async generator)
- [ ] Tailwind CSS IntelliSense (via tailwindcss-language-server)
Expand All @@ -115,6 +115,14 @@ A desktop IDE built specifically for the workflow of running multiple AI coding
- [ ] Linked workspace groups — related workspaces (e.g. frontend + backend), cross-workspace terminal, shared env references
- [ ] Worktree color coding — assign a distinct accent color to each worktree and apply it to terminal tabs, editor tabs, and pane borders so it's immediately clear which worktree a tab belongs to (branch badge pills already implemented in 5.1e)
- [ ] Custom user themes beyond light/dark defaults

### Theme System (Implemented foundation)

- Themes now load through a registry-backed manifest system instead of hardcoded `one-dark` / `one-light` checks
- Built-in themes and user-installed themes share the same manifest shape: `id`, `label`, `appearance`, and token map
- User themes live in the app-level themes folder under Electron user data and can be reloaded without code changes
- App settings persist the active theme plus separate default dark and default light theme ids; the toggle switches between those configured defaults
- Command palette actions now cover selecting the active theme, changing default dark/light themes, reloading the registry, and opening the themes folder
- [ ] Editor minimap (community CodeMirror extension or custom build)
- [ ] Auto-update via `electron-updater` — notify + prompt (never silent restart). Compile-from-source only for MVP
- [ ] React `ErrorBoundary` per pane (crash in one pane doesn't kill others), graceful error state UI, opt-in crash telemetry via `electron.crashReporter` or Sentry
Expand Down Expand Up @@ -660,7 +668,7 @@ Terminal pane supports tabs internally. One tab for the interactive shell, one f
Replace raw terminal with structured integration:

```typescript
import { query } from '@anthropic-ai/claude-code'
import { query } from '@anthropic-ai/claude-agent-sdk'

const agentProcess = new UtilityProcess('./agent-worker.js', {
env: { ANTHROPIC_API_KEY: getStoredApiKey() },
Expand Down Expand Up @@ -1043,7 +1051,7 @@ The full workspace switching experience. You can create two workspaces, start Cl
- Display: estimated cost (token count × pricing)

- [ ] **5.2** Claude Agent SDK integration
- Install `@anthropic-ai/claude-code`
- Install `@anthropic-ai/claude-agent-sdk`
- Build `AgentWorker` UtilityProcess that runs the SDK's `query()` loop
- Implement IPC message protocol between AgentWorker and renderer
- Stream events to `AgentPane`: `file_read`, `file_write`, `command_run`, `thinking`, `complete`
Expand Down Expand Up @@ -1294,6 +1302,8 @@ These need a decision before or during the relevant phase.

Track milestone completion here. Update as you go.

**2026-04-08:** Full `@opencode-ai/sdk` integration — OpenCode is now a true first-class backend with parity to the SDK's surface. **Foundation:** new per-workspace `OpenCodeServerHost` (`packages/main/src/chat/openCodeServerHost.ts`) runs one persistent `opencode serve` process per `WorkspaceRuntime`, with a single shared SSE pump fanned out to per-session subscribers; the `openCodeAdapter` is now a thin per-turn driver that gets a client + session-scoped event stream from the host instead of spawning servers per turn. **Permissions:** new `permissionMatching.ts` lifts the IDE's `agent.permissionTier` + `agent.autoApprove` decision logic out of `agentManager.ts` so both built-in and CLI agents share it; new `openCodePermissionBridge.ts` maps the IDE's tool names to OpenCode's permission categories (`edit`/`bash`/`webfetch`/…) for both pre-flight agent-config and runtime decisions; new `approvalRouter.ts` (registered as a `WorkspaceRuntime` service slot) routes `CHAT_TOOL_APPROVE`/`CHAT_TOOL_REJECT` IPC to whichever manager owns the toolCallId so OpenCode permission prompts surface in the existing built-in approval UI (no new approval pane). **Telemetry:** existing per-session `totalCostUsd` accumulator extended with a per-session `totalTokens` (input/output/reasoning/cacheRead/cacheWrite) breakdown; both Claude and OpenCode adapters now extract token usage from result/message events; renderer shows a `CostTokenBadge` in the pane header. **Hot session config:** `CliAgentBackendState` extended with `providerID`/`modelID`/`agent`/`mode`/`systemPromptOverride`/`toolToggles`; new `cliAgentUpdateSessionConfig` IPC + `SessionSettingsPanel` collapsible disclosure in `CliAgentPane` exposes provider/model/agent/mode pickers, system prompt override, and a tool-toggle list (each lazy-fetched from `client.config.providers()` / `client.app.agents()` / `client.tool.list()`). **Rich part types:** `CliAgentMessageType` extended with `reasoning`/`patch`/`step`/`snapshot`/`retry`/`compaction`/`agent_change`/`subtask`/`file_attachment`; new `openCodePartConverter.ts` maps every SDK `Part` discriminant onto our normalized message shape; new `RichPartRenderer.tsx` renders each variant. **Session ops:** new IPC + manager methods + `SessionMenu.tsx` kebab for share/unshare/summarize/revert/unrevert/fork/abort/diff/todo/init/delete-remote (each delegates to `client.session.*`). **Workspace ops:** opt-in `OpenCodeToolsPane` Dockview pane with Files/Search/Shell/Status/Providers tabs that call `client.{file,find,session.shell,lsp,formatter}.*`; **Config/auth/providers:** `OpenCodeProvidersTab.tsx` lists providers, lets users sign in (paste-the-code OAuth or API key), and shows model lists; **Diagnostics + TUI:** `DiagnosticsPanel.tsx` shows server URL/mode/paths/LSP/formatter, `TuiControlPanel.tsx` exposes the TUI control surface. **Lifecycle integration:** `WorkspaceRuntime.refreshWorkload` sums pending approvals across both managers; `cliAgentManager.destroy()` disposes the `OpenCodeServerHost`; settings-changed listener mirrors `agent.permissionTier`/`agent.autoApprove` updates into `cliAgentManager.updatePermissions()` so live tier changes apply mid-session. **Tests:** new `openCodeServerHost`/`openCodeAdapter`/`openCodePermissionBridge`/`openCodePartConverter`/`cliAgentApprovalRouter` test files and 5 new assertions in `cliAgentManager.test.ts`; all 36 new tests pass alongside existing coverage.

**2026-03-29:** Built-in chat — `useChat` refreshes after `CHAT_STREAM_END` and tool-call IPC now call `chatGetHistory(workspaceId, sessionId)` so history stays scoped to the active tab; avoids main falling back to `getMostRecent` (multi-tab isolation + pre-persist race).

**2026-04-08:** Pane focus handoff fix — `EditorPane` and `TerminalPane` now move DOM focus into CodeMirror/xterm when a Dockview panel becomes active and also when a newly-created panel finishes mounting while already active. This fixes keyboard pane/tab switching paths that selected a panel without moving the caret into the target surface.
Expand Down Expand Up @@ -1365,7 +1375,7 @@ Track milestone completion here. Update as you go.
| 5.1c CLI native session hydration | ✅ Complete | `ClaudeNativeSessionWatcher.loadMessages(sessionId)` reads `~/.claude/projects/<slug>/<sessionId>.jsonl`, skips sidechains / thinking / file-history blocks, and maps rows to `CliAgentMessage[]`. IPC `cli-agent:load-messages` takes `(workspaceId, conversationId)`, returns `[]` when that workspace is not active (avoids native-prefix reads against the wrong project dir), and `useCliAgent` uses a hydrate generation guard, avoids clobbering a non-empty transcript with a stale empty IPC result, clears transcript only when the workspace+conversation key changes, and re-fetches native history once when `CONVERSATION_LIST_CHANGED` reports a `claude-native` row with messages but the pane is still empty. `CliAgentPane` waits on `historyHydrated`. Aide-managed sessions use `ConversationStore.loadMessages`. `CliAgentManager.start` sets `claudeSessionId` from `claude-native:<uuid>` for `--resume`. |
| 5.1d CLI multi-tab isolation | ✅ Complete | New `cliAgentPane` instances receive a provisional `conversationId` (`crypto.randomUUID()` from `agent.open` and default workspace layout in `workspaceSwitcher`). `useCliAgent` stops calling `cliAgentGetSession(workspaceId)` without a session id so tabs are not hydrated from `CliAgentManager.getSession`'s first in-memory match for the workspace. Command `agent.open` (e.g. Cmd+K Cmd+A) always adds a new agent panel for parallel work instead of focusing an existing tab. |
| 5.1e Multi-worktree agent orchestration | ✅ Complete | Per-panel worktree isolation: `worktreePath` threaded through `CliAgentManager.start()` → spawn `cwd`, `CliAgentSession`, IPC, `useCliAgent` hook, `CliAgentPane` params. `AgentTab` custom tab component with branch badge pill (registered in `DockviewContainer.tabComponents`). "Start Agent in Worktree" button + context menu entry in `WorktreePanel`/`WorktreeItem`. Built-in agent isolation via `ToolContext.effectiveRoot` in `agentTools.ts` (terminal_exec, search_files, git_status, git_diff). `ChatSession.worktreePath` loaded from `ConversationMeta`. Worktree removal confirmation guard. Terminal panels from worktrees also get branch badges. |
| 5.2 Claude Agent SDK integration | ⬜ Not started | |
| 5.2 Claude Agent SDK integration | ✅ Complete | `CliAgentManager` now owns a generic external-agent session layer with backend adapters for Claude Code, OpenCode, and Codex. Claude still streams via `@anthropic-ai/claude-agent-sdk` and resolves the packaged executable from the SDK's own unpacked `cli.js`; OpenCode is wired through the official SDK/client flow against an `opencode serve` process; Codex is wired through `codex exec --json`. Sessions persist per-backend resume state so a conversation can hot-swap external backends, while `ConversationMeta.backend` tracks the active backend. Frontend hot-swap controls and richer mixed-backend transcript UI are still pending. |
| 5.3 Diff preview before apply | ⬜ Not started | |
| 5.4 Agent edit highlighting in editor | ⬜ Not started | |
| 5.5 Crash recovery | ⬜ Not started | |
Expand Down
169 changes: 169 additions & 0 deletions docs/THEME_FILES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# Theme Files

aIDE loads custom themes from JSON files in the app themes folder.

## Location

- Open the folder from:
- Settings > Workbench > Appearance > `Open Themes Folder`
- Command palette: `Open Themes Folder`
- Drop one or more `.json` files into that folder.
- Reload themes from:
- Settings > Workbench > Appearance > `Reload Themes`
- Command palette: `Reload Themes`

## Required Structure

Each file must be valid JSON and contain one theme object.

Required fields:

- `id`: unique string id for the theme
- `label`: human-readable name shown in the UI
- `appearance`: must be `"dark"` or `"light"`
- `tokens`: object whose keys are CSS custom properties beginning with `--`

Optional fields:

- `description`
- `author`

## Minimal Example

```json
{
"id": "my-dark-theme",
"label": "My Dark Theme",
"appearance": "dark",
"tokens": {
"--bg-base": "#14161a",
"--text-primary": "#d7dae0",
"--accent": "#6aa0ff"
}
}
```

## Full Example

```json
{
"id": "forest-night",
"label": "Forest Night",
"appearance": "dark",
"description": "Muted green-tinted dark theme.",
"author": "You",
"tokens": {
"--bg-base": "#1a1f1c",
"--bg-elevated": "#151916",
"--bg-sunken": "#111512",
"--bg-overlay": "#101411",
"--bg-active-tab": "#1a1f1c",
"--bg-inactive-tab": "#171b18",
"--bg-hover": "rgba(255, 255, 255, 0.05)",
"--bg-selection": "rgba(98, 160, 120, 0.18)",
"--bg-info": "rgba(98, 160, 120, 0.12)",
"--bg-info-hover": "rgba(98, 160, 120, 0.22)",
"--text-primary": "#d7dae0",
"--text-secondary": "#9aa39c",
"--text-muted": "#68706a",
"--text-selected": "#ffffff",
"--text-info": "#74b7ff",
"--text-success": "#89c779",
"--text-warning": "#d8b36a",
"--text-error": "#e57c73",
"--border-base": "#0e120f",
"--border-subtle": "#283028",
"--accent": "#62a078",
"--accent-rgb": "98, 160, 120",
"--text-on-accent": "#ffffff",
"--syntax-keyword": "#c792ea",
"--syntax-fn": "#82aaff",
"--syntax-string": "#a5d6a7",
"--syntax-number": "#f7c873",
"--syntax-comment": "#5f6b66",
"--syntax-tag": "#f07178",
"--syntax-attr": "#7cc7ff",
"--merge-delete-bg": "rgba(240, 113, 120, 0.14)",
"--merge-delete-gutter": "#f07178",
"--merge-insert-bg": "rgba(165, 214, 167, 0.14)",
"--merge-insert-gutter": "#a5d6a7",
"--merge-char-insert": "rgba(165, 214, 167, 0.24)",
"--merge-char-delete": "rgba(240, 113, 120, 0.24)"
}
}
```

## Supported Tokens

These are the tokens the built-in themes define and the custom theme system expects.

Backgrounds:

- `--bg-base`
- `--bg-elevated`
- `--bg-sunken`
- `--bg-overlay`
- `--bg-active-tab`
- `--bg-inactive-tab`
- `--bg-hover`
- `--bg-selection`
- `--bg-info`
- `--bg-info-hover`

Text:

- `--text-primary`
- `--text-secondary`
- `--text-muted`
- `--text-selected`
- `--text-info`
- `--text-success`
- `--text-warning`
- `--text-error`
- `--text-on-accent`

Borders and accent:

- `--border-base`
- `--border-subtle`
- `--accent`
- `--accent-rgb`

Syntax:

- `--syntax-keyword`
- `--syntax-fn`
- `--syntax-string`
- `--syntax-number`
- `--syntax-comment`
- `--syntax-tag`
- `--syntax-attr`

Inline diff:

- `--merge-delete-bg`
- `--merge-delete-gutter`
- `--merge-insert-bg`
- `--merge-insert-gutter`
- `--merge-char-insert`
- `--merge-char-delete`

## Important Rules

- `id` must be unique across all installed themes.
- `appearance` controls whether the theme can be chosen as the default dark or default light theme.
- Token keys must start with `--`.
- Token values must be strings.
- Only `.json` files are loaded.
- Invalid or malformed theme files are ignored.

## Fallback Behavior

- If a token is missing, aIDE fills it from the built-in fallback theme of the same appearance.
- If the active theme no longer exists, aIDE falls back to the configured default dark theme.
- If a configured default dark/light theme no longer exists, aIDE falls back to the built-in `one-dark` or `one-light` theme.

## Notes

- The theme toggle switches between the configured default dark and default light themes, not between fixed built-in themes.
- Built-in themes use the same manifest shape as custom themes.
Loading
Loading