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
  2. Project Structure
  3. Tech Stack
  4. Getting Started
  5. Server Runtime Modules
  6. Client Components
  7. Buddy Companion Pet System
  8. Tools and Executor
  9. MCP Integration
  10. Configuration System
  11. Permissions System
  12. Plugin System
  13. Deployment
  14. Parity Status with Original
  15. 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

cd claw-web
pnpm install
pnpm dev          # Starts both client (Vite) and server (esbuild)

Build

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)):

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:

{
  "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:

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

  1. Session history/resume β€” no conversation resume across page reloads
  2. Cost tracker hooks β€” real-time cost tracking not integrated
  3. Agent summary β€” no session summary generation
  4. Output styles β€” basic implementation, needs loadOutputStylesDir

Low Priority

  1. OAuth PKCE/refresh β€” web app uses session auth, not needed
  2. Sandbox OverlayFS β€” mount isolation not enforced
  3. 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