Make any text pattern clickable in Termix and other xterm.js-based web terminals.
Matched patterns get a persistent colored underline and become clickable -- opening a URL or copying to clipboard.
git clone https://github.com/stlas/termix-linkifier.git
cd termix-linkifier
# Make /opt/shared/ paths clickable (copies to clipboard)
./install.sh --container termix --pattern '/opt/shared/'
# Make /var/log/ paths open in a web viewer
./install.sh --container termix --pattern '/var/log/' \
--url 'http://logviewer.example.com/?file={path}'Reload Termix in your browser (Ctrl+Shift+R). Done.
termix-linkifier patches the minified xterm.js bundle inside your Termix installation to inject:
- A custom Link Provider that detects your text pattern and makes matches clickable
- Persistent Decorations that draw colored underlines beneath matched text (not just on hover)
- Staleness Detection that automatically removes decorations when the line content changes
The patch hooks into xterm.js's WebLinksAddon.activate() method -- the same code path that makes http:// URLs clickable. This ensures correct coordinate handling and native terminal rendering.
- The main JavaScript bundle (e.g.
assets/index-Ddwdsiux.js) is copied toindex-LINKIFIER.jswith the patch applied index.htmlis updated to load the patched bundle (with a cache-busting query string)- The original bundle is backed up as
*.bakfor easy uninstall
./install.sh [OPTIONS]
| Option | Description |
|---|---|
--pattern TEXT |
Text prefix to match (e.g. /opt/shared/, JIRA-, /var/log/) |
| Option | Description |
|---|---|
--clipboard |
Copy matched text to clipboard (default) |
--url TEMPLATE |
Open URL on click. Use {path} as placeholder for the matched text |
| Option | Default | Description |
|---|---|---|
--container NAME |
termix |
Docker container name |
--bundle-dir PATH |
/app/html/assets |
Asset directory inside container |
--index-html PATH |
/app/html/index.html |
index.html path inside container |
| Option | Description |
|---|---|
--local |
Work directly on filesystem instead of Docker |
--bundle-dir PATH |
Asset directory on local filesystem |
--index-html PATH |
index.html on local filesystem |
| Option | Default | Description |
|---|---|---|
--color HEX |
#4fc3f7 |
Color of the persistent underline |
--no-decoration |
Disable persistent underline (links still work on hover) |
| Option | Description |
|---|---|
--regex REGEX |
Custom JavaScript regex instead of auto-generated from --pattern |
--dry-run |
Preview what would happen without making changes |
./install.sh --container termix \
--pattern '/opt/shared/' \
--url 'http://viewer.example.com/?file={path}' \
--color '#4fc3f7'./install.sh --container termix \
--pattern 'JIRA-' \
--url 'https://jira.example.com/browse/{path}' \
--color '#ff9800'./install.sh --container termix \
--regex 'ERR-[0-9]{3,6}' \
--url 'https://docs.example.com/errors/{path}' \
--color '#ef5350'./install.sh --local \
--bundle-dir /srv/termix/html/assets \
--index-html /srv/termix/html/index.html \
--pattern '/home/' \
--clipboardWhen Termix is updated (e.g. via docker compose pull && docker compose up -d), the patched bundle is replaced by the new version. Simply re-run install.sh with the same parameters:
# Termix update
cd /path/to/termix && docker compose pull && docker compose up -d
# Re-apply linkifier (auto-detects new bundle)
./install.sh --container termix --pattern '/opt/shared/' \
--url 'http://viewer.example.com/?file={path}'The installer automatically adapts to different xterm.js bundle versions and minification styles -- no manual adjustments needed.
# Docker mode
./uninstall.sh --container termix
# Local mode
./uninstall.sh --local --bundle-dir /path/to/assets --index-html /path/to/index.htmlThis restores the original bundle from backup and updates index.html.
| Component | Tested Version |
|---|---|
| Termix | 1.11.0, 1.12.0+ |
| xterm.js | 5.x (with WebLinksAddon) |
| Browser | Chromium-based (Chrome, Brave, Edge) |
| Python | 3.6+ |
| Bash | 4.0+ |
| Docker | 20.0+ |
Should work with any web terminal that uses xterm.js with the @xterm/addon-web-links package.
- Python 3 (for the patcher -- available on most systems)
- Docker CLI (for container mode) or direct filesystem access (
--local) - Bash 4+
The patcher uses a regex to find the WebLinksAddon activation pattern in the minified bundle:
this._linkProvider=this._terminal.registerLinkProvider(
new s.WebLinkProvider(this._terminal,VAR,this._handler,VAR)
)}dispose
Where VAR matches any single-letter minified variable name. This makes the patcher resilient to different minification outputs across xterm.js versions.
It then injects:
- A custom
registerLinkProvidercall (using xterm.js's native API) - Optional
registerDecorationcalls for persistent visual highlighting - Staleness detection that disposes decorations when line content changes
Key technical insights discovered during development:
provideLinks(lineNumber)passes 1-based line numbers, butbuffer.getLine()expects 0-based indices- xterm.js's built-in
WebLinkProvidervalidates matches withnew URL(), so it only works for actual URLs -- custom patterns need a raw link provider registerMarker(offset)requiresbufferLine - (baseY + cursorY)as the offset parameterWebLinkProvider.computeLinkinternally appends thegregex flag, so never pass a regex that already has it- Forward slashes in regex patterns must be escaped as
\/inside JavaScript regex literals - Docker containers may run as non-root users -- use
docker cpinstead ofdocker execfor file operations
Public Domain (The Unlicense). Use it however you want.
Built by the RASSELBANDE -- a collaborative AI development team.