CLI Output

Centralized terminal output system with profile-aware formatting

2 min read 499 words

Bengal's CLI Output system provides a unified interface for all terminal messaging with profile-aware formatting, consistent spacing, and automatic TTY detection.

Overview

The output system centralizes all CLI messaging, ensuring consistent formatting across commands and adapting to different user profiles (Writer, Theme-Dev, Developer).

from bengal.output import CLIOutput
from bengal.utils.profile import BuildProfile

cli = CLIOutput(profile=BuildProfile.WRITER)

cli.header("Building your site...")
cli.phase("Discovery", duration_ms=61, details="245 pages")
cli.detail("Found 245 pages", indent=1)
cli.success("Built 245 pages in 0.8s")

Architecture

graph TB subgraph "Output System" CLI[CLIOutput] Profile[BuildProfile<br/>Writer, Theme-Dev, Developer] Rich[Rich Console<br/>Auto-detected] end subgraph "Output Types" Header[Headers] Phase[Phase Messages] Detail[Details] Status[Status Messages] Error[Errors] end Profile --> CLI CLI --> Rich CLI --> Header CLI --> Phase CLI --> Detail CLI --> Status CLI --> Error

Build Profiles

Different profiles show different levels of detail:

Writer Profile

Optimized for content creators:

cli = CLIOutput(profile=BuildProfile.WRITER)
# Shows: High-level progress, errors, warnings
# Hides: Technical details, debug info

Theme-Dev Profile

For theme development:

cli = CLIOutput(profile=BuildProfile.THEME_DEV)
# Shows: Template resolution, asset processing
# Hides: Content discovery details

Developer Profile

Full technical output:

cli = CLIOutput(profile=BuildProfile.DEVELOPER)
# Shows: Everything, including debug info

Output Methods

Headers

cli.header("Building your site...")
# Output: Building your site...

Phase Messages

Track build phase completion with optional timing and details:

cli.phase("Discovery", duration_ms=61)
# Output: ✓ Discovery     61ms

cli.phase("Rendering", duration_ms=501, details="245 pages")
# Output: ✓ Rendering     501ms (245 pages)

cli.phase("Assets", status="Done")
# Output: ✓ Assets        Done

Parameters:name,status="Done",duration_ms=None,details=None,icon="✓"

Details

cli.detail("Found 245 pages", indent=1)
# Output:   Found 245 pages

Status Messages

cli.success("Build complete!")
cli.warning("Some pages have warnings")
cli.error("Build failed")
cli.info("Using cached assets")
cli.tip("Run 'bengal serve' to preview")

Message Levels

The output system uses message levels for filtering:

from bengal.output.enums import MessageLevel

cli.should_show(MessageLevel.INFO)    # True/False based on profile
cli.should_show(MessageLevel.DEBUG)   # Only in Developer profile

Rich Integration

The output system automatically detects Rich support:

cli = CLIOutput(use_rich=None)  # Auto-detect
cli = CLIOutput(use_rich=True)  # Force Rich
cli = CLIOutput(use_rich=False) # Plain text

Rich Features:

  • Syntax highlighting
  • Tables and panels
  • Progress bars
  • Colors and styling

Fallback: Automatically falls back to plain text when Rich isn't available.

Global Instance

Use the global instance for convenience:

from bengal.output import get_cli_output, init_cli_output
from bengal.utils.profile import BuildProfile

# Initialize once at CLI entry point
cli = init_cli_output(profile=BuildProfile.WRITER)

# Access from anywhere in the codebase
cli = get_cli_output()
cli.success("Done!")

Dev Server Integration

The output system integrates with the dev server:

# Dev server sets environment variable
os.environ["BENGAL_DEV_SERVER"] = "1"

# Output system detects dev mode
cli.dev_server  # True
# Enables phase deduplication, streaming output

Phase Deduplication

In dev server mode, duplicate phase messages are suppressed:

# Rapid rebuilds don't spam terminal
cli.phase("Rendering")  # Shows
cli.phase("Rendering")  # Suppressed (within 1.5s window)