Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ CLAWDBOT_GATEWAY_URL=ws://127.0.0.1:18789
CLAWDBOT_GATEWAY_TOKEN=
# Alternative:
# CLAWDBOT_GATEWAY_PASSWORD=

# File Explorer - root directory for file browsing
# Defaults to the user's home directory if not set.
FILES_ROOT=/home/agustin
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ count.txt
.output
.vinxi
todos.json
webclaw
70 changes: 60 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,71 @@
# WebClaw

![Cover](https://raw.githubusercontent.com/ibelick/webclaw/main/apps/webclaw/public/cover.jpg)
![Cover](./public/cover.webp)

Fast web client for OpenClaw.

[webclaw.dev](https://webclaw.dev)
Fast web client for OpenClaw

Currently in beta.

## Features

- πŸ’¬ **Chat** β€” Real-time chat with your OpenClaw agent
- πŸ“ **File Explorer** β€” Browse, upload, download, rename and delete files on the host filesystem
- ✏️ **Text Editor** β€” Edit YAML, JSON, Markdown, Python, JavaScript, and 30+ file types directly in the browser (Ctrl+S to save)

## Setup

Create `apps/webclaw/.env.local` with `CLAWDBOT_GATEWAY_URL` and either
`CLAWDBOT_GATEWAY_TOKEN` (recommended) or `CLAWDBOT_GATEWAY_PASSWORD`. These map
to your OpenClaw Gateway auth (`gateway.auth.token` or `gateway.auth.password`).
Default URL is `ws://127.0.0.1:18789`. Docs: https://docs.openclaw.ai/gateway
### 1. Install dependencies

```bash
pnpm install
pnpm dev
npm install
```

### 2. Configure environment

Create a `.env` file in the project root:

```env
# Gateway connection (required)
CLAWDBOT_GATEWAY_URL=ws://127.0.0.1:18789
CLAWDBOT_GATEWAY_TOKEN=your_gateway_token_here
# Or use password auth:
# CLAWDBOT_GATEWAY_PASSWORD=your_password_here

# File Explorer β€” root directory for browsing (optional)
# Defaults to the current user's home directory if not set.
FILES_ROOT=/home/your_user
```

| Variable | Required | Description |
|---|---|---|
| `CLAWDBOT_GATEWAY_URL` | No | WebSocket URL for the OpenClaw Gateway. Default: `ws://127.0.0.1:18789` |
| `CLAWDBOT_GATEWAY_TOKEN` | Yes* | Gateway auth token (`gateway.auth.token` in OpenClaw config) |
| `CLAWDBOT_GATEWAY_PASSWORD` | Yes* | Alternative: Gateway password (`gateway.auth.password`) |
| `FILES_ROOT` | No | Absolute path to the root directory for the file explorer. Default: `$HOME` |

\* One of `CLAWDBOT_GATEWAY_TOKEN` or `CLAWDBOT_GATEWAY_PASSWORD` is required.

### 3. Run

```bash
npm run dev
```

The app will be available at `http://localhost:3000`. Use `--host` to expose on the network:

```bash
npm run dev -- --host
```

## File Explorer

The file explorer reads and writes directly to the host filesystem under the `FILES_ROOT` directory. Key points:

- **Security**: All paths are jailed to `FILES_ROOT` β€” directory traversal and symlink escapes are blocked.
- **Hidden files**: Visible by default (dotfiles are shown).
- **Text editing**: Double-click any supported text file to open the built-in editor. Supported extensions include `.yaml`, `.yml`, `.json`, `.md`, `.txt`, `.py`, `.js`, `.ts`, `.sh`, `.html`, `.css`, and many more.
- **Context menu**: Right-click any file or folder for actions (Open, Edit, Download, Rename, Delete).

## Docs

Gateway auth docs: https://docs.openclaw.ai/gateway
Binary file added apps/webclaw/public/screenshot-file-explorer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions apps/webclaw/src/lib/file-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export type FileItem = {
path: string
name: string
size: number
extension: string
modified: string
mode: number
isDir: boolean
isSymlink: boolean
type: string // 'directory' | 'text' | 'image' | 'video' | 'audio' | 'blob'
}

export type FileListing = {
items: FileItem[]
path: string
name: string
isDir: boolean
size: number
modified: string
mode: number
numDirs: number
numFiles: number
sorting: {
by: string
asc: boolean
}
}
Loading