No description
  • Go 98.8%
  • Makefile 1.2%
Find a file
2026-02-25 22:50:11 -06:00
internal heirarchical menu system 2026-02-25 22:50:11 -06:00
go.mod initial starting app 2026-02-25 21:03:48 -06:00
go.sum initial starting app 2026-02-25 21:03:48 -06:00
main.go fix fonts 2026-02-25 21:33:32 -06:00
Makefile fix fonts 2026-02-25 21:33:32 -06:00
README.md initial starting app 2026-02-25 21:03:48 -06:00

uncloud-gui

A desktop GUI application built with Gio UI that serves as a graphical replacement for the uc CLI — the command-line tool for Uncloud, a lightweight Docker container orchestration platform.


Features

Every major uc command is surfaced through a dedicated UI panel:

Page CLI Commands Covered
Dashboard uc machine ls, uc service ls, uc ps, uc wg show
Machines uc machine ls/init/add/rm/rename/token
Services uc service ls/run/rm/logs/inspect/scale/start/stop/exec, uc deploy
Volumes uc volume ls/create/inspect/rm
Images uc image ls/push
DNS uc dns show/reserve/release
Caddy uc caddy config/deploy
Contexts uc ctx ls/use/connection
Terminal Free-form uc <any command> + full command history log
Settings Configure binary path, cluster context, --connect, --uncloud-config

Prerequisites

  • Go 1.21+
  • Gio UI dependencies (platform libraries for GPU rendering):
    • macOS: Xcode command-line tools
    • Linux: libwayland-dev libx11-dev libxkbcommon-x11-dev libgles2-mesa-dev
    • Windows: No extra deps
  • The uc binary installed and available in $PATH (or configure a custom path in Settings)

Installation

# Install uc CLI first
brew install psviderski/tap/uncloud  # macOS/Linux via Homebrew

# Clone and run uncloud-gui
git clone https://github.com/yourname/uncloud-gui
cd uncloud-gui
go mod tidy
go run .

Or build a standalone binary:

go build -o uncloud-gui .
./uncloud-gui

Project Structure

uncloud-gui/
├── main.go                          # Entry point, window setup
├── go.mod
└── internal/
    ├── runner/
    │   └── runner.go                # Wraps uc CLI execution (exec.Command)
    ├── theme/
    │   └── colors.go                # Dark theme color palette
    └── ui/
        ├── app.go                   # App state, main event loop, page routing
        ├── sidebar.go               # Left navigation panel
        ├── widgets.go               # Shared helpers: Card, StatusBadge, TerminalLog, OutputBox
        ├── page_dashboard.go        # Dashboard overview page
        ├── page_machines.go         # Machines management page
        ├── page_services.go         # Services management page (most complex)
        ├── page_generic.go          # Generic command page + Volumes/Images/DNS/Caddy/Contexts
        ├── page_terminal.go         # Terminal log + free-form command runner
        └── page_settings.go         # Settings / configuration page

Architecture

┌─────────────────────────────────────────────────────────┐
│                    Gio Window                           │
│  ┌──────────────┐  ┌──────────────────────────────────┐ │
│  │   Sidebar    │  │         Page Content             │ │
│  │              │  │                                  │ │
│  │ • Dashboard  │  │  Each page renders UI for a      │ │
│  │ • Machines   │  │  group of uc commands.           │ │
│  │ • Services   │  │                                  │ │
│  │ • Volumes    │  │  User clicks a button → page     │ │
│  │ • Images     │  │  calls runner.RunAsync(args…)    │ │
│  │ • DNS        │  │  → goroutine runs exec.Command   │ │
│  │ • Caddy      │  │  → result sent back via channel  │ │
│  │ • Contexts   │  │  → output displayed in panel     │ │
│  │ • Terminal   │  │                                  │ │
│  │ • Settings   │  │  All command output is also      │ │
│  │              │  │  logged to shared TerminalLog    │ │
│  └──────────────┘  └──────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
                          │
                    runner.Runner
                          │
                    exec.Command("uc", args…)
                          │
                    uc binary (SSH → cluster)

Key Design Decisions

Gio immediate mode UI: Every frame the entire UI is re-rendered from state. No retained widget tree. Widgets are laid out and painted in a single pass.

Async command execution: Commands run in goroutines. The page polls a result channel on each frame (select { case res := <-p.resultCh: ... default: }) and calls gtx.Execute(op.InvalidateCmd{}) to request repaints while loading.

TerminalLog: A thread-safe append-only log shared across all pages. The Terminal page displays it. Every command run anywhere in the app is recorded here.

PageView interface: Simple Layout(gtx, th) layout.Dimensions + Title() string. New pages can be added trivially.

genericPage: A reusable template for simple command pages (Volumes, Images, DNS, Caddy, Contexts). You declare CommandDef (label, mode, arg builder) and FieldDef (input fields per mode) and get a full page automatically.


Extending

To add a new command page:

  1. Implement the PageView interface or use newGenericPage()
  2. Add a new Page constant in app.go
  3. Register it in AppState.pages
  4. Add a nav item to NewSidebar() in sidebar.go

Example — adding a uc ps quick-view page:

// In page_generic.go or a new file:
func NewPsPage(r *runner.Runner, log *TerminalLog) PageView {
    cmds := []CommandDef{
        {Label: "List Containers", Mode: "ps", ArgsFunc: func(_ map[string]string) []string {
            return []string{"ps"}
        }},
    }
    return newGenericPage("Containers (ps)", r, log, cmds, nil)
}

License

MIT