asdf: ตัวจัดการเวอร์ชันเครื่องมือพัฒนาซอฟต์แวร์แบบครบวงจร (asdf: The All-in-One Development Tool Version Manager)

asdf: The All-in-One Development Tool Version Manager

asdf คือตัวจัดการเวอร์ชันเครื่องมือพัฒนาซอฟต์แวร์แบบครบวงจรที่ใช้ไฟล์ .tool-versions เป็นแหล่งกลางในการกำหนดเวอร์ชันต่าง ๆ ต่อโปรเจกต์ แทนที่จะต้องใช้ nvm, pyenv, rbenv แยกกัน asdf รวมทุกอย่างไว้ในเครื่องมือเดียวผ่านระบบ Plugin ที่ขยายได้ไม่จำกัด บทความนี้ครอบคลุมตั้งแต่การติดตั้ง แนวคิด หลักการจัดการ Plugin ไปจนถึงการสร้าง Plugin ของตัวเองและการแก้ไขปัญหาที่พบบ่อย


1. บทนำ (Introduction)

1.1 ปัญหาของการจัดการเวอร์ชันเครื่องมือหลายตัว (The Problem of Managing Multiple Tool Versions)

นักพัฒนาซอฟต์แวร์ในยุคปัจจุบันต้องทำงานกับโปรเจกต์หลายโปรเจกต์พร้อมกัน ซึ่งแต่ละโปรเจกต์มักต้องการเวอร์ชันของเครื่องมือที่แตกต่างกัน ปัญหาที่พบบ่อย ได้แก่:

ตัวอย่างสถานการณ์จริง:

โปรเจกต์ทีม (ก่อนใช้ asdf)
├── project-legacy/         ← Node.js 14, Python 3.8, Ruby 2.7
├── project-current/        ← Node.js 18, Python 3.11, Ruby 3.1
├── project-ai/             ← Python 3.10 (ต้องการ CUDA-specific version)
└── devops-scripts/         ← Terraform 1.3, kubectl 1.25

การสลับโปรเจกต์แต่ละครั้งต้องรัน nvm use 14, pyenv local 3.8 ฯลฯ ด้วยตนเอง ซึ่งนำไปสู่ข้อผิดพลาดที่หลีกเลี่ยงได้ยาก


1.2 asdf คืออะไร (What is asdf?)

asdf คือ Extensible Version Manager (ตัวจัดการเวอร์ชันที่ขยายได้) ที่เขียนด้วย Bash โดยมีแนวคิดหลักคือใช้ไฟล์ .tool-versions เดียวในการประกาศเวอร์ชันของเครื่องมือทุกตัวในโปรเจกต์ asdf ทำงานผ่านระบบ Plugin ซึ่งแต่ละ Plugin รับผิดชอบเครื่องมือหนึ่งตัว (เช่น Node.js, Python, Ruby) ทำให้สามารถรองรับเครื่องมือได้ไม่จำกัด

คุณสมบัติหลักของ asdf:


1.3 ประวัติและที่มาของโปรเจกต์ (Project History and Background)

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#d5c4a1', 'secondaryColor': '#3c3836', 'tertiaryColor': '#504945', 'background': '#282828', 'mainBkg': '#282828', 'nodeBorder': '#83a598', 'clusterBkg': '#3c3836', 'titleColor': '#ebdbb2', 'edgeLabelBackground': '#3c3836', 'fontFamily': 'monospace'}}}%%
flowchart LR
    subgraph ERA1["🕰️ ยุคก่อน asdf (Before asdf Era) — 2009–2013"]
        A1["nvm 0.1\n2010\nNode.js version manager"] --> A2["rbenv 1.0\n2011\nRuby version manager"]
        A2 --> A3["pyenv\n2012\nPython version manager"]
    end

    subgraph ERA2["🚀 กำเนิด asdf (asdf Birth) — 2014–2016"]
        B1["HashiCorp releases\nTerraform 0.1\n2014"] --> B2["Metrick Langille\nสร้าง asdf v0.1\n2014"]
        B2 --> B3["Plugin system\nเปิดตัวครั้งแรก\n2015"]
        B3 --> B4["asdf v0.2\nรองรับ Legacy files\n2016"]
    end

    subgraph ERA3["🌱 การเติบโต (Growth Era) — 2017–2020"]
        C1["Plugin registry\nสาธารณะ\n2017"] --> C2["Fish shell\nsupport\n2018"]
        C2 --> C3["asdf v0.7\nปรับปรุง Performance\n2019"]
        C3 --> C4["500+ plugins\nในชุมชน\n2020"]
    end

    subgraph ERA4["⚡ ยุคสมัยใหม่ (Modern Era) — 2021–ปัจจุบัน"]
        D1["asdf v0.10\nรองรับ Nushell\n2022"] --> D2["asdf v0.13\nasdf set\nแทน global/local\n2023"]
        D2 --> D3["asdf v0.14+\nGo rewrite\nในการพัฒนา\n2024"]
    end

    ERA1 --> ERA2 --> ERA3 --> ERA4

    style ERA1 fill:#3c3836,stroke:#83a598,color:#ebdbb2
    style ERA2 fill:#3c3836,stroke:#b8bb26,color:#ebdbb2
    style ERA3 fill:#3c3836,stroke:#fabd2f,color:#ebdbb2
    style ERA4 fill:#3c3836,stroke:#fb4934,color:#ebdbb2
    style A1 fill:#282828,stroke:#83a598,color:#ebdbb2
    style A2 fill:#282828,stroke:#83a598,color:#ebdbb2
    style A3 fill:#282828,stroke:#83a598,color:#ebdbb2
    style B1 fill:#282828,stroke:#b8bb26,color:#ebdbb2
    style B2 fill:#282828,stroke:#b8bb26,color:#ebdbb2
    style B3 fill:#282828,stroke:#b8bb26,color:#ebdbb2
    style B4 fill:#282828,stroke:#b8bb26,color:#ebdbb2
    style C1 fill:#282828,stroke:#fabd2f,color:#ebdbb2
    style C2 fill:#282828,stroke:#fabd2f,color:#ebdbb2
    style C3 fill:#282828,stroke:#fabd2f,color:#ebdbb2
    style C4 fill:#282828,stroke:#fabd2f,color:#ebdbb2
    style D1 fill:#282828,stroke:#fb4934,color:#ebdbb2
    style D2 fill:#282828,stroke:#fb4934,color:#ebdbb2
    style D3 fill:#282828,stroke:#fb4934,color:#ebdbb2

จุดเปลี่ยนสำคัญ: ในเวอร์ชัน 0.13 คำสั่ง asdf global และ asdf local ถูกแทนที่ด้วย asdf set ซึ่งมีความยืดหยุ่นกว่า และในเวอร์ชัน 0.14+ โปรเจกต์กำลังเขียนใหม่ด้วย Go เพื่อประสิทธิภาพที่ดีขึ้น


1.4 เปรียบเทียบกับเครื่องมือประเภทเดียวกัน (Comparison with Similar Tools)

คุณสมบัติ asdf nvm pyenv rbenv mise
ภาษาที่รองรับ ทุกภาษา (600+) Node.js เท่านั้น Python เท่านั้น Ruby เท่านั้น หลายภาษา
ไฟล์กำหนดเวอร์ชัน .tool-versions .nvmrc .python-version .ruby-version .mise.toml
Legacy file support
Shell รองรับ Bash/Zsh/Fish/Nu Bash/Zsh Bash/Zsh/Fish Bash/Zsh Bash/Zsh/Fish/Nu
เขียนด้วยภาษา Bash Bash Shell/Python Shell Rust
ประสิทธิภาพ ปานกลาง ดี ดี ดี ดีมาก (Rust)
Plugin ecosystem ใหญ่มาก ไม่มี น้อย น้อย กำลังเติบโต
CI/CD integration
Windows native ❌ (WSL เท่านั้น)

1.5 ข้อดีของการใช้เครื่องมือเดียวแทนหลายเครื่องมือ (Benefits of Using a Single Unified Tool)


2. การติดตั้ง asdf (Installing asdf)

2.1 ข้อกำหนดเบื้องต้น (Prerequisites)

ก่อนติดตั้ง asdf ต้องมีสิ่งต่อไปนี้:

# ตรวจสอบ prerequisites บน Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y \
  curl \
  git \
  build-essential \
  libssl-dev \
  zlib1g-dev \
  libbz2-dev \
  libreadline-dev \
  libsqlite3-dev

# ตรวจสอบเวอร์ชัน git
git --version
# ควรได้ผลลัพธ์: git version 2.x.x

2.2 การติดตั้งบน Linux (Installation on Linux)

วิธีที่ 1: ติดตั้งผ่าน Git (แนะนำ)

# Clone asdf repository ไปยัง ~/.asdf
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0

# ตรวจสอบว่าโฟลเดอร์ถูกสร้าง
ls ~/.asdf
# ควรเห็น: asdf.sh  bin/  completions/  lib/  shims/  ...

วิธีที่ 2: ติดตั้งผ่าน Package Manager (Pacman บน Arch Linux)

# สำหรับ Arch Linux / Manjaro
yay -S asdf-vm

# หรือใช้ paru
paru -S asdf-vm

วิธีที่ 3: ติดตั้งบน Void Linux (ไม่ใช้ systemd)

# Void Linux ใช้ xbps
sudo xbps-install -S git curl

# จากนั้นติดตั้งผ่าน Git
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0

2.3 การติดตั้งบน macOS (Installation on macOS)

ผ่าน Homebrew (แนะนำสำหรับ macOS):

# ติดตั้งผ่าน Homebrew
brew install asdf

# Homebrew จัดการ PATH ให้อัตโนมัติ
# แต่ต้องตั้งค่า Shell ด้วยตนเองตามข้อ 2.5

ผ่าน Git:

git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0

2.4 การติดตั้งบน Windows ผ่าน WSL (Installation on Windows via WSL)

# 1. เปิด WSL 2 (Windows Subsystem for Linux)
# ใน PowerShell (Admin): wsl --install

# 2. อัปเดต packages
sudo apt-get update && sudo apt-get upgrade -y

# 3. ติดตั้ง dependencies
sudo apt-get install -y curl git build-essential

# 4. Clone asdf
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0

# 5. ตั้งค่า Shell ตามข้อ 2.5

หมายเหตุ: asdf ไม่รองรับ Windows PowerShell หรือ CMD โดยตรง ต้องใช้ผ่าน WSL หรือ Git Bash เท่านั้น


2.5 การตั้งค่า Shell (Shell Configuration)

Bash:

# เพิ่มใน ~/.bashrc หรือ ~/.bash_profile
echo '. "$HOME/.asdf/asdf.sh"' >> ~/.bashrc
echo '. "$HOME/.asdf/completions/asdf.bash"' >> ~/.bashrc

# โหลดการตั้งค่าใหม่
source ~/.bashrc

Zsh:

# เพิ่มใน ~/.zshrc
echo '. "$HOME/.asdf/asdf.sh"' >> ~/.zshrc

# โหลดการตั้งค่าใหม่
source ~/.zshrc

Fish Shell:

# เพิ่มใน ~/.config/fish/config.fish
echo 'source ~/.asdf/asdf.fish' >> ~/.config/fish/config.fish

# ติดตั้ง completions สำหรับ Fish
mkdir -p ~/.config/fish/completions
ln -s ~/.asdf/completions/asdf.fish ~/.config/fish/completions

# โหลดการตั้งค่าใหม่
source ~/.config/fish/config.fish

Nushell:

# เพิ่มใน $nu.config-path (env.nu)
let asdf_path = ($env.HOME | path join ".asdf")
$env.PATH = ($env.PATH | prepend ($asdf_path | path join "shims"))
$env.PATH = ($env.PATH | prepend ($asdf_path | path join "bin"))

# source asdf.nu
source ~/.asdf/asdf.nu

สำหรับผู้ติดตั้งผ่าน Homebrew บน macOS:

# Bash/Zsh ผ่าน Homebrew
echo '. $(brew --prefix asdf)/libexec/asdf.sh' >> ~/.zshrc

# Fish ผ่าน Homebrew
echo 'source (brew --prefix asdf)/libexec/asdf.fish' >> ~/.config/fish/config.fish

2.6 การตรวจสอบการติดตั้ง (Verifying the Installation)

# ตรวจสอบเวอร์ชัน asdf
asdf version
# ผลลัพธ์: v0.14.0-xxxx

# ตรวจสอบว่า asdf อยู่ใน PATH
which asdf
# ผลลัพธ์: /home/username/.asdf/bin/asdf

# ดูคำสั่งที่มีทั้งหมด
asdf help

3. แนวคิดหลักของ asdf (Core Concepts of asdf)

3.1 Plugin คืออะไรและทำงานอย่างไร (What are Plugins and How They Work)

Plugin คือสคริปต์ที่บอก asdf วิธีการติดตั้ง ลบ และสลับเวอร์ชันของเครื่องมือหนึ่งตัว โดยแต่ละ Plugin คือ Git repository ที่มีโครงสร้างตามมาตรฐาน

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#d5c4a1', 'secondaryColor': '#3c3836', 'tertiaryColor': '#504945', 'background': '#282828', 'mainBkg': '#3c3836', 'nodeBorder': '#83a598', 'clusterBkg': '#3c3836', 'titleColor': '#ebdbb2', 'edgeLabelBackground': '#3c3836', 'fontFamily': 'monospace'}}}%%
graph TD
    USER["👤 ผู้ใช้ (User)"]
    ASDF["⚙️ asdf core\n~/.asdf/bin/asdf"]
    REGISTRY["📋 Plugin Registry\nGitHub asdf-vm/asdf-plugins"]

    subgraph PLUGINS["🧩 Installed Plugins (~/.asdf/plugins/)"]
        P1["asdf-nodejs\n(bin/list-all, bin/install...)"]
        P2["asdf-python\n(bin/list-all, bin/install...)"]
        P3["asdf-ruby\n(bin/list-all, bin/install...)"]
    end

    subgraph INSTALLS["📦 Installed Versions (~/.asdf/installs/)"]
        I1["nodejs/18.20.0/\nnodejs/20.15.0/"]
        I2["python/3.11.0/\npython/3.12.0/"]
        I3["ruby/3.2.0/"]
    end

    subgraph SHIMS["🔗 Shims (~/.asdf/shims/)"]
        S1["node → shim"]
        S2["python → shim"]
        S3["ruby → shim"]
        S4["npm → shim"]
        S5["pip → shim"]
    end

    USER -->|"asdf plugin add nodejs"| ASDF
    ASDF -->|"lookup plugin URL"| REGISTRY
    REGISTRY -->|"return git URL"| ASDF
    ASDF -->|"git clone"| PLUGINS
    ASDF -->|"call bin/install"| INSTALLS
    ASDF -->|"create shims"| SHIMS
    SHIMS -->|"redirect to correct version"| INSTALLS

    style USER fill:#282828,stroke:#b8bb26,color:#ebdbb2
    style ASDF fill:#282828,stroke:#83a598,color:#ebdbb2
    style REGISTRY fill:#282828,stroke:#d3869b,color:#ebdbb2
    style PLUGINS fill:#3c3836,stroke:#fabd2f,color:#ebdbb2
    style INSTALLS fill:#3c3836,stroke:#8ec07c,color:#ebdbb2
    style SHIMS fill:#3c3836,stroke:#fe8019,color:#ebdbb2
    style P1 fill:#282828,stroke:#fabd2f,color:#ebdbb2
    style P2 fill:#282828,stroke:#fabd2f,color:#ebdbb2
    style P3 fill:#282828,stroke:#fabd2f,color:#ebdbb2
    style I1 fill:#282828,stroke:#8ec07c,color:#ebdbb2
    style I2 fill:#282828,stroke:#8ec07c,color:#ebdbb2
    style I3 fill:#282828,stroke:#8ec07c,color:#ebdbb2
    style S1 fill:#282828,stroke:#fe8019,color:#ebdbb2
    style S2 fill:#282828,stroke:#fe8019,color:#ebdbb2
    style S3 fill:#282828,stroke:#fe8019,color:#ebdbb2
    style S4 fill:#282828,stroke:#fe8019,color:#ebdbb2
    style S5 fill:#282828,stroke:#fe8019,color:#ebdbb2

3.2 ไฟล์ .tool-versions และความสำคัญ (The .tool-versions File and Its Importance)

ไฟล์ .tool-versions คือไฟล์ plain text ที่ประกาศเวอร์ชันของเครื่องมือในโปรเจกต์นั้น ๆ ไฟล์นี้ควรเพิ่มใน version control (Git) เพื่อให้ทุกคนในทีมใช้เวอร์ชันเดียวกัน

# ตัวอย่างไฟล์ .tool-versions
nodejs 20.15.0
python 3.11.9
ruby 3.2.4
terraform 1.7.0
kubectl 1.29.0
golang 1.22.0

ความสำคัญของไฟล์ .tool-versions:


3.3 การกำหนดเวอร์ชันระดับ Global, Local และ Shell (Global, Local, and Shell Version Scoping)

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#d5c4a1', 'background': '#282828', 'mainBkg': '#3c3836', 'nodeBorder': '#83a598', 'clusterBkg': '#3c3836', 'titleColor': '#ebdbb2', 'edgeLabelBackground': '#3c3836', 'fontFamily': 'monospace'}}}%%
graph TB
    subgraph PRIORITY["ลำดับความสำคัญ (Priority Order) — สูงสุดไปต่ำสุด"]
        S["🔴 SHELL\n$ASDF_NODEJS_VERSION=20.15.0\nสูงสุด — ใช้เฉพาะ Session ปัจจุบัน"]
        L["🟡 LOCAL\n~/.../project/.tool-versions\nต่อโปรเจกต์ — commit ลง Git"]
        G["🟢 GLOBAL\n~/.tool-versions\nค่าเริ่มต้นทั้งระบบ"]
        SYS["⚪ SYSTEM\nVersion ที่ OS ติดตั้งมา\nต่ำสุด — fallback"]
    end

    S -->|"ถ้าไม่มี Shell override"| L
    L -->|"ถ้าไม่มี .tool-versions"| G
    G -->|"ถ้าไม่มี Global config"| SYS

    style PRIORITY fill:#3c3836,stroke:#83a598,color:#ebdbb2
    style S fill:#282828,stroke:#fb4934,color:#ebdbb2
    style L fill:#282828,stroke:#fabd2f,color:#ebdbb2
    style G fill:#282828,stroke:#b8bb26,color:#ebdbb2
    style SYS fill:#282828,stroke:#928374,color:#ebdbb2
ระดับ ตำแหน่งไฟล์ คำสั่ง ขอบเขต
Shell Environment variable asdf shell nodejs 20.15.0 เฉพาะ terminal session ปัจจุบัน
Local [project]/.tool-versions asdf set nodejs 20.15.0 เฉพาะโปรเจกต์นั้น
Global ~/.tool-versions asdf set --home nodejs 20.15.0 ทั้งระบบ (default)
System ระบบปฏิบัติการ asdf set nodejs system ใช้ version จาก OS

3.4 Legacy Version Files (Legacy Version File Support)

asdf รองรับไฟล์กำหนดเวอร์ชันของเครื่องมืออื่น ๆ (Legacy version files) เช่น .nvmrc, .python-version, .ruby-version โดยต้องเปิดใช้งานใน ~/.asdfrc

# ~/.asdfrc
legacy_version_file = yes

หลังจากเปิดใช้งาน:

ข้อควรทราบ: Legacy file support ขึ้นอยู่กับ Plugin — Plugin ต้องมีสคริปต์ bin/list-legacy-filenames ด้วย


3.5 Shim คืออะไรและทำงานอย่างไร (What are Shims and How They Work)

Shim คือ executable script ขนาดเล็กที่อยู่ใน ~/.asdf/shims/ ทำหน้าที่เป็น proxy ระหว่างผู้ใช้กับ binary จริง เมื่อผู้ใช้รันคำสั่งเช่น node, asdf จะ intercept ผ่าน shim และเลือก binary ที่ถูกต้องตามเวอร์ชัน

ขั้นตอนการทำงานของ Shim:

  1. ผู้ใช้พิมพ์คำสั่ง node --version
  2. Shell ค้นหา node ใน PATH → พบ ~/.asdf/shims/node
  3. Shim รัน asdf เพื่อหา version ที่ควรใช้
  4. asdf ตรวจสอบ (ตามลำดับ): Shell env → .tool-versions ในโฟลเดอร์ปัจจุบัน → .tool-versions ในโฟลเดอร์แม่ → ~/.tool-versions
  5. asdf เรียกใช้ ~/.asdf/installs/nodejs/[version]/bin/node --version
# ดูเนื้อหาของ Shim
cat ~/.asdf/shims/node
# #!/usr/bin/env bash
# # asdf-plugin: nodejs
# exec /home/user/.asdf/bin/asdf exec "nodejs" "node" "$@"

# Shim ถูกสร้างใหม่ได้ด้วย
asdf reshim nodejs

4. การจัดการ Plugin (Plugin Management)

4.1 การค้นหา Plugin ที่มีให้ใช้งาน (Searching for Available Plugins)

# แสดงรายการ Plugin ทั้งหมดในทะเบียนสาธารณะ
asdf plugin list all

# ค้นหา Plugin เฉพาะ (grep)
asdf plugin list all | grep -i node
# asdf-nodejs    https://github.com/asdf-vm/asdf-nodejs.git

# ค้นหาผ่าน Web browser
# https://github.com/asdf-vm/asdf-plugins

4.2 การเพิ่ม Plugin (Adding a Plugin)

# เพิ่ม Plugin จาก Registry สาธารณะ (ระบุชื่ออย่างเดียว)
asdf plugin add nodejs

# เพิ่ม Plugin พร้อมระบุ URL (สำหรับ Plugin นอก registry)
asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git

# เพิ่ม Plugin หลายตัวพร้อมกัน
asdf plugin add nodejs python ruby golang terraform

Plugin ยอดนิยมที่ควรติดตั้ง:

# ภาษาโปรแกรม
asdf plugin add nodejs
asdf plugin add python
asdf plugin add ruby
asdf plugin add golang
asdf plugin add rust
asdf plugin add java

# DevOps tools
asdf plugin add terraform
asdf plugin add kubectl
asdf plugin add helm
asdf plugin add awscli

# Erlang/Elixir ecosystem
asdf plugin add erlang
asdf plugin add elixir

4.3 การอัปเดต Plugin (Updating Plugins)

# อัปเดต Plugin ทีละตัว
asdf plugin update nodejs

# อัปเดต Plugin ทั้งหมดพร้อมกัน
asdf plugin update --all

# ตรวจสอบเวอร์ชัน Plugin (Git commit hash)
asdf plugin list --urls --refs

4.4 การลบ Plugin (Removing a Plugin)

# ลบ Plugin (และ versions ที่ติดตั้งทั้งหมดจะยังคงอยู่ใน ~/.asdf/installs/)
asdf plugin remove nodejs

# หมายเหตุ: การลบ Plugin ไม่ได้ลบ installed versions
# ต้องลบ versions ก่อนหรือลบโฟลเดอร์ด้วยตนเอง
ls ~/.asdf/installs/nodejs/
rm -rf ~/.asdf/installs/nodejs/  # ลบทั้งหมด (ระวัง!)

4.5 การแสดงรายการ Plugin ที่ติดตั้งแล้ว (Listing Installed Plugins)

# แสดงรายการ Plugin ที่ติดตั้ง
asdf plugin list
# nodejs
# python
# ruby
# terraform

# แสดงพร้อม URL และ Git ref
asdf plugin list --urls
# nodejs  https://github.com/asdf-vm/asdf-nodejs.git

asdf plugin list --refs
# nodejs  master  abc1234

4.6 การเพิ่ม Plugin จาก Repository ส่วนตัว (Adding Plugins from Custom Repositories)

# ใช้ URL ของ Git repository โดยตรง
asdf plugin add my-tool https://github.com/myorg/asdf-my-tool.git

# ใช้ path ท้องถิ่น (สำหรับการพัฒนา Plugin)
asdf plugin add my-tool file:///home/user/dev/asdf-my-tool

# ระบุ branch เฉพาะ (ผ่านการแก้ไข .git/config ใน plugin directory)
# หลังจากเพิ่ม plugin แล้ว
cd ~/.asdf/plugins/my-tool
git checkout feature-branch

5. การจัดการเวอร์ชันของเครื่องมือ (Tool Version Management)

5.1 การติดตั้งเวอร์ชัน (Installing a Version)

# ติดตั้งเวอร์ชันเฉพาะ
asdf install nodejs 20.15.0

# ติดตั้งเวอร์ชัน latest (ถ้า Plugin รองรับ)
asdf install nodejs latest

# ติดตั้ง latest ของ major version
asdf install nodejs latest:18

# ติดตั้งทุกเวอร์ชันที่ระบุใน .tool-versions ในโฟลเดอร์ปัจจุบัน
asdf install

# ตัวอย่าง: ติดตั้ง Java (ต้องระบุ variant)
asdf install java temurin-21.0.3+9

5.2 การแสดงเวอร์ชันที่มีให้ติดตั้ง (Listing Available Versions)

# แสดงเวอร์ชันทั้งหมดที่มี
asdf list all nodejs

# กรองด้วย grep
asdf list all nodejs | grep "^20\."
# 20.0.0
# 20.1.0
# ...
# 20.15.0

# แสดง latest version
asdf latest nodejs
# 22.4.0

# แสดง latest ของ major version
asdf latest nodejs 20
# 20.15.0

5.3 การแสดงเวอร์ชันที่ติดตั้งแล้ว (Listing Installed Versions)

# แสดงเวอร์ชันที่ติดตั้งแล้วสำหรับ tool ทั้งหมด
asdf list

# แสดงเฉพาะ tool ที่ระบุ
asdf list nodejs
#   18.20.4
# * 20.15.0    ← * หมายถึงเวอร์ชันที่ใช้งานอยู่ในขณะนี้
#   22.4.0

# แสดงเวอร์ชันที่ใช้งานอยู่ทั้งหมด
asdf current
# nodejs          20.15.0   /home/user/projects/myapp/.tool-versions
# python          3.11.9    /home/user/projects/myapp/.tool-versions
# terraform       1.7.0     /home/user/.tool-versions

5.4 การตั้งค่าเวอร์ชันด้วย asdf set (Setting Versions with asdf set)

5.4.1 รูปแบบและ Syntax ของคำสั่ง (Command Syntax and Format)

คำสั่ง asdf set เป็นคำสั่งหลักสำหรับกำหนดเวอร์ชันใน asdf 0.13+ มีรูปแบบดังนี้:

asdf set [--home] [--parent] <name> <version> [<version>...]
Flag/Argument ความหมาย
(ไม่มี flag) เขียนลงไฟล์ .tool-versions ในโฟลเดอร์ปัจจุบัน
--home เขียนลง ~/.tool-versions (global)
--parent เขียนลงไฟล์ .tool-versions ของโฟลเดอร์แม่ที่ใกล้ที่สุด
<name> ชื่อ Tool (เช่น nodejs, python)
<version> เวอร์ชันที่ต้องการ หรือ latest

5.4.2 การตั้งค่าเวอร์ชัน Local ต่อโปรเจกต์ด้วย asdf set

# ไปยังโฟลเดอร์โปรเจกต์
cd ~/projects/my-web-app

# กำหนดเวอร์ชัน Node.js สำหรับโปรเจกต์นี้
asdf set nodejs 20.15.0

# ตรวจสอบผล — ไฟล์ .tool-versions ถูกสร้าง/อัปเดต
cat .tool-versions
# nodejs 20.15.0

# กำหนดหลาย tools พร้อมกัน (ต้องรันทีละบรรทัด)
asdf set nodejs 20.15.0
asdf set python 3.11.9
asdf set terraform 1.7.0

# ผลลัพธ์ .tool-versions
cat .tool-versions
# nodejs 20.15.0
# python 3.11.9
# terraform 1.7.0

5.4.3 การตั้งค่าเวอร์ชัน Global ด้วย Flag --home

# กำหนด Node.js เวอร์ชัน Global (ทั้งระบบ)
asdf set --home nodejs 20.15.0

# กำหนด Python เวอร์ชัน Global
asdf set --home python 3.12.0

# ตรวจสอบ ~/.tool-versions
cat ~/.tool-versions
# nodejs 20.15.0
# python 3.12.0

5.4.4 การตั้งค่าเวอร์ชันในไดเรกทอรีที่ระบุด้วย Flag --parent

# สมมติโครงสร้าง:
# ~/projects/
# ├── .tool-versions    ← ต้องการเขียนที่นี่
# ├── frontend/
# │   └── (อยู่ที่นี่)
# └── backend/

cd ~/projects/frontend

# --parent เขียนลงไฟล์ .tool-versions ของโฟลเดอร์แม่ที่ใกล้ที่สุด
asdf set --parent nodejs 20.15.0

# ผลลัพธ์: ~/projects/.tool-versions ถูกอัปเดต
cat ~/projects/.tool-versions
# nodejs 20.15.0

5.4.5 ความแตกต่างระหว่าง asdf set กับ asdf global และ asdf local ในเวอร์ชันเก่า

คำสั่งเก่า (deprecated) คำสั่งใหม่ ความแตกต่าง
asdf global nodejs 18.0.0 asdf set --home nodejs 18.0.0 เหมือนกัน
asdf local nodejs 18.0.0 asdf set nodejs 18.0.0 เหมือนกัน
ไม่มี asdf set --parent nodejs 18.0.0 เพิ่มใหม่ใน asdf set

หมายเหตุ: asdf global และ asdf local ยังใช้งานได้ใน asdf 0.13+ แต่เป็น deprecated aliases — แนะนำให้ใช้ asdf set แทน


5.5 การตั้งค่าเวอร์ชันชั่วคราวใน Session (Setting Version for Current Shell Session)

# กำหนดเวอร์ชันชั่วคราวเฉพาะ terminal นี้
asdf shell nodejs 18.20.4

# ตรวจสอบ
node --version
# v18.20.4

# เปิด terminal ใหม่ → กลับไปใช้เวอร์ชัน local/global
# วิธีทำงานภายใน: ตั้งค่า env variable
echo $ASDF_NODEJS_VERSION
# 18.20.4

# ยกเลิก shell override
unset ASDF_NODEJS_VERSION

5.6 การลบเวอร์ชันที่ไม่ใช้งาน (Uninstalling a Version)

# ลบเวอร์ชันเฉพาะ
asdf uninstall nodejs 18.20.4

# ตรวจสอบว่าลบแล้ว
asdf list nodejs
# * 20.15.0
#   22.4.0

# ลบ version ที่ไม่ได้ใช้งานทั้งหมด (ด้วย script)
# asdf ไม่มีคำสั่ง prune ในตัว ต้องทำเอง
for version in $(asdf list nodejs | grep -v '*' | tr -d ' '); do
  echo "Removing nodejs $version..."
  asdf uninstall nodejs "$version"
done

5.7 การตรวจสอบเวอร์ชันที่กำลังใช้งาน (Checking Currently Active Version)

# ดูเวอร์ชันที่ใช้งานอยู่ทั้งหมด
asdf current
# nodejs          20.15.0   /home/user/project/.tool-versions
# python          3.11.9    /home/user/project/.tool-versions
# terraform       1.7.0     /home/user/.tool-versions

# ดูเฉพาะ tool ที่ระบุ
asdf current nodejs
# nodejs          20.15.0   /home/user/project/.tool-versions

# ดู binary path ที่ใช้งานอยู่จริง
asdf which node
# /home/user/.asdf/installs/nodejs/20.15.0/bin/node

6. การใช้งานไฟล์ .tool-versions (Working with .tool-versions File)

6.1 โครงสร้างและรูปแบบของไฟล์ (File Structure and Format)

ไฟล์ .tool-versions มีรูปแบบ plain text ง่ายมาก:

# รูปแบบ: <tool-name> <version> [<version2> ...]
# บรรทัดที่เริ่มด้วย # คือ comment
# สามารถระบุหลาย version ต่อ tool (สำหรับ compatibility)

nodejs 20.15.0
python 3.11.9 3.10.14
ruby 3.2.4
terraform 1.7.0
kubectl 1.29.6
helm 3.15.2
golang 1.22.5

กฎของรูปแบบ:


6.2 การสร้างและแก้ไขไฟล์ด้วยตนเอง (Creating and Editing the File Manually)

# สร้างไฟล์ด้วย text editor
cd ~/projects/my-project
nano .tool-versions

# หรือสร้างด้วย heredoc
cat > .tool-versions << 'EOF'
nodejs 20.15.0
python 3.11.9
terraform 1.7.0
EOF

# ตรวจสอบไฟล์
cat .tool-versions

# asdf จะอ่านไฟล์นี้อัตโนมัติ
asdf current

6.3 การใช้งานร่วมกับทีมและ Version Control (Using with Teams and Version Control)

# เพิ่ม .tool-versions ใน Git (ควรทำเสมอ)
git add .tool-versions
git commit -m "chore: add .tool-versions for consistent development environment"

# ตัวอย่าง .gitignore — ไม่ควร ignore .tool-versions
# .gitignore ที่ดีสำหรับ Node.js project:
cat >> .gitignore << 'EOF'
node_modules/
dist/
.env
# ไม่ต้อง ignore .tool-versions!
EOF

กระบวนการสำหรับทีม:

  1. นักพัฒนา A สร้าง .tool-versions และ commit
  2. นักพัฒนา B clone repository
  3. นักพัฒนา B รัน asdf install → ติดตั้งทุกเวอร์ชันที่ระบุ
  4. ทั้งสองทำงานบน environment เดียวกัน

6.4 การสืบทอดเวอร์ชันจากไดเรกทอรีแม่ (Version Inheritance from Parent Directories)

asdf ค้นหาไฟล์ .tool-versions จากโฟลเดอร์ปัจจุบันขึ้นไปจนถึง root:

/home/user/
├── .tool-versions          ← Global fallback (nodejs 20.x, python 3.12)
└── projects/
    ├── .tool-versions      ← Override (nodejs 18.x)
    ├── frontend/
    │   ├── .tool-versions  ← Override (nodejs 20.x)
    │   └── src/
    │       └── (ไม่มี .tool-versions → สืบทอดจาก frontend/)
    └── backend/
        └── (ไม่มี .tool-versions → สืบทอดจาก projects/)
# ทดสอบการสืบทอด
cd /home/user/projects/backend
asdf current nodejs
# nodejs  18.20.4  /home/user/projects/.tool-versions

cd /home/user/projects/frontend/src
asdf current nodejs
# nodejs  20.15.0  /home/user/projects/frontend/.tool-versions

6.5 การใช้ asdf install เพื่อติดตั้งทุกเวอร์ชันจากไฟล์พร้อมกัน

# อ่าน .tool-versions และติดตั้งทุก version ที่ยังไม่มี
cd ~/projects/my-project
asdf install
# Installing nodejs 20.15.0...
# Installing python 3.11.9...
# Installing terraform 1.7.0...

# ตรวจสอบหลังติดตั้ง
asdf current
# nodejs    20.15.0  /home/user/projects/my-project/.tool-versions
# python    3.11.9   /home/user/projects/my-project/.tool-versions
# terraform 1.7.0    /home/user/projects/my-project/.tool-versions

6.6 ความสัมพันธ์ระหว่าง asdf set กับการเขียนลงไฟล์ .tool-versions โดยตรง

# คำสั่ง asdf set = เขียน/แก้ไขไฟล์ .tool-versions โดยอัตโนมัติ

# วิธีที่ 1: ใช้ asdf set
asdf set nodejs 20.15.0
# ผล: เขียน "nodejs 20.15.0" ลงใน .tool-versions

# วิธีที่ 2: แก้ไขไฟล์ตรงๆ
echo "nodejs 20.15.0" >> .tool-versions

# ทั้งสองวิธีให้ผลเหมือนกัน
# แต่ asdf set ดีกว่าเพราะ:
# 1. อัปเดต entry ที่มีอยู่แล้วแทนการเพิ่มซ้ำ
# 2. จัดการ edge cases เช่น trailing whitespace
# 3. สะดวกกว่าในการเขียน script

7.1 Node.js — asdf-nodejs

# ติดตั้ง Plugin
asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git

# (ต้องการ GPG keys สำหรับ verification)
bash -c '${ASDF_DATA_DIR:=$HOME/.asdf}/plugins/nodejs/bin/import-release-team-keyring'

# ติดตั้ง Node.js
asdf install nodejs 20.15.0
asdf install nodejs lts   # ติดตั้ง LTS ล่าสุด

# ตั้งค่า
asdf set --home nodejs 20.15.0

# ทดสอบ
node --version    # v20.15.0
npm --version     # 10.x.x

7.2 Python — asdf-python

# Prerequisites สำหรับ Python (Ubuntu)
sudo apt-get install -y \
  libssl-dev zlib1g-dev libbz2-dev \
  libreadline-dev libsqlite3-dev \
  libncursesw5-dev xz-utils tk-dev \
  libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

# ติดตั้ง Plugin
asdf plugin add python https://github.com/danhper/asdf-python.git

# ติดตั้ง Python
asdf install python 3.11.9
asdf install python 3.12.4

# ตั้งค่า global
asdf set --home python 3.12.4

# ทดสอบ
python --version    # Python 3.12.4
pip --version       # pip 24.x

# ตั้งค่า pip ไม่ให้ require virtual env (optional)
export PIP_REQUIRE_VIRTUALENV=false

7.3 Ruby — asdf-ruby

# Prerequisites (Ubuntu)
sudo apt-get install -y \
  libssl-dev libreadline-dev \
  zlib1g-dev libyaml-dev

# ติดตั้ง Plugin
asdf plugin add ruby https://github.com/asdf-vm/asdf-ruby.git

# ติดตั้ง Ruby
asdf install ruby 3.3.3

# ตั้งค่า
asdf set --home ruby 3.3.3

# ทดสอบ
ruby --version   # ruby 3.3.3
gem --version    # 3.x.x

7.4 Go — asdf-golang

# ติดตั้ง Plugin
asdf plugin add golang https://github.com/asdf-community/asdf-golang.git

# ติดตั้ง Go
asdf install golang 1.22.5

# ตั้งค่า GOPATH (เพิ่มใน .bashrc/.zshrc)
export GOPATH="$HOME/go"
export PATH="$PATH:$GOPATH/bin"

# ตั้งค่า
asdf set --home golang 1.22.5

# ทดสอบ
go version    # go version go1.22.5 linux/amd64

7.5 Java — asdf-java

# ติดตั้ง Plugin
asdf plugin add java https://github.com/halcyon/asdf-java.git

# ดู distribution ที่มี
asdf list all java | grep temurin | head -20

# ติดตั้ง Adoptium Temurin 21 (LTS)
asdf install java temurin-21.0.3+9

# ตั้งค่า JAVA_HOME (เพิ่มใน .bashrc)
. ~/.asdf/plugins/java/set-java-home.bash  # สำหรับ Bash
# . ~/.asdf/plugins/java/set-java-home.zsh  # สำหรับ Zsh

# ตั้งค่า
asdf set --home java temurin-21.0.3+9

# ทดสอบ
java --version    # openjdk 21.0.3

7.6 Rust — asdf-rust

# ติดตั้ง Plugin
asdf plugin add rust https://github.com/code-lever/asdf-rust.git

# ติดตั้ง Rust stable
asdf install rust stable
asdf install rust 1.79.0

# ตั้งค่า
asdf set --home rust stable

# ทดสอบ
rustc --version    # rustc 1.79.0
cargo --version    # cargo 1.79.0

7.7 Erlang และ Elixir — asdf-erlang, asdf-elixir

# Prerequisites สำหรับ Erlang (Ubuntu)
sudo apt-get install -y \
  build-essential autoconf m4 libncurses5-dev \
  libwxwidgets-dev libgl1-mesa-dev libglu1-mesa-dev \
  libpng-dev libssh-dev unixodbc-dev xsltproc fop \
  libxml2-utils libncurses-dev openjdk-11-jdk

# ติดตั้ง Erlang ก่อน (Elixir ต้องการ Erlang)
asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git
asdf install erlang 26.2.5
asdf set --home erlang 26.2.5

# ติดตั้ง Elixir
asdf plugin add elixir https://github.com/asdf-vm/asdf-elixir.git
asdf install elixir 1.17.1-otp-26
asdf set --home elixir 1.17.1-otp-26

# ตั้งค่า .tool-versions สำหรับ Elixir project
cat > .tool-versions << 'EOF'
erlang 26.2.5
elixir 1.17.1-otp-26
nodejs 20.15.0
EOF

# ทดสอบ
erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().'
# "26"
elixir --version
# Erlang/OTP 26 [erts-14.x]
# Elixir 1.17.1 (compiled with Erlang/OTP 26)

7.8 Terraform และเครื่องมือ DevOps (Terraform and DevOps Tools)

# Terraform
asdf plugin add terraform https://github.com/asdf-community/asdf-hashicorp.git
asdf install terraform 1.9.0
asdf set --home terraform 1.9.0

# kubectl
asdf plugin add kubectl https://github.com/asdf-community/asdf-kubectl.git
asdf install kubectl 1.30.2
asdf set --home kubectl 1.30.2

# Helm
asdf plugin add helm https://github.com/Antiarchitect/asdf-helm.git
asdf install helm 3.15.2
asdf set --home helm 3.15.2

# AWS CLI
asdf plugin add awscli https://github.com/MetricMike/asdf-awscli.git
asdf install awscli 2.17.0
asdf set --home awscli 2.17.0

# ตัวอย่าง .tool-versions สำหรับ DevOps project
cat > .tool-versions << 'EOF'
terraform 1.9.0
kubectl 1.30.2
helm 3.15.2
awscli 2.17.0
EOF

# ติดตั้งทั้งหมดพร้อมกัน
asdf install

8. การรวม asdf เข้ากับเวิร์กโฟลว์การพัฒนา (Integrating asdf into Development Workflows)

8.1 การใช้งานร่วมกับ Direnv (Using with Direnv)

direnv เป็นเครื่องมือที่โหลด environment variables จากไฟล์ .envrc อัตโนมัติเมื่อเข้าไดเรกทอรี การใช้ร่วมกับ asdf ช่วยให้ตั้งค่า environment ได้ละเอียดขึ้น

# ติดตั้ง direnv
asdf plugin add direnv https://github.com/asdf-community/asdf-direnv.git
asdf install direnv latest
asdf set --home direnv latest

# ตั้งค่า direnv hook (เพิ่มใน .bashrc)
eval "$(direnv hook bash)"

# ตัวอย่าง .envrc ในโปรเจกต์
cat > .envrc << 'EOF'
# ใช้เวอร์ชันจาก .tool-versions
use asdf

# ตั้งค่า environment variables เพิ่มเติม
export DATABASE_URL="postgres://localhost/myapp_dev"
export NODE_ENV="development"
export RAILS_ENV="development"
EOF

# อนุญาต direnv
direnv allow .

8.2 การตั้งค่าใน CI/CD Pipeline (Configuration in CI/CD Pipelines)

GitHub Actions:

# .github/workflows/ci.yml
name: CI Pipeline

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # ใช้ .tool-versions เพื่อกำหนดเวอร์ชัน
      - name: Install asdf
        uses: asdf-vm/actions/setup@v3

      - name: Install plugins and versions
        uses: asdf-vm/actions/install@v3
        # อ่านจาก .tool-versions อัตโนมัติ

      - name: Verify versions
        run: |
          node --version
          python --version

      - name: Run tests
        run: npm test

GitLab CI:

# .gitlab-ci.yml
image: ubuntu:22.04

before_script:
  # ติดตั้ง asdf
  - apt-get update && apt-get install -y git curl
  - git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
  - . ~/.asdf/asdf.sh
  # ติดตั้ง plugins จาก .tool-versions
  - |
    while IFS= read -r line; do
      tool=$(echo "$line" | awk '{print $1}')
      asdf plugin add "$tool" 2>/dev/null || true
    done < .tool-versions
  - asdf install

test:
  script:
    - node --version
    - npm test

8.3 การใช้งานใน Docker Container (Usage inside Docker Containers)

# Dockerfile ที่ใช้ asdf
FROM ubuntu:22.04

# ติดตั้ง dependencies
RUN apt-get update && apt-get install -y \
    git curl build-essential \
    && rm -rf /var/lib/apt/lists/*

# ติดตั้ง asdf
RUN git clone https://github.com/asdf-vm/asdf.git /root/.asdf --branch v0.14.0

# ตั้งค่า PATH
ENV PATH="/root/.asdf/shims:/root/.asdf/bin:$PATH"
ENV BASH_ENV="/root/.asdf/asdf.sh"

# copy .tool-versions
COPY .tool-versions /app/.tool-versions
WORKDIR /app

# ติดตั้ง plugins และ versions
RUN bash -c '. /root/.asdf/asdf.sh && \
    asdf plugin add nodejs && \
    asdf plugin add python && \
    asdf install'

# เปิดใช้ asdf ใน shell
SHELL ["/bin/bash", "-c"]
RUN echo '. /root/.asdf/asdf.sh' >> /root/.bashrc

COPY . .

8.4 การแชร์สภาพแวดล้อมกับสมาชิกในทีม (Sharing Environment with Team Members)

# สร้าง script สำหรับ onboarding
cat > setup-dev-env.sh << 'EOF'
#!/usr/bin/env bash
# setup-dev-env.sh — ตั้งค่า development environment อัตโนมัติ

set -e

echo "🚀 กำลังตั้งค่า development environment..."

# ตรวจสอบว่า asdf ถูกติดตั้งแล้ว
if ! command -v asdf &> /dev/null; then
    echo "📦 ติดตั้ง asdf..."
    git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
    echo '. "$HOME/.asdf/asdf.sh"' >> ~/.bashrc
    source ~/.bashrc
fi

# ติดตั้ง plugins จาก .tool-versions
echo "🔌 ติดตั้ง asdf plugins..."
while IFS= read -r line; do
    [[ "$line" =~ ^#.*$ ]] && continue
    [[ -z "$line" ]] && continue
    tool=$(echo "$line" | awk '{print $1}')
    if ! asdf plugin list | grep -q "^$tool$"; then
        echo "  Adding plugin: $tool"
        asdf plugin add "$tool" 2>/dev/null || echo "  ⚠️  ไม่พบ $tool ใน registry"
    fi
done < .tool-versions

# ติดตั้ง versions
echo "📥 ติดตั้ง tool versions..."
asdf install

echo "✅ ตั้งค่าเสร็จสิ้น!"
asdf current
EOF

chmod +x setup-dev-env.sh

8.5 การใช้งานร่วมกับ Editor และ IDE (Integration with Editors and IDEs)

VS Code:

// .vscode/settings.json
{
  // ชี้ไปที่ binary ที่ asdf จัดการ
  "python.defaultInterpreterPath": "${env:HOME}/.asdf/shims/python",
  "python.terminal.activateEnvironment": false,

  // Node.js path สำหรับ ESLint, Prettier
  "eslint.nodePath": "${env:HOME}/.asdf/shims",

  // ป้องกัน VS Code override version
  "go.goroot": "${env:HOME}/.asdf/installs/golang/1.22.5/go"
}

Neovim (LSP configuration):

-- ~/.config/nvim/lua/lsp.lua
-- ใช้ asdf shims สำหรับ LSP servers

local lspconfig = require('lspconfig')

-- TypeScript/JavaScript LSP
lspconfig.tsserver.setup({
  cmd = {
    -- ใช้ node จาก asdf
    vim.fn.expand("~/.asdf/shims/node"),
    vim.fn.expand("~/.asdf/installs/nodejs/20.15.0/lib/node_modules/typescript-language-server/lib/cli.mjs"),
    "--stdio"
  }
})

-- Python LSP
lspconfig.pyright.setup({
  cmd = { vim.fn.expand("~/.asdf/shims/pyright-langserver"), "--stdio" }
})

9. การสร้าง Plugin ของตัวเอง (Creating Your Own Plugin)

9.1 โครงสร้างของ Plugin (Plugin Structure)

asdf-my-tool/
├── README.md
├── bin/
│   ├── list-all           ← บังคับ: แสดงรายการ versions ที่มี
│   ├── install            ← บังคับ: ติดตั้ง version ที่ระบุ
│   ├── list-legacy-filenames  ← เสริม: รองรับ legacy files
│   ├── parse-legacy-file   ← เสริม: อ่าน legacy file
│   ├── exec-env           ← เสริม: ตั้งค่า env ก่อนรัน
│   ├── exec-path          ← เสริม: ระบุ path ของ executable
│   ├── uninstall          ← เสริม: ลบ version
│   └── latest-stable      ← เสริม: บอก version ล่าสุด
└── lib/
    └── utils.bash         ← helper functions

9.2 สคริปต์บังคับที่ต้องมี: bin/list-all, bin/install (Required Scripts)

bin/list-all — แสดงรายการ versions ที่มี:

#!/usr/bin/env bash
# bin/list-all
# แสดงรายการ versions ทั้งหมด คั่นด้วยช่องว่าง

set -euo pipefail

# ดึงรายการ versions จาก GitHub releases
GH_REPO="https://api.github.com/repos/my-org/my-tool/releases"

# ดึงและแสดง tag names (ลบ 'v' prefix)
curl -sL "$GH_REPO" | \
  grep '"tag_name":' | \
  sed -E 's/.*"([^"]+)".*/\1/' | \
  sed 's/^v//' | \
  tr '\n' ' '

bin/install — ติดตั้ง version:

#!/usr/bin/env bash
# bin/install
# ตัวแปร environment ที่ asdf ส่งมา:
#   ASDF_INSTALL_TYPE  — "version" หรือ "ref"
#   ASDF_INSTALL_VERSION — version ที่ต้องการติดตั้ง
#   ASDF_INSTALL_PATH  — path ที่จะติดตั้ง

set -euo pipefail

install_tool() {
    local install_type="$ASDF_INSTALL_TYPE"
    local version="$ASDF_INSTALL_VERSION"
    local install_path="$ASDF_INSTALL_PATH"

    # สร้างโฟลเดอร์
    mkdir -p "$install_path/bin"

    # กำหนด OS และ Architecture
    local os arch
    os=$(uname -s | tr '[:upper:]' '[:lower:]')
    arch=$(uname -m)
    case "$arch" in
        x86_64) arch="amd64" ;;
        aarch64|arm64) arch="arm64" ;;
    esac

    # URL สำหรับดาวน์โหลด
    local download_url="https://github.com/my-org/my-tool/releases/download/v${version}/my-tool_${os}_${arch}.tar.gz"

    echo "📥 กำลังดาวน์โหลด my-tool v${version}..."

    # ดาวน์โหลดและแตกไฟล์
    local tmp_dir
    tmp_dir=$(mktemp -d)
    curl -sL "$download_url" -o "$tmp_dir/my-tool.tar.gz"
    tar -xzf "$tmp_dir/my-tool.tar.gz" -C "$tmp_dir"

    # คัดลอก binary ไปยัง install path
    cp "$tmp_dir/my-tool" "$install_path/bin/my-tool"
    chmod +x "$install_path/bin/my-tool"

    # ทำความสะอาด
    rm -rf "$tmp_dir"

    echo "✅ ติดตั้ง my-tool v${version} สำเร็จ"
}

install_tool

9.3 สคริปต์เสริม: bin/list-legacy-filenames, bin/exec-env (Optional Scripts)

bin/list-legacy-filenames:

#!/usr/bin/env bash
# แสดงชื่อ legacy version files ที่รองรับ
# คั่นด้วย space หรือ newline

echo ".my-tool-version"

bin/exec-env:

#!/usr/bin/env bash
# ตั้งค่า environment variables ก่อนรัน executable
# ตัวแปร ASDF_INSTALL_PATH มีค่าแล้วเมื่อถูกเรียก

export MY_TOOL_HOME="$ASDF_INSTALL_PATH"
export PATH="$ASDF_INSTALL_PATH/bin:$PATH"

bin/latest-stable:

#!/usr/bin/env bash
# แสดง version ล่าสุดที่ stable
# รับ argument เป็น version filter (optional)

local filter="${1:-}"
curl -sL "https://api.github.com/repos/my-org/my-tool/releases/latest" | \
  grep '"tag_name":' | \
  sed -E 's/.*"v([^"]+)".*/\1/'

9.4 การทดสอบ Plugin (Testing the Plugin)

# ทดสอบ Plugin ในเครื่อง
git clone https://github.com/myuser/asdf-my-tool.git /tmp/asdf-my-tool

# เพิ่ม Plugin จาก local path
asdf plugin add my-tool file:///tmp/asdf-my-tool

# ทดสอบแต่ละฟังก์ชัน
asdf list all my-tool          # ทดสอบ bin/list-all
asdf install my-tool 1.0.0     # ทดสอบ bin/install
asdf set my-tool 1.0.0         # ทดสอบการตั้งค่า
my-tool --version              # ทดสอบ shim

# ใช้ bats สำหรับ automated testing
# https://github.com/bats-core/bats-core
cat > tests/test_list_all.bats << 'EOF'
#!/usr/bin/env bats

@test "list-all returns versions" {
  run bin/list-all
  [ "$status" -eq 0 ]
  [[ "$output" =~ "1.0.0" ]]
}
EOF
bats tests/

9.5 การเผยแพร่ Plugin สู่ชุมชน (Publishing the Plugin to the Community)

  1. สร้าง Repository บน GitHub ชื่อ asdf-<tool-name>
  2. เพิ่ม README ที่ครอบคลุม prerequisites และวิธีติดตั้ง
  3. เพิ่ม Topic asdf-plugin และ asdf-<tool-name> ใน GitHub repository
  4. ส่ง Pull Request ไปยัง asdf-vm/asdf-plugins เพื่อเพิ่มเข้า official registry
# fork และ clone asdf-plugins registry
git clone https://github.com/YOUR-USERNAME/asdf-plugins.git
cd asdf-plugins

# เพิ่ม plugin ในไฟล์ที่เหมาะสม (เรียงตามตัวอักษร)
echo "my-tool = https://github.com/myuser/asdf-my-tool.git" >> plugins/m

# commit และ push
git add plugins/m
git commit -m "Add my-tool plugin"
git push origin main

# เปิด Pull Request บน GitHub

10. การอัปเดตและการบำรุงรักษา asdf (Updating and Maintaining asdf)

10.1 การอัปเดต asdf (Updating asdf Itself)

# อัปเดต asdf เป็นเวอร์ชันล่าสุด
asdf update

# หรืออัปเดตผ่าน Git โดยตรง
cd ~/.asdf
git fetch --prune
git checkout "$(git describe --abbrev=0 --tags)"

# ตรวจสอบเวอร์ชันหลังอัปเดต
asdf version

10.2 การอัปเดต Plugin ทั้งหมดพร้อมกัน (Updating All Plugins at Once)

# อัปเดต Plugin ทั้งหมด
asdf plugin update --all

# ตรวจสอบว่ามี version ใหม่หลังอัปเดต plugin
asdf list all nodejs | tail -5   # ดู versions ล่าสุด

# Script อัปเดต asdf และ Plugin ทั้งหมด
cat > update-asdf.sh << 'EOF'
#!/usr/bin/env bash
echo "🔄 อัปเดต asdf..."
asdf update

echo "🔌 อัปเดต plugins ทั้งหมด..."
asdf plugin update --all

echo "✅ อัปเดตเสร็จสิ้น"
asdf version
asdf plugin list
EOF
chmod +x update-asdf.sh

10.3 การสำรองและกู้คืนการตั้งค่า (Backing Up and Restoring Configuration)

# สำรองการตั้งค่า asdf
backup_asdf() {
    local backup_dir="$HOME/asdf-backup-$(date +%Y%m%d)"
    mkdir -p "$backup_dir"

    # สำรอง global .tool-versions
    cp ~/.tool-versions "$backup_dir/tool-versions.bak"

    # สำรอง .asdfrc
    cp ~/.asdfrc "$backup_dir/asdfrc.bak" 2>/dev/null || true

    # บันทึกรายการ plugins
    asdf plugin list --urls > "$backup_dir/plugins.txt"

    echo "✅ สำรองข้อมูลไปยัง $backup_dir"
}

# กู้คืนการตั้งค่า
restore_asdf() {
    local backup_dir="$1"

    # ติดตั้ง plugins จาก backup
    while IFS=' ' read -r name url; do
        asdf plugin add "$name" "$url" 2>/dev/null || true
    done < "$backup_dir/plugins.txt"

    # กู้คืน .tool-versions
    cp "$backup_dir/tool-versions.bak" ~/.tool-versions

    # ติดตั้ง versions
    asdf install

    echo "✅ กู้คืนสำเร็จ"
}

10.4 การย้ายการตั้งค่าไปยังเครื่องใหม่ (Migrating Configuration to a New Machine)

# บนเครื่องเก่า: export การตั้งค่า
export_asdf_config() {
    echo "# asdf global versions"
    cat ~/.tool-versions

    echo ""
    echo "# asdf plugins"
    asdf plugin list --urls
}

export_asdf_config > ~/asdf-config-export.txt

# บนเครื่องใหม่: import การตั้งค่า
import_asdf_config() {
    local config_file="$1"

    # ติดตั้ง asdf
    git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
    . ~/.asdf/asdf.sh

    # อ่านและติดตั้ง plugins
    while IFS= read -r line; do
        [[ "$line" =~ ^#.*$ ]] && continue
        [[ -z "$line" ]] && continue
        name=$(echo "$line" | awk '{print $1}')
        url=$(echo "$line" | awk '{print $2}')
        if [[ -n "$url" ]]; then
            asdf plugin add "$name" "$url"
        fi
    done < "$config_file"

    # ติดตั้ง versions
    asdf install
}

11. การแก้ไขปัญหาที่พบบ่อย (Troubleshooting Common Issues)

11.1 คำสั่งไม่พบหลังติดตั้ง — ปัญหา PATH และ Shim

อาการ: command not found: node แม้ติดตั้งแล้ว

# ตรวจสอบ PATH
echo $PATH
# ควรมี ~/.asdf/shims และ ~/.asdf/bin

# แก้ไข: เพิ่มใน shell config
export PATH="$HOME/.asdf/shims:$HOME/.asdf/bin:$PATH"
source ~/.bashrc

# ตรวจสอบว่า shim มีอยู่
ls ~/.asdf/shims/node
# ถ้าไม่มี → สร้าง shims ใหม่
asdf reshim nodejs

# ตรวจสอบว่า asdf รู้จัก tool
asdf current nodejs

11.2 เวอร์ชันไม่เปลี่ยนตามที่ตั้งค่า (Version Not Switching as Expected)

# ตรวจสอบว่าไฟล์ .tool-versions มีอยู่
cat .tool-versions

# ตรวจสอบว่า version ถูกติดตั้งแล้ว
asdf list nodejs

# ถ้าไม่มีในรายการ → ติดตั้งก่อน
asdf install nodejs 20.15.0

# ตรวจสอบ version ที่ใช้งานอยู่จริง
asdf current nodejs

# ตรวจสอบว่า shell override ไม่ขัดขวาง
echo $ASDF_NODEJS_VERSION  # ถ้ามีค่า → ลบออก
unset ASDF_NODEJS_VERSION

# ตรวจสอบ binary ที่ใช้งาน
which node
asdf which node

11.3 ความขัดแย้งกับ Package Manager อื่น (Conflicts with Other Package Managers)

# ปัญหา: Homebrew node ถูกใช้แทน asdf node

# ตรวจสอบ PATH order
echo $PATH
# ~/.asdf/shims ต้องมาก่อน /usr/local/bin (homebrew)

# แก้ไข: จัดลำดับ PATH ในไฟล์ shell config
# เพิ่มที่ด้านบนของ ~/.bashrc หรือ ~/.zshrc:
# export PATH="$HOME/.asdf/shims:$HOME/.asdf/bin:$PATH"

# ตรวจสอบว่าใช้ node ตัวไหน
which node
# ควรได้: /home/user/.asdf/shims/node

# ถ้า homebrew node มาก่อน ให้ unlink
brew unlink node

11.4 การติดตั้ง Plugin ล้มเหลวเนื่องจาก Dependency ขาด

# ตัวอย่าง: Python build failed

# ดู error message
asdf install python 3.11.9
# ERROR: The Python ssl extension was not compiled...

# แก้ไขบน Ubuntu/Debian
sudo apt-get install -y libssl-dev

# แก้ไขบน macOS
brew install openssl
export LDFLAGS="-L$(brew --prefix openssl)/lib"
export CPPFLAGS="-I$(brew --prefix openssl)/include"

# ลองใหม่
asdf install python 3.11.9

# ดูรายการ dependencies ที่ต้องการ
# (อ่านจาก README ของ Plugin)
asdf plugin info python

11.5 การ Rebuild Shim (Rebuilding Shims)

# เมื่อ shim ไม่ทำงานหลังติดตั้ง binary ใหม่
# เช่น หลัง npm install -g some-cli

# rebuild shims สำหรับ tool เฉพาะ
asdf reshim nodejs

# rebuild shims ทั้งหมด
asdf reshim

# ตรวจสอบว่า shim ถูกสร้างแล้ว
ls ~/.asdf/shims/ | grep "some-cli"

# ตรวจสอบเนื้อหาของ shim
cat ~/.asdf/shims/some-cli

11.6 ปัญหาเฉพาะของ Shell แต่ละตัว (Shell-Specific Issues)

Fish Shell:

# ปัญหา: asdf ไม่ทำงานใน Fish
# แก้ไข: ตรวจสอบ config.fish
cat ~/.config/fish/config.fish

# ควรมี:
# source ~/.asdf/asdf.fish

# ถ้าไม่มี ให้เพิ่ม
echo 'source ~/.asdf/asdf.fish' >> ~/.config/fish/config.fish

# Reload
source ~/.config/fish/config.fish

# ตรวจสอบ completions
ls ~/.config/fish/completions/ | grep asdf

Zsh:

# ปัญหา: asdf ไม่ทำงานกับ Oh My Zsh
# แก้ไข: ใน .zshrc ต้องโหลด asdf หลัง Oh My Zsh

# .zshrc ที่ถูกต้อง:
# export ZSH="$HOME/.oh-my-zsh"
# source $ZSH/oh-my-zsh.sh
# . "$HOME/.asdf/asdf.sh"   ← ต้องอยู่หลัง Oh My Zsh

11.7 asdf set ไม่มีผลตามที่คาดหวัง — ลำดับความสำคัญของเวอร์ชัน

# ตรวจสอบลำดับความสำคัญ
asdf current nodejs
# nodejs  18.20.4  $ASDF_NODEJS_VERSION  ← Shell override กำลัง override อยู่!

# แก้ไข: ลบ Shell override ก่อน
unset ASDF_NODEJS_VERSION

# ตรวจสอบว่าไฟล์ .tool-versions ใดถูกใช้
asdf current nodejs
# nodejs  20.15.0  /home/user/project/.tool-versions  ← ถูกต้อง

# ลำดับความสำคัญที่ต้องจำ:
# 1. $ASDF_<TOOL>_VERSION (สูงสุด)
# 2. .tool-versions ในโฟลเดอร์ปัจจุบัน
# 3. .tool-versions ในโฟลเดอร์แม่ (ขึ้นไปเรื่อยๆ)
# 4. ~/.tool-versions (global)
# 5. system (ต่ำสุด)

12. เคล็ดลับและการใช้งานขั้นสูง (Tips and Advanced Usage)

12.1 Alias และ Shortcut ที่มีประโยชน์ (Useful Aliases and Shortcuts)

# เพิ่ม aliases ใน ~/.bashrc หรือ ~/.zshrc

# ดู versions ทั้งหมดที่ใช้งาน
alias av='asdf current'

# ติดตั้ง tool ด้วยเวอร์ชันล่าสุด และตั้งค่า global
asdf-install-latest() {
    local tool="$1"
    local version
    version=$(asdf latest "$tool")
    echo "ติดตั้ง $tool $version..."
    asdf install "$tool" "$version"
    asdf set --home "$tool" "$version"
    echo "✅ $tool $version ติดตั้งและตั้งค่าเป็น global แล้ว"
}

# ดู path ของ executable ที่ใช้งานอยู่
alias awhich='asdf which'

# อัปเดต asdf และ plugins ทั้งหมด
alias asdf-update-all='asdf update && asdf plugin update --all'

# Fish shell version (สำหรับ Fish ใช้ function แทน alias)
# functions/asdf-install-latest.fish
function asdf-install-latest
    set tool $argv[1]
    set version (asdf latest $tool)
    echo "ติดตั้ง $tool $version..."
    asdf install $tool $version
    asdf set --home $tool $version
end

12.2 การใช้ Environment Variable ควบคุมพฤติกรรมของ asdf

# ASDF_DATA_DIR — เปลี่ยนโฟลเดอร์เก็บข้อมูล (default: ~/.asdf)
export ASDF_DATA_DIR="/opt/asdf-data"

# ASDF_CONFIG_FILE — เปลี่ยน config file (default: ~/.asdfrc)
export ASDF_CONFIG_FILE="$HOME/.config/asdf/asdfrc"

# ASDF_DEFAULT_TOOL_VERSIONS_FILENAME — เปลี่ยนชื่อไฟล์ version
# (default: .tool-versions)
export ASDF_DEFAULT_TOOL_VERSIONS_FILENAME=".versions"

# ASDF_<TOOL>_VERSION — Shell-level override สำหรับ tool เฉพาะ
export ASDF_NODEJS_VERSION=18.20.4
export ASDF_PYTHON_VERSION=3.10.14

# ตรวจสอบ
asdf current
# nodejs  18.20.4  $ASDF_NODEJS_VERSION
# python  3.10.14  $ASDF_PYTHON_VERSION

12.3 การจัดการ Multiple Runtime บนโปรเจกต์เดียว (Managing Multiple Runtimes in a Single Project)

# ตัวอย่าง: Full-stack project ที่ต้องการ Node.js + Python + Ruby + Terraform
cd ~/projects/fullstack-app

# ตั้งค่าทุก runtime พร้อมกัน
asdf set nodejs 20.15.0
asdf set python 3.11.9
asdf set ruby 3.2.4
asdf set terraform 1.7.0

# ไฟล์ .tool-versions
cat .tool-versions
# nodejs 20.15.0
# python 3.11.9
# ruby 3.2.4
# terraform 1.7.0

# ติดตั้งทั้งหมดพร้อมกัน (เหมาะสำหรับ onboarding)
asdf install

# ตรวจสอบ
asdf current
# nodejs     20.15.0  /home/user/projects/fullstack-app/.tool-versions
# python     3.11.9   /home/user/projects/fullstack-app/.tool-versions
# ruby       3.2.4    /home/user/projects/fullstack-app/.tool-versions
# terraform  1.7.0    /home/user/projects/fullstack-app/.tool-versions

12.4 Scripting และ Automation ด้วย asdf

#!/usr/bin/env bash
# script สำหรับ audit เวอร์ชันที่ติดตั้งและหาเวอร์ชันใหม่

check_updates() {
    echo "🔍 ตรวจสอบ updates สำหรับ global tools..."
    echo "================================================"

    while IFS=' ' read -r tool current_version; do
        [[ "$tool" =~ ^#.*$ ]] && continue
        [[ -z "$tool" ]] && continue

        latest=$(asdf latest "$tool" 2>/dev/null || echo "unknown")

        if [ "$current_version" = "$latest" ]; then
            echo "✅ $tool: $current_version (up to date)"
        else
            echo "⬆️  $tool: $current_version$latest (update available)"
        fi
    done < ~/.tool-versions
}

check_updates

12.5 asdf กับ Dotfiles Management (asdf with Dotfiles Management)

# โครงสร้าง dotfiles repository ที่แนะนำ
# ~/dotfiles/
# ├── .tool-versions      ← global versions
# ├── .asdfrc             ← asdf configuration
# ├── install.sh          ← setup script
# └── shells/
#     ├── .bashrc
#     ├── .zshrc
#     └── config.fish

# install.sh
#!/usr/bin/env bash
DOTFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# ติดตั้ง asdf
if [ ! -d "$HOME/.asdf" ]; then
    git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
fi

# symlink .tool-versions และ .asdfrc
ln -sf "$DOTFILES_DIR/.tool-versions" "$HOME/.tool-versions"
ln -sf "$DOTFILES_DIR/.asdfrc" "$HOME/.asdfrc"

# โหลด asdf
. ~/.asdf/asdf.sh

# ติดตั้ง plugins จาก .tool-versions
while IFS=' ' read -r tool _version; do
    [[ "$tool" =~ ^#.*$ ]] && continue
    [[ -z "$tool" ]] && continue
    asdf plugin add "$tool" 2>/dev/null || true
done < "$HOME/.tool-versions"

# ติดตั้ง versions
asdf install

echo "✅ Dotfiles setup complete!"

# ตัวอย่าง .asdfrc
cat > "$DOTFILES_DIR/.asdfrc" << 'EOF'
# ~/.asdfrc
legacy_version_file = yes
always_keep_download = no
plugin_repository_last_check_duration = 60
EOF

13. บทสรุป (Conclusion)

13.1 สรุปประโยชน์และจุดแข็งของ asdf (Summary of Benefits and Strengths)

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#d5c4a1', 'background': '#282828', 'mainBkg': '#3c3836', 'nodeBorder': '#83a598', 'clusterBkg': '#3c3836', 'titleColor': '#ebdbb2', 'edgeLabelBackground': '#3c3836', 'fontFamily': 'monospace'}}}%%
mindmap
  root((asdf))
    จุดแข็ง
      เครื่องมือเดียว
        600+ plugins
        รองรับทุกภาษา
      .tool-versions
        Single config
        ใช้ได้กับทีม
        Commit ลง Git
      ขยายได้
        สร้าง Plugin เอง
        Custom repos
    การใช้งาน
      Local Development
        ต่างเวอร์ชันต่อโปรเจกต์
        Environment isolation
      CI/CD
        GitHub Actions
        GitLab CI
      DevOps
        Terraform
        kubectl
        helm
    Shell รองรับ
      Bash
      Zsh
      Fish
      Nushell

จุดแข็งหลัก:


13.2 กรณีที่ควรและไม่ควรใช้ asdf (When to Use and When Not to Use asdf)

กรณี ควรใช้ asdf ทางเลือกอื่น
ทำงานกับหลายภาษาในโปรเจกต์เดียว ✅ เหมาะมาก
ทีมขนาดใหญ่ต้องการ environment เดียวกัน ✅ เหมาะมาก
DevOps tools (Terraform, kubectl) ✅ เหมาะมาก tfenv, mise
Elixir/Erlang ecosystem ✅ เหมาะมาก kiex, kerl
ต้องการประสิทธิภาพสูงสุด ⚠️ ปานกลาง mise (Rust-based)
Windows ไม่ใช้ WSL ❌ ไม่รองรับ scoop, mise
ต้องการ UI/GUI ❌ CLI only Volta
จัดการเฉพาะ Node.js อาจเกิน nvm, volta

13.3 อนาคตของ asdf และทิศทางการพัฒนา (The Future of asdf and Development Direction)

การพัฒนาที่กำลังดำเนินอยู่ในปี 2024–2025:


13.4 แหล่งข้อมูลและชุมชนเพิ่มเติม (Additional Resources and Community)


ภาคผนวก: ตัวอย่างไฟล์สำหรับการทดลองใช้งาน (Appendix: Sample Files for Practice)

ตัวอย่าง .tool-versions สำหรับ Full-Stack Web Project

# .tool-versions — Full-Stack Web Application
# อัปเดตล่าสุด: 2024-07

# Frontend Runtime
nodejs 20.15.0

# Backend Runtime
python 3.11.9

# Database CLI
postgresql 16.3

# Infrastructure
terraform 1.9.0
kubectl 1.30.2
helm 3.15.2

# Code Quality
golang 1.22.5

ตัวอย่าง .asdfrc

# ~/.asdfrc — asdf configuration
legacy_version_file = yes
always_keep_download = no
plugin_repository_last_check_duration = 60

ตัวอย่าง Script Onboarding

#!/usr/bin/env bash
# onboarding.sh — ใช้สำหรับตั้งค่า environment ครั้งแรก

set -euo pipefail

REQUIRED_TOOLS=(nodejs python terraform kubectl)

echo "================================================"
echo " 🚀 Developer Environment Setup"
echo "================================================"

# ตรวจสอบ asdf
if ! command -v asdf &>/dev/null; then
    echo "❌ ไม่พบ asdf — กรุณาติดตั้งก่อน"
    echo "   git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0"
    exit 1
fi

echo "✅ asdf $(asdf version) พบแล้ว"

# ติดตั้ง plugins
for tool in "${REQUIRED_TOOLS[@]}"; do
    if ! asdf plugin list | grep -q "^$tool$"; then
        echo "📦 เพิ่ม plugin: $tool"
        asdf plugin add "$tool"
    else
        echo "✅ plugin $tool มีอยู่แล้ว"
    fi
done

# ติดตั้ง versions จาก .tool-versions
echo "📥 ติดตั้ง tool versions..."
asdf install

# แสดงผล
echo ""
echo "================================================"
echo " ✅ ตั้งค่าเสร็จสิ้น!"
echo "================================================"
asdf current