Skip to main content

openclaw-studio-dashboard

Expert in OpenClaw Studio - web dashboard for managing OpenClaw Gateway, agents, chat, approvals, and jobs

Aller à l'installation

Informations de source

Dépôt
reason-machines/hermes-skills
Dernière activité de la source
17 mai 2026 à 17:49
Langue détectée de SKILL.md
anglais
Étoiles
5
Forks
0

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
openclaw-studio-dashboard
description
Expert in OpenClaw Studio - web dashboard for managing OpenClaw Gateway, agents, chat, approvals, and jobs
triggers
["set up openclaw studio dashboard","connect studio to openclaw gateway","create agent in openclaw studio","configure openclaw studio upstream","manage openclaw agents with studio","deploy openclaw studio to production","troubleshoot openclaw studio connection","run openclaw studio locally"]
# OpenClaw Studio Dashboard > Skill by [ara.so](https://ara.so) — Hermes Skills collection. OpenClaw Studio is a clean web dashboard for OpenClaw Gateway that provides a unified interface to connect gateways, manage agents, chat, handle approvals, and configure jobs. Built with TypeScript/Next.js, it runs a server-owned control plane architecture with SSE streaming for real-time runtime events. ## What OpenClaw Studio Does - **Gateway Connection**: Connect to local or remote OpenClaw Gateway instances via WebSocket - **Agent Management**: Create, configure, and monitor AI agents with tool policies and sandbox settings - **Chat Interface**: Stream conversations with PI agents including tool calls and thinking traces - **Approval Workflows**: Manage exec approvals and runtime permissions - **Job Configuration**: Set up and monitor cron jobs - **Runtime Streaming**: Real-time event streaming over SSE with replay/history ## Installation & Startup ### Quick Start (Recommended) ```bash # Run latest version with npx npx -y openclaw-studio@latest # Opens on http://localhost:3000 # Default gateway URL: ws://localhost:18789 ``` ### From Source ```bash git clone https://github.com/grp06/openclaw-studio.git cd openclaw-studio npm install npm run dev ``` ### Setup Helper ```bash # Configure gateway URL/token without opening UI npm run studio:setup ``` ## Connection Architecture OpenClaw Studio uses a two-path architecture: 1. **Browser → Studio**: HTTP + SSE (`/api/runtime/*`, `/api/intents/*`) 2. **Studio → Gateway**: Server-owned WebSocket to upstream OpenClaw **Critical concept**: `ws://localhost:18789` means "gateway on the Studio host", not "gateway on your browser's machine". ## Configuration Patterns ### Deployment Scenarios #### A. Both Local (Same Computer) ```bash # Start Studio npx -y openclaw-studio@latest cd openclaw-studio npm run dev # Open http://localhost:3000 # In Studio UI: # - Upstream URL: ws://localhost:18789 # - Upstream Token: <your-gateway-token> ``` Get gateway token: ```bash openclaw config get gateway.auth.token ``` #### B. Gateway in Cloud, Studio Local **Option 1: Tailscale Serve (Recommended)** On gateway host: ```bash tailscale serve --yes --bg --https 443 http://127.0.0.1:18789 ``` In Studio (local laptop): - Upstream URL: `wss://<gateway-host>.ts.net` - Upstream Token: `<gateway-token>` **Option 2: SSH Tunnel** From laptop: ```bash ssh -L 18789:127.0.0.1:18789 user@<gateway-host> ``` In Studio: - Upstream URL: `ws://localhost:18789` - Upstream Token: `<gateway-token>` #### C. Both in Cloud (Always-On) On Studio VPS: ```bash # Start Studio npx -y openclaw-studio@latest cd openclaw-studio npm install npm run dev # If OpenClaw is on same VPS: # - Upstream URL: ws://localhost:18789 # - Upstream Token: <gateway-token> # Expose Studio over Tailscale tailscale serve --yes --bg --https 443 http://127.0.0.1:3000 # Access from anywhere: https://<studio-host>.ts.net ``` ### Environment Variables ```bash # Gateway connection (optional, can set in UI) NEXT_PUBLIC_GATEWAY_URL=ws://localhost:18789 # Studio access control (required for public binds) STUDIO_ACCESS_TOKEN=your-secure-token-here # OpenClaw state directory OPENCLAW_STATE_DIR=~/.openclaw # Bind host (default: 127.0.0.1) HOST=0.0.0.0 # Public bind - requires STUDIO_ACCESS_TOKEN ``` ### Configuration Files Studio settings are stored in `~/.openclaw/openclaw-studio/`: ``` ~/.openclaw/ ├── openclaw.json # OpenClaw Gateway config └── openclaw-studio/ ├── settings.json # Gateway URL/token └── runtime.db # Control-plane runtime DB ``` ## API & Key Commands ### Studio Setup ```bash # Development mode with auto-restart npm run dev # Production build npm run build npm run start # Turbo dev mode npm run dev:turbo # Verify/repair native dependencies npm run verify:native-runtime:repair npm run verify:native-runtime:check ``` ### TypeScript API Patterns #### Connecting to Gateway ```typescript // In Studio UI components import { useGatewayConnection } from '@/hooks/useGatewayConnection'; export function DashboardPage() { const { connected, connect, disconnect, status } = useGatewayConnection(); const handleConnect = async () => { try { await connect({ url: 'ws://localhost:18789', token: process.env.GATEWAY_TOKEN }); } catch (error) { console.error('Connection failed:', error); } }; return ( <div> <button onClick={handleConnect} disabled={connected}> {connected ? 'Connected' : 'Connect'} </button> <span>Status: {status}</span> </div> ); } ``` #### Streaming Runtime Events ```typescript // Server-side SSE streaming import { NextRequest } from 'next/server'; export async function GET(request: NextRequest) { const encoder = new TextEncoder(); const stream = new ReadableStream({ async start(controller) { // Subscribe to runtime events const subscription = runtimeStore.subscribe((event) => { const data = `data: ${JSON.stringify(event)}\n\n`; controller.enqueue(encoder.encode(data)); }); // Replay history const history = await runtimeStore.getHistory(); for (const event of history) { const data = `data: ${JSON.stringify(event)}\n\n`; controller.enqueue(encoder.encode(data)); } return () => subscription.unsubscribe(); } }); return new Response(stream, { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' } }); } ``` #### Creating Agents ```typescript // Agent creation API interface AgentConfig { name: string; systemPrompt: string; toolPolicy: 'all' | 'allowlist' | 'denylist'; allowedTools?: string[]; sandboxEnabled: boolean; execApprovalRequired: boolean; } export async function createAgent(config: AgentConfig) { const response = await fetch('/api/intents/agent-create', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ agent_name: config.name, system_prompt: config.systemPrompt, tool_policy: config.toolPolicy, allowed_tools: config.allowedTools, sandbox_config: { enabled: config.sandboxEnabled, mounts: config.sandboxEnabled ? [ { host: '/tmp', container: '/workspace', readonly: false } ] : [] }, exec_approval_required: config.execApprovalRequired }) }); if (!response.ok) { const error = await response.json(); throw new Error(error.message || 'Failed to create agent'); } return response.json(); } ``` #### Chat with Streaming ```typescript // Client-side chat with SSE import { useEffect, useState } from 'react'; export function ChatInterface({ agentId }: { agentId: string }) { const [messages, setMessages] = useState<ChatMessage[]>([]); const [thinking, setThinking] = useState<string[]>([]); useEffect(() => { // Connect to runtime stream const eventSource = new EventSource('/api/runtime/stream'); eventSource.addEventListener('message', (event) => { const data = JSON.parse(event.data); switch (data.type) { case 'tool_call': setMessages(prev => [...prev, { role: 'assistant', content: `Using tool: ${data.tool_name}`, metadata: { type: 'tool', ...data } }]); break; case 'thinking': setThinking(prev => [...prev, data.content]); break; case 'transcript': setMessages(prev => [...prev, { role: data.role, content: data.content }]); setThinking([]); break; } }); return () => eventSource.close(); }, [agentId]); const sendMessage = async (content: string) => { await fetch('/api/intents/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ agent_id: agentId, message: content }) }); }; return ( <div> {messages.map((msg, i) => ( <div key={i} className={`message ${msg.role}`}> {msg.content} </div> ))} {thinking.length > 0 && ( <div className="thinking"> {thinking.map((t, i) => <p key={i}>{t}</p>)} </div> )} <input onKeyPress={(e) => { if (e.key === 'Enter') { sendMessage(e.currentTarget.value); e.currentTarget.value = ''; } }} /> </div> ); } ``` ## Real-World Examples ### Example 1: Local Development Setup ```bash #!/bin/bash # setup-local-dev.sh # Start OpenClaw Gateway (in separate terminal) # openclaw gateway start # Get gateway token GATEWAY_TOKEN=$(openclaw config get gateway.auth.token) # Start Studio npx -y openclaw-studio@latest cd openclaw-studio # Configure via environment export NEXT_PUBLIC_GATEWAY_URL=ws://localhost:18789 npm run dev # Open http://localhost:3000 # Enter gateway token in UI ``` ### Example 2: Production Cloud Setup ```bash #!/bin/bash # deploy-studio-cloud.sh # On your VPS running OpenClaw Gateway cd /opt npx -y openclaw-studio@latest cd openclaw-studio # Install dependencies npm install # Build for production npm run build # Set access token for public access export STUDIO_ACCESS_TOKEN=$(openssl rand -hex 32) # Expose over Tailscale tailscale serve --yes --bg --https 443 http://127.0.0.1:3000 # Run production server npm run start echo "Studio available at: https://$(tailscale status --json | jq -r '.Self.DNSName')/" echo "Access token: $STUDIO_ACCESS_TOKEN" echo "Use: https://your-host.ts.net/?access_token=$STUDIO_ACCESS_TOKEN" ``` ### Example 3: Agent with Sandbox & Approvals ```typescript // create-secure-agent.ts import { createAgent } from './lib/agent-api'; async function createSecureCodeAgent() { const agent = await createAgent({ name: 'secure-code-assistant', systemPrompt: `You are a secure code assistant. Always ask before executing commands. Work within the sandboxed environment only.`, toolPolicy: 'allowlist', allowedTools: [ 'bash', 'read_file', 'write_file', 'search_files' ], sandboxEnabled: true, execApprovalRequired: true }); console.log('Agent created:', agent.id); return agent; } // Usage createSecureCodeAgent().catch(console.error); ``` ### Example 4: Cron Job Configuration ```typescript // configure-cron-job.ts interface CronJobConfig { agentId: string; schedule: string; task: string; enabled: boolean; } async function createCronJob(config: CronJobConfig) { const response = await fetch('/api/intents/job-create', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ agent_id: config.agentId, schedule: config.schedule,
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub