mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
Consolidate CLI and server runtime directories from ~/.config/hapi/ (CLI) and ~/.hapi-server/ (Server) to a single ~/.hapi/ directory. Unify environment variables from HAPI_HOME_DIR (CLI) and HAPI_BOT_DATA_DIR (Server) to a single HAPI_HOME variable across both applications. Update all documentation and configuration references accordingly. Bump bun-types to 1.3.5.
224 lines
8.1 KiB
Markdown
224 lines
8.1 KiB
Markdown
# HAPI CLI Codebase Overview
|
|
|
|
## Project Overview
|
|
|
|
HAPI CLI (`hapi`) is a command-line tool that wraps Claude Code to enable remote control and session sharing via `hapi-server` (Telegram Bot + Mini App). It's part of a two-component system:
|
|
|
|
1. **hapi** (this project) - CLI wrapper for Claude Code
|
|
2. **hapi-server** - Public server (Socket.IO + REST + SQLite) + Telegram Mini App
|
|
|
|
## Code Style Preferences
|
|
|
|
### TypeScript Conventions
|
|
- **Strict typing**: No untyped code ("I despise untyped code")
|
|
- **Clean function signatures**: Explicit parameter and return types
|
|
- **As little as possible classes**
|
|
- **Comprehensive JSDoc comments**: Each file includes header comments explaining responsibilities.
|
|
- **Import style**: Uses `@/` alias for src imports, e.g., `import { logger } from '@/ui/logger'`
|
|
- **File extensions**: Uses `.ts` for TypeScript files
|
|
- **Export style**: Named exports preferred, with occasional default exports for main functions
|
|
|
|
### DO NOT
|
|
|
|
- Create stupid small functions / getters / setters
|
|
- Excessive use of `if` statements - especially if you can avoid control flow changes with a better design
|
|
- **NEVER import modules mid-code** - ALL imports must be at the top of the file
|
|
|
|
### Error Handling
|
|
- Graceful error handling with proper error messages
|
|
- Use of `try-catch` blocks with specific error logging
|
|
- Abort controllers for cancellable operations
|
|
- Careful handling of process lifecycle and cleanup
|
|
|
|
### Testing
|
|
- Unit tests using Vitest
|
|
- No mocking - tests make real API calls
|
|
- Test files colocated with source files (`.test.ts`)
|
|
- Descriptive test names and proper async handling
|
|
|
|
### Logging
|
|
- All debugging through file logs to avoid disturbing Claude sessions
|
|
- Console output only for user-facing messages
|
|
- Special handling for large JSON objects with truncation
|
|
|
|
## Architecture & Key Components
|
|
|
|
### 1. API Module (`/src/api/`)
|
|
Handles bot communication (direct connect; no end-to-end encryption).
|
|
|
|
- **`api.ts`**: Main API client class for session management
|
|
- **`apiSession.ts`**: WebSocket-based real-time session client with RPC support
|
|
- **`auth.ts`**: Loads `CLI_API_TOKEN` from env
|
|
- **`encryption.ts`**: Base64 helpers (no encryption)
|
|
- **`types.ts`**: Zod schemas for type-safe API communication
|
|
|
|
**Key Features:**
|
|
- Socket.IO for real-time messaging
|
|
- Optimistic concurrency control for state updates
|
|
- RPC handler registration for remote procedure calls
|
|
|
|
### 2. Claude Integration (`/src/claude/`)
|
|
Core Claude Code integration layer.
|
|
|
|
- **`loop.ts`**: Main control loop managing interactive/remote modes
|
|
- **`types.ts`**: Claude message type definitions with parsers
|
|
|
|
- **`claudeSdk.ts`**: Direct SDK integration using `@anthropic-ai/claude-code`
|
|
- **`interactive.ts`**: **LIKELY WILL BE DEPRECATED in favor of running through SDK** PTY-based interactive Claude sessions
|
|
- **`watcher.ts`**: File system watcher for Claude session files (for interactive mode snooping)
|
|
|
|
- **`mcp/startPermissionServer.ts`**: MCP (Model Context Protocol) permission server
|
|
|
|
**Key Features:**
|
|
- Dual mode operation: interactive (terminal) and remote (mobile control)
|
|
- Session persistence and resumption
|
|
- Real-time message streaming
|
|
- Permission intercepting via MCP [Permission checking not implemented yet]
|
|
|
|
### 3. UI Module (`/src/ui/`)
|
|
User interface components.
|
|
|
|
- **`logger.ts`**: Centralized logging system with file output
|
|
- **`qrcode.ts`**: QR code generation for mobile authentication
|
|
- **`start.ts`**: Main application startup and orchestration
|
|
|
|
**Key Features:**
|
|
- Clean console UI with chalk styling
|
|
- QR code display for easy mobile connection
|
|
- Graceful mode switching between interactive and remote
|
|
|
|
### 4. Core Files
|
|
|
|
- **`index.ts`**: CLI entry point with argument parsing
|
|
- **`persistence.ts`**: Local storage for settings and keys
|
|
- **`utils/time.ts`**: Exponential backoff utilities
|
|
|
|
## Data Flow
|
|
|
|
1. **Authentication**:
|
|
- Use `CLI_API_TOKEN` to authenticate to `hapi-server` (REST + Socket.IO)
|
|
|
|
2. **Session Creation**:
|
|
- Create/load session via `POST /cli/sessions` → Establish Socket.IO `/cli` connection
|
|
|
|
3. **Message Flow**:
|
|
- Local mode: terminal/SDK → hapi CLI → hapi-server → Telegram Mini App
|
|
|
|
4. **Permission Handling**:
|
|
- Claude requests permission → hapi CLI exposes RPC handlers → Mini App calls REST → hapi-server relays RPC to hapi CLI
|
|
|
|
## Key Design Decisions
|
|
|
|
1. **File-based logging**: Prevents interference with Claude's terminal UI
|
|
2. **Dual Claude integration**: Process spawning for interactive, SDK for remote
|
|
3. **No E2E encryption**: Use HTTPS/TLS for `hapi-server` deployments
|
|
4. **Session persistence**: Allows resuming sessions across restarts
|
|
5. **Optimistic concurrency**: Handles distributed state updates gracefully
|
|
|
|
## Security Considerations
|
|
|
|
- `CLI_API_TOKEN` is a shared secret; treat it like a password.
|
|
- No end-to-end encryption: use HTTPS/TLS for `hapi-server` deployments.
|
|
- Session isolation through unique session IDs.
|
|
|
|
## Dependencies
|
|
|
|
- Core: Node.js, TypeScript
|
|
- Claude: `@anthropic-ai/claude-code` SDK
|
|
- Networking: Socket.IO client, Axios
|
|
- Terminal: node-pty, chalk, qrcode-terminal
|
|
- Validation: Zod
|
|
- Testing: Vitest
|
|
|
|
|
|
# Running the Daemon
|
|
|
|
## Starting the Daemon
|
|
```bash
|
|
# From the hapi CLI directory:
|
|
hapi daemon start
|
|
|
|
# With custom bot URL (for local development):
|
|
HAPI_BOT_URL=http://localhost:3006 CLI_API_TOKEN=your_token hapi daemon start
|
|
|
|
# Stop the daemon:
|
|
hapi daemon stop
|
|
|
|
# Check daemon status:
|
|
hapi daemon status
|
|
```
|
|
|
|
## Daemon Logs
|
|
- Daemon logs are stored in `~/.hapi/logs/` (or `$HAPI_HOME/logs/`)
|
|
- Named with format: `YYYY-MM-DD-HH-MM-SS-daemon.log`
|
|
|
|
# Session Forking `claude` and sdk behavior
|
|
|
|
## Commands Run
|
|
|
|
### Initial Session
|
|
```bash
|
|
claude --print --output-format stream-json --verbose 'list files in this directory'
|
|
```
|
|
- Original Session ID: `aada10c6-9299-4c45-abc4-91db9c0f935d`
|
|
- Created file: `~/.claude/projects/.../aada10c6-9299-4c45-abc4-91db9c0f935d.jsonl`
|
|
|
|
### Resume with --resume flag
|
|
```bash
|
|
claude --print --output-format stream-json --verbose --resume aada10c6-9299-4c45-abc4-91db9c0f935d 'what file did we just see?'
|
|
```
|
|
- New Session ID: `1433467f-ff14-4292-b5b2-2aac77a808f0`
|
|
- Created file: `~/.claude/projects/.../1433467f-ff14-4292-b5b2-2aac77a808f0.jsonl`
|
|
|
|
## Key Findings for --resume
|
|
|
|
### 1. Session File Behavior
|
|
- Creates a NEW session file with NEW session ID
|
|
- Original session file remains unchanged
|
|
- Two separate files exist after resumption
|
|
|
|
### 2. History Preservation
|
|
- The new session file contains the COMPLETE history from the original session
|
|
- History is prefixed at the beginning of the new file
|
|
- Includes a summary line at the very top
|
|
|
|
### 3. Session ID Rewriting
|
|
- **CRITICAL FINDING**: All historical messages have their sessionId field UPDATED to the new session ID
|
|
- Original messages from session `aada10c6-9299-4c45-abc4-91db9c0f935d` now show `sessionId: "1433467f-ff14-4292-b5b2-2aac77a808f0"`
|
|
- This creates a unified session history under the new ID
|
|
|
|
### 4. Message Structure in New File
|
|
```
|
|
Line 1: Summary of previous conversation
|
|
Lines 2-6: Complete history from original session (with updated session IDs)
|
|
Lines 7-8: New messages from current interaction
|
|
```
|
|
|
|
### 5. Context Preservation
|
|
- Claude successfully maintains full context
|
|
- Can answer questions about previous interactions
|
|
- Behaves as if it's a continuous conversation
|
|
|
|
## Technical Details
|
|
|
|
### Original Session File Structure
|
|
- Contains only messages from the original session
|
|
- All messages have original session ID
|
|
- Remains untouched after resume
|
|
|
|
### New Session File Structure After Resume
|
|
```json
|
|
{"type":"summary","summary":"Listing directory files in current location","leafUuid":"..."}
|
|
{"parentUuid":null,"sessionId":"1433467f-ff14-4292-b5b2-2aac77a808f0","message":{"role":"user","content":[{"type":"text","text":"list files in this directory"}]},...}
|
|
// ... all historical messages with NEW session ID ...
|
|
{"parentUuid":"...","sessionId":"1433467f-ff14-4292-b5b2-2aac77a808f0","message":{"role":"user","content":"what file did we just see?"},...}
|
|
```
|
|
|
|
## Implications for handy-cli
|
|
|
|
When using --resume:
|
|
1. Must handle new session ID in responses
|
|
2. Original session remains as historical record
|
|
3. All context preserved but under new session identity
|
|
4. Session ID in stream-json output will be the new one, not the resumed one
|