Skip to content
cccskills
FreePublished on GitHub

add-config

Guide for adding new configuration settings to Wave Terminal. Use when adding a new setting to the configuration system, implementing a new config key, or adding user-customizable settings.

The English summary is being prepared. Showing the original description.

See how to install

Files included (1)

  • SKILL.md14.0 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Adding a New Configuration Setting to Wave Terminal

This guide explains how to add a new configuration setting to Wave Terminal's hierarchical configuration system.

Configuration System Overview

Wave Terminal uses a hierarchical configuration system with:

  1. Go Struct Definitions - Type-safe configuration structure in pkg/wconfig/settingsconfig.go
  2. JSON Schema - Auto-generated validation schema in schema/settings.json
  3. Default Values - Built-in defaults in pkg/wconfig/defaultconfig/settings.json
  4. User Configuration - User overrides in ~/.config/waveterm/settings.json
  5. Block Metadata - Block-level overrides in pkg/waveobj/wtypemeta.go
  6. Documentation - User-facing docs in docs/docs/config.mdx

Settings cascade from defaults → user settings → connection config → block overrides.

Step-by-Step Guide

Step 1: Add to Go Struct Definition

Edit pkg/wconfig/settingsconfig.go and add your new field to the SettingsType struct:

type SettingsType struct {
    // ... existing fields ...

    // Add your new field with appropriate JSON tag
    MyNewSetting string `json:"mynew:setting,omitempty"`

    // For different types:
    MyBoolSetting   bool    `json:"mynew:boolsetting,omitempty"`
    MyNumberSetting float64 `json:"mynew:numbersetting,omitempty"`
    MyIntSetting    *int64  `json:"mynew:intsetting,omitempty"`    // Use pointer for optional ints
    MyArraySetting  []string `json:"mynew:arraysetting,omitempty"`
}

Naming Conventions:

  • Use namespace prefixes (e.g., term:, window:, ai:, web:, app:)
  • Use lowercase with colons as separators
  • Field names should be descriptive and follow Go naming conventions
  • Use omitempty tag to exclude empty values from JSON

Type Guidelines:

  • Use *int64 and *float64 for optional numeric values
  • Use *bool for optional boolean values (or bool if default is false)
  • Use string for text values
  • Use []string for arrays
  • Use float64 for numbers that can be decimals

Namespace Organization:

  • app:* - Application-level settings
  • term:* - Terminal-specific settings
  • window:* - Window and UI settings
  • ai:* - AI-related settings
  • web:* - Web browser settings
  • editor:* - Code editor settings
  • conn:* - Connection settings

Step 1.5: Add to Block Metadata (Optional)

If your setting should support block-level overrides, also add it to pkg/waveobj/wtypemeta.go:

type MetaTSType struct {
    // ... existing fields ...

    // Add your new field with matching JSON tag and type
    MyNewSetting *string `json:"mynew:setting,omitempty"`  // Use pointer for optional values

    // For different types:
    MyBoolSetting   *bool    `json:"mynew:boolsetting,omitempty"`
    MyNumberSetting *float64 `json:"mynew:numbersetting,omitempty"`
    MyIntSetting    *int     `json:"mynew:intsetting,omitempty"`
    MyArraySetting  []string `json:"mynew:arraysetting,omitempty"`
}

Block Metadata Guidelines:

  • Use pointer types (*string, *bool, *int, *float64) for optional overrides
  • JSON tags should exactly match the corresponding settings field
  • This enables the hierarchical config system: block metadata → connection config → global settings
  • Only add settings here that make sense to override per-block or per-connection

Step 2: Set Default Value (Optional)

If your setting should have a default value, add it to pkg/wconfig/defaultconfig/settings.json:

{
  "ai:preset": "ai@global",
  "ai:model": "gpt-5-mini",
  // ... existing defaults ...

  "mynew:setting": "default value",
  "mynew:boolsetting": true,
  "mynew:numbersetting": 42.5,
  "mynew:intsetting": 100
}

Default Value Guidelines:

  • Only add defaults for settings that should have non-zero/non-empty initial values
  • Ensure defaults make sense for typical user experience
  • Keep defaults conservative and safe
  • Boolean settings often don't need defaults if false is the correct default

Step 3: Update Documentation

Add your new setting to the configuration table in docs/docs/config.mdx:

| Key Name            | Type     | Function                                  |
| ------------------- | -------- | ----------------------------------------- |
| mynew:setting       | string   | Description of what this setting controls |
| mynew:boolsetting   | bool     | Enable/disable some feature               |
| mynew:numbersetting | float    | Numeric setting for some parameter        |
| mynew:intsetting    | int      | Integer setting for some configuration    |
| mynew:arraysetting  | string[] | Array of strings for multiple values      |

Documentation Guidelines:

  • Provide clear, concise descriptions
  • For new settings in upcoming releases, add <VersionBadge version="v0.14" />
  • Update the default configuration example if you added defaults
  • Explain what values are valid and what they do

Step 4: Regenerate Schema and TypeScript Types

Run the generate task to automatically regenerate the JSON schema and TypeScript types:

task generate

What this does:

  • Runs task build:schema (automatically generates JSON schema from Go structs)
  • Generates TypeScript type definitions in frontend/types/gotypes.d.ts
  • Generates RPC client APIs
  • Generates metadata constants

Important: The JSON schema in schema/settings.json is automatically generated from the Go struct definitions - you don't need to edit it manually.

Step 5: Use in Frontend Code

Access your new setting in React components:

import { getOverrideConfigAtom, getSettingsKeyAtom, useAtomValue } from "@/store/global";

// In a React component
const MyComponent = ({ blockId }: { blockId: string }) => {
    // Use override config atom for hierarchical resolution
    // This automatically checks: block metadata → connection config → global settings → default
    const mySettingAtom = getOverrideConfigAtom(blockId, "mynew:setting");
    const mySetting = useAtomValue(mySettingAtom) ?? "fallback value";

    // For global-only settings (no block overrides)
    const globalOnlySetting = useAtomValue(getSettingsKeyAtom("mynew:globalsetting")) ?? "fallback";

    return <div>Setting value: {mySetting}</div>;
};

Frontend Configuration Patterns:

// 1. Settings with block-level overrides (recommended for most view/display settings)
const termFontSize = useAtomValue(getOverrideConfigAtom(blockId, "term:fontsize")) ?? 12;

// 2. Global-only settings (app-wide settings that don't vary by block)
const appGlobalHotkey = useAtomValue(getSettingsKeyAtom("app:globalhotkey")) ?? "";

// 3. Connection-specific settings
const connStatus = useAtomValue(getConnStatusAtom(connectionName));

When to use each pattern:

  • Use getOverrideConfigAtom() for settings that can vary by block or connection (most UI/display settings)
  • Use getSettingsKeyAtom() for app-level settings that are always global
  • Always provide a fallback value with ?? operator

Step 6: Use in Backend Code

Access settings in Go code:

// Get the full config
fullConfig := wconfig.GetWatcher().GetFullConfig()

// Access your setting
myValue := fullConfig.Settings.MyNewSetting

// For optional values (pointers)
if fullConfig.Settings.MyIntSetting != nil {
    intValue := *fullConfig.Settings.MyIntSetting
    // Use intValue
}

Complete Examples

Example 1: Simple Boolean Setting (No Block Override)

Use case: Add a setting to hide the AI button globally

1. Go Struct (pkg/wconfig/settingsconfig.go)

type SettingsType struct {
    // ... existing fields ...
    AppHideAiButton bool `json:"app:hideaibutton,omitempty"`
}

2. Default Value (pkg/wconfig/defaultconfig/settings.json)

{
  "app:hideaibutton": false
}

3. Documentation (docs/docs/config.mdx)

| app:hideaibutton <VersionBadge version="v0.14" /> | bool | Hide the AI button in the tab bar (defaults to false) |

4. Generate Types

task generate

5. Frontend Usage

import { getSettingsKeyAtom } from "@/store/global";

const TabBar = () => {
    const hideAiButton = useAtomValue(getSettingsKeyAtom("app:hideaibutton"));

    if (hideAiButton) {
        return null; // Don't render AI button
    }

    return <button>AI</button>;
};

6. Usage Examples

# Set in settings file
wsh setconfig app:hideaibutton=true

# Or edit ~/.config/waveterm/settings.json
{
  "app:hideaibutton": true
}

Example 2: Terminal Setting with Block Override

Use case: Add a terminal bell sound setting that can be overridden per block

1. Go Struct (pkg/wconfig/settingsconfig.go)

type SettingsType struct {
    // ... existing fields ...
    TermBellSound string `json:"term:bellsound,omitempty"`
}

2. Block Metadata (pkg/waveobj/wtypemeta.go)

type MetaTSType struct {
    // ... existing fields ...
    TermBellSound *string `json:"term:bellsound,omitempty"`  // Pointer for optional override
}

3. Default Value (pkg/wconfig/defaultconfig/settings.json)

{
  "term:bellsound": "default"
}

4. Documentation (docs/docs/config.mdx)

| term:bellsound <VersionBadge version="v0.14" /> | string | Sound to play for terminal bell ("default", "none", or custom sound file path) |

5. Generate Types

task generate

6. Frontend Usage

import { getOverrideConfigAtom } from "@/store/global";

const TerminalView = ({ blockId }: { blockId: string }) => {
    // Use override config for hierarchical resolution
    const bellSoundAtom = getOverrideConfigAtom(blockId, "term:bellsound");
    const bellSound = useAtomValue(bellSoundAtom) ?? "default";

    const playBellSound = () => {
        if (bellSound === "none") return;
        // Play the bell sound
    };

    return <div>Terminal with bell: {bellSound}</div>;
};

7. Usage Examples

# Set globally in settings file
wsh setconfig term:bellsound="custom.wav"

# Set for current block only
wsh setmeta term:bellsound="none"

# Set for specific block
wsh setmeta --block BLOCK_ID term:bellsound="beep"

# Or edit ~/.config/waveterm/settings.json
{
  "term:bellsound": "custom.wav"
}

Configuration Patterns

Clear/Reset Pattern

Each namespace can have a "clear" field for resetting all settings in that namespace:

AppClear  bool `json:"app:*,omitempty"`
TermClear bool `json:"term:*,omitempty"`

Optional vs Required Settings

  • Use pointer types (*bool, *int64, *float64) for truly optional settings
  • Use regular types for settings that should always have a value
  • Provide sensible defaults for important settings

Block-Level Overrides via RPC

Settings can be overridden at the block level using metadata:

import { RpcApi } from "@/app/store/wshclientapi";
import { TabRpcClient } from "@/app/store/wshrpcutil";
import { WOS } from "@/store/global";

// Set block-specific override
await RpcApi.SetMetaCommand(TabRpcClient, {
  oref: WOS.makeORef("block", blockId),
  meta: { "mynew:setting": "block-specific value" },
});

Common Pitfalls

1. Forgetting to Run task generate

Problem: TypeScript types not updated, schema out of sync

Solution: Always run task generate after modifying Go structs

2. Type Mismatch Between Settings and Metadata

Problem: Settings uses string, metadata uses *int

Solution: Ensure types match (except metadata uses pointers for optionals)

3. Not Providing Fallback Values

Problem: Component breaks if setting is undefined

Solution: Always use ?? operator with fallback:

const value = useAtomValue(getSettingsKeyAtom("key")) ?? "default";

4. Using Wrong Config Atom

Problem: Using getSettingsKeyAtom() for settings that need block overrides

Solution: Use getOverrideConfigAtom() for any setting in MetaTSType

Best Practices

Naming

  • Use descriptive names: term:fontsize not term:fs
  • Follow namespace conventions: Group related settings with common prefix
  • Use consistent casing: Always lowercase with colons

Types

  • Use bool for simple on/off settings (no pointer if false is default)
  • Use *bool only if you need to distinguish unset from false
  • Use *int64/*float64 for optional numeric values
  • Use string for text, paths, or enum-like values
  • Use []string for lists

Defaults

  • Provide sensible defaults for settings users will commonly change
  • Omit defaults for advanced/optional settings
  • Keep defaults safe - don't enable experimental features by default
  • Document defaults clearly in config.mdx

Block Overrides

  • Enable for view/display settings: Font sizes, colors, themes, etc.
  • Don't enable for app-wide settings: Global hotkeys, window behavior, etc.
  • Consider the use case: Would a user want different values per block or connection?

Documentation

  • Be specific: Explain what the setting does and what values are valid
  • Provide examples: Show common use cases
  • Add version badges: Mark new settings with <VersionBadge version="v0.x" />
  • Keep it current: Update docs when behavior changes

Quick Reference

When adding a new configuration setting:

  • Add field to SettingsType in pkg/wconfig/settingsconfig.go
  • Add field to MetaTSType in pkg/waveobj/wtypemeta.go (if block override needed)
  • Add default to pkg/wconfig/defaultconfig/settings.json (if needed)
  • Document in docs/docs/config.mdx
  • Run task generate to update TypeScript types
  • Use appropriate atom (getOverrideConfigAtom or getSettingsKeyAtom) in frontend

Related Documentation

  • User Documentation: docs/docs/config.mdx - User-facing configuration docs
  • Type Definitions: pkg/wconfig/settingsconfig.go - Go struct definitions
  • Metadata Types: pkg/waveobj/wtypemeta.go - Block metadata definitions

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Guide for adding new RPC calls to Wave Terminal. Use when implementing new RPC commands, adding server-client communication methods, or extending the RPC interface with new functionality.

The English summary is being prepared. Showing the original description.

mits-pl/wove42Updated Jun 20, 2026

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.

The English summary is being prepared. Showing the original description.

mits-pl/wove42Updated Jun 20, 2026

Guide for creating and displaying context menus in Wave Terminal. Use when implementing right-click menus, adding context menu items, creating submenus, or handling menu interactions with checkboxes and separators.

The English summary is being prepared. Showing the original description.

mits-pl/wove42Updated Jun 20, 2026

Guide for implementing a new view type in Wave Terminal. Use when creating a new view component, implementing the ViewModel interface, registering a new view type in BlockRegistry, or adding a new content type to display within blocks.

The English summary is being prepared. Showing the original description.

mits-pl/wove42Updated Jun 20, 2026

Guide for adding new Electron APIs to Wave Terminal. Use when implementing new frontend-to-electron communications via preload/IPC.

The English summary is being prepared. Showing the original description.

mits-pl/wove42Updated Jun 20, 2026

Search and order products online. Compares prices across Polish marketplaces (Allegro, Ceneo, Google Shopping), presents options in a comparison table, and assists with checkout. Handles the full flow: priority selection, research, comparison, cart, and checkout handoff. Triggers on: "order", "buy", "find product", "compare prices", "cheapest", "zamow", "kup", "znajdz produkt", "porownaj ceny", "najtaniej".

The English summary is being prepared. Showing the original description.

mits-pl/wove42Updated Jun 20, 2026

See all skills by mits-pl

Report a problem with this skill