Glazed provides a powerful, queryable help system for creating rich CLI documentation with sections, metadata, and programmatic access.
The Glazed help system provides a structured, queryable approach to CLI documentation that goes beyond basic command help. It organizes documentation into typed sections (topics, examples, applications, tutorials) with rich metadata for filtering and discovery. The system supports both human-readable help pages and programmatic querying through a simple DSL, making it easy to build comprehensive CLI documentation that users can explore efficiently.
The help system stores sections in an SQLite-backed store, enabling fast queries, text search, and metadata filtering. You typically load documentation from markdown files with YAML frontmatter at startup, creating a self-contained help database that you can query from both the command line and Go code.
You can also export the entire help tree—or a filtered slice of it—to JSON, CSV, YAML, individual markdown files, or a standalone SQLite database. This is useful for backups, external indexing, and shipping documentation alongside your application. See [glaze help export-help-entries](glaze help export-help-entries) for details.
Help sections follow a type-based classification system that separates conceptual documentation from practical examples. This separation enables precise filtering and contextual help display, allowing users to find exactly the type of information they need based on their current task.
Each section contains:
type Section struct {
// Core content
Slug string // Unique identifier for referencing
Title string // Display title
Short string // Brief description
Content string // Full markdown content
// Section classification
SectionType SectionType // GeneralTopic, Example, etc.
// Searchable metadata
Topics []string // Related topic tags
Commands []string // Relevant CLI commands
Flags []string // Associated command flags
// Display behavior
IsTopLevel bool // Show in main help listing
ShowPerDefault bool // Include without --all flag
Order int // Sort order within type
}
The help system exposes a programming model centered around the HelpSystem struct, which manages an SQLite-backed documentation store. You can initialize the system, load documentation from various sources, and query sections using both simple lookups and complex DSL expressions.
// Create new help system with in-memory storage
hs := help.NewHelpSystem()
// Load documentation from embedded filesystem
//go:embed docs
var docsFS embed.FS
err := hs.LoadSectionsFromFS(docsFS, "docs")
if err != nil {
log.Fatal(err)
}
You typically load documentation from markdown files with YAML frontmatter:
// Load from filesystem recursively
err := hs.LoadSectionsFromFS(filesystem, "documentation")
// Load individual section from markdown
markdownBytes := []byte(`---
Title: Example Command
Slug: json-example
SectionType: Example
Topics: [json, formatting]
Commands: [json]
---
# JSON Output Example
Use the json command to format data:
...`)
section, err := help.LoadSectionFromMarkdown(markdownBytes)
if err == nil {
hs.AddSection(section)
}
The help system treats documentation as structured data that can be queried using boolean logic and metadata filters. This approach transforms static help text into a searchable knowledge base where users can find relevant documentation by combining criteria like section type, topics, and command associations.
// Query by section type
examples, err := hs.QuerySections("type:example")
// Find sections about databases
dbSections, err := hs.QuerySections("topic:database")
// Search for specific commands
jsonHelp, err := hs.QuerySections("command:json")
// Full-text search
searchResults, err := hs.QuerySections(`"SQLite integration"`)
// AND operations - sections that are both examples AND about databases
results, err := hs.QuerySections("type:example AND topic:database")
// OR operations - either examples or tutorials
results, err := hs.QuerySections("type:example OR type:tutorial")
// NOT operations - exclude advanced topics
results, err := hs.QuerySections("type:example AND NOT topic:advanced")
// Grouping with parentheses
results, err := hs.QuerySections("(type:example OR type:tutorial) AND topic:database")
// Query section display properties
topLevel, err := hs.QuerySections("toplevel:true")
defaults, err := hs.QuerySections("default:true")
// Flag and command associations
flagHelp, err := hs.QuerySections("flag:--output")
cmdHelp, err := hs.QuerySections("command:json OR command:yaml")
When you know the exact section you need, you can retrieve it directly using its unique slug identifier. This approach bypasses the query system for immediate access to specific documentation sections.
// Get specific section by slug
section, err := hs.GetSectionWithSlug("help-system")
if err != nil {
if err == help.ErrSectionNotFound {
// Handle missing section
}
return err
}
// Access section content and metadata
fmt.Printf("Title: %s\n", section.Title)
fmt.Printf("Type: %s\n", section.SectionType.String())
fmt.Printf("Topics: %v\n", section.Topics)
The help system extends Cobra's built-in help functionality by automatically displaying relevant documentation sections when users request help for specific commands. This integration creates contextual help that shows both command syntax and related educational content.
Glazed now renders command help to stdout by default so that users can pipe or capture the full help text just like any other command output. If your application relied on the old behavior (printing to stderr) or you need to redirect help into a custom sink, configure the writer once during startup:
import (
"os"
help_cmd "github.com/go-go-golems/glazed/pkg/help/cmd"
)
func init() {
// Route all Glazed-generated help output back to stderr
help_cmd.SetHelpWriter(os.Stderr)
}
You can pass any io.Writer, which makes it easy to capture help text for tests or to mirror it into logs.
func SetupHelpSystem(rootCmd *cobra.Command, hs *help.HelpSystem) {
// Add help command with query support
helpCmd := &cobra.Command{
Use: "help [topic]",
Short: "Help about any command or topic",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
// Show top-level help page
page := hs.GetTopLevelHelpPage()
fmt.Print(page.Render())
return
}
// Look up specific section
section, err := hs.GetSectionWithSlug(args[0])
if err != nil {
fmt.Printf("Help topic '%s' not found\n", args[0])
return
}
fmt.Print(section.Content)
},
}
rootCmd.AddCommand(helpCmd)
}
// Augment command help with related sections
func AugmentCommandHelp(cmd *cobra.Command, hs *help.HelpSystem) {
originalUsageFunc := cmd.UsageFunc()
cmd.SetUsageFunc(func(c *cobra.Command) error {
// Show standard command help
if err := originalUsageFunc(c); err != nil {
return err
}
// Find related help sections
query := fmt.Sprintf("command:%s AND default:true", c.Name())
sections, err := hs.QuerySections(query)
if err != nil || len(sections) == 0 {
return nil
}
// Display related sections
fmt.Println("\n## Related Documentation")
for _, section := range sections {
fmt.Printf(" %s - %s\n", section.Slug, section.Short)
fmt.Printf(" glaze help %s\n", section.Slug)
}
return nil
})
}
Section metadata transforms help content into a rich data structure that you can filter and organize based on user context. By leveraging metadata fields like topics, commands, and flags, you can build intelligent help systems that surface the most relevant documentation for any given situation.
// Get sections for specific contexts
func GetSectionsForCommand(hs *help.HelpSystem, commandName string) []*help.Section {
sections, _ := hs.QuerySections(fmt.Sprintf("command:%s", commandName))
return sections
}
func GetExamplesForTopic(hs *help.HelpSystem, topic string) []*help.Section {
query := fmt.Sprintf("type:example AND topic:%s", topic)
sections, _ := hs.QuerySections(query)
return sections
}
func GetDefaultSections(hs *help.HelpSystem) []*help.Section {
sections, _ := hs.QuerySections("default:true")
return sections
}
// Build contextual help based on current command and flags
func BuildContextualHelp(hs *help.HelpSystem, cmdName string, flags []string) {
var queries []string
// Add command-specific sections
queries = append(queries, fmt.Sprintf("command:%s", cmdName))
// Add flag-specific sections
for _, flag := range flags {
queries = append(queries, fmt.Sprintf("flag:%s", flag))
}
// Combine with OR logic
query := strings.Join(queries, " OR ")
sections, err := hs.QuerySections(query)
if err != nil {
return
}
// Display relevant sections
for _, section := range sections {
if section.ShowPerDefault {
fmt.Printf("📖 %s\n", section.Short)
}
}
}
When building complex documentation systems, you need visibility into how queries are parsed and executed. The help system includes debugging tools that show query AST generation and SQL translation, helping you understand and optimize query performance.
// Debug query parsing and SQL generation
err := hs.PrintQueryDebug("type:example AND topic:database", true, true)
// Outputs:
// Query: type:example AND topic:database
// AST:
// AND
// ├── Field: type = "example"
// └── Field: topic = "database"
// SQL Query:
// SELECT * FROM sections WHERE section_type = ? AND ? = ANY(topics)
// Fields: [1 database]
For high-frequency querying scenarios, you can implement caching by storing query results in a map. The help system's SQLite backend is already optimized for typical usage patterns.
For more information about the query DSL syntax and capabilities:
glaze help simple-query-dsl
glaze help export-help-entries](glaze help export-help-entries) — Export help sections to files, JSON, CSV, or SQLiteglaze help serve-help-over-http](glaze help serve-help-over-http) — Browse help in a web browserglaze help export-help-static-website](glaze help export-help-static-website) — Export help as a static websiteglaze help writing-help-entries](glaze help writing-help-entries) — How to write help sectionsglaze help sections-guide](glaze help sections-guide) — Deep dive into section metadata and query DSL