Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 35 additions & 0 deletions cmd/wsh/cmd/wshcmd-secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import (
"strings"

"github.com/spf13/cobra"
"github.com/wavetermdev/waveterm/pkg/waveobj"
"github.com/wavetermdev/waveterm/pkg/wshrpc"
"github.com/wavetermdev/waveterm/pkg/wshrpc/wshclient"
)

// secretNameRegex must match the validation in pkg/wconfig/secretstore.go
var secretNameRegex = regexp.MustCompile(`^[A-Za-z][A-Za-z0-9_]*$`)

var secretUiMagnified bool

var secretCmd = &cobra.Command{
Use: "secret",
Short: "manage secrets",
Expand Down Expand Up @@ -54,12 +57,22 @@ var secretDeleteCmd = &cobra.Command{
PreRunE: preRunSetupRpcClient,
}

var secretUiCmd = &cobra.Command{
Use: "ui",
Short: "open secrets UI",
Args: cobra.NoArgs,
RunE: secretUiRun,
PreRunE: preRunSetupRpcClient,
}

func init() {
secretUiCmd.Flags().BoolVarP(&secretUiMagnified, "magnified", "m", false, "open secrets UI in magnified mode")
rootCmd.AddCommand(secretCmd)
secretCmd.AddCommand(secretGetCmd)
secretCmd.AddCommand(secretSetCmd)
secretCmd.AddCommand(secretListCmd)
secretCmd.AddCommand(secretDeleteCmd)
secretCmd.AddCommand(secretUiCmd)
}

func secretGetRun(cmd *cobra.Command, args []string) (rtnErr error) {
Expand Down Expand Up @@ -156,4 +169,26 @@ func secretDeleteRun(cmd *cobra.Command, args []string) (rtnErr error) {

WriteStdout("secret deleted: %s\n", name)
return nil
}

func secretUiRun(cmd *cobra.Command, args []string) (rtnErr error) {
defer func() {
sendActivity("secret", rtnErr == nil)
}()

wshCmd := &wshrpc.CommandCreateBlockData{
BlockDef: &waveobj.BlockDef{
Meta: map[string]interface{}{
waveobj.MetaKey_View: "secretstore",
},
},
Magnified: secretUiMagnified,
Focused: true,
}

_, err := RpcClient.SendRpcRequest(wshrpc.Command_CreateBlock, wshCmd, &wshrpc.RpcOpts{Timeout: 2000})
if err != nil {
return fmt.Errorf("opening secrets UI: %w", err)
}
return nil
}
51 changes: 46 additions & 5 deletions docs/docs/wsh-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -342,19 +342,36 @@ This will connect to a WSL distribution on the local machine. It will use the de

## web

You can search for a given url using:
The `web` command opens URLs in a web block within Wave Terminal.

```sh
wsh web open [url]
wsh web open [url] [-m] [-r blockid]
```

Alternatively, you can search with the configured search engine using:
You can open a specific URL or perform a search using the configured search engine.

Flags:

- `-m, --magnified` - open the web block in magnified mode
- `-r, --replace <blockid>` - replace an existing block instead of creating a new one

Examples:

```sh
wsh web open [search-query]
# Open a URL
wsh web open https://waveterm.dev

# Search with the configured search engine
wsh web open "wave terminal documentation"

# Open in magnified mode
wsh web open -m https://github.com

# Replace an existing block
wsh web open -r 2 https://example.com
```

Both of these commands will open a new web block with the desired page.
The command will open a new web block with the desired page, or replace an existing block if the `-r` flag is used. Note that `--replace` and `--magnified` cannot be used together.

---

Expand Down Expand Up @@ -978,6 +995,30 @@ wsh secret delete old_api_key
wsh secret delete temp_token
```

### ui

```sh
wsh secret ui [-m]
```

Open the secrets management interface in a new block. This provides a graphical interface for viewing and managing all your secrets.

Flags:

- `-m, --magnified` - open the secrets UI in magnified mode

Examples:

```sh
# Open the secrets UI
wsh secret ui

# Open the secrets UI in magnified mode
wsh secret ui -m
```

The secrets UI provides a convenient visual way to browse, add, edit, and delete secrets without needing to use the command-line interface.

:::tip
Use secrets in your scripts to avoid hardcoding sensitive values. Secrets work across remote machines - store an API key locally with `wsh secret set`, then access it from any SSH or WSL connection with `wsh secret get`. The secret is securely retrieved from your local machine without needing to duplicate it on remote systems.
:::
Expand Down
13 changes: 10 additions & 3 deletions frontend/app/view/secretstore/secretstore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,19 @@ const LoadingSpinner = memo(({ message }: { message: string }) => {
});
LoadingSpinner.displayName = "LoadingSpinner";

const EmptyState = memo(() => {
const EmptyState = memo(({ onAddSecret }: { onAddSecret: () => void }) => {
return (
<div className="flex flex-col items-center justify-center gap-3 py-12">
<div className="flex flex-col items-center justify-center gap-4 py-12">
<i className="fa-sharp fa-solid fa-key text-4xl text-gray-600" />
<h3 className="text-lg font-semibold text-gray-400">No Secrets</h3>
<p className="text-gray-500">Add a secret to get started</p>
<button
className="flex items-center gap-2 px-4 py-2 bg-accent-600 hover:bg-accent-500 rounded cursor-pointer transition-colors"
onClick={onAddSecret}
>
<i className="fa-sharp fa-solid fa-plus" />
<span className="font-medium">Add New Secret</span>
</button>
</div>
);
});
Expand Down Expand Up @@ -352,7 +359,7 @@ export const SecretStoreView = memo(({ model }: { blockId: string; model: Secret
}

if (secretNames.length === 0) {
return <EmptyState />;
return <EmptyState onAddSecret={() => model.startAddingSecret()} />;
}

return (
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading