mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-02-14 12:47:33 +00:00
* feat: improve version comparison logic in useVersionCheck hook
* refactor: useVersionCheck.js to typescript
* refactor: move VersionUpgradeModal component to its own file and remove it from AppContent component
* refactor: improve VersionUpgradeModal props and extract ReleaseInfo type
Using useVersionCheck hook in 2 places caused github requests to be made twice, which is not ideal.
* refactor: handleUpdateNow function with useCallback and error display in VersionUpgradeModal
* refactor: move isOpen check to the correct position in VersionUpgradeModal
* refactor: move VersionUpgradeModal and collapsed sidebar to Sidebar component from App.jsx
* refactor: remove unused SettingsIcon import from App.jsx
* refactor: move formatTimeAgo function to dateUtils.ts
* refactor: replace useLocalStorage with useUiPreferences for better state management in AppContent
* refactor: use shared props for Sidebar props in AppContent
* refactor: remove showQuickSettings state and toggle from AppContent, manage isOpen state directly in QuickSettingsPanel
* refactor: move preference props directly to QuickSettingsPanel and MainContent
* refactor: remove unused isPWA prop
* refactor: remove unused isPWA prop from AppContent
* refactor: remove unused generatingSummary state from Sidebar component
* refactor: remove unused isPWA prop from MainContent component
* refactor: use usePrefrences for sidebar visibility in Sidebar component
* refactor: extract device detection into hook and localize PWA handling to Sidebar
- Add new `useDeviceSettings` hook (`src/hooks/useDeviceSettings.ts`) to centralize
device-related state:
- exposes `isMobile` and `isPWA`
- supports options: `mobileBreakpoint`, `trackMobile`, `trackPWA`
- listens to window resize for mobile updates
- listens to `display-mode: standalone` changes for PWA updates
- includes `matchMedia.addListener/removeListener` fallback for older environments
- Update `AppContent` (`src/App.jsx`) to consume `isMobile` from
`useDeviceSettings({ trackPWA: false })`:
- remove local `isMobile` state/effect
- remove local `isPWA` state/effect
- keep existing `isMobile` behavior for layout and mobile sidebar flow
- stop passing `isPWA` into `Sidebar` props
- Update `Sidebar` (`src/components/Sidebar.jsx`) to own PWA detection:
- consume `isPWA` from `useDeviceSettings({ trackMobile: false })`
- add effect to toggle `pwa-mode` class on `document.documentElement` and `document.body`
- retain use of `isMobile` prop from `App` for sidebar/mobile rendering decisions
Why:
- removes duplicated device-detection logic from `AppContent`
- makes device-state logic reusable and easier to maintain
- keeps PWA-specific behavior where it is actually used (`Sidebar`)
* chore(to-remove): comment todo's
* refactor: remove unused createNewProject and cancelNewProject functions from Sidebar component
* refactor(sidebar): extract typed app/sidebar architecture and split Sidebar into modular components
- Replace `src/App.jsx` with `src/App.tsx` and move route-level UI orchestration into `src/components/app/AppContent.tsx`.
This separates provider/bootstrap concerns from runtime app layout logic, keeps route definitions minimal, and improves readability of the root app entry.
- Introduce `src/hooks/useProjectsState.ts` to centralize project/session/sidebar state management previously embedded in `App.jsx`.
This keeps the existing behavior for:
project loading,
Cursor session hydration,
WebSocket `loading_progress` handling,
additive-update protection for active sessions,
URL-based session selection,
sidebar refresh/delete/new-session flows.
The hook now exposes a typed `sidebarSharedProps` contract and typed handlers used by `AppContent`.
- Introduce `src/hooks/useSessionProtection.ts` for active/processing session lifecycle logic.
This preserves session-protection behavior while isolating `activeSessions`, `processingSessions`, and temporary-session replacement into a dedicated reusable hook.
- Replace monolithic `src/components/Sidebar.jsx` with typed `src/components/Sidebar.tsx` as a thin orchestrator.
`Sidebar.tsx` now focuses on wiring controller state/actions, modal visibility, collapsed mode, and version modal behavior instead of rendering every UI branch inline.
- Add `src/hooks/useSidebarController.ts` to encapsulate sidebar interaction/state logic.
This includes expand/collapse state, inline project/session editing state, project starring/sorting/filtering, lazy session pagination, delete confirmations, rename/delete actions, refresh state, and mobile touch click handling.
- Add strongly typed sidebar domain models in `src/components/sidebar/types.ts` and move sidebar-derived helpers into `src/components/sidebar/utils.ts`.
Utility coverage now includes:
session provider normalization,
session view-model creation (name/time/activity/message count),
project sorting/filtering,
task indicator status derivation,
starred-project persistence and readbacks.
- Split sidebar rendering into focused components under `src/components/sidebar/`:
`SidebarContent.tsx` for top-level sidebar layout composition.
`SidebarProjectList.tsx` for project-state branching and project iteration.
`SidebarProjectsState.tsx` for loading/empty/no-search-result placeholders.
`SidebarProjectItem.tsx` for per-project desktop/mobile header rendering and actions.
`SidebarProjectSessions.tsx` for expanded session area, skeletons, pagination, and new-session controls.
`SidebarSessionItem.tsx` for per-session desktop/mobile item rendering and session actions.
`SessionProviderIcon.tsx` for provider icon normalization.
`SidebarHeader.tsx`, `SidebarFooter.tsx`, `SidebarCollapsed.tsx`, and `SidebarModals.tsx` as dedicated typed UI surfaces.
This keeps rendering responsibilities local and significantly improves traceability.
- Convert shared UI primitives from JSX to TSX:
`src/components/ui/button.tsx`,
`src/components/ui/input.tsx`,
`src/components/ui/badge.tsx`,
`src/components/ui/scroll-area.tsx`.
These now provide typed props/variants (`forwardRef` where appropriate) while preserving existing class/behavior.
- Add shared app typings in `src/types/app.ts` for projects/sessions/websocket/loading contracts used by new hooks/components.
- Add global window declarations in `src/types/global.d.ts` for `__ROUTER_BASENAME__`, `refreshProjects`, and `openSettings`, removing implicit `any` usage for global integration points.
- Update `src/main.jsx` to import `App.tsx` and keep app bootstrap consistent with the TS migration.
- Update `src/components/QuickSettingsPanel.jsx` to self-resolve mobile state via `useDeviceSettings` (remove `isMobile` prop dependency), and update `src/components/ChatInterface.jsx` to render `QuickSettingsPanel` directly.
This reduces prop drilling and keeps quick settings colocated with chat UI concerns.
* refactor(sidebar): integrate settings modal into SidebarModals and update props
* fix(mobile): prevent menu tap from triggering unintended dashboard navigation
The mobile sidebar menu button redirects users to `cloudcli.ai/dashboard` when a
session was active. The redirect happened because
the menu was opened on `touchstart`, which mounted the sidebar before the touch
sequence completed; the follow-up tap/click then landed on the sidebar header
anchor.
This change rewrites mobile menu interaction handling in `MainContent.jsx` to
eliminate touch/click event leakage and ghost-click behavior.
Key changes:
- Added `suppressNextMenuClickRef` to guard against synthetic click events that
fire after a touch interaction.
- Added `openMobileMenu(event)` helper to centralize `preventDefault`,
`stopPropagation`, and `onMenuClick()` invocation.
- Added `handleMobileMenuTouchEnd(event)`:
- opens the menu on `touchend` instead of `touchstart`
- sets a short suppression window (350ms) for the next click.
- Added `handleMobileMenuClick(event)`:
- ignores/suppresses click events during the suppression window
- otherwise opens the menu normally.
- Updated all mobile menu button instances in `MainContent.jsx` (loading state,
no-project state, active header state) to use:
- `onTouchEnd={handleMobileMenuTouchEnd}`
- `onClick={handleMobileMenuClick}`
- Removed the previous `onTouchStart` path that caused premature DOM mutation.
Behavioral impact:
- Mobile sidebar still opens reliably with one tap.
- Tap no longer leaks to newly-mounted sidebar header links.
- Prevents accidental redirects while preserving existing menu UX.
* refactor(main-content): migrate MainContent to TypeScript and modularize UI/state boundaries
Replace the previous monolithic MainContent.jsx with a typed one and
extract focused subcomponents/hooks to improve readability, local state ownership,
and maintainability while keeping runtime behavior unchanged.
Key changes:
- Replace `src/components/MainContent.jsx` with `src/components/MainContent.tsx`.
- Add typed contracts for main-content domain in `src/components/main-content/types.ts`.
- Extract header composition into:
- `MainContentHeader.tsx`
- `MainContentTitle.tsx`
- `MainContentTabSwitcher.tsx`
- `MobileMenuButton.tsx`
- Extract loading/empty project views into `MainContentStateView.tsx`.
- Extract editor presentation into `EditorSidebar.tsx`.
- Move editor file-open + resize behavior into `useEditorSidebar.ts`.
- Move mobile menu touch/click suppression logic into `useMobileMenuHandlers.ts`.
- Extract TaskMaster-specific concerns into `TaskMasterPanel.tsx`:
- task detail modal state
- PRD editor modal state
- PRD list loading/refresh
- PRD save notification lifecycle
Behavior/compatibility notes:
- Preserve existing tab behavior, session passthrough props, and Chat/Git/File flows.
- Keep interop with existing JS components via boundary `as any` casts where needed.
- No intentional functional changes; this commit is structural/type-oriented refactor.
Validation:
- `npm run typecheck` passes.
- `npm run build` passes (existing unrelated CSS minify warnings remain).
* refactor(chat): split monolithic chat interface into typed modules and hooks
Replace the legacy monolithic ChatInterface.jsx implementation with a modular TypeScript architecture centered around a small orchestration component (ChatInterface.tsx).
Core architecture changes:
- Remove src/components/ChatInterface.jsx and add src/components/ChatInterface.tsx as a thin coordinator that wires provider state, session state, realtime WebSocket handlers, and composer behavior via dedicated hooks.
- Update src/components/MainContent.tsx to use typed ChatInterface directly (remove AnyChatInterface cast).
State ownership and hook extraction:
- Add src/hooks/chat/useChatProviderState.ts to centralize provider/model/permission-mode state, provider/session synchronization, cursor model bootstrap from backend config, and pending permission request scoping.
- Add src/hooks/chat/useChatSessionState.ts to own chat/session lifecycle state: session loading, cursor/claude/codex history loading, pagination, scroll restoration, visible-window slicing, token budget loading, persisted chat hydration, and processing-state restoration.
- Add src/hooks/chat/useChatRealtimeHandlers.ts to isolate WebSocket event processing for Claude/Cursor/Codex, including session filtering, streaming chunk buffering, session-created/pending-session transitions, permission request queueing/cancellation, completion/error handling, and session status updates.
- Add src/hooks/chat/useChatComposerState.ts to own composer-local state and interactions: input/draft persistence, textarea sizing and keyboard behavior, slash command execution, file mentions, image attachment/drop/paste workflow, submit/abort flows, permission decision responses, and transcript insertion.
UI modularization under src/components/chat:
- Add view/ChatMessagesPane.tsx for message list rendering, loading/empty states, pagination affordances, and thinking indicator.
- Add view/ChatComposer.tsx for composer shell layout and input area composition.
- Add view/ChatInputControls.tsx for mode toggles, token display, command launcher, clear-input, and scroll-to-bottom controls.
- Add view/PermissionRequestsBanner.tsx for explicit tool-permission review actions (allow once / allow & remember / deny).
- Add view/ProviderSelectionEmptyState.tsx for provider and model selection UX plus task starter integration.
- Add messages/MessageComponent.tsx and markdown/Markdown.tsx to isolate message rendering concerns, markdown/code rendering, and rich tool-output presentation.
- Add input/ImageAttachment.tsx for attachment previews/removal/progress/error overlay rendering.
Shared chat typing and utilities:
- Add src/components/chat/types.ts with shared types for providers, permission mode, message/tool payloads, pending permission requests, and ChatInterfaceProps.
- Add src/components/chat/utils/chatFormatting.ts for html decoding, code fence normalization, regex escaping, math-safe unescaping, and usage-limit text formatting.
- Add src/components/chat/utils/chatPermissions.ts for permission rule derivation, suggestion generation, and grant flow.
- Add src/components/chat/utils/chatStorage.ts for resilient localStorage access, quota handling, and normalized Claude settings retrieval.
- Add src/components/chat/utils/messageTransforms.ts for session message normalization (Claude/Codex/Cursor) and cached diff computation utilities.
Command/file input ergonomics:
- Add src/hooks/chat/useSlashCommands.ts for slash command fetching, usage-based ranking, fuzzy filtering, keyboard navigation, and command history persistence.
- Add src/hooks/chat/useFileMentions.tsx for project file flattening, @mention suggestions, mention highlighting, and keyboard/file insertion behavior.
TypeScript support additions:
- Add src/types/react-syntax-highlighter.d.ts module declarations to type-check markdown code highlighting imports.
Behavioral intent:
- Preserve existing chat behavior and provider flows while improving readability, separation of concerns, and future refactorability.
- Move state closer to the components/hooks that own it, reducing cross-cutting concerns in the top-level chat component.
* perf(project-loading): eliminate repeated Codex session rescans and duplicate cursor fetches
The staged changes remove the main source of project-load latency by avoiding repeated full scans of ~/.codex/sessions for every project and by removing redundant client-side cursor session refetches.
Server changes (server/projects.js):\n- Add a per-request Codex index reference in getProjects so Codex metadata is built once and reused across all projects, including manually added ones.\n- Introduce normalizeComparablePath() to canonicalize project paths (including Windows long-path prefixes and case-insensitive matching on Windows).\n- Introduce findCodexJsonlFiles() + buildCodexSessionsIndex() to perform a single recursive Codex scan and group sessions by normalized cwd.\n- Update getCodexSessions() to accept indexRef and read from the prebuilt index, with fallback index construction when no ref is provided.\n- Preserve existing session limiting behavior (limit=5 default, limit=0 returns all).
Client changes (src/hooks/useProjectsState.ts):\n- Remove loadCursorSessionsForProjects(), which previously triggered one extra /api/cursor/sessions request per project after /api/projects.\n- Use /api/projects response directly during initial load and refresh.\n- Expand projectsHaveChanges() to treat both cursorSessions and codexSessions as external session deltas.\n- Keep refresh comparison aligned with external session updates by using includeExternalSessions=true in sidebar refresh path.
Impact:\n- Reduces backend work from roughly O(projects * codex_session_files) to O(codex_session_files + projects) for Codex discovery during a project load cycle.\n- Removes an additional client-side O(projects) network fan-out for Cursor session fetches.\n- Improves perceived and actual sidebar project-loading time, especially in large session datasets.
* fix(chat): make Stop and Esc reliably abort active sessions
Problem
Stop requests were unreliable because aborting depended on currentSessionId being set, Esc had no actual global abort binding, stale pending session ids could be reused, and abort failures were surfaced as successful interruptions. Codex sessions also used a soft abort flag without wiring SDK cancellation.
Changes
- Add global Escape key handler in chat while a run is loading/cancellable to trigger the same abort path as the Stop button.
- Harden abort session target selection in composer by resolving from multiple active session id sources (current, pending view, pending storage, cursor storage, selected session) and ignoring temporary new-session-* ids.
- Clear stale pendingSessionId when launching a brand-new session to prevent aborting an old run.
- Update realtime abort handling to respect backend success=false responses: keep loading state when abort fails and emit an explicit failure message instead of pretending interruption succeeded.
- Improve websocket send reliability by checking socket.readyState === WebSocket.OPEN directly before send.
- Implement real Codex cancellation via AbortController + runStreamed(..., { signal }), propagate aborted status, and suppress expected abort-error noise.
Impact
This makes both UI Stop and Esc-to-stop materially more reliable across Claude/Cursor/Codex flows, especially during early-session windows before currentSessionId is finalized, and prevents false-positive interrupted states when backend cancellation fails.
Validation
- npm run -s typecheck
- npm run -s build
- node --check server/openai-codex.js
* refactor: tool components
* refactor: tool components
* fix: remove one-line logic from messagecomponent
* refactor(design): change the design of bash
* refactor(design): fix bash design and config
* refactor(design): change the design of tools and introduce todo list and task list.
* refactor(improvement):add memo on diffviewer, cleanup messsagecomponent
* refactor: update readme and remove unusedfiles.
* refactor(sidebar): remove duplicate loading message in SidebarProjectsState
* refactor(sidebar): move VersionUpgradeModal into SidebarModals
* refactor: replace individual provider logos with a unified SessionProviderLogo component
* fix(commands): restore /cost slash command and improve command execution errors
The /cost command was listed as built-in but had no handler, causing execution to
fall through to custom command logic and return 400 ("command path is required").
- Add a built-in /cost handler in server/routes/commands.js
- Return the expected payload shape for the chat UI (`action: "cost"`, token usage,
estimated cost, model)
- Normalize token usage inputs and compute usage percentage
- Add provider-based default pricing for cost estimation
- Fix model selection in command execution context so codex uses `codexModel`
instead of `claudeModel`
- Improve frontend command error handling by parsing backend error responses and
showing meaningful error messages instead of a generic failure
* fix(command-menu): correct slash command selection with frequent commands
When the “Frequently Used” section is visible, command clicks/hover could use a
UI-local index instead of the canonical `filteredCommands` index, causing the
wrong command to execute (e.g. clicking `/help` running `/clear`).
- map rendered menu items back to canonical command indices using a stable key
(`name + namespace/type + path`)
- use canonical index for hover/click selection callbacks
- deduplicate frequent commands from other grouped sections to avoid duplicate
rows and selection ambiguity
- keep and restore original inline comments, with clarifications where needed
* refactor(sidebar): update sessionMeta handling for session loading logic
- This fixes an issue where the sidebar was showing 6+ even when there were only 5 sessions, due to the hasMore logic not accounting for the case where there are exactly 6 sessions.
It was also showing "Show more sessions" even where there were no more sessions to load.
- This was because `hasMore` was sometimes `undefined` and the logic checked for hasMore !== false, which treated undefined as true.
Now we explicitly check for hasMore === true to determine if there are more sessions to load.
* refactor(project-watcher): add codex and cursor file watchers
* fix: chat session scroll to bottom error even when scrolled up
* fix(chat): clear stuck loading state across realtime lifecycle events
The chat UI could remain in a stale "Thinking/Processing" state when session IDs
did not line up exactly between view state (`currentSessionId`), selected route
session, pending session IDs, and provider lifecycle events. This was most visible
with Codex completion/abort flows, but the same mismatch risk existed in shared
handlers.
Unify lifecycle cleanup behavior in realtime handlers and make processing tracking
key off the active viewed session identity.
Changes:
- src/hooks/chat/useChatRealtimeHandlers.ts
- src/components/ChatInterface.tsx
- src/hooks/chat/useChatSessionState.ts
What changed:
- Added shared helpers in realtime handling:
- `collectSessionIds(...)` to normalize and dedupe candidate session IDs.
- `clearLoadingIndicators()` to consistently clear `isLoading`, abort UI, and status.
- `markSessionsAsCompleted(...)` to consistently notify inactive/not-processing state.
- Updated lifecycle branches to use shared cleanup logic:
- `cursor-result`
- `claude-complete`
- `codex-response` (`turn_complete` and `turn_failed`)
- `codex-complete`
- `session-aborted`
- Expanded completion/abort cleanup to include all relevant session IDs
(`latestMessage.sessionId`, `currentSessionId`, `selectedSession?.id`,
`pendingSessionId`, and Codex `actualSessionId` when present).
- Switched processing-session marking in `ChatInterface` to use
`selectedSession?.id || currentSessionId` instead of `currentSessionId` alone.
- Switched processing-session rehydration in `useChatSessionState` to use
the same active-view session identity fallback.
Result:
- Prevents stale loading indicators after completion/abort when IDs differ.
- Keeps processing session bookkeeping aligned with the currently viewed session.
- Reduces provider-specific drift by using one lifecycle cleanup pattern.
* fix(chat): stabilize long-history scroll-up pagination behavior
- fix top-pagination lockups by only locking when older messages are actually fetched
- make fetched older messages visible immediately by increasing `visibleMessageCount` on prepend
- prevent unintended auto-scroll-to-bottom during older-message loading and scroll restore
- replace state-based pagination offset with a ref to avoid stale offset/reload side effects
- ensure initial auto-scroll runs only after initial session load completes
- reset top-load lock/restore state and visible window when switching sessions
- loosen top-lock release near the top to avoid requiring a full down/up cycle
* refactor: Restructure files and folders to better mimic feature-based architecture
* refactor: reorganize chat view components and types
* feat(chat): move thinking modes, token usage pie, and related logic into chat folder
* refactor(tools): add agent category for Task tool
Add visual distinction for the Task tool (subagent invocation) by
introducing a new 'agent' category with purple border styling. This
separates subagent tasks from regular task management tools
(TaskCreate, TaskUpdate, etc.) for clearer user feedback.
Also refactor terminal command layout in OneLineDisplay to properly
nest flex containers, fixing copy button alignment issues.
* refactor(tools): improve Task tool display formatting
Update Task tool config to show cleaner subagent information in the UI.
Simplifies the input display by showing only the prompt when no
optional fields are present, reducing visual clutter. Updates title
format to "Subagent / {type}" for better categorization. Enhances
result display to better handle complex agent response structures with
array content types, extracting text blocks for cleaner presentation.
* fix: show auth url panel in shell only on mobile
- use static url: https://auth.openai.com/codex/device, for codex login.
- add an option for hiding the panel
* fix(chat): escape command name in regex to prevent unintended matches
* fix(chat): handle JSON parsing errors for saved chat messages
* refactor(chat): replace localStorage provider retrieval with prop usage in MessageComponent
* fix(chat): handle potential null content in message before splitting lines
* refactor(todo): update TodoListContentProps to include optional id and priority fields that are used in TodoList.jsx
* fix(watcher): ensure provider folders exist before creating watchers to maintain active watching
* refactor(chat): improve message handling by cloning state updates and improving structured message parsing
* refactor(chat): exclude currentSessionId from dependency array to prevent unnecessary reloading of messages
* refactor(useFileMentions): implement abort controller for fetch requests
* refactor(MessageComponent): add types
* refactor(calculateDiff): optimize LCS algorithm for improved diff calculation
* refactor(createCachedDiffCalculator): use both newStr and oldStr as cache keys
* refactor(useSidebarController): manage project session overrides in local state
* refactor(ScrollArea): adjust ref placement and className order
* fix: type annotations
* refactor(ChatInputControls): update import statement for ThinkingModeSelector
* refactor(dateUtils): update type annotation for formatTimeAgo function
* refactor(ToolRenderer): ensure stable hook order
* refactor(useProjectsState): normalize refreshed session metadata to maintain provider stability; use getProjectSessions helper for session retrieval.
* refactor(useChatComposerState): improve input handling and command execution flow
* refactor(useChatRealtimeHandlers): normalize interactive prompt content to string for consistent ChatMessage shape
* refactor(OneLineDisplay): improve clipboard functionality with fallback for unsupported environments
* refactor(QuickSettingsPanel): simplify state management by removing localIsOpen and using isOpen directly
* refactor(ChatMessagesPane): use stable message key
* refactor:: move AssistantThinkingIndicator component to its own file
* refactor(ChatMessagesPane): extract message key generation logic to a utility function
* refactor(SidebarModals): move normalizeProjectForSettings into utils file
* refactor(ToolConfigs): use optional chaining for content retrieval
* fix(chat): stabilize provider/message handling and complete chat i18n coverage
Unify provider typing, harden realtime message effects, normalize tool input
serialization, and finish i18n/a11y updates across chat UI components.
- tighten provider contracts from `Provider | string` to `SessionProvider` in:
- `useChatProviderState`
- `useChatComposerState`
- `useChatRealtimeHandlers`
- `ChatMessagesPane`
- `ProviderSelectionEmptyState`
- refactor `AssistantThinkingIndicator` to accept `selectedProvider` via props
instead of reading provider from local storage during render
- fix stale-closure risk in `useChatRealtimeHandlers` by:
- adding missing effect dependencies
- introducing `lastProcessedMessageRef` to prevent duplicate processing when
dependencies change without a new message object
- standardize `toolInput` shape in `messageTransforms`:
- add `normalizeToolInput(...)`
- ensure all conversion paths produce consistent string output
- remove mixed `null`/raw/stringified variants across cursor/session branches
- harden tool display fallback in `CollapsibleDisplay`:
- default border class now falls back safely for unknown categories
- improve chat i18n consistency:
- localize hardcoded strings in `MessageComponent`
(`permissions.*`, `interactive.*`, `thinking.emoji`, `json.response`,
`messageTypes.error`)
- localize button titles in `ChatInputControls`
(`input.clearInput`, `input.scrollToBottom`)
- localize provider-specific empty-project prompt in `ChatInterface`
(`projectSelection.startChatWithProvider`)
- localize repeated “Start the next task” prompt in
`ProviderSelectionEmptyState` (`tasks.nextTaskPrompt`)
- add missing translation keys in all supported chat locales:
- `src/i18n/locales/en/chat.json`
- `src/i18n/locales/ko/chat.json`
- `src/i18n/locales/zh-CN/chat.json`
- new keys:
- `input.clearInput`
- `input.scrollToBottom`
- `projectSelection.startChatWithProvider`
- `tasks.nextTaskPrompt`
- improve attachment remove-button accessibility in `ImageAttachment`:
- add `type="button"` and `aria-label`
- make control visible on touch/small screens and focusable states
- preserve hover behavior on larger screens
Validation:
- `npm run typecheck`
* fix(chat): sync quick settings state and stabilize thinking toggle
Synchronize useUiPreferences instances via custom sync events and storage listeners so Quick Settings updates apply across UI consumers immediately.
Also hide standalone thinking messages when showThinking is disabled, while preserving hook order to avoid Rendered fewer hooks runtime errors.
* refactor(validateGitRepository): improve directory validation for git work tree
* refactor(GitPanel): clear stale state on project change and improve error handling
* refactor(git): use spawnAsync for command execution and improve commit log retrieval
* fix: iOS pwa bottom margin
* fix: pass diff information to code editor
* refactor(sidebar): remove touch event handlers from project and session items
* bumping node to v22
* Release 1.17.0
---------
Co-authored-by: Haileyesus <something@gmail.com>
Co-authored-by: simosmik <simosmik@gmail.com>
371 lines
12 KiB
Markdown
371 lines
12 KiB
Markdown
<div align="center">
|
|
<img src="public/logo.svg" alt="Claude Code UI" width="64" height="64">
|
|
<h1>Cloud CLI (又名 Claude Code UI)</h1>
|
|
</div>
|
|
|
|
|
|
[Claude Code](https://docs.anthropic.com/en/docs/claude-code)、[Cursor CLI](https://docs.cursor.com/en/cli/overview) 和 [Codex](https://developers.openai.com/codex) 的桌面端和移动端界面。您可以在本地或远程使用它来查看 Claude Code、Cursor 或 Codex 中的活跃项目和会话,并从任何地方(移动端或桌面端)对它们进行修改。这为您提供了一个在任何地方都能正常使用的合适界面。
|
|
|
|
[English](./README.md) | [中文](./README.zh-CN.md)
|
|
|
|
## 截图
|
|
|
|
<div align="center">
|
|
|
|
<table>
|
|
<tr>
|
|
<td align="center">
|
|
<h3>桌面视图</h3>
|
|
<img src="public/screenshots/desktop-main.png" alt="Desktop Interface" width="400">
|
|
<br>
|
|
<em>显示项目概览和聊天界面的主界面</em>
|
|
</td>
|
|
<td align="center">
|
|
<h3>移动端体验</h3>
|
|
<img src="public/screenshots/mobile-chat.png" alt="Mobile Interface" width="250">
|
|
<br>
|
|
<em>具有触摸导航的响应式移动设计</em>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="center" colspan="2">
|
|
<h3>CLI 选择</h3>
|
|
<img src="public/screenshots/cli-selection.png" alt="CLI Selection" width="400">
|
|
<br>
|
|
<em>在 Claude Code、Cursor CLI 和 Codex 之间选择</em>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
## 功能特性
|
|
|
|
- **响应式设计** - 在桌面、平板和移动设备上无缝运行,您也可以在移动端使用 Claude Code、Cursor 或 Codex
|
|
- **交互式聊天界面** - 内置聊天界面,与 Claude Code、Cursor 或 Codex 无缝通信
|
|
- **集成 Shell 终端** - 通过内置 shell 功能直接访问 Claude Code、Cursor CLI 或 Codex
|
|
- **文件浏览器** - 交互式文件树,支持语法高亮和实时编辑
|
|
- **Git 浏览器** - 查看、暂存和提交您的更改。您还可以切换分支
|
|
- **会话管理** - 恢复对话、管理多个会话并跟踪历史记录
|
|
- **TaskMaster AI 集成** *(可选)* - 通过 AI 驱动的任务规划、PRD 解析和工作流自动化实现高级项目管理
|
|
- **模型兼容性** - 适用于 Claude Sonnet 4.5、Opus 4.5 和 GPT-5.2
|
|
|
|
|
|
## 快速开始
|
|
|
|
### 前置要求
|
|
|
|
- [Node.js](https://nodejs.org/) v22 或更高版本
|
|
- 已安装并配置 [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code),和/或
|
|
- 已安装并配置 [Cursor CLI](https://docs.cursor.com/en/cli/overview),和/或
|
|
- 已安装并配置 [Codex](https://developers.openai.com/codex)
|
|
|
|
### 一键操作(推荐)
|
|
|
|
无需安装,直接运行:
|
|
|
|
```bash
|
|
npx @siteboon/claude-code-ui
|
|
```
|
|
|
|
服务器将启动并可通过 `http://localhost:3001`(或您配置的 PORT)访问。
|
|
|
|
**重启**: 停止服务器后只需再次运行相同的 `npx` 命令
|
|
|
|
### 全局安装(供常规使用)
|
|
|
|
为了频繁使用,一次性全局安装:
|
|
|
|
```bash
|
|
npm install -g @siteboon/claude-code-ui
|
|
```
|
|
|
|
然后使用简单命令启动:
|
|
|
|
```bash
|
|
claude-code-ui
|
|
```
|
|
|
|
|
|
**重启**: 使用 Ctrl+C 停止,然后再次运行 `claude-code-ui`。
|
|
|
|
**更新**:
|
|
```bash
|
|
cloudcli update
|
|
```
|
|
|
|
### CLI 使用方法
|
|
|
|
全局安装后,您可以访问 `claude-code-ui` 和 `cloudcli` 命令:
|
|
|
|
| 命令 / 选项 | 简写 | 描述 |
|
|
|------------------|-------|-------------|
|
|
| `cloudcli` 或 `claude-code-ui` | | 启动服务器(默认) |
|
|
| `cloudcli start` | | 显式启动服务器 |
|
|
| `cloudcli status` | | 显示配置和数据位置 |
|
|
| `cloudcli update` | | 更新到最新版本 |
|
|
| `cloudcli help` | | 显示帮助信息 |
|
|
| `cloudcli version` | | 显示版本信息 |
|
|
| `--port <port>` | `-p` | 设置服务器端口(默认: 3001) |
|
|
| `--database-path <path>` | | 设置自定义数据库位置 |
|
|
|
|
**示例:**
|
|
```bash
|
|
cloudcli # 使用默认设置启动
|
|
cloudcli -p 8080 # 在自定义端口启动
|
|
cloudcli status # 显示当前配置
|
|
```
|
|
|
|
### 作为后台服务运行(推荐用于生产环境)
|
|
|
|
在生产环境中,使用 PM2(Process Manager 2)将 Claude Code UI 作为后台服务运行:
|
|
|
|
#### 安装 PM2
|
|
|
|
```bash
|
|
npm install -g pm2
|
|
```
|
|
|
|
#### 作为后台服务启动
|
|
|
|
```bash
|
|
# 在后台启动服务器
|
|
pm2 start claude-code-ui --name "claude-code-ui"
|
|
|
|
# 或使用更短的别名
|
|
pm2 start cloudcli --name "claude-code-ui"
|
|
|
|
# 在自定义端口启动
|
|
pm2 start cloudcli --name "claude-code-ui" -- --port 8080
|
|
```
|
|
|
|
|
|
#### 系统启动时自动启动
|
|
|
|
要使 Claude Code UI 在系统启动时自动启动:
|
|
|
|
```bash
|
|
# 为您的平台生成启动脚本
|
|
pm2 startup
|
|
|
|
# 保存当前进程列表
|
|
pm2 save
|
|
```
|
|
|
|
|
|
### 本地开发安装
|
|
|
|
1. **克隆仓库:**
|
|
```bash
|
|
git clone https://github.com/siteboon/claudecodeui.git
|
|
cd claudecodeui
|
|
```
|
|
|
|
2. **安装依赖:**
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
3. **配置环境:**
|
|
```bash
|
|
cp .env.example .env
|
|
# 使用您喜欢的设置编辑 .env
|
|
```
|
|
|
|
4. **启动应用程序:**
|
|
```bash
|
|
# 开发模式(支持热重载)
|
|
npm run dev
|
|
|
|
```
|
|
应用程序将在您在 .env 中指定的端口启动
|
|
|
|
5. **打开浏览器:**
|
|
- 开发环境: `http://localhost:3001`
|
|
|
|
## 安全与工具配置
|
|
|
|
**🔒 重要提示**: 所有 Claude Code 工具**默认禁用**。这可以防止潜在的有害操作自动运行。
|
|
|
|
### 启用工具
|
|
|
|
要使用 Claude Code 的完整功能,您需要手动启用工具:
|
|
|
|
1. **打开工具设置** - 点击侧边栏中的齿轮图标
|
|
3. **选择性启用** - 仅打开您需要的工具
|
|
4. **应用设置** - 您的偏好设置将保存在本地
|
|
|
|
<div align="center">
|
|
|
|

|
|
*工具设置界面 - 仅启用您需要的内容*
|
|
|
|
</div>
|
|
|
|
**推荐方法**: 首先启用基本工具,然后根据需要添加更多。您可以随时调整这些设置。
|
|
|
|
## TaskMaster AI 集成 *(可选)*
|
|
|
|
Claude Code UI 支持 **[TaskMaster AI](https://github.com/eyaltoledano/claude-task-master)**(aka claude-task-master)集成,用于高级项目管理和 AI 驱动的任务规划。
|
|
|
|
它提供
|
|
- 从 PRD(产品需求文档)生成 AI 驱动的任务
|
|
- 智能任务分解和依赖管理
|
|
- 可视化任务板和进度跟踪
|
|
|
|
**设置与文档**: 访问 [TaskMaster AI GitHub 仓库](https://github.com/eyaltoledano/claude-task-master)获取安装说明、配置指南和使用示例。
|
|
安装后,您应该能够从设置中启用它
|
|
|
|
|
|
## 使用指南
|
|
|
|
### 核心功能
|
|
|
|
#### 项目管理
|
|
当可用时,它会自动发现 Claude Code、Cursor 或 Codex 会话并将它们分组到项目中
|
|
- **项目操作** - 重命名、删除和组织项目
|
|
- **智能导航** - 快速访问最近的项目和会话
|
|
- **MCP 支持** - 通过 UI 添加您自己的 MCP 服务器
|
|
|
|
#### 聊天界面
|
|
- **使用响应式聊天或 Claude Code/Cursor CLI/Codex CLI** - 您可以使用自适应聊天界面或使用 shell 按钮连接到您选择的 CLI
|
|
- **实时通信** - 通过 WebSocket 连接从您选择的 CLI(Claude Code/Cursor/Codex)流式传输响应
|
|
- **会话管理** - 恢复之前的对话或启动新会话
|
|
- **消息历史** - 带有时间戳和元数据的完整对话历史
|
|
- **多格式支持** - 文本、代码块和文件引用
|
|
|
|
#### 文件浏览器与编辑器
|
|
- **交互式文件树** - 使用展开/折叠导航浏览项目结构
|
|
- **实时文件编辑** - 直接在界面中读取、修改和保存文件
|
|
- **语法高亮** - 支持多种编程语言
|
|
- **文件操作** - 创建、重命名、删除文件和目录
|
|
|
|
#### Git 浏览器
|
|
|
|
|
|
#### TaskMaster AI 集成 *(可选)*
|
|
- **可视化任务板** - 用于管理开发任务的看板风格界面
|
|
- **PRD 解析器** - 创建产品需求文档并将其解析为结构化任务
|
|
- **进度跟踪** - 实时状态更新和完成跟踪
|
|
|
|
#### 会话管理
|
|
- **会话持久化** - 所有对话自动保存
|
|
- **会话组织** - 按项目和 timestamp 分组会话
|
|
- **会话操作** - 重命名、删除和导出对话历史
|
|
- **跨设备同步** - 从任何设备访问会话
|
|
|
|
### 移动应用
|
|
- **响应式设计** - 针对所有屏幕尺寸进行优化
|
|
- **触摸友好界面** - 滑动手势和触摸导航
|
|
- **移动导航** - 底部选项卡栏,方便拇指导航
|
|
- **自适应布局** - 可折叠侧边栏和智能内容优先级
|
|
- **添加到主屏幕快捷方式** - 添加快捷方式到主屏幕,应用程序将像 PWA 一样运行
|
|
|
|
## 架构
|
|
|
|
### 系统概览
|
|
|
|
```
|
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
│ Frontend │ │ Backend │ │ Agent │
|
|
│ (React/Vite) │◄──►│ (Express/WS) │◄──►│ Integration │
|
|
│ │ │ │ │ │
|
|
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
```
|
|
|
|
### 后端 (Node.js + Express)
|
|
- **Express 服务器** - 具有静态文件服务的 RESTful API
|
|
- **WebSocket 服务器** - 用于聊天和项目刷新的通信
|
|
- **Agent 集成 (Claude Code / Cursor CLI / Codex)** - 进程生成和管理
|
|
- **文件系统 API** - 为项目公开文件浏览器
|
|
|
|
### 前端 (React + Vite)
|
|
- **React 18** - 带有 hooks 的现代组件架构
|
|
- **CodeMirror** - 具有语法高亮的高级代码编辑器
|
|
|
|
|
|
|
|
|
|
### 贡献
|
|
|
|
我们欢迎贡献!请遵循以下指南:
|
|
|
|
#### 入门
|
|
1. **Fork** 仓库
|
|
2. **克隆** 您的 fork: `git clone <your-fork-url>`
|
|
3. **安装** 依赖: `npm install`
|
|
4. **创建** 特性分支: `git checkout -b feature/amazing-feature`
|
|
|
|
#### 开发流程
|
|
1. **进行更改**,遵循现有代码风格
|
|
2. **彻底测试** - 确保所有功能正常工作
|
|
3. **运行质量检查**: `npm run lint && npm run format`
|
|
4. **提交**,遵循 [Conventional Commits](https://conventionalcommits.org/)的描述性消息
|
|
5. **推送** 到您的分支: `git push origin feature/amazing-feature`
|
|
6. **提交** 拉取请求,包括:
|
|
- 更改的清晰描述
|
|
- UI 更改的截图
|
|
- 适用时的测试结果
|
|
|
|
#### 贡献内容
|
|
- **错误修复** - 帮助我们提高稳定性
|
|
- **新功能** - 增强功能(先在 issue 中讨论)
|
|
- **文档** - 改进指南和 API 文档
|
|
- **UI/UX 改进** - 更好的用户体验
|
|
- **性能优化** - 让它更快
|
|
|
|
## 故障排除
|
|
|
|
### 常见问题与解决方案
|
|
|
|
|
|
#### "未找到 Claude 项目"
|
|
**问题**: UI 显示没有项目或项目列表为空
|
|
**解决方案**:
|
|
- 确保已正确安装 [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
|
|
- 至少在一个项目目录中运行 `claude` 命令以进行初始化
|
|
- 验证 `~/.claude/projects/` 目录存在并具有适当的权限
|
|
|
|
#### 文件浏览器问题
|
|
**问题**: 文件无法加载、权限错误、空目录
|
|
**解决方案**:
|
|
- 检查项目目录权限(在终端中使用 `ls -la`)
|
|
- 验证项目路径存在且可访问
|
|
- 查看服务器控制台日志以获取详细错误消息
|
|
- 确保您未尝试访问项目范围之外的系统目录
|
|
|
|
|
|
## 许可证
|
|
|
|
GNU General Public License v3.0 - 详见 [LICENSE](LICENSE) 文件。
|
|
|
|
本项目是开源的,在 GPL v3 许可下可自由使用、修改和分发。
|
|
|
|
## 致谢
|
|
|
|
### 构建工具
|
|
- **[Claude Code](https://docs.anthropic.com/en/docs/claude-code)** - Anthropic 的官方 CLI
|
|
- **[Cursor CLI](https://docs.cursor.com/en/cli/overview)** - Cursor 的官方 CLI
|
|
- **[Codex](https://developers.openai.com/codex)** - OpenAI Codex
|
|
- **[React](https://react.dev/)** - 用户界面库
|
|
- **[Vite](https://vitejs.dev/)** - 快速构建工具和开发服务器
|
|
- **[Tailwind CSS](https://tailwindcss.com/)** - 实用优先的 CSS 框架
|
|
- **[CodeMirror](https://codemirror.net/)** - 高级代码编辑器
|
|
- **[TaskMaster AI](https://github.com/eyaltoledano/claude-task-master)** *(可选)* - AI 驱动的项目管理和任务规划
|
|
|
|
## 支持与社区
|
|
|
|
### 保持更新
|
|
- **Star** 此仓库以表示支持
|
|
- **Watch** 以获取更新和新版本
|
|
- **Follow** 项目以获取公告
|
|
|
|
### 赞助商
|
|
- [Siteboon - AI powered website builder](https://siteboon.ai)
|
|
---
|
|
|
|
<div align="center">
|
|
<strong>为 Claude Code、Cursor 和 Codex 社区精心打造。</strong>
|
|
</div> |