1534 lines
86 KiB
Markdown
1534 lines
86 KiB
Markdown
# 📋 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.
|