---
title: "Web"
description: "Serving the same workspace to a browser, the link that admits one, reaching other machines through it, the page's own settings, keys and phone layout, and what it cannot do."
url: "https://docs.closex.org/thinkterm/web.html"
markdown_url: "https://docs.closex.org/thinkterm/web.md"
site: "CloseX Docs"
product: "ThinkTerm"
language: "en"
last_updated: "2026-11-08T12:04:16.000Z"
alternates:
  en: "https://docs.closex.org/thinkterm/web.md"
  zh-Hans: "https://docs.closex.org/zh/thinkterm/web.md"
  ja: "https://docs.closex.org/ja/thinkterm/web.md"
---

# Web

> **Documentation in progress**
> Some sections are still incomplete.

A ThinkTerm multiplexer can serve its terminals to a browser. A phone, or a machine with no ThinkTerm on it, opens the sessions already running on the machine that has one — the same Spaces, Projects and Threads, not a copy of them.

Nothing listens until you ask for it.

## Turning it on

Three ways, all of them addressing a multiplexer server rather than the GUI's own in-process one:

- **`Settings › Web`** — a switch, the address it is accepting on, and the list of links you have handed out.
- **`thinkterm cli web-server on`** — the same thing from a shell. `--bind-address` chooses where to listen, `status` reports where it is accepting, and `off` closes the port and drops the browsers on it.
- **A `web_servers` entry in the configuration** — read when the server starts, so the port is open every time it runs.

The first two change a running server and last as long as it does. The config entry is the durable form; reloading the config does not open or close a web port. The one thing a reload does change is whether the page may reach other machines, described [below](#reaching-other-machines).

Local terminals have to be running in a background session server for there to be anything to serve — that setting is described in [Remote](https://docs.closex.org/thinkterm/remote.md), and a new installation starts with it on. Without one, `Settings › Web` says so rather than offering a switch that would do nothing. If the only thing attached is a remote domain, that section is about *that* machine's port, not this one's.

## The link is the credential

A browser is admitted by a token, and the token arrives as a URL:

```bash
thinkterm cli web-token mint --label phone --ttl 12h
```

Whoever opens that URL has what you have on that machine: a shell as your user, and every pane's scrollback. With [reaching other machines](#reaching-other-machines) on, the link also reaches every machine that account can SSH to. Treat it the way you treat an ssh key — in particular, do not paste one anywhere you would not paste a private key.

- `--ttl` takes `30m`, `12h`, `7d`, or a number of seconds. Without it the token lives until it is revoked. A link copied from Settings expires in eight hours unless you pick something else, up to `Until revoked`.
- `web-token list` shows every token the server knows, and how many browsers are on each.
- `web-token revoke <id>`, or `--all`, cuts them off at once, live browsers included.
- `--url-only` prints nothing but the URL, for scripts.

A connected browser appears in `thinkterm cli list-clients` under the label its token was minted with.

The token travels in the part of the URL after `#`, which a browser never sends to a server or in a `Referer`. The page moves it into the browser tab's own session storage and rewrites the address bar without it, so it is not bookmarked, shared or caught in a screenshot by accident. A reload in the same tab keeps working; a new tab, or the bare address, needs the link again and says so.

## Who can reach the port

Out of the box the listener binds `127.0.0.1:8088` — the machine it runs on, and nothing else.

`Reachable from other devices` rebinds it to every address the machine has, so turn it on only on a network you trust. Browsers only expose WebGPU to a secure context, and `http://localhost` is one while a plain `http://` to any other host is not, so a listener off loopback needs TLS: without a certificate of your own, ThinkTerm generates a self-signed one naming the machine's hostname and each of its addresses. A browser warns about that certificate once and then draws the page. Before you accept the warning, compare the certificate's SHA-256 fingerprint in the browser with the one `Settings › Web` shows, or the one the full `web-token mint` output prints — `--url-only` leaves it out — and stop if they differ. `require_tls_off_loopback`, on by default, is what refuses to serve a non-loopback address in the clear — a page served that way would have no WebGPU and show nothing anyway.

For a phone on the same network or tailnet, the QR code in `Settings › Web` is the short way to get the link across. Over the open internet, forward the loopback port with `ssh -L` rather than exposing it.

### Behind a reverse proxy

The listener accepts a page only from its own address. A page reached under any other name — through a reverse proxy, say `https://terminal.example.com` — has to be listed in `allowed_origins`, or its connection is refused. Listing any origin replaces that default, and the links `web-token mint` prints then point at the listed origins.

## Reaching other machines

A page can also open terminals on machines other than the one that served it. A browser cannot make an SSH connection, so the server does it: the page names a machine over a second WebSocket, `/relay`, which takes the same token; the server signs in to that machine over SSH and carries the page's connection to the ThinkTerm running there. The machine's Spaces, Projects and Threads then appear in the page beside this server's own, as a ThinkTerm Connect host's do on the desktop, with this server in the middle.

It is off until you turn it on, in either of two places:

- **`Settings › Web` › `Reach other machines`** on the desktop turns it on for every web listener on that machine.
- **`relay = true`** in a [`web_servers` entry](#the-web-servers-entry) turns it on for that one listener, which is how to turn it on for a server with no desktop. The entry is matched to the listener by its exact `bind_address`.

Either one is enough. Neither needs a restart: both are read again as the page uses them, so a config reload reaches pages that are already open, and turning both off ends the machines open through the relay within about two seconds. While it is off the Remote Hosts page lists nothing and says that reaching other machines is off on this server and where to turn it on; opening, adding or forgetting a machine is refused.

> **There is no list of allowed hosts**
> Whoever holds the link can open every machine the server's user can SSH to, signing in with that user's keys and `~/.ssh/config`, and can type in any other host, port and user as well. A link already gives a shell on the server, and through it whatever that server's SSH setup reaches; the relay adds no reach of its own, but it puts all of it behind the link.
>
> The connection is not encrypted end to end. The browser's TLS ends at this server and the SSH connection to the other machine starts there, so the server carries the traffic between them.

Revoking a link closes the machines opened through it along with its other connections.

### The Remote Hosts page

The globe button at the foot of the sidebar opens it as a tab of its own. `Remote Hosts` and `Add Remote Host…` are also among the search palette's commands, and the Space menu offers `Add Remote Host…`. Under `Connected` come this server and each machine open in the page, with how far a connection has got; the machines it can reach follow, each tagged with where it came from:

| Tag | Where the machine comes from |
|---|---|
| `~/.ssh/config` | The server's own `~/.ssh/config`, in a folded group of its own that opens while you search |
| `Desktop` | The hosts saved in the desktop's own host list on the server's machine, passwords saved there included |
| `Added here` | Hosts added from a page like this one, kept on the server |

`New Host` asks for a `Host`, and optionally a `Port` (22), a `User`, a `Name` and a `Password`. `Add and connect` saves it on the server in `web_machines.json`, with any password encrypted, and connects. `Forget` removes a machine that was added here, or whatever the server kept for the others: a saved password, or the go-ahead to install.

While a machine opens, the page shows each step — `Connecting…`, `Signing in…`, `Checking ThinkTerm there…` — and asks what only you can answer:

- **A password**, a key's passphrase, or a code the host asks for. A password or passphrase comes with `Remember on this server`, ticked by default. Ticked, the server keeps it encrypted the way the desktop keeps saved passwords, in the same folder as the host book, so the [caveats there](https://docs.closex.org/thinkterm/remote.md#saved-passwords) apply, and the next connection, and every reconnect, goes through without asking. A code is never kept.
- **`Trust this machine?`** the first time the server meets the host, with the host key's fingerprint to check. A host whose key has since changed fails with `Its host key has changed` instead of asking again.
- **`Install ThinkTerm there?`** when the machine has none. It goes into `~/.local/bin` for that user, without root, and is asked once per machine.

The ThinkTerm on the machine has to be one this server can talk to. An older one is updated without asking, and a running server there hands its sessions to the new one; if it cannot, the page asks `Stop the old ThinkTerm server there?`, since stopping it ends everything in it. A newer release there is left as it is, since its sessions would not come to an older build, and the page says to update this server; a build with a newer protocol that is not a newer release, such as a development build, is only replaced after `Replace the newer ThinkTerm there?`. A desktop installation is never replaced from here, and the page says to update that desktop app first. Where ThinkTerm cannot be used on the machine, the page offers `Open a plain SSH terminal` instead.

With more than one machine open, the Space menu groups the Spaces by machine, each machine other than this server with its own `New Space Here`, and `Add workspace…` gains a selector for the machine the Project goes on. Machines open in the page are reopened in the background the next time it loads.

## Settings › Web

| Row | What it does |
|---|---|
| `Allow browser access` | Opens or closes the port on the session server |
| `Reachable from other devices` | Listens on every address with its own certificate, instead of loopback only |
| `Reach other machines` | Lets a page open the machines this computer can SSH to, off by default. On, it applies to every web listener on this computer; off, only listeners with `relay = true` allow it. No restart needed. See [Reaching other machines](#reaching-other-machines) |
| `Access link` › `Copy link` | Mints a link and copies it |
| `Link expires` | How long the next copied link lives: 1 hour, 8 hours (the default), 1 day, 7 days or `Until revoked` |
| `Scan on your phone` › `Show code` | Mints a link and shows it as a QR code |
| `Links you have handed out` | Every live link, with a `Revoke` button each |
| `Every link` › `Revoke all` | Cuts off every browser at once |

Each handed-out link is named by the label it was minted with, otherwise by the device that last used it, otherwise `Not used yet`. Beneath it is when it expires and how many browsers are connected through it. `Revoke` ends that one link and drops the browsers using it; the others keep working.

## The `web_servers` entry {#the-web-servers-entry}

Each entry in `web_servers` is one port, read when the server starts:

```lua
config.web_servers = {
  {
    bind_address = '127.0.0.1:8088',
    token_file = wezterm.home_dir .. '/.local/share/thinkterm/web-tokens.json',
  },
}
```

| Field | Default | Meaning |
|---|---|---|
| `bind_address` | `127.0.0.1:8088` | The address and port to listen on |
| `pem_private_key` | unset | A PEM private key. With `pem_cert` set too, the port serves `https` and `wss` |
| `pem_cert` | unset | A PEM certificate |
| `pem_ca` | unset | A PEM CA chain |
| `static_dir` | beside the installed program | Where the page's files are |
| `token_file` | unset | Where minted tokens are kept, as digests |
| `allowed_origins` | the listener's own address | Origins allowed to open the connection |
| `require_tls_off_loopback` | `true` | Refuse to start without TLS on a non-loopback address |
| `relay` | `false` | Let a page opened on this listener reach other machines through the server. See [Reaching other machines](#reaching-other-machines) |

`relay` is the one field that is read again when the config reloads, including for pages already open. A reload does not open or close the port, change its certificate or move it.

**`token_file` matters more than it looks.** Unset, tokens live in the server's memory only: when the server restarts — after a reboot, or an update that cannot hand its sessions over — every link stops working and has to be minted again. Set it, and links survive a restart. The file holds digests, never the tokens, so a copy of it lets nobody in.

`static_dir` is for running a page other than the one installed, such as a development build; the `THINKTERM_WEB_STATIC_DIR` environment variable does the same without a config change, and `static_dir` wins when both are set.

## What the page can do

The browser draws the same workspace: the Space, Project and Thread tree, the tab strip, split panes, a search palette, and the right-hand panel. Threads and panes can be opened and closed from it.

The right-hand panel offers Snippets, Status, and the panels of installed [plugins](https://docs.closex.org/thinkterm/plugins.md). Snippets and plugins come from the machine that served the page, not the one the browser runs on: a browser pointed at a server sees that server's snippets and that server's plugins. A Run or Paste lands in the pane that had focus when you pressed it. Status is off until you turn it on with the button at the right end of the tab row. Like the desktop's, it shows what a program reports about itself: what it is doing, why it waits, a progress bar, and its sub-tasks folded into one line that opens on a click. Each agent carries the same mark as on the desktop: Claude Code, Copilot CLI and Kimi Code in colour (Kimi in a single colour on a light page), Codex, CodeBuddy Code, Cursor Agent, OpenCode and Pi in a single colour (OMP borrows Pi's), and, for a program with no mark of its own, the icon its pane's tab shows.

Tabs carry the same [program icons](https://docs.closex.org/thinkterm/window.md#tab-icons) as the desktop's. The cards are the ones set in the desktop's settings on the machine that served the page, not on the one the browser runs on.

Pictures sent with the Kitty graphics protocol are drawn in the page, animations included. PNG or JPEG pictures sent through the iTerm2 protocol are not yet.

### The sidebar

The sidebar shows one Space at a time, as the desktop's does: its name at the top, `New Thread`, pinned Threads under `Pinned`, then the Projects under `Workspaces` with their Threads. The `…` beside the Space's name lists the other Spaces and offers `New Space`, and renaming or deleting the one on show — never the last one.

From the page you can:

- create, rename, switch and delete Spaces
- add a Project by typing a directory on the server, `~/dir` or `/dir`, under `Add workspace…`; it comes with a `main` Thread
- collapse a Project by clicking it, rename it by double-clicking its name, archive it, restore it, remove it
- start, pin, unpin and delete Threads, rename one by double-clicking its name, and mark one unread
- drag a Thread within its Project, or a Project within the Space, to reorder them

Archived Projects collect under `Archived (N)` at the bottom of the Space; click it to show them. A Thread row's delete button and a tab's close button both ask a second time, showing `delete?` or `close?`, because they end the programs inside. Windows on the server that no Thread claims are listed under `Other windows`, so nothing is out of reach.

The sidebar's width is dragged at its edge and remembered by the browser. The button at the start of the tab row hides it; with `Reveal the sidebar on hover` on, resting the pointer on the left edge brings it back until the pointer leaves.

### Menus

Right-click offers the desktop's menus, less what the server has no operation for:

| On | Offers |
|---|---|
| A pane | `Copy`, `Paste`, `Split Right`, `Split Left`, `Split Down`, `Split Up`, `Frontend access` › `A · Shared (tmux-like)` / `B · Handoff (exclusive)` |
| A tab | `Close Tabs to Left`, `Close Tabs to Right`, `Close Other Tabs`, `New Terminal Tab to Right`, `Zoom Pane` |
| A Thread | `Pin Thread` or `Unpin Thread`, `Rename Thread…`, `Delete Thread`, `Mark as Unread` |
| A Project | `Rename Project…`, `New Thread`, `Collapse / Expand Threads`, `Archive Project…`, `Remove Project` |
| An archived Project | `Unarchive Project`, `Delete Permanently…` › `Delete Project and Threads` |

When a Project has panes running, `Archive Project…` says how many it will close before `Archive and Close Panes` does it. Renaming a tab, moving a tab between windows and `Reset Terminal` are desktop-only. Tabs can still be reordered by dragging them along the tab row, and a pane dragged onto the edge of another pane moves there.

Every pane carries a bar with its tabs on the left and, on the right, a new tab in that pane, split down, split right and zoom. A tab in that bar is named by the pane's label when it has one — set by renaming the tab on the desktop, or with `thinkterm cli set-pane-label` (see [Command Line](https://docs.closex.org/thinkterm/cli.md#naming-panes)) — and otherwise by the program's title. The tab strip above keeps the program's title, as the desktop's does.

### The search palette

`⌘K` on a Mac, `Ctrl+K` elsewhere, opens the search palette; the shortcut can be changed in the page's settings. It finds, in sections:

- `Find Thread` — Threads in every Space
- `Tabs` and `Panes` — those in the window on show
- `Switch Space` — the Spaces
- `Commands` — `New Thread`, `New Tab`, `Split Right`, `Split Down`, `Zoom Pane`, `Close Pane`, `Take Over the Terminal`, `Follow the Desktop's Focus`, `Show or Hide the Sidebar`, `Settings`, `Increase font size`, `Decrease font size`, `Reset font size`

With nothing typed, the things you picked recently come first. Arrows move, `Enter` runs, `Esc` closes. The magnifier at the foot of the sidebar opens it with Threads only.

### Who drives the terminal

How a terminal is shared is the server's choice: the pane menu's `Frontend access` submenu switches it, with a tick by the current one. The server keeps the choice, across restarts too, so it applies to every device attached to it, not only this page.

**`B · Handoff (exclusive)`**, the default, gives a terminal one driver at a time. Opening a terminal the desktop is holding puts a card over it — `Terminal is being used on another device`, `Click or scroll to continue` — and the terminal stays visible underneath. A click, a scroll or a keystroke in it takes it over. The first keystroke is not lost; it is typed once the handoff completes. Clicks on the tab row, the pane bars and the sidebar never take it. `Ctrl+Shift+T`, or `Take Over the Terminal` in the palette, takes it explicitly. That is the same handoff described in [Remote](https://docs.closex.org/thinkterm/remote.md), with a browser counting as one device identified by its link — two tabs opened from the same link share a turn.

**`A · Shared (tmux-like)`** has no driver to hand over: every attached client sees the same terminals and can type into them, and the last one to interact with a tab decides its size.

While the page holds a tab, the tab is reshaped to the browser window. While the desktop holds it, the page keeps the desktop's size and shape, and clips when the tab is larger than the window. `Ctrl+Shift+F` reshapes the tab to this window on demand.

**`Follow the Desktop's Focus`**, on when the page opens, keeps one focus between the two: when the desktop moves to another pane, the page moves with it, and a click on a pane in the page moves the desktop. Run the command again to stop following; it is not remembered across loads.

### Clipboard

Selecting text with the mouse copies it as soon as you let go. A double click selects a word, a triple click a line. When a program has asked for the mouse, hold `Shift` to select text yourself. `Copy` and `Paste` are also in the pane menu.

A program can set the clipboard with OSC 52, but only from a pane the page is showing: a pane nobody is looking at does not get to write this device's clipboard.

### Keyboard shortcuts

| Keys | Action |
|---|---|
| `Cmd+C` or `Ctrl+Shift+C` | Copy the selection |
| `Cmd+V` or `Ctrl+Shift+V` | Paste |
| `Ctrl+Shift+Enter` | Split right |
| `Ctrl+Shift+\` | Split down |
| `Ctrl+Shift+Z` | Zoom the pane, or unzoom it |
| `Ctrl+Shift+F` | Fit the tab to this window |
| `Ctrl+Shift+T` | Take the terminal over |
| `Ctrl+Shift` with an arrow | Focus the neighbouring pane, without moving the desktop's focus |
| `Cmd+=`, `Cmd+-`, `Cmd+0` | The focused pane's font size: larger, smaller, reset |
| `⌘K` / `Ctrl+K` | The search palette, unless another shortcut is chosen |

Every other `Cmd` combination is left to the browser — reload, the address bar, tabs — and never reaches the terminal. Everything else goes to the focused pane, including `Ctrl` keys, so the default palette shortcut means `Ctrl+K` does not reach the terminal off a Mac; pick `Ctrl+Shift+P` in the settings if a program needs it. Input methods work: keys the input method is composing stay with it, and its candidate window follows the terminal cursor. On WebKit browsers — Safari, and every browser on iOS — the Return that picks a candidate is not sent to the terminal as well.

## On a phone

The page switches to its phone layout when the pointer is a finger, or when the window is narrower than 720 pixels. Reach the server over `https` first, as described above.

- The terminal takes the whole screen. The sidebar and Status become drawers over it; a swipe in from the left edge brings the sidebar out, and a swipe back to the left puts it away. Picking a Thread in the drawer closes it.
- A key bar along the bottom carries `Esc`, `Tab`, `Ctrl` and `Alt`, the four arrows, `Home`, `End`, `PgUp`, `PgDn`, and `-` `/` `|` `~`. `Ctrl` and `Alt` are sticky: tap one, and it applies to the next key from the bar or from the soft keyboard. Holding an arrow repeats it.
- The soft keyboard appears only when you ask for it with the keyboard button on the key bar, so a tap on the terminal does not cover half the screen. The button stays at the start of the bar while the keys scroll beside it.
- A finger drag scrolls, and a flick keeps scrolling. A finger put down on a split divider, within a finger's width of it, drags the divider instead. Two fingers scroll too; pinching changes the font size of the pane under them.
- A tap is a click. A long press, half a second, opens the pane's menu.
- A tab with a single pane shows no pane bar; one appears when there is a split to tell apart.

Text cannot be selected by touch: a drag in a pane scrolls it.

## The page's own settings

The gear at the foot of the sidebar opens the page's settings. They belong to this browser, not to the server or your account. On a phone they are two pages, as a phone's own are: the list of sections, then the one you picked, with a way back.

| Section | Setting | Choices |
|---|---|---|
| General | `Language` | `Follow System` — the browser's languages — or one of ThinkTerm's languages |
| General | `Scrolling` | `Smooth` (default), following a finger or trackpad by the pixel, or `Stepped`, a row at a time |
| General | `Search shortcut` | `⌘K` (default), `⌘⇧P`, `Ctrl+Shift+P`. Off a Mac, `⌘` means `Ctrl` |
| Appearance | `Color scheme` | `Follow the desktop` (default), using the scheme the server is configured with, or any built-in scheme |
| Appearance | `Theme` | `Dark` (default), `Light` or `Follow System`, for the page around the terminal |
| Appearance | `Font size` | `Follow the desktop`, so a cell here matches one there, or `Fixed size`, 6 to 72 in half-point steps |
| Sidebar & Plugins | `Reveal the sidebar on hover` | On by default |
| Sidebar & Plugins | `Reset sidebar width` | Puts the sidebar back to its default width |
| Sidebar & Plugins | `Status`, `Snippets` | Whether the right-hand panel offers them |
| Sidebar & Plugins | `Reload plugins`, and each plugin | A switch, and how long it runs unused. A plugin you have never allowed shows `New: it does not run until you allow it` and an `Allow` button instead |
| About | `Copy Info` | A card with the version and `Copy Info`, which copies the version, build, language and browser; then `Version`, `Build`, `Host` — the address the page came from — `Language` and `License` |

`Color scheme` opens a searchable list with each scheme's colours beside it; the terminal previews whichever row is under the pointer or the arrows, `Enter` keeps it, and `Esc` puts back what you had. The search box at the top of the settings finds a row in any section.

### Where they are kept

In the browser's local storage, along with the Space the page was last showing, the palette's recent picks, the sidebar's width, the machines open in Remote Hosts (`thinkterm.machines`), which are reopened on load, and the picked colour scheme with its colours, so the next load draws in it straight away. Another browser, or a private window, starts from the defaults. Nothing of this goes to the server. A browser that blocks storage keeps the settings for that load only.

### URL overrides

A URL can override some settings for one load, without changing what is stored:

| Parameter | Effect |
|---|---|
| `?lang=de-DE` | The page's language |
| `?theme=light` | `light`, `dark` or `system` |
| `?font=14` | A fixed font size, 6 to 72 |
| `?glyphfont=` | The CSS font list used for characters the page's own fonts lack, which also picks the regional shape of Han characters |

Put them before the `#` of a minted link: `https://example-host:8088/?theme=light#token=…`.

## When the connection drops

The page reconnects by itself, to the same tab: once straight away, then after a second, doubling the wait each time up to fifteen seconds. A note at the bottom right says the connection was lost and that it is reconnecting. After six failed attempts it adds that the link may have expired, or the server may be down — a browser is not told why a connection was refused, so a revoked link, an expired one and a stopped server look the same from the page.

What was on screen stays there while it is down, and the tab is laid out again from the server once it is back. The page gives up only when there is nothing to come back to: the server has no panes, or speaks a different protocol version. It says which.

## What the page cannot do

- **Files and Notes** — desktop-only for now.
- **Live Overview** — there is no browser counterpart, and no button for it.
- **Thread references** — they are the desktop's own and are not shown. Projects on an SSH host are not shown either: the server could not open them.
- **Notifications and sounds** — the bell has nothing in it, and nothing plays.
- **Links** — links in the output cannot be clicked.
- **Scrollback search, copy mode and quick select** — the palette searches the workspace, not the text in a pane.
- **Selecting by touch** — on a phone, dragging scrolls.
- **iTerm2 images** — PNG and JPEG pictures sent through the iTerm2 protocol are not drawn yet.
- **Right-to-left text** — shown as boxes, since the page does not reorder bidirectional text and correct letters in the wrong order would be harder to notice.
- **Renaming or moving tabs between windows, Reset Terminal** — the server has no operation for them.

Characters the page's two bundled fonts lack — CJK, Hangul, emoji — are drawn with the fonts installed on the device the browser runs on. A character none of them has shows as a box. Without WebGPU the page shows nothing but a message saying to open it over `https` or `http://localhost` in a browser with WebGPU enabled.

## Related

- [Remote](https://docs.closex.org/thinkterm/remote.md) — the session server that serves the browser, and how the handoff works
- [Command Line](https://docs.closex.org/thinkterm/cli.md) — `web-server` and `web-token` in full
- [Plugins](https://docs.closex.org/thinkterm/plugins.md) — the panels a browser shows from the server's machine
- [Spaces, Projects and Threads](https://docs.closex.org/thinkterm/spaces.md) — the workspace the page shows
- [Privacy and Security](https://docs.closex.org/thinkterm/privacy.md) — what the page stores and sends
- [Configuration](https://docs.closex.org/thinkterm/configuration.md) — where `web_servers` and the listener's certificate live
