Glazed Command Authoring
Use this skill when creating or refactoring Glazed commands. It captures the current conventions, pitfalls, and wiring patterns we used successfully. Keep it lean, but always follow the workflow so commands are consistent and CLI behavior is predictable.
Quick Start (Minimal Workflow)
- •Define a command struct embedding
*cmds.CommandDescription. - •Define a settings struct with
glazed.parametertags. - •Create a constructor that builds the description using
cmds.NewCommandDescription,cmds.WithFlags, andcmds.WithLayersList. - •Implement
RunIntoGlazeProcessorand decode values into your settings struct. - •Build a Cobra command using
cli.BuildCobraCommand(or a custom wrapper) and register it in your root/group command.
Canonical Code Skeleton
// 1) Command + settings structs
type FooCommand struct {
*cmds.CommandDescription
}
type FooSettings struct {
Limit int `glazed.parameter:"limit"`
Debug bool `glazed.parameter:"debug"`
}
// 2) Constructor
func NewFooCommand() (*FooCommand, error) {
glazedLayer, err := schema.NewGlazedSchema()
if err != nil {
return nil, err
}
commandSettingsLayer, err := cli.NewCommandSettingsLayer()
if err != nil {
return nil, err
}
cmdDesc := cmds.NewCommandDescription(
"foo",
cmds.WithShort("Short description"),
cmds.WithLong(`
Long description.
Examples:
foo --limit 5
foo --output json
`),
cmds.WithFlags(
fields.New(
"limit",
fields.TypeInteger,
fields.WithDefault(10),
fields.WithHelp("Maximum number of results"),
),
fields.New(
"debug",
fields.TypeBool,
fields.WithDefault(false),
fields.WithHelp("Enable debug output"),
),
),
cmds.WithLayersList(glazedLayer, commandSettingsLayer),
)
return &FooCommand{CommandDescription: cmdDesc}, nil
}
// 3) RunIntoGlazeProcessor
func (c *FooCommand) RunIntoGlazeProcessor(
ctx context.Context,
vals *values.Values,
gp middlewares.Processor,
) error {
settings := FooSettings{}
if err := values.DecodeSectionInto(vals, schema.DefaultSlug, &settings); err != nil {
return err
}
row := types.NewRow(
types.MRP("limit", settings.Limit),
types.MRP("debug", settings.Debug),
)
return gp.AddRow(ctx, row)
}
Field/Parameter Conventions
- •Preferred constructor: use
fields.New(...)(not the olderparameters.NewParameterDefinition). - •Struct tags:
glazed.parameter:"flag-name"is the authoritative mapping. - •Always decode with
values.DecodeSectionInto(vals, schema.DefaultSlug, &settings)instead of reading Cobra flags directly.
Layer Composition
- •Glazed output layer:
schema.NewGlazedSchema()(adds--output,--fields, etc). - •Command settings layer:
cli.NewCommandSettingsLayer()(adds--print-parsed-parameters,--print-schema,--print-yaml). - •Add custom layers (e.g. Zigbee layer) via
cmds.WithLayersList(...).
Per-command output defaults
If a command should default to a specific output (ex: yaml + streaming), supply output defaults when creating the glazed layer:
glazedLayer, err := schema.NewGlazedSchema(
settings.WithOutputParameterLayerOptions(
layers.WithDefaults(map[string]interface{}{
"output": "yaml",
"stream": true,
}),
),
)
Use this for commands that primarily stream events or logs.
Cobra Integration
- •Build the Cobra command with:
cobraCmd, err := cli.BuildCobraCommand(cmd,
cli.WithParserConfig(cli.CobraParserConfig{
ShortHelpLayers: []string{schema.DefaultSlug},
MiddlewaresFunc: cli.CobraCommandDefaultMiddlewares,
}),
)
- •For multiple command groups, create a group
root.goper directory and callRegister(root, defaults).
Custom middlewares
If you need config/env/profile precedence (like Geppetto), implement a custom MiddlewaresFunc and pass it via cli.WithParserConfig. Keep precedence explicit and documented.
Help + Documentation
- •Use
cmds.WithLongwith examples for every command. - •Wire the help system at the root using
help.NewHelpSystem()andhelp_cmd.SetupCobraRootCommand(). - •Frontmatter YAML in help docs must be valid. Quote strings that contain colons.
Logging (recommended)
- •Add logging layer to root command:
_ = logging.AddLoggingLayerToRootCommand(rootCmd, "appname")
- •Initialize logging in
PersistentPreRunE:
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return logging.InitLoggerFromCobra(cmd)
},
Grouping Commands
Two valid patterns:
- •Explicit Cobra parents (recommended for larger apps)
- •Metadata parents using
cmds.WithParents("group")(fine for simple sets)
If you use explicit groups, keep this convention:
- •one directory per group
- •one file per verb
- •one
root.goper group to register subcommands
Streaming Commands
- •Use a
--watchor--streamflag. - •If events are long-running, add a duration or timeout and exit cleanly.
- •Filter to relevant events before emitting rows.
Common Pitfalls
- •Pointer to interface:
schema.Sectionis an interface; don’t use*schema.Section. - •Output defaults: use
settings.WithOutputParameterLayerOptionsonschema.NewGlazedSchema. - •Help frontmatter: quote strings with colons.
- •Duplicate flags: don’t add the same layer to both parent and child commands.
Reference: Read these when needed
- •Glazed tutorial:
/home/manuel/code/wesen/corporate-headquarters/glazed/pkg/doc/tutorials/05-build-first-command.md - •Glazed repo code (patterns, middlewares, layers):
/home/manuel/code/wesen/corporate-headquarters/glazed