Skip to content
Back to skills

2521 Plugin System 66a19e0d

ASecurity

ZERG supports plugins for extending quality gates, reacting to lifecycle events, and adding custom worker launcher backends. Plugins are additive only -- they observe and extend, but cannot mutate orchestrator state. Plugin failures are isolated and never crash the orchestrator. For the full API reference, see [[Plugin API Reference]]. For configuration options, see [[Configuration]]. ---

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
devopspythonshellreactkubernetesapibackendsecurityperformance

Works with

  • claude code
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2521-plugin-system_66a19e0d --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2521 Plugin System 66a19e0d?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2521 Plugin System 66a19e0d
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2521-plugin-system-66a19e0d/badge)](https://www.skillsdirectory.com/skills/tools-only-2521-plugin-system-66a19e0d)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Plugin System

ZERG supports plugins for extending quality gates, reacting to lifecycle events, and adding custom worker launcher backends. Plugins are additive only -- they observe and extend, but cannot mutate orchestrator state. Plugin failures are isolated and never crash the orchestrator.

For the full API reference, see [[Plugin API Reference]]. For configuration options, see [[Configuration]].

---

## Plugin Types

ZERG provides four plugin extension points:

| Plugin Type | Purpose | Blocks Execution | Example Use Case |
|-------------|---------|:-----------------:|------------------|
| Quality Gate | Validate code after merges | Yes (if `required`) | Security scan, complexity check, license audit |
| Lifecycle Hook | React to ZERG events | No | Slack notifications, metrics reporting, audit logs |
| Launcher | Custom worker environments | No | Kubernetes pods, SSH clusters, cloud VMs |
| Context | Custom context injection | No | Project-specific context, custom summarization |

---

## Quality Gate Plugins

Quality gates validate code after each level merge. They run sequentially after the built-in gates defined in `quality_gates` of the config.

### YAML Configuration (Simple)

For gates that are shell commands, define them directly in `.zerg/config.yaml`:

```yaml
plugins:
  quality_gates:
    - name: security-scan
      command: bandit -r src/ --severity medium
      required: false
      timeout: 300

    - name: complexity-check
      command: radon cc src/ --min B
      required: true
      timeout: 120

    - name: license-audit
      command: pip-licenses --fail-on "GPL-3.0"
      required: false
      timeout: 60
```

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `name` | string | required | Unique gate identifier |
| `command` | string | required | Shell command to execute |
| `required` | bool | `false` | If true, failure blocks the merge |
| `timeout` | int | `300` | Max seconds before timeout (1-3600) |

### Python Plugin (Advanced)

For gates that need custom logic, API calls, or multi-step validation, implement the `QualityGatePlugin` abstract base class. See [[Plugin API Reference]] for the full class definition.

```python
from zerg.plugins import QualityGatePlugin, GateContext
from zerg.types import GateRunResult
from zerg.constants import GateResult

class PerformanceBenchmark(QualityGatePlugin):
    @property
    def name(self) -> str:
        return "perf-benchmark"

    def run(self, ctx: GateContext) -> GateRunResult:
        # Run benchmark and compare against baseline
        # ...
        return GateRunResult(
            gate_name=self.name,
            result=GateResult.PASS,
            command="bench --compare baseline",
            exit_code=0,
            stdout="All benchmarks within threshold",
            stderr="",
        )
```

### Execution Order

```
Built-in gates (from quality_gates config)
  lint -> typecheck -> test -> coverage -> security
        |
        v
Plugin gates (from plugins.quality_gates config)
  security-scan -> complexity-check -> license-audit
        |
        v
Python plugin gates (from entry points)
  perf-benchmark -> ...
        |
        v
Merge completes (if all required gates passed)
```

---

## Lifecycle Hook Plugins

Hooks observe events during the ZERG lifecycle without blocking execution. They are useful for notifications, logging, and metrics collection.

### Available Events

| Event Type | Emitted When | Data Payload |
|------------|-------------|--------------|
| `task_started` | Worker begins task execution | `task_id`, `worker_id`, `level` |
| `task_completed` | Task verification passes | `task_id`, `worker_id`, `duration`, `output` |
| `level_complete` | All tasks in a level finish | `level`, `task_count`, `elapsed_time` |
| `merge_complete` | Level branches merged | `level`, `branch_count`, `conflicts` |
| `worker_spawned` | New worker process starts | `worker_id`, `port`, `mode` |
| `quality_gate_run` | Quality gate executes | `gate_name`, `result`, `level` |
| `rush_started` | `/zerg:rush` begins | `feature`, `workers`, `config` |
| `rush_finished` | All levels complete | `feature`, `total_time`, `tasks_completed` |

### YAML Configuration (Simple)

For hooks that execute shell commands:

```yaml
plugins:
  hooks:
    - event: task_completed
      command: echo "Task {task_id} completed at $(date)"
      timeout: 60

    - event: level_complete
      command: ./scripts/notify-slack.sh "Level {level} done"
      timeout: 120

    - event: merge_complete
      command: |
        python scripts/generate_report.py \
          --level {level} \
          --feature {feature}
      timeout: 180

    - event: rush_finished
      command: ./scripts/send-summary.sh "{feature}" "{total_time}"
      timeout: 60
```

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `event` | string | required | Event type from the table above |
| `command` | string | required | Shell command (parsed with `shlex.split`, no shell=True) |
| `timeout` | int | `60` | Max seconds before timeout (1-600) |

**Variable substitution.** Curly-brace placeholders like `{level}`, `{feature}`, `{task_id}`, and `{worker_id}` are replaced with values from the event data payload.

### Python Plugin (Advanced)

For hooks with custom logic, implement the `LifecycleHookPlugin` abstract base class:

```python
from zerg.plugins import LifecycleHookPlugin, LifecycleEvent

class SlackNotifier(LifecycleHookPlugin):
    @property
    def name(self) -> str:
        return "slack-notifier"

    def on_event(self, event: LifecycleEvent) -> None:
        if event.event_type == "rush_finished":
            send_slack_message(
                f"Feature {event.data['feature']} built in "
                f"{event.data['total_time']}s"
            )
```

### Safety Guarantees

- Hooks never block orchestrator execution.
- Each hook invocation is wrapped in its own try/except.
- One failing hook does not prevent other hooks from running.
- Hooks have no access to mutable orchestrator state.

---

## Launcher Plugins

Launcher plugins add custom worker execution environments beyond the built-in `subprocess` and `container` modes.

### YAML Configuration

```yaml
plugins:
  launchers:
    - name: kubernetes
      entry_point: my_pkg.launchers:K8sLauncher
```

| Field | Type | Description |
|-------|------|-------------|
| `name` | string | Launcher name referenced in `workers.launcher_type` |
| `entry_point` | string | Python entry point in `module:Class` format |

After registering a launcher plugin, use it by setting:

```yaml
workers:
  launcher_type: kubernetes
```

### Python Plugin (Advanced)

```python
from zerg.plugins import LauncherPlugin

class K8sLauncherPlugin(LauncherPlugin):
    @property
    def name(self) -> str:
        return "kubernetes"

    def create_launcher(self, config):
        return K8sWorkerLauncher(config)
```

The returned object must implement the `WorkerLauncher` abstract base class with `launch()`, `wait()`, and `cleanup()` methods. See [[Plugin API Reference]] for details.

---

## Context Plugins

Context plugins customize the context injected into worker prompts. The built-in `ContextEngineeringPlugin` handles security rule filtering and spec excerpts. Custom context plugins can add project-specific context.

See [[Context Engineering]] for the built-in plugin and [[Plugin API Reference]] for the abstract base class.

---

## Plugin Registration

Plugins are discovered and registered through three mechanisms, in order of priority:

### 1. YAML Configuration

The simplest approach. Define hooks and gates directly in `.zerg/config.yaml`. Suitable for shell commands and simple automation.

### 2. Python Entry Points

For installable plugins distributed as Python packages. Register plugins via `pyproject.toml`:

```toml
[project.entry-points."zerg.plugins"]
my-gate = "my_package.gates:MyGatePlugin"
my-hook = "my_package.hooks:MyHookPlugin"
my-launcher = "my_package.launchers:MyLauncherPlugin"
```

ZERG discovers entry points in the `zerg.plugins` group at startup and registers them based on which abstract base class they implement.

### 3. Direct Registration

For programmatic use, register plugins directly with the `PluginRegistry`:

```python
from zerg.plugins import PluginRegistry

registry = PluginRegistry()
registry.register_gate(MyGatePlugin(), required=True)
registry.register_hook("task_completed", my_callback)
registry.register_launcher(MyLauncherPlugin())
```

---

## Task System Integration

All plugin operations integrate with the Claude Code Task system per ZERG conventions.

| Operation | Task Subject |
|-----------|-------------|
| Plugin registration | `[Plugins] Register {name}` |
| Quality gate execution | `[Gate] Run {gate_name}` |
| Lifecycle hook invocation | `[Hook] Process {event_type}` |
| Custom launcher execution | `[Launcher] Spawn {worker_id}` |

Plugin state is tracked in both the Task system (authoritative) and `.zerg/state/plugins.json` (supplementary). If they disagree, the Task system wins.

---

## See Also

- [[Plugin API Reference]] -- Full class definitions and method signatures
- [[Configuration]] -- All configuration options
- [[Context Engineering]] -- Built-in context engineering plugin

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…