Files

1534 lines
86 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 📋 PRD: tia — "Terminal Is A" My Way
> **Product Requirements Document**
> **Version:** 1.0.0-draft
> **Author:** oxpoe
> **Created:** 2026-10-15
> **Status:** Draft — Menunggu review & approval
---
## 1. Executive Summary
**tia** (Terminal Is A — my way) adalah aplikasi terminal yang dibangun dengan Go dan ekosistem Charm (charmbracelet), berfungsi sebagai all-in-one Docker management tool langsung dari terminal. tia menggabungkan kemampuan **management & convert dari Dockge** dengan **UI/UX elegance dari lazydocker**, diperkaya dengan audio feedback, animasi ASCII, dashboard beranda yang keren, serta utilitas pelengkap.
### Vision Statement & Tagline
```
"Satu binary untuk semua kebutuhan Docker kamu — Terminal Is A My Way"
Tagline: "Just Work"
```
### Kenapa tia?
- **Dockge** bagus tapi web-based — butuh browser, tidak cocok untuk server headless atau workflow terminal-native.
- **lazydocker** bagus tapi pakai library lama (gocui), tidak ada fitur konversi `docker run` → `compose`, dan manajemen stack terbatas.
- **tia** mengambil yang terbaik dari keduanya: **modern UI (Charm Bubble Tea v2)** + **manajemen stack lengkap** + **konverter cerdas** + **multi-host** + **audio & animasi ASCII** — semuanya dalam satu binary ringkas tanpa dependensi runtime rumit.
### Prinsip Produk: Satu Binary Multifungsi (TUI Utama + CLI Pendamping)
tia hadir sebagai **satu binary mandiri (single static binary)** yang fleksibel dengan filosofi **"Just Work"**:
1. **Pengalaman Utama = TUI Interaktif Penuh:**
Menjalankan `tia-love` tanpa argumen langsung meluncurkan TUI modern lengkap dengan dashboard keren (logo, jam digital ASCII), animasi dinamis, mouse support penuh, efek suara interaktif, dan notifikasi toast status.
2. **Mode CLI Pendamping (Scriptable & Headless):**
Untuk kebutuhan otomatisasi, CI/CD, atau perintah kilat tanpa membuka antarmuka TUI, binary yang sama dapat dipanggil dengan subcommand CLI (misal: `tia-love convert ...`, `tia-love ps`, `tia-love up <stack>`, `tia-love doctor`). Seluruh logika inti di-share dari `internal/core`, sehingga output dan perilakunya 100% konsisten.
3. **Instalasi Instan:**
Dapat diinstal dengan **1 baris perintah (`curl -fsSL ... | sh`)** atau cukup unduh binary Go precompiled secara manual dan langsung jalankan (`./tia-love`).
4. **Mouse & Keyboard Setara:**
Seluruh navigasi dan operasi di TUI ramah mouse (klik, drag, scroll, hover) maupun keyboard shortcut vim-like.
5. **Aset Bebas & Terbuka:**
Aset suara (CC0), palet warna (Catppuccin), dan animasi murni open-source serta tertanam (embedded) langsung di dalam binary.
---
## 2. Target Users
| User | Use Case |
|---|---|
| **Homelab enthusiast** | Manage Docker stacks di server rumah via SSH |
| **DevOps engineer** | Monitor & manage containers di production/staging |
| **Developer** | Quick convert docker run commands, manage dev containers |
| **Sysadmin** | Multi-host Docker management tanpa web UI overhead |
---
## 3. Technology Stack
| Component | Technology | Version | Alasan |
|---|---|---|---|
| **Language** | Go | 1.24+ | Performance, single binary, Docker SDK native |
| **TUI Framework** | Bubble Tea v2 | `charm.land/bubbletea/v2` | Elm Architecture, Cursed Renderer, modern |
| **UI Components** | Bubbles v2 | `charm.land/bubbles/v2` | List, Table, Viewport, TextInput, dll |
| **Styling** | Lip Gloss v2 | `charm.land/lipgloss/v2` | CSS-like styling, canvas layering |
| **Forms** | Huh v2 | `charm.land/huh/v2` | Interactive forms, setup wizard |
| **Markdown** | Glamour v2 | `charm.land/glamour/v2` | Help docs rendering |
| **Logging** | Charm Log v2 | `charm.land/log/v2` | Structured logging to file |
| **Docker** | Docker SDK for Go | `github.com/docker/docker/client` | Real-time events, stats, management |
| **Compose** | Docker Compose CLI | System binary | Compose operations (up/down/pull) |
| **YAML** | go-yaml v3 | `gopkg.in/yaml.v3` | Compose file parsing/writing |
| **Config** | go-yaml v3 | `gopkg.in/yaml.v3` | Baca/tulis config, diatur lewat layar Pengaturan di TUI (tanpa framework CLI) |
| **Audio Engine** | Oto v3 | `github.com/ebitengine/oto/v3` | Pure-Go audio player (`CGO_ENABLED=0`), PulseAudio/PipeWire/ALSA fallback |
| **Audio Assets** | Kenney Interface Sounds | CC0 1.0 Universal | Aset audio open-source tanpa royalti, WAV 44.1kHz mono embedded (<2MB) |
| **Animation Engine**| Harmonica | `github.com/charmbracelet/harmonica` (v0.2.0) | Fisika pegas (spring physics) & timer ticker 30 FPS untuk animasi TUI |
| **CLI Dispatcher** | Native Go Router | Go standard library | Router ringan untuk mode CLI pendamping (`tia-love convert`, `tia-love ps`, dll) |
### Docker Interaction Strategy: Hybrid
```
┌─────────────────────────────────────────────────────────────┐
│ tia Docker Layer │
├──────────────────────────┬──────────────────────────────────┤
│ Docker SDK for Go │ docker compose CLI │
│ (Real-time & Direct) │ (Compose Operations) │
├──────────────────────────┼──────────────────────────────────┤
│ • Container list/inspect │ • docker compose up -d │
│ • Image list/inspect │ • docker compose down │
│ • Volume list/inspect │ • docker compose pull │
│ • Network list/inspect │ • docker compose restart │
│ • Container stats stream │ • docker compose logs -f │
│ • Container logs stream │ • docker compose ps │
│ • Docker events stream │ • docker compose ls │
│ • Container start/stop │ • docker compose build │
│ • Container exec │ • docker compose config │
│ • Image pull/remove │ │
│ • System prune │ │
│ • Container update │ │
│ (resource limits) │ │
└──────────────────────────┴──────────────────────────────────┘
```
**Alasan hybrid:**
- Docker SDK lebih performant untuk real-time operations (events, stats, logs)
- Docker Compose CLI lebih reliable untuk compose operations — karena compose logic (variable interpolation, .env loading, service ordering, network creation) terlalu complex untuk di-reimplment via raw API
- Ini approach yang sama dengan Dockge dan lazydocker
---
## 4. Feature Requirements
### 4.1 Core Features (MVP — Phase 1 & 2)
#### F-001: Multi-Panel TUI Layout
- **Priority:** P0 (Must Have)
- **Description:** Layout 2 panel (sidebar + content) dengan responsive sizing, mirip lazydocker
- **Acceptance Criteria:**
- Sidebar (⅓ width) menampilkan: Stacks, Containers, Images, Volumes, Networks
- Content panel (⅔ width) menampilkan detail item yang dipilih
- Tab navigation di content panel (Logs, Stats, Config, Env, Top)
- Responsive saat terminal resize
- 3 screen modes: normal (33/67), half (50/50), fullscreen (100% content)
#### F-002: Container Management View
- **Priority:** P0
- **Description:** List dan inspect semua Docker containers
- **Acceptance Criteria:**
- List containers dengan status indicator (🟢 running, 🔴 stopped, 🟡 paused)
- Show: name, image, status, ports, uptime
- Real-time status update via Docker events
- Filter/search containers
#### F-003: Image, Volume, Network Views
- **Priority:** P0
- **Description:** Browse dan inspect Docker resources
- **Acceptance Criteria:**
- Images: repository, tag, size, created date, in-use status
- Volumes: name, driver, mountpoint, size
- Networks: name, driver, scope, subnet, attached containers
#### F-004: Real-time Log Viewer
- **Priority:** P0
- **Description:** Stream container/stack logs real-time
- **Acceptance Criteria:**
- Real-time log streaming dengan ANSI color support
- Scroll through history (viewport)
- Toggle timestamps on/off
- Search/filter dalam logs (`/`)
- Configurable tail lines (default 300)
#### F-005: Resource Stats & Graphs
- **Priority:** P0
- **Description:** Live CPU, Memory, Network, I/O stats dengan ASCII graphs
- **Acceptance Criteria:**
- CPU usage percentage + sparkline graph
- Memory usage (used/limit) + bar graph
- Network I/O (↑ upload, ↓ download rate)
- Disk I/O (read/write rate)
- PIDs count
- Update interval: 1 second
- ASCII sparkline characters: `▁▂▃▄▅▆▇█`
#### F-006: Vim-like Navigation & Keybindings
- **Priority:** P0
- **Description:** Keyboard-driven navigation
- **Keybinding Map:**
| Key | Scope | Action |
|---|---|---|
| `q` / `Ctrl+C` | Global | Quit |
| `?` | Global | Toggle help overlay |
| `Tab` / `Shift+Tab` | Global | Switch focus sidebar ↔ content |
| `j` / `↓` | List | Move down |
| `k` / `↑` | List | Move up |
| `Enter` | List | Select / Expand |
| `h` / `←` | Tabs | Previous tab |
| `l` / `→` | Tabs | Next tab |
| `[` / `]` | Tabs | Previous / Next tab |
| `/` | List | Search / Filter |
| `Esc` | Modal | Close modal / Cancel |
| `1-5` | Global | Jump to section |
| `+` / `_` | Global | Cycle screen mode |
#### F-022: Full Mouse Support (Mouse-Friendly)
- **Priority:** P0 (Must Have — berlaku sejak Phase 1, bukan fitur tambahan)
- **Description:** tia harus nyaman dipakai hanya dengan mouse, selevel dengan keyboard. Mouse bukan pelengkap, tapi cara interaksi utama yang setara.
- **Prinsip desain:**
1. **Parity:** semua aksi yang bisa dilakukan lewat keyboard juga bisa lewat mouse, dan sebaliknya
2. **Discoverable:** elemen klikable terlihat jelas (tombol berlabel, hover highlight, ikon)
3. **Non-destruktif:** aksi destruktif lewat mouse tetap lewat dialog konfirmasi
- **Interaksi mouse yang didukung:**
| Interaksi | Lokasi | Aksi |
|---|---|---|
| Klik kiri | Item di sidebar | Pilih item + tampilkan detail |
| Klik kiri | Header section sidebar (Stacks/Containers/…) | Expand / collapse section |
| Klik kiri | Tab (Logs/Stats/Config/…) | Pindah tab |
| Klik kiri | Panel (sidebar/content) | Pindah fokus ke panel tsb |
| Double-click | Item container/stack | Aksi default (buka detail/logs fullscreen) |
| Klik kanan | Item di list | Context menu (start/stop/restart/exec/remove/…) |
| Scroll wheel | List / log / YAML / inspector | Scroll konten (sesuai `mouse_scroll_lines`) |
| Scroll wheel | Tab bar | Ganti tab (opsional) |
| Klik + drag | Scrollbar | Scroll cepat |
| Klik + drag | Border antara sidebar & content | Resize lebar sidebar |
| Hover | Item / tombol / tab | Highlight + tooltip singkat (shortcut key) |
| Klik kiri | Tombol toolbar/status bar | Jalankan aksi (`▶ Start`, `■ Stop`, `↻ Restart`, `⌨ Exec`, `⟳ Update`, `🗑 Delete`, `⇄ Convert`) |
| Klik kiri | Hint di status bar (`[?] help`, `[q] quit`) | Jalankan aksi hint tersebut |
| Klik kiri | Checkbox di list | Multi-select untuk bulk action |
| Klik kiri | Tombol/field di modal & form | Fokus field, tekan tombol, pilih opsi |
- **Acceptance Criteria:**
- Seluruh alur utama dapat diselesaikan **tanpa menyentuh keyboard** (kecuali mengetik teks, mis. paste command ke converter)
- **Toolbar aksi klikable** muncul di atas content panel sesuai konteks item terpilih (container/stack/image/volume/network)
- Hover highlight pada list item, tab, dan tombol
- Klik kanan membuka context menu yang sama dengan keybinding `x`
- Sidebar bisa di-resize dengan drag (disimpan di config)
- Scroll wheel bekerja di semua area scrollable
- Mode **text select** (toggle `m`) untuk menonaktifkan mouse capture sementara agar bisa select & copy teks native terminal; tersedia juga tombol **Copy** + OSC52 clipboard di log/YAML viewer
- Mouse dapat dimatikan penuh via config (`mouse_enabled: false`) dan app tetap fungsional via keyboard
- Berfungsi di dalam tmux dan SSH session
- **Catatan implementasi (high level, tanpa kode):** Bubble Tea mendukung event klik, scroll, dan motion; hit-testing area klik dikelola oleh layout manager (setiap komponen mendaftarkan zona klikable-nya), sehingga perlu direncanakan dari Phase 1 agar tidak refactor besar di belakang.
#### F-023: Multi-Bahasa / i18n (Indonesia & English)
- **Priority:** P0 (berlaku sejak Phase 1)
- **Description:** Seluruh teks UI tersedia dalam **Bahasa Indonesia (default)** dan **English**. Bahasa dapat dipilih di setup wizard dan diubah kapan saja lewat config atau menu pengaturan, tanpa restart.
- **Acceptance Criteria:**
- Default bahasa: Indonesia (`language: id`); fallback otomatis ke English jika kunci terjemahan belum ada
- Katalog bahasa disimpan sebagai file YAML (`id.yaml`, `en.yaml`) dan di-embed ke dalam binary (tetap single binary)
- **Tidak ada string UI yang di-hardcode**: label, tombol, tab, dialog, pesan error, dan hint status bar semuanya lewat katalog
- Bahasa dipilih di langkah pertama wizard, dan bisa diganti lewat config (`ui.language`) atau menu pengaturan dengan efek langsung
- Bahasa dapat diganti kapan saja dari **layar Pengaturan** di dalam tia (lihat 5.1.5); tidak ada flag atau env var yang diperlukan
- Istilah teknis yang sudah umum **tidak diterjemahkan**: `Env`, `Image`, `Volume`, `Stack`, `Shell`, `CPU`, `RAM`, `PID`, `Log`
- Tidak diterjemahkan juga: output log container, nama flag docker, isi file YAML
- Lebar kolom/tombol tidak boleh rusak karena teks Indonesia lebih panjang (layout dihitung dari panjang teks, bukan lebar tetap)
- Struktur katalog mudah ditambah bahasa baru di masa depan (cukup tambah file `<kode>.yaml`)
- Pesan error dari Docker/CLI tetap ditampilkan asli, dengan penjelasan singkat berbahasa terpilih di atasnya
**Contoh pemetaan istilah:**
| Kunci | Indonesia | English |
|---|---|---|
| `section.stacks` | Stack | Stacks |
| `section.containers` | Kontainer | Containers |
| `section.networks` | Jaringan | Networks |
| `tab.logs` | Log | Logs |
| `tab.stats` | Statistik | Stats |
| `tab.config` | Konfigurasi | Config |
| `tab.processes` | Proses | Top |
| `action.start` | Mulai | Start |
| `action.stop` | Hentikan | Stop |
| `action.restart` | Mulai ulang | Restart |
| `action.pause` | Jeda | Pause |
| `action.remove` | Hapus | Remove |
| `action.update` | Perbarui | Update |
| `state.running` | berjalan | running |
| `state.stopped` | berhenti | stopped |
| `state.healthy` | sehat | healthy |
#### F-024: Audio Feedback & Sound Effects
- **Priority:** P0 (berlaku sejak Phase 1)
- **Description:** Setiap interaksi pengguna (klik mouse, navigasi keyboard, buka modal, dismiss, eksekusi perintah, notifikasi status) memberikan umpan balik suara yang menyenangkan dan memuaskan (*tactile feel*).
- **Interaksi & Kejadian Bersuara:**
- `click.wav`: Saat mengklik tombol toolbar, baris list, tab, atau checkbox.
- `navigate.wav`: Saat memindahkan kursor navigasi (`j`/`k` atau panah) di daftar.
- `modal_open.wav`: Saat modal dialog terbuka (konverter, prune, pengaturan).
- `modal_close.wav`: Saat modal ditutup atau dibatalkan.
- `notify_success.wav`: Saat operasi berhasil (stack running, konversi sukses, prune tuntas).
- `notify_warning.wav`: Saat muncul peringatan atau konfirmasi aksi destruktif (misal: hapus kontainer).
- `notify_error.wav`: Saat perintah gagal, koneksi daemon putus, atau syntax error.
- `exec.wav`: Saat memicu shell exec atau trigger rebuild.
- **Acceptance Criteria:**
- Menggunakan library audio pure-Go `github.com/ebitengine/oto/v3` (`CGO_ENABLED=0`), tanpa kompilasi CGO dan tanpa merusak sifat single binary mandiri.
- Seluruh aset audio bersumber dari lisensi terbuka **CC0 (Kenney Interface Sounds / UI Audio)**, dikonversi ke WAV (mono 44.1kHz, 16-bit), total ukuran < 2 MB, di-embed lewat `go:embed`.
- Inisialisasi audio asynchronous (tidak memperlambat waktu startup aplikasi < 500ms).
- Dilengkapi kontrol penuh di Layar Pengaturan:
- Toggle On/Off efek suara (`ui.sound_enabled: true/false`).
- Pengatur volume (0% - 100%).
- Mute otomatis jika mendeteksi sesi SSH (dengan opsi override aktif manual).
- Degradasi anggun (*graceful fallback*): jika mesin tidak memiliki audio driver/server aktif (misal container atau headless tanpa sound card), aplikasi tetap berjalan 100% normal tanpa panik/crash.
- Seluruh sinyal audio **selalu memiliki padanan visual** (toast, status badge, warna Catppuccin).
#### F-025: Top-Center Status Toast Notifications
- **Priority:** P0 (berlaku sejak Phase 1)
- **Description:** Setiap notifikasi status aplikasi muncul sebagai pop-up (toast) animasi elegan yang meluncur dari **tengah atas layar** (*top-center*), lengkap dengan status badge, ikon, dan deskripsi kejadian.
- **Kategori Status Notifikasi:**
1. `[ SUKSES ]` (Hijau/Green): Aksi berhasil (contoh: *Kontainer 'api' berhasil dimulai*, *Konversi docker run tersimpan ke ~/.tia/stacks/web*).
2. `[ PERINGATAN ]` (Kuning/Yellow): Butuh perhatian (contoh: *Penyimpanan Docker tersisa < 10%*, *Port 8080 bertabrakan*).
3. `[ GAGAL ]` (Merah/Red): Error/kegagalan (contoh: *Gagal menarik image nginx:latest - timeout*, *Docker daemon tidak merespons*).
4. `[ INFO ]` (Biru/Blue): Pemberitahuan informasional (contoh: *Host remote 'prod-srv' terhubung*, *Mode tema diubah ke Latte*).
- **Acceptance Criteria:**
- Posisi selalu berada di tengah atas viewport terminal (`x: center`, `y: 0` atau `y: 1`).
- Animasi transisi slide-in lembut saat muncul dan slide-out saat hilang.
- Dilengkapi auto-dismiss timer (default: 4 detik), durasi dapat dihentikan saat mouse di-hover di atasnya.
- Tombol tutup cepat (`✕`) yang bisa diklik mouse atau ditekan `Esc` untuk menutup seketika.
- Sistem antrean (*toast queue*): jika ada beberapa event masuk serentak, notifikasi diantrekan secara berurutan atau ditumpuk rapi tanpa menutupi layar kerja secara agresif.
- Mendukung klik langsung pada toast untuk menuju ke resource terkait (misal: klik toast error container -> langsung fokus ke container tersebut dan buka tab Log).
#### F-026: Animasi ASCII & Efek Visual Dinamis
- **Priority:** P0 (berlaku sejak Phase 1)
- **Description:** Menghadirkan animasi ASCII yang hidup, estetik, dan halus (*charming*) untuk memperkuat identitas TUI modern tanpa membebani CPU.
- **Elemen Animasi:**
1. **Splash Screen / Animated Logo:** Saat aplikasi start pertama kali atau membuka Beranda, logo ASCII `tia` muncul dengan efek ketikan/glitch/shimmer halus.
2. **Real-time Live Digital Clock:** Jam digital format ASCII dinamis yang berdetik setiap detik di pojok dashboard beranda.
3. **Pulsing Status Indicators:** Indikator titik status kontainer berkedip/bernapas lembut (pulsing `●`) untuk kontainer yang sedang dalam masa transisi (*starting*, *restarting*).
4. **Smooth Progress Bars & Spinners:** Visual progress bar pengunduhan image dan spinner elegan dari Charm saat memproses operasi latar belakang.
5. **Animated Sparklines:** Grafik telemetri CPU & Memory yang mengalir halus secara real-time.
- **Acceptance Criteria:**
- Framerate dibatasi maksimal 30 FPS untuk menjaga efisiensi daya dan CPU (< 3% idle CPU usage).
- Ditenagai oleh `github.com/charmbracelet/harmonica` (spring physics) untuk fisika transisi dan `tea.Tick` untuk timer event.
- Mode *Reduced Motion / Non-Animated*: opsi di layar Pengaturan untuk mematikan animasi bagi pengguna yang menginginkan tampilan statis atau berada di koneksi SSH dengan bandwidth sangat rendah.
#### F-027: Dashboard Beranda Keren (Home Dashboard View)
- **Priority:** P0 (berlaku sejak Phase 1)
- **Description:** Layar sambutan / beranda komprehensif yang menampilkan status menyeluruh ekosistem Docker lokal/remote, jam real-time, logo ASCII, serta pintasan aksi cepat.
- **Komponen Dashboard Beranda:**
- **Header Hero:** Seni ASCII Logo `tia` bertuliskan *Terminal Is A My Way* + Tagline *Just Work* dengan warna aksen Catppuccin.
- **Live Digital Clock Widget:** Jam digital ASCII besar (`HH:MM:SS`) beserta penanggalan lengkap dan zona waktu lokal.
- **Docker Engine Overview Card:** Versi Docker daemon, API version, status socket, total memory/CPU host, uptime.
- **Quick Resource Counters:** Kotak metrik ringkas: Total Stack (Aktif/Mati), Kontainer (Berjalan/Berhenti), Total Image, Volume, & Jaringan.
- **Quick Actions Launcher:** Tombol pintas klikable untuk aksi favorit: `[ ⇄ Konversi Baru ]`, `[ 🧹 Bersihkan Sistem ]`, `[ ➕ Buat Stack ]`, `[ ⚙ Pengaturan ]`, `[ 🌐 Ganti Host ]`.
- **Recent Activity Feed:** 5 peristiwa Docker terkini (kontainer baru start, image di-pull, error terakhir).
- **Acceptance Criteria:**
- Tampil saat aplikasi baru pertama kali dibuka, atau dapat diakses kapan saja dengan menekan `0` atau mengklik ikon Beranda di header.
- Seluruh kartu statistik dan tombol aksi dapat diklik dengan mouse.
- Tata letak responsif menyesuaikan ukuran jendela terminal.
#### F-028: Satu Binary Multifungsi & CLI Companion Mode
- **Priority:** P0 (arsitektur fondasi)
- **Description:** `tia-love` adalah satu file binary mandiri (single binary) yang multifungsi. Secara default `tia-love` membuka TUI interaktif penuh, namun dapat dipanggil langsung dari command line (CLI mode) untuk eksekusi skrip, CI/CD, atau konversi cepat tanpa membuka TUI.
- **Subcommand CLI Pendamping:**
- `tia-love`: Meluncurkan antarmuka TUI interaktif penuh.
- `tia-love convert [flags/command]`: Mengonversi perintah `docker run` menjadi compose YAML dan mencetaknya ke stdout atau menyimpannya langsung ke direktori stack (contoh: `tia-love convert "docker run -d -p 80:80 nginx"`).
- `tia-love ps`: Menampilkan ringkasan status semua stack & kontainer dalam format tabel rapi atau JSON (`--json`).
- `tia-love up <stack-name>`: Menjalankan stack di background tanpa membuka TUI.
- `tia-love down <stack-name>`: Menghentikan & menurunkan stack.
- `tia-love update <stack-name>`: Menarik image terbaru dan merefresh kontainer stack via CLI.
- `tia-love doctor`: Memeriksa kesehatan sistem (koneksi Docker daemon, ketersediaan sound server/driver, versi Go, direktori stack).
- `tia-love version` / `tia-love --version`: Menampilkan versi, commit git, dan build info.
- **Acceptance Criteria:**
- Berbagi basis kode logika inti yang sama di `internal/core`, menjamin kesamaan hasil antara eksekusi di TUI dan CLI.
- Kode keluar (*exit codes*) standar (0 = sukses, >0 = error) untuk integrasi skrip bash.
- Format output CLI mendukung `--json` untuk parsing oleh `jq` atau tool otomatisasi lainnya.
- Tetap terkompilasi sebagai satu binary statis tanpa ketergantungan library eksternal.
#### F-029: 1-Line Installer & Standalone Binary Distribution
- **Priority:** P0 (distribusi rilis)
- **Description:** Pengguna dapat memasang `tia-love` dalam hitungan detik menggunakan perintah instalasi satu baris (*one-line command*) otomatis, atau dengan mengunduh binary Go mandiri tanpa proses kompilasi manual.
- **Metode Instalasi:**
1. **One-Line Command (Rekomendasi):**
```bash
curl -fsSL https://gitea.oxpoe.qzz.io/oxpoe/tia-love/raw/branch/main/install.sh | sh
```
- Skrip otomatis mendeteksi OS (Linux, macOS) dan arsitektur CPU (`amd64`, `arm64`).
- Mengunduh rilis tarball terbaru dari Gitea Releases (gitea.oxpoe.qzz.io).
- Memverifikasi checksum SHA256 secara otomatis demi keamanan sebelum mengekstrak.
- Memasang binary ke direktori pengguna (`~/.local/bin/tia-love` tanpa memerlukan akses `sudo`).
- Memberikan instruksi jika `~/.local/bin` belum ada di `$PATH`.
2. **Manual Download Precompiled Binary:**
- Pengguna dapat langsung menuju halaman Releases di Gitea (https://gitea.oxpoe.qzz.io/oxpoe/tia-love/releases), mengunduh file binary terkompresi (misal: `tia-love_linux_amd64.tar.gz`), mengekstraknya, dan langsung menjalankannya (`./tia-love`).
3. **Go Install (untuk developer Go):**
```bash
go install gitea.oxpoe.qzz.io/oxpoe/tia-love/cmd/tia-love@latest
```
- **Acceptance Criteria:**
- Skrip instalasi aman (`set -euo pipefail`), transparan, dan tidak meminta privilege root/sudo secara membabi-buta.
- Rilis otomatis di-bundle via GoReleaser dengan SHA256 checksums file.
---
### 4.2 Stack Management & Converter (Phase 3)
#### F-007: Stacks Directory Management
- **Priority:** P0
- **Description:** Manage Docker Compose stacks dengan filesystem-based approach
- **Stacks Strategy:**
1. Saat setup pertama, user menentukan stacks directory (default: `~/.tia/stacks/`)
2. tia scan system untuk existing compose files (`docker compose ls --all`)
3. Existing stacks bisa di-copy/move ke stacks directory
4. Semua managed stacks ada dalam 1 folder yang ditentukan saat setup
- **Acceptance Criteria:**
- Setup wizard saat pertama run
- Scan dan discover existing compose stacks
- Import/migrate stacks ke managed directory
- Stack status: Active (🟢), Exited (🔴), Inactive (⚪)
- Stack CRUD: create, start, stop, restart, down, delete, update
#### F-008: Docker Run → Docker Compose Converter
- **Priority:** P0
- **Description:** Convert `docker run` commands menjadi `docker-compose.yml`
- **Supported docker run flags:**
| Flag | Compose Mapping |
|---|---|
| `--name` | `container_name` |
| `-p` / `--publish` | `ports` |
| `-v` / `--volume` | `volumes` |
| `--mount` | `volumes` (long syntax) |
| `-e` / `--env` | `environment` |
| `--env-file` | `env_file` |
| `--restart` | `restart` |
| `--network` | `networks` |
| `--memory` / `-m` | `deploy.resources.limits.memory` |
| `--cpus` | `deploy.resources.limits.cpus` |
| `-d` / `--detach` | (implied) |
| `--hostname` | `hostname` |
| `--entrypoint` | `entrypoint` |
| (trailing args) | `command` |
| `--user` / `-u` | `user` |
| `--workdir` / `-w` | `working_dir` |
| `--label` / `-l` | `labels` |
| `--cap-add` | `cap_add` |
| `--cap-drop` | `cap_drop` |
| `--privileged` | `privileged` |
| `--pid` | `pid` |
| `--dns` | `dns` |
| `--log-driver` | `logging.driver` |
| `--log-opt` | `logging.options` |
| `--tmpfs` | `tmpfs` |
| `--device` | `devices` |
| `--health-cmd` | `healthcheck.test` |
| `--health-interval` | `healthcheck.interval` |
| `--health-timeout` | `healthcheck.timeout` |
| `--health-retries` | `healthcheck.retries` |
| `--shm-size` | `shm_size` |
| `--init` | `init` |
| `--read-only` | `read_only` |
| `--stop-signal` | `stop_signal` |
| `--stop-grace-period` | `stop_grace_period` |
- **Acceptance Criteria:**
- Modal UI: paste docker run → preview YAML → edit → save as stack
- Support multi-line commands (backslash continuation)
- Handle quoted strings dan special characters
- Generate valid compose YAML
- Option: append to existing stack or create new
#### F-009: Compose YAML Editor
- **Priority:** P1 (Should Have)
- **Description:** View dan edit compose.yaml dari dalam tia
- **Acceptance Criteria:**
- YAML viewer dengan syntax highlighting (via glamour)
- **Editor YAML bawaan di dalam tia** (area teks multi-baris, syntax highlighting, nomor baris, validasi YAML live), bisa dioperasikan dengan keyboard dan mouse
- Tombol `[ Simpan ]`, `[ Batal ]`, dan `[ Validasi ]` yang bisa diklik
- Editor eksternal bersifat **opsional** (vim/nano/helix lewat pengaturan): TUI di-suspend sementara lalu kembali otomatis
- Editor `.env` dengan cara yang sama (bawaan di tia)
- Compose validation (`docker compose config`)
#### F-010: Stack Update
- **Priority:** P0
- **Description:** Update stack (pull latest images + recreate containers)
- **Acceptance Criteria:**
- Pull latest images untuk semua services in stack
- Recreate containers dengan images baru
- Show progress (pull progress, recreating status)
- Option: update single service atau seluruh stack
---
### 4.3 Container Actions (Phase 4)
#### F-011: Container Exec (Shell)
- **Priority:** P0
- **Description:** Exec shell into running container
- **Acceptance Criteria:**
- Suspend TUI → attach ke container shell → resume TUI saat exit
- Auto-detect shell (`/bin/bash`, `/bin/sh`, `/bin/ash`)
- Menggunakan `tea.ExecProcess()` untuk clean suspension
- Keybinding: `e` pada container yang dipilih
#### F-012: Container Lifecycle Actions
- **Priority:** P0
- **Description:** Full container lifecycle management
- **Acceptance Criteria:**
- Start, Stop, Restart, Pause, Unpause, Remove, Rename
- Confirmation dialog untuk destructive actions (remove)
- Bulk actions: select multiple → apply action
- Context menu (`x`) untuk semua available actions
#### F-013: Bulk Operations
- **Priority:** P1
- **Description:** Batch operations pada multiple resources
- **Acceptance Criteria:**
- Select multiple containers/images/volumes
- Apply: stop all, remove all, restart all
- Confirmation with summary sebelum execute
---
### 4.4 Advanced Features (Phase 5)
#### F-014: System Prune
- **Priority:** P1
- **Description:** Cleanup unused Docker resources
- **Acceptance Criteria:**
- Interactive prune dialog
- Preview: reclaimable space per category
- Categories: stopped containers, dangling images, unused images, unused volumes, unused networks, build cache
- Selective prune (pilih kategori)
- Summary setelah prune (space reclaimed)
#### F-015: Container Health Check Monitor
- **Priority:** P1
- **Description:** Monitor container health checks
- **Acceptance Criteria:**
- Health status indicators: 🟢 healthy, 🟡 starting, 🔴 unhealthy, ⚪ none
- Health check command, interval, timeout, retries
- Health check log history
- Alert/highlight unhealthy containers
#### F-016: Resource Limits Editor
- **Priority:** P2 (Nice to Have)
- **Description:** Edit container resource limits on-the-fly
- **Acceptance Criteria:**
- Form (via huh) untuk set/modify: memory limit, CPU limit, pids limit
- Uses Docker SDK `ContainerUpdate()`
- Show current vs new values
#### F-017: Dockerfile Builder/Editor
- **Priority:** P2
- **Description:** Basic Dockerfile template editor
- **Acceptance Criteria:**
- Dockerfile templates (FROM, RUN, COPY, EXPOSE, CMD, etc.)
- Editor Dockerfile bawaan di dalam tia (opsional: buka di editor eksternal lalu kembali ke TUI)
- Build integration: `docker build` dari dalam tia
- Build progress streaming
#### F-018: Docker Registry Browser
- **Priority:** P2
- **Description:** Browse Docker Hub dan search images
- **Acceptance Criteria:**
- Search images on Docker Hub (via Registry HTTP API v2)
- View available tags
- Pull image langsung dari browser
- Show image description, stars, pulls
#### F-019: Export/Import Stacks
- **Priority:** P1
- **Description:** Export dan import compose stacks
- **Acceptance Criteria:**
- Export: pack `compose.yaml` + `.env` + configs → `.tar.gz`
- Import: extract archive → create stack in stacks directory
- Portable format
#### F-020: Volume Backup & Restore
- **Priority:** P1
- **Description:** Backup dan restore named Docker volumes
- **Acceptance Criteria:**
- Backup: volume → `.tar.gz` (via temporary alpine container)
- Restore: `.tar.gz` → volume
- Backup strategy:
```
docker run --rm -v <volume>:/data -v <backup-dir>:/backup alpine \
tar czf /backup/<volume>-<timestamp>.tar.gz -C /data .
```
- List available backups
- Selective restore
---
### 4.5 Multi-Host Support (Phase 6)
#### F-021: Multi-Host Docker Management
- **Priority:** P1
- **Description:** Manage Docker pada multiple remote servers via SSH
- **Acceptance Criteria:**
- Add/remove/edit remote hosts
- SSH tunnel ke remote Docker socket
- Host selector di sidebar (switch antar hosts)
- Semua fitur bekerja di remote host (containers, stacks, images, etc.)
- Host config: name, address, SSH key path, port, user
- Connection status indicator per host
- Config persistence di `~/.config/tia/hosts.yaml`
---
## 5. UI/UX Design
### 5.1.0 Layar Beranda (Home Dashboard View) — Jam Digital ASCII, Metrik & Pintasan
Layar pembuka interaktif yang menampilkan identitas keren `tia` ("Terminal Is A My Way" - Tagline: "Just Work"), jam digital ASCII dinamis, status ringkas ekosistem Docker, dan pintasan aksi cepat:
```
┌──────────────────────────────────────────────────────────────────────────────┐
│ ▓ tia · terminal is a Tagline: Just Work ● lokal ▾ │
├──────────────────────────────────────────────────────────────────────────────┤
│ _ _ │
│ | |_(_) __ _ ╔╦╗╦╔═╗ Terminal Is A My Way ┌─── JAM LOKAL ────┐ │
│ | __| |/ _` | ║ ║╠═╣ v0.1.0 (Catppuccin Mocha) │ ██ █▀█ █ █ █▀█ │ │
│ |_| |_|\__,_| ╩ ╩╩ ╩ Engine: Docker 27.2.0 (API 1.47│ ██ █▄█ █▀█ █▄█ │ │
│ │ WIB (UTC+7) │ │
│ ┌─ STATUS EKOSISTEM DOCKER ─────────────────────────┐ │ 15 Okt 2026 │ │
│ │ 📦 Stacks : 3 Total (● 2 Aktif, ○ 1 Berhenti) │ └──────────────────┘ │
│ │ 🐳 Kontainer : 8 Total (● 5 Berjalan, ○ 3 Mati) │ │
│ │ 🖼️ Image : 14 Buah (1.42 GB digunakan) │ ┌─ RESOURCE HOST ───┐ │
│ │ 💾 Volume : 6 Buah (340 MB) │ │ CPU : [███░░] 28% │ │
│ │ 🌐 Jaringan : 4 Jaringan (bridge, host, app-net) │ │ RAM : 4.2G/16G │ │
│ └───────────────────────────────────────────────────┘ └───────────────────┘ │
│ │
│ ┌─ PINTASAN AKSI CEPAT (Klik mouse atau tekan shortcut) ───────────────────┐ │
│ │ [ ⇄ Konversi (c) ] [ ➕ Stack Baru (n) ] [ 🧹 Prune (P) ] [ ⚙ Set (,) ]│ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─ AKTIVITAS TERKINI (Log Event Docker) ───────────────────────────────────┐ │
│ │ 05:42:10 [kontainer] 'api' health status: healthy │ │
│ │ 05:40:02 [stack] 'web-app' diperbarui (pull image sukses) │ │
│ │ 05:38:15 [image] 'postgres:16-alpine' di-pull selesai │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
├──────────────────────────────────────────────────────────────────────────────┤
│ [Enter] Masuk Workspace [0] Beranda [?] Bantuan [q] Keluar │
└──────────────────────────────────────────────────────────────────────────────┘
```
### 5.1 Workspace Utama (Resource Management & Inspection)
> Bahasa UI default: **Indonesia** (opsi English, lihat F-023). Istilah teknis (`Env`, `Image`, `Volume`, `Stack`, `Shell`) tidak diterjemahkan. Pesan log container ditampilkan apa adanya.
```
┌──────────────────────────────────────────────────────────────────────────────┐
│ ▓ tia · terminal is a ● lokal ▾ v0.1.0 │
├──────────────────────┬───────────────────────────────────────────────────────┤
│ ▾ Stack (3) │ [Log] Statistik Konfigurasi Env Proses │
│ ● web-app │ [■ Berhenti] [↻ Mulai Ulang] [⌨ Shell] [⏸ Jeda] │
│ ● database │ ───────────────────────────────────────────────────── │
│ ○ redis │ 05:17:08 INFO Starting server... │
│ ▾ Kontainer (5) │ 05:17:09 INFO Listening on :8080 │
│ ● nginx │ 05:17:10 INFO DB connected │
│ ▶ ● api │ 05:17:11 WARN Cache miss rate 40% │
│ ● postgres │ 05:17:12 INFO GET /health 200 2ms │
│ ● worker │ 05:17:13 ERRO timeout: redis:6379 │
│ ○ redis │ 05:17:14 INFO retrying (1/3)... │
│ ▸ Image (12) │ 05:17:15 INFO redis reconnected │
│ ▸ Volume (8) │ │
│ ▸ Jaringan (4) │ │
├──────────────────────┴───────────────────────────────────────────────────────┤
│ [?]bantuan [c]konversi [n]baru [P]bersihkan [m]pilih-teks [/]cari [q]keluar │
└──────────────────────────────────────────────────────────────────────────────┘
baris ter-highlight = terpilih ● berjalan ○ berhenti ▾/▸ = buka/tutup bagian
Mouse: klik item/tab/tombol · klik kanan = menu · scroll · seret batas = ubah lebar
Semua elemen [..] di toolbar & status bar bisa diklik.
```
### 5.1.1 Tab Statistik
```
┌────────────────────────────────────────────────────────────┐
│ Log [Statistik] Konfigurasi Env Proses │
│ │
│ CPU ████████░░░░░░░░░░░░ 45.2% │
│ RAM ██████░░░░░░░░░░░░░░ 312M / 1.0G │
│ │
│ Riwayat CPU (60 dtk) │
│ ▁▂▃▄▅▆▇█▇▆▅▄▃▂▁▂▃▄▅▆▇▆▅▄▃▂▁▁▂▃ │
│ │
│ NET ↑ 1.2 MB/s ↓ 340 KB/s │
│ Disk Baca 2.1 MB/s Tulis 890 KB/s │
│ PIDs 24 │
└────────────────────────────────────────────────────────────┘
```
### 5.1.2 Detail Stack
```
┌────────────────────────────────────────────────────────────┐
│ [Layanan] Konfigurasi Env Log │
│ [▶ Jalankan] [■ Henti] [↻ Ulang] [⟳ Perbarui] [✎ Edit] │
│ ────────────────────────────────────────────────────────── │
│ LAYANAN IMAGE STATUS PORT │
│ web nginx:1.27 ● berjalan 8080→80 │
│ app myapp:latest ● berjalan 3000→3000 │
│ db postgres:16 ● sehat 5432 │
│ cache redis:7 ○ berhenti - │
│ │
│ Pembaruan terakhir: 2 hari lalu Tersedia update: 2 │
└────────────────────────────────────────────────────────────┘
```
### 5.1.3 Modal Konversi `docker run` → compose
```
┌────────────────────────────────────────────────────────────┐
│ ⇄ Konversi docker run → compose ✕ │
├────────────────────────────────────────────────────────────┤
│ Tempel perintah docker run: │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ docker run -d --name web -p 8080:80 \ │ │
│ │ -v ./html:/usr/share/nginx/html:ro \ │ │
│ │ -e TZ=Asia/Jakarta --restart unless-stopped \ │ │
│ │ nginx:latest │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ Pratinjau (compose.yaml): │
│ │ services: │ │
│ │ web: │ │
│ │ image: nginx:latest │ │
│ │ container_name: web │ │
│ │ ports: ["8080:80"] │ │
│ │ volumes: ["./html:/usr/share/nginx/html:ro"] │ │
│ │ environment: [TZ=Asia/Jakarta] │ │
│ │ restart: unless-stopped │ │
│ │
│ Simpan: (•) Stack baru [ web ] ( ) Tambah │
│ │
│ [ Salin YAML ] [ Simpan & Jalankan ] [ Batal ] │
└────────────────────────────────────────────────────────────┘
```
### 5.1.4 Menu Klik Kanan & Dialog Konfirmasi
```
┌────────────────────────┐ ┌────────────────────────────────────────┐
│ ▶ Mulai │ │ Hapus kontainer? │
│ ■ Hentikan │ │ │
│ ↻ Mulai ulang │ │ Kontainer "api" akan dihapus. │
│ ⏸ Jeda │ │ Volume tetap disimpan. │
│ ⌨ Buka shell │ │ │
│ ≣ Lihat log │ │ [ Hapus ] [ Batal ] │
│ ⟳ Perbarui image │ └────────────────────────────────────────┘
│ ✎ Ganti nama │
├────────────────────────┤
│ ✕ Hapus │
└────────────────────────┘
```
### 5.1.5 Layar Pengaturan (dibuka dengan `,` atau menu ⚙ di header)
Semua pengaturan diubah **dari dalam tia**, tanpa flag CLI, env var, atau edit file manual. Perubahan bahasa, tema, suara, dan animasi langsung berlaku seketika.
```
┌────────────────────────────────────────────────────────────┐
│ ⚙ Pengaturan ✕ │
├────────────────────────────────────────────────────────────┤
│ Bahasa [ Indonesia ▾ ] │
│ Mode tema [ Otomatis ▾ ] │
│ Warna aksen [ mauve ▾ ] │
│ Direktori stack [ ~/.tia/stacks ] │
│ │
│ [x] Efek suara interaktif (klik, modal, alert, notif) │
│ Volume audio [ ████████░░ 80% ] │
│ [x] Mute suara otomatis saat koneksi SSH │
│ [x] Animasi ASCII dinamis (logo shimmer, clock, 30 FPS) │
│ [x] Tampilkan timestamp log │
│ [x] Aktifkan navigasi mouse │
│ [x] Efek hover highlight mouse │
│ │
│ Perubahan berlaku langsung tanpa restart. │
│ │
│ [ Simpan ] [ Batal ] │
└────────────────────────────────────────────────────────────┘
```
### 5.1.6 Notifikasi Toast Melayang (Top-Center Status Popup)
Notifikasi status meluncur halus dari **tengah atas layar** (*top-center*), lengkap dengan status badge berwarna Catppuccin, ikon, deskripsi peristiwa, dan tombol tutup cepat `✕`:
```
┌────────────────────────────────────────────────────────┐
│ ✔ [ SUKSES ] Konversi Berhasil Disimpan ✕│
│ Stack 'web-app' tersimpan di ~/.tia/stacks/web-app/ │
└────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────┐
│ ⚠ [ PERINGATAN ] Port 8080 Bentrok ✕│
│ Kontainer 'nginx' gagal bind port: sudah dipakai 'api' │
└────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────┐
│ ✖ [ GAGAL ] Docker Daemon Putus ✕│
│ Gagal menghubungi /var/run/docker.sock - periksa servis│
└────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────┐
│ ℹ [ INFO ] Host Remote Terhubung ✕│
│ Berhasil membuka SSH tunnel ke node 'prod-server-01' │
└────────────────────────────────────────────────────────┘
```
> Setup wizard pertama kali ada di bagian 7.3.
### 5.2 Detail Tabs per Resource
| Sidebar Section | Available Tabs | Content |
|---|---|---|
| **Stacks** | Logs, Services, Config, Env | Stack logs, service list, compose.yaml, .env |
| **Containers** | Logs, Stats, Config, Env, Top | Container logs, resource stats, inspect JSON, env vars, processes |
| **Images** | Config, Layers | Image inspect, Dockerfile layers/history |
| **Volumes** | Config | Volume inspect, mountpoint, driver |
| **Networks** | Config | Network inspect, IPAM, attached containers |
### 5.3 Modal System
Modals digunakan untuk:
- **Confirm Dialog:** Destructive actions (delete, prune, remove)
- **Input Dialog:** Search, filter, rename
- **Form Dialog:** Stack creation wizard, resource limits editor, host config (via huh)
- **Converter Dialog:** docker run → compose converter
- **Help Overlay:** Full keybinding reference
**Mouse pada modal:** semua modal punya tombol klikable (`[ OK ]`, `[ Cancel ]`, `[ Save ]`), tombol close `✕` di pojok, klik di luar modal = tutup (kecuali form yang belum disimpan → minta konfirmasi), field form bisa difokuskan dengan klik, dan list/select bisa dipilih dengan klik.
### 5.4 Theme System: Catppuccin
**Keputusan:** tia memakai **Catppuccin** sebagai satu-satunya tema bawaan (v1). Tema lain (Dracula, Tokyo Night, dll.) tidak masuk v1.
#### Mode tema
| Mode | Perilaku |
|---|---|
| `auto` (default) | Deteksi background terminal saat start → **Mocha** (gelap) atau **Latte** (terang) |
| `dark` | Paksa **Catppuccin Mocha** |
| `light` | Paksa **Catppuccin Latte** |
| `terminal` | Pakai **palet ANSI terminal pengguna** (16 warna) agar tia otomatis serasi dengan tema terminal yang sudah dipakai |
- Mode bisa diganti saat runtime lewat menu pengaturan atau keybinding (tanpa restart)
- Mode diganti lewat **layar Pengaturan** di dalam tia, atau tombol cepat `T` untuk berganti mode (Otomatis → Gelap → Terang → Terminal)
- Warna **aksen** dapat dipilih (default `mauve`), mengikuti 14 warna aksen Catppuccin
#### Arsitektur warna: token semantik
Komponen UI **tidak boleh memakai kode warna langsung**. Semuanya lewat token semantik yang dipetakan ke palet aktif, supaya ganti mode tidak mengubah komponen apa pun:
| Token | Dipakai untuk | Mocha (gelap) | Latte (terang) |
|---|---|---|---|
| `base` | Background utama | Base | Base |
| `surface` | Panel, modal, toolbar | Surface0 | Surface0 |
| `overlay` | Border, separator | Overlay0 | Overlay0 |
| `text` | Teks utama | Text | Text |
| `subtext` | Teks sekunder, hint | Subtext0 | Subtext0 |
| `accent` | Fokus, tab aktif, item terpilih | Mauve (default) | Mauve (default) |
| `success` | ● berjalan, sehat | Green | Green |
| `warning` | ⏸ jeda, WARN, memulai | Yellow | Yellow |
| `danger` | ○ berhenti, ERRO, unhealthy, tombol Hapus | Red | Red |
| `info` | INFO, link, port | Blue | Blue |
| `hover` | Highlight saat mouse hover | Surface1 | Surface1 |
| `selection` | Item terpilih | Surface2 | Surface2 |
#### Mode `terminal`
- Token dipetakan ke warna ANSI terminal (mis. `success` → ANSI hijau, `danger` → ANSI merah, `accent` → ANSI magenta)
- Background tidak diubah (memakai background terminal), hanya warna foreground dan aksen
- Cocok untuk pengguna yang sudah memasang Catppuccin (atau tema lain) di terminal mereka
#### Acceptance Criteria
- Semua komponen (sidebar, tab, toolbar, log, grafik, modal, menu, wizard) terbaca jelas di Mocha, Latte, dan mode terminal
- Kontras teks memenuhi keterbacaan (tidak ada teks pudar di Latte)
- Level log berwarna: `INFO`=info, `WARN`=warning, `ERRO`=danger
- Grafik CPU/RAM berubah warna sesuai beban: hijau (<60%), kuning (60–85%), merah (>85%)
- Fallback otomatis ke 256/16 warna jika terminal tidak mendukung truecolor
- Jika deteksi background gagal, `auto` jatuh ke Mocha (gelap)
- Ganti mode saat runtime langsung berlaku tanpa restart
- Mode `terminal` tetap terbaca di terminal dengan palet apa pun
> **Catatan:** Catppuccin juga punya flavor Frappé dan Macchiato (gelap menengah). Tidak masuk v1, bisa ditambahkan nanti hanya dengan menambah palet karena arsitektur token sudah siap.
---
## 6. Architecture
### 6.1 High-Level Architecture
```mermaid
graph TD
subgraph "tia Binary"
A[main.go] --> C[Bubble Tea Program]
subgraph "UI Layer"
C --> D[Root Model]
D --> D1[Sidebar Panel]
D --> D2[Content Panel]
D --> D3[Status Bar]
D --> D4[Modal Stack]
end
subgraph "Service Layer"
E[Docker Service] --> E1[Container Ops]
E --> E2[Image Ops]
E --> E3[Volume Ops]
E --> E4[Network Ops]
E --> E5[Stats Collector]
E --> E6[Events Listener]
F[Stack Service] --> F1[Stack Manager]
F --> F2[Stack Scanner]
F --> F3[Converter]
G[Config Service] --> G1[Setup Wizard]
G --> G2[Config Manager]
G --> G3[Theme Manager]
end
subgraph "Docker Layer"
H["Docker SDK Client"] --> H1["Container API"]
H --> H2["Image API"]
H --> H3["System API"]
I["docker compose CLI"] --> I1["Compose Ops"]
end
D --> E
D --> F
D --> G
E --> H
F --> I
end
subgraph "External"
J[Docker Daemon]
K[Docker Hub Registry]
L["Remote Host (SSH)"]
end
H --> J
I --> J
E2 --> K
L --> J
```
### 6.2 Project Structure
```
tia/
├── cmd/
│ └── tia-love/
│ └── main.go # Entry point (Router TUI default vs CLI companion)
├── internal/
│ ├── app/
│ │ ├── app.go # Root bubbletea Model
│ │ ├── keymap.go # Global keybindings
│ │ └── messages.go # Custom tea.Msg types
│ ├── cli/ # Mode CLI pendamping (single binary)
│ │ ├── root.go # CLI argument parser & dispatcher
│ │ ├── convert.go # 'tia-love convert' command
│ │ ├── ps.go # 'tia-love ps' list stacks & containers
│ │ ├── stack.go # 'tia-love up / down / update' commands
│ │ └── doctor.go # 'tia-love doctor' diagnostic check
│ ├── audio/ # Audio feedback engine (Pure Go, Oto v3)
│ │ ├── player.go # Audio context & sound player
│ │ ├── sounds.go # Sound event definitions & mapping
│ │ └── assets/ # Embedded CC0 WAV sound files (<2MB)
│ │ ├── click.wav
│ │ ├── modal_open.wav
│ │ ├── modal_close.wav
│ │ ├── success.wav
│ │ ├── warning.wav
│ │ └── error.wav
│ ├── ui/
│ │ ├── animation/ # ASCII animation & spring physics
│ │ │ ├── ticker.go # 30 FPS render loop controller
│ │ │ ├── clock.go # Real-time ASCII digital clock generator
│ │ │ └── logo.go # Shimmer / typing ASCII logo banner
│ │ ├── layout/
│ │ │ ├── layout.go # Multi-panel layout manager
│ │ │ ├── sidebar.go # Left sidebar panel
│ │ │ └── content.go # Right content panel
│ │ ├── views/
│ │ │ └── home.go # Home Dashboard (logo, jam ASCII, metrik, aktivitas)
│ │ ├── components/
│ │ │ ├── toast.go # Top-Center floating notification popup
│ │ │ ├── statusbar.go # Bottom status/help bar
│ │ │ ├── tabbar.go # Tab navigation
│ │ │ ├── logview.go # Real-time log viewer
│ │ │ ├── statsview.go # CPU/Memory stats with graphs
│ │ │ ├── inspector.go # JSON inspector
│ │ │ ├── processview.go # Container processes (top)
│ │ │ ├── envview.go # Environment variables
│ │ │ ├── yamlview.go # YAML editor/viewer
│ │ │ ├── converter.go # docker run → compose UI
│ │ │ ├── healthview.go # Health check monitor
│ │ │ └── registry.go # Registry browser
│ │ ├── modal/
│ │ │ ├── modal.go # Modal dialog base
│ │ │ ├── confirm.go # Confirmation dialog
│ │ │ ├── input.go # Text input dialog
│ │ │ ├── form.go # Multi-field form (huh)
│ │ │ ├── prune.go # Prune dialog
│ │ │ └── resources.go # Resource limits editor
│ │ └── theme/
│ │ ├── theme.go # Theme manager & token semantik (bg, fg, accent, success, ...)
│ │ ├── catppuccin.go # Palet Catppuccin: Mocha (gelap) & Latte (terang)
│ │ ├── detect.go # Deteksi background terminal (gelap/terang)
│ │ └── ansi.go # Mode "terminal": pakai palet ANSI terminal pengguna
│ ├── docker/
│ │ ├── client.go # Docker SDK client wrapper
│ │ ├── container.go # Container CRUD + lifecycle
│ │ ├── image.go # Image operations
│ │ ├── volume.go # Volume operations
│ │ ├── network.go # Network operations
│ │ ├── compose.go # docker compose CLI wrapper
│ │ ├── stats.go # Stats streaming
│ │ ├── events.go # Events listener
│ │ ├── exec.go # Container exec
│ │ ├── prune.go # System/resource prune
│ │ ├── backup.go # Volume backup/restore
│ │ └── registry.go # Docker Hub API client
│ ├── stack/
│ │ ├── manager.go # Stack CRUD
│ │ ├── scanner.go # Filesystem scanner
│ │ ├── converter.go # docker run → compose parser
│ │ ├── export.go # Stack export/import
│ │ └── types.go # Stack data types
│ ├── i18n/
│ │ ├── i18n.go # Loader & fungsi terjemahan T("key")
│ │ └── locales/
│ │ ├── id.yaml # Katalog Bahasa Indonesia (default)
│ │ └── en.yaml # Katalog English (fallback)
│ ├── config/
│ │ ├── config.go # Config load/save
│ │ ├── setup.go # First-run setup wizard
│ │ ├── hosts.go # Multi-host config
│ │ └── types.go # Config structs
│ └── host/
│ ├── manager.go # Multi-host manager
│ ├── ssh.go # SSH tunnel
│ └── types.go # Host types
├── install.sh # One-line installer script
├── docs/
│ ├── PRD.md # This document
│ ├── ASSETS.md # Open-source assets register
│ └── rea/ # Reverse Engineering & Analysis reports
├── go.mod
├── go.sum
├── Makefile
├── README.md
├── LICENSE
└── .goreleaser.yml # Release automation
```
### 6.3 Key Design Patterns
#### Elm Architecture (The Elm Architecture / TEA)
```go
// Setiap komponen implement tea.Model
type Model interface {
Init() tea.Cmd
Update(tea.Msg) (tea.Model, tea.Cmd)
View() string
}
```
#### Message-Driven Communication
```go
// Contoh message types
type ContainerListMsg []docker.Container
type ContainerStatsMsg docker.Stats
type LogLineMsg string
type DockerEventMsg docker.Event
type StackStatusMsg stack.Status
type ErrorMsg error
```
#### Composable Components
```
Root Model
├── Sidebar Model (bubbles/list)
│ ├── Stacks List
│ ├── Containers List
│ ├── Images List
│ ├── Volumes List
│ └── Networks List
├── Content Model
│ ├── TabBar Model
│ ├── LogView Model (bubbles/viewport)
│ ├── StatsView Model
│ ├── Inspector Model (bubbles/viewport)
│ └── ProcessView Model (bubbles/table)
├── StatusBar Model (bubbles/help)
└── Modal Stack
├── Confirm Model
├── Form Model (huh)
└── Converter Model
```
---
## 7. Configuration
### 7.1 Config File Location
```
~/.config/tia/config.yaml
```
### 7.2 Config Schema
```yaml
# tia configuration
version: 1
# Stacks directory — all managed compose stacks live here
stacks_dir: ~/.tia/stacks
# UI preferences
ui:
language: id # id (Indonesia) | en (English); default: id, fallback: en
theme: catppuccin # satu-satunya tema bawaan (v1)
theme_mode: auto # auto | dark | light | terminal
# auto = deteksi background terminal -> Mocha (gelap) / Latte (terang)
# dark = Catppuccin Mocha
# light = Catppuccin Latte
# terminal = pakai palet ANSI terminal pengguna (ikut tema terminal)
theme_accent: mauve # warna aksen: rosewater|flamingo|pink|mauve|red|maroon|peach|yellow|green|teal|sky|sapphire|blue|lavender
sidebar_width: 0.33 # sidebar width ratio (0.2 - 0.5)
show_timestamps: true # show timestamps in logs
log_tail_lines: 300 # default number of log lines to tail
stats_interval: 1s # stats refresh interval
mouse_enabled: true # enable mouse support (click, scroll, drag, hover)
mouse_hover: true # hover highlight pada item/tombol/tab
mouse_scroll_lines: 3 # jumlah baris per scroll wheel tick
double_click_ms: 400 # interval double-click (ms)
show_action_buttons: true # tampilkan tombol aksi klikable di toolbar
# Audio & Sound Effects
sound_enabled: true # aktifkan efek suara (klik, popup notif, alert, modal)
sound_volume: 70 # volume suara (0 - 100)
sound_mute_on_ssh: true # otomatis senyapkan (mute) suara bila berjalan di sesi SSH
# Animasi & Visual Dinamis
animation_enabled: true # aktifkan animasi (splash shimmer, pulse indicator, ticker)
animation_fps: 30 # frame per second maksimum untuk animasi (default: 30 FPS)
# Editor
editor:
mode: builtin # builtin (editor di dalam tia) | external (suspend TUI, buka editor luar)
external_command: "" # kosong = pakai $EDITOR, fallback vim/nano (dipakai hanya jika mode: external)
# Docker
docker:
socket: unix:///var/run/docker.sock
compose_command: docker compose # or docker-compose for legacy
# Hosts (multi-host)
hosts:
- name: local
type: local
default: true
# - name: production
# type: ssh
# address: user@192.168.1.100
# port: 22
# key: ~/.ssh/id_rsa
# Keybinding overrides (optional)
# keybindings:
# quit: q
# help: "?"
```
### 7.3 First-Run Setup Wizard
Langkah wizard: **Bahasa → Direktori stack → Tema → Impor stack yang ditemukan.** Bahasa dipilih di langkah pertama (default: Indonesia) dan langsung diterapkan ke langkah berikutnya.
```
┌────────────────────────────────────────────────────────────┐
│ Selamat datang di tia! Mari kita atur dulu. │
│ │
│ Bahasa / Language: (•) Indonesia ( ) English │
│ │
│ Direktori stack: │
│ [ ~/.tia/stacks ] │
│ │
│ Tema: (•) Otomatis ( ) Gelap ( ) Terang ( ) Terminal │
│ │
│ Ditemukan 4 stack compose yang ada: │
│ [x] /opt/stacks/nginx │
│ [x] /opt/stacks/postgres │
│ [x] /home/oxpoe/projects/api │
│ [ ] /tmp/test-stack │
│ │
│ Mode impor: (•) Salin ( ) Pindah ( ) Symlink │
│ │
│ [ Kembali ] [ Selesai ] │
└────────────────────────────────────────────────────────────┘
```
---
## 8. Implementation Roadmap
### Phase 0: Riset, Spike & Fondasi Proses (Week 0-1)
> **Goal:** Mengunci keputusan berisiko sebelum membangun UI
| Deliverable | Description |
|---|---|
| **Spike audio** | Buktikan suara bisa diputar dari binary `CGO_ENABLED=0` (Oto v3) di Linux (PulseAudio/PipeWire/ALSA) & macOS; ukur latensi; uji fallback saat tanpa audio device |
| **Spike animasi** | Prototipe animasi ASCII 30 FPS + toast slide-in; ukur CPU idle |
| REA skill | Buat skill REA + template laporan; jalankan REA modul 1 (composerize) sebagai uji coba alur |
| Register aset | `docs/ASSETS.md`, `THIRD_PARTY_NOTICES`; pilih dan unduh aset suara CC0 (Kenney), konversi ke WAV |
| Keputusan lisensi | Tetapkan lisensi tia (rekomendasi MIT) |
| Repo & CI | Struktur repo, lint, test, goreleaser (dry run) |
**Exit Criteria:** Spike audio & animasi lolos target, REA terbukti jalan, aset & lisensi tercatat
---
### Phase 1: Foundation & MVP (Week 1-3)
> **Goal:** Working TUI yang bisa browse Docker resources, dengan "rasa" tia (dashboard, animasi, suara, notifikasi) dari awal
| Deliverable | Description |
|---|---|
| Project scaffolding | go mod, project structure, Makefile |
| `internal/core` | Lapisan logika bersama (Docker, stack, config) yang **tidak bergantung UI**, dipakai TUI dan CLI |
| Root model | Bubble Tea app with 2-panel layout |
| **Home Dashboard** | Layar pembuka: logo ASCII beranimasi, jam digital ASCII + tanggal, ringkasan Docker & host, aktivitas terbaru, aksi cepat (F-027) |
| Sidebar | Sections: Stacks, Containers, Images, Volumes, Networks |
| Content panel | Tab system with placeholder views |
| Docker client | SDK connection, list containers/images/volumes/networks |
| Navigation | Vim-like keybindings, focus management |
| Mouse support | Klik/scroll/hover/klik-kanan, hit-testing zones di layout, toolbar aksi klikable, drag resize sidebar |
| **Notifikasi (toast)** | Popup atas-tengah dengan status (sukses/peringatan/gagal/info), antrean, auto-dismiss, klik untuk tutup (F-025) |
| **Sound engine** | Efek suara untuk klik, navigasi, modal, notifikasi, sukses, peringatan, error; toggle & volume di Pengaturan (F-024) |
| **Animation engine** | Splash logo, shimmer logo, spinner/progress, toast slide-in, transisi status container (F-026) |
| i18n (id/en) | Katalog bahasa Indonesia & Inggris, semua string UI lewat katalog (tanpa hardcode), pilih bahasa di wizard & config |
| Config | Basic config load/save |
| Theme | Catppuccin (Mocha/Latte), mode Otomatis/Gelap/Terang/Terminal, deteksi background terminal, semua warna via token semantik |
| Status bar | Context-aware help text (hint klikable) |
| **Rilis awal** | goreleaser + Gitea Releases + `install.sh` + checksum (F-029), `tia-love --version` / `tia-love doctor` |
**Exit Criteria:** Jalankan `tia-love` → splash → Home Dashboard (jam, ringkasan) → masuk workspace, lihat semua resource Docker, navigasi dengan keyboard **dan mouse**; setiap aksi memberi suara + toast; instal dengan satu baris perintah berhasil di mesin bersih
---
### Phase 2: Monitoring & Logs (Week 3)
> **Goal:** Real-time monitoring capabilities
| Deliverable | Description |
|---|---|
| Log viewer | Real-time log streaming, ANSI colors, search, scroll |
| Stats view | CPU/Memory/Network/IO graphs, 1s refresh |
| Process view | Container processes (docker top) |
| Inspector | JSON inspect for any resource |
| Env view | Environment variables display |
| Events listener | Auto-update resource lists on Docker events |
**Exit Criteria:** Select container → see live logs, stats updating, processes
---
### Phase 3: Stack Management & Converter (Week 4-5)
> **Goal:** Full stack lifecycle + docker run converter
| Deliverable | Description |
|---|---|
| Stack scanner | Scan & discover existing compose stacks |
| Stack manager | Create, start, stop, restart, down, delete, update |
| Converter | docker run → compose.yaml with 25+ flags |
| Converter UI | Modal: paste → preview → edit → save |
| YAML viewer | Syntax highlighted compose.yaml view |
| Setup wizard | First-run setup with huh forms |
| Compose CLI wrapper | docker compose up/down/pull/restart/ps |
| REA modul 1, 2, 7 | Analisis composerize, Dockge (stack), dan format output Compose, hasil di `docs/rea/` + test vectors |
| CLI mode (pendamping) | `tia-love convert`, `tia-love ps`, `tia-love stacks`, `tia-love up/down/restart/update`, `--json`, kode keluar jelas (F-028) |
**Exit Criteria:** Convert docker run command → save as stack → manage it, **baik dari TUI maupun dari CLI**, dengan hasil identik
---
### Phase 4: Container Actions & Exec (Week 5-6)
> **Goal:** Full container lifecycle + exec shell
| Deliverable | Description |
|---|---|
| Container exec | Shell into container (tea.ExecProcess) |
| Lifecycle actions | Start, stop, restart, pause, unpause, remove, rename |
| Bulk actions | Multi-select + batch operations |
| Context menu | Action menu (`x`) for all available actions |
| Confirm dialogs | Confirmation for destructive actions |
**Exit Criteria:** Exec into container, bulk stop/remove, all lifecycle actions work
---
### Phase 5: Advanced Features (Week 7-8)
> **Goal:** Power-user features
| Deliverable | Description |
|---|---|
| System prune | Interactive cleanup with space preview |
| Health check monitor | Health status tracking & history |
| Resource limits editor | Modify CPU/memory limits on running containers |
| Dockerfile builder | Basic editor + build integration |
| Registry browser | Search Docker Hub, view tags, pull |
| Stack export/import | Pack/unpack stacks as .tar.gz |
| Volume backup | Backup/restore named volumes |
**Exit Criteria:** All advanced features functional
---
### Phase 6: Multi-Host (Week 9-10)
> **Goal:** Manage Docker on remote servers
| Deliverable | Description |
|---|---|
| Host manager | Add/remove/edit remote hosts |
| SSH tunnel | Forward remote Docker socket |
| Host selector | Switch between hosts in sidebar |
| Remote operations | All features work on remote hosts |
**Exit Criteria:** Add remote host → manage its containers/stacks from tia
---
## 9. Non-Functional Requirements
### Performance
- Startup time < 500ms
- UI response < 16ms (60fps)
- Memory usage < 50MB idle, < 100MB active monitoring
- Efficient rendering via Cursed Renderer (cell-diffing)
- Animasi dibatasi **30 FPS**, CPU idle < 3% saat dashboard terbuka
- Inisialisasi audio **tidak memblok startup** (dilakukan di background); suara pertama < 100 ms setelah siap
- Ukuran binary: target < 25 MB (termasuk aset suara < 2 MB)
### Compatibility
- Linux (primary)
- macOS (secondary)
- Windows (WSL2 — best effort)
- Docker Engine 20.10+
- Docker Compose v2 (plugin mode)
### Input & Mouse Support
- **Mouse-first friendly:** semua fitur utama dapat dioperasikan penuh dengan mouse, keyboard tetap first-class (tidak ada fitur mouse-only atau keyboard-only)
- Mouse capture aktif by default (`mouse_enabled: true`), bisa dimatikan via config
- Tampilan harus mengindikasikan elemen yang bisa diklik (hover highlight, tombol berlabel, kursor/affordance jelas)
- Kompatibel dengan terminal modern (kitty, alacritty, wezterm, gnome-terminal, iTerm2), tmux, dan SSH session
- Fallback graceful bila terminal tidak mendukung mouse
### Distribution
- **Satu binary statis** (`CGO_ENABLED=0`), tanpa runtime dependency selain Docker (audio memakai library pure-Go; server audio hanya dibutuhkan jika suara diaktifkan)
- Instal satu baris (skrip) **atau** unduh binary manual dari Gitea Releases, detail di **F-029**
- Release otomatis via goreleaser: `.tar.gz`/`.zip` + `checksums.txt`; `.deb`, `.rpm`, Homebrew, AUR menyusul
- Binary name: `tia-love` (nama produk tetap: tia)
### Audio & Animasi
- Suara dan animasi **opsional**: bisa dimatikan penuh dari Pengaturan, dan aplikasi tetap 100% fungsional tanpa keduanya
- Setiap suara dan animasi punya padanan visual/teks agar informasi tidak hanya lewat bunyi
- Mode "reduced motion" untuk pengguna yang sensitif terhadap gerakan
### Security
- No credentials stored in plaintext (SSH keys referenced by path)
- Docker socket access follows system permissions
- Confirmation for all destructive operations
---
## 10. Success Metrics
| Metric | Target |
|---|---|
| Docker run → compose conversion accuracy | > 95% untuk common flags |
| TUI startup time | < 500ms |
| Real-time stats latency | < 2 seconds |
| Container exec suspend/resume | Clean, no artifacts |
| Stack operations (up/down/restart) | Same reliability as native CLI |
| Multi-host connection | < 5 seconds SSH tunnel setup |
| Mouse coverage | 100% aksi utama bisa dilakukan hanya dengan mouse (tanpa keyboard) |
| Parity keyboard & mouse | Setiap fitur bisa lewat keyboard DAN mouse |
| Latensi suara klik | < 100 ms dari aksi sampai terdengar |
| Notifikasi (toast) muncul | < 100 ms setelah event, tampil di atas-tengah dengan status lengkap |
| Animasi | Stabil 30 FPS, CPU idle < 3% saat dashboard terbuka |
| Instalasi satu baris | < 30 detik dari perintah sampai `tia-love` bisa dijalankan |
| Paritas CLI vs TUI | Hasil konversi & operasi stack lewat CLI identik dengan lewat TUI |
| Coverage aset | 100% aset tercatat di register aset dengan lisensi valid |
---
## 11. Risks & Mitigations
| Risk | Impact | Mitigation |
|---|---|---|
| Charm v2 breaking changes (baru release) | High | Pin exact versions, thorough testing |
| Docker API version incompatibility | Medium | Use API version negotiation |
| Terminal compatibility (colors, unicode) | Medium | Lipgloss adaptive colors, fallback ASCII |
| Complex compose files break converter | Medium | Focus on common flags, graceful fallback |
| SSH tunnel instability | Low | Reconnection logic, timeout handling |
| Mouse event tidak konsisten antar terminal/tmux/SSH | Medium | Test di terminal populer (kitty, alacritty, wezterm, gnome-terminal, tmux, SSH), keyboard selalu jadi fallback penuh, toggle mouse via config |
| Mouse capture mengganggu copy-paste teks native | Medium | Sediakan mode "text select" (toggle `m`) + tombol Copy di log/YAML viewer + dukungan OSC52 clipboard |
| Suara tidak terdengar saat tia dijalankan lewat SSH (audio diputar di server, bukan di laptop pengguna) | High | Deteksi sesi SSH → suara default mati + info; semua suara selalu punya padanan visual; opsi terminal bell (BEL) sebagai fallback; rekomendasikan pola "tia lokal + multi-host" |
| Tidak ada audio device/server (PulseAudio/PipeWire/ALSA) di mesin | Medium | Deteksi saat start, degradasi diam-diam ke mode tanpa suara + notifikasi sekali; `tia-love doctor` menampilkan status audio |
| Dependensi audio merusak single static binary (cgo) | High | Pilih library audio pure-Go (Oto v3 dengan `CGO_ENABLED=0`); **spike teknis di Phase 0** untuk membuktikan sebelum dikunci |
| Animasi menghabiskan CPU / flicker di terminal lambat | Medium | Batas 30 FPS, animasi dimatikan otomatis saat idle/terminal lambat, mode "reduced motion", toggle di Pengaturan |
| Spam suara/notifikasi dari event Docker beruntun | Medium | Debounce, rate limit, dan pengelompokan notifikasi sejenis |
| Pola `curl \| sh` dianggap tidak aman | Medium | HTTPS saja, verifikasi checksum SHA256, skrip ringkas bisa dibaca, instal ke `~/.local/bin` tanpa sudo, sediakan jalur instal manual |
| Pelanggaran lisensi aset / kode referensi | High | Kebijakan aset open source (Appendix C), register aset, aturan REA "tulis ulang, jangan salin", verifikasi lisensi di awal tiap modul |
| Pertentangan prinsip TUI-first dengan mode CLI | Low | CLI hanya pendamping non-interaktif; seluruh logika di `internal/core` dipakai bersama sehingga tidak ada duplikasi |
---
## 12. REA Skill: Reverse Engineering & Analysis
> [!NOTE]
> Singkatan "REA" saya artikan sebagai **Reverse Engineering & Analysis**. Bagian ini perlu dikonfirmasi (lihat Open Questions).
### 12.1 Tujuan
REA adalah **skill kerja** (panduan terstruktur untuk agent/developer) yang dipakai selama pengembangan untuk **menganalisis logika backend proyek referensi** (Dockge, lazydocker, composerize) lalu **mem-porting perilakunya ke Go** di dalam tia, dengan hasil yang bisa diverifikasi.
Yang dianalisis dan di-clone adalah **logika backend** (alur, algoritma, aturan, format data, perintah Docker). **Bukan** UI, branding, aset, atau frontend mereka.
### 12.2 Aturan Legal & Etika
1. **Cek lisensi dulu** langsung dari repo sumber sebelum menyentuh kodenya (target saat ini umumnya MIT, tapi wajib diverifikasi)
2. **Tulis ulang, jangan salin.** Pelajari perilaku dan algoritma, lalu implementasikan sendiri dalam Go. Tidak ada copy-paste kode verbatim
3. Jika ada bagian yang terpaksa diadaptasi dekat dengan aslinya, **cantumkan atribusi** dan lisensi aslinya di `THIRD_PARTY_NOTICES`
4. Jangan pernah menganalisis/meniru proyek **closed-source** atau berlisensi tidak jelas
5. Jangan mengambil nama, logo, atau aset visual proyek referensi
### 12.3 Bentuk Skill
- Disimpan di repo sebagai skill (`SKILL.md` + template laporan), lokasi final mengikuti konvensi skill Antigravity
- Dipanggil per modul: "REA: analisis `<modul>` dari `<repo>`"
- Output selalu berupa dokumen analisis + test vectors + spesifikasi port, sebelum satu baris kode Go ditulis
### 12.4 Alur Kerja
```mermaid
flowchart LR
A[1. Scope] --> B[2. Map]
B --> C[3. Trace]
C --> D[4. Spec]
D --> E[5. Port]
E --> F[6. Verify]
F -->|beda perilaku| C
```
| Langkah | Aktivitas | Output |
|---|---|---|
| 1. **Scope** | Tentukan modul & batasnya, cek lisensi | Catatan scope + lisensi |
| 2. **Map** | Petakan file/fungsi/struktur data yang relevan | Peta modul |
| 3. **Trace** | Telusuri alur eksekusi dari input ke output, termasuk edge case & error path | Diagram alur + daftar edge case |
| 4. **Spec** | Tulis spesifikasi netral: input, output, aturan, tabel pemetaan, perintah Docker yang dipanggil | `docs/rea/<modul>.md` + test vectors |
| 5. **Port** | Implementasi ulang dalam Go (terpisah dari UI, di `internal/core`) | Kode Go + unit test |
| 6. **Verify** | Uji paritas: input sama harus menghasilkan output setara dengan referensi | Laporan paritas (lolos/gagal per kasus) |
### 12.5 Template Laporan Analisis (`docs/rea/<modul>.md`)
- Ringkasan & tujuan modul
- Sumber (repo, commit/versi, lisensi)
- Alur eksekusi (diagram)
- Struktur data & format I/O
- Aturan & edge case
- Perintah Docker/Compose yang dipanggil beserta format outputnya
- Test vectors (input → output yang diharapkan)
- Perbedaan yang disengaja dari referensi (dan alasannya)
### 12.6 Target Analisis
| # | Modul referensi | Yang dianalisis | Hasil di tia | Fase |
|---|---|---|---|---|
| 1 | **composerize** | Parser flag `docker run`, tokenisasi (quote, backslash, multi-line), pemetaan flag → field compose, normalisasi | `internal/stack/converter.go` + korpus test | 3 |
| 2 | **Dockge** (stack) | Scan folder stack, kandidat nama file compose (`compose.yaml`, `compose.yml`, `docker-compose.yaml`, `docker-compose.yml`), normalisasi nama project, rekonsiliasi status (`docker compose ls --all --format json` vs isi disk), deteksi unmanaged, pola perintah up/down/pull/restart | `internal/stack/scanner.go`, `manager.go`, `internal/docker/compose.go` | 3 |
| 3 | **Dockge** (agent) | Arsitektur primary ↔ agent untuk multi-host (ide desain; tia memakai SSH tunnel) | `internal/host/*` | 6 |
| 4 | **lazydocker** (commands) | Pemanggilan Docker SDK: list/inspect, stats streaming, buffer riwayat CPU/RAM, deteksi shell, log streaming | `internal/docker/*` | 2, 4 |
| 5 | **lazydocker** (tasks) | Manajemen stream di background: cancel stream saat pilihan pindah, cegah goroutine bocor | Pola stream/cancel pada TUI | 2 |
| 6 | **lazydocker** (custom commands) | Template perintah kustom dengan placeholder | Fitur custom commands (opsional) | 5 |
| 7 | **Docker/Compose CLI** | Format JSON `compose ls`, `compose ps`, `compose config`, kode keluar | Parser output compose | 3 |
### 12.7 Verifikasi Paritas
- **Golden tests:** pasangan input/output dari analisis disimpan sebagai test vectors
- **Differential testing (converter):** jalankan korpus perintah `docker run` yang sama pada composerize dan converter tia, lalu bandingkan YAML hasilnya setelah dinormalisasi (urutan key, kutip)
- **Target paritas:** ≥ 95% pada flag umum (selaras dengan success metric converter); setiap perbedaan harus tercatat sebagai "perbedaan yang disengaja"
- **Integration test** dengan Docker sungguhan untuk scanner dan status stack
### 12.8 Definition of Done per Modul
- [ ] Lisensi sumber sudah diverifikasi dan dicatat
- [ ] Laporan analisis `docs/rea/<modul>.md` selesai
- [ ] Test vectors tersedia
- [ ] Implementasi Go terpisah dari UI (bisa dipakai TUI **dan** CLI)
- [ ] Uji paritas lolos sesuai target
- [ ] `THIRD_PARTY_NOTICES` diperbarui bila perlu
---
## 13. Future Considerations (Post v1.0)
- [ ] Docker Swarm support
- [ ] Kubernetes basic support (pods, deployments)
- [ ] Plugin system (custom commands via Go plugins or Lua)
- [ ] Remote access via SSH TUI (using Charm's `wish`)
- [ ] Notification integrations (Discord, Telegram, Slack)
- [ ] Container metrics history & persistence
- [ ] Compose file templates marketplace
- [ ] AI-assisted compose generation
- [ ] Container security scanning integration (Trivy, Grype)
---
## Appendix A: Reference Projects
| Project | URL | What We Take |
|---|---|---|
| Dockge | https://github.com/louislam/dockge | Stack management, converter, file-system approach |
| lazydocker | https://github.com/jesseduffield/lazydocker | UI layout, keybindings, multi-panel design |
| Charm (bubbletea) | https://github.com/charmbracelet/bubbletea | TUI framework |
| Charm (bubbles) | https://github.com/charmbracelet/bubbles | UI components |
| Charm (lipgloss) | https://github.com/charmbracelet/lipgloss | Styling |
| Charm (huh) | https://github.com/charmbracelet/huh | Forms |
| Mirador | https://github.com/jchultarsky/mirador | Inspirasi tata letak dashboard TUI (panel grid dengan judul di border, meta kanan, jam blok, satu panel fokus terang) |
## Appendix B: Charm v2 Import Paths
```go
import (
tea "charm.land/bubbletea/v2"
"charm.land/bubbles/v2/list"
"charm.land/bubbles/v2/table"
"charm.land/bubbles/v2/viewport"
"charm.land/bubbles/v2/textinput"
"charm.land/bubbles/v2/help"
"charm.land/bubbles/v2/key"
"charm.land/bubbles/v2/spinner"
"charm.land/bubbles/v2/progress"
"charm.land/lipgloss/v2"
"charm.land/huh/v2"
"charm.land/glamour/v2"
"charm.land/log/v2"
)
```
## Appendix C: Aset Open Source & Lisensi
### Kebijakan
- Semua aset (suara, palet, font, ikon, library) **wajib open source / bebas dipakai**: CC0, MIT, Apache-2.0, BSD, OFL
- **Dilarang:** lisensi NC (non-commercial), ND (no-derivatives), atau lisensi yang tidak jelas
- Setiap aset dicatat di **register aset** (`docs/ASSETS.md` + `THIRD_PARTY_NOTICES`): nama, penulis, URL sumber, lisensi, tanggal diambil, dan file mana yang memakainya
- Aset suara di-embed ke binary, jadi atribusi harus ikut tersedia dari dalam aplikasi (menu **Tentang**)
- Lisensi tia sendiri perlu diputuskan (rekomendasi: **MIT**); lihat Open Questions
### Sumber yang direkomendasikan
| Kebutuhan | Sumber | Lisensi | Catatan |
|---|---|---|---|
| Efek suara UI (klik, notif, alert) | **Kenney: Interface Sounds / UI Audio** (kenney.nl) | CC0 | Pilihan utama, tanpa kewajiban atribusi |
| Efek suara tambahan | OpenGameArt (filter **CC0** saja) | CC0 | Cek lisensi per file |
| Efek suara tambahan | Freesound (filter **CC0** saja) | CC0 | Hindari CC-BY-NC |
| Palet warna | **Catppuccin** | MIT | Sudah diputuskan |
| Logo ASCII & animasi | **Buatan sendiri** | Ikut lisensi tia | Menghindari masalah lisensi font |
| Font ASCII (jika dipakai) | FIGlet / font lain | **Beda per font** | Wajib cek lisensi tiap font sebelum dipakai |
| Glyph/ikon | Unicode standar (●, ○, ▶, ⟳, ✔, ⚠) | Bebas | **Tidak mewajibkan Nerd Font**; sediakan fallback ASCII |
| Library TUI | Charm (bubbletea, bubbles, lipgloss, huh, glamour, log, harmonica) | MIT | |
| Library Docker | Docker SDK for Go | Apache-2.0 | |
| Library audio | Oto (ebitengine) | Apache-2.0 | |
### Format aset suara
- Sumber asli biasanya OGG. Untuk menghindari dependensi decoder tambahan, **konversi ke WAV** (44.1 kHz, 16-bit, mono) saat build aset
- Efek suara berdurasi pendek (< 1 detik), target total aset suara **< 2 MB** di dalam binary
- File suara disimpan di `internal/audio/assets/` dan di-embed lewat `go:embed`
> [!NOTE]
> Lisensi proyek referensi (Dockge, lazydocker, composerize) umumnya MIT, tetapi **wajib diverifikasi ulang langsung dari repo masing-masing** sebelum ada logika yang diadaptasi. Lihat bagian REA Skill.