web/README.md
web/ contains the standalone WebUI launcher for PicoClaw.
It is not just a frontend: it is a small launcher service that bundles a React dashboard, exposes a backend API, manages launcher authentication, and starts or attaches to the picoclaw gateway process.
picoclaw gateway subprocess.This directory is a small monorepo:
backend/
backend/dist.frontend/
At runtime the launcher and the main PicoClaw engine are separate processes:
18800 by default.picoclaw gateway -E./pico/ws.The current frontend exposes these major pages and flows:
/
/models
/credentials
/channels/*
weixin, telegram, discord, slack, feishu, dingtalk, line, qq, onebot, wecom, whatsapp, whatsapp_native, pico, maixcam, matrix, irc./agent/skills
/agent/tools
/config
/logs
The UI currently supports English and Simplified Chinese, plus light and dark themes.
The launcher uses the same PicoClaw config file as the main binary.
~/.picoclaw/config.jsonPICOCLAW_CONFIGpicoclaw-launcher /path/to/config.jsonLauncher-only settings are stored beside that app config:
launcher-config.json~/.picoclaw/launcher-config.jsonThat file currently stores:
portpublicallowed_cidrsIf -port or -public are passed explicitly, the CLI flag wins for that run.
If they are omitted, stored launcher settings are used.
If the target config file does not exist, the launcher tries to bootstrap it automatically by running:
picoclaw onboard
The launcher looks for the main PicoClaw binary in this order:
PICOCLAW_BINARYpicoclaw binary in the same directory as the launcherpicoclaw from PATHIf onboarding or gateway startup cannot find the main binary, set PICOCLAW_BINARY explicitly.
The launcher manages picoclaw gateway -E.
On startup it tries to auto-start or attach to the gateway, but only when startup preconditions pass. In the current code, the main checks are:
When a gateway process is started by the launcher, the launcher:
starting, restarting, and stoppingThe dashboard is protected by password login.
/launcher-setup to create the dashboard password./launcher-login.launcher-auth.db.launcher-config.json.launcher_token values are migrated once into password login and are removed from saved launcher config.PICOCLAW_LAUNCHER_TOKEN is deprecated and ignored; after upgrading from env-token auth, open /launcher-setup to create a password.Authorization: Bearer dashboard auth are not supported.By default the launcher listens on:
127.0.0.1:18800
With -public or public: true, it listens on all interfaces:
0.0.0.0:18800
When public access is enabled:
allowed_cidrs can restrict which client IP ranges may connect1.25+pnpmOn macOS, the web Makefile enables CGO_ENABLED=1 so tray-enabled launcher builds work as expected.
On Darwin or FreeBSD without cgo, the launcher falls back to headless mode without a tray.
If you want to prepare the frontend workspace manually, you can still install dependencies yourself:
cd frontend
pnpm install
From the web/ directory:
make dev
This does three things:
../build/picoclaw for launcher development.PICOCLAW_BINARY pointing at that binary.Use this when you want the full launcher flow during development.
make dev-frontend
make dev-backend
Notes:
dev-frontend runs the Vite server.dev-backend runs the Go backend only./api to http://localhost:18800.dev-backend alone is mainly useful for backend work or when backend/dist already contains a built frontend.From web/:
make build
This:
backend/dist.build/picoclaw-launcher.Override the output path if needed:
make build OUTPUT=/tmp/picoclaw-launcher
From the repository root you can also use:
make build-launcher
That writes the platform-specific launcher to:
build/picoclaw-launcher-<platform>-<arch>
and refreshes the build/picoclaw-launcher symlink.
For frontend work there are two useful package scripts:
cd frontend
pnpm build
pnpm build:backend
pnpm build writes a normal Vite build to frontend/distpnpm build:backend writes the embeddable build to ../backend/distExamples:
./build/picoclaw-launcher
./build/picoclaw-launcher -console
./build/picoclaw-launcher -public
./build/picoclaw-launcher -port 19999 /path/to/config.json
Current launcher flags:
-port-public-no-browser-lang-consoleFrom web/:
make dev
make dev-frontend
make dev-backend
make build
make build-frontend
make test
make lint
make clean
What they do today:
make build-frontend
pnpm install --frozen-lockfile when dependencies are missing or stale.backend/dist.make test
pnpm lint.make lint
go vet.pnpm check.pnpm check currently formats files with Prettier and fixes lint issues with ESLint, so this target can modify your working tree.make clean
frontend/dist, backend/dist, and build/, then recreates backend/dist/.gitkeep.web/
├── backend/
│ ├── api/ # REST API handlers and launcher runtime endpoints
│ ├── launcherconfig/ # launcher-config.json load/save/validation
│ ├── middleware/ # auth, content type, logging, CIDR allowlist
│ ├── model/ # Go data structures and logic wrappers
│ ├── utils/ # runtime helpers, onboarding, browser launch
│ ├── winres/ # Windows application resources
│ └── dist/ # embedded frontend build output
├── frontend/
│ ├── src/api/ # browser API clients
│ ├── src/components/ # UI pages and shared components
│ ├── src/features/ # feature-specific state, controllers, and protocol helpers
│ ├── src/hooks/ # shared React hooks
│ ├── src/i18n/ # internationalization language packs
│ ├── src/lib/ # generic library utilities
│ ├── src/routes/ # TanStack file routes
│ ├── src/store/ # global state management
│ └── vite.config.ts # dev server and build config
├── Makefile
└── README.md
Existing dashboard sessions do not survive launcher restarts.
That is expected: each launcher process generates a new session value, so old cookies become invalid.
Sign in again with the dashboard password on /launcher-login.
The launcher only allows gateway startup when the configured default model is usable. Check these in the dashboard:
picoclawSet the main binary explicitly:
export PICOCLAW_BINARY=/absolute/path/to/picoclaw
This affects onboarding and gateway subprocess startup.
Use make dev for the normal workflow.
If you run only make dev-backend, either run make dev-frontend alongside it or build the embedded frontend first with make build-frontend.
../README.md../docs/guides/configuration.md../docs/guides/providers.md../docs/operations/troubleshooting.md