๐Ÿค” Design Decisions

Dokumen ini menjelaskan kenapa OpsTerm dirancang seperti ini โ€” alasan di balik setiap keputusan teknis, termasuk trade-off yang diambil.


๐Ÿ“œ Daftar Keputusan

# Keputusan Pilihan Alternatif yang Ditolak
1 Bahasa Python 3 Go, Rust, Node.js, Bash
2 Arsitektur Single file CLI Modular package, Client-server
3 Dependencies Zero (stdlib only) PyYAML, requests, click
4 Config format YAML (custom parser) JSON, TOML, INI
5 AI Protocol OpenAI-compatible API LangChain, custom gRPC
6 SSH Method Subprocess + system ssh paramiko, asyncssh
7 State File-based (no daemon) SQLite daemon, Redis
8 Vault Optional cryptography Hardcoded key, no encryption
9 Completion Generated script Manual completion
10 Shell Integration Zsh plugin Hook shell, LD_PRELOAD

1๏ธโƒฃ Kenapa Python, bukan Go/Rust?

Konteks

OpsTerm butuh bahasa yang portable, zero-dep, dan gampang di-maintain.

Keputusan: โœ… Python 3

Alasan:

  1. Ada di mana-mana โ€” Semua Linux & macOS punya Python 3. User tinggal download script, langsung jalan. Kalo Go/Rust, harus compile dulu atau download binary.

  2. Stdlib kaya โ€” argparse, json, sqlite3, urllib, hashlib, subprocess โ€” semua built-in. Di Go/Rust, library-library ini butuh import eksternal atau stdlib yang kurang lengkap.

  3. Maintainability โ€” Python lebih gampang dibaca & dimodifikasi. Kontributor potensial lebih gampang ngerti kode.

  4. File size โ€” Script Python ~50KB vs Go binary ~10MB. Kecil, gampang di-copy ke server mana pun.

  5. Rapid iteration โ€” Fitur baru bisa langsung dipake tanpa compile. Edit โ†’ save โ†’ run.

Trade-off:
- Performance lebih rendah (tapi untuk CLI tool, ini gak kerasa)
- Butuh Python interpreter (tapi udah ada di semua system modern)


2๏ธโƒฃ Kenapa single file, bukan package?

Konteks

OpsTerm bisa aja dibikin sebagai Python package dengan pip install.

Keputusan: โœ… Single file (bin/ai)

Alasan:

  1. Portable โ€” Copy 1 file ke server mana pun, langsung jalan. scp bin/ai server:~/.local/bin/

  2. Zero setup โ€” Ga perlu pip install, ga perlu python -m opsterm. Langsung ./ai.

  3. Transparent โ€” Isinya bisa dibaca & dipahami. Gak ada __pycache__, egg-info, dll.

  4. Easy debugging โ€” Kalo error, tinggal edit baris tertentu, gak perlu cari file di folder.

Trade-off:
- File besar (~1500 baris). Tapi masih kecil dibanding app lain.
- Semua fungsi dalam 1 file โ€” susah di-test secara unit.
- Solusi: kode diorganisir dengan section headers (comments).


3๏ธโƒฃ Kenapa zero dependencies?

Konteks

Banyak Python CLI tool pake PyYAML, requests, click, dll.

Keputusan: โœ… Zero external dependencies

Alasan:

  1. No install step โ€” Clone repo โ†’ langsung jalan. Gak perlu pip install -r requirements.txt.

  2. No version conflicts โ€” Gak bakal bentrok sama library system atau project lain.

  3. Works in any Python env โ€” Virtual env, system Python, container, semuanya jalan.

  4. Easy to audit โ€” Semua kode yang jalan bisa dibaca. Gak ada hidden dependency.

Yang dikorbankan:
- YAML parser manual (~80 baris) โ€” gak support full YAML spec, tapi cukup buat kebutuhan.
- HTTP client stdlib (urllib) โ€” lebih verbose daripada requests, tapi fungsional.
- CLI parser stdlib (argparse) โ€” kurang powerful daripada click, tapi cukup.


4๏ธโƒฃ Kenapa YAML, bukan JSON/TOML?

Konteks

Config format buat server, workflow, dan AI settings.

Keputusan: โœ… YAML (dengan custom parser)

Alasan:

  1. Readability โ€” YAML lebih enak dibaca manusia dibanding JSON. Comment, indentasi bersih.

  2. User-friendly โ€” Target user OpsTerm adalah DevOps engineer yang biasa pake YAML (Docker Compose, Kubernetes, Ansible, GitHub Actions).

  3. No brackets โ€” JSON penuh {} dan [] yang ganggu readability buat config panjang.

Trade-off:
- Custom parser โ†’ terbatas. Tapi subset YAML yang kita pake (mapping, list, scalar) stabil dan cukup.
- Inkonisten dengan "zero dep" โ€” technically YAML parsing itu custom code, bukan dependency eksternal.


5๏ธโƒฃ Kenapa OpenAI-compatible API, bukan library AI?

Konteks

Bisa pake LangChain, LiteLLM, atau library abstraksi AI lainnya.

Keputusan: โœ… Direct HTTP call (OpenAI-compatible)

Alasan:

  1. Zero dependency โ€” Cuma urllib (stdlib). LangChain butuh 20+ dependencies.

  2. Provider agnostic โ€” Format OpenAI request/response udah jadi standar de-facto. DeepSeek, Ollama, vLLM, OpenRouter โ€” semua support.

  3. Simple โ€” Chat Completion API cuma 1 endpoint, format sederhana.

  4. Debug friendly โ€” Request/response bisa di-log, di-inspect, di-test pake curl.

Trade-off:
- Gak ada retry logic, streaming, atau tool calling.
- Tapi untuk CLI tool yang blocking, ini gak masalah.


6๏ธโƒฃ Kenapa system SSH, bukan library Python?

Konteks

Bisa pake paramiko (SSH client library Python).

Keputusan: โœ… System SSH (subprocess + /usr/bin/ssh)

Alasan:

  1. Feature parity โ€” System SSH punya semua fitur: key management, ProxyJump, agent forwarding, compression, dll.

  2. Zero dependency โ€” paramiko butuh bcrypt, cryptography, pynacl, dll.

  3. Familiar โ€” Semua konfigurasi SSH (known_hosts, config, agent) jalan otomatis.

  4. Interactive support โ€” os.execvp() bisa ngasih SSH session interaktif penuh. paramiko gak bisa seamless.

  5. Already configured โ€” User pasti udah setup SSH key di system-nya.

Trade-off:
- Gak bisa parse SSH output secara real-time.
- Error handling terbatas (cuma exit code).


7๏ธโƒฃ Kenapa file-based state, bukan daemon?

Konteks

Beberapa tool pake background daemon yang nyimpen state di memory.

Keputusan: โœ… File-based (no daemon)

Alasan:

  1. Zero resource โ€” Gak ada background process. Gak consume RAM/CPU kalo gak dipake.

  2. Crash-proof โ€” Kalo terminal kill, data gak ilang. Semua di file.

  3. Transparent โ€” User bisa buka config langsung, edit pake editor teks.

  4. Simple โ€” Gak perlu manage process lifecycle, signal handling, lock files.

Trade-off:
- State dibaca dari disk setiap kali command โ†’ overhead dikit (<10ms).
- Gak bisa ada "real-time" notification.


8๏ธโƒฃ Kenapa vault optional?

Konteks

Vault butuh cryptography yang gak ada di stdlib.

Alasan:

  1. Zero dep tetap berlaku โ€” Fitur dasar OpsTerm jalan tanpa vault.

  2. Security tetap prioritas โ€” Vault pake AES via cryptography. Fallback XOR + HMAC kalo gak ada.

  3. Progressive enhancement โ€” User bisa mulai tanpa vault, install cryptography kalo butuh.


9๏ธโƒฃ Kenapa generated completion?

Konteks

Completion bisa ditulis manual atau di-generate.

Keputusan: โœ… Generated (embedded in script)

Alasan:

  1. Always up-to-date โ€” Kalo ada subcommand baru, completion otomatis update karena di-generate dari kode.

  2. Zero additional file โ€” ai completion bash langsung print ke stdout. Gak perlu file terpisah.

  3. Works out of box โ€” source <(ai completion bash) โ€” 1 command, langsung jadi.


๐Ÿ”Ÿ Kenapa Zsh plugin terpisah?

Konteks

Shell integration bisa jadi bagian dari main script atau file terpisah.

Keputusan: โœ… File terpisah (zsh/opsterm.plugin.zsh)

Alasan:

  1. Bahasa berbeda โ€” Zsh plugin pake Zsh script, bukan Python. Gabungin di file Python bakal campur aduk.

  2. Zsh-only โ€” Fitur shell hooks (preexec, precmd) cuma ada di Zsh.

  3. Lazy loading โ€” Plugin cuma di-load kalo user source di .zshrc. Gak nambah weight.

  4. Familiar pattern โ€” Zsh plugin format udah standar (oh-my-zsh, antigen, zplug).


๐Ÿ’ก Saran untuk Improvement

Berdasarkan design decisions di atas, beberapa saran:

  1. Python โ†’ Rust (masa depan) โ€” Kalo performa & distribution jadi masalah, rewrite ke Rust buat single binary.

  2. YAML โ†’ TOML โ€” Kalo butuh config yang lebih strict (type safety), TOML lebih cocok. Tapi butuh library eksternal.

  3. Add plugin system โ€” Biar komunitas bisa nambah fitur tanpa edit core script.

  4. Support Fish shell โ€” Populer di kalangan developer modern.


๐Ÿ”— Referensi