Skip to content

feat: synthorg CLI — Go binary for install, setup wizard, updates, and diagnostics #392

@Aureliolo

Description

@Aureliolo

Summary

Replace the current "git clone + docker compose build" workflow with a cross-platform Go CLI binary (synthorg) that provides an interactive setup wizard, container management, self-updates, and diagnostic error reporting.

Current UX problem: Users must clone the entire source repo and build Docker images locally, even though pre-built, signed images are already published to GHCR on every release. There's no upgrade path beyond git pull && rebuild.

User Experience

# Install (platform-specific)
brew install aureliolo/tap/synthorg        # macOS
scoop install synthorg                      # Windows
curl -fsSL https://get.synthorg.io | sh    # Linux

# Setup wizard
synthorg init

# Lifecycle
synthorg start       # pull images + launch containers
synthorg stop        # stop containers
synthorg status      # health check + version info
synthorg logs        # tail container logs
synthorg update      # update CLI + pull new container images
synthorg doctor      # collect diagnostics, generate issue link
synthorg uninstall   # remove containers + data (with confirmation)

Interactive Setup Wizard (synthorg init)

Extended config wizard using charmbracelet/huh for terminal forms:

Welcome to SynthOrg Setup!

? Data directory [/opt/synthorg/data]
? Backend API port [8000]
? Web dashboard port [3000]
? Enable agent code sandbox? [y/N]
? Docker socket path [/var/run/docker.sock]
? Log level (debug/info/warn) [info]
? Generate JWT secret? [Y/n]

Pulling images...  ████████████████████ 100%
Starting services... done

SynthOrg is running!
  Dashboard: http://localhost:3000
  API:       http://localhost:8000
  First-run: http://localhost:3000/setup

Output: Generates a compose.yml (with image: tags, not build:) and .env in the chosen data directory. All LLM provider configuration happens through the web UI after setup (persisted in DB, not env vars).

Architecture

Tech Stack

Component Choice Rationale
Language Go Cross-compile to Linux/macOS/Windows, single binary, zero runtime deps
CLI framework Cobra Used by Docker, kubectl, gh CLI. Subcommands, flags, auto-help
Interactive forms Huh (charmbracelet) Terminal wizard with Select, Input, Confirm. Accessibility mode built-in
Spinners/progress Huh spinner Loading states for pull/start/health-check
Release GoReleaser Cross-platform builds, Homebrew tap, Scoop manifest, checksums, signing

CLI Structure

cmd/
  synthorg/
    main.go              # entry point
    cmd/
      root.go            # root command, version flag
      init.go            # interactive setup wizard
      start.go           # docker compose up
      stop.go            # docker compose down
      status.go          # health check + version
      logs.go            # docker compose logs
      update.go          # self-update + container update
      doctor.go          # diagnostics + issue link
      uninstall.go       # teardown with confirmation
    internal/
      compose/           # compose file generation + management
      config/            # .env generation, validation
      docker/            # Docker/Compose detection, version checks
      health/            # health check polling
      update/            # GitHub Releases API, self-update logic
      diag/              # diagnostic collection, issue URL generation

Key Behaviors

Docker prerequisite check (synthorg init / synthorg start):

  • Detect Docker Engine installed and running
  • Detect Docker Compose v2 (plugin) available
  • Check minimum versions
  • Platform-specific guidance if missing (Docker Desktop for macOS/Windows, apt/dnf for Linux)

Compose file generation (synthorg init):

  • Generates compose.yml with image: ghcr.io/aureliolo/synthorg-backend:<version> and image: ghcr.io/aureliolo/synthorg-web:<version>
  • Version baked from CLI's own version (CLI version = container version)
  • Includes all CIS hardening from current compose (security_opt, cap_drop, read_only, tmpfs)
  • Persists to data directory alongside .env

Self-update (synthorg update):

  1. Query GitHub Releases API for latest version
  2. Compare with current CLI version (embedded at build time)
  3. If newer: download platform binary, replace self (exec pattern)
  4. Pull new container images matching the new version
  5. Recreate containers with docker compose up -d
  6. Health check after restart

Diagnostic error reporting (synthorg doctor or auto on failure):

  1. Collect: OS, arch, kernel, Docker version, Compose version, disk space, memory
  2. Collect: container status, recent logs (last 50 lines), .env (redacted secrets)
  3. Save to local file (synthorg-diagnostic-<timestamp>.txt)
  4. Generate pre-filled GitHub issue URL: https://github.com/Aureliolo/synthorg/issues/new?title=...&labels[]=bug&labels[]=installer&body=...
  5. Print both file path and issue URL

Health check (synthorg status):

  • Poll http://localhost:<port>/api/v1/health with timeout
  • Show container states (running/stopped/unhealthy)
  • Show versions (CLI, backend image, web image)
  • Show resource usage (CPU/memory per container)

Distribution

Platform Method Details
macOS Homebrew aureliolo/tap/synthorg (GoReleaser auto-generates)
Windows Scoop aureliolo/scoop-bucket (GoReleaser auto-generates)
Linux curl installer curl -fsSL https://get.synthorg.io | sh (detects arch, downloads binary)
All GitHub Releases Binary downloads per platform/arch
Docker users Not needed CLI manages Docker, not runs inside it

What Changes

  • New Go module in repo (e.g. cli/ directory or separate synthorg-cli repo)
  • GoReleaser config for cross-platform builds
  • GitHub Actions workflow to build + release CLI on version tags
  • Homebrew tap repo (aureliolo/homebrew-tap)
  • Scoop bucket repo (aureliolo/scoop-synthorg)
  • get.synthorg.io redirect or static page for curl installer
  • Update README Quick Start to show synthorg init as primary path
  • Keep docker/compose.yml as dev-only (for building from source)
  • GitHub issue template for installer failures (install-failure.yaml)

Research References

  • Coolify: curl | bash installer with 9-step pipeline, CDN version manifest, upgrade.sh
  • Dokploy: Same script handles install + update via sh -s update
  • Supabase CLI: Go binary, supabase init/start, Homebrew/Scoop distribution
  • Sentry self-hosted: Gold standard for error reporting (opt-in diagnostics, dedup, Sentry envelopes)
  • charmbracelet/huh: Terminal forms library for Go (Select, Input, Confirm, wizard groups)
  • Cobra: CLI framework used by Docker, kubectl, gh CLI (173K+ projects)
  • GoReleaser: Cross-platform builds, Homebrew tap + Scoop manifest auto-generation

Metadata

Metadata

Assignees

No one assigned

    Labels

    prio:mediumShould do, but not blockingscope:large3+ days of worktype:featureNew feature implementation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions