{"id":51247302,"url":"https://github.com/gobii-ai/computer.cpp","last_synced_at":"2026-06-29T05:30:26.497Z","repository":{"id":362576162,"uuid":"1259799703","full_name":"gobii-ai/computer.cpp","owner":"gobii-ai","description":"Turn any desktop app into an agent-ready API.","archived":false,"fork":false,"pushed_at":"2026-06-23T13:39:19.000Z","size":1691,"stargazers_count":5,"open_issues_count":2,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-23T14:23:42.657Z","etag":null,"topics":["accessibility","ai-agents","c-plus-plus","cmake","computer-use","desktop-automation","linux","lua","macos","mcp","openrouter","windows"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gobii-ai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-04T21:47:53.000Z","updated_at":"2026-06-22T20:00:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gobii-ai/computer.cpp","commit_stats":null,"previous_names":["gobii-ai/computer.cpp"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/gobii-ai/computer.cpp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gobii-ai%2Fcomputer.cpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gobii-ai%2Fcomputer.cpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gobii-ai%2Fcomputer.cpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gobii-ai%2Fcomputer.cpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gobii-ai","download_url":"https://codeload.github.com/gobii-ai/computer.cpp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gobii-ai%2Fcomputer.cpp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34915001,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-29T02:00:05.398Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accessibility","ai-agents","c-plus-plus","cmake","computer-use","desktop-automation","linux","lua","macos","mcp","openrouter","windows"],"created_at":"2026-06-29T05:30:25.888Z","updated_at":"2026-06-29T05:30:26.475Z","avatar_url":"https://github.com/gobii-ai.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"![computer.cpp header: Turn GUI-only work into API-callable work](.github/assets/readme-header.png)\n\n# computer.cpp\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)\n![C++20](https://img.shields.io/badge/C%2B%2B-20-00599C?logo=cplusplus\u0026logoColor=white)\n![CMake 3.24+](https://img.shields.io/badge/CMake-3.24%2B-064F8C?logo=cmake\u0026logoColor=white)\n![Platforms](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-333333)\n![Lua App APIs](https://img.shields.io/badge/Lua-app%20APIs-2C2D72?logo=lua\u0026logoColor=white)\n![HTTP API](https://img.shields.io/badge/API-HTTP%20%7C%20MCP-0E8A16)\n\nMost software was not built for agents.\n\nIt was built for humans staring at windows.\n\nA human can open an app, understand what is on screen, click the right thing,\ntype the right text, wait for the UI to settle, and verify that the job is\ndone.\n\nAgents need tools, APIs, schemas, results, and something callable. Most desktop\napps do not provide that.\n\n`computer.cpp` gives agents the missing bridge.\n\nWrite one Lua file that describes what a desktop app can do:\n\n```text\nadd-reminder\ncomplete-reminder\nsummarize-list\nextract-visible-rows\napprove-invoice\nupdate-customer-record\nsubmit-form\n```\n\n`computer.cpp` turns that into:\n\n```text\nCLI commands\nlocal HTTP endpoints\ntyped input and output schemas\nsync and async operations\nprogress updates\ncancellation\ntrace logs\nscreenshots and artifacts\nbounded model tool calls\nagent-friendly MCP server\n```\n\nThe desktop app does not need to expose an API. The app vendor does not need to\nship an SDK. The workflow does not need to live in a browser.\n\nIf a human can operate it on screen, `computer.cpp` can help make it\nprogrammable.\n\n## Table Of Contents\n\n- [The Magic](#the-magic)\n- [What Actually Happens](#what-actually-happens)\n- [Why This Exists](#why-this-exists)\n- [Desktop Apps For Agents](#desktop-apps-for-agents)\n- [CLI, HTTP, And MCP](#cli-http-and-mcp)\n  - [CLI](#cli)\n  - [Local HTTP API](#local-http-api)\n  - [MCP Server](#mcp-server)\n- [Examples](#examples)\n- [Quick Start](#quick-start)\n- [Define An App API](#define-an-app-api)\n- [Operations](#operations)\n- [Micro-Agents](#micro-agents)\n- [Core Desktop Control](#core-desktop-control)\n- [LLM Configuration](#llm-configuration)\n  - [CLI and TOML](#cli-and-toml)\n  - [Tray Settings](#tray-settings)\n- [Lua Scripts](#lua-scripts)\n- [Protocol](#protocol)\n- [Tracing And Artifacts](#tracing-and-artifacts)\n- [Security Model](#security-model)\n- [Why C++?](#why-c)\n- [Project Status](#project-status)\n- [Alternatives And Comparisons](#alternatives-and-comparisons)\n- [Philosophy](#philosophy)\n- [Community And Contributions](#community-and-contributions)\n- [Stargazers](#stargazers)\n- [License](#license)\n\n## The Magic\n\nThe outside world sees a clean command:\n\n```http\nPOST /commands/add-reminder\n```\n\nInside, `computer.cpp` can run a tiny desktop micro-agent that sees the screen\nand uses bounded keyboard, mouse, screenshot, and app-specific tools.\n\n```lua\nlocal ac = require(\"computer_cpp\")\n\nlocal app = ac.app.define({\n  name = \"mac.reminders\",\n  title = \"macOS Reminders\",\n  version = \"1.0.0\",\n})\n\nlocal add_reminder_agent = ac.micro_agent.define({\n  name = \"reminders.add\",\n  system = [[\nYou operate the visible macOS Reminders window.\n\nAdd the requested reminder and verify that it appears.\nUse only screenshots and the provided tools.\nClick, type, wait, and verify from visible screen evidence.\nCall blocked if the screen is not usable.\n]],\n  tools = {\n    ac.tools.screenshot({ focusApp = \"Reminders\", frontmostWindowOnly = true }),\n    ac.tools.click_box({ focusApp = \"Reminders\" }),\n    ac.tools.type_text({ focusApp = \"Reminders\" }),\n    ac.tools.press_key({ focusApp = \"Reminders\" }),\n    ac.tools.wait_stable(),\n    ac.tools.blocked(),\n\n    ac.tool.define(\"confirm_created\", {\n      description = \"Confirm the requested reminder is visible\",\n      input = {\n        title = { type = \"string\", required = true },\n        evidence = { type = \"string\", required = true },\n      },\n    }),\n  },\n})\n\napp:command(\"add-reminder\", {\n  description = \"Add a reminder to a list\",\n  input = {\n    list = { type = \"string\", required = true },\n    title = { type = \"string\", required = true },\n    notes = { type = \"string\", default = \"\" },\n  },\n  output = {\n    created = { type = \"boolean\" },\n    title = { type = \"string\" },\n    evidence = { type = \"string\" },\n  },\n  handler = function(ctx, args)\n    ac.app.launch(\"Reminders\")\n    ac.wait_frontmost(\"Reminders\", { timeoutMs = 5000 })\n\n    local evidence = nil\n    local result = add_reminder_agent:run_loop(ctx, {\n      goal = \"Add reminder: \" .. args.title,\n      max_steps = 12,\n      state = args,\n      on_tool_call = {\n        confirm_created = function(call)\n          if call.args.title ~= args.title then\n            return ac.tool_result.error({\n              code = \"wrong_title\",\n              message = \"Visible reminder title did not match\",\n            })\n          end\n          evidence = call.args.evidence\n          return ac.tool_result.done({ created = true })\n        end,\n      },\n    })\n\n    if not result.ok then\n      error(result.error and result.error.message or \"add reminder failed\")\n    end\n\n    return {\n      created = true,\n      title = args.title,\n      evidence = evidence,\n    }\n  end,\n})\n\nreturn app\n```\n\nFrom that one file:\n\n```bash\ncomputer.cpp app run ./reminders.lua add-reminder \\\n  --list Today \\\n  --title \"Review release notes\"\n```\n\n```http\nPOST /commands/add-reminder\n```\n\n```http\nPOST /mcp\n```\n\nThe MCP server generates agent-friendly tools from the same Lua app definition,\nso the desktop app can be exposed through CLI, HTTP, and MCP without writing a\ncustom server for each app.\n\nNow Reminders is not just a GUI app. It is a command-line tool and a local HTTP\nAPI, and an MCP server agents can use.\n\n## What Actually Happens\n\nThe command looks simple:\n\n```text\nadd-reminder(\"Today\", \"Review release notes\")\n```\n\nThe runtime can do the messy desktop work underneath:\n\n```text\nfocus the app\ntake a screenshot\nask the model what it sees\nclick the toolbar plus button\ntype the title\nwait for the UI to settle\ntake another screenshot\nverify the reminder is visible\nreturn a typed result\nsave the trace\n```\n\nThe model does not get arbitrary control. It gets bounded tools. The Lua\ncommand owns the schema, state, validation, retries, progress, final result, and\nproof.\n\nThe caller never sees:\n\n```text\nclick(...)\ntype(...)\nscreenshot(...)\nscroll(...)\n```\n\nThe caller sees:\n\n```text\nadd-reminder(...)\ncomplete-reminder(...)\nsummarize-list(...)\nextract-visible-rows(...)\napprove-invoice(...)\n```\n\n`computer.cpp` does not merely automate desktop apps. It turns desktop apps into\nprogrammable infrastructure.\n\n## Why This Exists\n\nThere is a huge amount of useful software that agents cannot directly use. Not\nbecause the software is impossible to operate, but because it was built for\nhumans.\n\nA person can sit in front of a screen and work through:\n\n```text\na native productivity app\na finance system\na medical scheduling app\na thick-client enterprise tool\na remote desktop workflow\nan installer\nan internal operations console\na legacy application with no API\n```\n\nAn agent needs a callable interface. `computer.cpp` creates that interface. It\nwraps GUI-only work behind commands, schemas, results, traces, and operations.\n\nThe implementation can be ugly. The API should not be.\n\n## Desktop Apps For Agents\n\nAI agents are good at calling tools. Most desktop apps are not tools. They are\nhuman interfaces.\n\n`computer.cpp` turns a desktop app into something an agent can use:\n\n```text\ndesktop app\n-\u003e Lua app definition\n-\u003e CLI / HTTP / MCP\n-\u003e agent-callable API\n```\n\nAn agent can call:\n\n```text\nadd-reminder(list=\"Today\", title=\"Review release notes\")\n```\n\ninstead of trying to reason about:\n\n```text\ntake screenshot\nfind plus button\nclick coordinate\ntype title\npress escape\ntake another screenshot\nverify visually\n```\n\nThe second sequence may still happen internally. The agent sees the first one.\n\n## CLI, HTTP, And MCP\n\n`computer.cpp` exposes the same desktop app API in multiple ways.\n\n### CLI\n\nUse the CLI for local automation, scripts, tests, and agents that call shell\ncommands:\n\n```bash\ncomputer.cpp app run ./reminders.lua add-reminder \\\n  --list Today \\\n  --title \"Review release notes\"\n```\n\n### Local HTTP API\n\nUse HTTP when you want a normal local service interface:\n\n```http\nGET  /health\nGET  /schema\nPOST /commands/add-reminder\nPOST /commands/add-reminder?async=true\nGET  /operations/op_123\nGET  /operations/op_123/result?wait=30\nPOST /operations/op_123:cancel\n```\n\nWhen binding outside localhost, `app serve` requires `--auth-token-env` so the\nHTTP API is not exposed without a bearer token.\n\n### MCP Server\n\n[MCP](https://modelcontextprotocol.io/) is becoming a standard way for agents to\ndiscover and call tools.\n\n`app serve` also exposes a Streamable HTTP MCP endpoint at `/mcp`. The endpoint\nuses JSON-RPC over HTTP POST and returns JSON responses. It does not require TLS\nitself; put Caddy or another reverse proxy in front when exposing it over\nHTTPS.\n\nThe MCP endpoint is stateless: it does not allocate MCP session ids and does\nnot open SSE streams. MCP GET requests to `/mcp` return `405 Method Not\nAllowed`; clients should use the JSON response path over HTTP POST.\n\n```bash\ncomputer.cpp app serve ./reminders.lua --listen 127.0.0.1:8787\n```\n\n```http\nPOST /mcp\n```\n\nThe MCP server turns a Lua app definition into app-level tools such as:\n\n```text\nadd-reminder\ncomplete-reminder\nsummarize-list\n```\n\ninstead of raw desktop primitives like:\n\n```text\nclick\ntype\nscreenshot\nscroll\n```\n\nSupported MCP methods include:\n\n```text\ninitialize\nnotifications/initialized\nping\ntools/list\ntools/call\n```\n\nThe MCP tool schemas come from the command `input` and `output` schemas in the\nLua app definition. Tool calls return both `structuredContent` and a JSON text\ncontent block for clients that prefer either form.\n\nHTTP MCP requests should include:\n\n```text\nAccept: application/json, text/event-stream\nContent-Type: application/json\nMCP-Protocol-Version: 2025-11-25\n```\n\n`MCP-Protocol-Version` is negotiated by `initialize` and should be sent on\nsubsequent requests. The server supports the current `2025-11-25` revision and\nkeeps compatibility with `2025-06-18` and `2025-03-26` clients for the tool\nsurface implemented here.\n\nWhen exposing `/mcp` through a reverse proxy, set a bearer token and allow the\nbrowser origins that should be able to reach the endpoint:\n\n```bash\nexport COMPUTER_CPP_APP_TOKEN='change-me'\ncomputer.cpp app serve ./reminders.lua \\\n  --listen 127.0.0.1:8787 \\\n  --auth-token-env COMPUTER_CPP_APP_TOKEN \\\n  --allowed-origin https://mcp.example.com\n```\n\nThe source of truth is the Lua app definition:\n\n```text\none Lua app definition\n-\u003e CLI\n-\u003e HTTP API\n-\u003e MCP server\n-\u003e async operations\n-\u003e schemas\n-\u003e traces\n```\n\n## Examples\n\nPersonal productivity:\n\n```http\nPOST /commands/add-reminder\nPOST /commands/complete-reminder\nPOST /commands/summarize-list\n```\n\nBusiness operations:\n\n```http\nPOST /commands/extract-visible-invoices\nPOST /commands/approve-invoice\nPOST /commands/update-customer-record\nPOST /commands/export-report\n```\n\nInternal tools:\n\n```http\nPOST /commands/open-case\nPOST /commands/summarize-visible-record\nPOST /commands/fill-required-fields\nPOST /commands/submit-form\n```\n\nThese are not generic computer-use actions. They are app APIs.\n\n## Quick Start\n\nInstall the local build and Lua runtime dependencies. On macOS with Homebrew:\n\n```bash\nbrew install cmake ninja wxwidgets lua\n```\n\nBuild and run the test suite:\n\n```bash\n./scripts/build-mac.sh --verify\n```\n\nFor a faster tray-app development loop, build only `ComputerCpp.app` and\nrelaunch it:\n\n```bash\n./scripts/build-mac.sh --launch\n```\n\nThe macOS build script uses Ninja and writes build outputs to:\n\n```bash\nbuild/debug-ninja/computer.cpp\nbuild/debug-ninja/ComputerCpp.app\n```\n\nFor a cross-platform CMake wrapper, use `scripts/build.sh`. It accepts a\ngenerator explicitly, so Ninja users can run:\n\n```bash\n./scripts/build.sh --verify --generator Ninja --build-dir build/debug-ninja\n```\n\nIf CMake was already configured with another generator, add `--reconfigure` to\nrecreate the build directory.\n\nManual CMake fallback:\n\n```bash\ncmake -S . -B build/debug-ninja -G Ninja \\\n  -DCMAKE_BUILD_TYPE=Debug \\\n  -DBUILD_TESTING=ON \\\n  -DCMAKE_PREFIX_PATH=\"$(brew --prefix)\"\ncmake --build build/debug-ninja --target all --config Debug\nctest --test-dir build/debug-ninja --output-on-failure\n```\n\nFor release-style local builds on macOS:\n\n```bash\n./scripts/build-mac.sh --release --reconfigure\n```\n\nThe macOS build script also creates a reusable local signing identity before\nthe first signed build if you do not already have an Apple Development or\nDeveloper ID Application certificate. You can create or refresh that identity\nmanually with:\n\n```bash\n./scripts/create-local-codesign-identity.sh\n```\n\nOn macOS, the tray app also needs a stable code-signing identity before asking\nfor Accessibility and Screen Recording permissions. TCC records permissions\nagainst the app's code identity, so rebuilding with a different ad-hoc or\nregenerated certificate can leave stale privacy rows or prevent the app from\nappearing in System Settings.\n\nThe script is intentionally idempotent. If `ComputerCpp Local Code Signing`\nalready exists in the login keychain, it reuses that identity instead of\ngenerating a new one. That keeps the local TCC identity stable across rebuilds.\n\n`COMPUTER_CPP_CODE_SIGN_IDENTITY=auto` is the default. On macOS it prefers an\nApple Development or Developer ID Application certificate when one is available,\nthen falls back to `ComputerCpp Local Code Signing`, and finally to ad-hoc\nsigning. Ad-hoc signing is not recommended for macOS permission onboarding.\n\nLaunch the tray app from the build directory:\n\n```bash\nopen -n build/debug-ninja/ComputerCpp.app\n```\n\nUse the tray menu's `Permissions` item to grant and verify macOS permissions.\nThe panel has separate rows for Accessibility and Screen Recording:\n\n1. Click `Request` in the Accessibility row. macOS opens Privacy \u0026 Security.\n   Enable `ComputerCpp`, return to the permission panel, then click `Test`.\n2. Click `Request` in the Screen Recording row. If macOS does not add\n   `ComputerCpp` automatically, use the `+` button in Screen Recording and\n   select the running build artifact shown below. Return to the permission panel\n   and click `Test`.\n3. When both rows are granted, use `Restart ComputerCpp` if macOS asks for a\n   restart. If the permissions get wedged after rebuilds, use\n   `Reset Permissions \u0026\u0026 Restart`.\n\nAfter granting Screen Recording, macOS may ask to quit and reopen the app. If\nthe app does not visibly return, check the tray icon or run:\n\n```bash\npgrep -af ComputerCpp\n./build/debug-ninja/computer.cpp permissions\n```\n\nIf Screen Recording does not add `ComputerCpp` to the list, use the `+` button\nin System Settings and select the running build artifact:\n\n```text\nbuild/debug-ninja/ComputerCpp.app\n```\n\nIf permissions get stuck after changing bundle paths, bundle ids, or signing\nidentities, quit the tray app and do a service-wide reset for the two privacy\nservices before trying again:\n\n```bash\npkill -x ComputerCpp 2\u003e/dev/null || true\ntccutil reset Accessibility\ntccutil reset ScreenCapture\nopen -n build/debug-ninja/ComputerCpp.app\n```\n\nFor a public downloadable macOS binary, use Developer ID signing and\nnotarization. The self-signed identity is for local source builds; it is not a\nreplacement for Developer ID distribution.\n\nCheck permissions and capabilities:\n\n```bash\n./build/debug-ninja/computer.cpp permissions\n./build/debug-ninja/computer.cpp capabilities\n```\n\nRun the macOS Reminders example schema:\n\n```bash\n./build/debug-ninja/computer.cpp --json app run examples/mac/reminders.lua\n```\n\nRun a command:\n\n```bash\n./build/debug-ninja/computer.cpp --json app run examples/mac/reminders.lua \\\n  add-reminder \\\n  --list Today \\\n  --title \"Review release notes\"\n```\n\nServe it over HTTP:\n\n```bash\n./build/debug-ninja/computer.cpp app serve examples/mac/reminders.lua \\\n  --listen 127.0.0.1:8787\n```\n\nCall it:\n\n```bash\ncurl -X POST http://127.0.0.1:8787/commands/add-reminder \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"list\":\"Today\",\"title\":\"Review release notes\"}'\n```\n\nUse it as an MCP server:\n\n```bash\ncurl -X POST http://127.0.0.1:8787/mcp \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-11-25\",\"capabilities\":{},\"clientInfo\":{\"name\":\"curl\",\"version\":\"1.0.0\"}}}'\n```\n\nSee [examples/mac](examples/mac) for a complete macOS Reminders API that lists,\nadds, completes, and summarizes reminders through the real desktop app.\n\n## Define An App API\n\nA `computer.cpp` app is a Lua file that returns an app definition.\n\n```lua\nlocal ac = require(\"computer_cpp\")\n\nlocal app = ac.app.define({\n  name = \"demo.notes\",\n  title = \"Demo Notes\",\n  version = \"1.0.0\",\n  description = \"Desktop API for a notes app.\",\n})\n\napp:command(\"create-note\", {\n  description = \"Create a note\",\n  input = {\n    title = { type = \"string\", required = true },\n    body = { type = \"string\", default = \"\" },\n  },\n  output = {\n    created = { type = \"boolean\" },\n    title = { type = \"string\" },\n  },\n  handler = function(ctx, args)\n    ctx:progress({ step = \"opening_app\" })\n\n    -- Use snapshots, clicks, typing, screenshots, deterministic Lua,\n    -- or bounded model tool-call loops here.\n    return {\n      created = true,\n      title = args.title,\n    }\n  end,\n})\n\nreturn app\n```\n\nRun a command from the CLI:\n\n```bash\ncomputer.cpp app run ./notes.lua create-note \\\n  --title \"Draft release note\" \\\n  --body \"...\"\n```\n\nOr serve the app as a local HTTP API:\n\n```bash\ncomputer.cpp app serve ./notes.lua --listen 127.0.0.1:8787\ncurl http://127.0.0.1:8787/schema\ncurl -X POST http://127.0.0.1:8787/commands/create-note \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"title\":\"Draft release note\",\"body\":\"...\"}'\n```\n\nOr expose it as an MCP server through the same HTTP service:\n\n```bash\ncurl -X POST http://127.0.0.1:8787/mcp \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -H 'Content-Type: application/json' \\\n  -H 'MCP-Protocol-Version: 2025-11-25' \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\",\"params\":{}}'\n```\n\nFrom this one definition, `computer.cpp` can generate:\n\n```text\nCLI help\nCLI argument parsing\nHTTP schema\nHTTP input validation\nHTTP output validation\ncommand dispatch\nsync execution\nasync execution\noperation storage\nprogress updates\ntrace logging\nMCP tool schemas\nMCP server dispatch\n```\n\nThe MCP server uses the same command definitions as the CLI and HTTP surfaces.\n\n## Operations\n\nCommands can run synchronously or asynchronously.\n\nSync is default:\n\n```bash\ncomputer.cpp app run ./app.lua summarize-visible-items --limit 20\n```\n\nAsync is explicit:\n\n```bash\ncomputer.cpp app run ./app.lua summarize-visible-items --limit 20 --async\n```\n\nInspect async operations from the CLI:\n\n```bash\ncomputer.cpp app operation get ./app.lua op_01jabc\ncomputer.cpp app operation result ./app.lua op_01jabc --wait 30\ncomputer.cpp app operation cancel ./app.lua op_01jabc\n```\n\nHTTP follows the same model:\n\n```http\nPOST /commands/summarize-visible-items\nPOST /commands/summarize-visible-items?async=true\nGET  /operations/op_01jabc\nGET  /operations/op_01jabc/result?wait=30\nPOST /operations/op_01jabc:cancel\n```\n\nStatuses are:\n\n```text\npending\nrunning\nsucceeded\nfailed\ncancelled\n```\n\nLong-running desktop work should be inspectable, cancellable, traceable, and\neasy to call.\n\n## Micro-Agents\n\n`computer.cpp` supports small, bounded model-driven loops for narrow desktop\ntasks.\n\nA micro-agent is not a general planner. It does one thing:\n\n```text\nread visible rows\nextract candidate cards\nidentify the active modal\nverify that a record was saved\nfind the submit button\n```\n\nMicro-agents use real model tool calls with JSON schemas. They can call\nstandard tools like:\n\n```text\nscreenshot\nclick_box\nscroll_down\nscroll_up\npress_key\ntype_text\nwait\nwait_stable\ndone\nblocked\n```\n\nThey can also report semantic app-specific data through tools like:\n\n```text\nreport_visible_rows\nreport_invoice_fields\nreport_visible_state\nconfirm_saved_record\n```\n\nThe model does not return fake JSON in normal text. It calls real tools.\n`computer.cpp` validates the arguments, dispatches the tools, records the trace,\nand returns tool results.\n\n## Core Desktop Control\n\n`computer.cpp` is also a local desktop automation daemon and CLI. It exposes a\nsmall JSON protocol for desktop control on macOS, Linux, and Windows:\naccessibility snapshots, screenshots, input, window management, leases,\nclipboard access, image utilities, and optional LLM calls.\n\nDesktop-affecting commands are protected by a control-session lease. Acquire a\nlease directly or run a command under `session run`:\n\n```bash\ncomputer.cpp session acquire --owner local --purpose smoke\ncomputer.cpp session run --owner local --purpose smoke -- /bin/echo ok\n```\n\nTargets are resolved through one of these forms:\n\n```text\n@ref\npoint:x,y\nrect:left,top,right,bottom\nrole:button[name=\"Save\"]\n```\n\nUse `snapshot --with-bounds` and `target find role ...` to discover actionable\naccessibility refs.\n\nCommon commands:\n\n```bash\ncomputer.cpp ping\ncomputer.cpp capabilities\ncomputer.cpp schema\ncomputer.cpp permissions\ncomputer.cpp state\ncomputer.cpp snapshot --interactive --with-bounds\ncomputer.cpp screenshot /tmp/screen.png --max-dim 1200\ncomputer.cpp image info /tmp/screen.png\ncomputer.cpp image split /tmp/tall.png --chunk-height 900 --overlap 80\n```\n\nInput and window commands:\n\n```bash\ncomputer.cpp click @e1\ncomputer.cpp click point:500,400\ncomputer.cpp click rect:10,20,110,70\ncomputer.cpp mouse move 500 400 --duration-ms 250\ncomputer.cpp mouse drag 100 100 300 300 --button left\ncomputer.cpp scroll -600 0 --at role:scrollarea\ncomputer.cpp press \"Cmd+L\"\ncomputer.cpp type \"hello\" --paste\ncomputer.cpp window list Finder\ncomputer.cpp window bounds 100 100 1200 800\n```\n\nObservation commands record input events and sampled screenshot frames:\n\n```bash\ncomputer.cpp observe events 20\ncomputer.cpp observe frames last 10\n```\n\nWait commands support app focus and screen stability:\n\n```bash\ncomputer.cpp wait --frontmost Finder --timeout-ms 5000\ncomputer.cpp wait --stable-screen 750 --timeout-ms 5000\n```\n\nClipboard commands:\n\n```bash\ncomputer.cpp clipboard read\ncomputer.cpp clipboard write \"hello\"\ncomputer.cpp clipboard paste\n```\n\n## LLM Configuration\n\nLLM calls use one canonical user config file. The tray settings window and the\n`computer.cpp config` CLI commands both edit the same `config.toml`.\n\n### CLI and TOML\n\n```bash\ncomputer.cpp config path\ncomputer.cpp config init\ncomputer.cpp config set-provider openrouter --type openrouter --api-key-stdin\ncomputer.cpp config set-profile main --provider openrouter --model openai/gpt-4.1-mini \\\n  --temperature 0.2 --max-output-tokens 1200 --default\ncomputer.cpp config test\n```\n\nUse `computer.cpp config open` to open the editable TOML file. The config stores\nproviders, profiles, model ids, timeouts, sampling defaults, OpenRouter routing\npreferences, and provider API keys. `config show` redacts keys, and the file is\ncreated in the platform user config directory. On macOS/Linux it is written\nowner-read/write only.\n\nA minimal OpenRouter config looks like this:\n\n```toml\nversion = 1\ndefault_profile = \"openrouter\"\n\n[providers.openrouter]\ntype = \"openrouter\"\nbase_url = \"https://openrouter.ai/api/v1\"\napi_key = \"replace-with-your-key\"\n\n[profiles.openrouter]\nprovider = \"openrouter\"\nmodel = \"openai/gpt-4.1-mini\"\ntemperature = 0.2\nmax_output_tokens = 1200\ntimeout_ms = 180000\n\n[profiles.openrouter.openrouter.provider]\nallow_fallbacks = true\norder = [\"openai\"]\n```\n\nFor a local or OpenAI-compatible endpoint, use `type = \"openai-compatible\"` and\nset `base_url` to the endpoint's `/v1` URL. Omit `api_key` when the endpoint is\nlocal or otherwise does not require a key.\n\n```bash\ncomputer.cpp config set-provider local-llm \\\n  --type openai-compatible \\\n  --base-url http://127.0.0.1:8000/v1 \\\n  --no-api-key\ncomputer.cpp config set-profile main \\\n  --provider local-llm \\\n  --model qwen36-27b \\\n  --default\n```\n\nLegacy LLM environment variables are only a one-time import path:\n\n```bash\ncomputer.cpp config import-env\n```\n\nAfter import, edit the config file, tray settings, or `computer.cpp config`\ncommands instead of setting env vars at launch time.\n\n### Tray Settings\n\nLaunch the tray app and choose `Settings...` from the tray menu. The settings\nwindow edits the same `config.toml` file:\n\n- `Providers` defines endpoint names, provider type, base URL, and API key.\n  Choose `OpenRouter` for `https://openrouter.ai/api/v1`, or\n  `OpenAI-compatible` for local and compatible `/v1` endpoints. Check\n  `No API key required` for local endpoints that accept unauthenticated calls.\n- `Profiles` defines the active model settings. Pick a provider, set the model\n  id, optional temperature, top-p, max token, timeout, extra request params, and\n  optional OpenRouter routing JSON. Use `Set Active` to make a profile the\n  default and `Test Inference` to verify it.\n- `Config` shows the config file path. `Open Config` opens the TOML file in the\n  default editor, `Reload` discards unsaved UI changes, and `Save Changes`\n  writes the TOML file.\n\n## Lua Scripts\n\nLua scripts can call the same daemon surface through `ac`:\n\n```lua\nlocal ac = require(\"computer_cpp\")\n\nac.snapshot({ interactive = true, bounds = true })\nac.click(\"role:button[name=\\\"Save\\\"]\")\nac.wait_frontmost(\"Finder\", { timeoutMs = 5000 })\nac.screenshot(\"/tmp/screen.png\", { maxDimension = 1200 })\n```\n\nRun scripts with:\n\n```bash\ncomputer.cpp run --owner local --purpose script ./script.lua\ncomputer.cpp run --dry-run ./script.lua\n```\n\n## Protocol\n\nRequests are JSON objects with a `method` and optional `params`. Responses use\n`ok`, `data`, `error`, and `code` fields.\n\n```json\n{\"method\":\"ping\",\"params\":{}}\n```\n\nBatch requests run multiple steps through the same control-session gate:\n\n```bash\nprintf '[{\"method\":\"ping\",\"params\":{}}]' | computer.cpp --json batch\n```\n\n## Tracing And Artifacts\n\nEvery app command execution can be traceable.\n\nA trace may include:\n\n```text\ncommand input\nprogress updates\nscreenshots\nmodel requests\nmodel tool calls\ntool results\ndesktop actions\nfinal result\nerror or cancellation\ntiming\nartifacts\n```\n\nNormal command results should stay small. Traces and artifacts are for\ndebugging, verification, replay, and improving app wrappers.\n\nUse `--trace` to include an execution trace in JSON output, or `--trace-dir` to\nwrite the trace as JSONL:\n\n```bash\ncomputer.cpp --json app run ./app.lua command-name --trace\ncomputer.cpp --json app run ./app.lua command-name --trace-dir ./traces\n```\n\n## Security Model\n\n`computer.cpp` is a local automation tool, not a remote SaaS control plane.\n\nDefault posture:\n\n```text\nlocal daemon\nlocal socket\nlocalhost HTTP by default\ndesktop-control leases\nexplicit permissions\ntraceable operations\nauth required when binding beyond localhost\n```\n\nImportant notes:\n\n```text\nA process with a control-session token can perform real desktop actions.\nLocalhost HTTP serving is intended for local development/control.\nDo not expose the HTTP server broadly without authentication and a proper network boundary.\nScreenshots and traces may contain sensitive data.\nModel-backed commands may send screenshots or text to a configured model provider.\n```\n\nThe tool is powerful because it can operate the real desktop. Use it with the\nsame care you would use for any local automation system that can click, type,\nread screenshots, and access the clipboard.\n\n## Why C++?\n\nThis project has to touch the real computer.\n\nScreenshots, input injection, window state, accessibility snapshots, clipboard\nbehavior, display geometry, native app focus, and desktop permissions all live\nat the operating system boundary.\n\nA CMake-based C++ project can compile close to the metal, link directly against\nOS APIs, and run as a small local binary. On macOS, desktop automation means\ntalking to frameworks like AppKit, CoreGraphics, Accessibility,\nScreenCaptureKit, and the system clipboard. On Linux, it can mean X11, XTest,\nWayland/KWin helpers, desktop portals, or other platform-specific adapters. On\nWindows, it means Win32, UI Automation, input APIs, window handles, sessions,\nand desktop permissions.\n\nLua sits on top because app APIs need to be easy to define. C++ sits underneath\nbecause the computer has to actually move.\n\n## Project Status\n\nCurrent implementation status:\n\n```text\nmacOS: primary and most complete backend\nLinux: adapter work exists; support is partial and depends on native dependencies\nWindows: adapter work exists; support is evolving\nMCP: supported through Lua app definitions\n```\n\nThe current macOS backend includes native desktop control, permissions,\nscreenshots, accessibility snapshots, window/app state, input actions, optional\nLLM calls, Lua app definitions, local HTTP serving, async operation records,\nMCP serving, tracing, and the Reminders example.\n\nLinux and Windows support should be treated as evolving.\n\n## Alternatives And Comparisons\n\n### Cua vs computer.cpp\n\n[Cua](https://github.com/trycua/cua) is a broader computer-use stack for agents.\nIt includes components for controlling desktops, working with sandboxes,\nexposing tools, running agents, and building computer-use workflows.\n\nCua asks:\n\n```text\nHow do we give agents access to computers?\n```\n\n`computer.cpp` asks:\n\n```text\nHow do we turn this desktop app or workflow into a callable API?\n```\n\nA Cua-style system gives an agent ways to inspect and operate a computer:\nwindows, screenshots, accessibility state, mouse, keyboard, tools, and\nexecution environments.\n\n`computer.cpp` lets a developer wrap a specific desktop app as a semantic API:\n\n```http\nPOST /commands/add-reminder\nPOST /commands/approve-invoice\nPOST /commands/extract-visible-rows\nGET  /operations/op_123/result\n```\n\nThe app may still be controlled through screenshots, clicks, typing, keyboard\nshortcuts, accessibility snapshots, or model vision internally. Those details\nstay behind the command boundary.\n\nThe public interface is not \"click this coordinate.\"\n\nThe public interface is \"perform this app operation.\"\n\nCua gives agents computers.\n\n`computer.cpp` gives desktop apps APIs.\n\nThey can be complementary: a lower-level computer-use driver can provide\ndesktop control, while `computer.cpp` defines the semantic app contract,\nschemas, operations, traces, and API surface.\n\n### PyAutoGUI vs computer.cpp\n\n[PyAutoGUI](https://github.com/asweigart/pyautogui) is a classic Python desktop\nautomation library. It can move the mouse, type text, press keys, take\nscreenshots, and locate images on screen.\n\nThat is low-level desktop scripting.\n\n`computer.cpp` lets developers wrap a GUI app as a typed command surface.\n\nPyAutoGUI-style code says:\n\n```python\nclick(x, y)\nwrite(\"hello\")\npress(\"enter\")\n```\n\n`computer.cpp` says:\n\n```http\nPOST /commands/add-reminder\n```\n\nThe implementation may still click, type, wait, and screenshot internally. The\ncaller gets a semantic command and a typed result.\n\nPyAutoGUI helps you automate a screen.\n\n`computer.cpp` helps you publish an API for a desktop workflow.\n\n### SikuliX vs computer.cpp\n\n[SikuliX](https://sikulix.github.io/) is a visual automation tool built around\nimage recognition: find this image, click that region, wait for the UI to\nchange.\n\nThat can be useful for visual desktop automation and GUI testing.\n\n`computer.cpp` can use visual information too, but not as the public\nabstraction.\n\nA visual macro is usually a sequence of UI actions.\n\nA `computer.cpp` app definition is an API contract:\n\n```lua\napp:command(\"summarize-visible-items\", {\n  input = {\n    limit = { type = \"integer\", default = 20 },\n  },\n\n  output = {\n    items = { type = \"array\" },\n    summary = { type = \"string\" },\n  },\n\n  handler = function(ctx, args)\n    return my_app.summarize_visible_items(ctx, args)\n  end,\n})\n```\n\nFrom that one definition, `computer.cpp` can provide:\n\n```bash\ncomputer.cpp app run ./my-app.lua summarize-visible-items --limit 20\n```\n\nand:\n\n```http\nPOST /commands/summarize-visible-items\n```\n\nVisual macros automate steps.\n\n`computer.cpp` defines callable app behavior.\n\n### AutoHotkey vs computer.cpp\n\n[AutoHotkey](https://www.autohotkey.com/) is excellent for Windows hotkeys,\nmacros, and personal automation.\n\nIt is great when a human wants to customize their own machine.\n\n`computer.cpp` is aimed at a different layer: turning desktop workflows into\nprogrammatic APIs that agents, scripts, and services can call.\n\nAutoHotkey scripts typically expose behavior through hotkeys or script entry\npoints.\n\n`computer.cpp` exposes behavior through typed commands, schemas, CLI, HTTP, MCP,\nasync operations, and traceable results.\n\nAutoHotkey is personal automation.\n\n`computer.cpp` is an app API runtime.\n\n### agent-computer-use vs computer.cpp\n\n[agent-computer-use](https://github.com/kortix-ai/agent-computer-use), also\nknown as `agent-cu`, focuses on accessibility-based desktop automation.\n\nAccessibility-first tools are useful when the target app exposes a reliable\naccessibility tree. They can provide deterministic element references, labels,\nroles, and structured UI state.\n\nAccessibility is powerful when it works.\n\nBut many real workflows involve apps or surfaces where accessibility is\nincomplete, stale, misleading, unavailable, or simply not the right abstraction:\n\n```text\ncustom-rendered UIs\nremote desktops\nlegacy enterprise software\ncanvas apps\ninstallers\nGPU-heavy views\nbroken Electron apps\nmixed workflows across multiple apps\n```\n\n`computer.cpp` can use accessibility snapshots internally when they help.\n\nBut it does not require the public API to mirror the accessibility tree.\n\nThe goal is not to expose UI elements.\n\nThe goal is to expose useful app operations:\n\n```http\nPOST /commands/extract-visible-invoices\nPOST /commands/approve-invoice\nPOST /commands/update-customer-record\n```\n\nThe implementation can use accessibility, screenshots, keyboard shortcuts,\nmodel vision, or direct input.\n\nThe caller should not care.\n\n### NIB / nut.js vs computer.cpp\n\n[nut.js](https://github.com/nut-tree/nut.js) and\n[NIB](https://nutjs.dev/nib) provide desktop automation tools for mouse,\nkeyboard, screen, windows, and agent-facing CLI usage.\n\nThey are useful when you want a JavaScript or Node-oriented desktop automation\nstack.\n\n`computer.cpp` has a different center of gravity.\n\nIt is not a Node package and not just an agent CLI for desktop actions.\n\nIt is a C++ desktop app API runtime.\n\nThe goal is not only:\n\n```text\nlet an agent click and type\n```\n\nThe goal is:\n\n```text\nlet a developer define a semantic API for a desktop app\n```\n\nThat API can then be exposed through CLI, HTTP, and MCP with schemas,\noperations, results, traces, and artifacts.\n\n### computer-use-mcp vs computer.cpp\n\n[computer-use-mcp](https://github.com/zavora-ai/computer-use-mcp) is an MCP\nserver/client for controlling a desktop computer with AI agents. It exposes\ntools like screenshots, mouse, keyboard, clipboard, app management, and window\ntargeting.\n\nThat is useful when your primary goal is MCP-based computer control.\n\n`computer.cpp` exposes MCP too, but MCP is not the core abstraction.\n\nThe core abstraction is the app API definition.\n\n```text\none Lua file\n-\u003e semantic commands\n-\u003e CLI\n-\u003e HTTP\n-\u003e MCP\n-\u003e async operations\n-\u003e traces\n```\n\n`computer-use-mcp` exposes computer-control tools to agents.\n\n`computer.cpp` helps developers expose app-specific commands to agents.\n\nAgents should not always be asked to operate a desktop at the level of pixels\nand clicks.\n\nThey should be able to call:\n\n```text\napprove-invoice\nextract-visible-rows\nsummarize-list\ncomplete-reminder\n```\n\n### Playwright / Puppeteer / Selenium vs computer.cpp\n\nBrowser automation tools are the right answer when the workflow lives inside a\nbrowser and the DOM or browser protocol is available.\n\nExamples:\n\n* [Playwright](https://playwright.dev/)\n* [Puppeteer](https://pptr.dev/)\n* [Selenium](https://www.selenium.dev/)\n* [browser-use](https://github.com/browser-use/browser-use)\n* [agent-browser](https://github.com/vercel-labs/agent-browser)\n\nUse browser automation for browser-native work.\n\nUse `computer.cpp` when the workflow lives on the desktop:\n\n```text\nnative apps\ndesktop software\nsystem dialogs\ninstallers\nremote desktops\nlegacy enterprise tools\ncustom internal applications\napps with no official API\nmixed workflows across multiple apps\npersonal productivity apps\n```\n\nBrowser automation gives you a browser API.\n\n`computer.cpp` helps you build APIs for GUI workflows that do not already have\none.\n\n### OpenAI / Anthropic computer use vs computer.cpp\n\nModel providers increasingly expose computer-use capabilities.\n\nExamples:\n\n* [OpenAI computer use](https://platform.openai.com/docs/guides/tools-computer-use)\n* [Anthropic computer use](https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/computer-use-tool)\n\nThose systems help models reason about screens and produce actions.\n\n`computer.cpp` is different.\n\nIt is the local runtime for making desktop workflows callable, traceable, and\nreusable.\n\nA model may be used inside a `computer.cpp` command, but the public contract is\nstill the app command:\n\n```http\nPOST /commands/summarize-visible-items\n```\n\nnot:\n\n```text\nhere is a screenshot, decide what to click next\n```\n\nModel computer use is a reasoning capability.\n\n`computer.cpp` is an app API layer for real desktop software.\n\n### UiPath / Power Automate / traditional RPA vs computer.cpp\n\nTraditional RPA platforms such as [UiPath](https://www.uipath.com/),\n[Microsoft Power Automate](https://www.microsoft.com/en-us/power-platform/products/power-automate),\n[Automation Anywhere](https://www.automationanywhere.com/), and\n[Blue Prism](https://www.blueprism.com/) are full workflow systems.\n\nThey often include recorders, schedulers, credential vaults, queues, dashboards,\napprovals, governance, and enterprise administration.\n\n`computer.cpp` is smaller and more developer-native.\n\nIt does not try to be a full RPA platform.\n\nIt gives developers a runtime for defining semantic commands over desktop\nworkflows, then exposing them through CLI, HTTP, and MCP.\n\nRPA asks:\n\n```text\nHow do we manage a fleet of business-process bots?\n```\n\n`computer.cpp` asks:\n\n```text\nHow do we turn this desktop app or workflow into a callable API?\n```\n\nThat makes it useful as a local substrate, an agent tool, an internal\nautomation layer, or the foundation for more opinionated systems.\n\n### Bespoke Agents vs computer.cpp\n\nBespoke agents are powerful. For hard workflows, specific code often beats\ngeneric frameworks.\n\n`computer.cpp` preserves that.\n\nThe app logic is still bespoke. The Lua file can define exactly how one app or\nworkflow should behave.\n\nBut `computer.cpp` standardizes the boring parts:\n\n```text\nCLI\nHTTP server\nMCP server\ninput validation\noutput validation\noperation ids\nasync execution\nresult retrieval\ncancellation\nprogress updates\ntrace logs\nscreenshots\nartifacts\nmodel tool calling\nstandard desktop tools\n```\n\nSo each app can be custom where it matters, without rebuilding the runtime\nevery time.\n\nBespoke behavior.\n\nStandard runtime.\n\n### Raw Desktop Endpoints vs computer.cpp\n\nA desktop automation server could expose endpoints like:\n\n```http\nPOST /click\nPOST /type\nPOST /scroll\nPOST /screenshot\n```\n\n`computer.cpp` intentionally avoids that as the default public API.\n\nRaw desktop primitives are internal tools.\n\nThe public API should describe what the app does:\n\n```http\nPOST /commands/add-reminder\nPOST /commands/complete-reminder\nPOST /commands/extract-visible-rows\nPOST /commands/approve-invoice\n```\n\nThis makes the API stable even if the implementation changes.\n\nToday a command might use screenshots and mouse clicks.\n\nTomorrow it might use keyboard shortcuts, accessibility, a model tool call, or a\nbetter app-specific strategy.\n\nThe caller should not care.\n\n## Philosophy\n\nThe API is semantic.\n\nThe implementation can be ugly.\n\nDesktop apps are messy. They have modals, weird focus behavior, stale screens,\nbroken accessibility trees, remote views, unexpected dialogs, and no official\nAPIs.\n\n`computer.cpp` gives developers a way to wrap that mess in a clean command\nsurface:\n\n```text\ndefine the app API once\nexpose it through CLI, HTTP, and MCP\ntrace every operation\nkeep low-level desktop tools internal\nturn GUI-only work into API-callable work\n```\n\n## Community And Contributions\n\nIf you are building desktop agents, app wrappers, local automation tools, or\ncomputer-use infrastructure, you are invited to build with us.\n\nYou can absolutely build your own thing on top of `computer.cpp`. The reason to\ncontribute reusable pieces upstream is leverage.\n\nWhen a fix or helper lands here, you no longer have to carry it alone. Other\npeople can test it on platforms, displays, apps, and edge cases you do not have.\nYour work becomes part of the shared runtime, your use case influences the\ndirection of the project, and your contribution becomes visible proof of the\nproblem you solved.\n\nThat is good for you and good for the project:\n\n```text\nless private maintenance\nmore review and testing\npublic credit for useful work\na stronger foundation for your own products\nfaster progress on the boring runtime layer\nmore time for the app-specific work that makes your project unique\n```\n\nThe best place to compete is at the product and workflow layer. The best place\nto cooperate is the substrate: screenshots, input, accessibility, leases, app\nschemas, operation tracking, MCP, HTTP, traces, and cross-platform desktop\nbehavior.\n\nGood contributions include:\n\n```text\nLua app definitions for real desktop apps\nplatform backend fixes\nbetter accessibility targeting\nmore reliable screenshot and input behavior\nMCP, HTTP, and CLI improvements\ndocs, examples, and tests\nbug reports with clear reproduction steps\nsmall helper APIs that remove repeated wrapper code\n```\n\nPrivate workflows can stay private. If you automate an internal app, you may not\nbe able to share the app logic, screenshots, or data. That is fine. The reusable\nparts are still valuable: selectors, retries, validation helpers, trace patterns,\nmicro-agent tools, platform fixes, and lessons learned from real failure modes.\n\nOpen a pull request, start a discussion, or publish a small example. If you are\nbuilding something adjacent, the door is open. A healthier desktop-agent\necosystem is one where independent projects can still improve the common pieces\ntogether.\n\n## Stargazers\n\n[![Stargazers welcome](https://img.shields.io/badge/stargazers-welcome-ffdd00?logo=github)](../../stargazers)\n\nIf this project helps, star the repository so other people can find it.\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgobii-ai%2Fcomputer.cpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgobii-ai%2Fcomputer.cpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgobii-ai%2Fcomputer.cpp/lists"}