Atlas / Skills / wavetermdev / Add Wshcmd

Add WshcmdSAFE

skills/wavetermdev/add-wshcmd

An open-source, AI-integrated, cross-platform terminal for seamless workflows

Verdict
SAFE
Grade
B
Trust score
89 /100
Version
—
Hosts
—
License
Apache-2.0
Stars
22,404
01

Overview

An open-source, AI-integrated, cross-platform terminal for seamless workflows

Read from source at commit 63907843412fOBSERVED · 2026-10-03
02

What it tells the agent

The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.

---
name: add-wshcmd
description: Guide for adding new wsh commands to Wave Terminal. Use when implementing new CLI commands, adding command-line functionality, or extending the wsh command interface.
---

# Adding a New wsh Command to Wave Terminal

This guide explains how to add a new command to the `wsh` CLI tool.

## wsh Command System Overview

Wave Terminal's `wsh` command provides CLI access to Wave Terminal features. The system uses:

1. **Cobra Framework** - CLI command structure and parsing
2. **Command Files** - Individual command implementations in `cmd/wsh/cmd/wshcmd-*.go`
3. **RPC Client** - Communication with Wave Terminal backend via `RpcClient`
4. **Activity Tracking** - Telemetry for command usage analytics
5. **Documentation** - User-facing docs in `docs/docs/wsh-reference.mdx`

Commands are registered in their `init()` functions and execute through the Cobra framework.

## Step-by-Step Guide

### Step 1: Create Command File

Create a new file in `cmd/wsh/cmd/` named `wshcmd-[commandname].go`:

```go
// Copyright 2025, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

package cmd

import (
    "fmt"

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

var myCommandCmd = &cobra.Command{
    Use:   "mycommand [args]",
    Short: "Brief description of what this command does",
    Long: `Detailed description of the command.
Can include multiple lines and examples of usage.`,
    RunE:                  myCommandRun,
    PreRunE:               preRunSetupRpcClient,  // Include if command needs RPC
    DisableFlagsInUseLine: true,
}

// Flag variables
var (
    myCommandFlagExample string
    myCommandFlagVerbose bool
)

func init() {
    // Add command to root
    rootCmd.AddCommand(myCommandCmd)
    
    // Define flags
    myCommandCmd.Flags().StringVarP(&myCommandFlagExample, "example", "e", "", "example flag description")
    myCommandCmd.Flags().BoolVarP(&myCommandFlagVerbose, "verbose", "v", false, "enable verbose output")
}

func myCommandRun(cmd *cobra.Command, args []string) (rtnErr error) {
    // Always track activity for telemetry
    defer func() {
        sendActivity("mycommand", rtnErr == nil)
    }()
    
    // Validate arguments
    if len(args) == 0 {
        OutputHelpMessage(cmd)
        return fmt.Errorf("requires at least one argument")
    }
    
    // Command implementation
    fmt.Printf("Command executed successfully\n")
    return nil
}
```

**File Naming Convention:**
- Use `wshcmd-[commandname].go` format
- Use lowercase, hyphenated names for multi-word commands
- Examples: `wshcmd-getvar.go`, `wshcmd-setmeta.go`, `wshcmd-ai.go`

### Step 2: Command Structure

#### Basic Command Structure

```go
var myCommandCmd = &cobra.Command{
    Use:   "mycommand [required] [optional...]",
    Short: "One-line description (shown in help)",
    Long:  `Detailed multi-line description`,
    
    // Argument validation
    Args:    cobra.MinimumNArgs(1),  // Or cobra.ExactArgs(1), cobra.NoArgs, etc.
    
    // Execution function
    RunE:    myCommandRun,
    
    // Pre-execution setup (if needed)
    PreRunE: preRunSetupRpcClient,  // Sets up RPC client for backend communication
    
    // Example usage (optional)
    Example: "  wsh mycommand foo\n  wsh mycommand --flag bar",
    
    // Disable flag notation in usage line
    DisableFlagsInUseLine: true,
}
```

**Key Fields:**
- `Use`: Command name and argument pattern
- `Short`: Brief description for command list
- `Long`: Detailed description shown in help
- `Args`: Argument validator (optional)
- `RunE`: Main execution function (returns error)
- `PreRunE`: Setup function that runs before `RunE`
- `Example`: Usage examples (optional)
- `DisableFlagsInUseLine`: Clean up help display

#### When to Use PreRunE

Include `PreRunE: preRunSetupRpcClient` if your command:
- Communicates with the Wave Terminal backend
- Needs access to `RpcClient` 
- Requires JWT authentication (WAVETERM_JWT env var)
- Makes RPC calls via `wshclient.*Command()` functions

**Don't include PreRunE** for commands that:
- Only manipulate local state
- Don't need backend communication
- Are purely informational/local operations

### Step 3: Implement Command Logic

#### Command Function Pattern

```go
func myCommandRun(cmd *cobra.Command, args []string) (rtnErr error) {
    // Step 1: Always track activity (for telemetry)
    defer func() {
        sendActivity("mycommand", rtnErr == nil)
    }()
    
    // Step 2: Validate arguments and flags
    if len(args) != 1 {
        OutputHelpMessage(cmd)
        return fmt.Errorf("requires exactly one argument")
    }
    
    // Step 3: Parse/prepare data
    targetArg := args[0]
    
    // Step 4: Make RPC call if needed
    result, err := wshclient.SomeCommand(RpcClient, wshrpc.CommandSomeData{
        Field: targetArg,
    }, &wshrpc.RpcOpts{Timeout: 2000})
    if err != nil {
        return fmt.Errorf("executing command: %w", err)
    }
    
    // Step 5: Output results
    fmt.Printf("Result: %s\n", result)
    return nil
}
```

**Important Patterns:**

1. **Activity Tracking**: Always include deferred `sendActivity()` call
   ```go
   defer func() {
       sendActivity("commandname", rtnErr == nil)
   }()
   ```

2. **Error Handling**: Return errors, don't call `os.Exit()`
   ```go
   if err != nil {
       return fmt.Errorf("context: %w", err)
   }
   ```

3. **Output**: Use standard `fmt` package for output
   ```go
   fmt.Printf("Success message\n")
   fmt.Fprintf(os.Stderr, "Error message\n")
   ```

4. **Help Messages**: Show help when arguments are invalid
   ```go
   if len(args) == 0 {
       OutputHelpMessage(cmd)
       return fmt.Errorf("requires arguments")
   }
   ```

5. **Exit Codes**: Set custom exit code via `WshExitCode`
   ```go
   if notFound {
       WshExitCode = 1
       return nil  // Don't return error, just set exit code
   }
   ```

### Step 4: Define Flags
03

Trust audit

SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeNA
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
none-observed
Network
none-observed
Shell
none-observed
Dependencies
pinned
Secrets in source
none-found

Findings (0)

No findings outside the package's declared scope.

Gates applied: no_behavioural_pass.

Audited 2026-10-03 · audit v0.4.1 · source sha 63907843412ffull audit observations/trust-audit/skill/wavetermdev__add-wshcmd.json · Report an issue / request a re-scan
04

Audit history

Every audit this skill has had.

DateSourceVerdictGradeScoreChange
2026-10-0363907843412fSAFEB89first audit
05

Questions

What does the Add Wshcmd skill do?

An open-source, AI-integrated, cross-platform terminal for seamless workflows

Is Add Wshcmd safe to install?

The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.

What can Add Wshcmd access on my machine?

The audit observed no filesystem, network or shell use at all in its source.

How current is this page?

The grade is for one exact copy of the source (63907843412f), read on 2026-10-03. The repository is watched, and a new audit runs when it changes — this is the first audit.

Advertisement