Skip to content
Star on GitHub

Write your data once. Render it anywhere.

One Go library. 16 output formats across tables, trees, and diagrams. Plus NOM-style real-time progress for long-running workflows. Zero heavy deps in root.

Get Started →
$ go get github.com/larsartmann/go-output
main.go
package main

import (
    "fmt"
    "github.com/larsartmann/go-output"
    "github.com/larsartmann/go-output/graph"
)

func main() {
    // 1. Build — mutable
    b := output.NewGraphBuilder()
    b.AddNode(output.NewGraphNode("compile", "Compile"))
    b.AddNode(output.NewGraphNode("test", "Test"))
    b.AddEdge(output.NewGraphEdge("compile", "test"))

    // 2. Freeze — immutable
    g := b.Build()

    // 3. Render — pure functions
    dot, _     := graph.RenderDOT(g)
    mermaid, _ := graph.RenderMermaid(g)

    fmt.Println(dot, mermaid)
}

16 formats. 3 data shapes.

Every format declares which shapes it supports. Query the matrix at runtime.

JSON root
Table Tree Graph
YAML serialization
Table Tree Graph
TOML serialization
Table Tree Graph
CSV delimited
Table
TSV delimited
Table
JSONL serialization
Table
XML markup
Table
HTML markup
Table Tree
AsciiDoc markup
Table
Markdown root
Table
Table table
Table
Tree root
Tree
D2 d2
Table Graph
Mermaid graph
Table Graph
DOT graph
Table Graph
PlantUML plantuml
Table Graph

Engineered for flexibility.

Every API decision optimized for real-world CLI tools, CI pipelines, and documentation generators.

16 Formats, One API

Same Table, TreeNode, or GraphNode. JSON, CSV, Markdown, D2, Mermaid — no format-specific code paths.

Type-Safe Everything

Format, ColorMode, ActivityStatus — validated at parse time. Branded IDs prevent mixing types at compile time.

Zero Heavy Deps in Root

go get pulls only x/term. YAML, lipgloss, bubbletea, and diagram renderers are opt-in sub-modules.

NOM Real-Time Progress

Dependency trees, activity counts, timing estimates, and inline terminal rendering. O(1) summary bars.

Streaming for Large Data

CQRS pure-function renderers stream via standard encoders. No intermediate string allocations.

Zero-Config Color

ColorModeAuto detects TTY, respects NO_COLOR, CI, FORCE_COLOR. Three wiring mechanisms, one result.

Build. Freeze. Render.

CQRS architecture: mutable builders, immutable snapshots, pure-function renderers. Same data, every format.

1

Build — Mutable

b := output.NewGraphBuilder()
b.AddNode(node)
b.AddEdge(edge)
Fluent API, chainable calls
2

Freeze — Immutable

g := b.Build()
// g.Nodes() / g.Edges() only
Snapshot taken, no further mutation
3

Render — Pure Functions

dot, _     := graph.RenderDOT(g)
mermaid, _ := graph.RenderMermaid(g)
Same Graph, multiple formats, no side effects

Why go-output?

One data model, sixteen formats. Not a per-format wrapper, not a heavy framework.

DIY
DIY
Hand-write each format
No type safety on enums
Duplicate logic per renderer
No cross-shape conversion
go-output
Free
16 formats from one data model
Type-safe enums + branded IDs
CQRS pure-function renderers
Cross-shape projections built-in
NOM real-time progress included
Heavy
Heavy
Pulls lipgloss/bubbletea everywhere
Tightly coupled renderers
No streaming-first design
Large dependency footprint

Built for real tools.

Drop it into any CLI, CI pipeline, documentation generator, or dashboard.

CLI Tools

One data model, runtime format flags. CSV for scripts, tables for terminals, JSON for pipelines.

CI/CD Pipelines

NOM progress tracking with CI-safe degradation. Auto-detects non-TTY and appends frames line-by-line.

Documentation

Render architecture diagrams as D2, Mermaid, DOT, or PlantUML from a single graph builder.

Dashboards

Interactive SVG DAGs for HTML. Pan, zoom, click-highlight. Zero external dependencies.

Start rendering in seconds.

One import, one data model, sixteen formats. Plus NOM-style progress visualization.