# How to Extend ChaosBlade with Custom Matchers and Flags: A Complete Guide

> Extend ChaosBlade with custom matchers and flags dynamically without recompiling. Learn how to edit YAML specs for a complete guide. Accelerate your chaos engineering.

- Repository: [ChaosBlade/chaosblade](https://github.com/chaosblade-io/chaosblade)
- Tags: how-to-guide
- Published: 2026-02-27

---

**You can extend ChaosBlade with custom matchers and flags by editing YAML specification files in `$HOME/.chaosblade/spec` without recompiling the binary, as the CLI dynamically builds its command tree from these specs at runtime.**

ChaosBlade is an open-source chaos engineering platform that uses a specification-driven architecture to define experiments. Understanding how to extend ChaosBlade with custom matchers and flags allows you to tailor resource selection and experiment parameters to your specific infrastructure needs without modifying the core Go source code.

## Understanding ChaosBlade's Specification-Driven Architecture

ChaosBlade constructs its entire command-line interface from YAML specification files that describe experiments, actions, flags, and matchers. When the CLI initializes, it loads these specifications and dynamically registers commands using Cobra.

### How the CLI Builds Commands from YAML

The entry point for command registration occurs in [`cli/cmd/exp.go`](https://github.com/chaosblade-io/chaosblade/blob/main/cli/cmd/exp.go). The process follows three distinct phases:

1. **Specification Loading**: The system loads YAML files from the directory returned by `specutil.GetYamlHome()` (default: `$HOME/.chaosblade/spec`):

```go
models, err := specutil.ParseSpecsToModel(file, os.NewExecutor())
// cli/cmd/exp.go: 38-42

```

2. **Command Registration**: For each experiment model, the system registers a top-level command:

```go
command := ec.registerExpCommand(model, "")
// cli/cmd/exp.go: 48-55

```

3. **Flag Binding**: The system binds both action flags and matcher flags to the command:

```go
// bind matcher flags
ec.bindFlagsFunc(command.MatcherFlags, command.command, actionCommandSpec.Matchers())
// cli/cmd/exp.go: 400-402

```

### The Role of Matchers and Flags

In ChaosBlade's architecture, **matchers** function as specialized flags used for resource selection (such as `--process` or `--container`), while **flags** define experiment parameters (such as `--time` or `--duration`). Both follow the same `ExpFlagSpec` schema defined in the `chaosblade-spec-go` library, but matchers are processed separately to facilitate resource targeting.

## Adding Custom Matchers to ChaosBlade Experiments

Extending ChaosBlade with custom matchers requires creating or modifying YAML specification files. This approach requires no recompilation of the binary.

### Creating or Editing YAML Specification Files

Create a new YAML file or edit an existing spec in `$HOME/.chaosblade/spec/`. The filename typically follows the pattern `chaosblade-<target>-spec-<version>.yaml`.

For example, to add a custom matcher for process selection:

```yaml

# $HOME/.chaosblade/spec/chaosblade-os-spec-1.9.0.yaml

- name: process
  scope: host
  actions:
    - name: kill
      flags:
        - name: signal
          desc: signal to send (default: SIGKILL)
      matchers:
        - name: process
          desc: name of the process to kill
          required: true
        - name: mylabel
          desc: custom label matcher for process selection
          required: false

```

### Defining Matcher Properties

Matchers support the same properties as standard flags:

- **name**: The flag name used on the CLI (e.g., `--mylabel`)
- **desc**: Description shown in help text
- **required**: Boolean indicating if the matcher must be provided
- **default**: Optional default value

### Using Custom Matchers in Commands

After saving the YAML file, the CLI automatically discovers the new matcher. Execute the experiment using your custom matcher:

```bash
cb create process kill --mylabel myapp-tier --signal SIGTERM

```

The matcher value is passed to the executor via `expModel.ActionFlags["mylabel"]`, as implemented in [`exec/os/executor.go`](https://github.com/chaosblade-io/chaosblade/blob/main/exec/os/executor.go) at line 313 within the `convertFlagsToResourceFlags` function.

## Implementing Custom Flags for Experiment Actions

Custom flags follow the same YAML-based approach as matchers but are declared under the `flags` section rather than `matchers`.

### Declaring Action-Level Flags

Add flags to any action in your YAML specification:

```yaml
- name: network
  scope: host
  actions:
    - name: delay
      flags:
        - name: time
          desc: delay time in ms
          required: true
        - name: duration
          desc: how long the delay lasts (seconds)
          required: false
        - name: jitter
          desc: network jitter in ms
          required: false

```

These flags become standard Cobra command-line flags accessible via `--time`, `--duration`, and `--jitter`.

### Accessing Flag Values in Executors

When the experiment executes, flag values are available in the `ExpModel` structure:

```go
// Inside your executor implementation
func (e *executor) Exec(expModel *spec.ExpModel) (*spec.Response, error) {
    delayTime := expModel.ActionFlags["time"]
    duration := expModel.ActionFlags["duration"]
    
    // Implementation logic using these values
}

```

## Advanced: Creating Custom Executors for Complex Matchers

When custom matchers require specialized processing logic beyond standard resource selection, implement a custom `spec.Executor`.

### Implementing the spec.Executor Interface

Create a new executor struct that implements the interface defined in the `chaosblade-spec-go` library:

```go
package myexecutor

import (
    "github.com/chaosblade-io/chaosblade-spec-go/spec"
)

type customExecutor struct{}

// Exec implements spec.Executor
func (e *customExecutor) Exec(expModel *spec.ExpModel) (*spec.Response, error) {
    // Retrieve custom matcher values
    customMatcher := expModel.ActionFlags["mylabel"]
    
    // Implement custom resource selection logic
    // Return spec.Response with success or failure details
    return spec.Success(), nil
}

// SetChannel implements spec.Executor (required for some implementations)
func (e *customExecutor) SetChannel(channel spec.Channel) {}

```

### Registering Your Executor

Register the executor in the appropriate `register*ExpCommands` function within [`cli/cmd/exp.go`](https://github.com/chaosblade-io/chaosblade/blob/main/cli/cmd/exp.go):

```go
// In your command registration logic
executors[createExecutorKey("mytarget", "host", "myaction")] = &myexecutor.customExecutor{}

```

This registration pattern follows the existing implementation at line 69 of [`cli/cmd/exp.go`](https://github.com/chaosblade-io/chaosblade/blob/main/cli/cmd/exp.go) where executors are mapped to specific target-scope-action combinations.

## Key Source Files and Implementation Details

Understanding these specific source files helps when debugging or extending ChaosBlade:

| File | Purpose | Key Lines |
|------|---------|-----------|
| [`cli/cmd/exp.go`](https://github.com/chaosblade-io/chaosblade/blob/main/cli/cmd/exp.go) | Core command registration and flag binding | 38-42 (spec loading), 48-55 (command registration), 400-402 (matcher binding) |
| [`cli/cmd/check_os.go`](https://github.com/chaosblade-io/chaosblade/blob/main/cli/cmd/check_os.go) | Demonstrates matcher and flag merging logic | `mergeMatchesAndFlags` function |
| [`exec/os/executor.go`](https://github.com/chaosblade-io/chaosblade/blob/main/exec/os/executor.go) | Consumes matcher values during execution | 313 (`convertFlagsToResourceFlags`) |
| [`build/spec/spec.go`](https://github.com/chaosblade-io/chaosblade/blob/main/build/spec/spec.go) | Programmatic spec generation | 168-172 (ActionMatchers field) |
| [`spec/util/parse.go`](https://github.com/chaosblade-io/chaosblade/blob/main/spec/util/parse.go) | YAML parsing into Go structs | External library: `chaosblade-spec-go` |
| [`spec/exp_flag.go`](https://github.com/chaosblade-io/chaosblade/blob/main/spec/exp_flag.go) | Flag and matcher schema definition | External library: `chaosblade-spec-go` |

## Summary

- **ChaosBlade uses YAML specifications** located in `$HOME/.chaosblade/spec` to dynamically build its CLI, eliminating the need for recompilation when adding matchers or flags.
- **Custom matchers** are defined under the `matchers:` section in action specifications and function as specialized resource selectors passed to executors via `expModel.ActionFlags`.
- **Custom flags** follow the same YAML schema as matchers but reside under `flags:` and define experiment parameters rather than resource selection criteria.
- **Implementation details** center on [`cli/cmd/exp.go`](https://github.com/chaosblade-io/chaosblade/blob/main/cli/cmd/exp.go) for command registration (lines 400-402 for matcher binding) and [`exec/os/executor.go`](https://github.com/chaosblade-io/chaosblade/blob/main/exec/os/executor.go) for flag consumption at runtime.
- **Advanced extensions** require implementing the `spec.Executor` interface and registering the executor in the command initialization map for custom processing logic.

## Frequently Asked Questions

### Do I need to recompile ChaosBlade to add custom matchers?

No, you do not need to recompile the binary. ChaosBlade loads experiment specifications from YAML files in `$HOME/.chaosblade/spec` at runtime. Simply create or edit a spec file, add your matcher under the `matchers:` section of the desired action, and the CLI will automatically expose it as a new flag.

### What is the difference between a matcher and a flag in ChaosBlade?

While both use the same underlying `ExpFlagSpec` schema, **matchers** are specialized flags used for resource selection (such as `--process` or `--container`) and are processed separately to identify target resources. **Flags** define experiment parameters (such as `--duration` or `--time`) that control how the action behaves. Matchers are defined under `matchers:` in the YAML, while flags are defined under `flags:`.

### How do I access custom matcher values in my experiment executor?

Custom matcher values are accessible via the `ActionFlags` map in the `ExpModel` struct passed to your executor's `Exec` method. For example, if you defined a matcher named `mylabel`, you retrieve it in Go code using `expModel.ActionFlags["mylabel"]`. The executor at [`exec/os/executor.go`](https://github.com/chaosblade-io/chaosblade/blob/main/exec/os/executor.go) demonstrates this pattern in the `convertFlagsToResourceFlags` function around line 313.

### Can I add custom matchers to existing ChaosBlade experiments like network or CPU?

Yes, you can extend existing experiments by modifying their specification files. Locate the YAML spec for the target (such as [`chaosblade-os-spec.yaml`](https://github.com/chaosblade-io/chaosblade/blob/main/chaosblade-os-spec.yaml) for OS-level experiments), find the action you want to extend (like `delay` for network or `fullload` for CPU), and add your custom matcher under the `matchers:` section. The ChaosBlade CLI will automatically merge your custom matcher with the existing command structure when it parses the specification on startup.