一键导入
webui
Web UI development guidelines for the v2 React UI in webui/. Apply when working on files in webui/, creating React components, or using TanStack Router/Query.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Web UI development guidelines for the v2 React UI in webui/. Apply when working on files in webui/, creating React components, or using TanStack Router/Query.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Guidelines for writing Go tests. Apply when creating or modifying test files.
Execute an already-agreed plan by delivering it as a stack of "layer cake" PRs — one xagent task per PR, strictly one at a time. Use when the design is settled (usually an accepted proposal) and the job is to build it. You delegate each layer to a task, review the PR it opens, and the human merges. A merge is the go signal to start the next layer. Feedback on a PR — yours or the user's — is relayed back to the task (which wakes on the PR event) rather than fixed by hand. Mute all channel notifications and unmute only the tasks you create. Track progress in a GitHub issue with a checkbox per layer so the work can be resumed after context loss.
Create a design proposal for a feature or change. Use when the user wants to plan or design something before implementing it.
Act as an engineering manager who delegates implementation to xagent tasks. Use for sessions where the user wants you to design, delegate, and review work rather than write production code yourself. You scope work, kick off xagent tasks, and review the proposals and PRs they produce — requesting changes by commenting on the PR and tagging the author.
Create xagent tasks using the MCP tools. Use when the user wants to create a task for the xagent system.
Guidelines for working with the Connect RPC (gRPC) API. Apply when modifying proto definitions, implementing server handlers, or creating API clients.
| name | webui |
| description | Web UI development guidelines for the v2 React UI in webui/. Apply when working on files in webui/, creating React components, or using TanStack Router/Query. |
A modern React-based UI is being developed in webui/ to replace the Go template-based UI in internal/server/templates/.
grpc skill for details)cd webui
pnpm install
pnpm run dev # Runs on http://localhost:5173
The v2 UI runs independently on the Vite dev server and can be developed incrementally alongside the existing Go template UI.
Always run pnpm lint in webui/ before finishing any task that touches frontend code. CI runs ESLint on every webui PR and will fail otherwise. Fix all lint errors before opening a PR — do not push code with known lint failures.
cd webui
pnpm lint
File-based routing - Routes are defined as files in src/routes/. The TanStack Router Vite plugin auto-generates routeTree.gen.ts (gitignored).
Route file naming:
index.tsx → /tasks.tsx → /taskstasks/$id.tsx → /tasks/:id (dynamic param)tasks.$id.edit.tsx → /tasks/:id/edit__root.tsx → Root layout (wraps all routes)Creating a route:
// src/routes/tasks.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/tasks')({
component: TasksPage,
})
function TasksPage() {
return <div>Tasks</div>
}
Accessing route params:
// src/routes/tasks/$id.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/tasks/$id')({
component: TaskDetail,
})
function TaskDetail() {
const { id } = Route.useParams()
return <div>Task {id}</div>
}
Navigation:
import { Link, useNavigate } from '@tanstack/react-router'
// Declarative
<Link to="/tasks/$id" params={{ id: '123' }}>View Task</Link>
// Programmatic
const navigate = useNavigate()
navigate({ to: '/tasks/$id', params: { id: '123' } })
Type safety - The router instance is registered via module augmentation in main.tsx, enabling full TypeScript autocomplete for routes, params, and navigation throughout the app.
Use Connect-Query for ALL API calls - The webui uses @connectrpc/connect-query which provides type-safe hooks generated from protobuf definitions. Do NOT use raw fetch or manual useQuery with fetch.
Generated code - Run pnpm run generate in the webui/ directory to regenerate TypeScript types and hooks from proto definitions. Generated files are in src/gen/ (gitignored).
Fetching data with useQuery:
import { useQuery } from '@connectrpc/connect-query'
import { listTasks } from '@/gen/xagent/v1/xagent-XAgentService_connectquery'
function TaskList() {
const { data, isLoading, error } = useQuery(listTasks, {
statuses: ['pending', 'running'],
})
if (isLoading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
return (
<ul>
{data?.tasks.map(task => (
<li key={String(task.id)}>{task.name}</li>
))}
</ul>
)
}
Mutations with useMutation:
import { useMutation, useQueryClient } from '@connectrpc/connect-query'
import { createTask, listTasks } from '@/gen/xagent/v1/xagent-XAgentService_connectquery'
function CreateTaskButton() {
const queryClient = useQueryClient()
const mutation = useMutation(createTask, {
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [listTasks.service.typeName] })
},
})
return (
<button onClick={() => mutation.mutate({ name: 'New Task', workspace: 'default' })}>
Create
</button>
)
}
Benefits:
grpc skill for complete documentation on TypeScript client usageUse shadcn/ui components - Always prefer off-the-shelf shadcn components with their default styles. Avoid writing custom UI components unless absolutely necessary. Browse available components at https://ui.shadcn.com/docs/components
Add components as needed - Install shadcn components with npx shadcn@latest add <component-name> (e.g., button, card, table, dialog)
Reference v1 for data, not design - The Go template UI in internal/server/templates/ can be referenced to understand:
Do NOT copy v1 implementation - Do not replicate v1's layout, styles, HTML structure, or templates. The v2 is a complete rewrite with modern components and UX patterns.
API Access - The v2 UI will call the same Connect RPC API at /xagent.v1.XAgentService/* that the v1 UI uses.
Directory structure:
src/components/ui/ - shadcn/ui primitives only (Button, Badge, Card, Table, etc.)src/components/ - Custom project components (StatusBadge, RelativeTime, CommandBadge, etc.)shadcn/ui philosophy - shadcn/ui is NOT a traditional npm package. It's a code distribution system that copies component source code into your project (src/components/ui/). You own the code and can modify it directly.
Important: Only shadcn components belong in components/ui/. Custom components that build on top of shadcn primitives go in components/.
Examples:
src/components/ui/badge.tsx ← shadcn primitive
src/components/ui/button.tsx ← shadcn primitive
src/components/status-badge.tsx ← custom component (uses Badge)
src/components/command-badge.tsx ← custom component (uses Badge)
src/components/relative-time.tsx ← custom component (uses Tooltip)
One component, multiple variants - Do NOT create multiple copies of the same component (e.g., button-primary.tsx, button-secondary.tsx). Instead, use class-variance-authority (CVA) to add variants to a single component:
// src/components/ui/button.tsx
const buttonVariants = cva(
"inline-flex items-center justify-center...",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground...",
destructive: "bg-destructive text-destructive-foreground...",
success: "bg-green-600 text-white hover:bg-green-700", // Custom variant
}
}
}
)
Usage: <Button variant="success">Save</Button>
When to create custom components (in src/components/):
TaskCard that uses Card + Badge + Button)StatusBadge, CommandBadge)Don't create:
components/ui/ - that directory is reserved for shadcn primitivesPattern: One source of truth per primitive component, compose for complexity.