agentsclimarketplace

Finfocus plugin

Skill rshade/finfocus/.claude/skills/finfocus-plugin/finfocus-plugin

FinOps CLI for Pulumi — projected costs, actual spend tracking, budget enforcement, and cost optimization for cloud infrastructure

Install
npx -y skills add rshade/finfocus --skill finfocus-plugin

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Guide for building FinFocus cost plugins using the pluginsdk and gRPC protocol. Use when creating a new plugin, implementing CostSourceService methods, setting up plugin scaffolding, debugging plugin communication, understanding the plugin lifecycle, or working with the recorder reference plugin. Triggers on: "create a plugin", "implement GetProjectedCost", "plugin gRPC", "pluginsdk", "plugin development", "recorder plugin", or any task involving finfocus plugin architecture.

SKILL.md

4.4 KB, as published. Nobody here has run it

FinFocus Plugin Development

Plugin Architecture

Plugins communicate with finfocus-core via gRPC using protocol buffers from finfocus-spec. Each plugin is a standalone binary that implements the CostSourceService.

Core CLI -> gRPC -> Plugin Binary
                    (CostSourceService)

Two launcher types:

  • ProcessLauncher (TCP) - Plugin listens on a port
  • StdioLauncher (stdin/stdout) - Plugin communicates over stdio

Quick Start: New Plugin

  1. Create Go module with finfocus-spec dependency
  2. Embed pluginsdk.BasePlugin for common functionality
  3. Implement required gRPC methods
  4. Build binary and install to ~/.finfocus/plugins/<name>/<version>/
import (
    "github.com/rshade/finfocus-spec/sdk/go/pluginsdk"
    pbc "github.com/rshade/finfocus-spec/sdk/go/proto/finfocus/v1"
)

type MyPlugin struct {
    *pluginsdk.BasePlugin
    logger zerolog.Logger
    mu     sync.Mutex
}

func (p *MyPlugin) Name() string { return "my-plugin" }

Required Methods

Every plugin must implement these CostSourceService methods:

MethodPurpose
GetProjectedCostEstimate future costs from resource descriptors
GetActualCostReturn historical costs for a time range
GetRecommendationsReturn cost optimization recommendations
GetPluginInfoReturn plugin metadata (name, version, providers)
ShutdownClean up resources on termination

Request Validation

Use pluginsdk validation helpers before processing:

func (p *MyPlugin) GetProjectedCost(ctx context.Context, req *pbc.GetProjectedCostRequest) (*pbc.GetProjectedCostResponse, error) {
    p.mu.Lock()
    defer p.mu.Unlock()

    if err := pluginsdk.ValidateProjectedCostRequest(req); err != nil {
        return nil, status.Errorf(codes.InvalidArgument, "validation: %v", err)
    }
    // Process request...
}

Plugin Installation

Plugins install to ~/.finfocus/plugins/<name>/<version>/:

# Build and install
make build-recorder
make install-recorder  # -> ~/.finfocus/plugins/recorder/0.1.0/

# Verify
./bin/finfocus plugin list
./bin/finfocus plugin validate

Environment Variables

Plugins receive these from core via pluginsdk constants:

ConstantEnv VarPurpose
pluginsdk.EnvPortFINFOCUS_PLUGIN_PORTgRPC port
pluginsdk.EnvLogLevelFINFOCUS_LOG_LEVELLog verbosity
pluginsdk.EnvLogFormatFINFOCUS_LOG_FORMATjson or text
pluginsdk.EnvLogFileFINFOCUS_LOG_FILELog file path
pluginsdk.EnvTraceIDFINFOCUS_TRACE_IDDistributed trace ID

Trace ID Propagation

// Server-side: extract trace ID from incoming gRPC metadata
server := grpc.NewServer(
    grpc.UnaryInterceptor(pluginsdk.TracingUnaryServerInterceptor()),
)

// In handlers: get trace ID from context
traceID := pluginsdk.TraceIDFromContext(ctx)

Reference Implementation

The recorder plugin at plugins/recorder/ demonstrates all patterns. See references/recorder-reference.md for the complete implementation walkthrough.

Plugin Communication Details

See references/pluginsdk-api.md for the full pluginsdk API, proto message types, and gRPC patterns.

Testing Plugins

go test ./plugins/recorder/...                       # Unit tests
go test ./test/integration/recorder_test.go          # Integration
go test -bench=BenchmarkRecorder ./plugins/recorder/... # Perf (<10ms)

Common Pitfalls

  • Always use sync.Mutex for thread safety in gRPC handlers
  • Return status.Errorf(codes.InvalidArgument, ...) for validation errors
  • Call cmd.Wait() after Kill() to prevent zombie processes
  • 10-second timeout with 100ms retry delays for plugin startup
  • Platform-specific binary detection (Unix permissions vs Windows .exe)

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.