Use the browser
Run the browser workbench for shared conversations, files, Git changes, terminals, and configuration.
The browser is Harness UI's collaborative playground for individuals and trusted small teams. It shares the same HarnessUiApp as the terminal, with conversations, execution controls, setup, provider accounts, configuration, and Project readiness. It is not Service Console and does not provide separate participant permissions or tenant isolation.
Start the server, open its printed login link, connect a model, and send a first prompt. Keep the server process running while you work. Review authentication before sharing the instance.
Start the server
The browser includes guided setup, shared conversations and drafts, saved history, live output, pending decisions, configuration and native Host Files/Git/terminal panels. Chat is the main view; Files and Git open in the side drawer, Terminal below it. Git viewing needs an installed Git executable, and native PTYs need a POSIX Host. Comment controls are currently disabled, although saved backend comments remain available through the API.
a13n-harness-ui webui # 127.0.0.1:8765, generated per-process API key
a13n-harness-ui webui --host 127.0.0.1 --port 9000
a13n-harness-ui webui --no-share-computer # Opt out of native computer sharingNative Files, Git Changes, and Terminal access is enabled by default. These panels use the server account or container mounts, not the Agent's selected Environment. Use --no-share-computer to disable them without changing shared chat, drafts, or page presence. Git changes in the workbench are read-only; use a deliberate shell action for Git mutations. Presence and shared drafts are live state, not saved continuation.
Markdown files open with Preview selected and expose Preview and Text as explicit buttons; the preview renders the current local buffer, so unsaved edits can be checked before saving. File operations are compact buttons, and Add to chat is the single file-context action: it adds the selected source lines when the text editor has a selection, otherwise the complete reviewed file. It does not send the composer. Same-instance Host-file links in assistant Markdown open the Files drawer on the current page. WebUI root Agents receive the supported relative link shape in their per-input surface guidance: /threads/{root_thread_id}?native=files&native_path={URL-encoded absolute Host path}. Bare Host paths and direct Files API URLs are not browser file links; external Markdown links continue to open separately.
Observe Memory
The Memory button in the bottom-left navigation opens an observation-only workspace when Memory is enabled. Global memory is separate from Project scopes. The center reuses conversation history, live tool activity and Inspect & usage, but has no input area or manual execution controls. Each automatic organization Run starts with fresh model context while previous rounds and recorded usage remain visible, including after server restart.
The right panel shows current scope files, not historical snapshots. You can inspect files even before the first organization Run; opening a scope never starts one. The viewer is read-only and works without Host computer sharing. Use the existing authorized file tools or Host access if you intend to edit memory.
Memory controls stay in Settings → General. Turning off automatic organization keeps the Memory button and viewer available; turning off Memory hides the button. Neither switch deletes files or saved history.
Work with a Coordinator
Select a Project, enable Coordinator in the composer, and send an objective. This creates a Coordinator, or converts an existing ordinary conversation before sending. On narrow screens, the toggle is in Composer settings. Each Project can have several Coordinators; Goal is an independent option.
The role is permanent after creation or conversion. If sending fails afterward, the conversation remains a Coordinator and your input stays available for retry. A Coordinator requires a Project.
Alternatively, open an existing conversation's actions or Conversation details, choose Make Coordinator, and confirm. It must be idle, unarchived, project-bound and have no pending decisions. Promotion keeps its URL, history, title and settings; the role is permanent. Workers cannot be promoted, and existing conversations or earlier Sidekicks are not adopted.
Share a goal in the ordinary composer. A Coordinator can create its own workers, answer their questions and integrate verified results. A connected-nodes icon identifies the role. Click its title to open it, or the disclosure arrow to show its workers. Each worker is a normal root conversation with its own history, controls and human interaction—not a subagent. Workers appear under only their owner, not again in Running or Recent. Search still finds them as Coordinator worker. A visible worker keeps its owner reachable even if the owner was archived or falls outside the current page.
To assign work yourself, choose New worker in the Coordinator's actions. Write and send the task directly in the new conversation; the Coordinator does not relay it. Managed by · name replaces the Coordinator toggle and fixes the Project. Before creation, its remove button changes the draft to an independent conversation without losing your message, attachments or selections. After creation the label is fixed, even if sending fails. Uncertain creation keeps the assignment locked until you inspect the retained conversation. The same owner label remains in existing worker composers.
Use Pause automatic follow-up / Enable automatic follow-up on each Coordinator to control automatic lifecycle notifications. This setting is stored by the backend and shared across browsers. Pausing does not hide the Coordinator or workers, remove its role or prevent manual messages and execution. New Coordinators start with follow-up enabled. Migrated Coordinators preserve the old enabled setting. Sidekick preferences choose defaults for Agent-created workers; directly created workers use the choices shown in the composer, but disabling Sidekick does not disable Coordinators or their follow-up.
Automatic follow-up attempts to notify the Coordinator when you first submit work directly to a worker, or when an owned worker finishes, fails, is cancelled or waits for input. The Coordinator inspects saved results before treating work as complete. Delivery is best effort, with no retry or restart replay. Closing the browser leaves this running; stopping the Coordinator neither stops its workers nor pauses later notifications. Question and approval deadlines still apply.
Star important conversations
Hover or focus a conversation row and click the star beside its … menu, or choose Star conversation from that menu. On touch screens the button is visible without hovering. Filled stars stay visible; click again to unstar. Stars are shared with everyone using the instance, not personal bookmarks, and survive browser changes and server restarts.
Within each Project, starred conversations stay at the top of Recent, without using its five ordinary conversation slots or being hidden behind More. Running and unread New results still take priority without duplicate rows. Star and unstar do not open the conversation or change its last-visited time. Archiving hides a starred conversation but keeps its star for restoration. Ordinary conversations and Coordinators support stars; workers remain nested under their Coordinator instead of gaining separate top-level shortcuts.
Find unfinished input
Unsent (N) at the top of the conversation sidebar links to saved conversations with unfinished shared input, even when their Projects are collapsed or they are outside the recent list. Each shortcut includes its Project name. A pencil marker labeled Unsent input also appears beside the conversation in ordinary lists, without replacing running or unread-result indicators. The shortcut section stays visible while searching or filtering the lists below it.
Opening a conversation does not dismiss the reminder. Send successfully and clear the captured input, or remove the text and selected attachments yourself; edits added concurrently remain marked. Pending and failed attachment uploads count, but whitespace and changes to composer settings do not. Archiving hides the shortcut without discarding the draft.
These are shared Thread drafts, not a personal task queue. Synchronized drafts can be rediscovered after refreshing the browser while the same server is running; server restart discards them. The separate, not-yet-created New conversation draft still opens through Home.
Agent and Model settings
The composer footer right-aligns the current Agent and Model names as a read-only summary. Use the adjacent Agent & Model settings icon to change them. Agent, Model, and Reasoning mode open their choices inside the same panel; Thinking levels and the Fast button are directly available on the overview. Each has a Use default action to restore inherited settings instead of guessing an explicit equivalent.
On phones, the panel opens as a bottom sheet. Goal, Coordinator, and Environments remain in the composer header. Use the Clear context eraser beside attachments to clear saved context.
Fast mode
Open Agent & Model settings and toggle Fast directly. The adjacent label distinguishes explicit On or Off from Default. Default follows the Model's configured Fast setting; Provider default leaves the request to the provider rather than claiming Off. On and Off explicitly request Fast or standard processing for subsequent Sends in this tab. Choose Use default to clear the override. Switching Agent or Model also clears the temporary choice and follows the newly selected Model. Fast does not change thinking, save Model configuration, or accompany steering.
The Context / Cost / Cache / Time row shows Fast On, Off, or Default from the active or saved Run's captured settings, not the next-Send selection. Default means the Model or provider decides; an unavailable capture shows a dash. This is a request setting, not confirmation of faster service. Fast may increase API cost or subscription credit usage.
Controls use the connection's native semantics: OpenAI API and Codex subscription priority processing, reviewed direct Anthropic Fast speed, or reviewed Gemini API priority processing. Unsupported or unreviewed connections disable explicit choices with a reason, while keeping Default available to clear a stale override. Claude subscription, Grok subscription, Vertex provisioned throughput, and arbitrary compatible gateways are not assumed to have the same Fast capability. Custom endpoint support and account entitlement remain the provider's responsibility; there is no automatic paid probe or fallback.
Navigate conversation inputs
The slim rail at the left of Chat has one mark per ordinary input. Hover or focus a mark to preview the input and its saved output excerpt, then select it to jump back. Steering messages remain part of their original turn rather than adding marks. On narrow screens, use Inputs to open the same directory. The directory includes saved inputs beyond the currently loaded messages; selecting one loads that history window. Load later messages and Back to latest return toward newer work without resubmitting anything.
Inputs, applied steering, and all Agent text—including progress messages and every final-answer part—stay visible in chronological order. Consecutive reasoning, tools, and other execution activity between those messages form separate Execution details sections, each collapsed by default even while work is running. Expand a section to inspect only that stretch of execution; on mobile, it opens a full-screen reader. Each header counts its own loaded tool calls, not the whole turn.
If part of a saved turn is not loaded, Load earlier messages in this turn appears directly in the conversation. It loads the missing messages and execution activity without requiring you to open details; failures offer an explicit retry. Pending questions and approvals also remain actionable outside the disclosures. Navigation and expansion are personal display choices, not evidence of successful execution or changes to the Agent's context or another participant's view.
Pending questions, approvals, and external results
The pending-decision form handles structured questions, generic tool approvals, and externally supplied tool results. Shell approvals show the risk assessment and reason before the command, working directory, and selected mount. Environment variable values are hidden in argument previews. Other approvals show the tool, arguments, and available review context without requiring a tool-specific form.
For a single approval, choose Approve once or Deny, optionally entering a denial reason first. Edit arguments appears only when the request permits replacements; bound shell approvals must keep their original arguments. To change such a command, deny it with an explanation and let the Agent propose another. Arguments omitted by the server cannot be approved from the form; missing risk assessments alone do not prevent a decision. Approval is not confirmation that execution succeeded.
Multiple or mixed requests must be answered together using Submit responses. Provide a result accepts the actual external tool result as JSON; it does not execute that tool in your browser. Enter null explicitly if that is the intended result—an empty editor is not a result. No approval is selected automatically. If submission acknowledgement is lost, inspect the current request instead of assuming failure; the browser never resends the decision automatically.
Questions and approval timeouts
New pending root questions, approvals, and external-result requests share one server-owned response window per batch, controlled by tools.interaction_timeout_seconds (default 120 seconds). The workbench displays the remaining time. Submit the complete form before it expires; partial selections and typed but unsubmitted answers are not sent to the Agent.
On timeout, the server continues with explicit failed results: unanswered questions tell the Agent to proceed with reasonable assumptions where possible, and approvals are denied, never automatically granted. Switching conversations, refreshing, opening another browser, or closing the page does not reset or stop the timer. Another participant can answer first.
Stopping the server or archiving the conversation cancels its pending timer. Restart does not replay elapsed deadlines: questions retained from an earlier process remain available for a manual answer without a countdown. If a timeout response fails to start or save, inspect the reported operation before manually retrying; the App does not repeatedly submit it. Terminal CLI questions retain their separate per-question countdown.
Interactive MCP tool results
Opted-in MCP Apps appear inline beside the real tool result and can remain interactive after the assistant finishes. Saved history executes no App HTML until Open App. Use Activate interactions for current-policy-checked server operations; tool approvals, selected context, message confirmation and external-link confirmation stay in the trusted Host card outside the iframe. Opening does not repeat a tool call, and closing a View does not discard its server connection. The Apps guide covers setup, lifetime, limitations and the required separate sandbox origin for remote deployments.
Install as an app
Open Settings → General → Install Harness UI to install the workbench in its own window. If the browser offers an install prompt, choose Install app. Otherwise use its Install app or Add to Home Screen option when available. On iPhone or iPad, open the page in Safari and choose Share → Add to Home Screen. On Mac, Safari offers File → Add to Dock. Browser support and menu wording vary; ordinary browser access remains available.
Installation requires HTTPS or a local loopback address such as localhost or 127.0.0.1. A phone accessing a server by its LAN IP over plain HTTP does not receive the same installation guarantees. Keep the server address stable: changing its scheme, hostname, or port changes the browser origin and may require a new installation and login.
The installed app requires a reachable Harness UI server. Enter the instance key if requested, and enable background notifications separately for alerts while it is closed. Save private editor changes before reloading; installation adds no offline execution or editor recovery.
Restart or update the server
Stop WebUI normally with SIGTERM (or Ctrl+C), wait for the process to exit, then start it again with the same data directory. No preparation request or settings action is required. For an update, install the new package after the old process exits and before starting the replacement.
During graceful shutdown the App stops new input and gives active model/tool batches time to reach a safe continuation boundary. It saves root and child checkpoints, finalizes their Environments, and only then commits a restart handoff. On the next start it consumes that handoff once, reconstructs compatible tasks into fresh Runs, and continues without resending your prompt or replaying the saved tool batch. Reconnecting browsers only fetch current state.
shutdown_timeout_seconds (60 seconds by default) bounds the safe-boundary wait, not total process exit. If a model/tool batch cannot finish within that interval, or checkpoint/Environment finalization fails, the batch is not armed for automatic recovery. Cancellation and cleanup still need to finish. Give the supervisor enough time for those steps; do not start the replacement while the old process is still executing.
Automatic continuation requires a successful graceful shutdown and compatible reconstruction. After a forced kill or failed recovery, inspect logs and saved history before retrying uncertain work. Pending decisions remain unanswered. Native terminals, old shell handles, unsent drafts and unsaved editors are not restored.
Server logs and shutdown
The foreground server reports startup, successful readiness, API response status and cleanup progress using the configured log_level and log_format (pretty or json). The default INFO level shows normal API activity; static assets and successful health probes are DEBUG. API records identify route templates, status and time to response headers, not request bodies, access keys, query values or native file paths. Warnings also include the application error code, a safe fixed reason when known, and available generated Thread/receipt/Run identifiers. For example, thread_history_continuation_changed (transcript 400) and thread_continuation_conflict (tasks 409) both mean the selected saved continuation changed before that read; refresh the conversation. Other failures retain their own codes. Dynamic error text is kept in the API response rather than copied into logs.
For object_payload_incompatible, inspect the accompanying storage warning: it identifies the object kind and digest, schema/codec versions, expected payload model, and up to eight validation errors with field locations and error types. Arbitrary mapping keys are masked; field values and dynamic error messages are omitted. Use this evidence to diagnose compatibility rather than clearing your data directory. Legacy model context_window inputs remain readable as context_window_tokens without rewriting existing files or snapshots.
A printed login URL precedes startup; WebUI ready confirms the listener started successfully.
Press Ctrl+C once, or send SIGTERM, to stop. The server reports Stopping WebUI, ends browser event streams before draining HTTP connections, closes WebSockets, and lets the App clean up its terminal sessions, active Runs and storage. WebUI stopped confirms normal cleanup completed. Browser disconnection alone does not stop Runs or terminal sessions. The connection-drain timeout is a fallback, not a hard deadline for trusted Python cleanup. Slow shutdown continues to report elapsed waiting time; DEBUG adds the App cleanup stages (admitted operations, terminal sessions, root/child Runs and subscriptions). Raising the log level to WARNING intentionally hides ordinary progress.
If the browser loses its server connection, one compact Connection interrupted notice replaces repeated connection errors across panels. It reconnects automatically; Retry now skips the current retry delay. If the server was stopped, restart it first. Other actionable errors remain visible. This is not an offline mode: reconnecting refreshes observations and never replays a failed save or prompt submission.
Configure the workbench
On a fresh installation, the browser opens a three-step setup wizard automatically:
- Connect a Codex or Grok account inline, reuse an available account, or save a provider API key. Device login shows a verification link and copyable code; browser callback login is an advanced option requiring access to the server's loopback listener. Credentials are shared by this server, separately from your browser's instance login key. A new API key is saved immediately, even if you leave setup later.
- Choose a model from the installed release's suggestions, or enter an API provider model ID and endpoint. Reviewed defaults cover reasoning, context, and native tools; advanced controls remain available. These are suggestions, not a model-entitlement test.
- Choose your workspace: Full Control runs as the Host account without isolation; Sandbox requires a successful explicit readiness check. Optionally enter an existing server Project directory, or leave it blank for a projectless conversation. Review the configuration, then choose Save and start chatting.
Setup opens one empty first conversation and focuses its composer. It never sends a prompt or makes a model-request test. Set up later retains your nonsecret draft without reopening the wizard on every navigation. Refresh and authorization in another tab preserve your choices; secret inputs are not browser-persisted. If a save response is lost, use Check saved setup and open conversation before retrying. Partial or changed files remain explicit and are not treated as a completed save.
Existing installations keep their conversations and configuration. General → Setup & diagnostics offers focused repair rather than reinitialization. Open Settings for General defaults, Agents & models, Capabilities, Environments, Projects, Accounts & API keys, MCP connections, and Advanced configuration. Later provider connection uses the same flow under Accounts & API keys.
Capabilities enables installed capabilities for a selected Agent after Save changes; it is not a global toggle. Reusable agent plugin configurations remain distinct. Environments shows remote Devices, configured profiles, built-in read-only environments, and installed providers. Configure opens a profile draft for an available provider; provider-specific adapter/settings remain in the configuration file. Installing packages happens on the server, not through these controls.
Advanced supports configuration creation, checking, saving and deletion. Task-specific Add actions open drafts directly; unsaved drafts remain available in their relevant lists. Save changes already validates the configuration, so Check configuration is optional. Common fields and the advanced YAML editor share one local draft. Edits survive navigation and access-key replacement in the current tab, but not a reload. Publication is a complete-file, last-write-wins operation; an observed external change never silently overwrites a dirty draft. Validation does not publish, and active Runs keep their captured configuration. MCP source content is not readable through this API: replacing it explicitly replaces every resource and unseen field in that file.
Projects edits server directories and defaults directly, with a separate saved-default preview and per-axis provenance. Each folder has its own row with add/remove controls. Browse lets you navigate server directories one level at a time, go to a parent or entered path, and choose Use this directory; selection stays in the draft until you save. With --no-share-computer, enter paths manually instead. Saved Project defaults and folders initialize new conversations. Existing conversations keep their saved roots unless you explicitly update their next-Run Environment selections. Default, None and Custom list selections remain distinct. Preview does not include unsaved source changes or execute a model. The top-right header automatically shows a generated collaboration name on first entry. Click it to change the name; Save name remembers it in this browser and updates live presence and composer labels. The online indicator opens the per-tab participant directory. This profile is not provider login or an authenticated identity.
Add or forget a working environment
In Settings → Environments, add a Device connection with its identity, HTTP endpoint or reverse WebSocket transport, and credential reference. Check connection reads the live Device descriptor; saving a connection does not require the Device to be online. This resource can be reused with different working directories and aliases.
In Projects or Configuration → Change next Run selections, use Add environment, select the Device, and enter a known absolute working directory or browse the online Device. Use this directory updates only the draft. Choose a default environment explicitly when adding or removing the selected default, then save. A Project can combine local folders and remote environments, or use only remote environments; it cannot remove its final working environment. Device directory browsing remains available independently of native computer sharing.
Use Forget on an unused Device or custom profile to remove its local configuration, including when the Device is offline or the provider is no longer installed. The dialog lists current configuration references and links to their editors. Repair those defaults first, then return and forget the resource. This does not delete remote data, uninstall a provider, or remove conversation history. Built-in environments cannot be forgotten.
Existing conversations keep their saved choices. A removed resource appears as Not configured, not as a silently substituted environment. Open Conversation details → Configuration → Change next Run selections, remove or replace the missing environment, select a replacement default if necessary, and save. These changes apply to future Runs; the captured configuration and continuation of earlier Runs remain unchanged.
Files, Changes, and Terminal panels still address the listener Host. Selecting a Device does not turn them into remote panels, and a Device working directory is not a filesystem sandbox. See Device configuration and removal for file-based setup.
Environments for subsequent Runs
Open Environments in the composer to edit local mode, directories, remote bindings and the default working location together. Local · Harness server → Local mode offers Sandbox, Full Control and configured profiles, including in an existing conversation. Follow conversation local mode inherits the saved local profile. Closing without applying discards the draft; Use conversation defaults clears all temporary overrides. Full Control runs as the server's Host account; it is not a sandbox. Sandbox requires the Host's supported isolation launcher and native runtime and fails explicitly if unavailable, without switching to Full Control. The Host establishes that boundary; the Device daemon does not enforce Project roots as an access policy.
An explicit choice is sent with each Run you start from that tab until you change it or choose Default. It does not rewrite the conversation's defaults, affect another participant's selection, or change an active Run. While work is running, the picker prepares the next Send; Steer only adds instructions. Answering a deferred question or its automatic timeout retains the suspended Run's selected environment. New subagents inherit the captured environment; resumed subagents keep their own conversation configuration. Switching modes does not copy or isolate your project files or conversation history.
Open Configuration to distinguish saved conversation defaults from the environment captured by a Run. An unavailable custom profile remains visible and must be explicitly replaced. An unsent new-conversation draft retains its choice across reloads; an existing conversation's override is private to the current tab.
Thinking for the next Run
Open Agent & Model settings → Thinking in the composer. Default shows the selected Model's configured thinking and inherits its settings unchanged. The menu comes from the server's model-aware controls: effort levels and token-budget presets depend on the model and installed adapter. Off appears only where supported; minimal effort does not necessarily mean Off. Unknown models keep Default and explain why overrides are unavailable.
Your explicit choice stays private to the current tab and is sent with the next Run, not with steering. Selecting another Agent or Model clears it. It does not edit Model settings or persist a Thread preference. Running work keeps its captured selection; inspect Configuration for the requested thinking captured for that Run. Thinking controls do not change the output-token limit. A disabled budget or custom-settings conflict must be resolved in Model configuration rather than silently reduced or ignored.
New results in this browser
Conversations you open or start in this browser are followed automatically. When a Run saves a successful result you have not read, its sidebar row gains a New result dot. Each Project groups Running, New results, and Recent conversations; unread results remain reachable even outside the five recent rows. Collapsed Projects show the number of conversations with new results. Multiple completions count once per conversation, and later running or failed work does not erase an unread success.
The dot clears when the saved conversation is visible in a focused browser tab and you reach the bottom of its history. Merely selecting the conversation or receiving live text is not enough. Reading an older saved snapshot cannot clear a newer result. Archived conversations show their dots on Archived, not in ordinary Project counts.
These reminders are personal to this browser and site address, shared across its tabs through IndexedDB. Reloading or reopening WebUI refreshes followed conversations independently of sidebar pagination, including results saved while the browser was closed or the server restarted. First visits treat existing results as historical; unopened collaborators' conversations do not all become unread. Clearing site data removes your follow/read state. If browser storage or refresh fails, an explicit warning explains the limitation and offers retry; existing reminders remain visible.
This does not require desktop-notification permission and does not add closed-page push delivery. Live task notices below remain separate; reopening restores dots rather than replaying old notification banners.
Task notifications
Background notifications can reach Android Chrome after you close WebUI or lock your phone. Use a stable HTTPS address, including the same port you normally use to log in. The Harness UI server must stay running and have outbound access to your browser's push service. No separate push account or manually configured VAPID key is required.
- Open Settings → Notifications on the device that should receive alerts.
- Choose Allow notifications or Enable background notifications, then accept the browser prompt if shown. The initial Enable task notifications prompt can also set this up. Existing browser permission alone does not enable background delivery after an upgrade.
- Check that Background delivery says Enabled on this device, then choose Send test notification.
- Keep any WebUI page visible to mark this device active. Start a task, close WebUI, and check the resulting system notification. Clicking it opens the matching conversation; ordinary login may still be required.
Enable this independently on each device. On Android, allow both this site's notifications and Chrome's system notifications. Force-stopping Chrome, battery restrictions, Do Not Disturb, network loss, or vendor push-service reachability can prevent or delay alerts. On iPhone or iPad, notifications require iOS/iPadOS 16.4 or later and a Home Screen web app, not a regular Chrome or Safari tab. In Chrome, choose Share → Add to Home Screen → Add, then open Harness UI from that icon and enable notifications inside the app. If Chrome does not offer this action, open the same address in Safari to add it. Manage permission for the Home Screen app in the device's notification settings; changing Chrome's app-level permission alone does not enable website push. Browser support varies; remote plain HTTP is not supported. Loopback addresses can be used for local browser development.
Notices cover completion, failure, and requests for input across all root conversations, including ones never opened on this device. They contain actual reply/question/failure previews without an additional model call. Previews may appear on your lock screen. Archived or deleted conversations do not generate push alerts. System notifications are sent only to opted-in devices active within the last six hours. Keeping any WebUI page visible renews this window roughly every minute; it does not need keyboard/mouse activity or focus. After six hours without a visible page, open WebUI again to resume eligibility.
Every open page also shows in-app notices, including for the conversation you are viewing. These have no six-hour or visit-history restriction. System push and in-app notices may appear together. Web Push is the only system-notification path: if it is unsupported or its provider cannot be reached, only in-app notices remain. There is no local system-notification fallback.
After upgrading, reload any previously open WebUI pages. Existing subscriptions and signing keys are retained, but old Thread interest lists are removed. Devices become eligible when a visible updated page first reports activity; registration synchronization alone does not count as activity.
If enabling notifications reports Browser push registration failed, the browser failed to obtain a subscription before it could be saved to Harness UI. The error keeps the original browser detail and distinguishes this stage from server delivery. For Android Chrome push-service errors, check Google Play services and the device's push-service connectivity, including VPN or firewall restrictions; opening the WebUI successfully is not a push connectivity test. Compare Wi-Fi and mobile data, then explicitly retry registration. Avoid clearing browser storage as a first step because it also removes private drafts and preferences.
The test reports whether the push service accepted the message, not whether your device displayed it. If no alert appears, check site permission, system notification settings, and network access. On macOS, check System Settings → Notifications and Focus. Enabled on this device means the subscription was synchronized, not that delivery was confirmed. A stored subscription starts as Checking subscription…; a failed refresh or test shows Subscription needs attention, rather than continuing to claim enabled delivery. Foreground return and network reconnection retry synchronization. Reconnect background notifications replaces a rejected/expired endpoint and repairs a changed server signing key. Subscription registrations survive server restart, but unmaintained registrations expire after 90 days without registration refresh or activity. This retention period is separate from the six-hour delivery window.
Turn off Enable browser notifications to remove this browser's subscription and stop permission reminders without disabling in-app notices or affecting other devices. Logging out also attempts cleanup. If both browser and server cleanup fail, use the site's browser notification permissions to block delivery. Clearing browser storage is not a server-side unsubscribe; turn notifications off first when possible.
Push is best effort, not a durable notification inbox. The server uses a bounded memory queue and limited retries; shutdown or provider failure can lose reminders. Reopening WebUI does not replay old completions. Push does not alter saved history, browser-local new-result dots, or the lifetime of the agent's work. Back up the server data root securely to retain its signing identity and subscriptions.
Work in a conversation
Use Add project at the top of the sidebar to save a name and server directory; additional roots are optional. It creates only the Project, not an empty conversation. Expand a Project to see its five most recently updated root conversations. Show more loads the next page for that Project only; collapsing a group retains its loaded pages. Without a project and Unavailable projects keep unassigned conversations and those with removed Project references accessible.
Drag the handle beside a Project heading to move the whole group. For keyboard ordering, focus the handle, press Space, use Up/Down, and press Enter to save or Escape to cancel. The Project menu also offers Rename project, Move up/down, and Reset project order. Rename changes the display name, not the Project ID, directories, or conversations; save or discard existing settings edits first. By default, Projects whose first directory matches the server's current working directory appear first. Manual ordering takes precedence, and Reset restores that default. Newly generated setup Projects use the folder name instead of a generic label; existing saved names are preserved. Project ordering and expansion are remembered only in this browser; they do not edit server configuration or affect collaborators. Active conversations stay above recent ones. When an operation ends, its navigation touch time is refreshed so recently finished work is easy to find; progress and checkpoints do not continuously reorder the list. Conversations cannot be manually reordered or dragged to another Project. Search queries all saved root conversations, including unloaded pages, and temporarily replaces the groups. Include archived applies to both views.
Home and the + beside every Project share one New conversation draft. Clicking + changes Project without clearing the prompt or your explicit Agent, Model, and Environment choices. The text and choices are saved in this browser and restored after navigation, reload, or reopening; delete the input when you want to start over. This is one browser-local slot, not a list of saved conversations or live cross-tab editing. Local file bytes survive navigation only: after a reload, remove unavailable attachment markers and attach the files again. If browser storage is unavailable, a warning asks you to keep the tab open. No server Thread is created until Send. A positive submission receipt clears the persisted New slot; an uncertain result keeps the input and requires outcome review, never automatic resubmission. Project selection stays locked while a creation outcome is unresolved. A direct Thread link opens that saved conversation. If the selected conversation is older than the loaded pages, a labeled selected row keeps it visible without loading every intervening page. Each conversation row's … menu contains Rename conversation, Share conversation, and Conversation details. Project settings in the Project heading's menu edits the Project itself, not a Thread. Archived conversations keep their history and can be restored.
The shared CodeMirror editor shows collaborator cursors and synchronization status. Enter sends; Shift+Enter adds a line. Ctrl+Enter and Cmd+Enter still send, and input-method composition never sends a message. The compact editor keeps a fixed height and scrolls longer prompts internally. Accepted steering appears as a dismissible status in the message stream for five seconds, not inside the editor. On phones the editor starts at one-line height and stays within the visible viewport without replacing the shared editor. Send is enabled only after this browser's pending edits have synchronized. Attach files, clipboard images, and dropped files insert atomic filename controls at the cursor/drop position, alongside text. Images show thumbnails from authenticated Thread bytes. Backspace/Delete, selection, cut/paste within the same draft, and undo/redo preserve attachment identity; typing or pasting a visible label as ordinary text does not attach a file. Upload positions are reserved immediately. Pending or failed uploads block Send; click a failed upload to retry in its originating tab, or remove it. Uploads and immutable captured context are Thread-scoped, with metadata and original-byte download available to collaborators. Click an editor attachment to inspect retained text or a larger image. Submitted input keeps the authored text/attachment order in live and saved messages; expand its compact attachment control for metadata and original bytes. Remote media URLs are never loaded automatically. A positive receipt clears only the submitted snapshot; edits outside that snapshot remain. An uncertain acknowledgement preserves input and requires inspection before an explicitly new submission; nothing retries execution automatically.
While a Run is active, Next message remains editable without becoming a queue. Send as instruction targets the current operation, rather than creating a new turn. Steering preserves the same ordered text and attachments as ordinary Send. Stop addresses the exact displayed receipt. Closing a page stops observation, not execution. Questions, approvals (including allowed argument overrides) and external-result requests have complete-set response controls; stale or competing decisions are refreshed rather than represented as a second success. After a question is answered, its short title and recorded answer remain visible, including multiple selections and custom text. Expand Questions & details to revisit the full questions and options.
Saved transcript pages remain visible while replacement history loads or fails. Live output is provisional until replacement saved history arrives; stream completion alone is not proof of a saved continuation. Reasoning, tool activity, media, context operations and diagnostics remain distinguishable. Assistant prose, reasoning and summaries support Markdown tables, syntax-highlighted code and Mermaid diagrams. Summary and Compact Summary are collapsed by default. Tool-produced media is not an authored user turn; genuine uploaded media remains visible. Failed operations show a concise reason in the output area, with longer details collapsed. Retry sends Continue completing the previous task. as an ordinary new turn without changing your current draft or attachments. It does not restore the failed Run or replay its history, and it stays disabled while submission is pending or its acknowledgement is uncertain. Running conversation icons animate unless reduced motion is requested.
Adjacent tool activity is collapsed by default: Explored groups file reads and lookups, commands and process observations share a Shell group, web searches and page reads share a browsing group, and File changes summarizes modified files. Assistant messages and different activity types remain boundaries. Expand once to inspect each operation's details, output, formatted/raw arguments and results, or copy controls. Applied edits show observed before/after diffs in live output and retained history. Applied edits retain complete observed before/after content without per-edit or per-Run preview omission limits. Expanded details scroll within a bounded-height block. Content omitted by older versions remains explicitly unavailable, and older replacement arguments are labeled Requested replacement, not an applied diff. Failed, denied, interrupted and missing results remain visible in the collapsed summary, and Awaiting result means only that arguments are complete. Open on host explicitly looks up an absolute path on the WebUI server/container, preserving any private editor buffer. It does not resolve relative paths or map an Agent Environment to the Host; recorded content can differ from the file you open.
Details separates root operation, child executions, tasks/notes/usage, captured configuration and next-Run selections. Model execution, continuation publication and Environment cleanup have separate outcomes. Child review/control uses the exact parent execution. Each child inspection panel shows readable activity and its latest complete saved result, with exact-source pagination for long results. Activity previews remain explicitly bounded and are not a complete historical event log. Results truncated by earlier versions cannot be reconstructed. Applying Project defaults requires a before/after preview and the reviewed Thread version/digest. Competing configuration changes retain local selection edits and require another review, never silently replace the edit base.
Draft collaboration lives only in this App instance. In-app navigation retains the browser's editor state, and reconnecting to the same instance resynchronizes it. After server restart, explicitly rejoin the replacement draft and choose whether to restore this browser's text. Reload/browser-process-loss recovery is not promised. Display profiles are not authenticated identities; undo is local to the editor, and accepted Send establishes a new undo boundary.
Skills and work inspection
Type $ followed by a Skill name to see available Skills and their descriptions. Use Up/Down to choose and Enter or Tab to insert the name; Escape dismisses the list. Accepting a completion does not send the prompt. The reference stays editable as ordinary $name text and works in new conversations, saved conversations, and steering. Recognized references are validated against the current or active Run's catalog; unknown names remain ordinary text. No slash-command interface is added.
Tasks, Notes, Subagents, and Processes above the composer open floating inspectors without changing your draft or conversation. Processes shows the last observed background command and status, with expandable process handle, Run identity, and exit code. Its count reflects observed running handles, not all processes on the server. Foreground shell calls do not count. Run completion or loss of observation marks unfinished handles unavailable rather than exited; gaps and bounded omissions are explicit. At most 16 entries are shown from 128 retained observations. Reloading or changing conversations does not reconstruct processes from saved messages. Output stays in tool details; the inspector cannot stop or control processes.
Agent collaboration and Sidekick
WebUI root Agents receive their current Thread ID and captured Project ID/roots directly in their instructions, with no discovery call needed. They can also discover configured Projects, Agents and Models, inspect conversations with get_thread(), and start or steer independent work. Collaboration tool rows use readable action descriptions; created, continued, steered and messaged Threads have inline links that navigate without starting another Run. These are Host tools over the same App, not shell commands, API-key setup or a Skill. Resource discovery reports accepted configuration rather than model connectivity; Model credentials and raw configuration are omitted.
create_thread accepts a configured agent_id and project_id: omit the Project or use "current" to keep the source Project, use null for no Project, or select another configured Project ID. With Sidekick disabled and no explicit Agent/Project selection it retains the source conversation's settings, including its default Model; otherwise it resolves normal defaults for the selected Project/Agent. A new conversation receives the task, requesting Thread and captured Project, and explicit instructions to use send_thread_message for clarification, blockers and final findings/changes/validation. The requesting Agent uses the same tool to answer; source-attributed messages identify where to reply. The worker does not receive a copy of the source's complete history, so supply the context it needs. Optional model_id overrides the first Run's Model without editing the selected Agent; run_thread accepts the same option for a later explicit turn. Creating work does not create a child subagent relationship.
For both questions and reports, send_thread_message follows the same delivery rules: an active target receives a steering attempt addressed to its exact operation; an idle target starts a new turn. A preparing or no-longer-running operation can reject steering, and idle admission can conflict with another sender. Rejected steering never automatically starts a replacement operation. Archived conversations and child Threads cannot receive these messages; pending decisions need resolution before starting an idle target. Results mean acceptance, not completed processing or saved delivery. There is no offline queue or automatic retry; inspect the target before repeating an uncertain operation.
Sidekick is enabled by default. Settings → General → Sidekick selects a preferred Agent and/or default Model through the root configuration. Omitted configuration enables it; explicit sidekick: null keeps it disabled, including after an upgrade. Leave Agent at Inherit current agent for Model-only Sidekick; leave Model at Use agent model to keep the selected Agent's Model. The Host applies these defaults when create_thread creates independent work, even without explicit Agent/Model tool arguments. The configured Model is saved on the new Thread and applies to later messages, Send/Retry and resume. Instructions cover independent work, context, reporting and result verification. It does not auto-launch an Agent or introduce a separate execution lifecycle. Choose Disabled to remove the preference while retaining all generic collaboration tools. Saving applies to future WebUI Run captures and their newly created Threads; current Runs, existing Thread defaults and delegated children do not change.
In conversation configuration, Default model sets a persistent Model independently of the composer Run picker. Choose Follow Agent model to clear it. The picker displays Thread default when following a saved default; choosing another Model affects only that Run draft. Configuration inspection distinguishes the next Model from the captured Model used by the current or saved Run.
Saved output and comments
Browser comment creation, selection actions, highlights, menus and discussion panels are disabled pending redesign. This does not delete backend comments or their API. Feedback references captured before this change remain readable in messages and drafts. Child saved results remain available in their inspection panels without comment controls.
Read, edit and capture native code
Use the top-right Files or Changes icon to open the right drawer. On wide screens Chat stays visible beside it. Selecting a file opens its editor inside the drawer; Back to files returns to the containing directory, and Back to changes returns to the change list. Open-file tabs stay inside the drawer, show unsaved changes, and remember selection/scroll while you switch files. Drag the drawer separator or use its arrow keys to resize; this browser remembers the width. Expand drawer gives a wider code view. Loaded-path filters and list scroll survive reading and returning. A small in-tab cache remembers recent Project directories, tabs, and selected terminals. Closing the drawer returns focus to Chat without discarding buffers. Smaller screens show one work area at a time while keeping the same conversation and draft mounted. Files and Changes automatically use the current conversation's Project, starting at its first root. Additional configured roots appear as compact folder navigation. Up goes to the parent folder and is unavailable at the Project root. The visible path marks the current folder; click any ancestor, including the Project name, to return directly. Folder navigation stays above both the listing and file editor, without a separate directory-entry form. Projectless conversations show a prompt to open a Project conversation instead of silently selecting another Project. These paths belong to the server/container OS account, not the browser or an Agent's remote Environment.
Files supports directory pages, text editing, upload/download, creation, rename/move, explicit replacement uploads and confirmed deletion. Common source languages are highlighted, including content opened with Open on host. Use Wrap lines, Ctrl/Cmd+G to go to a line, and Ctrl/Cmd+S to save. Filtering covers loaded paths in the current directory, not a recursive project search. Text editors require complete NUL-free UTF-8 up to 512 KiB; binary/larger files have an explicit non-editable view. Transfers and whole-file captures support up to 10 MiB. Local unsaved buffers survive navigation and access-key replacement within the tab, but not reload or browser closure. Refresh never replaces dirty text. If another actor changes the disk revision, inspect the latest version and choose Use disk version or Keep local text before an explicit save. Lost write acknowledgements are not automatically retried. Common CRLF/LF line endings are preserved; editing mixed endings normalizes to the first style and is disclosed.
Changes separates staged HEAD/index, unstaged index/worktree and untracked new-file comparisons. Filter loaded paths, fold groups, and move between loaded comparisons or hunks. Selecting a new-file line in an unstaged or untracked diff can jump to that line in the current working file; a staged or deleted-side line is not assumed to match it. Its unified diff uses separate old/new file-line gutters, monospace code and light/dark-aware addition, deletion and hunk colors. Headers and no-newline notices remain part of the reviewed patch. Text selection reports its original patch lines for capture; displayed file numbers do not replace those coordinates. Repository, HEAD, index and diff identities remain inspectable, including rename/conflict/binary and unborn states. Git errors are not shown as clean results, and Files works outside repositories. Refresh after your native actions or return to the pane to inspect new observations; there is no recursive watcher or claim of Run-specific change attribution. There are no stage, commit, discard or worktree buttons.
Use Add to chat for a file or Add to message for a diff to capture its reviewed revision into the shared draft. Select lines first to capture only that range. Review the attachment card before sending; later file edits do not change the captured bytes. The same attachments can be sent as instructions to an active Run.
Share a native terminal
Open Terminal, then New terminal to start in the currently browsed directory. Files also offers Open terminal here for folders; this creates a new session rather than injecting cd into an existing one. Only that Project's sessions appear in the panel. Switching Projects hides and detaches the old view without ending its sessions or changing their working directories. Opening the panel alone does not start a shell, and creating one requires a Project with a configured root. Existing unassociated sessions remain available through the native API. The displayed initial directory does not follow later shell cd commands; terminal execution remains independent of the Agent's Environment.
The creating browser automatically requests control once after its first authenticated frame, provided no one else has already acquired it. Input and resizing stay disabled until the server confirms ownership, then input receives focus. Other participants see Viewing only and can use Take control or Take over input. Those actions compare the currently observed control epoch. Release control leaves the session running for other viewers. Controller dimensions follow the actual pane, while viewers retain the shared dimensions and can scroll a narrow viewport. Shell control keys stay in the terminal. Input is bounded UTF-8, with a 16 KiB per-paste browser limit; legacy binary mouse reports are not supported by the current text-input protocol.
Disconnect, opening Settings, and collapsing the panel release this connection without closing the process. Reopening automatically reconnects as a read-only viewer, unless you explicitly used Disconnect; then choose Reconnect. Up to three recent screens are retained while switching within the Project. Reconnection never repeats keystrokes or automatically takes control. The server retains at most 1 MiB of raw bytes and the emulator keeps 2,000 local scrollback lines, not a durable log. Output gaps reset decoding and disclose that the screen is built from retained raw output, not a complete screen snapshot. A slow renderer pauses its attachment rather than accumulating an unbounded output queue. Reconnect after it drains; missing bytes may no longer be available.
End session requires confirmation because it closes the shared native session and its jobs for everyone. Exited sessions remain inspectable until closed. An uncertain create/close result is not automatically replayed: refresh the session list before deciding on another action. App restart does not restore or recreate sessions. POSIX hosts support native PTY; Windows explicitly reports it unavailable while Files and Git remain independently usable.
Use Find in output (Ctrl/Cmd+F), previous/next matches, and Copy selection to inspect retained output. HTTP links open separately; unambiguous absolute path:line references open Host files. Add selection to prompt appends an attributed excerpt to the current shared draft without sending it, and Return to conversation focuses that draft. Relative or ambiguous terminal paths are not guessed.
After shell file or Git mutations, return to Files/Changes or refresh native observations. Native actions, focus returns, and Run completion also refresh observations without replacing dirty buffers. The browser tab title follows the current conversation; other pages use a13n harness ui. This retains selected paths and private dirty text. The drawer's Share explorer view link icon creates an access-key-free same-instance explorer link. The participant directory can also open an exact focused file or diff. The participant directory reports the focused conversation, native file/diff, terminal or configuration page, and Open page deliberately opens an available peer view; it never enables continuous following or moves another participant. Background tabs remain distinguishable from foreground attention.
Authentication and key retention
Startup stdout prints the ordinary URL and, only for a generated key, the key and a convenience fragment URL. The browser consumes and removes the key fragment, sends Authorization: Bearer <key> on API requests, and retains successfully used keys in same-origin localStorage. Use Log out to remove the retained key and close protected views. Static assets contain no key and need no authentication.
Key precedence is --apikey, then A13N_HARNESS_UI_API_KEY, then a fresh process key. Supplied keys are not echoed; command arguments may still be visible to the shell and operating system. Explicitly empty keys and conflicting repeated key values are rejected. --dangerous-skip-permissions disables Web authentication only, not Agent permissions or computer-sharing gates; combining it with a CLI or environment key is an error. --api-key and --dangerously-bypass-permission remain compatibility aliases.
Listener and application lifetime
Non-loopback listening grants shared instance authority on a trusted network, not tenant isolation; use external TLS when needed. The server owns the App lifetime even without browsers; Ctrl+C or SIGTERM closes it. Unauthenticated /healthz and /readyz report bounded liveness and App readiness. A fresh instance can be ready for setup before any model is configured.
TUI and WebUI processes can share one local database across compatible package upgrades. A newer migration revision alone does not reject an older compatible reader or gate an active Run's save. An older App leaves unknown newer migration history unchanged and checks that its required tables and columns remain available. Missing storage and real continuation/version conflicts still fail explicitly; schema compatibility does not share live execution ownership. Already released binaries keep their own startup checks, and incompatible payload formats cannot be made readable merely by relaxing revision validation.
Container and installed assets
The GHCR image is ghcr.io/converge-ai-labs/a13n-harness-ui: dev follows main, releases use X.Y.Z, and RCs use X.Y.Z-rc.N without advancing latest. Python and the page display RC metadata as X.Y.ZrcN. Development builds display source version 0.0.0 with a separate Git revision. For persistent configuration, data, and work mounts with loopback-only port publishing, use the repository's deploy/docker/compose/a13n-harness-ui.yaml. The image runs as UID/GID 10001:10001; bind mounts must be writable by that account. Do not remove its volumes when preserving data. Restart rotates generated keys; supply the API-key environment variable at runtime when a stable key is needed.
The browser assets ship inside the wheel. End users do not need Node.js or a separate frontend checkout. For repository development, use make webui: it builds and installs the bundled assets, then starts the foreground server with isolated configuration/data in var/harness-ui/. No manual API key is required: without a supplied CLI or environment key, stdout contains a directly usable login link. Authentication is still required. Use make webui WEBUI_ARGS='--port 9000 --no-share-computer' to forward server options; CLI_ARGS forwards global options before the subcommand. See the development guide for configuration seeding and environment overrides.
Options and ownership
See the registered webui options for listener, authentication, and compatibility aliases. Listener settings are process arguments rather than fields in root YAML. An open server owns active App work; closing a tab does not stop the server, and this is not a detached worker service.
For API clients, follow the HTTP workflow and route reference. For an in-process interface, use the Python App. For automation without a browser server, use one-shot execution.