Culebra, meaning 'snake' in Costa Rica, is a library for loading Lua scripts as configuration files and optionally bind them into Viper and integrate with Cobra CLI apps.
Important
The lua config will not replace existing cobra options like yml and json, it should work alongside them.
- Load Lua scripts as dynamic configuration sources with support for both traditional and Neovim-style configurations.
- Return configurations as
map[string]any
or easily bind them into Viper. - Integrate with Cobra through a simple one-liner:
culebra.UseWithCobra()
. - Provide flexibility with zero dependencies on Cobra/Viper β their usage is optional.
-- config.lua
app = {
name = "My App",
version = "1.0.0"
}
database = {
host = "localhost",
port = 5432
}
debug = true
-- Environment-based logic
if os.getenv("ENVIRONMENT") == "production" then
debug = false
database.host = "prod-db.example.com"
end
-- config-neovim-style.lua
local config = {}
local function setup_database()
return {
host = os.getenv("DB_HOST") or "localhost",
port = tonumber(os.getenv("DB_PORT") or "5432"),
ssl_mode = os.getenv("ENVIRONMENT") == "production" and "require" or "disable"
}
end
config.app = {
name = "My App",
version = "1.0.0"
}
config.database = setup_database()
config.features = {
debug_mode = os.getenv("ENVIRONMENT") ~= "production"
}
-- Validation
assert(config.database.host, "Database host is required")
return config
- β
Load(cfg Config) (map[string]any, error)
β Loads Lua configuration from file. - β
LoadWithArrays(filePath string) (map[string]any, error)
β Loads Lua config with array conversion. - β
LoadWithGlobals(filePath string, globals map[string]any) (map[string]any, error)
β Loads Lua config with global variables. - β
LoadWithArraysAndGlobals(filePath string, globals map[string]any) (map[string]any, error)
β Loads with both features. - β
BindToViper(cfg Config, v *viper.Viper) error
β Injects configuration into Viper. - β
UseWithCobra(cmd *cobra.Command)
β Adds--config
flag with automatic Lua discovery. - β Includes comprehensive error handling and validation.
- β Supports both traditional and Neovim-style configuration patterns.
github.com/yuin/gopher-lua
β Lua VM in Go.github.com/spf13/viper
(optional).gitproxy.zycloud.tk/spf13/cobra
(optional).
// Simple Lua configuration loading
cfg := culebra.Config{FilePath: "config.lua"}
data, err := culebra.Load(cfg)
if err != nil {
log.Fatal(err)
}
fmt.Printf("App name: %s\n", data["app"].(map[string]any)["name"])
// Load with automatic array conversion
data, err := culebra.LoadWithArrays("config.lua")
// Lua arrays become Go slices: []any{"item1", "item2", "item3"}
// Pass Go variables to Lua configuration
globals := map[string]any{
"environment": "production",
"debug_enabled": false,
}
data, err := culebra.LoadWithGlobals("config.lua", globals)
cfg := culebra.Config{
FilePath: "config.lua",
ConvertArrays: true,
}
err := culebra.BindToViper(cfg, viper.GetViper())
rootCmd := &cobra.Command{
Use: "myapp",
Short: "My application with Lua configuration",
Run: func(cmd *cobra.Command, args []string) {
// Access configuration via Viper
fmt.Printf("Database: %s\n", viper.GetString("database.host"))
},
}
// Adds --config flag with automatic .lua file discovery
culebra.UseWithCobra(rootCmd)
// Configure automatic .lua file discovery
viper.SetConfigName("myapp") // Searches for myapp.lua
viper.AddConfigPath("/etc/myapp")
viper.AddConfigPath("$HOME/.config/myapp")
viper.AddConfigPath(".")
culebra.UseWithCobra(rootCmd) // Auto-loads first .lua file found
The repository includes comprehensive examples showcasing different use cases:
examples/basic/
- Basic Lua configuration with Cobra/Viperexamples/autoload/
- Automatic configuration discoveryexamples/arrays/
- Array conversion and Viper integrationexamples/advanced/
- Complex, environment-aware configurationexamples/viper-showcase/
- Comprehensive demo of ALL Viper Get functions
Run all examples: just example
Currently, Culebra supports local configuration logic but doesn't include HTTP capabilities. Future versions could add network support for advanced use cases:
-- Future capability: Remote configuration fetching
local feature_flags = http.get("https://api.company.com/feature-flags")
local service_discovery = http.get("https://consul.company.com/v1/catalog/services")
config.features = feature_flags.enabled
config.services = service_discovery.endpoints
This would enable:
- Remote Feature Flags: Dynamic feature toggling from external services
- Service Discovery: Automatic service endpoint configuration
- External Configuration: Loading partial config from remote sources
- API Integration: Direct integration with configuration management APIs
Implementation Options:
- Custom HTTP module for gopher-lua
- Integration with existing
gluahttp
library - Go-side pre-fetching with Lua globals
- Async configuration updates
- Configuration Caching: Cache remote configurations with TTL
- Hot Reloading: Watch for configuration changes and reload automatically
- Configuration Validation: Schema validation for Lua configurations
- Encrypted Configurations: Support for encrypted configuration files
- Configuration Templating: Advanced templating beyond basic Lua logic
MIT