2 poin oleh GN⁺ 5 jam lalu | 1 komentar | Bagikan ke WhatsApp
  • uv unggul dalam kecepatan, manajemen versi Python, dan integrasi dalam satu biner, tetapi UX pengelolaan paket pada tahap pemeliharaan masih terasa kasar
  • Paket lama bisa diperiksa dengan uv pip list --outdated, tetapi karena berada di bawah namespace kompatibilitas pip dan bukan perintah tingkat atas, tingkat ketertemuannya rendah
  • uv add pydantic secara default menambahkan batasan tanpa batas atas seperti pydantic>=2.13.4, sehingga kenaikan versi mayor pun diizinkan
  • Upgrade penuh dilakukan dengan uv lock --upgrade, dan untuk beberapa paket tertentu perlu mengulang --upgrade-package, sehingga perintah menjadi panjang
  • Dengan pengaturan add-bounds = "major", batasan default yang lebih aman bisa diterapkan, tetapi ini masih fitur pratinjau dan aplikasi membutuhkan UX pembaruan yang lebih intuitif

Kelebihan uv dan ketidaknyamanan pada tahap pemeliharaan

  • uv dari Astral punya keunggulan pada kecepatan, manajemen versi Python, dan kemampuannya menggantikan beberapa alat dengan satu biner
  • Alur memulai proyek Python baru dan menambahkan dependensi pertama memang mudah, tetapi ketika proyek masuk ke tahap pemeliharaan, UX untuk memeriksa paket lama dan melakukan upgrade berkala terasa lebih kasar dibanding pnpm atau Poetry
  • Ketidaknyamanan utamanya terletak pada ketertemuan perintah untuk memeriksa paket lama, tidak adanya batas atas pada batasan versi default, dan panjangnya perintah upgrade

Memeriksa paket yang sudah usang

  • Dalam proyek JavaScript, pnpm outdated memungkinkan kita melihat paket yang sudah usang, versi saat ini, versi terbaru, dan versi yang masih diizinkan oleh constraint secara ringkas
  • Di uv tidak ada perintah tingkat atas uv outdated, dan pada awalnya perintah berikut digunakan sebagai alternatif
$ uv tree --outdated --depth 1
  • uv tree --outdated --depth 1 tidak hanya memfilter item yang usang, tetapi menampilkan seluruh pohon dependensi tingkat atas lalu menambahkan anotasi kecil di samping item yang bisa diperbarui
  • Jika ada 50 dependensi dan hanya 2 paket yang usang, kita tetap harus menelusuri daftar 50 baris
  • poetry show --outdated juga punya nama perintah yang kurang intuitif, tetapi output nyatanya hanya menampilkan paket yang usang

Risiko batasan versi default

  • Pendekatan default pnpm dan Poetry

    • pnpm add menulis requirement caret seperti ^1.23.4 ke package.json
    • ^1.23.4 mengizinkan versi 1.x.x, tetapi tidak akan memperbarui ke 2.0.0
    • Poetry juga secara default menggunakan format seperti >=1.23.4,<2.0.0; penulisannya memang kurang mudah dibaca, tetapi efeknya sama
    • Pada kedua alat itu, dengan asumsi paket mengikuti SemVer, menjalankan pnpm update atau poetry update dapat mengurangi kemungkinan build rusak akibat perubahan API mayor
  • Pendekatan default uv

    • uv add pydantic menambahkan batasan tanpa batas atas berikut ke pyproject.toml
dependencies = [
    "pydantic>=2.13.4",
]
  • Dengan batasan ini, pydantic versi 2, 3, bahkan 100 semuanya diizinkan
  • Saat menjalankan pembaruan massal, kita bukan hanya menerima perbaikan bug, tetapi juga perubahan yang memutus kompatibilitas yang dirilis oleh semua pemelihara di dalam graf dependensi
  • Khususnya dalam pemeliharaan aplikasi, ini bisa menjadi risiko stabilitas

UX perintah upgrade

  • Di pnpm dan Poetry, pembaruan penuh sesederhana berikut
$ pnpm update
$ poetry update
  • Di uv, perintah berikut digunakan untuk upgrade penuh
$ uv lock --upgrade
  • uv lock --upgrade bukan uv update atau uv upgrade, melainkan opsi dari perintah lock, sehingga terasa kurang intuitif sebagai perintah pengelolaan paket yang digunakan manusia
  • Jika digabungkan dengan batasan tanpa batas atas, uv lock --upgrade pada dasarnya menjadi pilihan untuk menaikkan semua paket di lockfile ke versi terbaru mutlak
  • Pembaruan ini juga bisa mencakup dependensi bertingkat dalam yang bahkan tidak kita ketahui secara langsung
  • Untuk memperbarui hanya paket tertentu, pnpm cukup menuliskan nama paket seperti berikut
$ pnpm update pydantic httpx uvicorn
  • Di uv, kita harus mengulang flag --upgrade-package untuk setiap paket
$ uv lock --upgrade-package pydantic --upgrade-package httpx --upgrade-package uvicorn
  • Saat menaikkan beberapa paket sekaligus, pengulangan flag menjadi kerepotan besar

Flag --bounds dan pengaturan

  • uv baru-baru ini menambahkan opsi --bounds untuk uv add
$ uv add pydantic --bounds major
  • Perintah ini menghasilkan batasan yang lebih aman, yaitu pydantic>=2.13.4,<3.0.0
  • --bounds major saat ini adalah fitur pratinjau dan merupakan fitur opt-in yang harus diketik langsung pada setiap perintah
  • Belakangan diketahui bahwa nilai default juga bisa diatur sekali di pyproject.toml
[tool.uv]
add-bounds = "major"
  • Dengan pengaturan ini, kita bisa mendapatkan default yang lebih masuk akal pada uv add berikutnya tanpa harus mengetik --bounds major setiap kali
  • Untuk aplikasi, perilaku ini lebih baik jika menjadi default, tetapi dari sisi kenyamanan penggunaan nyata, keadaannya tidak seburuk yang digambarkan pada awalnya

Perbedaan aplikasi dan library

  • Saran standar dalam packaging Python adalah agar library yang didistribusikan ke PyPI tidak mengunci batas atas, dan saran ini memang masuk akal
  • Jika semua library mengunci batas atas, pohon dependensi konsumen di bawahnya bisa gagal diresolusikan
  • Sebaliknya, aplikasi adalah simpul ujung dari graf dependensi, dan tidak ada pengguna lain yang melakukan resolusi berdasarkan constraint tersebut
  • Dalam aplikasi, tidak ada biaya dari penggunaan batas atas, dan itu bisa melindungi dari kenaikan versi mayor yang tak terduga
  • Ruang lingkup pembahasan di sini adalah pemeliharaan aplikasi seperti situs web, layanan, atau alat internal; untuk distribusi library, default tanpa batas atas bisa jadi masuk akal

Bagian yang telah dikoreksi dan masalah yang tersisa

  • Dengan uv pip list --outdated, kita bisa melihat hanya paket yang sudah usang
$ uv pip list --outdated
  • Karena itu, kritik terhadap output yang berisik dari uv tree --outdated --depth 1 menjadi berkurang
  • Masalah yang tersisa adalah fitur ini berada di bawah namespace kompatibilitas pip, bukan sebagai perintah tingkat atas, sehingga ketertemuannya rendah
  • Dengan pengaturan add-bounds = "major", kita bisa menentukan bounds default, jadi ini bukan lagi pilihan biner antara harus mengedit batas atas secara manual setiap kali atau menerima risiko
  • Meski begitu, fitur tersebut masih pratinjau, dan dalam pengelolaan paket aplikasi tetap dibutuhkan batasan default yang lebih aman serta perintah pembaruan yang lebih intuitif

Arah perbaikan yang diharapkan

  • Dibutuhkan perintah uv outdated khusus yang dengan jelas hanya menampilkan paket yang sudah usang
  • Dibutuhkan perintah update yang lebih ergonomis agar tidak perlu mengulang flag saat memperbarui beberapa paket
  • Batasan versi default seharusnya lebih mencerminkan ekspektasi stabilitas dari semantic versioning (SemVer)
  • Dalam kondisi saat ini, masih ada beban untuk memeriksa setiap baris perubahan lockfile dengan rasa curiga

1 komentar

 
GN⁺ 5 jam lalu
Komentar Hacker News
  • Rentang versi default untuk uv add bisa ditetapkan sebagai pengaturan permanen, jadi tidak perlu diberikan setiap kali
    Referensi: https://docs.astral.sh/uv/reference/settings/#add-bounds
    Alasan tidak menambahkan batas atas secara default adalah karena itu menimbulkan banyak konflik yang tidak perlu di ekosistem, dan saat masih memakai Poetry saya juga pernah mengumpulkan materi terkait: https://github.com/zanieb/poetry-relax#references

    • Saya paham bahwa saat mendistribusikan library, menghapus batas atas versi itu penting, tetapi tulisan ini dibuat dari sudut pandang membangun website, bukan library
      Saat memakai dependensi di proyek web, saya ingin ada batas atas untuk mencegah perubahan yang breaking, dengan asumsi dependensi tersebut mengikuti SemVer
    • Komunitas Haskell juga bergulat dengan masalah ini selama bertahun-tahun, dan pendekatan yang dulu paling sukses adalah Stackage
      Mereka mendorong agar tidak menambahkan batas atas defensif, lalu terus membangun bagian besar ekosistem yang aktif pada setiap rilis untuk menemukan masalah kompatibilitas nyata, mengirim notifikasi otomatis kepada pemilik, dan memberikan jadwal yang jelas agar tetap masuk ke rilis "LTS" berikutnya
      Sekarang tampaknya interpreter Cabal saja pun sudah cukup stabil, tetapi build nightly yang luas serta kegagalan dan pemblokiran yang terlihat kemungkinan membantu menjaga ekosistem tetap bisa di-resolve
    • Saya baru tahu soal pengaturan add-bounds, dan ini berguna untuk proyek tempat pin dependensi yang presisi itu penting tetapi mudah terlewat oleh developer yang kurang berpengalaman, terutama produk akhir, bukan library
    • Saya penasaran apakah ada cara untuk menetapkan flag --native-tls secara permanen
      Karena konfigurasi Zscaler di kantor, UV selalu gagal tanpa flag ini
      Saya juga penasaran apakah ada rencana mendukung fitur untuk menentukan versi Python kompatibel yang sesuai arsitektur tertentu. Ada satu paket yang dipelihara perusahaan saya yang harus memakai Python 32-bit, jadi saya selalu harus memberi --python /path/to/32bit
    • Mungkin ini pertanyaan yang agak kurang matang, tetapi saya penasaran apakah ada cara agar uv menghormati exclude-newer di pyproject.toml
      Saat menjalankan uv run, exclude-newer dihapus dari pyproject.toml
      Saya memang bisa menjalankan uv run —-frozen atau uv run --exclude-newer setiap kali, tetapi rasanya itu bukan alur yang tepat, jadi saya penasaran apakah ada cara idiomatis yang saya lewatkan
  • uv membutuhkan satu hasil resolusi tunggal, jadi tanpa batas atas adalah desain yang disengaja
    npm bisa memasang hasil resolusi yang berbeda di bagian pohon yang berbeda, tetapi di Python itu bukan pilihan. Di Rye kami juga harus mengambil keputusan yang sama, dan memang tidak ada solusi yang lebih baik di sini
    Menambahkan batas atas pada praktiknya bisa menghasilkan pohon yang tidak lagi bisa di-resolve. Sebagian ekosistem paket Python di masa lalu bahkan pernah merilis override untuk paket lama yang dirilis dengan asumsi batas atas yang keliru
    Hari ini, Anda belum bisa tahu apakah paket Anda akan kompatibel atau tidak dengan paket yang bahkan belum dirilis

    • Secara pribadi, saya lebih suka menerima error dari uv saat update bahwa paket-paket tidak kompatibel, lalu bisa melakukan override bila perlu
      Itu lebih baik daripada menemui error inkompatibilitas versi saat runtime yang sulit dilacak
    • Tidak adanya batas atas di pyproject.toml bukan masalah yang sebenarnya
      Masalah sebenarnya adalah bahwa uv lock —-upgrade meng-upgrade semuanya sekaligus yang tidak punya batas atas
      Jika ada cara untuk meng-upgrade paket tanpa menaikkan major version, perintah ini akan jauh lebih aman
    • uv memang sudah banyak memperbaiki keadaan, tetapi tampaknya ada cukup banyak hal yang pada dasarnya tidak bisa diselesaikan hanya dengan alat
      Dibanding sebelum uv, ini jauh lebih baik, tetapi tampaknya sulit menjadi benar-benar baik tanpa perubahan yang agak memecahkan seluruh ekosistem. Mengingat transisi Python 2 ke 3, sepertinya untuk sementara ini juga belum banyak keinginan ke arah perubahan seperti itu
    • Untuk penulis library, itu memang benar, tetapi saat membuat website dan bergantung pada banyak paket, saya ingin batas atas agar upgrade tetap aman
      Flag —-bound membantu, tetapi itu satu hal lagi yang harus diketik dan diingat
      Kalau uv bisa tahu bahwa proyek itu bukan library, mungkin saja secara default ia menambahkan batas atas
    • Sebenarnya cara yang benar memakai uv maupun npm adalah mengubah semuanya menjadi = dan jangan percaya update non-major tidak akan merusak, lalu hanya update secara manual
  • Saya punya 257 dependensi Python di aplikasi produksi, dan lebih dari setengahnya adalah dependensi langsung
    Di pyproject.toml saya tidak memberi batas atas, dan setiap dua minggu saya menjalankan uv lock --upgrade lewat GitHub Actions
    Cakupan pengujian kami bagus, jadi kalau ada yang rusak tes akan gagal, dan kami juga punya alur review berbantuan AI. Saat PR upgrade dibuat, workflow AI mencantumkan update major dan minor version dengan skrip Python, mencari changelog, menautkan dan merangkumnya, lalu menganalisis tingkat risiko tiap paket berdasarkan bagaimana paket itu dipakai di codebase
    Umumnya nyaris tidak menyakitkan, dan tidak perlu menaikkan paket satu per satu, memeriksa paket usang, atau menangani dependensi yang terbengkalai. Sangat jarang ada kasus yang butuh perbaikan dari penulis dependensi sehingga tidak bisa diselesaikan di kode kami, kira-kira setahun sekali. Dalam 3 bulan terakhir ada 18 kenaikan major version, dan hanya satu yang membutuhkan perubahan kode
    Saya ingin melakukan ini juga di frontend, tetapi tesnya belum cukup untuk dijalankan dengan aman. Tes backend lebih mudah ditulis dan lebih penting, jadi menurut saya semua codebase harus memilikinya. Kalau ada tes, Anda bisa langsung meng-upgrade semuanya secara otomatis

    • Menulis tes juga merupakan hal yang agen AI lakukan dengan baik
      Setidaknya mereka sangat bagus dalam mengubah instruksi bahasa alami menjadi tes yang akurat
      Sudah lama saya tidak menulis tes dengan tangan sendiri, dulu itu hal yang selalu saya keluhkan, sekarang tidak lagi
  • UV sudah banyak membantu Python, tetapi hari ini saya cukup bergulat dengannya
    Saya mencoba mengelola secara terpusat skrip-skrip yang tersebar di banyak repositori dan implementasinya makin berbeda seiring waktu
    Pendekatan yang saya bayangkan adalah uv run --with $package main --help, dan saya ingin secara otomatis 1) memasang lalu menjalankan jika belum ada, 2) tidak memasang jika sudah terbaru, 3) kalau belum terbaru maka diperbarui
    Namun ketiganya ternyata lebih rumit dari perkiraan. Pada dasarnya uv run memasang ulang setiap kali, dan butuh 6 detik untuk virtual environment dan instalasi
    uvx atau uv tool juga tidak jauh lebih baik, tetapi malah memunculkan masalah baru bahwa pengguna tidak mendapat upgrade
    Akhirnya saya membuat skrip mengirim GET pagination ke CodeArtifact, lalu jika ada versi non-development yang lebih baru maka diperbarui dan dijalankan ulang. Itu memang berfungsi, dan latensi 200ms lebih baik daripada 6 detik, tetapi bukan pengalaman yang saya inginkan

    • Saya agak bingung karena uv run --with $package main --help seharusnya melakukan perilaku yang Anda sebutkan dengan overhead yang sangat kecil
      Itu tidak memasang ulang setiap kali, dan environment --with disimpan di cache. Bahkan jika environment belum di-cache, dependensinya tetap di-cache, dan memasang dari cache sangat cepat. Seharusnya jelas di bawah 200ms
      Kalau Anda bisa membuka contoh reproduksi yang rinci, saya bisa melihatnya
    • Untuk penggunaan itu, uv tool install dan uv tool upgrade tampaknya yang tepat
      Tetapi ketidaknyamanan kecil seperti ini sepertinya relatif mudah diperbaiki, jadi akan bagus kalau Anda membuka issue
    • Anda juga bisa mendefinisikan dependensi yang diperlukan di blok dokumen di bagian atas file, lalu cukup menjalankan uv run main
      Maka dependensi yang diperlukan akan otomatis dipasang, di-cache, dan dijalankan: https://docs.astral.sh/uv/guides/scripts/
    • Bukankah pengguna bisa langsung menjalankan uv tool upgrade?
    • Mungkin juga layak melihat https://copier.readthedocs.io/en/stable/
      Saya tidak tahu apakah use case-nya persis sama, tetapi ini sangat bagus untuk menyinkronkan ekosistem microservice polyrepo
  • Saya cukup terkejut melihat rekomendasi "uv tree --outdated --depth 1" untuk melihat daftar dependensi lama
    Secara pribadi, sejak fitur itu diperkenalkan saya memakai "uv pip list --outdated"
    Namun saya setuju bahwa perintah sepenting ini pantas punya subperintah tingkat atas tersendiri

    • Dari sudut pandang penulis, itu lebih merupakan satu-satunya cara yang ia tahu, bukan rekomendasi
      Memang benar "uv pip list --outdated" memberi output yang jauh lebih baik, terima kasih
      Tetapi fakta bahwa ada sampai 2 cara untuk melihat paket usang dan output-nya sangat berbeda juga membuat saya merasa UX-nya berantakan
    • "uv tree -od1" mungkin juga akan bekerja
      Namun kritik terhadap manajer paket seperti pacman juga, seperti apt, adalah bahwa perintah yang sering dipakai seharusnya punya perintah yang mudah dipahami manusia
  • Dibanding kata “berantakan” di judulnya, contoh yang diberikan sebenarnya hanya soal perlu menulis beberapa argumen tambahan
    Judul yang lebih baik tampaknya peningkatan kualitas hidup yang saya harapkan ada di UV

    • Ungkapan itu dan frasa seperti “siapa yang merancang antarmuka command line ini” tampak ditujukan untuk menarik perhatian dan klik
      Feedback-nya sendiri berguna dan sebagian besar saya setujui, tetapi frasa seperti itu menurunkan nilai feedback dan memancing respons defensif
      Antarmuka command line uv menurut saya pribadi juga merepotkan, tetapi saya mengerti kenapa ditulis seperti ini
  • uv memang hebat, tetapi masalah terbesar Python packaging saat ini tetaplah menangani packaging saintifik/machine learning dengan baik
    Jika ingin memasang PyTorch, Anda harus memikirkan versinya, apakah CUDA, dan kalau CUDA maka ada 6 varian menurut versi CUDA, sementara wheel-nya terlalu besar untuk diunggah ke PyPI sehingga harus diambil langsung
    Conda hanya menyelesaikan masalah ini sebagian. Spack sangat bisa dikonfigurasi dan dapat menyiapkan dependensi C/C++/Fortran yang dibutuhkan beserta toolchain compiler untuk mengeluarkan performa tertinggi, tetapi tidak terintegrasi baik dengan uv dan semacamnya. Karena itu, sulit membawa proyek machine learning eksperimental buatan peneliti sampai ke produksi

    • Dulu saya mengakalinya dengan Anaconda, tetapi terlalu banyak bawaan tambahan dan environment pengembangan jadi sama sekali berbeda dari environment produksi, jadi itu juga kurang bagus
      Pada akhirnya kita kembali lagi ke situasi yang disebut di awal
  • Ada banyak feedback yang berguna, tetapi bercampur dengan ungkapan ala clickbait
    Soal pnpm outdated, selama ini memang tidak terlalu sering muncul, tetapi tampaknya itu permintaan yang masuk akal. Mungkin ini berasal dari perbedaan budaya antara Python dan JavaScript. Saya hampir tidak pernah peduli apakah dependensi itu usang kecuali rentan atau rusak, tetapi di ekosistem JavaScript tampaknya cukup umum untuk meng-upgrade saat ada kesempatan. Ini bukan berarti buruk, melainkan menunjukkan betapa berbeda intuisi tentang apa yang perlu ditampilkan di antarmuka command line antara komunitas pemrograman besar
    Seperti kata Armin, perilaku batas atas uv itu disengaja dan secara fungsional memang perlu karena cara resolusi Python bekerja. Ini adalah trade-off yang diambil Python dibanding bahasa lain, tetapi saya rasa ini trade-off yang baik karena hanya ada satu dari tiap dependensi di pohon dependensi dan semua kebutuhan yang saling terkait di-resolve agar cocok dengan itu
    Alasan uv lock --upgrade seperti itu adalah karena ia meng-upgrade lockfile, bukan requirement milik pengguna sendiri. Sebaliknya, pnpm update tampaknya meng-upgrade requirement pengguna di package.json. Ini memang bisa membingungkan, tetapi meletakkannya di bawah uv lock lebih akurat. Kalau tidak, akan ada pengguna yang bingung karena uv upgrade tidak melakukan upgrade seperti yang mereka bayangkan. Meski begitu, masih ada ruang untuk penyajian yang lebih rapi, dan memang jelas ada permintaan pengguna untuk subperintah uv yang juga langsung meng-upgrade requirement itu sendiri
    https://news.ycombinator.com/item?id=48230048

    • Saya setuju soal paket usang dan batas atas, tetapi jika pengguna mengeluh antarmukanya sulit, jelas ada sesuatu di situ
      Masuk akal bahwa perintah uv lock hanya menangani lockfile, tetapi pengguna punya kebutuhan nyata untuk meng-upgrade dependensi langsung dan transitif. Dependensi transitif bisa dilakukan dengan uv lock --upgrade-package, tetapi agak panjang. Itu juga bekerja pada dependensi langsung, tetapi tidak menyentuh pyproject.toml, padahal file ini jauh lebih terlihat bagi developer
      Jika versi paket di uv.lock melaju lebih jauh daripada pyproject.toml, maka pyproject.toml menjadi kurang bisa diandalkan sebagai panduan untuk memahami permukaan dependensi. Akan bagus jika ada perintah uv upgrade yang ramah
      Jebakan UX terbesar uv yang pernah saya lihat sejauh ini adalah uv pip. Banyak proyek yang memakai uv dengan benar untuk pengembangan lewat pyproject.toml dan uv.lock, tetapi di Dockerfile deployment atau tool CI mereka memakai uv pip install -r pyproject.toml sehingga melewati uv.lock
      Memang masalahnya agen coding punya terlalu banyak pip di data pelatihan sehingga merekomendasikan pola uv pip yang buruk, tetapi uv juga harus menyediakan pengaman untuk melindungi pengguna
      Menurut saya uv adalah alat yang hebat dan seharusnya dipakai lebih luas: https://aleyan.com/blog/2026-why-arent-we-uv-yet
    • Dari sudut pandang penulis, maaf kalau itu terlihat “ala clickbait”, tetapi sebenarnya itu hanya gaya bicara Belanda yang lugas dan terus terang
      poetry update juga meng-update lockfile. Saya merasa cara penyusunan CLI uv cukup menyebalkan untuk dipakai. Rasanya dirancang demi akurasi dan mesin, bukan demi keramahan bagi pengguna
    • Sebagai orang yang pindah dari pip ke uv, saat saya membutuhkan informasi itu saya akhirnya kembali ke uv pip list --outdated
    • uv upgrade ada di roadmap
      Alasan belum dikerjakan adalah karena sulit dibuat menjadi pengalaman yang hebat, nuansanya jauh lebih banyak daripada yang orang kira, timnya kecil, dan prioritasnya banyak
    • Salah satu kegunaan fitur ala pnpm outdated adalah untuk melihat apa yang akan di-update jika menjalankan "uv sync --update" atau "uv lock --update"
      Meski begitu, mungkin akan lebih baik jika perintah-perintah itu punya prompt konfirmasi
  • Pixi memakai uv sebagai backend, dan saya menyukai UI-nya karena mudah menambahkan alias task untuk menampilkan paket usang dengan rapi
    Khususnya Pixi-diff-to-markdown membuat update paket otomatis di CI mudah ditinjau sekilas
    Jika ingin melihat paket usang mana yang akan di-update, Anda bisa membuat alias task seperti ini di proyek
    pixi task add outdated "pixi update --dry-run --json | pixi exec pixi-diff-to-markdown"
    Lalu di proyek cukup jalankan pixi run outdated
    Output-nya berupa tabel Markdown yang mudah dibaca berisi paket yang akan di-update, versi lama, dan versi baru yang akan dipasang oleh perintah pixi update. Tentu saja ini bisa berbeda tergantung selera dan situasi

  • Baru-baru ini skrip env muncul di path saya dan mengganggu penggunaan perintah UNIX env yang normal
    Ternyata penginstal uv membuat ini saat menjalankan perintah di bawah
    curl -LsSf [https://astral.sh/uv/install.sh](<https://astral.sh/uv/install.sh>;) | sh
    Ia memasang ke $HOME/.cargo/bin/, lalu membuat skrip shell di $HOME/.cargo/env yang menambahkan $HOME/.cargo/bin/ ke depan PATH jika belum ada
    Sulit memahami programmer macam apa yang menulis kode yang menimpa perintah UNIX dasar dengan cara seperti ini