PinchChat

PinchChat

[![CI](https://github.com/MarlBurroW/pinchchat/actions/workflows/ci.yml/badge.svg)](https://github.com/MarlBurroW/pinchchat/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org/) [![Docker](https://img.shields.io/badge/docker-ghcr.io-blue)](https://github.com/MarlBurroW/pinchchat/pkgs/container/pinchchat) [![Website](https://img.shields.io/badge/website-GitHub%20Pages-blueviolet)](https://marlburrow.github.io/pinchchat/) **A sleek, dark-themed webchat UI for [OpenClaw](https://github.com/openclaw/openclaw) โ€” monitor sessions, stream responses, and inspect tool calls in real-time.** > ๐Ÿ–ผ๏ธ *Screenshot coming soon โ€” [contributions welcome](https://github.com/MarlBurroW/pinchchat/issues)!* ## โœจ Features - ๐ŸŒ‘ **Dark neon theme** โ€” easy on the eyes, built with Tailwind CSS v4 - ๐Ÿ“Š **Token progress bars** โ€” track token usage per session in real-time - ๐Ÿ”ง **Tool call badges** โ€” expandable panels with syntax-highlighted JSON - ๐Ÿ“‹ **Session sidebar** โ€” browse active sessions with live activity indicators - ๐Ÿ“ **Markdown rendering** โ€” full GFM support with code highlighting - ๐Ÿ“Ž **File upload** โ€” attach files to your messages - โšก **Streaming responses** โ€” watch the AI think in real-time - ๐Ÿ” **Runtime login** โ€” enter gateway credentials at runtime, no secrets in the build - ๐ŸŒ **i18n support** โ€” English and French, configurable via `VITE_LOCALE` ## ๐Ÿš€ Quick Start ### Docker (recommended) ```bash docker run -p 3000:80 ghcr.io/marlburrow/pinchchat:latest ``` Open `http://localhost:3000` and enter your OpenClaw gateway URL + token on the login screen. Or use Docker Compose: ```bash curl -O https://raw.githubusercontent.com/MarlBurroW/pinchchat/main/docker-compose.yml docker compose up -d ``` ### From source **Prerequisites:** Node.js 18+, an OpenClaw gateway running and accessible. ```bash git clone https://github.com/MarlBurroW/pinchchat.git cd pinchchat npm install cp .env.example .env npm run dev ``` Optionally edit `.env` to pre-fill the gateway URL: ```env VITE_GATEWAY_WS_URL=ws://localhost:18789 VITE_LOCALE=en # or "fr" for French UI ``` ### Production build ```bash npm run build npx vite preview ``` Or serve the `dist/` folder with nginx, Caddy, or any static file server. ## โš™๏ธ Configuration All configuration is optional โ€” credentials are entered at runtime via the login screen. | Variable | Description | Default | |---|---|---| | `VITE_GATEWAY_WS_URL` | Pre-fill the gateway URL on the login screen | `ws://:18789` | | `VITE_LOCALE` | UI language (`en` or `fr`) | `en` | > **Note:** The gateway token is entered at runtime and stored in `localStorage` โ€” it is never baked into the build. ## ๐Ÿ— Architecture ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ PinchChat (Browser) โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Login โ”‚โ†’ โ”‚ App.tsx โ”‚โ†’ โ”‚ Chat + Sidebar โ”‚ โ”‚ โ”‚ โ”‚ Screen โ”‚ โ”‚ (router) โ”‚ โ”‚ (main UI) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ useGateway (hook) โ”‚ โ”‚ โ”‚ โ”‚ WebSocket state machine โ”‚ โ”‚ โ”‚ โ”‚ auth ยท sessions ยท messages โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ WebSocket (JSON frames) โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ OpenClaw Gateway โ”‚ โ”‚ (ws://host:18789) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### Key Components | File | Role | |---|---| | `src/hooks/useGateway.ts` | WebSocket connection, auth, message streaming, session management | | `src/components/LoginScreen.tsx` | Runtime credential entry (stored in `localStorage`) | | `src/components/Chat.tsx` | Message list with auto-scroll and streaming display | | `src/components/ChatInput.tsx` | Input with file upload, paste, drag & drop, image compression | | `src/components/ChatMessage.tsx` | Markdown rendering, tool calls, thinking blocks | | `src/components/Sidebar.tsx` | Session list with token usage bars and activity indicators | | `src/components/Header.tsx` | Connection status, token progress bar, logout | | `src/lib/i18n.ts` | Lightweight i18n (English + French) | | `src/lib/gateway.ts` | WebSocket protocol helpers and message types | ### Data Flow 1. **Login** โ€” User enters gateway URL + token โ†’ stored in `localStorage` 2. **Connect** โ€” `useGateway` opens a WebSocket and authenticates with the token 3. **Sessions** โ€” Gateway pushes session list; user selects one in the sidebar 4. **Messages** โ€” Messages stream in via WebSocket frames; the hook assembles partial chunks into complete messages 5. **Send** โ€” User input (+ optional file attachments) is sent as a JSON frame over the WebSocket ## ๐Ÿ›  Tech Stack - [React](https://react.dev/) 19 - [Vite](https://vite.dev/) 7 - [Tailwind CSS](https://tailwindcss.com/) v4 - [Radix UI](https://www.radix-ui.com/) primitives - [highlight.js](https://highlightjs.org/) via rehype-highlight - [Lucide React](https://lucide.dev/) icons - [react-markdown](https://github.com/remarkjs/react-markdown) with GFM ## ๐Ÿ“„ License [MIT](LICENSE) ยฉ Nicolas Varrot ## ๐Ÿค Contributing Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. ## ๐Ÿ”— Links - [OpenClaw](https://github.com/openclaw/openclaw) โ€” the AI agent platform PinchChat connects to