Stage 3 · Build
Building CLI Tools
Plugin Architecture
HashiCorp go-plugin, Yaegi, and dynamic loading for extensible CLI tools.
When to Use Plugins
Plugins extend your tool without recompiling. They are useful for custom checks, vendor-specific integrations, and community extensions. But plugins add complexity — use them only when the extension point justifies the overhead.
- Custom linting rules or compliance checks
- Vendor-specific cloud provider integrations
- Custom output formatters or report generators
- Community-contributed extensions
- Separating proprietary logic from open-source core
Go's plugin package
Go has a built-in plugin package for loading shared libraries at runtime. Plugins are compiled as .so files and must match the host binary's Go version exactly.
The host binary and plugin must use the exact same Go version, dependency versions, and build flags. A mismatch causes runtime panics. This makes Go plugins fragile for distribution.
HashiCorp go-plugin
HashiCorp go-plugin runs plugins as separate processes. Communication happens over gRPC or net/rpc. This eliminates version coupling — the plugin process can use a different Go version or dependencies.
Yaegi Interpreter
Yaegi is a Go interpreter. It can execute Go source code at runtime without compilation. This is useful for scripting, configuration logic, and user-defined transformations.
Plugin Interface Design
A good plugin interface is minimal, stable, and versioned. Define the interface in a shared package that both host and plugins import.
Security Considerations
Plugins run with the same permissions as the host process. Treat them as untrusted code. Validate inputs, sandbox execution, and verify plugin signatures.
- Verify plugin checksums before loading
- Run plugins with minimal permissions (non-root user)
- Set execution timeouts for plugin calls
- Validate all inputs before passing to plugins
- Log all plugin invocations for audit trails
- Consider running plugins in containers for isolation
Many tools that claim to need plugins actually do not. Start with a simple architecture. If users need extensibility, add it later. Premature abstraction is the root of all evil in plugin design.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.