claw-web-v2 / DEVELOPER_GUIDE.md
Claw Web
docs: Comprehensive developer guide for next developer
0065b67
# Claw-Web Developer Guide
**Complete documentation for the Claw-Web project β€” a web-based port of Claude Code (Rust CLI) to a full-stack TypeScript web application.**
**Total codebase:** ~32,700 lines of TypeScript/TSX across 126 source files.
---
## Table of Contents
1. [Architecture Overview](#architecture-overview)
2. [Project Structure](#project-structure)
3. [Tech Stack](#tech-stack)
4. [Getting Started](#getting-started)
5. [Server Runtime Modules](#server-runtime-modules)
6. [Client Components](#client-components)
7. [Buddy Companion Pet System](#buddy-companion-pet-system)
8. [Tools and Executor](#tools-and-executor)
9. [MCP Integration](#mcp-integration)
10. [Configuration System](#configuration-system)
11. [Permissions System](#permissions-system)
12. [Plugin System](#plugin-system)
13. [Deployment](#deployment)
14. [Parity Status with Original](#parity-status-with-original)
15. [Known Issues and TODOs](#known-issues-and-todos)
---
## Architecture Overview
Claw-Web is a **full-stack TypeScript application** that ports the original Claude Code Rust CLI to a web interface. It uses a client-server architecture where:
- **Client** (React + Vite + TailwindCSS) provides the chat UI, settings, file manager, terminal, and buddy companion
- **Server** (Express + tRPC + esbuild) runs the agent loop, tool executor, LLM API calls, and all runtime modules
- **Database** (MySQL/TiDB via Drizzle ORM) stores sessions, messages, settings, and user data
- **LLM** (HuggingFace Router API, OpenAI-compatible) powers the AI agent with tool calling
The agent loop in `server/runtime/agent.ts` is a direct port of the original `conversation.rs` Rust module, implementing the same iteration model with `Number.MAX_SAFE_INTEGER` max iterations (matching Rust's `usize::MAX`).
---
## Project Structure
```
claw-web/
β”œβ”€β”€ client/ # Frontend (React + Vite)
β”‚ └── src/
β”‚ β”œβ”€β”€ buddy/ # Companion pet system (6 modules)
β”‚ β”‚ β”œβ”€β”€ types.ts # Type definitions (BuddyState, BuddyStats, etc.)
β”‚ β”‚ β”œβ”€β”€ sprites.ts # Sprite configs (6 stages x 10 moods)
β”‚ β”‚ β”œβ”€β”€ companion.ts # State management, XP, leveling, evolution
β”‚ β”‚ β”œβ”€β”€ prompt.ts # Personality, messages, achievements
β”‚ β”‚ β”œβ”€β”€ useBuddyNotification.tsx # React hook for buddy state
β”‚ β”‚ └── index.ts # Barrel export
β”‚ β”œβ”€β”€ components/ # UI components
β”‚ β”‚ β”œβ”€β”€ BuddySprite.tsx # Companion pet UI (stats panel, interactions)
β”‚ β”‚ β”œβ”€β”€ ChatInput.tsx # Message input with slash commands
β”‚ β”‚ β”œβ”€β”€ FileManagerPanel.tsx # File browser
β”‚ β”‚ β”œβ”€β”€ MessageBubble.tsx # Chat message rendering
β”‚ β”‚ β”œβ”€β”€ PluginMarketplace.tsx # Plugin management UI
β”‚ β”‚ β”œβ”€β”€ SettingsPanel.tsx # Settings (Model, Parameters, Permissions, MCP, etc.)
β”‚ β”‚ β”œβ”€β”€ Sidebar.tsx # Session sidebar
β”‚ β”‚ β”œβ”€β”€ TaskManagerPanel.tsx # Task/todo management
β”‚ β”‚ β”œβ”€β”€ TerminalPanel.tsx # Embedded terminal
β”‚ β”‚ β”œβ”€β”€ ThinkingBlock.tsx # AI thinking display
β”‚ β”‚ β”œβ”€β”€ ToolCallCard.tsx # Tool call visualization
β”‚ β”‚ └── ui/ # shadcn/ui components (70+ files)
β”‚ β”œβ”€β”€ contexts/ # React contexts
β”‚ β”œβ”€β”€ hooks/ # Custom hooks (useChat, useMobile, etc.)
β”‚ β”œβ”€β”€ pages/ # Page components (Home, NotFound, etc.)
β”‚ └── lib/ # Utilities (trpc client, utils)
β”œβ”€β”€ server/ # Backend
β”‚ β”œβ”€β”€ _core/ # Framework core (tRPC, auth, LLM, etc.)
β”‚ β”‚ β”œβ”€β”€ llm.ts # LLM API client (OpenAI-compatible)
β”‚ β”‚ β”œβ”€β”€ oauth.ts # OAuth handling
β”‚ β”‚ └── ... # Other core modules
β”‚ β”œβ”€β”€ runtime/ # Agent runtime (ported from Rust)
β”‚ β”‚ β”œβ”€β”€ agent.ts # Main agent loop (← conversation.rs)
β”‚ β”‚ β”œβ”€β”€ bootstrap.ts # Project bootstrap/onboarding
β”‚ β”‚ β”œβ”€β”€ chat-endpoint.ts # Chat SSE endpoint + slash commands
β”‚ β”‚ β”œβ”€β”€ compact.ts # Context compaction (527 lines)
β”‚ β”‚ β”œβ”€β”€ config.ts # Config loading + deep merge
β”‚ β”‚ β”œβ”€β”€ lsp-client.ts # LSP client for diagnostics
β”‚ β”‚ β”œβ”€β”€ mcp-client.ts # MCP server manager
β”‚ β”‚ β”œβ”€β”€ permissions.ts # Permission policy system
β”‚ β”‚ β”œβ”€β”€ plugins.ts # Plugin manager
β”‚ β”‚ β”œβ”€β”€ remote.ts # Remote/proxy configuration
β”‚ β”‚ β”œβ”€β”€ sandbox.ts # Container sandbox detection
β”‚ β”‚ β”œβ”€β”€ session.ts # Session serialization/validation
β”‚ β”‚ β”œβ”€β”€ system-prompt.ts # System prompt + TOOL_DEFINITIONS
β”‚ β”‚ └── usage.ts # Token/cost tracking
β”‚ β”œβ”€β”€ tools/ # Tool implementations
β”‚ β”‚ β”œβ”€β”€ executor.ts # 30+ tool implementations (1600+ lines)
β”‚ β”‚ └── file-ops.ts # File operation utilities
β”‚ β”œβ”€β”€ db.ts # Database schema (Drizzle)
β”‚ β”œβ”€β”€ routers.ts # tRPC routers
β”‚ └── storage.ts # File storage
β”œβ”€β”€ shared/ # Shared types between client/server
β”‚ β”œβ”€β”€ claw-types.ts # Core shared types
β”‚ └── types.ts # Additional types
β”œβ”€β”€ drizzle/ # Database migrations
β”œβ”€β”€ package.json
β”œβ”€β”€ vite.config.ts
└── tsconfig.json
```
---
## Tech Stack
| Layer | Technology |
|-------|-----------|
| Frontend | React 18, Vite, TailwindCSS, shadcn/ui |
| Backend | Express, tRPC, esbuild |
| Database | MySQL/TiDB via Drizzle ORM |
| Auth | Manus OAuth (session-based) |
| LLM | HuggingFace Router API (OpenAI-compatible) |
| Deployment | HuggingFace Spaces (Docker) |
| Language | TypeScript throughout |
---
## Getting Started
### Prerequisites
- Node.js 22+
- pnpm
- MySQL/TiDB database
### Development
```bash
cd claw-web
pnpm install
pnpm dev # Starts both client (Vite) and server (esbuild)
```
### Build
```bash
pnpm build # Builds client (Vite) + server (esbuild)
```
### Environment Variables
| Variable | Description |
|----------|-------------|
| `DATABASE_URL` | MySQL/TiDB connection string |
| `HF_TOKEN` | HuggingFace API token for LLM |
| `SESSION_SECRET` | Session encryption key |
---
## Server Runtime Modules
### agent.ts β€” Main Agent Loop
**Original:** `conversation.rs` (Rust)
**Parity:** ~95%
The core agent loop that:
1. Builds system prompt with `TOOL_DEFINITIONS` + dynamically injected MCP tools
2. Calls LLM API with streaming
3. Processes tool calls from LLM response
4. Executes tools via `executor.ts`
5. Runs pre/post-tool hooks
6. Appends results to conversation
7. Loops until LLM stops calling tools or max iterations reached
Key constants:
- `MAX_ITERATIONS = Number.MAX_SAFE_INTEGER` (matches Rust `usize::MAX`)
- Tools are dynamically merged: `TOOL_DEFINITIONS + mcpTools`
### compact.ts β€” Context Compaction
**Original:** `compact.rs` (Rust)
**Parity:** ~99%
Full implementation (527 lines) of context window compaction:
- `shouldCompact()` β€” checks if conversation exceeds token threshold
- `compactSession()` β€” summarizes old messages, preserves recent context
- Triggered manually via `/compact` slash command
### config.ts β€” Configuration System
**Original:** `config.rs` (Rust)
**Parity:** ~90%
Loads configuration from multiple sources with deep merge:
- `.claw/settings.json` (project-level)
- `~/.claw/settings.json` (user-level)
- `deepMergeObjects()` β€” recursive merge for nested configs
- `extendUnique()` / `pushUnique()` β€” deduplicated array merging for hooks
- `mergeHooksConfig()` β€” proper PreToolUse/PostToolUse hook merging
### permissions.ts β€” Permission Policy
**Original:** `permissions.rs` (Rust)
**Parity:** ~85%
Permission modes (ordered by severity, matching Rust `derive(PartialOrd, Ord)`):
```typescript
ReadOnly = 0 // Can only read files
WorkspaceWrite = 1 // Can write within workspace
DangerFullAccess = 2 // Can execute dangerous operations
Prompt = 3 // Must prompt user for approval
Allow = 4 // Auto-approve everything
```
### mcp-client.ts β€” MCP Server Manager
**Original:** `mcp.rs` (Rust)
**Parity:** ~80%
Model Context Protocol integration:
- `McpServerManager` β€” manages multiple MCP server connections
- `connectAndListAllTools()` β€” discovers tools from all configured servers
- `normalizeNameForMcp()` β€” name normalization (preserves case, handles `claude.ai` prefix)
- `callTool()` β€” executes MCP tool calls via JSON-RPC
- Dynamic tool injection into agent's `TOOL_DEFINITIONS`
### sandbox.ts β€” Container Sandbox Detection
**Original:** `sandbox.rs` (Rust)
**Parity:** ~85%
Detects container environments:
- Docker (`.dockerenv`, cgroup)
- Podman (`/run/.containerenv`)
- Kubernetes (`KUBERNETES_SERVICE_HOST`)
- containerd (cgroup)
- libpod (cgroup)
### session.ts β€” Session Serialization
**Original:** Session handling in Rust
**Parity:** ~90%
Validated deserialization with `SessionError` class:
- `validateSessionData()` β€” validates all required fields
- `deserializeSession()` β€” safe JSON parsing with error handling
- `serializeSession()` β€” serialization with validation
### usage.ts β€” Token/Cost Tracking
**Original:** `usage.rs` (Rust)
**Parity:** ~85%
Tracks API usage:
- `UsageTracker` β€” accumulates token counts and costs
- `formatUsd()` β€” formats costs with 4 decimal places (matches Rust `format!("${:.4}")`)
- `summaryLines()` β€” generates usage summary
---
## Client Components
### Home.tsx β€” Main Page (~1020 lines)
The primary page component containing:
- Chat interface with message bubbles
- Sidebar with session management
- Settings panel
- File manager, terminal, task manager panels
- Buddy companion pet integration
- Plan mode with step visualization
- Ask-user dialog for agent questions
- Export/import session functionality
### SettingsPanel.tsx β€” Settings UI
Tabs: **Model, Parameters, Permissions, MCP, Costs, Memory**
Note: API tab was intentionally removed (built-in HuggingFace Router).
### BuddySprite.tsx β€” Companion Pet UI
Full companion pet with:
- Evolution-stage sprites (egg β†’ baby β†’ junior β†’ senior β†’ master β†’ legendary)
- Interactive stats panel (XP, happiness, energy, hunger)
- Achievement system (17 achievements)
- Notification system (level-ups, evolutions, achievements)
- Feed and Pet interactions
- Rename functionality
---
## Buddy Companion Pet System
The buddy system is a **6-module subsystem** matching the original Claude Code architecture:
| Module | Lines | Description |
|--------|-------|-------------|
| `types.ts` | 95 | Full type system: BuddyState, BuddyStats, evolution stages, XP rewards |
| `sprites.ts` | 160 | Sprite configs for 6 evolution stages x 10 moods, colors, animations |
| `companion.ts` | 250 | State management, XP/leveling, evolution, persistence, time decay |
| `prompt.ts` | 210 | Personality messages, stage greetings, 17 achievements, stats formatting |
| `useBuddyNotification.tsx` | 140 | React hook: state loading, event handlers, mood calculation, decay timer |
| `BuddySprite.tsx` | 300 | Full UI: sprite, speech bubbles, stats panel, achievements, notifications |
### Evolution Stages
| Stage | Level Range | Description |
|-------|------------|-------------|
| Egg | 0-2 | Just hatched, minimal interaction |
| Baby | 3-5 | Learning, simple faces |
| Junior | 6-10 | Growing, more expressive |
| Senior | 11-20 | Experienced, accessories |
| Master | 21-50 | Expert, special effects |
| Legendary | 51+ | Transcended, full effects |
### XP Rewards
| Action | XP |
|--------|-----|
| Tool call | 5 |
| File created | 10 |
| File edited | 3 |
| Bug fixed | 25 |
| Test passed | 15 |
| Session completed | 20 |
| Streak day | 50 |
| First session | 100 |
---
## Tools and Executor
`server/tools/executor.ts` implements **30+ tools** (1600+ lines):
| Tool | Description |
|------|-------------|
| `bash` | Shell command execution with sandbox support |
| `read_file` | Read file contents with line ranges |
| `write_file` | Create/overwrite files |
| `edit_file` | Surgical file edits (find/replace) |
| `multi_edit` | Multiple edits in one call |
| `grep_search` | Regex search across files |
| `glob_search` | File path pattern matching |
| `list_dir` | Directory listing |
| `TodoRead` / `TodoWrite` | Task management |
| `NotebookRead` / `NotebookEdit` | Jupyter notebook support |
| `Agent` | Sub-agent spawning with presets |
| `WebSearch` / `WebFetch` | Web browsing |
| `REPL` | Python REPL execution |
| `mcp__*` | Dynamic MCP tool routing |
### MCP Tool Routing
When the LLM calls a tool with prefix `mcp__`, the executor:
1. Splits the name: `mcp__servername__toolname`
2. Finds the MCP server by name
3. Calls `McpServerManager.callTool(serverName, toolName, args)`
4. Returns the result to the LLM
---
## MCP Integration
### Configuration
MCP servers are configured in `.claw/settings.json`:
```json
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["./mcp-server.js"],
"env": {}
}
}
}
```
### Dynamic Tool Injection
At agent loop start:
1. `initializeMcpFromConfig(workDir)` loads MCP config
2. `connectAndListAllTools()` discovers tools from all servers
3. MCP tools are converted to OpenAI function calling format
4. Merged with static `TOOL_DEFINITIONS`
5. Full tool list sent to LLM
---
## Configuration System
### Config Loading Order
1. `.claw/settings.json` (project-level)
2. `~/.claw/settings.json` (user-level)
3. Database settings (per-session)
4. Environment variables
### Deep Merge
Uses `deepMergeObjects()` for recursive merging. Arrays in hooks use `extendUnique()` for deduplication (matching original Rust `extend_unique`).
---
## Permissions System
### Permission Modes
```
ReadOnly (0) < WorkspaceWrite (1) < DangerFullAccess (2) < Prompt (3) < Allow (4)
```
This ordering matches the original Rust `derive(PartialOrd, Ord)` enum ordering.
### Tool Permission Mapping
Each tool has a required permission level. The agent checks `modeGte(toolPermission, currentMode)` before executing.
---
## Plugin System
### Plugin Structure
```
.claw-plugins/
└── my-plugin/
β”œβ”€β”€ .claw-plugin/
β”‚ └── plugin.json # Manifest
└── hooks/
β”œβ”€β”€ pre.sh # Pre-tool hook
└── post.sh # Post-tool hook
```
### Hook Environment Variables
Pre-tool hooks receive:
- `HOOK_EVENT_NAME` β€” "PreToolUse"
- `HOOK_TOOL_NAME` β€” tool name
- `HOOK_TOOL_INPUT` β€” tool input (first 10KB)
- `HOOK_TOOL_INPUT_JSON` β€” full JSON input
- `HOOK_SESSION_ID` β€” session identifier
- `HOOK_WORKING_DIR` β€” working directory
Post-tool hooks additionally receive:
- `HOOK_TOOL_OUTPUT` β€” tool output (first 10KB)
- `HOOK_TOOL_RESULT_IS_ERROR` β€” "true" or "false"
---
## Deployment
### HuggingFace Spaces
The project deploys to HuggingFace Spaces via git push:
```bash
git remote add space https://huggingface.co/spaces/drt2221143/claw-web
git push space main
```
The Space uses a Docker container with Node.js 22.
### Live URL
https://drt2221143-claw-web.hf.space/
---
## Parity Status with Original
### Overall: ~92%
| Module | Parity | Notes |
|--------|--------|-------|
| agent.ts (conversation.rs) | 95% | Full loop, unlimited iterations, MCP injection |
| compact.ts | 99% | Full implementation |
| config.ts | 90% | Deep merge + extendUnique for hooks |
| permissions.ts | 85% | Correct ordering, authorize logic |
| mcp-client.ts | 80% | Full normalize, dynamic injection, callTool |
| session.ts | 90% | Validated deserialization |
| sandbox.ts | 85% | Full container detection |
| remote.ts | 85% | All 8 proxy env keys |
| usage.ts | 85% | formatUsd matches original |
| executor.ts | 85% | 30+ tools, MCP routing, hook payloads |
| lsp-client.ts | 85% | stderr drain, graceful shutdown |
| plugins.ts | 70% | Install/execute work, update/uninstall basic |
| bootstrap.ts | 100% | Full implementation |
| buddy system | 90% | 6/6 modules implemented |
### Not Ported (CLI-specific, not needed for web)
- `coordinator mode` β€” multi-agent CLI coordination
- `vim mode` β€” terminal vim keybindings
- `voice mode` β€” microphone input (CLI-specific)
- `auto updater` β€” self-update (not applicable to web)
- `magic docs` β€” auto-documentation (future enhancement)
- `prompt suggestion` β€” smart suggestions (future enhancement)
---
## Known Issues and TODOs
### High Priority
1. **Duplicate `/context` case** in `chat-endpoint.ts` (line 645 and 2070) β€” causes build warning
2. **Plugin update/uninstall** β€” basic stubs, need full implementation
3. **LSP diagnostics enrichment** β€” LSP works but doesn't enrich agent context
### Medium Priority
4. **Session history/resume** β€” no conversation resume across page reloads
5. **Cost tracker hooks** β€” real-time cost tracking not integrated
6. **Agent summary** β€” no session summary generation
7. **Output styles** β€” basic implementation, needs loadOutputStylesDir
### Low Priority
8. **OAuth PKCE/refresh** β€” web app uses session auth, not needed
9. **Sandbox OverlayFS** β€” mount isolation not enforced
10. **Keybindings** β€” minimal, original has 14 modules
---
## Contributing
### Code Style
- TypeScript strict mode
- ESLint + Prettier
- Functional components with hooks (React)
- tRPC for type-safe API calls
### Adding a New Tool
1. Add tool definition to `TOOL_DEFINITIONS` in `system-prompt.ts`
2. Add case handler in `executor.ts` switch statement
3. Set required permission level
4. Add pre/post hook support if needed
### Adding an MCP Server
1. Configure in `.claw/settings.json` under `mcpServers`
2. Tools are automatically discovered and injected
3. No code changes needed
---
*Last updated: April 2026*
*Maintained by: drt2221143*