termroom 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- termroom-0.1.0/.gitignore +22 -0
- termroom-0.1.0/LICENSE +21 -0
- termroom-0.1.0/PKG-INFO +364 -0
- termroom-0.1.0/README.md +346 -0
- termroom-0.1.0/pyproject.toml +58 -0
- termroom-0.1.0/termroom/__init__.py +3 -0
- termroom-0.1.0/termroom/app.py +2749 -0
- termroom-0.1.0/termroom/assets.py +83 -0
- termroom-0.1.0/termroom/auth.py +106 -0
- termroom-0.1.0/termroom/cli.py +530 -0
- termroom-0.1.0/termroom/config.py +191 -0
- termroom-0.1.0/termroom/db.py +511 -0
- termroom-0.1.0/termroom/files.py +501 -0
- termroom-0.1.0/termroom/i18n.py +122 -0
- termroom-0.1.0/termroom/locales/en.json +406 -0
- termroom-0.1.0/termroom/locales/ko.json +406 -0
- termroom-0.1.0/termroom/pty_process.py +122 -0
- termroom-0.1.0/termroom/pwa_icon.py +73 -0
- termroom-0.1.0/termroom/runtime.py +56 -0
- termroom-0.1.0/termroom/secrets.py +87 -0
- termroom-0.1.0/termroom/security.py +56 -0
- termroom-0.1.0/termroom/ssh_askpass.py +24 -0
- termroom-0.1.0/termroom/ssh_backend.py +1460 -0
- termroom-0.1.0/termroom/static/app.css +5284 -0
- termroom-0.1.0/termroom/static/app.js +826 -0
- termroom-0.1.0/termroom/static/manifest.webmanifest +31 -0
- termroom-0.1.0/termroom/static/sw.js +8 -0
- termroom-0.1.0/termroom/static/terminal.js +460 -0
- termroom-0.1.0/termroom/static/termroom-icon.svg +5 -0
- termroom-0.1.0/termroom/static/vendor/xterm.LICENSE +21 -0
- termroom-0.1.0/termroom/static/vendor/xterm.css +285 -0
- termroom-0.1.0/termroom/static/vendor/xterm.js +2 -0
- termroom-0.1.0/termroom/static/vendor/xterm.version +1 -0
- termroom-0.1.0/termroom/templates/base.html +60 -0
- termroom-0.1.0/termroom/templates/computer.html +80 -0
- termroom-0.1.0/termroom/templates/computer_new.html +132 -0
- termroom-0.1.0/termroom/templates/editor.html +61 -0
- termroom-0.1.0/termroom/templates/error.html +8 -0
- termroom-0.1.0/termroom/templates/file_view.html +99 -0
- termroom-0.1.0/termroom/templates/files.html +214 -0
- termroom-0.1.0/termroom/templates/home.html +61 -0
- termroom-0.1.0/termroom/templates/login.html +17 -0
- termroom-0.1.0/termroom/templates/recent.html +73 -0
- termroom-0.1.0/termroom/templates/scrollback.html +16 -0
- termroom-0.1.0/termroom/templates/terminal.html +157 -0
- termroom-0.1.0/termroom/templates/workspace_base.html +72 -0
- termroom-0.1.0/termroom/templates/workspace_open.html +327 -0
- termroom-0.1.0/termroom/terminal_control.py +96 -0
- termroom-0.1.0/termroom/terminals.py +372 -0
- termroom-0.1.0/termroom/workspaces.py +126 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.venv/
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.log
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
.ruff_cache/
|
|
7
|
+
.uv-cache/
|
|
8
|
+
.qa-*/
|
|
9
|
+
.xterm*-inspect/
|
|
10
|
+
.termroom-state/
|
|
11
|
+
.qa-*.txt
|
|
12
|
+
.coverage
|
|
13
|
+
htmlcov/
|
|
14
|
+
dist/
|
|
15
|
+
build/
|
|
16
|
+
*.egg-info/
|
|
17
|
+
.termroom/
|
|
18
|
+
.env
|
|
19
|
+
.DS_Store
|
|
20
|
+
.idea/
|
|
21
|
+
.vscode/
|
|
22
|
+
.~lock.*#
|
termroom-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 huhumanmaninganingansalamlam
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
termroom-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: termroom
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Self-hosted Linux workspace for persistent tmux terminals and files
|
|
5
|
+
Project-URL: Repository, https://github.com/huhumanmaninganingansalamlam/termroom
|
|
6
|
+
Author: Termroom contributors
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
License-File: termroom/static/vendor/xterm.LICENSE
|
|
10
|
+
Requires-Python: >=3.12
|
|
11
|
+
Requires-Dist: cryptography<51,>=43
|
|
12
|
+
Requires-Dist: fastapi<1,>=0.115
|
|
13
|
+
Requires-Dist: jinja2<4,>=3.1
|
|
14
|
+
Requires-Dist: paramiko<5,>=3.5
|
|
15
|
+
Requires-Dist: python-multipart<1,>=0.0.20
|
|
16
|
+
Requires-Dist: uvicorn[standard]<1,>=0.34
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# Termroom
|
|
20
|
+
|
|
21
|
+
[English](https://github.com/huhumanmaninganingansalamlam/termroom/blob/main/README.md) · [한국어](https://github.com/huhumanmaninganingansalamlam/termroom/blob/main/README.ko.md)
|
|
22
|
+
|
|
23
|
+
**A personal workspace for continuing terminal work from a browser.**
|
|
24
|
+
|
|
25
|
+
Run `termroom .` inside a project folder to open its terminals and files in your
|
|
26
|
+
browser. `tmux` keeps terminal processes alive, so closing the browser or switching
|
|
27
|
+
devices does not end the work that is already running.
|
|
28
|
+
|
|
29
|
+
Termroom is aimed at workflows such as starting a long build or AI task on a laptop,
|
|
30
|
+
checking it from a phone later, and working with remote Linux servers through the same
|
|
31
|
+
terminal-and-files interface.
|
|
32
|
+
|
|
33
|
+
> **Status: early release.** Termroom is available as a Python CLI package and the
|
|
34
|
+
> project is still evolving quickly. Expect small workflow and UI changes between
|
|
35
|
+
> early versions.
|
|
36
|
+
|
|
37
|
+
## When is it useful?
|
|
38
|
+
|
|
39
|
+
- Check a long-running command from a phone or tablet after starting it on your PC.
|
|
40
|
+
- Keep terminal work alive even when the browser is closed.
|
|
41
|
+
- Browse, upload, download, or edit project files from the browser.
|
|
42
|
+
- Move between several local projects from one interface.
|
|
43
|
+
- Use SSH Linux servers in a workflow similar to local projects.
|
|
44
|
+
|
|
45
|
+
Termroom is not a cloud IDE. **The real terminal processes and files stay on your Linux
|
|
46
|
+
computer or on an SSH server you control.** Termroom provides the browser interface.
|
|
47
|
+
|
|
48
|
+
## Quick start
|
|
49
|
+
|
|
50
|
+
### 1. Requirements
|
|
51
|
+
|
|
52
|
+
The current release requires:
|
|
53
|
+
|
|
54
|
+
- Linux
|
|
55
|
+
- Python 3.12+
|
|
56
|
+
- `tmux`
|
|
57
|
+
|
|
58
|
+
For example, on Ubuntu/Debian systems, install `tmux` if needed:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
sudo apt install tmux
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 2. Install Termroom
|
|
65
|
+
|
|
66
|
+
For a CLI application, an isolated tool environment is the cleanest option. With
|
|
67
|
+
[`uv`](https://docs.astral.sh/uv/):
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
uv tool install termroom
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Or with `pipx`:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pipx install termroom
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Regular `pip` installation is also supported:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pip install termroom
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
After installation, the `termroom` command is available from your shell. `uv tool`
|
|
86
|
+
and `pipx` are recommended because they keep Termroom's dependencies isolated from
|
|
87
|
+
other Python applications.
|
|
88
|
+
|
|
89
|
+
> If your shell says `termroom: command not found`, run `uv tool update-shell` once and
|
|
90
|
+
> open a new terminal when you installed it with `uv tool`.
|
|
91
|
+
|
|
92
|
+
### 3. Open your project
|
|
93
|
+
|
|
94
|
+
Store the Termroom login password once in its global configuration:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
mkdir -p ~/.config/termroom
|
|
98
|
+
printf '%s\n' 'TERMROOM_PASSWORD=choose-a-password' 'TERMROOM_LOCALE=en' > ~/.config/termroom/.env
|
|
99
|
+
chmod 600 ~/.config/termroom/.env
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Then move to the project you actually want to use:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
cd ~/my-project
|
|
106
|
+
termroom .
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Termroom starts in the background and opens your browser automatically. You can also
|
|
110
|
+
open the printed URL manually. Sign in with the password stored in
|
|
111
|
+
`~/.config/termroom/.env`.
|
|
112
|
+
|
|
113
|
+
Once a Termroom Core is already running on the same computer, another project can be
|
|
114
|
+
added with:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
cd ~/another-project
|
|
118
|
+
termroom .
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## What can it do?
|
|
122
|
+
|
|
123
|
+
### Terminal
|
|
124
|
+
|
|
125
|
+
- Use real shell and TUI programs in the browser.
|
|
126
|
+
- Keep work running in `tmux` after the browser closes.
|
|
127
|
+
- Create, rename, and close multiple terminals per Workspace.
|
|
128
|
+
- Reopen the same terminal after reconnecting.
|
|
129
|
+
- Mobile CJK/IME input and touch helper keys.
|
|
130
|
+
- Optional command-editing mode for long commands.
|
|
131
|
+
- Browser-local terminal font-size settings.
|
|
132
|
+
- Search and copy existing `tmux` scrollback.
|
|
133
|
+
|
|
134
|
+
### Files
|
|
135
|
+
|
|
136
|
+
- Browse and search project folders.
|
|
137
|
+
- Select several files or folders and download them as a ZIP.
|
|
138
|
+
- Upload multiple files with overwrite confirmation.
|
|
139
|
+
- Create files/folders, rename, and delete them.
|
|
140
|
+
- Edit small text files directly in the browser.
|
|
141
|
+
- Preview images/PDFs, JSON/CSV, and bounded portions of large text files.
|
|
142
|
+
- Use the same Files UI for local and SSH projects.
|
|
143
|
+
|
|
144
|
+
### Recent
|
|
145
|
+
|
|
146
|
+
- See recently created or modified files.
|
|
147
|
+
- See recently used terminals and activity timestamps.
|
|
148
|
+
- Identify files that are still growing.
|
|
149
|
+
- Exclude dependency/cache/hidden directories by default.
|
|
150
|
+
- Add project-specific rules with `.termroomignore`.
|
|
151
|
+
|
|
152
|
+
## The basic model
|
|
153
|
+
|
|
154
|
+
In Termroom, a **Workspace is simply one project folder**.
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
Computer
|
|
158
|
+
└─ Workspace (project folder)
|
|
159
|
+
├─ Terminal
|
|
160
|
+
├─ Files
|
|
161
|
+
└─ Recent
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
A `Computer` is either this Linux machine or an SSH Linux server you registered.
|
|
165
|
+
|
|
166
|
+
### Local projects
|
|
167
|
+
|
|
168
|
+
The simplest path is to run Termroom from the project folder:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
cd ~/projects/example
|
|
172
|
+
termroom .
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The web UI can also open other allowed folders on this computer as Workspaces.
|
|
176
|
+
|
|
177
|
+
Choose **Add location → Browse folders** to start from your home directory and click through
|
|
178
|
+
folders instead of typing an absolute path. Direct path entry remains available when you
|
|
179
|
+
already know it.
|
|
180
|
+
|
|
181
|
+
### SSH servers
|
|
182
|
+
|
|
183
|
+
Choose **Add SSH computer** in the web UI, then:
|
|
184
|
+
|
|
185
|
+
```text
|
|
186
|
+
Enter SSH address
|
|
187
|
+
→ verify the host-key fingerprint
|
|
188
|
+
→ choose password / Termroom-managed key / existing key authentication
|
|
189
|
+
→ browse from the remote home folder or type the project path directly
|
|
190
|
+
→ open the Workspace
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The remote Linux host needs an SSH server and `tmux`.
|
|
194
|
+
|
|
195
|
+
## Common commands
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
termroom . # Open the current project
|
|
199
|
+
termroom /path/to/project # Open a specific project
|
|
200
|
+
termroom attach . # Attach directly to this Workspace's tmux session
|
|
201
|
+
termroom stop . # Stop this Workspace's tmux session
|
|
202
|
+
termroom stop --core # Stop only the Termroom web Core
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
The **Core** is Termroom's background web process. Normally one Core runs per computer
|
|
206
|
+
and manages multiple Workspaces.
|
|
207
|
+
|
|
208
|
+
When Docker or systemd owns the process lifecycle, run it in the foreground:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
termroom /srv/projects --foreground --no-open
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Access from another device
|
|
215
|
+
|
|
216
|
+
The default bind address is `127.0.0.1`, so **only the computer running Termroom can
|
|
217
|
+
connect by default.**
|
|
218
|
+
|
|
219
|
+
For phones, tablets, or other computers, prefer an existing LAN, VPN/Tailscale network,
|
|
220
|
+
or an HTTPS reverse proxy that you operate.
|
|
221
|
+
|
|
222
|
+
To bind to other interfaces explicitly:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
termroom ~/projects --host 0.0.0.0
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Behind an HTTPS reverse proxy, enable secure cookies:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
termroom ~/projects --host 0.0.0.0 --secure-cookie
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Termroom is not designed to be exposed directly to the public internet without an
|
|
235
|
+
appropriate private network or HTTPS setup.
|
|
236
|
+
|
|
237
|
+
## Password and configuration
|
|
238
|
+
|
|
239
|
+
Login requires `TERMROOM_PASSWORD`. For a normal install, keep it in Termroom's global
|
|
240
|
+
configuration file at `~/.config/termroom/.env`.
|
|
241
|
+
|
|
242
|
+
```text
|
|
243
|
+
TERMROOM_PASSWORD=change-this-password
|
|
244
|
+
TERMROOM_LOCALE=en
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
`TERMROOM_LOCALE` controls the initial UI language for browsers that have not
|
|
248
|
+
chosen a language yet. Supported values are `en` and `ko`. A language selected
|
|
249
|
+
in the web UI is stored in that browser and overrides this default.
|
|
250
|
+
|
|
251
|
+
Restrict the file so other users cannot read it:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
chmod 600 ~/.config/termroom/.env
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
If a shell or service manager provides `TERMROOM_PASSWORD`, the environment variable takes
|
|
258
|
+
priority over the global `.env`. Project-folder `.env` files remain a compatibility fallback,
|
|
259
|
+
but the global file is recommended so Termroom's login password is not mixed with project
|
|
260
|
+
configuration.
|
|
261
|
+
|
|
262
|
+
Termroom does not enforce a minimum password length by default. Operators can opt in:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
TERMROOM_MIN_PASSWORD_LENGTH=12
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Persistent state defaults to `~/.config/termroom/`:
|
|
269
|
+
|
|
270
|
+
```text
|
|
271
|
+
.env # optional global password / default locale
|
|
272
|
+
termroom.sqlite3
|
|
273
|
+
access-token
|
|
274
|
+
credential-key
|
|
275
|
+
credentials/
|
|
276
|
+
ssh/
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Override the location with `--config-dir` or `TERMROOM_CONFIG_DIR`.
|
|
280
|
+
|
|
281
|
+
SSH passwords are not stored as plaintext in project files or the SQLite DB. They are
|
|
282
|
+
stored in owner-only encrypted credential files under the config directory. This is not
|
|
283
|
+
a replacement for a hardware-backed vault.
|
|
284
|
+
|
|
285
|
+
## Docker Compose
|
|
286
|
+
|
|
287
|
+
To run with Docker:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
cp .env.example .env
|
|
291
|
+
# Change TERMROOM_PASSWORD
|
|
292
|
+
docker compose up -d --build
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
The included Compose configuration uses:
|
|
296
|
+
|
|
297
|
+
- `termroom-config:/config` for persistent DB, SSH-key, and credential state
|
|
298
|
+
- `./workspaces:/workspaces` for local content visible to the Core
|
|
299
|
+
- `127.0.0.1:8765:8765` as the default host publish
|
|
300
|
+
|
|
301
|
+
Replace the volume or bind mount to fit your deployment.
|
|
302
|
+
|
|
303
|
+
## PWA and languages
|
|
304
|
+
|
|
305
|
+
Termroom includes an installable PWA manifest and icons. The Service Worker does not
|
|
306
|
+
offline-cache authenticated Workspace, file, or terminal responses.
|
|
307
|
+
|
|
308
|
+
The UI defaults to English. Korean is available from the language selector. Locale
|
|
309
|
+
sources live in `termroom/locales/`.
|
|
310
|
+
|
|
311
|
+
## Technical overview
|
|
312
|
+
|
|
313
|
+
`tmux`, not the browser, is what keeps terminal work alive.
|
|
314
|
+
|
|
315
|
+
```text
|
|
316
|
+
Browser / PWA
|
|
317
|
+
│
|
|
318
|
+
▼
|
|
319
|
+
Termroom Core
|
|
320
|
+
├─ Local filesystem + local tmux
|
|
321
|
+
└─ SFTP + OpenSSH + remote tmux
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Local terminals connect xterm.js in the browser to a real PTY over WebSocket. SSH
|
|
325
|
+
Workspaces use the local OpenSSH client and SFTP. See
|
|
326
|
+
[`docs/architecture.md`](docs/architecture.md) for the data model and security boundaries.
|
|
327
|
+
|
|
328
|
+
## Development
|
|
329
|
+
|
|
330
|
+
For source development, use the project virtual environment:
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
git clone https://github.com/huhumanmaninganingansalamlam/termroom.git
|
|
334
|
+
cd termroom
|
|
335
|
+
uv sync --all-groups
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Validation commands:
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
uv run --frozen ruff check termroom tests
|
|
342
|
+
uv run --frozen pytest
|
|
343
|
+
node --check termroom/static/app.js
|
|
344
|
+
node --check termroom/static/terminal.js
|
|
345
|
+
docker compose config
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
User-facing changes should also be exercised in real browsers across mobile, tablet,
|
|
349
|
+
and desktop layouts.
|
|
350
|
+
|
|
351
|
+
## Documentation
|
|
352
|
+
|
|
353
|
+
- [`docs/architecture.md`](docs/architecture.md) — data model, terminal/file pipelines,
|
|
354
|
+
and security boundaries
|
|
355
|
+
- [`docs/mobile-terminal.md`](docs/mobile-terminal.md) — mobile terminal and IME input
|
|
356
|
+
contract
|
|
357
|
+
- [`docs/i18n.md`](docs/i18n.md) — locale and translation rules
|
|
358
|
+
- [`CONTRIBUTING.md`](CONTRIBUTING.md) — development setup and contribution rules
|
|
359
|
+
|
|
360
|
+
## License
|
|
361
|
+
|
|
362
|
+
Termroom's original code is distributed under the [MIT License](LICENSE).
|
|
363
|
+
Vendored `@xterm/xterm 6.0.0` is also MIT-licensed; its upstream copyright notice is
|
|
364
|
+
preserved in [`termroom/static/vendor/xterm.LICENSE`](termroom/static/vendor/xterm.LICENSE).
|