--- Source: /docs/workspaces.md # Your FlintVM workspace FlintVM gives you a Linux environment for development, desktop applications and AI work. Open **Workspace** and sign in with your account. If you received an invitation, follow the invitation flow on the sign-in page. See [sign-in and CLI login](/docs/sso.md). ## Create an environment 1. Choose **New environment** and give it a name. 2. Choose a template or custom configuration, then select an available distribution and release. Arch Linux is rolling and has no release choice. 3. Select a resource plan from the options available to your account. 4. Choose desktop and AI controls, search for packages, and select encrypted disk storage if available. 5. Create the environment. Start its desktop or run a command when you are ready to use it. Creation saves your choices. The first start can take longer while software is prepared. You do not need to choose or configure a server. If no capacity or suitable plan is available, contact your administrator. ## Use the desktop Open your environment and choose **Start desktop**. Wait until it is running, then connect the Computer viewer. Choose **Take control** to use the mouse and keyboard. **Match display** adjusts the desktop resolution to the viewer, including in fullscreen. For native SSH, VNC or Xpra clients, open **Details → Remote connections** and follow the [connection guide](/docs/remote-access.md). Available connection methods depend on your account and environment. ## Connect an AI agent Open **Agent connections** to create a scoped API key or configure your harness. The [MCP guide](/docs/mcp.md) explains setup; the [agent quickstart](/docs/agent-guide.md) covers creating environments, running commands and transferring files. Agents act within your workspace permissions. ## Change environment variables Open **Configuration → Environment variables**, edit the `KEY=value` entries and choose **Save variables**. You can save while the desktop runs. New agent commands and future starts use the new values; existing applications keep their current environment. Agents can read saved values. Use these fields for configuration, not secret storage. Other configuration changes may require stopping the environment or creating a new one. ## Save installed software and files Install your software and save your work, then stop the environment. In **Saved images**, choose a name and select **Save image**. Wait for completion before creating another environment from that image. A clone gets an independent writable disk. Saved images capture disk contents, not running processes or open network connections. Treat image deletion and environment deletion as permanent actions; check the selected item before confirming. ## Network access and privacy Outbound browsing does not need a port mapping. A port mapping is an optional inbound connection to a service inside your VM, such as a development web server. Availability depends on your account’s policy. Your environments and agent credentials belong to your account. Team membership does not automatically share VMs. Encrypted disks protect stored data while locked; they do not protect running memory from the host administrator. Memory protection from the host is currently unavailable. ## Idle shutdown and interruptions The default idle shutdown is ten minutes; active AI commands prevent idle shutdown. Account settings can impose other time limits. Save your work regularly. If the connection drops, check the environment and task status before repeating work. During service maintenance, wait until the environment is ready and reconnect using its existing name. If an infrastructure or storage error persists, send the error to your administrator. --- Source: /docs/agent-guide.md # FlintVM for agents FlintVM gives an AI harness a dedicated Linux workspace. Use `flint` to sign in and connect native clients, and `flint-mcp` to connect a stdio-based harness. No Python control client is required. This guide describes the authenticated web/MCP workflow. Start with the runtime's discovered tool schemas: they determine the exact fields, scopes and capabilities available to your account. ## 1. Connect Open the FlintVM service URL provided to you. You do not need to provision a server to use your workspace. The web UI is at `/app`. Sign in, open **Agent connections**, and create a named, expiring API key with only the necessary scopes. Save it outside the repository in a private file with mode `0600`. Configure a stdio-capable harness with absolute paths: ```json { "mcpServers": { "flint": { "command": "/absolute/path/to/flint-mcp", "args": ["--endpoint", "https://YOUR-SERVICE/mcp", "--key-file", "/absolute/private/flint.key"] } } } ``` Replace `https://YOUR-SERVICE/mcp` with your service’s MCP endpoint, shown in **Agent connections**. Native HTTP harnesses can use `/mcp` with a bearer API key or OAuth. OAuth requires S256 PKCE, user consent and an exactly registered literal-loopback callback with an explicit port. Hosted/custom-scheme callbacks are not supported by this local provider. Use the stdio adapter when a client's native OAuth flow does not match. See [MCP setup](/docs/mcp.md) for Claude Code, Codex, Cursor, VS Code Copilot, Windsurf, Cline, Roo Code, Gemini CLI, Continue and OpenCode. Configuration examples are not a claim that every client version has been tested. ## 2. Discover before acting Initialize MCP, call `tools/list`, then: ```json {"name":"flint_capabilities","arguments":{}} ``` Call `flint_list_templates` and `flint_list_environments`. Read the allowed releases, resource presets, quotas and encryption availability from the capabilities response. Do not guess a distro release, CPU allocation, owner ID or host path. The service applies your account’s limits. If workloads or storage are unavailable, contact your administrator. ## 3. Create a workspace If `ai-desktop` appears in the template list and fits your limits: ```json {"name":"flint_create_environment","arguments":{"name":"research","template":"ai-desktop"}} ``` Creating saves the configuration; it does not mean the VM is running. For custom configuration, use the discovered `options` schema and only curated releases/resource combinations. Arch is rolling and has no release field. Package search is available through `flint_search_packages` with distro, release and query. Call `flint_get_environment` to obtain the current configuration and revision. `flint_update_environment` requires an idle environment and the latest revision. `flint_update_variables` accepts the current revision and a complete replacement variable map, including while a desktop is running. New commands see updated values; already running processes do not change. Saved variables are visible to authorized agents, so use them for configuration rather than secret storage. ## 4. Start, execute and observe For a persistent desktop, call `flint_start_desktop` with `{"name":"research"}`. Poll `flint_list_tasks` and match the returned task ID. Read status and output; never equate task submission with success. While it runs, use: ```json {"name":"flint_execute","arguments":{"name":"research","argv":["sh","-lc","uname -a"],"timeoutMs":30000}} ``` This executes inside the running desktop VM. Arguments are structured; invoking a shell is an explicit choice. Check the exit code and bounded stdout/stderr. Commands have a maximum five-minute timeout and bounded output. Active AI work prevents the default ten-minute idle shutdown; background polling alone is not useful activity. For a stopped environment, use `flint_run_command` with `name` and `command`, then poll its task. It starts an isolated run and cleans up afterward. It cannot take over a desktop that already owns the lifecycle. Do not retry a mutation just because a response was lost; inspect environment/task state first. ## 5. Use the computer `flint_screenshot` returns the guest desktop as an MCP image. `flint_control` accepts a versioned request: ```json {"name":"flint_control","arguments":{"name":"research","request":{"version":1,"action":"browser.tabs"}}} ``` Available actions include desktop screenshot, move, click, scroll, key and type, plus browser tabs, navigate, focus, evaluate, screenshot and CDP. Read [control payloads](/docs/agent-controls.md) before sending input. Coordinates refer to the guest's current screen. Inspect a fresh screenshot after changing resolution. Browser evaluation and command execution carry full guest-user privileges. ## 6. Transfer files File tools require a running desktop and use absolute paths inside the guest. They do not accept host file paths or select another owner. - `flint_list_files`: `name`, `path`. Returns bounded directory metadata. - `flint_download`: `name`, `path`, `offset`, optional `length`. Check the returned exit code, then base64-decode `stdout`. Advance the offset by the decoded length; a shorter-than-requested chunk (or an empty chunk at an exact boundary) marks end of file. Each chunk is at most 256 KiB decoded. - `flint_upload`: `name`, `path`, `offset`, base64 `data`. Each chunk is at most 256 KiB decoded. Offset zero truncates an existing file; later offsets must match its current length. For safe replacement, upload to a new temporary guest path, verify its size/hash using `flint_execute`, then rename it into place. Chunked upload is not an atomic transaction. If a response is lost, inspect the guest file length before resuming; do not blindly resend offset zero. Never insert file contents into a shell command string. ## 7. Save and reuse an image Install the software you need, stop the desktop using `flint_stop_desktop`, and wait for completion. Call `flint_save_image` with the environment `name` and a new `image` name; poll the task. List images with `flint_list_images`, then call `flint_clone_image` with the source `image` and a new environment `name`. These are reusable disk images, not live memory snapshots. Clones have independent writable disks and must fit your account’s quotas. `flint_delete_image` removes an unused saved image. Confirm the user's intent before destructive deletion of their environments, images or files. ## Remote VM addresses Call `flint_connection_info` with the environment name to discover its assigned hostname and allowed remote protocols. Use `flint connect` for authenticated SSH/VNC/Xpra tunnels; see [remote access](/docs/remote-access.md). Keys remain owner-scoped, and native SSH still requires guest SSH authentication. ## Scopes | Scope | Allows | | --- | --- | | environments:read | Discover capabilities, environments, templates, tasks and images | | environments:write | Create, configure and delete environments | | workloads:execute | Start/stop desktops and execute guest commands | | desktop:control | View and control the desktop/browser | | files:read | List and download guest files | | files:write | Upload guest files | | images:write | Save, clone and delete reusable images | A command-capable agent can also manipulate guest files through commands. File scopes are endpoint permissions, not a restriction on what arbitrary guest code can do. Credentials always remain bound to their owner's workspace; teams do not implicitly share VMs or network access. ## Troubleshooting - Authentication failure: stop retrying with the same invalid credential; ask the user to renew/revoke it in Agent connections. Use only credentials issued to your account. - Revision conflict: reload the current configuration, reconcile the requested change and retry with the new revision. - Busy lifecycle: inspect active tasks; wait or ask before stopping another operation. - Rate/concurrency limit: use bounded backoff. Avoid concurrent start, save, stop and configuration mutations. - Service, storage or network unavailable: report the exact failure to your administrator. - Command timeout/disconnect: inspect task state and output before retrying. Missing terminal status is not evidence of success. - Service restart: sign in again if necessary and check environment/task status before resuming work. ## Isolation and honest limits Choose encrypted disk storage when it is available in your environment settings. Disk encryption protects stored data while locked; it does not hide a running VM's memory from the host administrator. Host-private memory is currently unavailable. Network access and resource choices depend on your account’s available plans. Internet access does not grant access to other users’ VMs. Contact your administrator if a required option is unavailable. Port mappings are optional inbound routes to an application inside your VM; outbound browsing does not need one. ## Interactive CLI authentication Use `flint login --server https://YOUR-SERVICE` to authorize this machine through the browser, including Google, Apple or GitHub if enabled. `flint-mcp` uses that login when no explicit API key is supplied, checks the service origin and refreshes expiring credentials. Request only required scopes. Never read or upload the local credential file. `flint logout` revokes the grant. See [SSO and CLI login](/docs/sso.md) for setup and native-tunnel lifetime limits. ## Maintenance interruptions During maintenance, your desktop connection may disconnect. Check the environment and task status, then reconnect when it is ready. Keep using the same environment name and MCP tools; there is no server to select. Do not create a replacement VM solely because a connection was lost. Keep image identifiers returned by the service unchanged when cloning or deleting. --- Source: /docs/sso.md # Single sign-on and CLI login FlintVM supports Google and Apple OpenID Connect sign-in, plus GitHub OAuth sign-in. Provider sign-in works in the web workspace and during `flint login`. Provider credentials are configured by the administrator; users never give the CLI a Google, Apple or GitHub password. ## Registration and connected identities New SSO users need an administrator/team invitation. On the sign-in page, expand **First time here? Use your invitation**, enter a username and invitation code, then choose a provider. Email-bound invitations require the provider's verified email to match. Apple private-relay addresses must match the invited address too. New accounts receive the ordinary user role and any membership carried by the invitation. Existing users sign in with their current method, then open **Accounts → Connected sign-in methods** to connect another provider. Matching emails never merge accounts automatically. Provider identities use the provider's stable subject ID, not a mutable email address or GitHub username. Disconnecting a provider leaves the account and environments intact. You must retain a local password or another connected sign-in method. If sign-in is unavailable, contact your administrator. Review and revoke your agent credentials in **Agent connections** when access is no longer needed. ## CLI sign-in ```sh flint login --server https://app.example.com flint auth status ``` The browser opens the FlintVM sign-in page. Choose Google, Apple, GitHub or a local sign-in method, then approve the CLI's requested scopes. By default it requests environment read, workload execution and desktop control. Request other scopes explicitly: ```sh flint login --server https://app.example.com \ --scope environments:read,desktop:control,workloads:execute,files:read,files:write ``` Use `--no-browser` to print the URL instead of launching `xdg-open`. Open it in a browser on the same machine as the CLI: the callback uses a temporary `127.0.0.1` listener. This is a browser authorization-code flow with PKCE, not a remote device-code flow. It times out after five minutes. Credentials are saved to `$XDG_CONFIG_HOME/flint/auth/session.json` (normally `~/.config/flint/auth/session.json`) in a private `0700` directory with a `0600` file. Never upload this file to an agent workspace or repository. Access tokens last 15 minutes and refresh automatically with the rotating server grant. Concurrent local clients serialize refreshes so they do not replay a rotating token. `flint connect` and `flint-mcp` use the saved login when neither `--key-file` nor `FLINT_API_KEY` is supplied: ```sh flint-mcp --endpoint https://app.example.com/mcp flint connect YOUR-VM-HOSTNAME --protocol ssh ``` The MCP client refuses to send a saved login to a different service origin and refreshes it for subsequent requests. Before connecting to a VM gateway, the CLI asks its saved service to authorize that exact VM hostname and protocol, then verifies the gateway's TLS certificate. A native SSH/VNC/Xpra tunnel authenticates once at connection setup and closes when that access token expires; reconnect to obtain a refreshed token, or use an explicitly scoped API key for longer native sessions. The CLI's existing `run`, `create` and `execute` commands still operate on local environments; login does not silently redirect them to a remote host. Agents control remote environments through MCP. ```sh flint logout ``` Logout revokes the CLI grant family on the server and removes the local credential. If the server is unreachable, `flint logout --local-only` removes the local file without revocation; revoke the grant from **Agent connections** when the server is available. CLI logout does not end your browser session or provider session. --- Source: /docs/mcp.md # Connect AI harnesses to FlintVM Find your service’s MCP endpoint in **Agent connections**. Connect your harness with a scoped API key or supported OAuth flow. Every request uses your account’s permissions and resource limits. ## API keys and the built-in stdio adapter 1. Sign in to FlintVM Web and open **Agent connections**. 2. Create a named API key, choose its scopes, and choose an expiration (1–90 days). Copy it immediately; FlintVM persists only its hash. 3. Save the key in a file outside your project, readable only by your user: `chmod 600 /absolute/private/path/flint.key`. 4. Use the `flint-mcp` executable supplied with your FlintVM client installation. 5. Select your harness in Agent connections and copy its configuration, replacing the binary and private key file paths with absolute paths. The adapter is a compiled Go MCP server. It bridges stdio to authenticated HTTP; no Python, Node package, or third-party proxy is required. It also accepts `FLINT_API_KEY` when `--key-file` is absent. It never accepts a key on the command line, refuses HTTP redirects, and permits plaintext HTTP only to literal loopback IP addresses. Do not put a key in a repository or a shared configuration file. Common JSON entry (merge into the client's configuration): ```json { "mcpServers": { "flint": { "command": "/absolute/path/to/flint-mcp", "args": ["--endpoint", "https://YOUR-SERVICE/mcp", "--key-file", "/absolute/private/path/flint.key"] } } } ``` Replace `https://YOUR-SERVICE/mcp` in these examples with your endpoint. The formats below cover ten harnesses; use the configuration generated in **Agent connections** where available. Client versions differ, so check the linked client documentation if its settings have changed. | Harness | Configuration / setup | Official documentation | | --- | --- | --- | | Claude Code | `claude mcp add --transport stdio flint -- /absolute/path/to/flint-mcp --endpoint https://YOUR-SERVICE/mcp --key-file /absolute/private/path/flint.key` | [Claude Code MCP](https://code.claude.com/docs/en/mcp) | | Codex | TOML example below, or MCP settings | [Codex MCP](https://developers.openai.com/codex/mcp/) | | Cursor | Common JSON in `.cursor/mcp.json` or global MCP settings | [Cursor MCP](https://docs.cursor.com/context/model-context-protocol) | | VS Code Copilot | `.vscode/mcp.json`; use `servers` instead of `mcpServers`, and add `"type":"stdio"` to the entry | [VS Code configuration](https://code.visualstudio.com/docs/agents/reference/mcp-configuration) | | Windsurf / Cascade | Common JSON in the MCP configuration opened from Cascade settings; newer Devin Desktop versions have moved this file | [Cascade configuration](https://docs.devin.ai/desktop/cascade/mcp) | | Cline | Common JSON in MCP Servers → Configure MCP Servers | [Cline MCP source documentation](https://github.com/cline/cline/blob/main/docs/mcp/mcp-overview.mdx) | | Roo Code | Common JSON in `.roo/mcp.json` or global MCP settings | [Roo Code MCP](https://docs.roocode.com/features/mcp/using-mcp-in-roo) | | Gemini CLI | Common JSON in `.gemini/settings.json` | [Gemini MCP](https://geminicli.com/docs/tools/mcp-server/) | | Continue | Common JSON in `.continue/mcpServers/flint.json`, or the YAML example below; enable Agent mode | [Continue MCP](https://docs.continue.dev/customize/deep-dives/mcp) | | OpenCode | Local MCP entry in `opencode.json`, example below | [OpenCode MCP](https://opencode.ai/docs/mcp-servers/) | Codex: ```toml [mcp_servers.flint] command = "/absolute/path/to/flint-mcp" args = ["--endpoint", "https://YOUR-SERVICE/mcp", "--key-file", "/absolute/private/path/flint.key"] ``` Continue (inside an existing configuration): ```yaml mcpServers: - name: flint command: /absolute/path/to/flint-mcp args: ["--endpoint", "https://YOUR-SERVICE/mcp", "--key-file", "/absolute/private/path/flint.key"] ``` OpenCode: ```json { "mcp": { "flint": { "type": "local", "command": ["/absolute/path/to/flint-mcp", "--endpoint", "https://YOUR-SERVICE/mcp", "--key-file", "/absolute/private/path/flint.key"], "enabled": true } } } ``` ## Direct HTTP and OAuth Native HTTP clients can use the endpoint directly with `Authorization: Bearer `. Use your client's secret/environment support to supply that header. All requests, including initialization and tool discovery, require a valid credential. FlintVM advertises protected-resource metadata and authorization-server metadata. It implements public-client registration, authorization code with S256 PKCE, explicit signed-in user consent, exact redirect matching, resource-bound access tokens, refresh rotation with family revocation on replay, and revocation. Access tokens last 15 minutes; refresh tokens last seven days. Requested scopes must be explicitly supported. A refresh can narrow scopes, never expand them. A client requesting no scopes receives only `environments:read`. This local OAuth provider accepts **HTTP literal-loopback callbacks with explicit ports**, registered exactly. Clients requiring a custom URI scheme, hosted callback, or a different registration mechanism should use API keys or the stdio adapter. This limitation is intentional and must not be described as universal native-OAuth client compatibility. Browser authorization uses the existing FlintVM login, followed by a consent sheet; authorizing a client does not grant administrator access. ## Tools and scopes | Scope | Tools | | --- | --- | | `environments:read` | `flint_capabilities`, `flint_list_environments`, `flint_get_environment`, `flint_list_templates`, `flint_list_tasks`, `flint_list_images` | | `environments:write` | `flint_create_environment`, `flint_update_environment`, `flint_delete_environment` | | `workloads:execute` | `flint_start_desktop`, `flint_stop_desktop`, `flint_run_command`, `flint_execute` | | `desktop:control` | `flint_control`, `flint_screenshot` | | `files:read` | `flint_list_files`, `flint_download` | | `files:write` | `flint_upload` | | `images:write` | `flint_save_image`, `flint_clone_image` | Execution and desktop control can operate applications with full guest access; file writing can modify guest executables and startup configuration. These scopes are not intended to create separate security compartments inside a guest. None permits selecting a host executable, host socket, host upload/download path, or another user's workspace. Account disablement and password changes invalidate existing agent grants, including after re-enabling the account. Suggested agent workflow: 1. Read capabilities and templates. Choose an available resource plan, distribution, packages, desktop/browser controls, and optional encrypted disk storage. Creation does not start a VM. 2. Start the desktop and poll tasks until ready. `flint_execute` runs argv in that live VM; active commands prevent idle shutdown. For stopped environments, `flint_run_command` starts a bounded command task and returns its ID. 3. Use `flint_control` with a request such as `{"version":1,"action":"browser.navigate","url":"https://example.com"}`. Screenshots are returned as native MCP image content for vision-capable agents. See [agent controls](/docs/agent-controls.md) for exact action parameters. 4. Upload/download absolute **guest** paths in chunks of at most 256 KiB. `data` is base64, `offset` counts decoded bytes, and download `length` is bytes. Downloads return base64 in `stdout`; command status/exit must be checked. Upload offset zero replaces a file; subsequent offsets must match its size. Multi-chunk uploads are not atomic. Upload to a temporary guest path and use an execution grant to rename after verification when atomic publication is required. Read-only file grants cannot execute shell commands. 5. Stop the VM, save an image, then clone it for another independent environment. Requests and output are bounded. Commands in live desktops have a maximum five-minute timeout and one MiB per output stream. Parallel web requests are bounded by the service and your account limits. Polling status and viewing graphs do not prevent idle shutdown. ### Curated configuration and live variables Read `flint_capabilities` for the releases and resource plans available to your account. Use those choices when creating/updating environments; arbitrary sizes, unlisted releases are rejected by this service. Arch uses an empty release in structured requests. Networking should default to `user` when allowed by capabilities. Process limits are filled from account policy. `flint_search_packages` takes `distro`, `release`, and `query` (at least two characters), and returns up to 60 matches with cache freshness metadata. `flint_update_variables` takes `name`, current configuration `revision`, and a complete `variables` map. It requires `environments:write` and works while a desktop runs. Fetch the new revision before another write. New `flint_execute` calls inherit these variables (with per-call overrides); already-running applications do not change. --- Source: /docs/agent-controls.md # Desktop and browser controls Start an environment with **XFCE desktop**, **Desktop and browser controls for AI**, and, if needed, **Chromium browser** enabled. The available templates and options appear in the creation wizard. For an agent, discover them through `flint_capabilities` and `flint_list_templates`. Connect your harness using the [MCP guide](/docs/mcp.md). It needs `workloads:execute` to start a desktop and `desktop:control` to view or interact with it. Browser controls require a browser-enabled environment; viewer-only environments cannot accept control actions. ## Start and inspect Call `flint_start_desktop` with the environment name, then poll `flint_list_tasks` until it is running. Send actions through `flint_control`: ```json {"name":"flint_control","arguments":{"name":"research","request":{"version":1,"action":"status"}}} ``` The status response describes supported actions and current dimensions. `flint_screenshot` returns a desktop image directly to image-capable agents. Take a fresh screenshot before clicking coordinates, especially after resizing the desktop. ## Actions | Action | Fields | Result/use | | --- | --- | --- | | `status` | none | Supported actions, dimensions, browser and guest UID | | `desktop.screenshot` | none | `mimeType: image/png`, base64 `data` | | `desktop.move` | integer `x`, `y` | Move pointer within display bounds | | `desktop.click` | `x`, `y`; optional `button` 1–3, `count` 1–3 | Click or double click | | `desktop.type` | UTF-8 `text` up to 8192 bytes | Literal text into focused window; shell syntax has no special meaning to the API | | `desktop.key` | `key`, e.g. `Return`, `ctrl+l`, `alt+F2` | X11 key combination | | `desktop.scroll` | `direction`: up/down/left/right; optional `count` 1–20 | Scroll at the current pointer | | `browser.tabs` | none | `tabs` with `targetId`, title and URL | | `browser.focus` | optional `targetId` | Bring the tab to the front before physical desktop input | | `browser.navigate` | `url`, optional `targetId` | Start HTTP(S) navigation; does not wait for page load | | `browser.evaluate` | `expression`, optional `targetId` | CDP Runtime result, with by-value result under `result.result.value`; JS exceptions fail the call | | `browser.screenshot` | optional `targetId` | PNG `mimeType` and base64 `data` | | `browser.cdp` | `method`, optional object `params`, optional `targetId` | One CDP request and result; no event subscription | Browser actions default to the page only if exactly one tab is open. With multiple tabs, obtain and pass an explicit `targetId`. For browser-level CDP methods use `targetId: "browser"`. CDP page sessions attach for each call and detach afterwards; event subscriptions and session-scoped domain state do not persist. Use the version of the protocol supported by the installed Chromium. ## Example: navigate and check a page ```json {"name":"flint_control","arguments":{"name":"research","request":{"version":1,"action":"browser.navigate","url":"https://example.com"}}} ``` Navigation success means loading has started. Check the page before assuming it is ready: ```json {"name":"flint_control","arguments":{"name":"research","request":{"version":1,"action":"browser.evaluate","expression":"({title:document.title,ready:document.readyState})"}}} ``` Use `browser.focus` before typing into a browser window through desktop controls. Browser screenshots capture the page; desktop screenshots include panels and other windows. Inspect the resulting state after each meaningful action. Do not blindly repeat a click or form submission after a disconnect. ## Using the desktop yourself Open the environment’s Computer tab and connect the viewer. Choose **Take control** to interact. **Match display** resizes the guest screen to the viewer; **Fullscreen** makes it fill your display. Native VNC and Xpra connections are covered in [remote access](/docs/remote-access.md). ## Limits and saved work Send actions sequentially. Control requests are limited to 64 KiB, responses to 16 MiB, and guest actions to 25 seconds. The CDP action supports individual requests, not persistent event subscriptions or long-lived page sessions. Browser scripts and desktop controls act with the guest user’s privileges. They can change or delete that user’s files. Keep credentials out of saved environment variables and grant only the scopes your agent needs. Control activity counts as use; idle and maximum session limits still apply. Browser session profiles are temporary. Save downloads and work to persistent guest files, and use saved images to reuse installed software. Internet browsing depends on your environment’s network availability; it does not require port mappings. --- Source: /docs/remote-access.md # VM addresses and remote connections When remote connections are available, each VM has its own address. Find the address and supported protocols in its connection details. For example: ```text -research-.flintvm.xyz ``` The suffix prevents collisions when names are shortened or normalized. The same VM name under another account gets a different address. A hostname is an identifier, never an access credential. Teams do not implicitly share VM access. ## Find your VM address Open an environment's **Details → Remote connections**. The page shows its hostname and connection commands. An agent can call `flint_connection_info` with `{"name":"research"}`. Start the desktop before connecting. Use the actual gateway port with `--port` when it differs from 443. SSH and raw VNC do not transmit the DNS hostname to a shared server. The built-in `flint connect` helper carries the hostname and credential through a TLS WebSocket tunnel. Native clients connect through that helper; no Python proxy is needed. Create a scoped API key in **Agent connections** and save it in a private `0600` file outside the repository. SSH requires `workloads:execute`; VNC and Xpra require `desktop:control`. The key remains bound to its account. Expiry, revocation, account disable or VM shutdown closes the connection. ## SSH SSH uses a fixed transport to **guest loopback port 22**. It requires a compatible FlintVM guest agent and an SSH daemon configured inside the guest. The daemon still authenticates your guest SSH key; the gateway does not create a passwordless shell. ```sh ssh -i /private/guest_ed25519 \ -o 'ProxyCommand=flint connect %h --protocol ssh --key-file /private/flint.key' \ flint-desktop@YOUR-VM-HOSTNAME ``` Keep normal SSH host-key checking enabled. For a nonstandard gateway port, add `--port 8443` inside the ProxyCommand. Port 22 in the SSH client is the guest SSH service; the helper's port is the gateway TLS port. To prepare a Debian guest, install `openssh-server` through its package configuration before first provisioning, or install it inside an existing guest using authorized guest commands. Add your public key to the guest user's `~/.ssh/authorized_keys` (directory `0700`, file `0600`, owned by that user). Configure sshd with `ListenAddress 127.0.0.1`, `PubkeyAuthentication yes`, `PasswordAuthentication no`, `KbdInteractiveAuthentication no` and `PermitRootLogin no`. Generate guest host keys with `ssh-keygen -A`, then start/restart the guest SSH service. These commands apply inside the VM, not on the host. Regenerate SSH host keys when cloning an image that contains them. The gateway currently connects to running desktop VMs. It does not start a headless persistent VM or install a guest daemon implicitly. Existing legacy guest agents do not advertise the SSH bridge; keep using their desktop connection or migrate data into a new compatible image. A running desktop's `sshReady` connection-info field reports bridge support, not sshd installation or successful guest-key authentication. ## VNC Start the desktop with the VNC protocol (the web UI default). Create a private local directory and start a one-client tunnel: ```sh mkdir -m 700 -p "$HOME/.flint-connections" flint connect YOUR-VM-HOSTNAME --protocol vnc \ --key-file /private/flint.key \ --socket "$HOME/.flint-connections/vnc.sock" ``` In another terminal, use [TigerVNC Viewer](https://tigervnc.org/doc/vncviewer.html), which supports Unix sockets: ```sh vncviewer -AcceptClipboard=0 -SendClipboard=0 \ "$HOME/.flint-connections/vnc.sock" ``` The helper creates a `0600` Unix socket inside your private directory. It does not open an unauthenticated loopback TCP port that another local user could take over. It accepts one viewer and exits when that connection ends; rerun it to reconnect. ## Xpra Start the desktop with Xpra using **Start native Xpra desktop** in its connection details, or call `flint_start_desktop` with `{"name":"research","protocol":"xpra"}`. Stop an existing VNC desktop first. The browser's built-in viewer uses VNC; Xpra uses a native client. ```sh mkdir -m 700 -p "$HOME/.flint-connections" flint connect YOUR-VM-HOSTNAME --protocol xpra \ --key-file /private/flint.key \ --socket "$HOME/.flint-connections/xpra.sock" ``` In another terminal, use the [native Xpra client](https://xpra.org/manual): ```sh xpra attach "socket:$HOME/.flint-connections/xpra.sock" \ --clipboard=no --file-transfer=no --open-files=no --open-url=no \ --printing=no --webcam=no --speaker=off --microphone=off \ --notifications=no --mmap=no --remote-logging=no ``` VNC and Xpra are alternative running desktop protocols. The gateway rejects a protocol that does not match the current desktop. SSH can use its separate bridge alongside either one. ## Troubleshooting and boundaries - TLS failure: check that you copied the correct VM address. If it still fails, contact your administrator. Use a private CA file only if your administrator supplied it; keep certificate verification enabled. - Authentication failure: check key scope/expiry and account status. Never put credentials in a URL or command-line argument. - Connection unavailable: confirm that you own the VM and its desktop is running; contact your administrator if remote connections are unavailable. Another user's VM is deliberately indistinguishable from an unknown VM. - SSH closes immediately: confirm bridge compatibility and a guest SSH daemon on loopback port 22. Check guest sshd logs and key permissions. - Idle native sessions: inbound client activity updates the VM idle timer. An idle tunnel alone does not exempt the VM from shutdown. Use the bounded MCP execute workflow when AI commands need to hold the workload active. Remote connections are limited to your own environments and the protocols available to your account.