Configuration
Text

Configuration

exe's settings are in one file, ~/.exe/config.json. Windows → Configuration edits it in place, and Windows → Log Viewer shows what the daemon is doing and who is calling its API.

What they are for

  • Read exe in your language. The desk's menus, windows and messages come in English, Simplified Chinese or Japanese.
  • Decide who reaches exe. Set the address the desktop and the API listen on (your Tailscale IP, to use exe from your phone) and the token every API call must carry.
  • Connect it to the rest. The model behind Chat and the Agent tab, GitHub, a hub and Cloudflare each have a tab of their settings.
  • Size new VMs. The CPUs, memory and disk a VM gets when you leave them empty.
  • Look closer when something is wrong. The Log Viewer streams the daemon's own log and every request to the API, live.

An agent reads the same over HTTP: GET /v1/config is the whole configuration, and GET /v1/logs and GET /v1/logs/access stream the two logs. Chat can read the end of the daemon log as well, to work out why a publish or a VM failed. Changing the configuration is yours to do: an agent leaves it alone unless you ask.

The Configuration window

The Configuration window on its Daemon tab: listen, proxy_listen, ssh_listen, advertise_host, api_token and more

The fields are grouped on tabs: General, Daemon, VMs, Ollama, OpenAI, GitHub, Hub and Cloudflare, and on a Linux machine Firecracker, which runs the VMs there. Change what you want and press Save.

  • Most fields hot-reload on Save: they take effect at once.
  • Fields marked * take effect after a daemon restart: ssh_user, image_url and everything on the Firecracker tab. Restart Daemon…, on the Daemon tab, does it when pressed twice; the VMs restart too.
  • listen, proxy_listen and ssh_listen rebind as you save. If listen moved, reload the page at the new address.
  • Bind to Tailscale IP, on the Daemon tab of a machine on a tailnet, fills listen with that address for you to save.
  • The Hub tab shows this node on the hub the Hub app joined: its Hub ID, the same on every hub; whether that hub answers; this node's profile there; and whether the hub lets it post. Join a Hub… opens the Hub app's Join a Hub wizard. See The Hub.
  • The Cloudflare tab has no fields. It shows what the Cloudflare Setup Wizard set, and its Set Up… or Change… button opens the wizard. See Publishing to the web.

A few keys have no field in the window; vm_dir, the folder that holds the VMs' disks, is one. Edit the file for those and restart the daemon, which reads the file when it starts. Configuration, on the website, has a longer table of the keys, vm_dir among them.

The language of the desk

Language, on the General tab, is the language of the desk: English, 简体中文 (Simplified Chinese) or 日本語 (Japanese). Choose one and press Save. Every screen that has this node's desk open loads it again in that language. A screen with unsaved work on it waits until the work is saved, as it does for an update.

  • The key is language in the file: en, zh-Hans or ja. It is English when the key is not there.
  • Your own text stays as you wrote it: file names, notes, chats and the desktop menu. So do the names of products and the keys of the settings.
  • The apps in windows (Welcome, Blue Pencil, the Hub app and the others) and this manual are in English for now.

The settings you will want first

KeyTabWhat it sets
languageGeneralThe language of the desk's menus, windows and messages: en, zh-Hans or ja.
listenDaemonThe address of this UI and API. Bind it to your Tailscale IP to use exe from your phone.
api_tokenDaemonSet it before listening beyond localhost; every API call then needs it.
ssh_listenDaemonThe address of the SSH gate, :2222 unless changed; off disables it.
ssh_userDaemonThe user created in every VM (default dev). It is marked *.
default_cpus, default_memory_mb, default_disk_gbVMsThe size of a new VM when you leave its fields empty: 2 CPUs, 2048 MB and 20 GB unless changed.
ollama.*, chat_provider, openai.modelOllama, OpenAISee The coding agent.
github.client_idGitHubSee Publishing to GitHub.
hub.*HubSee The Hub.
cloudflare.*CloudflareSee Publishing to the web.

The API token

The desktop asks for the token by itself the first time a browser opens it, and checks it before keeping it (in localStorage).

The token goes on no address. Each time the desktop loads, it gives the token to exe and gets back a cookie that only exe's own pages can use and that no script can read. App windows, apps opened from /apps/, terminals and movies get in with that cookie. A new token ends every such cookie at once: each open terminal window says "signed out", and the desktop asks for the token again. The Terminal sessions stay in tmux, and the windows come back to them after you sign in. In a browser that keeps no cookies, the desktop puts the token on those addresses instead.

  • exe token, run on the machine that runs exe, shows it again.
  • Special → Set API Token… brings the dialog back.

Sign in with a passkey

A passkey signs a browser in to exe in place of the API token, with Face ID, Touch ID, Windows Hello or a security key. On a phone, you no longer type the token.

  1. Open the desktop at a name over HTTPS, such as its Tailscale Serve address. Passkeys do not work at an IP address.
  2. Choose Windows → Configuration, click the Passkeys tab, then click Add Passkey….
  3. In another browser, open the same address. The API Token dialog then offers Use Passkey….

A browser that signs in with a passkey keeps no token. It stays signed in until you remove the passkey or the token changes.

  • A passkey works only at the address it was made at.
  • Remove on the Passkeys tab ends the passkey and every browser it signed in, at once: their terminal windows say "signed out", and their Terminal sessions stay in tmux for the next sign-in.
  • Passkeys need an API token. Keep the token: it adds the first passkey, and it gets you back in when every passkey is gone. curl, agents and joined desks still use it.

The Log Viewer

Windows → Log Viewer streams two logs live, a tab each, when something needs a closer look.

  • Daemon Log is the daemon's own log, also kept in ~/.exe/daemon.log.
  • Access Log is every request to the API (this UI included), also kept in ~/.exe/access.log: one line each with the time, the caller's address, the request, its status, size and duration, and for Tailscale Serve the tailnet login.

API tokens in the URL are written as redacted, and in both logs every email address is masked to its first letter and domain ([email protected] shows as s***@example.com).

The access log's file moves to access.log.1 at 64 MB, so the two keep about twelve days of requests while two desktops are open.

Filter a log

Each tab has a Filter field at its top. It shows only the lines holding every word you type, in any case, and a word starting with - leaves out the lines holding it (GET -healthz).

  • New lines pass through the filter as they arrive.
  • The status line counts the matches.
  • Escape clears the field.
  • Each tab keeps its own filter and its own place while you look at the other.

Keep your place in a log

A line you have scrolled up to stays under your eye while the log keeps filling:

  • through the trim that drops the oldest lines once the printout is long;
  • through the reconnect that follows a daemon restart, which resends the recent lines and looks yours up again. A line the daemon no longer holds sends you to the tail.

This manual

This page lives at /docs.md, and the machine-readable counterpart for agents at /skill.md.

Contents