title: CloudSlash - Custom Plugins Reference description: A plugin is a compiled binary that implements one gRPC interface: 5 methods. The engine orchestrates; the plugin does the cloud work. Every plugin is a hashi...
Custom Plugins¶
A plugin is a compiled binary that implements one gRPC interface: 5 methods. The engine orchestrates; the plugin does the cloud work.
The Provider Contract¶
Every plugin is a hashicorp/go-plugin binary exposing the Provider gRPC service:
service Provider {
rpc Handshake(HandshakeRequest) returns (HandshakeResponse);
rpc Scan(ScanRequest) returns (stream ScanResponse);
rpc ApplyQuarantine(QuarantineRequest) returns (QuarantineResponse);
rpc CheckReversibility(ReversibilityRequest) returns (ReversibilityProof);
}
Plugins that support remediation also implement the Remediator extension:
The engine discovers plugin capabilities at startup via the gRPC handshake: a plugin that doesn't implement Remediate degrades gracefully to scan-only mode.
Scaffold¶
A Plugin in 30 Seconds
DEVI AI¶
Recommended
Open the Web Dashboard → DEVI chat panel and type:
"Create a plugin for Hetzner Cloud that scans servers, volumes, and floating IPs"
DEVI generates a complete, compilable main.go with the Provider contract pre-wired, saves it to ~/.cloudslash/plugins/src/cloudslash-plugin-hetzner/, and offers to build it.
Manual Scaffold¶
package main
import (
"context"
"fmt"
"os"
"github.com/hashicorp/go-plugin"
pb "github.com/DrSkyle/cloudslash/v2/pkg/engine/plugin/proto"
"github.com/DrSkyle/cloudslash/v2/pkg/engine/plugin/shared"
)
type HetznerProvider struct {
pb.UnimplementedProviderServer
pb.UnimplementedRemediatorServer
}
func (p *HetznerProvider) Handshake(_ context.Context, _ *pb.HandshakeRequest) (*pb.HandshakeResponse, error) {
return &pb.HandshakeResponse{
Compatible: true,
PluginVersion: "v0.1.0",
Message: "Hetzner Cloud Plugin Ready",
}, nil
}
func (p *HetznerProvider) Scan(req *pb.ScanRequest, stream pb.Provider_ScanServer) error {
// Use the Hetzner Cloud Go SDK to discover resources.
// For each resource, stream a pb.Node with:
// - Crn: "crn:devi:hetzner:<datacenter>:<project>:<type>/<id>"
// - Properties: JSON-encoded resource attributes
// - Cost: monthly cost in USD
return nil
}
func (p *HetznerProvider) Remediate(ctx context.Context, req *pb.RemediateRequest) (*pb.RemediateResponse, error) {
// Dispatch by resource type from CRN.
// Always create a snapshot before destructive operations.
return &pb.RemediateResponse{
Success: false,
Error: "not yet implemented",
}, nil
}
func main() {
if len(os.Args) > 1 && os.Args[1] == "version" {
fmt.Println("cloudslash-plugin-hetzner v0.1.0")
return
}
plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: shared.Handshake,
Plugins: map[string]plugin.Plugin{
"provider": &shared.ProviderPlugin{Impl: &HetznerProvider{}},
},
GRPCServer: plugin.DefaultGRPCServer,
})
}
The CRN Format¶
Every resource must be assigned a CloudSlash Resource Name (CRN):
Examples:
| Resource | CRN |
|---|---|
| AWS EC2 Instance | crn:devi:aws:us-east-1:123456789:ec2:instance:i-0abc123 |
| GCP Compute Instance | crn:devi:gcp:us-central1-a:my-project:compute:instance:vm-001 |
| Hetzner Server | crn:devi:hetzner:fsn1:12345:server:67890 |
| Carbon Footprint | crn:devi:carbon:us-east-1:org:estimate:monthly-2026-05 |
Remediate¶
Implementing
The Remediate RPC is called by the engine after s.a.u approval. Your plugin receives:
type RemediateRequest struct {
Crn string // The resource to act on
Action string // "stop", "delete", "throttle", "pause", etc.
Properties map[string]string // Additional context (region, credentials, etc.)
DryRun bool // If true, validate but don't execute
}
Rules:
- Always snapshot before destructive operations. Return the snapshot ID in the response so s.a.u can rollback.
- Support
dry_run. Ifreq.DryRunis true, validate permissions and return success without executing. - Return structured errors. Never panic: return
RemediateResponse{Success: false, Error: "..."}.
type RemediateResponse struct {
Success bool
Status string // "stopped", "deleted", "throttled", etc.
Error string // Empty on success
Snapshot map[string]string // Snapshot IDs for rollback
}
Compilation and Registration¶
# Build the plugin binary
cd ~/.cloudslash/plugins/src/cloudslash-plugin-hetzner/
go build -o ~/.cloudslash/plugins/cloudslash-plugin-hetzner .
# Hot-reload into the running daemon
kill -HUP $(pgrep cloudslash)
Or use the DEVI chat in the Web Dashboard:
"Build the hetzner plugin"
Non-Cloud Use Cases¶
The engine operates on a generic graph: nodes with properties and edges with relationships. Nothing in the protocol is cloud-specific. Community plugins can target:
| Use Case | Plugin Name | What It Scans |
|---|---|---|
| Carbon Footprint | cloudslash-plugin-carbon |
COâ‚‚ estimates per compute region |
| SaaS License Audit | cloudslash-plugin-okta |
Unused Okta seats and SSO configs |
| Database Optimization | cloudslash-plugin-postgres |
Bloated tables, unused indexes |
| Network Security | cloudslash-plugin-nmap |
Open ports and attack surface |
| Cost Attribution | cloudslash-plugin-finops |
Cross-cloud cost allocation tags |
The engine applies the same policy mesh, saga orchestration, and CRDT state resolution regardless of what domain the nodes represent.