| name | executor-pattern |
| description | Use when writing code that shells out to external CLIs (k3d, kubectl, kustomize, tilt, helm). Shows the correct way to use the executor package, handle errors, parse output, and set timeouts. |
| allowed-tools | Read, Write, Edit, Grep |
Executor Pattern
Every CLI interaction in this project goes through internal/executor/executor.go. This skill shows the correct patterns.
Basic Usage
func handleKubectlGet(ctx context.Context, exec *executor.Executor, input KubectlGetInput) (*KubectlGetOutput, error) {
args := []string{"get", input.Resource, "-o", "json"}
if input.Name != nil {
args = append(args, *input.Name)
}
if input.Namespace != nil {
args = append(args, "-n", *input.Namespace)
}
if input.Selector != nil {
args = append(args, "-l", *input.Selector)
}
if input.AllNamespaces {
args = append(args, "-A")
}
result, err := exec.Run(ctx, "kubectl", args...)
if err != nil {
return nil, fmt.Errorf("kubectl_get: %w", err)
}
var output KubectlGetOutput
if err := json.Unmarshal(result.Stdout, &output.Resources); err != nil {
return nil, fmt.Errorf("kubectl_get: parse output: %w", err)
}
return &output, nil
}
Anti-Patterns (NEVER do these)
cmd := exec.Command("kubectl", "get", "pods")
cmd := exec.Command("sh", "-c", "kubectl get pods -n " + namespace)
result, err := exec.Run(context.Background(), "kubectl", args...)
result, _ := exec.Run(ctx, "kubectl", args...)
args := []string{"get", "pods"}
Timeout Override
ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
defer cancel()
result, err := exec.Run(ctx, "tilt", "ci", "--timeout", "300s")
Capturing Stderr
The executor captures both stdout and stderr. Use stderr for diagnostics when the command fails:
result, err := exec.Run(ctx, "kubectl", args...)
if err != nil {
return nil, fmt.Errorf("kubectl_apply: %s: %w", string(result.Stderr), err)
}