diff --git a/README.md b/README.md index b453f028..40879539 100644 --- a/README.md +++ b/README.md @@ -13,30 +13,30 @@ Run Claude Code / Codex / Gemini sessions locally and control them remotely thro - Track session progress with todo lists. - Supports multiple AI backends: Claude Code, Codex, and Gemini. -## Quickstart (single executable) +## Quickstart -1. Download the prebuilt `hapi` binary for your platform and put it on your PATH. - -2. Start the server on a machine you control: +1. Start the server on a machine you control: ```bash -hapi server +npx @twsxtd/hapi server ``` -3. If the server has no public IP, expose it over HTTPS: +> Alternatively, download the prebuilt binary from [Releases](https://github.com/tiann/hapi/releases) and run `hapi server`. + +2. If the server has no public IP, expose it over HTTPS: - Cloudflare Tunnel: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/ - Tailscale: https://tailscale.com/kb/ -4. Run the CLI on the machine where you want sessions: +3. Run the CLI on the machine where you want sessions: ```bash # If the server is not on localhost:3006 export HAPI_BOT_URL="https://your-domain.example" -hapi +npx @twsxtd/hapi ``` -5. Open the UI in a browser at the server URL and log in with `CLI_API_TOKEN`. +4. Open the UI in a browser at the server URL and log in with `CLI_API_TOKEN`. ## Telegram Mini App (optional) @@ -65,9 +65,9 @@ ALLOWED_CHAT_IDS="12345678" ## Multi-agent support -- `hapi` - Start a Claude Code session. -- `hapi codex` - Start an OpenAI Codex session. -- `hapi gemini` - Start a Google Gemini session. +- `npx @twsxtd/hapi` - Start a Claude Code session. +- `npx @twsxtd/hapi codex` - Start an OpenAI Codex session. +- `npx @twsxtd/hapi gemini` - Start a Google Gemini session. ## CLI config file diff --git a/spinner.md b/spinner.md deleted file mode 100644 index 9de8afc3..00000000 --- a/spinner.md +++ /dev/null @@ -1,131 +0,0 @@ -# Loading 元素精简优化计划 - -## 一、当前 Loading 元素汇总 - -| 位置 | 文件 | 当前样式 | 展示时机 | -|------|------|----------|----------| -| 同步横幅 | `SyncingBanner.tsx` | 顶部固定横幅 + 旋转符号 | `isSyncing && isOnline` | -| 权限按钮 | `PermissionFooter.tsx:66-73` | SVG SpinnerIcon | `loading` 状态 | -| 认证加载 | `App.tsx:132-146` | 纯文本 "Loading…" / "Authorizing…" | `isAuthSourceLoading` / `isAuthLoading` | -| 会话加载 | `router.tsx:100-106` | 纯文本 "Loading session…" | `!session` | -| 消息加载 | `HappyThread.tsx:235-258` | 纯文本 "Loading..." + 按钮文本 | `isLoadingMessages` / `isLoadingMoreMessages` | -| Git 状态 | `files.tsx:313-318` | 纯文本 "Loading Git status..." / "Loading files..." | `gitLoading` / `searchResults.isLoading` | -| 文件内容 | `file.tsx:231-232` | 纯文本 "Loading file..." | `diffQuery.isLoading \|\| fileQuery.isLoading` | -| 登录按钮 | `LoginPrompt.tsx:77` | 按钮文本 "Signing in..." | `isLoading` | -| 创建会话 | `NewSession.tsx:119-122, 216` | "Loading machines..." / "Creating..." | `isPending` | -| 问卷提交 | `AskUserQuestionFooter.tsx:385` | 按钮文本 "Submitting…" | `loading` | - -## 二、问题 - -1. **样式不统一** - 纯文本 vs SpinnerIcon vs 旋转符号 -2. **SpinnerIcon 无法复用** - 定义在 PermissionFooter 内部 -3. **省略号不一致** - "..." vs "…" - -## 三、精简方案 - -**核心原则:Spinner 做基础元件,LoadingState 负责语义化加载** - -### 创建唯一的 Spinner 组件(可访问性就绪) - -```tsx -// web/src/components/Spinner.tsx -export function Spinner({ - size = 'md', - className, - label = 'Loading', -}: { - size?: 'sm' | 'md' | 'lg' - className?: string - label?: string -}) { - const sizeClasses = { sm: 'h-4 w-4', md: 'h-5 w-5', lg: 'h-6 w-6' } - return ( - - ) -} -``` - -### 新增 LoadingState(Spinner + 可选文案) - -```tsx -// web/src/components/LoadingState.tsx -export function LoadingState({ - label = 'Loading…', - className, - spinnerSize = 'md', -}: { - label?: string - className?: string - spinnerSize?: 'sm' | 'md' | 'lg' -}) { - return ( -