Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1aa5eb8
add a backend config update system (easier than wps)
sawka Nov 29, 2025
39164ea
add no telemetry watcher + add panic handlers
sawka Nov 29, 2025
9f4db4e
ssh password from secret store
sawka Nov 29, 2025
a4f27c7
integrate secret store functionality into waveconfig
sawka Nov 29, 2025
c21997c
open secrets in waveconfig from menu... dont center anymore
sawka Nov 29, 2025
e28d6e6
remove max width
sawka Nov 29, 2025
dde9ebb
add secrets docs. add new connection secret pw doc
sawka Dec 1, 2025
b69c3fc
working on wave ai modes documentation
sawka Dec 1, 2025
456b3da
Merge remote-tracking branch 'origin/main' into sawka/config-updates
sawka Dec 2, 2025
68b7369
rename ai:baseurl => ai:endpoint to be more clear
sawka Dec 3, 2025
ac4d731
make fewer fields required for AI config
sawka Dec 3, 2025
b0b5b37
working on ai:provider, and better schema
sawka Dec 3, 2025
9179a06
add openai + openrouter providers
sawka Dec 3, 2025
c6eff86
add azure ai provider
sawka Dec 4, 2025
5b90771
generate schema/types
sawka Dec 4, 2025
932c737
widgets.json open in waveconfig, add to ai context
sawka Dec 4, 2025
c9d9704
add configure modes
sawka Dec 4, 2025
ec2ab56
better mode switcher, waveai cloud / custom models separated
sawka Dec 4, 2025
484cbb8
add 2 new settings, waveai:defaultmode and waveai:showcloudmodes
sawka Dec 4, 2025
7c92805
reafactor on config (to support tabs/multiple views), fix context men…
sawka Dec 4, 2025
705e64b
remove unused
sawka Dec 4, 2025
924e40e
always set auth header (even if apitoken is empty)
sawka Dec 4, 2025
49ab592
remove shortdesc, not used
sawka Dec 4, 2025
3b1a05d
apply openai-chat as the default apitype
sawka Dec 4, 2025
fe45aa5
more config updates, sanitizing, making more consistent
sawka Dec 4, 2025
a44fd1c
fix iswaveproxy to use wave provider
sawka Dec 4, 2025
69ee6ca
fix some nits
sawka Dec 4, 2025
127544e
allow azure to set api-key, fix some error messages, fix some anthrop…
sawka Dec 4, 2025
5c7d3c4
fix outline
sawka Dec 5, 2025
3698197
remove unused
sawka Dec 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
709 changes: 709 additions & 0 deletions aiprompts/aimodesconfig.md

Large diffs are not rendered by default.

53 changes: 52 additions & 1 deletion cmd/server/main-server.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ func doShutdown(reason string) {

// watch stdin, kill server if stdin is closed
func stdinReadWatch() {
defer func() {
panichandler.PanicHandler("stdinReadWatch", recover())
}()
buf := make([]byte, 1024)
for {
_, err := os.Stdin.Read(buf)
Expand All @@ -109,6 +112,9 @@ func startConfigWatcher() {
}

func telemetryLoop() {
defer func() {
panichandler.PanicHandler("telemetryLoop", recover())
}()
var nextSend int64
time.Sleep(InitialTelemetryWait)
for {
Expand All @@ -120,6 +126,42 @@ func telemetryLoop() {
}
}

func sendNoTelemetryUpdate(telemetryEnabled bool) {
ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
defer cancelFn()
clientData, err := wstore.DBGetSingleton[*waveobj.Client](ctx)
if err != nil {
log.Printf("telemetry update: error getting client data: %v\n", err)
return
}
if clientData == nil {
log.Printf("telemetry update: client data is nil\n")
return
}
err = wcloud.SendNoTelemetryUpdate(ctx, clientData.OID, !telemetryEnabled)
if err != nil {
log.Printf("[error] sending no-telemetry update: %v\n", err)
return
}
}

func setupTelemetryConfigHandler() {
watcher := wconfig.GetWatcher()
if watcher == nil {
return
}
currentConfig := watcher.GetFullConfig()
currentTelemetryEnabled := currentConfig.Settings.TelemetryEnabled

watcher.RegisterUpdateHandler(func(newConfig wconfig.FullConfigType) {
newTelemetryEnabled := newConfig.Settings.TelemetryEnabled
if newTelemetryEnabled != currentTelemetryEnabled {
currentTelemetryEnabled = newTelemetryEnabled
go sendNoTelemetryUpdate(newTelemetryEnabled)
}
})
}

func backupCleanupLoop() {
defer func() {
panichandler.PanicHandler("backupCleanupLoop", recover())
Expand Down Expand Up @@ -232,6 +274,9 @@ func beforeSendActivityUpdate(ctx context.Context) {
}

func startupActivityUpdate(firstLaunch bool) {
defer func() {
panichandler.PanicHandler("startupActivityUpdate", recover())
}()
ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
defer cancelFn()
activity := wshrpc.ActivityUpdate{Startup: 1}
Expand Down Expand Up @@ -476,11 +521,17 @@ func main() {
maybeStartPprofServer()
go stdinReadWatch()
go telemetryLoop()
setupTelemetryConfigHandler()
go updateTelemetryCountsLoop()
go backupCleanupLoop()
go startupActivityUpdate(firstLaunch) // must be after startConfigWatcher()
blocklogger.InitBlockLogger()
go wavebase.GetSystemSummary() // get this cached (used in AI)
go func() {
defer func() {
panichandler.PanicHandler("GetSystemSummary", recover())
}()
wavebase.GetSystemSummary()
}()

webListener, err := web.MakeTCPListener("web")
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions cmd/testai/main-testai.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func testOpenAIComp(ctx context.Context, model, message string, tools []uctypes.
opts := &uctypes.AIOptsType{
APIType: uctypes.APIType_OpenAIChat,
APIToken: apiKey,
BaseURL: "https://api.openai.com/v1/chat/completions",
Endpoint: "https://api.openai.com/v1/chat/completions",
Model: model,
MaxTokens: 4096,
ThinkingLevel: uctypes.ThinkingLevelMedium,
Expand Down Expand Up @@ -216,7 +216,7 @@ func testOpenRouter(ctx context.Context, model, message string, tools []uctypes.
opts := &uctypes.AIOptsType{
APIType: uctypes.APIType_OpenAIChat,
APIToken: apiKey,
BaseURL: "https://openrouter.ai/api/v1/chat/completions",
Endpoint: "https://openrouter.ai/api/v1/chat/completions",
Model: model,
MaxTokens: 4096,
ThinkingLevel: uctypes.ThinkingLevelMedium,
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/ai-presets.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
sidebar_position: 3.6
id: "ai-presets"
title: "AI Presets"
title: "AI Presets (Deprecated)"
---
:::warning Deprecation Notice
The AI Widget and its presets are being replaced by [Wave AI](./waveai.mdx). Please refer to the Wave AI documentation for the latest AI features and configuration options.
Expand Down
3 changes: 3 additions & 0 deletions docs/docs/connections.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ 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, local WSL connections, and AWS S3 buckets.
Expand Down Expand Up @@ -156,6 +158,7 @@ In addition to the regular ssh config file, wave also has its own config file to
| 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](/secrets) to use as the SSH password. When set, this password will be automatically used for password authentication instead of prompting the user. <VersionBadge version="v0.13" /> |
| 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.|
Expand Down
100 changes: 0 additions & 100 deletions docs/docs/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,6 @@ title: "FAQ"

# FAQ

### How do I enable Claude Code support with Shift+Enter?

Wave supports Claude Code and similar AI coding tools that expect Shift+Enter to send an escape sequence + newline (`\u001b\n`) instead of a regular carriage return. This can be enabled using the `term:shiftenternewline` configuration setting.

To enable this globally for all terminals:
```bash
wsh setconfig term:shiftenternewline=true
```

To enable this for just a specific terminal block:
```bash
wsh setmeta term:shiftenternewline=true
```

You can also set this in your [settings.json](./config) file:
```json
"term:shiftenternewline": true
```

### 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).
Expand All @@ -48,87 +29,6 @@ Just remember in JSON, backslashes need to be escaped. So add this to your [sett

`wsh` is an internal CLI for extending control over Wave to the command line, you can learn more about it [here](./wsh). To prevent misuse by other applications, `wsh` requires an access token provided by Wave to work and will not function outside of the app.

### How do I make new blocks or splits inherit my shell’s current directory?

Wave uses a special escape sequence (OSC 7) to track the shell’s working directory and maintain the working directory of new terminal blocks and splits. Wave listens for these sequences to update its `cmd:cwd` metadata. That metadata is copied to new blocks when you:

- Open a new terminal block (Alt N / Cmd N)
- Split a pane (Cmd D / Cmd Shift D)

Not all shells emit this escape sequence, so new blocks or splits may start in your home directory instead. To ensure your shell emits the OSC 7 escape sequence, add the following to your shell startup/config file and restart Wave (or source your config).

#### Bash

Add to `~/.bashrc` or `~/.bash_profile`:

```bash
# Emit OSC 7 on each prompt to tell terminal about new working directory
__update_cwd() {
# Only run in interactive shells
[[ $- == *i* ]] || return
# Only run if attached to a terminal
[ -t 1 ] || return
# Redirect to tty so output doesn't show in shell
printf "\033]7;file://%s%s\007" "$HOSTNAME" "${PWD// /%20}" > /dev/tty
}
if [[ -n "$PROMPT_COMMAND" ]]; then
export PROMPT_COMMAND="__update_cwd; $PROMPT_COMMAND"
else
export PROMPT_COMMAND="__update_cwd"
fi
```

#### Zsh

Add to `~/.zshrc`:

```zsh
# Emit OSC 7 escape on directory change and prompt
function _wave_emit_cwd() {
printf "\033]7;file://%s%s\007" "$HOSTNAME" "${PWD// /%20}" > /dev/tty
}
autoload -U add-zsh-hook
add-zsh-hook chpwd _wave_emit_cwd
add-zsh-hook precmd _wave_emit_cwd
```

#### Fish

> Fish shell (v4.0.0 and later) emits OSC 7 by default—no config required.

For older Fish versions, add to `~/.config/fish/config.fish`:

```fish
# Emit OSC 7 on each PWD change
function _wave_emit_cwd --on-variable PWD
printf "\033]7;file://%s%s\007" (hostname) (string replace ' ' '%20' $PWD) > /dev/tty
end
```

After configuring, open a new block or split (Alt T / Cmd T, Alt N / Cmd N, Cmd D / Cmd Shift D) and verify blocks start in your current directory.

#### Verifying Current Directory Preservation

1. Open a Wave terminal block.
2. `cd` into a project folder, e.g. `cd ~/projects/foo`.
3. Right-click on the block's title bar and select "Copy BlockId" to retrieve the block’s ID.
4. Use the copied BlockId to retrieve the block’s metadata:

```bash
# Example: replace BLOCK_ID with your actual block reference
wsh getmeta --block BLOCK_ID
```

5. Confirm the output JSON contains a `cmd:cwd` field, for example:

```json
{
"cmd:cwd": "/Users/you/projects/foo",
...
}
```

6. Open a new block or split the pane—both should start in `/Users/you/projects/foo`.

## Why does Wave warn me about ARM64 translation when it launches?

Expand Down
147 changes: 147 additions & 0 deletions docs/docs/secrets.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
---
sidebar_position: 3.2
id: "secrets"
title: "Secrets"
---

import { VersionBadge } from "@site/src/components/versionbadge";

# Secrets

<VersionBadge version="v0.13" />

Wave Terminal provides a secure way to store sensitive information like passwords, API keys, and tokens. Secrets are stored encrypted in your system's native keychain (macOS Keychain, Windows Credential Manager, or Linux Secret Service), ensuring your sensitive data remains protected.

## Why Use Secrets?

Secrets in Wave Terminal allow you to:

- **Store SSH passwords** - Automatically authenticate to SSH connections without typing passwords
- **Manage API keys** - Keep API tokens, keys, and credentials secure
- **Share across sessions** - Access your secrets from any terminal block or remote connection
- **Avoid plaintext storage** - Never store sensitive data in configuration files or scripts

## Opening the Secrets UI

There are several ways to access the secrets management interface:

1. **From the widgets bar** (recommended):
- Click the **<i className="fa-gear fa-solid fa-sharp"/>** settings icon on the widgets bar
- Select **Secrets** from the menu

2. **From the command line:**
```bash
wsh secret ui
```


The secrets UI provides a visual interface to view, add, edit, and delete secrets.

## Managing Secrets via CLI

Wave Terminal provides a complete CLI for managing secrets from any terminal block:

```bash
# List all secret names (not values)
wsh secret list

# Get a specific secret value
wsh secret get MY_SECRET_NAME

# Set a secret (format: name=value, no spaces around =)
wsh secret set GITHUB_TOKEN=ghp_xxxxxxxxxx
wsh secret set DB_PASSWORD=super_secure_password

# Delete a secret
wsh secret delete MY_SECRET_NAME
```

## Secret Naming Rules

Secret names must match the pattern: `^[A-Za-z][A-Za-z0-9_]*$`

This means:
- Must start with a letter (A-Z or a-z)
- Can only contain letters, numbers, and underscores
- Cannot contain spaces or special characters

**Valid names:** `MY_SECRET`, `ApiKey`, `ssh_password_1`
**Invalid names:** `123_SECRET`, `my-secret`, `secret name`

## Using Secrets with SSH Connections

<VersionBadge version="v0.13" />

Secrets can be used to automatically provide passwords for SSH connections, eliminating the need to type passwords repeatedly.

### Configure in connections.json

Add the `ssh:passwordsecretname` field to your connection configuration:

```json
{
"myserver": {
"ssh:hostname": "example.com",
"ssh:user": "myuser",
"ssh:passwordsecretname": "SERVER_PASSWORD"
}
}
```

Then store your password as a secret:

```bash
wsh secret set SERVER_PASSWORD=my_actual_password
```

Now when Wave connects to `myserver`, it will automatically use the password from your secret store instead of prompting you.

### Benefits

- **Security**: Password stored encrypted in your system keychain
- **Convenience**: No need to type passwords for each connection
- **Flexibility**: Update passwords by changing the secret, not the configuration

## Security Considerations

- **Encrypted Storage**: Secrets are stored encrypted in your Wave configuration directory. The encryption key itself is protected by your operating system's secure credential storage (macOS Keychain, Windows Credential Manager, or Linux Secret Service).

- **No Plaintext**: Secrets are never stored unencrypted in logs or accessible files.

- **Access Control**: Secrets are only accessible to Wave Terminal.


## Storage Backend

Wave Terminal automatically detects and uses the appropriate secret storage backend for your operating system:

- **macOS**: Uses the macOS Keychain
- **Windows**: Uses Windows Credential Manager
- **Linux**: Uses the Secret Service API (freedesktop.org specification)

:::warning Linux Secret Storage
On Linux systems, Wave requires a compatible secret service backend (typically GNOME Keyring or KWallet). These are usually pre-installed with your desktop environment. If no compatible backend is detected, you won't be able to set secrets, and the UI will display a warning.
:::

## Troubleshooting

### "No appropriate secret manager found"

This error occurs on Linux when no compatible secret service backend is available. Install GNOME Keyring or KWallet and ensure the secret service is running.

### Secret not found

Ensure the secret name is spelled correctly (names are case-sensitive) and that the secret exists:

```bash
wsh secret list
```

### Permission denied on Linux

The secret service may require you to unlock your keyring. This typically happens after login. Consult your desktop environment's documentation for keyring management.

## Related Documentation

- [Connections](/connections) - Learn about SSH connections and configuration
- [wsh Command Reference](/wsh-reference#secret) - Complete CLI command documentation for secrets
Loading
Loading