Skip to main content

Web dashboard

Orka includes a built-in web dashboard served by the controller. Nothing extra to deploy.

Open it​

Forward the API port if it is not already forwarded, and have a client token ready (see Connect to the API):

kubectl -n orka-system port-forward svc/orka 8080:8080
kubectl -n orka-system create token orka-client

Open http://localhost:8080. The login page asks for a token; paste the one you just created. From there you can create Tasks, chat with the orchestrator, watch Tasks run live, and browse sessions and artifacts. If you use the CLI, orka login opens the dashboard already signed in.

Tech stack​

LayerTechnology
RuntimeBun 1.2+
FrontendReact 19
Build ToolVite 6
StylingTailwind CSS 4
UI Primitivesshadcn/ui (Radix-based)
State ManagementZustand 5
Data FetchingTanStack Query 5
RoutingTanStack Router (file-based)
Schema ValidationZod 3
IconsLucide React
TestingVitest + Testing Library

Architecture​

┌─────────────┐ ┌─────────────────┐ ┌──────────────────┐
│ Browser │────▶│ Go API Server │────▶│ Kubernetes │
│ (React) │◀────│ (Fiber, :8080) │◀────│ API Server │
└─────────────┘ └────────┬────────┘ └──────────────────┘
│
┌──────┴──────┐
│ //go:embed │
│ ui/dist/* │
└─────────────┘

Development:
Vite (:5173) --proxy /api/*--> Go API (:8080)

Production:
Go binary serves ui/dist/ at "/" and API at "/api/*"

Pages​

PageRouteDescription
Dashboard/Overview with task/session/agent/tool counts and recent tasks
Tasks/tasksCreate, monitor, and manage tasks with log streaming
Task Detail/tasks/:taskIdTask metadata, spec, status, result viewer, logs, execution timeline, trace, and approvals; fork provenance when forked
Create Task/tasks/newForm with type selector (container/AI/agent) and conditional fields
Board / Kanban/kanbanKanban board for task status and work-in-progress tracking
Live/liveLive agent grid for active task execution and status updates
Security/securityRepository scan inventory with scan status, finding counts, and manual scan actions
New Repository Scan/security/newForm for creating a RepositoryScan from provider, URL, branch, schedule, and analysis agent
Repository Security Detail/security/:repoIdThreat model editor, scan history, finding tables, and recommended remediation view
Security Finding Detail/security/findings/:findingIdEvidence, validation status, patch proposal, dismissal/reopen, and remediation PR actions
Sessions/sessionsBrowse sessions with message count and token stats
Session Detail/sessions/:sessionIdTranscript viewer plus an aggregated execution timeline across the session's tasks
Agents/agentsCard grid of agents with model and tool info
Agent Detail/agents/:agentIdFull agent configuration view
Create Agent/agents/newAgent creation form
Tools/toolsTable of built-in and custom tools
Tool Detail/tools/:toolNameTool spec with JSON Schema parameters
Chat/chatInteractive chat with SSE streaming and tool execution
Settings › Connectors/settings/connectorsLink your own accounts (for example GitHub) for agents to act as you, change a link between read-only and read-write, reconnect, and disconnect; the OAuth callback returns here
Login/loginToken input for ServiceAccount authentication

Execution events​

Task and session detail pages surface the evented execution backbone (see the Execution Events reference for the underlying APIs):

  • Timeline tab — the semantic execution event stream for a task, loaded from GET /tasks/:id/events and followed live over GET /tasks/:id/stream. Events are deduplicated by sequence, grouped by category, and filterable by category, severity, and free-text search. Redacted/truncated payloads are marked and the raw (already-redacted) payload is available behind a disclosure toggle and a copy-JSON action. Live follow stops on the terminal stream_complete frame.
  • Trace tab — an explainable, grouped view from GET /tasks/:id/trace: lifecycle summary, model requests, tool calls, child tasks (linkable), workspace, artifacts, approvals, fork provenance, and errors/warnings, with a raw-timeline fallback when no structured groups exist.
  • Approvals tab — pending high-risk approvals from GET /tasks/:id/approvals with approve/decline actions (optional reason) posted to POST /tasks/:id/approvals/:approvalID/decision. Buttons disable while a decision is in flight; conflicts (decided elsewhere/expired) surface inline.
  • Fork from a checkpoint — each timeline row offers "Fork from here", which opens a dialog seeded with that event's sequence and posts to POST /tasks/:id/fork. Forked tasks show a provenance card derived from their orka.ai/fork-source-task and orka.ai/fork-source-seq annotations.
  • Session timeline — session detail aggregates events across the session's tasks from GET /sessions/:id/events / GET /sessions/:id/stream, with each row linking to its originating task.

These surfaces hide gracefully (with a clear message) when execution event storage is not enabled on the server (501 Not Implemented).

Authentication​

The UI uses ServiceAccount bearer tokens stored in localStorage:

  1. CLI login: orka login extracts the OIDC token from kubeconfig and opens the browser with #token=<token>
  2. Manual login: Paste a ServiceAccount token on the login page
  3. Token creation: kubectl create token orka-client -n orka-system

All API requests include Authorization: Bearer <token>.

Features​

  • Dark/light theme: Toggle with localStorage persistence
  • Namespace selector: Filter all views by Kubernetes namespace
  • Security workflow: Manage repository scans, edit threat models, triage findings, validate/reproduce issues, generate patch proposals, and open remediation PRs
  • Skeleton loaders: Loading states for all list/detail pages
  • Error handling: Global error boundary, toast notifications, 401 redirect
  • Responsive design: Mobile-responsive sidebar, tables, and cards
  • Auto-refresh: TanStack Query refetchInterval for live status updates
  • Live event streams: SSE-backed task/session execution timelines that reconnect from the last sequence and recover history after refresh
  • Cursor pagination: Kubernetes-style continue token pagination

Development​

# Install dependencies
make ui-install # or: cd ui && bun install

# Run dev server (port 5173, proxies /api to :8080)
make ui-dev # or: cd ui && bun run dev

# Build for production
make ui-build # or: cd ui && bun run build

# Run tests
make ui-test # or: cd ui && bun run test

# Run tests with coverage
make ui-test-coverage # or: cd ui && bun run test:coverage

# Lint
make ui-lint # or: cd ui && bun run lint

Directory structure​

ui/
├── index.html
├── package.json
├── vite.config.ts
├── components.json # shadcn/ui config
├── src/
│ ├── main.tsx # App entry
│ ├── app.tsx # Root component with providers
│ ├── index.css # Tailwind imports
│ ├── routeTree.gen.ts # TanStack Router generated
│ ├── lib/
│ │ ├── api-client.ts # Fetch wrapper with auth
│ │ └── utils.ts # cn() helper
│ ├── schemas/ # Zod schemas matching Go API types
│ │ ├── agent.ts
│ │ ├── chat.ts
│ │ ├── security.ts # RepositoryScan, findings, scan runs, patch proposals
│ │ ├── session.ts
│ │ ├── task.ts
│ │ └── tool.ts
│ ├── stores/
│ │ ├── auth.ts # Zustand: token, user info
│ │ ├── chat.ts # Zustand: chat state
│ │ └── ui.ts # Zustand: sidebar, theme, namespace
│ ├── hooks/ # TanStack Query hooks per resource
│ │ ├── use-agents.ts
│ │ ├── use-chat.ts
│ │ ├── use-security.ts # Repository security API hooks
│ │ ├── use-sessions.ts
│ │ ├── use-tasks.ts
│ │ └── use-tools.ts
│ ├── components/
│ │ ├── ui/ # shadcn/ui primitives
│ │ ├── layout/ # Sidebar, header, root layout
│ │ ├── tasks/ # Task list/detail, Kanban board, live agent grid
│ │ ├── events/ # Execution event timeline, trace, severity primitives
│ │ ├── security/ # Repository scans, threat models, findings, patch proposals
│ │ ├── sessions/ # Session list, detail, transcript
│ │ ├── agents/ # Agent list, detail, create form
│ │ ├── tools/ # Tool list, detail
│ │ ├── chat/ # Chat interface
│ │ └── dashboard/ # Overview, stats cards
│ ├── routes/ # File-based TanStack Router routes
│ │ ├── index.tsx # Dashboard
│ │ ├── chat.tsx
│ │ ├── kanban.tsx # Board / Kanban
│ │ ├── live.tsx # Live agent grid
│ │ ├── security/
│ │ │ ├── index.tsx # /security
│ │ │ ├── new.tsx # /security/new
│ │ │ ├── $repoId.tsx # /security/:repoId
│ │ │ └── findings/
│ │ │ └── $findingId.tsx # /security/findings/:findingId
│ │ ├── tasks/
│ │ ├── sessions/
│ │ ├── agents/
│ │ └── tools/
│ └── test/ # Test utilities and setup
└── dist/ # Vite build output (gitignored)

Embedding​

The UI is embedded into the Go binary via //go:embed:

// internal/uiembed/embed.go
//go:embed all:dist
var distFS embed.FS

func FS() fs.FS { ... }

The Fiber server serves embedded static assets at / with fallback to index.html for client-side routing.