English | 한국어
A cross-platform Python/ttkbootstrap desktop GUI for configuring, queuing, monitoring, validating, comparing, and reporting OSWorld experiments, with provider-aware API cost tracking.
English interface in the Dark theme. The same workspace can switch to Korean without restarting.
- Generate safe OSWorld commands from text, dropdown, numeric, Boolean, file, and folder controls.
- Queue multiple experiments and monitor live completed/total and success/fail/total task counts.
- Preserve the OSWorld checkout and Python interpreter per Queue item; legacy entries infer their original checkout from the result path when possible.
- Browse, search, filter, and multi-select the 369 tasks registered in the official OSWorld task set without entering UUIDs manually.
- Pause after the current experiment, edit the pending Queue, and resume from the updated list.
- Run a configurable smoke-test subset before the full experiment and stop the Queue only when rule-based checks detect an execution-blocking failure.
- Apply paper-aligned or OSWorld-default model presets while keeping every option manually editable.
- Store OpenAI, Google, OpenRouter, LM Studio, and RunPod credentials in the operating system's secure credential store.
- Check provider connectivity and load the server's live model list directly into the editable model dropdown.
- Track per-task and cumulative API costs with actual/estimated labels, saved price snapshots, manual overrides, and optional experiment budgets.
- Export rule-based result analysis as styled Word reports.
- Save a versioned, secret-free experiment record during every run and reconstruct comparable records from existing result folders.
- Browse saved runs in Analysis / Report, filter the history, and inspect one experiment's environment, task outcomes, commands, and errors.
- Send completion or failure notifications through cross-platform SMTP email, with optional macOS Notification Center and Messages integrations.
- Switch the interface between English and Korean without losing the current form values, Queue, or console history.
- Switch between the Nord Light and Dark themes without restarting the application; the selected theme is restored on the next launch.
- Save portable, secret-free settings profiles and choose a persistent startup default.
- Launch without a preinstalled OSWorld checkout, then locate an existing copy or clone and prepare the official repository from OSWorld Setup.
The GUI is maintained independently at:
./OSWorld-gui-tool
OSWorld-gui-tool/
├── docs/screenshots/
├── pyproject.toml
├── run_gui.py
├── src/osworld_gui/
└── tests/
OSWorld does not need to be installed before the manager starts. Use Python 3.10 or newer with Tk support, then install the standalone GUI:
git clone https://github.com/issumer-ku/OSWorld-gui-tool.git
cd ./OSWorld-gui-tool
python -m pip install -e .
osworld-guiYou can also run the source checkout without installing it:
cd ./OSWorld-gui-tool
python run_gui.pyTo select an OSWorld checkout explicitly:
OSWORLD_ROOT=../OSWorld osworld-guiUse a Python distribution with Tk support if tkinter is unavailable in your
current environment.
On first launch, the manager automatically opens OSWorld Setup when no
valid checkout is configured. Enter a path, use Auto, or choose Install
OSWorld. The installer clones the official xlang-ai/OSWorld repository,
creates an isolated Python 3.10 environment, and installs requirements.txt
there. Experiments automatically use that interpreter even when the GUI itself
runs on a newer Python release. Clone and dependency-install output is streamed
to Debug Console. VMware, Docker, and other host runtimes remain separate
OSWorld prerequisites.
The manager itself is not macOS-only. Its core Python/ttkbootstrap features run on macOS, Windows, and desktop Linux, subject to the OSWorld runner and virtualization backend being available on that host.
| Capability | macOS | Windows | Linux |
|---|---|---|---|
| GUI, Queue, debug console, reports | Yes | Yes | Yes |
| Secure credential storage | Keychain | Credential Locker | Secret Service / system keyring |
| SMTP email notifications | Yes | Yes | Yes |
| Native desktop notification | Notification Center | Not currently integrated | Not currently integrated |
| Messages / iMessage | Yes | No | No |
Linux credential storage requires a usable Secret Service or other keyring
backend in the desktop session. Native Windows/Linux notification integrations
can be added independently; they are not required for experiment execution.
- If OSWorld is not connected, open OSWorld Setup to locate an existing checkout or install the official repository. The selected path is restored on later launches.
- Open API / Secrets, select a provider from the dropdown, and save its API key and optional Base URL.
- In Experiment Setup / Queue, choose a model preset and adjust the environment, model, task, agent, and execution options. Every preset starts with VMware as the local desktop environment.
- Select the VM, task metadata, configuration, and result paths with the file and folder dialogs.
- Add the experiment to the Queue. Double-click an item, or use Load / edit selected, to revise it.
- Review the generated command with Preview command.
- Start the Queue and follow task progress in the table or the live Debug Console. While an experiment is running, Run Queue becomes Pause. Pausing lets the current experiment finish before the manager waits; Resume then re-reads the current Queue and continues with the latest pending entries, including edits, additions, and removals.
- The manager first runs the configured smoke-test tasks. It stops the Queue and sends a notification if it finds a fatal failure.
- When all remaining tasks finish, the manager can quietly save a styled Word report without opening an external application. Control this per Queue item with Auto-Generate Report under Experiment.
The toolbar above Experiment provides Save Settings File, Load Settings File, Reset, and Set Current as Default. Reset restores the experiment form, runner options, additional JSON, notification inputs, API entry fields, and debug-console font size to program defaults. It clears an explicit startup default but deliberately preserves Queue entries and API keys in the operating-system credential store. A portable JSON profile stores the current form, every runner option, additional JSON, Queue, notification fields, UI language, Light/Dark theme, and provider Base URLs. API keys and SMTP passwords are deliberately excluded and remain in the operating system's credential store.
Use the Theme dropdown in the header to switch between Nord Light and Dark without restarting. The selected theme is restored on the next launch and is included in portable settings profiles.
The current form is also saved on a normal program exit, so it is restored on the next launch instead of resetting to a model preset. Set current as default creates an explicit startup template; once set, that template takes priority over the most recently used form until it is replaced or a profile without a default is loaded.
The Debug Console displays the generated command, runner stdout/stderr, process ID, exit code, Queue progress, and lifecycle status with timestamps. Commands, status messages, warnings, and errors use distinct colors.
- Disable Auto-scroll to inspect earlier output while an experiment runs.
- Use Clear console, Copy all, or Save log… to manage the current session output.
- Use the Font size −/+ controls to resize console text immediately; the selected size is restored on the next launch.
- Console history survives an English/Korean UI switch.
- Python child-process buffering is disabled so output appears as promptly as the runner emits it.
The Analysis / Report tab appears immediately after Experiment Setup / Queue. Its upper pane lists automatically saved and reconstructed experiment records with local start time, status, provider, model, success/fail/total, success rate, record source, and result folder. Search matches experiment name, provider, model, and result path; the adjacent filter limits the list by running, completed, failed, stopped, or interrupted status. Select one record for its complete details, or select two or three records for A/B/C comparison. Click any history column heading to sort ascending or descending; the active column displays an arrow indicating the current direction.
Selecting one record fills the detail tabs:
- Overview shows timestamps, elapsed time, counts and percentages, runner environment, platform details, record provenance, and configuration/task-set fingerprints.
- Task Outcomes shows domain-qualified task IDs, full instructions, score, failure reason, and termination metadata. Its own text and status filters can narrow large task sets.
- Configuration / Commands / Errors shows the secret-masked runner options, executed commands, recorded errors, terminal message, and recovery metadata.
- API Cost shows requests, tokens, pricing basis, per-task cost, anomalies, and the saved price source. With multiple records selected, it compares the original cost snapshots side by side.
Collapse the history or selected-details block with − and restore it with
+; the visible block uses the released space. Open Result Folder opens
the selected run in Finder, File Explorer, or the Linux file manager.
The list refreshes after background restoration and while Queue progress is
being recorded.
With two or three records selected, Comparison shows success/fail/total and
success/failure percentages side by side in a bordered row-and-column grid. A configuration-difference table
identifies provider, model, runner, runner-option, operating-system,
architecture, and Python changes. Task identity uses domain/task-id; a task
JSON hash mismatch is reported separately from experiment-setting changes.
The task-change table uses an A/B/C status pattern and can filter common successes, common failures, regressions, improvements, changed outcomes, missing or incomplete tasks, task-definition changes, A-success/B-failure, A-failure/B-success, and failures from each selected run. Tasks absent from one run's original plan are shown as Not planned, rather than being conflated with a missing result.
Choose the run whose settings should seed a rerun, then use Prepare selected rerun or Prepare all shown. The manager transfers the chosen domain-qualified tasks and the source run's non-secret options to Experiment Setup / Queue without starting them. Review the generated name, active OSWorld path, VM, model, and other options before adding the experiment to the Queue. Credential placeholders are never copied from history records.
Use Word report with one selected record to create a detailed report, or with two or three records to create a comparison report. Comparison reports include the side-by-side summary, environment and configuration differences, task-level transitions, and each run's successful and failed task lists. The report language follows the current UI language.
Experiment records can be moved between computers as .oswexp packages.
Portable export contains the versioned records used for comparison;
Full diagnostic additionally includes sanitized event history and task
termination details. Both modes exclude credentials, screenshots, videos, and
general runtime logs. Import validates package paths and checksums, indexes new
records locally, and skips records whose experiment ID already exists.
Smoke-test evaluation is automatic and rule-based. The manager checks:
- nonzero runner exit codes and process crashes;
- missing or invalid
result.txtfiles; - adapter exceptions and API authentication/connection failures recorded in
termination.jsonorruntime.log; - fatal runtime patterns such as uncaught tracebacks and segmentation faults.
Valid 0.0 scores, stagnation, and max_steps are task-performance
outcomes. They do not stop the Queue, even when a runner records stagnation
under the broad model_error provenance.
The report generator aggregates completion counts, mean success rate, missing
results, termination causes, detected errors, commands, and complete successful
and failed task lists into a styled python-docx document. The document is
saved directly without launching Microsoft Word or another external application.
Auto-Generate Report is stored with each Queue item. Reports created from Analysis / Report use the current UI language and are also saved quietly.
In the Model runner-options tab, Check next to API Base URL performs a read-only request against the provider's models endpoint. Load Models populates the editable model dropdown, while Refresh requests a fresh list from the server. Changing the AI provider updates the Base URL to its saved or official default endpoint. Connection success or failure and model-list results appear in the bordered Status box instead of an OK popup.
Button results throughout the manager use the same Status box whenever possible, including Queue validation, duplication/removal, reports, defaults, notifications, and provider operations. File open/save workflows retain their native dialogs and completion/error popups because the selected path is part of the result; command preview remains a dedicated non-modal window.
OpenAI, OpenRouter, LM Studio, and RunPod vLLM use their OpenAI-compatible
/models endpoint. Google uses the paginated Gemini v1beta/models endpoint
and keeps only models that support generateContent. Requests read API keys
from the operating-system credential store; keys are never added to URLs, logs,
exported settings, or source files.
The RunPod · vLLM Serverless preset selects vllm, fills
https://api.runpod.ai/v2/ENDPOINT_ID/openai/v1, and keeps the OSWorld desktop
on local VMware. Replace ENDPOINT_ID, save the RunPod account API key in the
vllm (RunPod Serverless) provider, and click Load Models to replace the
example model ID with the model actually served by the endpoint. RunPod checks
use a longer timeout to accommodate a Serverless cold start. See RunPod's
OpenAI compatibility documentation.
The RunPod · vLLM Pod preset selects the separate vllm_pod provider and
fills https://POD_ID-8000.proxy.runpod.net/v1. Expose HTTP port 8000, start
vLLM on 0.0.0.0:8000 with --api-key, replace POD_ID, and save that vLLM
server key under the separate vllm (RunPod Pod) provider. The two RunPod
credentials are intentionally independent. RunPod's HTTP proxy has a 100-second
request limit; direct TCP exposure can be used with a Base URL such as
http://PUBLIC_IP:MAPPED_PORT/v1 when longer requests are required. See the
RunPod port exposure documentation.
The Custom · Lab vLLM Server preset selects vllm_custom, keeps the local
OSWorld desktop on VMware, and fills the private-network example
http://192.168.0.100:8000/v1. Replace the address with the lab server's IP or
DNS name, then use Load Models to select the exact model ID returned by
/models. Its vllm (Custom / Lab) credential is independent from both
RunPod rows. The API key is optional for an unauthenticated internal endpoint;
when the server starts with vllm serve --api-key, save that same key here.
Use HTTPS or another protected network path when traffic crosses an untrusted
network.
The status row includes a live API Cost panel for the current task, the current Queue, and a full-experiment forecast when enough usage data is available. Cost Settings stores model-specific token, request, image, or GPU-hour rates. Auto Fill identifies the active provider and model and uses a documented machine-readable source when available; Refresh requests that source again. OpenRouter prices are loaded from its Models API. Providers without a stable pricing endpoint can use a built-in snapshot or manual rate. LM Studio and lab vLLM default to zero API charge, while an optional GPU-hour rate can represent compute cost.
Selecting a model in Runner Options also checks and saves available pricing automatically. This background price lookup does not read the operating system's credential store. Buttons and interactive controls provide hover tooltips, and English UI labels use Title Case consistently.
Each Queue item keeps a credential-free pricing snapshot. During execution the
manager incrementally reads model_usage from OSWorld traj.jsonl files and
the optional .osworld-manager/api-usage.jsonl journal. Actual provider cost
is preferred when recorded; otherwise token or compute usage is evaluated
against the snapshot. Missing usage remains not configured rather than
being reported as zero. If the projected total exceeds an experiment budget,
the Queue pauses after the current experiment.
The API Cost page under Analysis / Report shows request and token
counts, cost basis, cost per task, cost per successful task, the most expensive
task, and tasks above twice the median cost. Selecting up to three experiments
compares these values and their original pricing sources. Cost data is included
in .oswexp packages, but API keys are never included.
Controls react to the selected configuration:
- Selecting
dockerdisables the VMware.vmxfile field. - Auto beside the VMware VM field searches the active OSWorld checkout,
sibling OSWorld checkouts, and standard user virtual-machine folders for
.vmxfiles. It selects the active checkout's first match and reports the result in the Status box. - Selecting
vmwarefixes parallel environments at1, because controlling one personal VM from multiple processes can cause VM or snapshot conflicts. - A model preset limits the AI-provider dropdown to compatible providers.
- The LM Studio preset permits only
lm_studio; the RunPod Serverless preset permits onlyvllm, the RunPod Pod preset permits onlyvllm_pod, and the custom lab preset permits onlyvllm_custom. - Manual task IDs accept
UUID,UUID.json, ordomain/UUID.jsonseparated by commas, whitespace, or newlines and take precedence over the task-list JSON. - The domain dropdown is populated from the directories under the active task
configuration folder's
examplesdirectory. The current official task set includeschrome,gimp,libreoffice_calc,libreoffice_impress,libreoffice_writer,multi_apps,os,thunderbird,vlc, andvs_code, plusall. - A repeat count of two or more creates independent Queue entries and result
folders such as
experiment-run-1andexperiment-run-2.
The Tasks runner-options tab keeps the manual-ID field for advanced use and
adds Select tasks… for guided selection. The resizable picker reads only
the task IDs registered in the active checkout's official
evaluation_examples/test_all.json. JSON files that exist only in the examples
folder are ignored. The current official task set exposes 369 tasks.
- Search matches domain, UUID, and full instruction text.
- The domain filter, Select all shown, and extended single/multi-selection support fast bulk selection.
- Rows display
[domain] — shortened instruction; hovering a row or selecting it reveals the full instruction. - Add selected stages tasks without duplicates. Staged tasks can be removed individually or cleared before submission.
- Add to Queue creates one experiment containing all staged tasks. For
example, 12 staged tasks create one Queue row whose progress runs from
0/12to12/12; repeat count duplicates that complete 12-task experiment. - The generated
domain/UUIDlist remains visible in the manual field and is preserved by settings files and startup-state persistence. Reopening the picker restores all official tasks found in that field.
Hover over a label, input, checkbox, or browse button to see concise help in the currently selected language. Runner-specific JSON now lives in the Additional options runner-options tab, so it does not consume Queue space unless that tab is selected. The editor preserves at least three visible lines.
The selected result path is a base folder. The experiment name is appended automatically:
selected-results-folder/
└── Qwen25VL72B_Enhanced_TestSmall_Screenshot_v4/
├── .osworld-manager/
│ ├── Qwen25VL72B_Enhanced_TestSmall_Screenshot_v4/
│ │ ├── execution-metadata.json
│ │ └── selected-tasks.json
│ └── history/<experiment-id>/
│ ├── experiment-record.json
│ └── events.jsonl
├── pyautogui/
└── osworld-report-*.docx
The Queue calculates Done/Total from the selected domain and task IDs.
During execution it periodically checks for new result.txt files and displays
an animated running indicator. Click a path in the Result folder column to
open that directory in the operating system's file manager. A vertical
scrollbar appears automatically when the Queue contains more rows than the
visible area can show.
The adjacent Success/Fail/Total column is updated by the same live scan. A
finite score greater than 0 counts as success; 0, negative, non-finite, or
unreadable scores count as failure. Tasks without result.txt remain pending
and appear only in the total.
Every Queue run receives a unique experiment ID. Its versioned
experiment-record.json is updated atomically at start, task-plan creation,
progress changes, command launch, and final completion, failure, stop, or
interruption. It stores timestamps, provider/model/runner settings, a
configuration fingerprint, operating-system and Python details, masked
commands and errors, and domain-qualified task outcomes with instructions and
task-file hashes. Re-running the same experiment name creates a separate
record instead of replacing an earlier run. API keys, passwords, tokens, and
other credential-like option values are redacted.
The manager maintains a rebuildable local index at
~/.osworld-experiment-manager/experiment-history.sqlite3. The portable JSON
inside the result folder remains the source of truth. At startup, known result
locations are scanned in the background: existing records are re-indexed,
stale running records are finalized as interrupted, and older result
folders are reconstructed from selected-tasks.json, result.txt, and
termination.json. Reconstructed records explicitly identify whether the
original planned task list was available or only observed task outputs could
be recovered.
Stop uses the same native platform style as the other buttons. While the Queue is active, Run Queue becomes Pause. Pause never terminates the experiment currently in progress; it waits after that experiment finishes. While paused, pending Queue entries can be edited, added, or removed. Resume re-reads the visible Queue and runs the latest pending entries. Clicking Stop while idle only displays a status message.
At the start of every experiment, execution-metadata.json records
workspace_root, git_branch, git_commit, and dirty_state for the exact
OSWorld checkout being executed. dirty_state is clean, dirty (including
untracked files), or unavailable when Git metadata cannot be read. A UTC
capture timestamp is stored alongside these fields.
API keys and SMTP app passwords are stored through Python keyring in the
operating system's secure credential store, never in the settings JSON or
Queue. This maps to macOS Keychain, Windows Credential Locker, or a Linux
Secret Service/system keyring backend.
The API / Secrets tab opens as a fresh-entry form and never reads the operating-system credential store during application startup, tab creation, or provider selection. Select a provider and click Load saved values only when you want to authorize a credential-store lookup. Existing values are then placed into the regular input fields. The key remains masked until Show is pressed, and the adjacent Copy button copies it to the clipboard. Show changes to Hide while the key is visible. Load success, missing values, and credential-store errors are reported inline below the inputs without a popup. There is no separate persistent-values panel. Exported settings still contain Base URLs only and never include API keys.
- SMTP email works across platforms using the configured host, port, user, recipients, and app password. Separate multiple addresses with commas or semicolons; each recipient receives an individual message.
- macOS Notification Center is attempted only on macOS.
- macOS Messages accepts comma- or semicolon-separated phone numbers and Apple IDs and is ignored on other platforms.
Email and Messages are sent independently. An empty recipient field is silently ignored.
Completion messages include success, failure, and total task counts, both percentages, and the result folder. Completion emails additionally include the AI provider, model, absolute agent-runner path, actual commands, and complete successful and failed task lists. Stopped or failed Messages include up to three representative error entries; email includes every error entry captured for that execution. Credential values such as API keys, tokens, and client passwords are redacted from commands written to notifications and reports.
Direct voice calls are not included. A paid telephony provider such as Twilio would require a separate integration and credentials.
cd ./OSWorld-gui-tool
python -m pytest -q