| title | Web Dashboard |
|---|---|
| description | Local web dashboard for managing agents from the browser. |
| order | 5 |
Forge includes a local web dashboard for managing agents from the browser — no CLI needed after launch.
# Launch the dashboard
forge ui
# Specify workspace and port
forge ui --dir /path/to/workspace --port 4200
# Launch without auto-opening browser
forge ui --no-openOpens http://localhost:4200 with a full-featured SPA for the complete agent lifecycle.
The main view discovers all agents in the workspace directory and shows their status in real-time via SSE (Server-Sent Events).
| Feature | Description |
|---|---|
| Agent discovery | Auto-scans workspace for forge.yaml files |
| Start / Stop | Start and stop agents with one click |
| Daemon processes | Agents run as background daemons via forge serve — they survive UI shutdown |
| Live status | Real-time state updates (stopped, starting, running, errored) |
| Passphrase unlock | Prompts for FORGE_PASSPHRASE when agents have encrypted secrets |
| Startup error display | Shows actual error messages (e.g., missing env vars) in the agent card when startup fails, extracted from .forge/serve.log |
| Auto-rescan | Detects new agents after creation |
| Unified management | All agents (UI-started or CLI-started) get identical Start/Stop controls |
The UI manages agents as daemon processes using forge serve start / forge serve stop under the hood. This means:
- Agents survive UI shutdown — closing the dashboard does not kill running agents.
- Restart detection — restarting the UI auto-discovers running agents via
.forge/serve.jsonand TCP probing. - PID liveness verification — after
forge serve startreturns, the UI verifies the child process is still alive via PID probing and TCP port check. If the child crashed (e.g., missing env vars), the error is extracted from.forge/serve.logand displayed in the agent card. - Unified view — agents started from the CLI (
forge serve start) and agents started from the UI appear identically. There is no distinction between "UI-managed" and "CLI-managed" agents.
Click any running agent to open a chat interface that streams responses via the A2A protocol.
| Feature | Description |
|---|---|
| Streaming responses | Real-time token streaming with progress indicators |
| Markdown rendering | Code blocks, tables, lists rendered inline |
| Session history | Browse and resume previous conversations |
| Tool call visibility | See which tools the agent invokes during execution |
A multi-step wizard (web equivalent of forge init) that walks through the full agent setup:
| Step | What it does |
|---|---|
| Name | Set agent name with live slug preview |
| Provider | Select LLM provider (OpenAI, Anthropic, Gemini, Ollama, Custom) with descriptions |
| Model & Auth | Pick from provider-specific model lists; OpenAI supports API key or browser OAuth login, plus optional Organization ID for enterprise accounts |
| Channels | Select Slack/Telegram with inline token collection |
| Tools | Select builtin tools; web_search shows Tavily vs Perplexity provider choice with API key input |
| Skills | Browse registry skills by category with inline required/optional env var collection |
| Fallback | Select backup LLM providers with API keys for automatic failover |
| Auth | Select a2a auth provider (see below) |
| Egress | Review the outbound allowlist (including auth-provider-derived hosts) |
| Env & Security | Add extra env vars; set passphrase for AES-256-GCM secret encryption |
| Review | Summary of all selections before creation |
The wizard collects credentials inline at each step (matching the CLI TUI behavior) and supports all the same options: model selection, OAuth, web search providers, fallback chains, and encrypted secret storage.
The Auth step exposes the same provider chain as forge.yaml's
auth.providers[] block. Picker options:
| Option | Effect |
|---|---|
| None | Anonymous access — no auth: block written |
| OIDC (JWT) | Generic OIDC IdP (Keycloak, Auth0, Okta, Google) — collects issuer + audience |
| HTTP Verifier | Legacy — POST tokens to your own /verify endpoint |
| AWS Sigv4 (IAM) | AWS-IAM-based callers — collects region + optional audience + comma-separated allowed accounts |
| GCP Identity-Aware Proxy | Forge behind GCP LB+IAP — collects backend service ID |
| Azure AD / Entra ID | Microsoft Entra ID (single-tenant in the wizard; multi-tenant requires editing forge.yaml as a deliberate security trade-off) |
| Custom | Comment stub — edit forge.yaml yourself |
The Auth step runs before Egress, so the Egress step's review screen
displays auth-provider-derived hosts (e.g. sts.us-east-1.amazonaws.com
when AWS Sigv4 is selected) alongside the model / channel / tool / skill
hosts. The operator sees the full outbound surface for approval in one
place.
The Web UI's POST /api/create endpoint additionally filters incoming
auth settings through a closed-key whitelist (defined in
forge-core/validate/auth.go) before scaffolding — unknown keys are
silently dropped rather than written to disk.
See Authentication for the full provider reference.
Edit forge.yaml for any agent with a Monaco-based YAML editor:
| Feature | Description |
|---|---|
| Syntax highlighting | YAML language support with Monaco editor |
| Live validation | Validate config against the forge schema without saving |
| Save with validation | Server-side validation before writing to disk |
| Keyboard shortcut | Cmd/Ctrl+S to save |
| Restart integration | Restart agent after config changes |
| Fallback editor | Plain textarea if Monaco fails to load |
The Monaco editor is a tree-shaken YAML-only bundle (~615KB) built with esbuild — not the full 4MB distribution.
Browse the built-in skill registry with filtering and detail view:
| Feature | Description |
|---|---|
| Grid view | Skill cards showing name, description, category, tags |
| Category filter | Filter skills by category |
| Detail panel | Click a skill to view its full SKILL.md content |
| Env requirements | Shows required, one-of, and optional env vars per skill |
An AI-powered conversational tool for creating custom skills. Access it via the Build Skill button on any agent card, or navigate to #/skill-builder/{agent-id}.
The Skill Builder uses a workspace-level LLM that's independent of any specific agent's runtime LLM. The same configuration applies across every agent in the workspace and works before any agent has been scaffolded.
Configuration is persisted under <workspace>/.forge/:
ui.yamlholds the non-secret fields (provider,model, optionalbase_url, optionalapi_key_env)..envholds the API key value (mode0600, auto-protected by a sibling.gitignore).
The status banner above the chat panel surfaces the resolution source — workspace, user (machine-wide fallback), agent_fallback (a deprecated compat shim used when no workspace/user config exists), or unset. When unset, the banner shows a Configure button that opens the settings modal.
See Skill Builder LLM for the full configuration reference, three-tier resolution precedence, and trust-boundary rationale.
| Feature | Description |
|---|---|
| Conversational design | Describe what you want in plain language; the AI asks clarifying questions and generates the skill |
| Live streaming | LLM responses stream token-by-token via SSE |
| Artifact extraction | Automatically parses skill.md and script: code fences from the LLM response |
| SKILL.md preview | Live preview panel shows the generated SKILL.md with syntax highlighting |
| Script preview | View generated helper scripts alongside the SKILL.md |
| Validation | Server-side validation checks name format, required fields, egress domain declarations, and name uniqueness |
| One-click save | Save the validated skill directly to the agent's skills/ directory |
| Egress injection | Automatically merges declared egress_domains into forge.yaml allowlist on save |
| Env var handling | Writes user-provided env vars to .env; prompts for missing required vars after save |
- Open the Skill Builder from an agent card
- Describe the skill you want (e.g. "Create a skill that queries Jira issues")
- Iterate — the AI asks about requirements, security constraints, and env vars
- Review — inspect the generated SKILL.md and scripts in the preview panel
- Validate — check for errors and warnings before saving
- Save — writes
skills/{name}/SKILL.mdandskills/{name}/scripts/to the agent directory, merges egress domains intoforge.yaml, and writes env vars to.env - Configure — if the skill requires env vars that aren't set, the UI shows input fields to provide them and re-save
The validator enforces the SKILL.md format:
| Check | Level | Description |
|---|---|---|
| Name present | Error | name is required in frontmatter |
| Name format | Error | Must be lowercase kebab-case, max 64 characters |
| Description present | Error | description is required in frontmatter |
| YAML parse | Error | Frontmatter must be valid YAML |
| Tool sections | Warning | Body should contain ## Tool: sections |
| Category format | Warning | category should be lowercase kebab-case |
| Egress domains | Warning | Scripts referencing HTTP(S) URLs should declare them in egress_domains |
| Name uniqueness | Warning | Warns if a skill with the same name already exists in the agent |
| Method | Path | Description |
|---|---|---|
GET |
/api/skill-builder/provider |
Returns the resolved workspace-level LLM (provider, model, source, has_key, deprecation warning). Use this for first-run detection before any agent is picked. |
GET |
/api/agents/{id}/skill-builder/provider |
Same shape as above, but consults the agent-fallback tier when no workspace/user config exists. |
GET |
/api/agents/{id}/skill-builder/context |
Returns the system prompt used for skill generation |
POST |
/api/agents/{id}/skill-builder/chat |
Streams an LLM conversation via SSE (accepts messages array). Returns 400 when the workspace LLM is unset or has no resolvable API key. |
POST |
/api/agents/{id}/skill-builder/validate |
Validates a SKILL.md and optional scripts |
POST |
/api/agents/{id}/skill-builder/save |
Saves a validated skill to skills/{name}/, merges egress domains, writes env vars; returns SkillSaveResult with path, egress_added, env_configured, env_missing |
GET |
/api/settings/skill-builder |
Returns the workspace-level config + metadata for the Settings modal (source, has_key, providers list). The API key value is never echoed back. |
PUT |
/api/settings/skill-builder |
Persists provider, model, optional base_url, optional api_key_env to <workspace>/.forge/ui.yaml. When an optional api_key field is present in the body, writes it to <workspace>/.forge/.env (mode 0600) under api_key_env (or the provider default). The key value never leaks to ui.yaml. Submit an empty / omitted api_key to leave the saved value untouched. |
The dashboard is a single Go module (forge-ui) embedded into the forge binary:
forge-cli/cmd/ui.go CLI command, injects ExePath/CreateFunc/OAuthFunc/LLMStreamFunc
forge-ui/
server.go HTTP server with CORS, SPA fallback
handlers.go Dashboard API (agents, start/stop, chat, sessions)
handlers_create.go Wizard API (create, config, skills, tools, OAuth)
handlers_skill_builder.go Skill Builder API (chat, validate, save, provider)
handlers_settings.go Workspace-level settings API (skill-builder LLM)
uiconfig/ Workspace ui.yaml + .env loader; SkillBuilderLLM
resolution + atomic .env writer with auto-.gitignore
skill_builder_context.go System prompt for the Skill Designer AI
skill_validator.go SKILL.md validation and artifact extraction
process.go Process manager (exec forge serve start/stop)
discovery.go Workspace scanner (finds forge.yaml + detects running daemons)
sse.go Server-Sent Events broker
chat.go A2A chat proxy with streaming
types.go Shared types
static/dist/ Embedded frontend (Preact + HTM, no build step)
app.js SPA with hash routing
style.css Dark theme styles
monaco/ Tree-shaken YAML editor
Key design decisions:
forge-cliimportsforge-ui(not vice versa). CLI-specific logic (scaffold, config loading, OAuth flow) is injected via function callbacks, keepingforge-uiframework-agnostic.- Daemon-based lifecycle — the UI delegates to
forge serve start/stopviaexec.Command, so agents are independent OS processes that survive UI restarts. - Scanner as source of truth —
discovery.goreads.forge/serve.jsonand does a TCP probe to detect running agents. No in-memory state tracking is needed. - Version display — the sidebar footer shows the Forge version (injected via
-ldflagsat build time) and links to useforge.ai.