File: README.md
Wave Terminal
Wave is an open-source, AI-integrated terminal for macOS, Linux, and Windows. It works with any AI model. Bring your own API keys for OpenAI, Claude, or Gemini, or run local models via Ollama and LM Studio. No accounts required.
Wave also supports durable SSH sessions that survive network interruptions and restarts, with automatic reconnection. Edit remote files with a built-in graphical editor and preview files inline without leaving the terminal.
Key Features
- Wave AI - Context-aware terminal assistant that reads your terminal output, analyzes widgets, and performs file operations
- Durable SSH Sessions - Remote terminal sessions survive connection interruptions, network changes, and Wave restarts with automatic reconnection
- Flexible drag & drop interface to organize terminal blocks, editors, web browsers, and AI assistants
- Built-in editor for editing remote files with syntax highlighting and modern editor features
- Rich file preview system for remote files (markdown, images, video, PDFs, CSVs, directories)
- Quick full-screen toggle for any block - expand terminals, editors, and previews for better visibility, then instantly return to multi-block view
- AI chat widget with support for multiple models (OpenAI, Claude, Azure, Perplexity, Ollama)
- Command Blocks for isolating and monitoring individual commands
- One-click remote connections with full terminal and file system access
- Secure secret storage using native system backends - store API keys and credentials locally, access them across SSH sessions
- Rich customization including tab themes, terminal styles, and background images
- Powerful
wshcommand system for managing your workspace from the CLI and sharing data between terminal sessions - Connected file management with
wsh file- seamlessly copy and sync files between local and remote SSH hosts
Wave AI
Wave AI is your context-aware terminal assistant with access to your workspace:
- Terminal Context: Reads terminal output and scrollback for debugging and analysis
- File Operations: Read, write, and edit files with automatic backups and user approval
- CLI Integration: Use
wsh aito pipe output or attach files directly from the command line - BYOK Support: Bring your own API keys for OpenAI, Claude, Gemini, Azure, and other providers
- Local Models: Run local models with Ollama, LM Studio, and other OpenAI-compatible providers
- Free Beta: Included AI credits while we refine the experience
- Coming Soon: Command execution (with approval)
Learn more in our Wave AI documentation and Wave AI Modes documentation.
Installation
Wave Terminal works on macOS, Linux, and Windows.
Platform-specific installation instructions can be found here.
You can also install Wave Terminal directly from: www.waveterm.dev/download.
Minimum requirements
Wave Terminal runs on the following platforms:
- macOS 11 or later (arm64, x64)
- Windows 10 1809 or later (x64)
- Linux based on glibc-2.28 or later (Debian 10, RHEL 8, Ubuntu 20.04, etc.) (arm64, x64)
The WSH helper runs on the following platforms:
- macOS 11 or later (arm64, x64)
- Windows 10 or later (x64)
- Linux Kernel 2.6.32 or later (x64), Linux Kernel 3.1 or later (arm64)
Roadmap
Wave is constantly improving! Our roadmap will be continuously updated with our goals for each release. You can find it here.
Want to provide input to our future releases? Connect with us on Discord or open a Feature Request!
Links
- Homepage — https://www.waveterm.dev
- Download Page — https://www.waveterm.dev/download
- Documentation — https://docs.waveterm.dev
- X — https://x.com/wavetermdev
- Discord Community — https://discord.gg/XfvZ334gwU
Building from Source
Contributing
Wave uses GitHub Issues for issue tracking.
Find more information in our Contributions Guide, which includes:
Sponsoring Wave โค๏ธ
If Wave Terminal is useful to you or your company, consider sponsoring development.
Sponsorship helps support the time spent building and maintaining the project.
License
Wave Terminal is licensed under the Apache-2.0 License. For more information on our dependencies, see here.
File: docs/docs/ai-presets.mdx
sidebar_position: 3.6 id: "ai-presets" title: "AI Presets (Deprecated)"
:::warning Deprecation Notice
The AI Widget and its presets are being replaced by Wave AI. Please refer to the Wave AI documentation for the latest AI features and configuration options.
:::
Wave's AI widget can be configured to work with various AI providers and models through presets. Presets allow you to define multiple AI configurations and easily switch between them using the dropdown menu in the AI widget.
How AI Presets Work
AI presets are defined in ~/.config/waveterm/presets/ai.json. You can easily edit this file using:
wsh editconfig presets/ai.jsonEach preset defines a complete set of configuration values for the AI widget. When you select a preset from the dropdown menu, those configuration values are applied to the widget. If no preset is selected, the widget uses the default values from settings.json.
Here's a basic example using Claude:
{
"ai@claude-sonnet": {
"display:name": "Claude 3 Sonnet",
"display:order": 1,
"ai:*": true,
"ai:apitype": "anthropic",
"ai:model": "claude-3-5-sonnet-latest",
"ai:apitoken": "<your anthropic API key>"
}
}To make a preset your default, add this single line to your settings.json:
{
"ai:preset": "ai@claude-sonnet"
}:::info
You can quickly set your default preset using the setconfig command:
wsh setconfig ai:preset=ai@claude-sonnetThis is easier than editing settings.json directly!
:::
Provider-Specific Configurations
Anthropic (Claude)
To use Claude models, create a preset like this:
{
"ai@claude-sonnet": {
"display:name": "Claude 3 Sonnet",
"display:order": 1,
"ai:*": true,
"ai:apitype": "anthropic",
"ai:model": "claude-3-5-sonnet-latest",
"ai:apitoken": "<your anthropic API key>"
}
}OpenAI
To use OpenAI's models:
{
"ai@openai-gpt41": {
"display:name": "GPT-4.1",
"display:order": 2,
"ai:*": true,
"ai:model": "gpt-4.1",
"ai:apitoken": "<your OpenAI API key>"
}
}Local LLMs (Ollama)
To connect to a local Ollama instance:
{
"ai@ollama-llama": {
"display:name": "Ollama - Llama2",
"display:order": 3,
"ai:*": true,
"ai:baseurl": "http://localhost:11434/v1",
"ai:name": "llama2",
"ai:model": "llama2",
"ai:apitoken": "ollama"
}
}Note: The ai:apitoken is required but can be any value as Ollama ignores it. See Ollama OpenAI compatibility docs for more details.
Azure OpenAI
To connect to Azure AI services:
{
"ai@azure-gpt4": {
"display:name": "Azure GPT-4",
"display:order": 4,
"ai:*": true,
"ai:apitype": "azure",
"ai:baseurl": "<your Azure AI base URL>",
"ai:model": "<your model deployment name>",
"ai:apitoken": "<your Azure API key>"
}
}Note: Do not include query parameters or api-version in the ai:baseurl. The ai:model should be your model deployment name in Azure.
Perplexity
To use Perplexity's models:
{
"ai@perplexity-sonar": {
"display:name": "Perplexity Sonar",
"display:order": 5,
"ai:*": true,
"ai:apitype": "perplexity",
"ai:model": "llama-3.1-sonar-small-128k-online",
"ai:apitoken": "<your perplexity API key>"
}
}Google (Gemini)
To use Google's Gemini models from Google AI Studio:
{
"[email protected]": {
"display:name": "Gemini 2.0",
"display:order": 6,
"ai:*": true,
"ai:apitype": "google",
"ai:model": "gemini-2.0-flash-exp",
"ai:apitoken": "<your Google AI API key>"
}
}OpenRouter
To use OpenRouter's models:
{
"ai@openrouter": {
"display:name": "OpenRouter (Qwen)",
"display:order": 7,
"ai:*": true,
"ai:model": "qwen/qwen3-next-80b-a3b-thinking",
"ai:apitoken": "<openrouter-key>",
"ai:baseurl": "https://openrouter.ai/api/v1"
}
}Multiple Presets Example
You can define multiple presets in your ai.json file:
{
"ai@claude-sonnet": {
"display:name": "Claude 3 Sonnet",
"display:order": 1,
"ai:*": true,
"ai:apitype": "anthropic",
"ai:model": "claude-3-5-sonnet-latest",
"ai:apitoken": "<your anthropic API key>"
},
"ai@openai-gpt41": {
"display:name": "GPT-4.1",
"display:order": 2,
"ai:*": true,
"ai:model": "gpt-4.1",
"ai:apitoken": "<your OpenAI API key>"
},
"ai@ollama-llama": {
"display:name": "Ollama - Llama2",
"display:order": 3,
"ai:*": true,
"ai:baseurl": "http://localhost:11434/v1",
"ai:name": "llama2",
"ai:model": "llama2",
"ai:apitoken": "ollama"
},
"ai@perplexity-sonar": {
"display:name": "Perplexity Sonar",
"display:order": 4,
"ai:*": true,
"ai:apitype": "perplexity",
"ai:model": "llama-3.1-sonar-small-128k-online",
"ai:apitoken": "<your perplexity API key>"
}
}The display:order value determines the order in which presets appear in the dropdown menu.
Remember to set your default preset in settings.json:
{
"ai:preset": "ai@claude-sonnet"
}Using a Proxy
If you need to route AI requests through an HTTP proxy, you can add the ai:proxyurl setting to any preset:
{
"ai@claude-with-proxy": {
"display:name": "Claude 3 Sonnet (via Proxy)",
"display:order": 1,
"ai:*": true,
"ai:apitype": "anthropic",
"ai:model": "claude-3-5-sonnet-latest",
"ai:apitoken": "<your anthropic API key>",
"ai:proxyurl": "http://proxy.example.com:8080"
}
}The proxy URL should be in the format http://host:port or https://host:port. This setting works with all AI providers except Wave Cloud AI (the default).
File: docs/docs/config.mdx
sidebar_position: 3.45 id: "config" title: "Configuration"
import { Kbd } from "@site/src/components/kbd";
import { PlatformProvider, PlatformSelectorButton } from "@site/src/components/platformcontext";
import { VersionBadge, DeprecatedBadge } from "@site/src/components/versionbadge";
Wave's configuration files are located at ~/.config/waveterm/.
The main configuration file is settings.json (~/.config/waveterm/settings.json).
The file is structured as a mostly flat JSON file. Instead of using sub-objects we prefer to
use ":" as level separators.
:::info
The easiest way to edit your config files is to use the wsh editconfig command which will open your Wave config file in our built-in preview editor.
wsh editconfig:::
Configuration Keys
| Key Name | Type | Function |
|---|---|---|
| app:globalhotkey | string | A systemwide keybinding to open your most recent wave window. This is a set of key names separated by :. For more info, see Customizable Systemwide Global Hotkey |
| app:dismissarchitecturewarning | bool | Disable warnings on app start when you are using a non-native architecture for Wave. For more info, see Why does Wave warn me about ARM64 translation when it launches?. |
| app:defaultnewblock | string | Sets the default new block (Cmd:n, Cmd:d). "term" for terminal block, "launcher" for launcher block (default = "term") |
| app:showoverlayblocknums | bool | Set to false to disable the Ctrl+Shift block number overlay that appears when holding Ctrl+Shift (defaults to true) |
| app:ctrlvpaste | bool | On Windows/Linux, when null (default) uses Control+V on Windows only. Set to true to force Control+V on all non-macOS platforms, false to disable the accelerator. macOS always uses Command+V regardless of this setting |
| app:confirmquit |
bool | Set to false to disable the quit confirmation dialog when closing Wave Terminal (defaults to true, requires app restart) |
| app:hideaibutton |
bool | Set to true to hide the AI button in the tab bar (defaults to false) |
| app:disablectrlshiftarrows |
bool | Set to true to disable Ctrl+Shift block-navigation keybindings (Arrow and h/j/k/l) (defaults to false) |
| app:disablectrlshiftdisplay |
bool | Set to true to disable the Ctrl+Shift visual indicator display (defaults to false) |
| app:focusfollowscursor |
string | Controls whether block focus follows cursor movement: "off" (default), "on" (all blocks), or "term" (terminal blocks only) |
| app:tabbar |
string | Controls the position of the tab bar: "top" (default) for a horizontal tab bar at the top of the window, or "left" for a vertical tab bar on the left side of the window |
| ai:preset | string | the default AI preset to use |
| ai:baseurl | string | Set the AI Base Url (must be OpenAI compatible) |
| ai:apitoken | string | your AI api token |
| ai:apitype | string | defaults to "open_ai", but can also set to "azure" (forspecial Azure AI handling), "anthropic", or "perplexity" |
| ai:name | string | string to display in the Wave AI block header |
| ai:model | string | model name to pass to API |
| ai:apiversion | string | for Azure AI only (when apitype is "azure", this will default to "2023-05-15") |
| ai:orgid | string | |
| ai:maxtokens | int | max tokens to pass to API |
| ai:timeoutms | int | timeout (in milliseconds) for AI calls |
| ai:proxyurl | string | HTTP proxy URL for AI API requests (does not apply to Wave Cloud AI) |
| conn:askbeforewshinstall | bool | set to false to disable popup asking if you want to install wsh extensions on new machines |
| conn:localhostdisplayname |
string | override the display name for localhost in the UI (e.g., set to "My Laptop" or "Local", or set to empty string to hide the name) |
| term:fontsize | float | the fontsize for the terminal block |
| term:fontfamily | string | font family to use for terminal block |
| term:disablewebgl | bool | set to true to disable WebGL acceleration in terminal (default false) |
| term:localshellpath | string | set to override the default shell path for local terminals |
| term:localshellopts | string[] | set to pass additional parameters to the term:localshellpath (example: ["-NoLogo"] for PowerShell will remove the copyright notice) |
| term:copyonselect | bool | set to false to disable terminal copy-on-select |
| term:scrollback | int | size of terminal scrollback buffer, max is 10000 |
| term:theme | string | preset name of terminal theme to apply by default (default is "default-dark") |
| term:transparency | float64 | set the background transparency of terminal theme (default 0.5, 0 = not transparent, 1.0 = fully transparent) |
| term:allowbracketedpaste | bool | allow bracketed paste mode in terminal (default false) |
| term:shiftenternewline | bool | when enabled, Shift+Enter sends escape sequence + newline (\u001b\n) instead of carriage return, useful for claude code and similar AI coding tools (default false) |
| term:macoptionismeta | bool | on macOS, treat the Option key as Meta key for terminal keybindings (default false) |
| term:cursor |
string | terminal cursor style. valid values are block (default), underline, and bar |
| term:cursorblink |
bool | when enabled, terminal cursor blinks (default false) |
| term:bellsound |
bool | when enabled, plays the system beep sound when the terminal bell (BEL character) is received (default false) |
| term:bellindicator |
bool | when enabled, shows a visual indicator in the tab when the terminal bell is received (default false) |
| term:osc52 |
string | controls OSC 52 clipboard behavior: always (default, allows OSC 52 at any time) or focus (requires focused window and focused block) |
| term:durable |
bool | makes remote terminal sessions durable across network disconnects (defaults to false) |
| term:showsplitbuttons |
bool | when enabled, shows split horizontal and vertical buttons in the terminal block header (defaults to false) |
| editor:minimapenabled | bool | set to false to disable editor minimap |
| editor:stickyscrollenabled | bool | enables monaco editor's stickyScroll feature (pinning headers of current context, e.g. class names, method names, etc.), defaults to false |
| editor:wordwrap | bool | set to true to enable word wrapping in the editor (defaults to false) |
| editor:fontsize | float64 | set the font size for the editor (defaults to 12px) |
| editor:inlinediff | bool | set to true to show diffs inline instead of side-by-side, false for side-by-side (defaults to undefined which uses Monaco's responsive behavior) |
| preview:showhiddenfiles | bool | set to false to disable showing hidden files in the directory preview (defaults to true) |
| preview:defaultsort |
string | sets the default sort column for directory preview. "name" (default) sorts alphabetically by name ascending; "modtime" sorts by last modified time descending (newest first) |
| markdown:fontsize | float64 | font size for the normal text when rendering markdown in preview. headers are scaled up from this size, (default 14px) |
| markdown:fixedfontsize | float64 | font size for the code blocks when rendering markdown in preview (default is 12px) |
| web:openlinksinternally | bool | set to false to open web links in external browser |
| web:defaulturl | string | default web page to open in the web widget when no url is provided (homepage) |
| web:defaultsearch | string | search template for web searches. e.g. https://www.google.com/search?q={query}. "{query}" gets replaced by search term |
| autoupdate:enabled | bool | enable/disable checking for updates (requires app restart) |
| autoupdate:intervalms | float64 | time in milliseconds to wait between update checks (requires app restart) |
| autoupdate:installonquit | bool | whether to automatically install updates on quit (requires app restart) |
| autoupdate:channel | string | the auto update channel "latest" (stable builds), or "beta" (updated more frequently) (requires app restart) |
| tab:preset |
string | a "bg@" preset to automatically apply to new tabs. e.g. bg@green. should match the preset key. deprecated in favor of tab:background |
| tab:background |
string | a "bg@" preset to automatically apply to new tabs. e.g. bg@green. should match the preset key |
| tab:confirmclose | bool | if set to true, a confirmation dialog will be shown before closing a tab (defaults to false) |
| widget:showhelp | bool | whether to show help/tips widgets in right sidebar |
| window:transparent | bool | set to true to enable window transparency (cannot be combined with window:blur) (macOS and Windows only, requires app restart, see note on Windows compatibility) |
| window:blur | bool | set to enable window background blurring (cannot be combined with window:transparent) (macOS and Windows only, requires app restart, see note on Windows compatibility) |
| window:opacity | float64 | 0-1, window opacity when window:transparent or window:blur are set |
| window:bgcolor | string | set the window background color (should be hex: #xxxxxx) |
| window:reducedmotion | bool | set to true to disable most animations |
| window:tilegapsize | int | set to change override default gap size (in CSS pixels) between blocks |
| window:magnifiedblockopacity | float64 | change the opacity of a magnified block (must be between 0 and 1, defaults to 0.6) |
| window:magnifiedblocksize | float64 | change the size of a magnified block as a percentage of the dimensions of its parent layout (must be between 0 and 1, defaults to 0.9) |
| window:magnifiedblockblurprimarypx | int | change the blur in CSS pixels that is applied directly behind a magnified block (see backdrop-filter for more info on how this gets applied) |
| window:magnifiedblockblursecondarypx | int | change the blur in CSS pixels that is applied to the visible portions of non-magnified blocks when a block is magnified (see backdrop-filter for more info on how this gets applied) |
| window:maxtabcachesize | int | number of tabs to cache. when tabs are cached, switching between them is very fast. (defaults to 10) |
| window:showmenubar | bool | set to use the OS-native menu bar (Windows and Linux only, requires app restart) |
| window:nativetitlebar | bool | set to use the OS-native title bar, rather than the overlay (Windows and Linux only, requires app restart) |
| window:disablehardwareacceleration | bool | set to disable Chromium hardware acceleration to resolve graphical bugs (requires app restart) |
| window:fullscreenonlaunch | bool | set to true to launch the foreground window in fullscreen mode (defaults to false) |
| window:savelastwindow | bool | when true, the last window that is closed is preserved and is reopened the next time the app is launched (defaults to true) |
| window:confirmonclose | bool | when true, a prompt will ask a user to confirm that they want to close a window if it has an unsaved workspace with more than one tab (defaults to true) |
| window:dimensions | string | set the default dimensions for new windows using the format "WIDTHxHEIGHT" (e.g. "1920x1080"). when a new window is created, these dimensions will be automatically applied. The width and height values should be specified in pixels. |
| telemetry:enabled | bool | set to enable/disable telemetry |
For reference, this is the current default configuration (v0.14.0):
{
"ai:preset": "ai@global",
"ai:model": "gpt-5-mini",
"ai:maxtokens": 4000,
"ai:timeoutms": 60000,
"app:defaultnewblock": "term",
"app:confirmquit": true,
"app:hideaibutton": false,
"app:disablectrlshiftarrows": false,
"app:disablectrlshiftdisplay": false,
"app:focusfollowscursor": "off",
"autoupdate:enabled": true,
"autoupdate:installonquit": true,
"autoupdate:intervalms": 3600000,
"conn:askbeforewshinstall": true,
"conn:wshenabled": true,
"editor:minimapenabled": true,
"web:defaulturl": "https://github.com/wavetermdev/waveterm",
"web:defaultsearch": "https://www.google.com/search?q={query}",
"window:tilegapsize": 3,
"window:maxtabcachesize": 10,
"window:nativetitlebar": true,
"window:magnifiedblockopacity": 0.6,
"window:magnifiedblocksize": 0.9,
"window:magnifiedblockblurprimarypx": 10,
"window:fullscreenonlaunch": false,
"window:magnifiedblockblursecondarypx": 2,
"window:confirmclose": true,
"window:savelastwindow": true,
"telemetry:enabled": true,
"term:bellsound": false,
"term:bellindicator": false,
"term:osc52": "always",
"term:cursor": "block",
"term:cursorblink": false,
"term:copyonselect": true,
"term:durable": false,
"waveai:showcloudmodes": true,
"waveai:defaultmode": "waveai@balanced",
"preview:defaultsort": "name"
}:::warning
If you installed Wave pre-v0.9.0 your configuration file will be located at~/.waveterm/config/settings.json. This includes all of the other configuration
files as well: termthemes.json, presets.json, and widgets.json.
:::
Environment Variable Resolution
To avoid putting secrets directly in config files, Wave supports environment variable resolution using $ENV:VARIABLE_NAME or $ENV:VARIABLE_NAME:fallback syntax. This works for any string value in any config file (settings.json, presets.json, ai.json, etc.).
{
"ai:apitoken": "$ENV:OPENAI_APIKEY",
"ai:baseurl": "$ENV:AI_BASEURL:https://api.openai.com/v1"
}WebBookmarks Configuration
WebBookmarks allows you to store and manage web links with customizable display preferences. The bookmarks are stored in a JSON file (bookmarks.json) as a key-value map where the key (id) is an arbitrary identifier for the bookmark. By convention, you should start your ids with "bookmark@". In the web widget, you can pull up your bookmarks using
Bookmark Structure
Each bookmark follows this structure (only url is required):
{
"url": "https://example.com",
"title": "Example Site",
"iconurl": "https://example.com/custom-icon.png",
"display:order": 1
}Fields
| Field | Type | Description |
|---|---|---|
| url | string | Required. The URL of the bookmark. |
| title | string | Optional. A display title for the bookmark. |
| icon | string | Optional, rarely used. Overrides the default favicon with an icon name. |
| iconcolor | string | Optional, rarely used. Sets a custom color for the specified icon. |
| iconurl | string | Optional. Provides a custom icon URL, useful if the favicon is incorrect (e.g., for dark mode compatibility). |
| display:order | float64 | Optional. Defines the order in which bookmarks appear. |
Example `bookmarks.json`
{
"bookmark@google": {
"url": "https://www.google.com",
"title": "Google"
},
"bookmark@claude": {
"url": "https://claude.ai",
"title": "Claude AI"
},
"bookmark@wave": {
"url": "https://waveterm.dev",
"title": "Wave Terminal",
"display:order": -1
},
"bookmark@wave-github": {
"url": "https://github.com/wavetermdev/waveterm",
"title": "Wave Github",
"iconurl": "https://github.githubassets.com/favicons/favicon-dark.png"
},
"bookmark@chatgpt": {
"url": "https://chatgpt.com",
"iconurl": "https://cdn.oaistatic.com/assets/favicon-miwirzcw.ico"
},
"bookmark@wave-pulls": {
"url": "https://github.com/wavetermdev/waveterm/pulls",
"title": "Wave Pull Requests",
"iconurl": "https://github.githubassets.com/favicons/favicon-dark.png"
}
}Behavior
- If
iconurlis set, it fetches the icon from the specified URL instead of the site's default favicon. - Bookmarks are sorted based on
display:order(if provided), otherwise by id. iconandiconcolorare rarely needed since the default behavior fetches the site's favicon.- favicons are refreshed every 24-hours
Terminal Theming
User-defined terminal themes are located in ~/.config/waveterm/termthemes.json.
This JSON file is structured as an object, with each sub-key defining a theme.
Themes are applied by right-clicking on the terminal's header bar and selecting an entry from the "Themes" sub-menu. Alternatively they can be applied to
the block's metadata key term:theme. This uses the JSON key value as the identifier. Note, for best consistency all colors should be of the format "#rrggbb" or "#rrggbbaa" (aa = alpha channel for transparency).
wsh setmeta this term:theme="default-dark"Here is an example of defining a full terminal theme. All of the built-in themes are defined here: https://github.com/wavetermdev/waveterm/blob/main/pkg/wconfig/defaultconfig/termthemes.json (if you'd like to add a popular terminal theme, please submit a PR!)
{
"default-dark": {
"display:name": "Default Dark",
"display:order": 1,
"black": "#757575",
"red": "#cc685c",
"green": "#76c266",
"yellow": "#cbca9b",
"blue": "#85aacb",
"magenta": "#cc72ca",
"cyan": "#74a7cb",
"white": "#c1c1c1",
"brightBlack": "#727272",
"brightRed": "#cc9d97",
"brightGreen": "#a3dd97",
"brightYellow": "#cbcaaa",
"brightBlue": "#9ab6cb",
"brightMagenta": "#cc8ecb",
"brightCyan": "#b7b8cb",
"brightWhite": "#f0f0f0",
"gray": "#8b918a",
"cmdtext": "#f0f0f0",
"foreground": "#c1c1c1",
"selectionBackground": "",
"background": "#00000077",
"cursorAccent": ""
}
}:::info
You can easily open the termthemes.json config file by running:
wsh editconfig termthemes.json:::
| Key Name | Type | ANSI FG# | ANSI BG# | Function |
|---|---|---|---|---|
| display:name | string | the name as it will appear in the UI context menu | ||
| display:order | float | entries in the context menu are sorted by display:order | ||
| black | CSS color | 30 | 40 | color for black |
| red | CSS color | 31 | 41 | color for red |
| green | CSS color | 32 | 42 | color for green |
| yellow | CSS color | 33 | 43 | color for yellow |
| blue | CSS color | 34 | 44 | color for blue |
| magenta | CSS color | 35 | 45 | color for magenta |
| cyan | CSS color | 36 | 46 | color for cyan |
| white | CSS color | 37 | 47 | color for white |
| brightBlack | CSS color | 90 | 100 | color for bright black |
| brightRed | CSS color | 91 | 101 | color for bright red |
| brightGreen | CSS color | 92 | 102 | color for bright green |
| brightYellow | CSS color | 93 | 103 | color for bright yellow |
| brightBlue | CSS color | 94 | 104 | color for bright blue |
| brightMagenta | CSS color | 95 | 105 | color for bright magenta |
| brightCyan | CSS color | 96 | 106 | color for bright cyan |
| brightWhite | CSS color | 97 | 107 | color for bright white |
| gray | CSS color | currently unused | ||
| cmdtext | CSS color | currently unused | ||
| foreground | CSS color | foreground color (default when no color code is applied) | ||
| background | CSS color | background color (default when no color code is applied), must have alpha channel (#rrggbbaa) if you want the terminal to be transparent | ||
| cursorAccent | CSS color | color for cursor | ||
| selectionBackground | CSS color | background color for selected text |
Customizable Systemwide Global Hotkey
Wave allows settings a custom global hotkey to open your most recent window from anywhere in your computer. This has the name "app:globalhotkey" in the settings.json file and takes the form of a series of key names separated by the : character.
Examples
As a practical example, suppose you want a value of F5 as your global hotkey. Then you can simply set the value of "app:globalhotkey" to "F5" and reboot Wave to make that your global hotkey.
As a less practical example, suppose you use the combination of the keys Ctrl, Option, and e. Then the value for this keybinding would be "Ctrl:Option:e".
Allowed Key Names
We support the following key names:
CtrlCmdShiftAltOptionMetaSuper- Digits (non-numpad) represented by
c{Digit0}throughc{Digit9} - Letters
athoughz - F keys
F1throughF20 - Soft keys
Soft1throughSoft4. These are essentially the same asF21throughF24. - Space represented as either
Spaceor a literal space Enter(This is labeled as return on Mac)TabCapsLockNumLockBackspace(This is labeled as delete on Mac)DeleteInsert- The arrow keys
ArrowUp,ArrowDown,ArrowLeft, andArrowRight HomeEndPageUpPageDownEsc- Volume controls
AudioVolumeUp,AudioVolumeDown,AudioVolumeMute - Media controls
MediaTrackNext,MediaTrackPrevious,MediaPlayPause, andMediaStop PrintScreen- Numpad keys represented by
c{Numpad0}throughc{Numpad9} - The numpad decimal represented by
Decimal - The numpad plus/add represented by
Add - The numpad minus/subtract represented by
Subtract - The numpad star/multiply represented by
Multiply - The numpad slash/divide represented by
Divide
File: docs/docs/connections.mdx
sidebar_position: 3.1 id: "connections" title: "Connections"
import { VersionBadge } from "@site/src/components/versionbadge";
Connections
Wave allows users to connect to various machines and unify them together in a way that preserves the unique behavior of each. At the moment, this extends to SSH remote connections and local WSL connections.
Access a Connection in a Block
The easiest way to access connections is to click the icon. From there, you can type one of the following to depending on the connection you want:
For SSH Connections:
[user]@[host][host][user]@[host]:[port]
For WSL Connections:
wsl://<distribution name>
Alternatively, if the connection already exists in the dropdown list, you can either click it or navigate to it with arrow keys and press enter to connect.
Different Types of Connections
As there are several different types of connections, not all of the types have access to the same features. SSH and WSL connections can always work in terminal widgets, and if wsh shell extensions are installed, they can also work in preview widgets and the sysinfo widget.
What are wsh Shell Extensions?
wsh is a small program that helps manage waveterm regardless of which machine you are currently connected to. It is always included on your host machine, but you also have the option to install it when connecting to SSH and WSL Connections. If it is installed on the connection, it is installed at ~/.waveterm/bin/wsh. Then, when wave connects to your connection (and only when wave connects to your connection), the following happens:
~/.waveterm/binis added to yourPATHfor that individual session. This allows the user to use thewshcommand without providing the complete path.- Several environment variables are injected into the session to make certain tasks with
wsheasier. These are listed below. - The user-defined environment variables in the
cmd:enventry ofconnections.jsonare injected into the session. - The user-defined initialization scripts located in
connections.jsonare run. For more information on these scripts, see the section below.
If this fails for some reason, Wave will attempt to run without wsh. You will see this indicated by a small `` icon in the block header. For more info on what wsh is capable of, see wsh command. And if you wish to view the source code of wsh, you can find it here.
With wsh installed, you have the ability to view certain widgets from the remote machine as if it were your host, for instance the files and sysinfo widgets. In addition, wsh can be used to influence the widgets across various machines. As a simple example, you can close a widget on the host machine by using the wsh command in a terminal window on a remote machine. For more information on what you can accomplish with wsh, take a look here.
Additional Environment Variables
As mentioned above, wsh injects a few environment variables in remote sessions for the user's convenience. These are listed below:
| Variable Name | Description |
|---|---|
| TERM_PROGRAM | Set to waveterm in wave. |
| WAVETERM | This is set to 1 in wave. |
| WAVETERM_BLOCKID | The id of the block containing your current terminal widget. |
| WAVETERM_CLIENTID | The id of the RPC Client being used by your current terminal widget. |
| WAVETERM_CONN | The name of the remote connection being used by your current terminal widget. |
| WAVETERM_TABID | The id of the tab containing your current terminal widget. |
| WAVETERM_VERSION | The current semver version of wave. |
| WAVETERM_WORKSPACEID | The id of thw workspace containing your current terminal widget. |
Initialization Scripts
Wave provides you with options for running initialization scripts on your remote machines when connecting to them. These are defined in connections.json and can take either the form of the path of a script or a short script written directly in the file. If multiple scripts are defined, the most specific one relevant to the current shell is applied. The keywords for the scripts are:
| Script Keyword | Shells Where Applied |
|---|---|
| cmd:initscript | all shells |
| cmd:initscript.sh | bash and zsh |
| cmd:initscript.bash | bash |
| cmd:initscript.zsh | zsh |
| cmd:initscript.pwsh | pwsh |
| cmd:initscript.fish | fish |
Add a New Connection to the Dropdown
The SSH values that are loaded into the dropdown by default are obtained by parsing the internal config/connections.json file in addition to your ~/.ssh/config and /etc/ssh/ssh_config files. Adding a new connection can be added in a couple ways:
- adding a new
Hostto one of your ssh config files, typically the~/.ssh/configfile - adding a new entry in the internal
config/connections.jsonfile - manually typing your connection into the connection box (if this successfully connects, the connection will be added to the internal
config/connections.jsonfile) - use
wsh ssh [user]@[host]in your terminal (if this successfully connects, the connection will be added to the internalconfig/connections.jsonfile)
WSL connections are added by searching the installed WSL distributions as they appear in the Windows Registry. They also exist in the config/connections.json file similarly to SSH connections.
SSH Config Parsing
At the moment, we are capable of parsing any SSH config file that does not contain the Match keyword. This keyword is incompatible with a library we are using, but we are hoping to fix that soon. While all other valid keywords are parsed, we only support the functionality of a small subset of them at the moment:
| Keyword | Description |
|---|---|
| Host | The pattern to match when attempting to connect via [user]@[host]. We list hosts that do not contain any wildcards characters (*, ?, or !). Even if a host pattern contains wildcards, it will still be parsed when determining the values associated with the keys as usual. |
| User | The user of the SSH remote connection. This will default to the current user on the local machine if not specified. |
| HostName | The real host name of the machine to log into. An IP address can be used if desired. This will default to the Host if not specified. |
| Port | The port to connect to the remote on. 22 is the default if not specified. |
| IdentityFile | This can be specified more than once per host. It gives the path to a private identity file (id_rsa, id_ed25519, id_ecdsa, etc.) that is used to authenticate the connection. Each will be tried in order, and they can be encrypted with a passphrase if desired. If no value is set, the default is to try in order: ~/.ssh/id_rsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519_sk, ~/.ssh/id_dsa. |
| BatchMode | If set to true, user interaction via password, challenge/response, and publickey passphrase authentication will be disabled. It is set to false by default. |
| PubkeyAuthentication | (partial) This is used to specify if pubkey authentication should be attempted. It is partially implementented as the unbound and host-bound values simply work the same as the yes value. The default is yes. |
| PasswordAuthentication | This is used to specify if password authentication should be attempted. The default is yes. |
| KbdInteractiveAuthentication | This is used to specify if keyboard-interactive authentication should be attempted. The default is yes. |
| PreferredAuthentications | (partial) Specifies the order the client should attempt to authenticate in. It is partially implemented as it does not support gssapi-with-mic or hostbased authentication. The default is publickey,keyboard-interactive,password |
| AddKeysToAgent | (partial) This option will automatically add keys and their corresponding passphrase to your running ssh agent if it is enabled. It is partially supported as it can only accept yes and no as valid inputs. Other inputs such as confirm or a time interval will behave the same as no. The default value is no. |
| IdentityAgent | Specifies the Unix Domain Socket used to communicate with the SSH Agent. This is used to overwrite the SSH_AUTH_SOCK identity agent. |
| IdentitiesOnly | Specifies that only the specified authentication identity files should be used. This is either the default files or the ones specified with the IdentityFile keyword. It can accept yes or no. The default value is no. |
| ProxyJump | Specifies one or more jump proxies in a comma separated list. Each will be visited sequentially using TCP forwarding before connecting to the desired connection (also using TCP forwarding). It can be set to none to disable the feature. |
| UserKnownHostsFile | Provides the location of one or more user host key database files for recording trusted remote connections. The filenames are entered in the same string and separated by whitespace. The default value is "~/.ssh/known_hosts ~/.ssh/known_hosts2". |
| GlobalKnownHostsFile | Provides the location of one or more global host key database files for recording trusted remote connections. The filenames are entered in the same string and separated by whitespace. The default value is "/etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2". |
Example SSH Config Host
For a quick example, a host in your config file may look like:
Host myhost
User username
HostName 203.0.113.254
IdentityFile ~/.ssh/id_rsa
AddKeysToAgent yesYou would then be able to access this connection with myhost or username@myhost. And if you wanted to manually specify a port such as port 2222, you could do that by either adding Port 2222 to the config file or connecting to username@myhost:2222.
Internal SSH Configuration
In addition to the regular ssh config file, wave also has its own config file to manage separate variables. These include
| Keyword | Description |
|---|---|
| conn:wshenabled | This boolean allows wsh to be used for your connection, if it is set to false, wsh will never be used for that connection. It defaults to true. |
| conn:askbeforewshinstall | This boolean is used to prompt the user before installing wsh. If it is set to false, wsh will automatically be installed instead without prompting. It defaults to true. |
| conn:wshpath | A string indicating the path to the wsh executable on the connection. It defaults to "~/.waveterm/bin/wsh". |
| conn:shellpath | A string indicating the path to the shell executable on the connection. If not set, the output of $SHELL on the connection will be used. |
| conn:ignoresshconfig | This boolean allows wave to ignore the ~/.ssh/config file for resolving keywords for this connection. The regular defaults will be used, but all changes to those must be specified in the connections.json file instead. This defaults to false. |
| display:hidden | This boolean hides the connection from the dropdown list. It defaults to false |
| display:order | This float determines the order of connections in the connection dropdown. It defaults to 0. |
| term:fontsize | This int can be used to override the terminal font size for blocks using this connection. The block metadata takes priority over this setting. It defaults to null which means the global setting will be used instead. |
| term:fontfamily | This string can be used to specify a terminal font family for blocks using this connection. The block metadata takes priority over this setting. It defaults to null which means the global setting will be used instead. |
| term:theme | This string can be used to specify a terminal theme for blocks using this connection. The block metadata takes priority over this setting. It defaults to null which means the global setting will be used instead. |
| cmd:env | A json object with key value pairs of environment variables and the value they should be set to for this remote. This only works if wsh is enabled. |
| cmd:initscript | A script or a path to a script that runs when initializing this connection with any shell. This only works if wsh is enabled. |
| cmd:initscript.sh | A script or a path to a script that runs when initializing this connection with POSIX shells like bash or zsh. This only works if wsh is enabled. |
| cmd:initscript.bash | A script or a path to a script that runs when initializing this connection with the bash shell. This only works if wsh is enabled. |
| cmd:initscript.zsh | A script or a path to a script that runs when initializing this connection with the zsh shell. This only works if wsh is enabled. |
| cmd:initscript.pwsh | A script or a path to a script that runs when initializing this connection with the pwsh shell. This only works if wsh is enabled. |
| cmd:initscript.fish | A script or a path to a script that runs when initializing this connection with the fish shell. This only works if wsh is enabled. |
| ssh:user | A string that indicates the username of the connection. Can be used to override the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:hostname | A string representing the internal hostname of the connection. Can be used to override the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:port | A string to indicate the numerical port to connect on. Can be used to override the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:identityfile | A list of strings containing the paths to identity files that will be used. If a wsh ssh command using the -i flag is successful, the identity file will automatically be added here. These are used before the ~/.ssh/config values. |
| ssh:identitiesonly | A boolean indicating if only the specified identity files should be used. This means only the files set with the ssh:identityfile flag or the defaults. Can be used to override the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:batchmode | A boolean indicating if password and passphrase prompts should be skipped. Can be used to override the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:pubkeyauthentication | A boolean indicating if public key authentication is enabled. Can be used to override the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:passwordauthentication | A boolean indicating if password authentication is enabled. Can be used to override the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:passwordsecretname | A string specifying the name of a secret stored in the secret store to use as the SSH password. When set, this password will be automatically used for password authentication instead of prompting the user. |
| ssh:kbdinteractiveauthentication | A boolean indicating if keyboard interactive authentication is enabled. Can be used to override the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:preferredauthentications | A list of strings indicating an ordering of different types of authentications. Each authentication type will be tried in order. This supports "publickey", "keyboard-interactive", and "password" as valid types. Other types of authentication are not handled and will be skipped. Can be used to override the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:addkeystoagent | A boolean indicating if the keys used for a connection should be added to the ssh agent. Can be used to override the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:identityagent | A string giving the path to the unix domain socket of the identity agent. Can be used to overwrite the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:proxyjump | A list of strings specifying the names of hosts that must be successively visited with tcp forwarding to establish a connection. Can be used to overwrite the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:userknownhostsfile | A list containing the paths of any user host key database files used to keep track of authorized connections. Can be used to overwrite the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
| ssh:globalknownhostsfile | A list containing the paths of any global host key database files used to keep track of authorized connections. Can be used to overwrite the value in ~/.ssh/config or to set it if the ssh config is being ignored. |
SSH Agent Detection
Wave resolves the identity agent path in this order:
- If
ssh:identityagent(orIdentityAgentin SSH config) is set for the connection, that socket or pipe is used. - If not set on Windows, Wave falls back to the built-in OpenSSH agent pipe
\\.\pipe\openssh-ssh-agent. Ensure the OpenSSH Authentication Agent service is running. - If not set on macOS/Linux, Wave queries your shell environment for
SSH_AUTH_SOCKto detect the agent path automatically.
Example Internal Configurations
Here are a couple examples of things you can do using the internal configuration file connections.json:
Hiding a Connection
Suppose you have a connection named github.com in your ~/.ssh/config file that shows up as [email protected] in the connections dropdown. While it does belong in the config file for authentication reasons, it makes no sense to be in the dropdown since it doesn't involve connecting to a remote environment. In that case, you can hide it as in the example below:
{
<... other connections go here ...>,
"[email protected]" : {
"display:hidden": true
},
<... other connections go here ...>
}Moving a Connection
Suppose you have a connection named rarelyused that shows up as myusername@rarelyused:9999 in the connections dropdown. Since it's so rarely used, you would prefer to move it later in the list. In that case, you can move it as in the example below:
{
<... other connections go here ...>,
"myusername@rarelyused:9999" : {
"display:order": 100
},
<... other connections go here ...>
}Theming a Connection
Suppose you have a connection named myhost that shows up as myusername@myhost in the connections dropdown. You use this connection a lot, but you keep getting it mixed up with your local connections. In this case, you can use the internal configuration file to style it differently. For example:
{
<... other connections go here ...>,
"myusername@myhost" : {
"term:theme": "warmyellow",
"term:fontsize": 16,
"term:fontfamily": "menlo"
},
<... other connections go here ...>
}This style, font size, and font family will then only apply to the widgets that are using this connection.
Entirely Defined Internally
Suppose you want to set up a connection but have no desire to learn the syntax of ~/.ssh/config. In this case, you can entirely define the connection in your connections.json file. For example:
{
<... other connections go here ...>,
"myusername@myhost" : {
"ssh:hostname": "190.0.2.0",
"ssh:identityfile": ["~/.ssh/myidentityfile"],
"ssh:identitiesonly": true,
"ssh:addkeystoagent": true
},
<... other connections go here ...>
}This will create a connection without that connection needing to be in the ~/.ssh/config file. A couple additional options are set as well as an example of how that can be done.
Disabling wsh for a Connection
While Wave provides an option disable wsh when first connecting to a remote, there are cases where you may wish to disable it afterward. The easiest way to do this is by editing the connections.json file. Suppose the connection shows up in the dropdown as root@wshless. Then you can disable it manually with the following line:
{
<... other connections go here ...>,
"root@wshless" : {
"conn:enablewsh": false,
},
<... other connections go here ...>
}Note that this same line gets added to your connections.json file automatically when you choose to disable wsh in gui when initially connecting.
Managing Connections with the CLI
The wsh command gives some commands specifically for interacting with the connections. You can view these here.
Troubleshooting Connections
Log Files
If there are issues with connections, the easiest first step is to enable debugging in a terminal widget that is trying to connect. To do this, click the `` button and hover over the Debug Connection item. From there you can select two log levels, Info and Verbose. After this, debug info will print out to the terminal during the connection.
If this is not sufficient, it is also possible to view the full log file. To do this, you can run the command wsh wavepath log to get the location of a log file.
Known Limitations
In the case that there is an error setting up wsh, your connection will still launch without wsh. However, depending on the debug info, there are a few things that can cause this.
Shell Type
Wave is capable of injecting wsh in the following shells:
- bash
- zsh
- pwsh (powershell)
- fish
If the shell is different than those, it is possible the wsh command will not work by default. The easiest way to fix this at the moment is the switch the shell type. This can be done by setting the conn:shellpath value with a path to one of the above shells in the connections.json file for the connection you are trying to use. Alternatively, you can use the chsh command to change the shell in that connection, but this will also take effect outside of wave. Once this is done, restart wave for the changes to take effect.
AllowTcpForwarding in sshd
Some systems have sshd configured to disable TCP forwarding by default. This can be found on the connection in the /etc/ssh/sshd_config file. In that file, search for the line containing AllowTcpForwarding. If this is set to no, it is likely the reason wsh will not work on your connection. In order to get wsh working, set the value for AllowTcpForwarding to either yes or local (they both provide different levels of permission but both work in this case). Then, restart the sshd service with whichever method your remote machine provides. Once that is done, restart wave, so it can reconnect with this change.
File: docs/docs/customization.mdx
sidebar_position: 3.2 id: "customization" title: "Customization"
Tab Themes
Right click on any tab to bring up a menu which allows you to rename the tab and select different backgrounds.
It is also possible to create your own background themes using custom colors, gradients, images and more by editing your backgrounds.json config file. To see how Wave's built-in tab backgrounds are defined, you can check out the default backgrounds.json file.
To apply a tab background to all new tabs by default, set the key tab:background in your Wave Config File to one of the background preset keys (e.g. "bg@ocean-depths"). The available built-in background keys can be found in the default backgrounds.json file.
Terminal Customization
Terminal Theme
Right click in the header area of any terminal block to bring up a menu which allows you to set a terminal
theme for that terminal.
You can set the default theme for all terminals (which haven't had their theme manually overridden) by editing your settings.json file and adding the key term:theme and setting it to the appropriate key. The keys can be found
in the default termthemes.json file.
If you add your own termthemes.json file in the config directory, you can also add your own custom terminal themes (just follow the same format).
Font Size
From the same context menu you can also change the font-size of the terminal. To change the default font size across all of your (non-overridden) terminals, you can set the config key term:fontsize to the size you want. e.g. { "term:fontsize": 14}.
Font Family
There is no UI to edit your default terminal font family. But, it can be overridden. In your settings.json file you can add the key term:fontfamily and set it to a font that is installed on your local system. If type a font that is not installed, or use a non-monospace font, your terminal will look terrible (don't do that ๐), delete the key to return to using the default.
Widgets Sidebar
See Custom Widgets for detailed documentation around changing what appears in your right widget sidebar.
Using widgets.json, you'll be able to remove any default widgets and add widgets of your own. You can fully customize the icons, colors, text, and defaults (like directories, webpages, AI model, remote connection, commands, etc.) of your custom widgets.
You can also suppress the help widgets in the bottom right by setting the config key widget:showhelp to false.
Tab Backgrounds
Wave supports powerful custom backgrounds for your tabs using images, patterns, gradients, and colors. The quickest way to set an image background is using the wsh setbg command:
# Set an image background with 50% opacity (default)
wsh setbg ~/pictures/background.jpg
# Set a color background (use quotes to prevent # being interpreted as a shell comment)
wsh setbg "#ff0000" # hex color
wsh setbg forestgreen # CSS color name
# Adjust opacity
wsh setbg --opacity 0.3 ~/pictures/light-pattern.png
wsh setbg --opacity 0.7 # change only opacity of current background
# Image positioning options
wsh setbg --tile ~/pictures/texture.png # create tiled pattern
wsh setbg --center ~/pictures/logo.png # center without scaling
wsh setbg --center --size 200px ~/pictures/logo.png # center with specific size (px, %, auto)
# Remove background
wsh setbg --clearYou can use any JPEG, PNG, GIF, WebP, or SVG image as your background. The --center option is particularly useful for logos or icons where you want to maintain the original size.
To preview the metadata for any background without applying it, use the --print flag:
wsh setbg --print "#ff0000"For more advanced customization options including gradients, colors, and saving your own custom backgrounds, check out our Tab Backgrounds documentation.
File: docs/docs/customwidgets.mdx
sidebar_position: 6 id: "customwidgets" title: "Custom Widgets"
Custom Widgets
Wave allows users to create their own widgets to uniquely customize their experience for what works for them. While we plan on greatly expanding on this in the future, it is already possible to make some widgets that you can access at the press of a button. All widgets can be created by modifying the <WAVETERM_HOME>/config/widgets.json file. By adding a widget to this file, it is possible to add widgets to the widget bar. By default, the widget bar looks like this:
By adding additional widgets, it is possible to get a widget bar that looks like this:
The Structure of a Widget
All widgets share a similar structure that roughly looks like the example below:
"<widget name>": {
"icon": "",
"label": "",
"color": "",
"blockdef": {
"meta": {
"view": "term",
"controller": "cmd",
"cmd": ""
}
}
}This consists of a couple different parts. First and foremost, each widget has a unique identifying name. The value associated with this name is the outer WidgetConfigType. It is outlined in red below:
This WidgetConfigType is shared between all types of widgets. That is to say, all widgets—regardless of type— will use the same keys for this. The accepted keys are:
| Key | Description |
|---|---|
| "display:order" | (optional) Overrides the order of widgets with a number in case you want the widget to be different than the order provided in the widgets.json file. Defaults to 0. |
| "icon" | (optional) The name of a font awesome icon. Defaults to "browser". |
| "color" | (optional) A string representing a color as would be used in CSS. Hex codes and custom CSS properties are included. This defaults to "var(--secondary-text-color)" which is a color wave uses for text that should be differentiated from other text. Out of the box, it is "#c3c8c2". |
| "label" | (optional) A string representing the label that appears underneath the widget. It will also act as a tooltip on hover if the "description" key isn't filled out. It is null by default. |
| "description" | (optional) A description of what the widget does. If it is specified, this serves as a tooltip on hover. It is null by default. |
| "magnified" | (optional) A boolean indicating whether or not the widget should launch magnfied. It is false by default. |
| "blockdef" | This is where the the non-visual portion of the widget is defined. Note that all further definition takes place inside a meta object inside this one. |
Font Awesome Icons
Font Awesome provides a ton of useful icons that you can use as a widget icon in your app. At its simplest, you can just provide the icon name and it will be used. For example, the string "house", will provide an icon containing a house. We also allow you to apply a few different styles to your icon by modifying the name as follows:
| format | description |
|---|---|
| <icon name> | The plain icon with no additional styles applied. |
| solid@<icon name> | Adds the fa-solid class to the icon to fill in the content with a fill color rather than leaving it a background. |
| regular@<icon name> | Adds the fa-regular class to the icon to ensure the content will not have a fill color and will use a standard outline instead. |
| brands@<icon name> | This is required to add the required fa-brands class to an icon associated with a brand. Without this, brand icons will not render properly. This will not work with icons that aren't brand icons. |
:::
The other options are part of the inner MetaTSType (outlined in blue in the image). This contains all of the details about how the widget actually works. The valid keys vary with each type of widget. They will be individually explored in more detail below.
Terminal and CLI Widgets
A terminal widget, or CLI widget, is a widget that simply opens a terminal and runs a CLI command. They tend to look something like the example below:
{
<... other widgets go here ...>,
"<widget name>": {
"icon": "",
"label": "",
"color": "",
"blockdef": {
"meta": {
"view": "term",
"controller": "cmd",
"cmd": ""
}
}
},
<... other widgets go here ...>
}The WidgetConfigType takes the usual options common to all widgets. The MetaTSType can include the keys listed below:
| Key | Description |
|---|---|
| "view" | A string that specifies the general type of widget. In the case of custom terminal widgets, this must be set to "term". |
| "controller" | A string that specifies the type of command being used. For more persistent shell sessions, set it to "shell". For one off commands, set it to "cmd". When "cmd" is set, the widget has an additional refresh button in its header that allows the command to be re-run. |
| "cmd" | (optional) When the "controller" is set to "cmd", this option provides the actual command to be run. Note that because it is run as a command, there is no shell session unless you are launching a command that contains a shell session itself. Defaults to an empty string. |
| "cmd:args" | (optional, array of strings) arguments to pass to the cmd |
| "cmd:shell" | (optional) if cmd:shell if false (default), then we use cmd + cmd:args (suitable to pass to execve). if cmd:shell is true, then we just use cmd, and cmd can include spaces, and shell syntax (like pipes or redirections, etc.) |
| "cmd:interactive" | (optional) When the "controller" is set to `"term", this boolean adds the interactive flag to the launched terminal. Defaults to false. |
| "cmd:login" | (optional) When the "controller" is set to "term", this boolean adds the login flag to the term command. Defaults to false. |
| "cmd:runonstart" | (optional) The command will rerun when the block is created or the app is started. Without it, you must manually run the command. Defaults to true. |
| "cmd:runonce" | (optional) Runs on start, but then sets "cmd:runonce" and "cmd:runonstart" to false (so future runs require manual restarts) |
| "cmd:clearonstart" | (optional) When the cmd runs, the contents of the block are cleared out. Defaults to false. |
| "cmd:closeonexit" | (optional) Automatically closes the block if the command successfully exits (exit code = 0) |
| "cmd:closeonexitforce" | (optional) Automatically closes the block if when the command exits (success or failure) |
| "cmd:closeonexitdelay | (optional) Change the delay between when the command exits and when the block gets closed, in milliseconds, default 2000 |
| "cmd:env" | (optional) A key-value object represting environment variables to be run with the command. Defaults to an empty object. |
| "cmd:cwd" | (optional) A string representing the current working directory to be run with the command. Currently only works locally. Defaults to the home directory. |
| "cmd:nowsh" | (optional) A boolean that will turn off wsh integration for the command. Defaults to false. |
| "cmd:jwt" | (optional) A boolean that forces adding JWT token to the environment. Required for running waveapps as widgets (both local and remote). Defaults to false. |
| "term:localshellpath" | (optional) Sets the shell used for running your widget command. Only works locally. If left blank, wave will determine your system default instead. |
| "term:localshellopts" | (optional) Sets the shell options meant to be used with "term:localshellpath". This is useful if you are using a nonstandard shell and need to provide a specific option that we do not cover. Only works locally. Defaults to an empty string. |
| "cmd:initscript" | (optional) for "shell" controller only. an init script to run before starting the shell (can be an inline script or an absolute local file path) |
| cmd:initscript.sh" | (optional) same as cmd:initscript but applies to bash/zsh shells only |
| cmd:initscript.bash" | (optional) same as cmd:initscript but applies to bash shells only |
| cmd:initscript.zsh" | (optional) same as cmd:initscript but applies to zsh shells only |
| cmd:initscript.pwsh" | (optional) same as cmd:initscript but applies to pwsh/powershell shells only |
| cmd:initscript.fish" | (optional) same as cmd:initscript but applies to fish shells only |
Example Local Shell Widgets
If you have multiple shells installed on your machine, there may be times when you want to use a non-default shell. For cases like this, it is easy to create a widget for each.
Suppose you want a widget to launch a fish shell. Once you have fish installed on your system, you can define a widget as
{
<... other widgets go here ...>,
"fish" : {
"icon": "fish",
"color": "#4abc39",
"label": "fish",
"blockdef": {
"meta": {
"view": "term",
"controller": "shell",
"term:localshellpath": "/usr/local/bin/fish",
"term:localshellopts": "-i -l"
}
}
},
<... other widgets go here ...>
}This adds an icon to the widget bar that you can press to launch a terminal running the fish shell.
:::info
It is possible that fish is not in your path. If this is true, using "fish" as the value of "term:localshellpath" will not work. In these cases, you will need to provide a direct path to it. This is often somewhere like "/usr/local/bin/fish", but it may be different on your system.
:::
If you want to do the same for something like Powershell Core, or pwsh, you can define the widget as
{
<... other widgets go here ...>,
"pwsh" : {
"icon": "rectangle-terminal",
"color": "#2671be",
"label": "pwsh",
"blockdef": {
"meta": {
"view": "term",
"controller": "shell",
"term:localshellpath": "pwsh"
}
}
},
<... other widgets go here ...>
}This adds an icon to the widget bar that you can press to launch a terminal running the pwsh shell.
:::info
It is possible that pwsh is not in your path. If this is true, using "pwsh" as the value of "term:localshellpath" will not work. In these cases, you will need to provide a direct path to it. This could be somewhere like "/usr/local/bin/pwsh" on a Unix system or "C:\\Program Files\\PowerShell\\7\\pwsh.exe" on
Windows. but it may be different on your system. Also note that both pwsh.exe and pwsh work on Windows, but only pwsh works on Unix systems.
:::
Example Remote Shell Widgets
If you want to open a terminal widget for a particular connection (SSH or WSL), you can use the connection meta key. The connection key's value should match connections.json (or what's in your connections dropdown menu). Note that you should only use the canonical name (do not use any custom "display:name" that you've set). For WSL that might look like wsl://Ubuntu, and for SSH connections that might look like user@remotehostname.
{
<... other widgets go here ...>,
"remote-term": {
"icon": "rectangle-terminal",
"label": "remote",
"blockdef": {
"meta": {
"view": "term",
"controller": "shell",
"connection": "<connection>"
}
}
},
<... other widgets go here ...>
}Example Cmd Widgets
Here are a few simple cmd widgets to serve as examples.
Suppose I want a widget that will run speedtest-go when opened. Then, I can define a widget as
{
<... other widgets go here ...>,
"speedtest" : {
"icon": "gauge-high",
"label": "speed",
"blockdef": {
"meta": {
"view": "term",
"controller": "cmd",
"cmd": "speedtest-go --unix",
"cmd:clearonstart": true
}
}
},
<... other widgets go here ...>
}This adds an icon to the widget bar that you can press to launch a terminal running the speedtest-go --unix command.
Using "cmd" for the "controller" is the simplest way to accomplish this. "cmd:clearonstart" isn't necessary, but it makes it so every time the command is run (which can be done by right clicking the header and selecting Force Controller Restart), the previous contents are cleared out.
Now suppose I wanted to run a TUI app, for instance, dua. Well, it turns out that you can more or less do the same thing:
{
<... other widgets go here ...>,
"dua" : {
"icon": "brands@linux",
"label": "dua",
"blockdef": {
"meta": {
"view": "term",
"controller": "cmd",
"cmd": "dua"
}
}
},
<... other widgets go here ...>
}This adds an icon to the widget bar that you can press to launch a terminal running the dua command.
Because this is a TUI app that does not return anything when closed, the "cmd:clearonstart" option doesn't change the behavior, so it has been excluded.
Web Widgets
Sometimes, it is desireable to open a page directly to a website. That can easily be accomplished by creating a custom "web" widget. They have the following form in general:
{
<... other widgets go here ...>,
"<widget name>": {
"icon": "",
"label": "",
"color": "",
"blockdef": {
"meta": {
"view": "web",
"url": ""
}
}
},
<... other widgets go here ...>
}The WidgetConfigType takes the usual options common to all widgets. The MetaTSType can include the keys listed below:
| Key | Description |
|---|---|
| "view" | A string that specifies the general type of widget. In the case of custom web widgets, this must be set to "web". |
| "url" | This string is the url of the current page. As part of a widget, it will serve as the page the widget starts at. If not specified, this will default to the globally configurable "web:defaulturl" which is https://github.com/wavetermdev/waveterm on a fresh install. |
| "pinnedurl" | (optional) This string is the url the homepage button will take you to. If not specified, this will default to the globally configurable "web:defaulturl" which is https://github.com/wavetermdev/waveterm on a fresh install. |
Example Web Widgets
Say you want a widget that automatically starts at YouTube and will use YouTube as the home page. This can be done using:
{
<... other widgets go here ...>,
"youtube" : {
"icon": "brands@youtube",
"label": "youtube",
"blockdef": {
"meta": {
"view": "web",
"url": "https://youtube.com",
"pinnedurl": "https://youtube.com"
}
}
},
<... other widgets go here ...>
}This adds an icon to the widget bar that you can press to launch a web widget on the youtube homepage.
Alternatively, say you want a web widget that opens to github as if it were a bookmark, but will use google as its home page after that. This can easily be done with:
{
<... other widgets go here ...>,
"github" : {
"icon": "brands@github",
"label": "github",
"blockdef": {
"meta": {
"view": "web",
"url": "https://github.com",
"pinnedurl": "https://google.com"
}
}
},
<... other widgets go here ...>
}This adds an icon to the widget bar that you can press to launch a web widget on the github homepage.
Sysinfo Widgets
The Sysinfo Widget is intentionally kept to a very small subset of possible values that we will expand over time. But it is still possible to configure your own version of it—for instance, if you want to load a different plot by default. The general form of this widget is:
{
<... other widgets go here ...>,
"<widget name>": {
"icon": "",
"label": "",
"color": "",
"blockdef": {
"meta": {
"view": "sysinfo",
"graph:numpoints": ,
"sysinfo:type": ,
}
}
},
<... other widgets go here ...>
}The WidgetConfigType takes the usual options common to all widgets. The MetaTSType can include the keys listed below:
| Key | Description |
|---|---|
| "view" | A string that specifies the general type of widget. In the case of custom sysinfo widgets, this must be set to "sysinfo". |
| "graph:numpoints" | The maximum amount of points that can be shown on the graph. Equivalently, the number of seconds the graph window covers. This defaults to 100. |
| "sysinfo:type" | A string representing the collection of types to show on the graph. Valid values for this are "CPU", "Mem", "CPU + Mem", and All CPU. Note that these are case sensitive. If no value is provided, the plot will default to showing "CPU". |
Example Sysinfo Widgets
Suppose you have a build process that lasts 3 minutes and you'd like to be able to see the entire build on the sysinfo graph. Also, you would really like to view both the cpu and memory since both are impacted by this process. In that case, you can set up a widget as follows:
{
<... other widgets go here ...>,
"3min-info" : {
"icon": "circle-3",
"label": "3mininfo",
"blockdef": {
"meta": {
"view": "sysinfo",
"graph:numpoints": 180,
"sysinfo:type": "CPU + Mem"
}
}
},
<... other widgets go here ...>
}This adds an icon to the widget bar that you can press to launch the CPU and Memory plots by default with 180 seconds of data.
Now, suppose you are fine with the default 100 points (and 100 seconds) but would like to show all of the CPU data when launched. In that case, you can write:
{
<... other widgets go here ...>,
"all-cpu" : {
"icon": "chart-scatter",
"label": "all-cpu",
"blockdef": {
"meta": {
"view": "sysinfo",
"sysinfo:type": "All CPU"
}
}
},
<... other widgets go here ...>
}This adds an icon to the widget bar that you can press to launch All CPU plots by default.
Overriding Default Widgets
Wave ships with 5 default widgets in the widgets bar (terminal, files, web, ai, and sysinfo). You can modify or remove these by overriding their config in widgets.json. The names of the 5 widgets, in order, are:
defwidget@terminaldefwidget@filesdefwidget@webdefwidget@aidefwidget@sysinfo
To remove any of them, just set that key to null in your widgets.json file.
To see their definitions, to copy/paste them, or to understand how they work, you can view all of their definitions on GitHub - default widgets.json
File: docs/docs/faq.mdx
sidebar_position: 101 id: "faq" title: "FAQ"
import { VersionBadge } from "@site/src/components/versionbadge";
FAQ
How can I see the block numbers?
The block numbers will appear when you hold down Ctrl-Shift (and disappear once you release the key combo).
How do I make a remote connection?
There is a button in the header. Click the or
and type the [user]@[host] that you wish to connect to.
On Windows, how can I use Git Bash as my default shell?
Wave automatically detects Git Bash installations and adds them to the connection dropdown. Simply click the or button in the block header and select "Git Bash" from the list.
Alternatively, you can manually set Git Bash as your default shell by setting the configuration variable term:localshellpath to
the location of the Git Bash "bash.exe" binary. By default it is located at "C:\Program Files\Git\bin\bash.exe".
Just remember in JSON, backslashes need to be escaped. So add this to your settings.json file:
"term:localshellpath": "C:\\Program Files\\Git\\bin\\bash.exe"Can I use WSH outside of Wave?
wsh is an internal CLI for extending control over Wave to the command line, you can learn more about it here. To prevent misuse by other applications, wsh requires an access token provided by Wave to work and will not function outside of the app.
Why does Wave warn me about ARM64 translation when it launches?
macOS and Windows both have compatibility layers that allow x64 applications to run on ARM computers. This helps more apps run on these systems while developers work to add native ARM support to their applications. However, it comes with significant performance tradeoffs.
To get the best experience using Wave, it is recommended that you uninstall Wave and reinstall the version that is natively compiled for your computer. You can find the right version by consulting our Installation Instructions.
You can disable this warning by setting app:dismissarchitecturewarning=true in your configurations.
How do I join the beta builds of Wave?
Wave publishes to two channels, latest and beta. If you've installed the app for macOS, Windows, or Linux via DEB or RPM, you can set the following configurations in your settings.json (see Configuration for more info):
"autoupdate:enabled": true,
"autoupdate:channel": "beta"If you've installed via Snap, you can use the following command:
sudo snap install waveterm --classic --betaCan I use Wave AI without enabling telemetry?
Yes! Wave AI is normally disabled when telemetry is not enabled. However, you can enable Wave AI features without telemetry by configuring your own custom AI model (either a local model or using your own API key).
To enable Wave AI without telemetry:
- Configure a custom AI mode (see Wave AI documentation)
- Set
waveai:defaultmodeto your custom mode's key in your Wave settings
Once you've completed both steps, Wave AI will be enabled and you can use it completely privately without telemetry. This allows you to use local models like Ollama or your own API keys with providers like OpenAI, OpenRouter, or others.
File: docs/docs/gettingstarted.mdx
sidebar_position: 1 id: "gettingstarted" title: "Getting Started"
import { PlatformProvider, PlatformSelectorButton, PlatformItem } from "@site/src/components/platformcontext";
import { Kbd } from "@site/src/components/kbd";
Wave Terminal is a modern terminal that includes graphical capabilities like web browsing, file previews, and AI assistance alongside traditional terminal features. This guide will help you get started.
Installation
Platform requirements
Supported architectures: Apple Silicon, x64
Supported OS version: macOS 11 Big Sur or later
Supported architectures: x64
Supported OS version: Windows 10 1809 or later, Windows 11
:::note
ARM64 is planned, but is currently blocked by upstream dependencies (see Windows ARM Support).
:::
- Supported architectures: x64, ARM64
- Supported OS version: must have glibc-2.28 or later (Debian >=10, RHEL >=8, Ubuntu >=20.04, etc.)
Package managers
Homebrew
brew install --cask waveWindows Package Manager
winget install CommandLine.WaveChocolatey
choco install waveSnap
sudo snap install --classic wavetermOther options available: AUR package (community maintained), Nix package (community maintained)
You can also download installers directly from our Downloads page.
Core Concepts
Tabs and Blocks
- Tabs: Like browser tabs, these help organize your work. Create new tabs with .
- Blocks: The building blocks of Wave. Each block can be a terminal, web browser, file preview, or other widget.
- Layout: Blocks can be dragged, dropped, and resized to create your ideal layout.
Key Features
Terminal Features
- Works with common shells (bash, zsh, fish)
- Supports standard terminal features (readline, control sequences, etc)
- Includes the
wshcommand for interacting with Wave's GUI features - GPU accelerated (on most platforms)
Graphical Widgets
- Preview files (images, video, markdown, code with syntax highlighting)
- Browse web pages
- Ask questions and get AI help directly from the terminal (set up multiple AI models)
- Basic system monitoring graphs
Remote Connections
- Easy SSH connections with the connection button
- WSL integration on Windows
- Consistent experience across local and remote sessions
Quick Start Guide
Open Your First New Tab
- New Wave tabs start with a single terminal block
- Use it just like your regular terminal
- Create additional terminal blocks with
Try Some Basic Commands
bash# View a file or directory wsh view ~/Documents # Open a webpage wsh web open github.com # Get AI assistance wsh ai -m "how do I find large files in my current directory?" -sCustomize Your Layout
- Drag block headers to rearrange them
- Hover between blocks to resize them
- Right-click tab headers for background options
- Right-click block headers for block-specific options
Connect to Remote Machines
- Click the button
- Enter
username@hostnamefor SSH connections - Or select a WSL distribution on Windows
Next Steps
- Explore Key Bindings to work more efficiently
- Learn about Tab Layouts to organize your workspace
- Set up Custom Widgets for quick access to your tools
- Configure Wave AI to use your preferred AI models
- Check out Configuration for detailed customization options
Getting Help
- Join our Discord community for help and discussions
- Report issues on GitHub
- Check our FAQ for common questions
File: docs/docs/index.mdx
sidebar_position: -1 id: "index" title: "Home" hide_title: true hide_table_of_contents: true
import { Card, CardGroup } from "@site/src/components/card";
Welcome to Wave Terminal
Wave is an open-source terminal that combines traditional terminal features with graphical capabilities like file previews, web browsing, and AI assistance. It runs on MacOS, Linux, and Windows.
Modern development involves constantly switching between terminals and browsers - checking documentation, previewing files, monitoring systems, and using AI tools. Wave brings these graphical tools directly into the terminal, letting you control them from the command line. This means you can stay in your terminal workflow while still having access to the visual interfaces you need.
Check out Getting Started for installation instructions.
:::info
If you have a question, please feel free to ask us in Discord. If you'd like to file a bug/enchancement, please use Github Issues. These docs are also open-source and we do accept PRs for docs here. You can click the "Edit this page" link at the bottom of the page to get taken directly to the editor page for that document in GitHub.
:::
Other References:
Roadmap
Want to provide input to our future releases? Connect with us on Discord or open a Feature Request!
Links
- Homepage https://waveterm.dev
- Download https://waveterm.dev/download
- Discord https://discord.gg/XfvZ334gwU
- GitHub https://github.com/wavetermdev/waveterm/
Looking for WaveLegacy documentation?
WaveLegacy docs can be found at legacydocs.waveterm.dev.
File: docs/docs/keybindings.mdx
sidebar_position: 2 id: "keybindings" title: "Key Bindings"
import { Kbd, KbdChord } from "@site/src/components/kbd";
import { PlatformProvider, PlatformSelectorButton } from "@site/src/components/platformcontext";
import { VersionBadge } from "@site/src/components/versionbadge";
Here's the set of default keybindings available in Wave. It is split into sections.
Some keybindings are always active. Others are only active for certain types of blocks.
Note that these are the MacOS keybindings (they use "Cmd"). For Windows and Linux,
replace "Cmd" with "Alt" (note that "Ctrl" is "Ctrl" on both Mac, Windows, and Linux).
Chords are shown with a + between the keys. You have 2 seconds to hit the 2nd chord key after typing the first key. Hitting Escape after an initial chord key will always be a no-op.
Global Keybindings
| Key | Function |
|---|---|
| Open a new tab | |
Open a new block (defaults to a terminal block with the same connection and working directory). Switch to launcher using app:defaultnewblock setting |
|
| Toggle WaveAI panel visibility | |
| Split horizontally, open a new block to the right | |
| Split vertically, open a new block below | |
| Split vertically, open a new block above | |
| Split vertically, open a new block below | |
| Split horizontally, open a new block to the left | |
| Split horizontally, open a new block to the right | |
| Open a new window | |
| Close the current block | |
| Close the current tab | |
| Magnify / Un-Magnify the current block | |
| Open the "connection" switcher | |
| Refocus the current block (useful if the block has lost input focus) | |
| Show block numbers | |
| Focus WaveAI input | |
| Switch to block number | |
| / | Move left, right, up, down between blocks |
| Replace the current block with a launcher block | |
| Rename the current tab |
|
| Switch to tab number | |
| / | Switch tab left |
| / | Switch tab right |
| Switch to workspace number | |
| Refresh the UI | |
| Toggle terminal multi-input mode |
File Preview Keybindings
| Key | Function |
|---|---|
| Any regular character (e.g. "a", "b") will filter the file list | |
| Clears the filter | |
| / | Change file selection up/down |
| Open the currently selected file/directory | |
| Move "up" a directory (parent directory) | |
| Back, move to the previously selected file/directory | |
| Forward (opposite of back) | |
| Open a new file (accepts relative paths to the current directory) | |
| When file editor is open, save file | |
| For files that can be previewed or edited (markdown, CSVs), switches between preview and edit mode | |
| When file editor is open, revert changes |
Web Keybindings
| Key | Function |
|---|---|
| Focus the URL input bar | |
| When the URL input bar is focused, will focus the web content | |
| Reload webpage | |
| Back | |
| Forward | |
| Find in webpage | |
| Open a bookmark |
WaveAI Keybindings
| Key | Function |
|---|---|
| Toggle WaveAI panel | |
| Focus WaveAI input | |
| Clear AI Chat |
Terminal Keybindings
| Key | Function |
|---|---|
| Copy | |
| Paste | |
| Paste (Windows Only) | |
| Clear Terminal | |
| Find in Terminal | |
| Scroll to top | |
| Scroll to bottom | |
| Scroll to top (macOS only) | |
| Scroll to bottom (macOS only) | |
| Move to beginning of line (macOS only) | |
| Move to end of line (macOS only) | |
| Scroll up one page | |
| Scroll down one page |
Process Viewer Keybindings
| Key | Function |
|---|---|
| Pause / resume live updates | |
| Open process filter / search | |
| Close search bar |
Customizeable Systemwide Global Hotkey
Wave allows setting a custom global hotkey to focus your most recent window from anywhere in your computer. For more information on this, see the config docs.