# JUJU

> **JUJU 0.8.2 — Cross-platform setup + native backends**: `juju setup` ตรวจ ติดตั้ง และทดสอบ Git, ripgrep, FFmpeg/ffprobe, Whisper + โมเดล, Playwright Chromium, LSP, speech, desktop และ command sandbox ตาม OS โดยไม่เปิด web/desktop consent ให้เอง Windows x64 ผ่านการตรวจรับบน Windows Server/Node 24 จริง; Linux ผ่าน Debian arm64/Node 22 + X11/XTEST/AT-SPI จริง; macOS arm64/Node 22 ผ่าน full gate ดู [Release 0.8.2](docs/RELEASE_0.8.2.md) · [Test report](docs/TEST_REPORT.md)
>
> **อัปเกรด IPC 0.8.x:** ถ้ายังรัน 0.7.x ให้หยุดด้วย CLI รุ่นเดิมหรือ terminal เดิมก่อนเปลี่ยน installation; IPC 0.8 ไม่มี unauthenticated legacy fallback และการอัปเกรดไม่ล้าง OAuth/ACL/trust เดิม

> **JUJU 0.7.1 — Compact Tool Surface**: HTTP/ChatGPT ใช้ catalog แบบย่อ 19 tools (gateway + `juju_discover`) เข้าถึงความสามารถทั้ง 74 ได้ครบโดยสิทธิ์และ policy เดิมทุกข้อ; STDIO/Codex ยังได้ catalog เต็ม 74 tools เหมือนเดิม ดู [คู่มือ 0.7.1](docs/RELEASE_0.7.1.md)
>
> **JUJU 0.7.0 — Coding Assistance + Multimodal**: **74 tools** รวมเครื่องมือช่วยเข้าใจงาน วิเคราะห์ผลกระทบ ตรวจงานหลังแก้ และเครื่องมือภาพ วิดีโอ เสียง เบราว์เซอร์ เกมแบบทีละขั้น และ workflow โดยใช้สิทธิ์เดิม ไม่เปิดอุปกรณ์หรือดาวน์โหลดโมเดลเองตอนติดตั้ง
>
> คู่มือ: [เริ่มใช้ฟีเจอร์ 0.7.0](docs/RELEASE_0.7.0.md) · [Task Assistance](docs/ASSISTANCE.md) · [Multimodal](docs/MULTIMODAL.md) · [Release notes](docs/RELEASE_NOTES.md)

**ให้ AI ช่วยเขียนโค้ด ดูภาพและคลิป ใช้เว็บ และทำงานเป็นขั้นตอนผ่าน MCP ในเครื่อง**

JUJU ให้ AI อ่าน ค้นหา เพิ่มและแก้ไฟล์ รัน test/build/install ติดตามงานเบื้องหลัง และใช้ Git ผ่านเครื่องมือ MCP โดยคุณเป็นผู้กำหนด workspace และสิทธิ์ ใช้ในเครื่องผ่าน **STDIO** หรือเชื่อมจากระยะไกลผ่าน **HTTP + OAuth** และ tunnel ที่คุณจัดการเอง

ชื่อแพ็กเกจ npm คือ **`juju-mcp`** ส่วนคำสั่งหลังติดตั้งคือ **`juju`** ไม่ต้องมี LLM API key สำหรับตัว JUJU; แอป AI ที่นำมาเชื่อมมีข้อกำหนดบัญชีของตัวเอง JUJU ไม่ใช่โมเดล AI และไม่ได้มีบริการ relay หรือจัดการ Cloudflare ให้

**ติดตั้งและตรวจ dependency:** หลัง `npm install -g juju-mcp` ให้รัน `juju setup` จาก terminal ของเจ้าของเครื่อง คำสั่งเดียวจะเตรียม component ที่ขาดสำหรับ Windows/macOS/Linux และทำ capability probes หลังติดตั้ง; ใช้ `juju setup --check` สำหรับตรวจอย่างเดียว และ `juju setup --plan` สำหรับดูแผนโดยไม่เขียน state. การเปิด outbound web ยังต้องสั่ง `juju setup --enable-web` โดยเจ้าของเอง และ Desktop ยังต้องอนุญาต app IDs แยกต่างหาก

**ขอบเขตแพลตฟอร์ม:** Windows Desktop ต้องเป็น unlocked interactive session; Linux Desktop ใช้ X11/XWayland ที่มี `DISPLAY`, X-Resource/XTEST และ AT-SPI (pure Wayland portal-only session ยังไม่ถูกอ้างว่ารองรับ); macOS ใช้ Screen Recording/Accessibility ตามระบบ. Command sandbox fail-closed ถ้า backend หรือ confinement probe ไม่พร้อม ไม่มี silent unsandboxed downgrade เมื่อคำขอกำหนด `sandbox:true`

**ขอบเขต:** JUJU ส่งหลักฐานภาพ/เสียงให้โมเดลที่เชื่อมมาตีความ ไม่ใช่โมเดลใหม่หรือ agent ที่เล่นเกม/เฝ้าจอต่อเอง ฟีเจอร์เกมเป็นการทำทีละขั้น ภาพหน้าจอเป็นชุดสั้น สื่อเริ่มจากไฟล์ใน workspace และเสียงตอบกลับเป็นไฟล์ให้ client เล่น ไม่เปิดไมโครโฟนหรือปลด DRM

**สิทธิ์ยังมีผล:** OAuth, สิทธิ์ client ต่อ workspace, โหมด inspect/edit/trusted, การอนุมัติ action และ Desktop ยังคงทำงาน งาน Cron ยังต้องได้รับการอนุมัติแยกโดยเจ้าของ ดู [การอัปเกรดจากระบบยืนยันรายแชต](docs/CONFIRMATION.md) และ [งานตั้งเวลา](docs/SCHEDULES.md)

**แพตช์ 0.3.1:** หน้า config ตรวจ workspace ID/epoch ก่อนบันทึกทุกครั้ง แท็บเก่าจะได้รับข้อความให้โหลดใหม่แทนการเปลี่ยนสิทธิ์ผิดโปรเจกต์ เมื่อ workspace เปลี่ยน หน้าเว็บล้างค่าที่ค้างไว้ให้ตรวจใหม่ การสลับและ shutdown รอให้ tool handlers จบจริง แม้ HTTP connection หลุดไปแล้ว พร้อมปิด connection เก่าก่อนปิด OAuth state

## สารบัญ

- [ฟีเจอร์และวิธีอัปเกรด 0.7.0](docs/RELEASE_0.7.0.md)
- [Task Assistance](docs/ASSISTANCE.md)
- [ภาพ วิดีโอ เสียง เบราว์เซอร์ เกม และ Workflow](docs/MULTIMODAL.md)
- [อัปเกรดจากระบบยืนยันรายแชต](docs/CONFIRMATION.md)
- [งานตั้งเวลา / Cron](docs/SCHEDULES.md)
- [เริ่มใช้งานและเปลี่ยนโปรเจกต์](#quickstart)
- [เลือกวิธีเชื่อมต่อ](#connection)
- [ติดตั้งและตรวจเครื่อง](#install)
- [เชื่อมในเครื่องผ่าน STDIO](#stdio)
- [เชื่อม ChatGPT ผ่าน HTTP และ OAuth](#chatgpt)
- [เชื่อม Codex ผ่าน OAuth](#codex-oauth)
- [สิทธิ์แก้ไฟล์และรันคำสั่ง](#permissions)
- [Sandbox และ config](#sandbox)
- [คำสั่งยาวและไฟล์ใหญ่](#large-inputs)
- [อ่านภาพและควบคุมหน้าต่าง](#desktop)
- [ตัวอย่างงานและเครื่องมือ](#tools)
- [การใช้งานประจำวันและอัปเดต](#operations)
- [แก้ปัญหาที่พบบ่อย](#troubleshooting)
- [ผลทดสอบและข้อจำกัด](#verification)
- [พัฒนาและเผยแพร่แพ็กเกจ](#release)

<a id="quickstart"></a>
## เริ่มใช้งาน HTTP และ Local Config

```bash
npm install -g juju-mcp
cd "/absolute/path/to/project"
juju
```

JUJU เปิด MCP ที่ `127.0.0.1:21730/mcp` และ **Local Config ที่ `127.0.0.1:21731`** คัดลอกลิงก์ Private config ที่แสดงใน terminal ไปเปิดเบราว์เซอร์ ลิงก์มี token ส่วนตัวหลัง `#` เพื่อยืนยันเจ้าของ ไม่ต้องส่งลิงก์นี้ให้ AI หรือคนอื่น

หน้า config แสดง root ปัจจุบัน ให้ตั้ง public HTTPS origin, trust mode และเลือกสิทธิ์ read/write/exec ให้ client สำหรับ root นี้ เมื่อเปลี่ยน public URL ต้อง restart; การเปลี่ยนสิทธิ์ client และ saved trust มีผลกับคำขอถัดไป (ยกเว้นโหมด override ที่ระบุไว้ด้านล่าง)

หน้า config (0.3) เป็น dashboard ธีมมืดเป็นค่าเริ่มต้น สลับสว่าง/ตามระบบได้และจำค่าไว้ในเบราว์เซอร์ มีส่วน: **Workspace** (ชื่อโปรเจกต์, path พร้อมปุ่มคัดลอก, workspace ID/epoch, ช่องเปลี่ยนโปรเจกต์), **Permissions** (แยก "ค่าที่บันทึก" กับ "สิทธิ์ที่มีผลในรอบนี้" และแสดง override จาก `--allow --all`/`--bypass` ชัดเจน), **Connection** (Local MCP URL, Public MCP URL, Local Config, สถานะ OAuth จริงของ process นี้ ไม่เดาว่า tunnel ออนไลน์) และ **Client access** (สิทธิ์ต่อ client สำหรับ workspace ปัจจุบัน มีกล่องยืนยันก่อนถอนสิทธิ์ ไม่แสดง secret/token) และ **Desktop** สำหรับดูสถานะสิทธิ์รายแอป ปิดสิทธิ์ และคัดลอกคำสั่งตั้งสิทธิ์ถาวร ทุกส่วนมีสถานะ loading/error และกันกดซ้ำระหว่างบันทึก

### Client access แสดงเฉพาะโฟลเดอร์ที่กำลังรัน

ด้านบนรายการจะแสดง path และจำนวน client ที่มีสิทธิ์ในโฟลเดอร์นี้เท่านั้น
client ของโปรเจกต์อื่น หรือ client ที่ถอนสิทธิ์หมดแล้ว จะไม่แสดงเป็นการ์ดในรายการหลัก
หากยังไม่มีสิทธิ์ จะขึ้น “ยังไม่มี client ที่อนุญาตในโฟลเดอร์นี้”

เมื่อต้องการใช้ connection เดิมกับโปรเจกต์ใหม่ ให้กด **เพิ่ม client ให้โฟลเดอร์นี้**
เลือก client ที่ลงทะเบียนไว้ (ตรวจ Client ID หากชื่อซ้ำกัน) เลือกอ่าน/แก้ไฟล์/รันคำสั่ง
แล้วกด **เพิ่มและบันทึกสิทธิ์** ไม่มีการเพิ่มให้เองเมื่อเปิดหน้าเว็บ ค่าเริ่มต้นเลือกเฉพาะอ่าน
หลังถอนสิทธิ์ทั้งหมด การ์ดจะหายจากโฟลเดอร์นี้ แต่ยังเลือกเพิ่มกลับได้

ทะเบียน OAuth ยังคงใช้ร่วมกันในเครื่อง จึงไม่ต้องล็อกอินใหม่เพราะการกรองรายการนี้
การเพิ่มหรือถอนมีผลเฉพาะโฟลเดอร์ที่แสดงอยู่ ไม่เปลี่ยนสิทธิ์ของโฟลเดอร์อื่น
เมื่อสลับโฟลเดอร์ รายการและแบบฟอร์มจะโหลดตามโปรเจกต์ใหม่

### ล้าง client ที่ไม่ใช้แล้ว

เปิด **Client access → ล้าง client ที่ไม่ใช้** เลือก client ที่ต้องการลบ
หรือกด **เลือกทั้งหมดในรายการนี้** แล้วกด **ล้าง client ที่เลือก**
ตรวจชื่อและ Client ID ในหน้าต่างยืนยัน ก่อนกด **ลบทะเบียนที่เลือก**
กดยกเลิกได้โดยข้อมูลไม่เปลี่ยน ส่วนนี้แสดงทะเบียนทั้งเครื่อง รวม client ที่ไม่มีสิทธิ์ในโฟลเดอร์นี้

การลบจะล้างทะเบียนและสิทธิ์ทุกโฟลเดอร์ของ client ที่เลือก พร้อมถอน access/refresh
และคำขออนุมัติที่เกี่ยวข้อง ถ้าลบตัวที่ ChatGPT ใช้อยู่ จะต้องลงทะเบียนและเชื่อมใหม่
client ตัวอื่น ไฟล์โปรเจกต์ public URL และ signing keys ไม่ถูกลบ

หากต้องการถอนเฉพาะโฟลเดอร์นี้ ให้ใช้ **ถอนสิทธิ์ทั้งหมด** บนการ์ดตามเดิม
งานที่เริ่มไปแล้วอาจทำต่อได้; ตารางที่ผูกกับ grant ที่ลบจะเริ่มรอบใหม่ไม่ได้
ประวัติงานและไฟล์ยังอยู่ การล้างเลือกได้ครั้งละ 100 client ถ้ามากกว่านั้นให้โหลดรายการใหม่
เมื่อสิทธิ์เปลี่ยนหลังเปิดรายการ ระบบให้โหลดและตรวจใหม่ก่อนลบ

### เปลี่ยนโปรเจกต์จากหน้า config โดยไม่ต้อง restart

พิมพ์ absolute path ของโฟลเดอร์ใหม่ในส่วน Workspace แล้วกด **เปลี่ยนโปรเจกต์** JUJU จะเตรียม workspace ใหม่ (workspace ID และ epoch ใหม่, trust และสิทธิ์ client ของ path นั้นเอง ไม่คัดลอกจาก path เก่า), ย้าย IPC socket ให้ `juju status/approve` จากโฟลเดอร์ใหม่ใช้ได้, แล้วจึงปิด services ของ path เก่า ระหว่างสลับ MCP ตอบ 503 ให้ client ลองใหม่ หลังสลับ **ให้ AI เรียก `project_overview` ใหม่** และ client ที่ยังไม่มีสิทธิ์ใน path ใหม่จะถูกปฏิเสธจนกว่าจะอนุญาตในหน้า config

JUJU จะ**ปฏิเสธ**การสลับ (และ path เดิมใช้งานต่อได้ตามปกติ) เมื่อ: มี job กำลังรัน (หยุดหรือรอให้เสร็จก่อน ไม่ kill ให้เงียบ ๆ), มีคำขอ MCP ค้างอยู่เกินเวลารอ, path ไม่ใช่โฟลเดอร์ที่มีอยู่ / เป็น home หรือ root ของดิสก์, หรือมี JUJU อีก process เปิดโฟลเดอร์นั้นอยู่ การสลับทำได้เฉพาะเจ้าของผ่านหน้า config นี้เท่านั้น ไม่มี MCP tool ให้ AI เปลี่ยน root เอง และ `juju stdio` ไม่รองรับการสลับ (ผูกกับโฟลเดอร์ที่ client เปิดมา) เบราว์เซอร์เลือกโฟลเดอร์ในเครื่องให้ตรง ๆ ไม่ได้ จึงต้องวาง path เอง

| คำสั่ง | พฤติกรรม |
|---|---|
| `juju` หรือ `juju start` | HTTP + local config; ใช้ saved trust (inspect เป็นค่าเริ่มต้น) |
| `juju start --allow --all` | อนุญาต action ทุกประเภทและเปิด fetch_url สำหรับรอบนี้ ใช้ default sandbox ตาม config |
| `juju --bypass` | trusted actions + fetch_url และปิด default job sandbox เฉพาะรอบนี้ |
| `juju stdio --root PATH` | explicit STDIO สำหรับ MCP subprocess; ไม่มีหน้า config จาก entry นี้ |

`--allow` และ `--all` ต้องใช้คู่กัน ทั้งสองโหมด override ไม่เปลี่ยน saved trust และไม่เพิ่ม client/path permissions, ไม่ปิด OAuth, ไม่ข้าม secret/path guards, expected hash หรือ workspace epoch ส่วน `--bypass` ไม่ปิดคำยืนยันของ ChatGPT/Codex และไม่ได้เป็น anonymous remote access

### สีใน terminal และแพตช์ 0.2.1

ชื่อแอป/URL ใช้สีฟ้า, local config ใช้สีม่วง, OAuth ที่เปิดใช้แล้วใช้สีเขียว,
สถานะ exec/คำเตือนใช้สีเหลือง และข้อมูลประกอบใช้สีจาง สีมีผลเฉพาะ terminal
ที่รองรับ; output ที่ redirect, JSON และ STDIO protocol ไม่ใส่ ANSI colors
ปิดสีเองได้ด้วย `NO_COLOR=1 juju`

หาก 0.2.0 ขึ้น `Unexpected token 'j'` ตอนเปิด config นั่นคือ migration เดิม
คัดลอก scopes แบบคั่นด้วยช่องว่างมาใส่คอลัมน์ JSON แพตช์ 0.2.1 มี migration
ซ่อมแถวเหล่านี้เมื่อเปิดฐานข้อมูล พร้อมรักษาการถอนสิทธิ์และแยก workspace เดิม
ไม่ต้องลบ state DB หรือสร้าง OAuth client ใหม่ หลังติดตั้งให้ restart JUJU

### เปลี่ยนโปรเจกต์โดยไม่ล็อกอิน OAuth ซ้ำ (แบบ restart)

วิธีนี้ยังใช้ได้เสมอ ส่วนการสลับจากหน้า config ด้านบนให้ผลเดียวกันโดยไม่ต้องหยุด process

1. หยุด JUJU เดิมด้วย Ctrl+C
2. `cd` เข้าโปรเจกต์ใหม่แล้วรัน `juju`
3. เปิด Private config URL ของรอบใหม่ กดเพิ่ม client ให้โฟลเดอร์นี้ เลือก client ที่เคยลงทะเบียน แล้วอนุญาต scopes ที่ต้องการสำหรับ path นี้
4. ให้ client เรียก `project_overview` ใหม่ก่อนทำงาน ใช้โดเมน/Client ID เดิมได้หาก origin และ callback ไม่เปลี่ยน

สิทธิ์แต่ละ path จำไว้ใน SQLite จึงไม่ต้องอนุญาตซ้ำเมื่อกลับมา path เดิม ตราบใดที่ไม่ได้ถอนสิทธิ์หรือแทนที่ directory ด้วย inode ใหม่ งานเก่าถูกแยกตาม workspace; คำสั่งที่ถือ workspaceId/epoch เก่าจะถูกปฏิเสธ

**อัปเกรดจาก 0.1:** token/grant เก่ายังคงผูก root เดิม ไม่ได้รับสิทธิ์ข้าม root อัตโนมัติ ลงชื่อเข้าใช้ใหม่หนึ่งครั้งเพื่อรับ identity grant รุ่น 2; หลังจากนั้นใช้ local config อนุญาต path ใหม่ได้ โดยไม่ต้อง OAuth consent ซ้ำทุกโปรเจกต์ การถอน OAuth grant ยกเลิก identity ทั้งหมด ส่วนเอา scopes ออกจาก client ในหน้า config ถอนเฉพาะ path ปัจจุบัน

### หน้า config ไม่ใช่ public endpoint

- Bind เฉพาะ IPv4 loopback; ปฏิเสธ Host/Origin ต่างถิ่นและ forwarded/Cloudflare headers
- ทุก API ต้องมี token ส่วนตัวจาก terminal อายุ 8 ชั่วโมง และจำกัด request rate
- เปิด `http://127.0.0.1:21731` โดยไม่มี token จะไม่เห็นข้อมูล workspace หรือแก้ config ได้
- Tunnel ต้องชี้ **21730 เท่านั้น** ห้ามชี้ 21731; ไม่มี remote-enable switch สำหรับหน้า config ในรุ่นนี้
- การ bind localhost อย่างเดียวไม่ใช่ authentication; token ยังจำเป็น และไม่รับประกันป้องกัน process ที่มี UID เดียวกันหรือ proxy ที่เจ้าของตั้งใจ rewrite headers
- ถ้าพอร์ต 21731 ถูกใช้ JUJU จะ fail ไม่ย้าย port หรือ kill โปรแกรมอื่น

**Breaking change:** ตั้งแต่ 0.2 bare `juju` เปิด HTTP แม้ stdin เป็น pipe ต้องแก้ client ที่เคยใช้ no-args ให้ใช้ `juju stdio` อย่างชัดเจน `JUJU_NO_IMPLICIT_STDIO` ไม่มีผลแล้ว

<a id="connection"></a>
## เลือกวิธีเชื่อมต่อ

| ต้องการใช้งาน | วิธี | ต้องมีโดเมนหรือไม่ |
|---|---|---|
| แอป AI ในเครื่องที่เปิด subprocess ได้ เช่น Codex | STDIO | ไม่ต้อง |
| ChatGPT บนเว็บเข้าถึงโปรเจกต์ในเครื่อง | Streamable HTTP + OAuth | ต้องมี HTTPS ที่เข้าถึงเครื่องได้ |
| Codex เชื่อมเซิร์ฟเวอร์ระยะไกล | Streamable HTTP + OAuth | ใช้ public HTTPS ตามคู่มือนี้ |

**STDIO** อ่านว่า standard input/output (ไม่ใช่ Studio): แอป AI เปิด JUJU เป็นโปรเซสและคุยผ่าน stdin/stdout ส่วน **OAuth** เป็นวิธียืนยันตัวตนที่ใช้กับ HTTP ไม่ใช่ transport อีกชนิดหนึ่ง

เริ่มจาก STDIO หากคุณเขียนโค้ดบนเครื่องเดียวกัน วิธีนี้ไม่ต้องตั้ง tunnel หรือกรอก Client ID/Secret

<a id="install"></a>
## 1. ติดตั้งและตรวจเครื่อง

ต้องมี Node.js และ npm โดย package กำหนด Node **>=22.12.0** สภาพแวดล้อมที่บันทึกผลทดสอบจริงคือ macOS Apple Silicon กับ Node 22.23.2; Windows ยังไม่รองรับ ส่วน Linux/macOS Intel ต้องตรวจผลทดสอบของเครื่องนั้นเพิ่มเติม

```bash
node --version
npm --version
npm install -g juju-mcp
juju --version
juju --help
juju doctor
```

`juju doctor` ช่วยตรวจ config, SQLite, Git และความพร้อมของ sandbox หากยังไม่ได้ตั้ง public URL จะมีข้อความเตือนสำหรับ HTTP แต่ **ไม่จำเป็นต้องตั้ง URL เพื่อใช้ STDIO**

หากไม่ต้องการติดตั้ง global ใช้รูปแบบนี้แทน:

```bash
npx --yes --package=juju-mcp juju --version
npx --yes --package=juju-mcp juju stdio --root "/absolute/path/to/project"
```

สำหรับการใช้งานที่ต้องการเวอร์ชันแน่นอน ให้ระบุเวอร์ชันแพ็กเกจที่ตรวจแล้วหลัง `juju-mcp@` การใช้ `latest` อาจได้รุ่นใหม่เมื่อ npm ตรวจ registry

**อย่าใช้ `npm install -g juju` หรือ `npx install juju`** เพราะไม่ใช่คำสั่งติดตั้งแพ็กเกจนี้

### Workspace คือโฟลเดอร์ไหน

- `juju start` ใช้โฟลเดอร์ที่คุณ `cd` เข้าไปก่อนรัน
- `juju stdio --root "/path/to/project"` ใช้โฟลเดอร์ที่ระบุ
- ไม่เลื่อนขึ้น Git root อัตโนมัติ จึงเลือกแพ็กเกจย่อยใน monorepo ได้
- ใช้กับโฟลเดอร์ที่ไม่มี Git ได้ ไม่ต้องสร้าง `.juju.json` เพื่อเริ่ม
- หนึ่งโปรเซสใช้หนึ่ง workspace; AI เปลี่ยน root หรือเพิ่มสิทธิ์ของตัวเองผ่าน tool ไม่ได้
- ใส่เครื่องหมายคำพูดเมื่อ path มีช่องว่างหรือภาษาไทย

<a id="stdio"></a>
## 2. เชื่อมในเครื่องผ่าน STDIO

### ขั้นที่ 1 — เลือกโฟลเดอร์และสิทธิ์

แทน path ตัวอย่างด้วยโปรเจกต์จริง:

```bash
cd "/absolute/path/to/project"
juju trust --mode edit
```

`edit` ให้แก้ไฟล์ได้ แต่รันคำสั่งต้องอนุมัติแยก หากต้องการให้ AI รัน test/build/install ได้ตาม standing consent ให้ดู [โหมด trusted](#permissions)

### ขั้นที่ 2 — กรอกในหน้าตั้งค่า MCP

เลือก **STDIO** แล้วกรอก:

| ช่อง | ค่า |
|---|---|
| Name | `juju-local` |
| Command | `juju` หรือ absolute path ของคำสั่ง |
| Arguments | `stdio`, `--root`, `/absolute/path/to/project` แยก 3 รายการ |
| Working directory หากมี | โฟลเดอร์โปรเจกต์เดียวกัน |
| Environment variables | ไม่ต้องเพิ่มสำหรับการตั้งค่าพื้นฐาน |

บน macOS หา absolute path ได้ด้วย `command -v juju` แล้วคัดลอกผลไปใส่ช่อง Command เช่น `/opt/homebrew/bin/juju` อย่าถือว่า path นี้ใช้ได้กับทุกเครื่อง

**ไม่ต้องรัน `juju start` ไว้ก่อน** แอป AI จะเปิดและปิด STDIO server เอง หลังบันทึกให้ Restart/reconnect MCP ในแอป

### ตั้งค่า Codex ผ่าน terminal

```bash
codex mcp add juju-local -- juju stdio --root "/absolute/path/to/project"
```

หรือเพิ่มใน `~/.codex/config.toml` โดยไม่สร้างหัวข้อชื่อเดียวกันซ้ำ:

```toml
[mcp_servers.juju-local]
command = "juju"
args = ["stdio", "--root", "/absolute/path/to/project"]
```

Codex ใช้ TOML; อย่านำ JSON ของแอปอื่นไปวางในไฟล์นี้

### แอปที่ใช้รูปแบบ `mcpServers` JSON

สำหรับ client ที่รองรับรูปแบบนี้ ให้เพิ่มในไฟล์ตั้งค่า MCP ของแอปนั้นตามคู่มือของแอป:

```json
{
  "mcpServers": {
    "juju": {
      "command": "juju",
      "args": ["stdio", "--root", "/absolute/path/to/project"]
    }
  }
}
```

ถ้าใช้ npx เปลี่ยนเฉพาะรายการเซิร์ฟเวอร์เป็น:

```json
{
  "command": "npx",
  "args": ["--yes", "--package=juju-mcp", "juju", "stdio", "--root", "/absolute/path/to/project"]
}
```

GUI อาจมี PATH ต่างจาก terminal หากขึ้น command not found ให้ใช้ absolute path ของ `juju` หรือ `npx` และตรวจว่าแอปเรียก Node ได้ด้วย ใช้ `--root` เสมอเพื่อไม่ให้เผลอใช้ home หรือโฟลเดอร์เริ่มต้นของแอป

### ขั้นที่ 3 — ทดสอบจากแชต

ให้ AI เรียก `project_overview` แล้วตรวจว่า root ตรงกับโปรเจกต์ที่เลือก จากนั้นอ่าน ค้นหา หรือแก้ไฟล์ตามสิทธิ์ที่ตั้งไว้ได้เลย ไม่ต้องลงทะเบียนแชตและไม่ต้องคัดลอกข้อความอนุญาตให้ AI

เครื่องมืออื่นยังต้องส่ง `workspaceId` และ `workspaceEpoch` จาก overview เพื่อป้องกันการทำงานผิดโปรเจกต์หลัง restart หรือสลับโฟลเดอร์ แอป AI จัดการข้อมูลนี้ผ่านผลลัพธ์เครื่องมือได้ตามปกติ

ค่าเริ่มต้น inspect อนุญาตให้อ่านและค้นหา การแก้ไฟล์/รันคำสั่งอาจขออนุมัติ action ตาม trust mode ที่ตั้งไว้ ส่วน Desktop ต้องเปิดสิทธิ์แอปแยกเสมอ ดู [สิทธิ์แก้ไฟล์และรันคำสั่ง](#permissions)

<a id="chatgpt"></a>
## 3. เชื่อม ChatGPT ผ่าน HTTP + OAuth

เส้นทางการเชื่อมต่อคือ **ChatGPT → public HTTPS → tunnel ของคุณ → JUJU ที่ 127.0.0.1:21730** เครื่องที่รัน JUJU ต้องเปิดอยู่และเข้าถึงได้

### Compact Tool Surface (ค่าเริ่มต้นของ HTTP ตั้งแต่ 0.7.1)

ChatGPT และ remote client อื่นเห็นเครื่องมือ **19 ตัว** แทน 74: `project_overview`, `juju_discover` และ gateway ตามหมวด (`juju_read`/`juju_write`/`juju_exec`, `juju_git_*`, `juju_desktop_*`, `juju_assist_*`, `juju_media`, `juju_browser`, `juju_game`, `juju_workflow_*`, `juju_schedule`, `juju_web`) ขนาด tool list ที่ client ต้องโหลดลดจากราว 236 KB เหลือราว 47 KB โดย**สิทธิ์ไม่เปลี่ยนแม้แต่ข้อเดียว**: ทุก operation ผ่าน scope/ACL/trust/approval/guard ของ operation ปลายทางเหมือนเรียกตรง

ตัวอย่าง flow ที่ AI ใช้:

```text
User: "แก้ src/example.ts ให้ function foo คืนค่า 2"

project_overview
juju_discover  { query: "edit TypeScript file" }
juju_read      { operation: "read_files", args: { files: [{ path: "src/example.ts" }] } }
juju_write     { operation: "edit_file",  args: { path: "src/example.ts", edits: [{ find: "return 1", replace: "return 2" }], expectedHash: "…" } }
juju_read      { operation: "read_files", args: { files: [{ path: "src/example.ts" }] } }
```

ตัวอย่างสื่อ: `juju_discover { query: "transcribe local video" }` → `juju_media { operation: "media_open", … }` → `juju_media { operation: "media_transcribe", … }`

กติกาสำคัญ: `workspaceId`/`workspaceEpoch` อยู่ระดับบนสุดของ gateway call เท่านั้น (ห้ามใส่ใน `args`), ใช้ `idempotencyKey` เดิมเมื่อ retry คำสั่งเดิม, และเรียก `juju_discover` พร้อม `operation="<ชื่อ>"` เมื่อต้องการ schema เต็มของ operation นั้น

ต้องการ catalog เต็ม 74 tools ผ่าน HTTP: ตั้ง `"toolSurface": "full"` ใน global config หรือรัน `juju start --tools full` ส่วน STDIO ได้ catalog เต็มเป็นค่าเริ่มต้นอยู่แล้ว (บังคับย่อได้ด้วย `juju stdio --tools compact`)

### Hybrid surface — 49 tools สำหรับ client ที่รับได้ราว 50 (0.7.2)

ถ้า client ของคุณรับ tools ได้จำกัด (เช่นราว 49) แต่อยากให้เครื่องมือหลักเป็น direct แบบเดิม รัน:

```bash
juju start --tools hybrid
```

จะได้ **49 tools พอดี**: ส่วนหัวคือชุด coverage เดียวกับ compact ทั้งหมด (overview + `juju_discover` + gateway 17 ตัว → เข้าถึงครบ 74 เสมอ แม้ client จะตัดท้ายลิสต์ทิ้ง) ตามด้วย direct tools ยอดนิยม 30 ตัว (read/write/edit/search/git/run/jobs) ชื่อและ schema เดิมทุกตัว payload ~113 KB (เต็ม ~237 KB, compact ~47 KB) สิทธิ์เหมือนเดิมทุกเส้นทาง ตั้งถาวรได้ด้วย `"toolSurface": "hybrid"` ใน global config (จะมีผลกับ STDIO ด้วย)

ใช้โดเมนของคุณแทน `juju.example.com` ในทุกขั้นตอน

### ขั้นที่ 1 — ตั้ง public origin ครั้งแรก

```bash
juju init --public-url https://juju.example.com
cd "/absolute/path/to/project"
juju trust --mode edit
juju start
```

`init` บันทึก global profile; ครั้งถัดไปเพียง `cd` เข้าโปรเจกต์แล้ว `juju` ไม่ต้อง init ซ้ำทุก repository

หากยังไม่มี public URL เซิร์ฟเวอร์ HTTP จะอยู่ในสถานะ locked/setup-required ไม่เปิดให้เรียกแบบไม่มี authentication แม้มาจาก localhost

### ขั้นที่ 2 — ตั้ง tunnel ของคุณ

ให้ hostname `juju.example.com` ส่งไปยัง service:

```text
http://127.0.0.1:21730
```

ต้องส่ง **ทุก path** ของ hostname ไม่ใช่เฉพาะ `/mcp` เพราะ OAuth ใช้ discovery, authorization, token และ interaction routes ด้วย JUJU ไม่รัน cloudflared หรือสร้าง DNS ให้ ดู [คู่มือ Tunnel](docs/TUNNEL.md) และ [ตัวอย่าง config](examples/cloudflared.yml)

การเปิดโดเมนได้อย่างเดียวไม่ยืนยันว่า OAuth ใช้ได้ หากมีหน้า login ของ proxy คั่นอยู่ ChatGPT ต้องเข้าถึง MCP และ OAuth endpoints ได้ด้วย

### ขั้นที่ 3 — สร้างแอป MCP ใน ChatGPT

เปิด Developer mode แล้วเปิดหน้าสร้างแอป/ปลั๊กอิน MCP ชื่อเมนูอาจต่างกันตาม UI และบัญชี

| ช่อง | ค่า |
|---|---|
| ชื่อ | `JUJU` |
| Server URL | `https://juju.example.com/mcp` — ต้องมี `/mcp` |
| Authentication | `OAuth` |
| OAuth registration | ไคลเอนต์ OAuth ที่ผู้ใช้กำหนด / static client |

JUJU ปิด DCR โดยค่าเริ่มต้นและไม่ได้เปิด CIMD ข้อความว่าใช้ DCR/CIMD ไม่ได้จึงไม่ใช่เหตุให้เปลี่ยนไป No Authentication ให้ใช้ static client ตามขั้นตอนต่อไป

### ขั้นที่ 4 — คัดลอก Callback URL จาก ChatGPT

ใน OAuth advanced settings กดคัดลอก **Callback URL จริงของแอปที่กำลังสร้าง** ไม่เดาจากตัวอย่างเก่าหรือพิมพ์ตามภาพ

เปิด terminal อีกหน้า โดยปล่อย `juju start` ทำงาน แล้วรัน:

```bash
juju auth add-client --name "ChatGPT" --redirect-uri "PASTE_EXACT_CALLBACK_URL_HERE"
```

แทนข้อความในเครื่องหมายคำพูดด้วย URL จริง JUJU จะแสดง `client_id`, `client_secret` และ `auth method` โดย secret แสดงครั้งเดียว เก็บในที่ปลอดภัยและอย่าส่งในแชต

### ขั้นที่ 5 — นำค่ากลับไปใส่ ChatGPT

| ช่องใน OAuth advanced settings | ค่าที่ใส่ |
|---|---|
| OAuth Client ID | ค่า `client_id` จาก JUJU |
| OAuth Client Secret | ค่า `client_secret` จาก JUJU |
| Token endpoint authentication | `client_secret_basic` / HTTP Basic |
| Scopes หากให้ระบุ | `juju:read juju:write juju:exec` หรือเฉพาะสิทธิ์ที่ต้องการ |

สำหรับ client ที่สร้างตามคำสั่งข้างบน **อย่าเลือก `none`** ที่ token endpoint ส่วน scope `openid` ที่ ChatGPT อาจส่งเพิ่มเป็นส่วนของ OIDC ไม่ใช่สิทธิ์รันคำสั่ง

หากหน้าตั้งค่ามีช่อง **Bearer token env var** ช่องนี้รับชื่อตัวแปรสภาพแวดล้อม ไม่ใช่ OAuth Client Secret สำหรับ OAuth ให้เว้นช่องนี้และ custom headers ว่าง

### ขั้นที่ 6 — อนุมัติจากเครื่องเจ้าของ

กดสร้าง/เชื่อมต่อใน ChatGPT เบราว์เซอร์จะเปิดหน้า JUJU ที่มี Request ID และ phrase จากนั้นใน terminal ของโปรเจกต์:

```bash
cd "/absolute/path/to/project"
juju auth pending
```

ตรวจ phrase, client, callback URL, workspace และ scopes ให้ตรงกับคำขอที่คุณตั้งใจ แล้ว **คัดลอกคำสั่งทั้งบรรทัดหลัง `approve:` จากผลล่าสุดมารัน** เช่น:

```bash
juju auth approve -- REQUEST_ID_FROM_LATEST_OUTPUT
```

`--` บอก CLI ว่าข้อความถัดไปเป็น ID แม้ขึ้นต้นด้วย `-` หากรุ่นที่ติดตั้งแสดงคำสั่งโดยไม่มี `--` แล้วขึ้น `unknown option` ให้เติม `--` ตามตัวอย่างนี้ ใช้ได้ทันทีใน 0.6.2 โดยไม่ต้องติดตั้งใหม่ หากคำขอหมดอายุ ให้เริ่มเชื่อมต่อใหม่และใช้ ID ล่าสุด

รอหน้าเบราว์เซอร์จบการลงชื่อเข้าใช้อัตโนมัติ ไม่ต้องกดสร้างคำขอใหม่ระหว่างรอ การแสดง `approved` หมายถึง owner consent สำเร็จ ยังต้องผ่าน callback และ token exchange ก่อนถือว่าเชื่อมครบ

เลือก JUJU ในบทสนทนาแล้วทดสอบ `project_overview` และ `list_files` ตามตัวอย่าง STDIO

<a id="codex-oauth"></a>
## 4. เชื่อม Codex ผ่าน OAuth

ใช้ HTTP server และ tunnel จากขั้นตอนก่อน สำหรับ Codex ลงทะเบียน **public client + PKCE** ซึ่งไม่ใช้ client secret ตัวอย่างนี้ใช้ callback port คงที่ 4321:

```bash
juju auth add-client --name "Codex" --public --redirect-uri "http://127.0.0.1:4321/callback"
```

เพิ่มใน `~/.codex/config.toml` แล้วแทน Client ID และโดเมน:

```toml
[mcp_servers.juju-remote]
url = "https://juju.example.com/mcp"

[mcp_servers.juju-remote.oauth]
client_id = "CLIENT_ID_FROM_JUJU"
callback_url = "http://127.0.0.1:4321/callback"
callback_port = 4321
```

```bash
codex mcp login juju-remote --scopes juju:read,juju:write,juju:exec
```

จากนั้นตรวจ phrase และอนุมัติด้วย `juju auth pending` / `juju auth approve` บนเครื่องที่รัน JUJU เช่นเดียวกับ ChatGPT ส่วน callback loopback ต้องเข้าถึง Codex ที่เปิดเบราว์เซอร์ลงชื่อเข้าใช้ พอร์ต 4321 ต้องว่าง

ตั้งค่า callback ให้ตรงทั้ง URL ที่ลงทะเบียนและ listener port หาก client แสดง callback ต่างจากนี้ ให้ตรวจเวอร์ชัน/config และใช้ URL ที่ตรงจริง ห้ามใช้ wildcard เพื่อแก้ปัญหา

อ้างอิงการตั้งค่าแอป: [Codex MCP/OAuth](https://learn.chatgpt.com/docs/extend/mcp?surface=cli) และ [ChatGPT Developer mode](https://developers.openai.com/api/docs/guides/developer-mode) การรองรับตามเอกสารไม่ใช่ผลทดสอบบัญชีจริงของ JUJU

<a id="permissions"></a>
## 5. สิทธิ์แก้ไฟล์และรันคำสั่ง

ทุกโหมดตรวจ OAuth/Client access ตามเดิม โดยไม่ต้องยืนยันรายแชต งานตั้งเวลาต้องมี [approval ของตาราง](docs/SCHEDULES.md) แยกต่างหาก

OAuth consent, trust mode ของ JUJU และการยืนยัน tool call ของแอป AI เป็นคนละชั้น การกดอนุมัติใน ChatGPT ไม่ได้เปลี่ยน JUJU เป็น trusted อัตโนมัติ

| Mode | อ่าน/ค้นหาและ preview | เปลี่ยนไฟล์ | รันคำสั่ง |
|---|---|---|---|
| `inspect` (ค่าเริ่มต้น) | ได้ตาม path policy | อนุมัติแต่ละ action | อนุมัติแต่ละ action |
| `edit` | ได้ | ได้ตาม standing consent | อนุมัติแต่ละ action |
| `trusted` | ได้ | ได้ | ได้ด้วยสิทธิ์ OS ของคุณ |

เลือกโหมดจาก **โฟลเดอร์เดียวกับ workspace**:

```bash
juju trust --mode inspect
juju trust --mode edit
```

สองคำสั่งข้างบนเป็นตัวเลือก ให้รันเฉพาะโหมดที่ต้องการ หากต้องการให้ AI รัน test/build/install ได้โดยไม่ขออนุมัติซ้ำที่ terminal ของ JUJU:

```bash
juju trust --mode trusted --yes
```

**Trusted ไม่ใช่ OS sandbox** แม้คำสั่งชื่อ test/lint ก็รันโค้ดใด ๆ ด้วยสิทธิ์ผู้ใช้ได้ รวมถึงโค้ดติดตั้ง dependencies แอป AI ยังอาจขอคำยืนยันตามการตั้งค่าของแอป และ OAuth ต้องมี scope ที่ตรงกับ action

หากเห็น `Exec: local approval required` ให้เลือก trusted เมื่อคุณตั้งใจให้สิทธิ์ถาวรสำหรับ workspace นั้น หรืออนุมัติเป็นครั้ง ๆ:

```bash
juju pending
juju approve ACTION_ID
```

`juju approve` ใช้กับ action ส่วน `juju auth approve` ใช้กับการลงชื่อเข้าใช้ อย่าสลับสองคำสั่งนี้

<a id="sandbox"></a>
## 6. Sandbox และ global config

`OS sandbox: NOT enabled` หมายถึงยังไม่ได้เปิด command sandbox ไม่ใช่ OAuth ล้มเหลว และ `trust --mode trusted` ไม่ได้เปิด sandbox

ใช้ `juju doctor` ดู config directory บน macOS ค่าเริ่มต้นคือ:

```text
~/Library/Application Support/juju/config.json
```

เปิดไฟล์เดิมและเพิ่ม/แก้เฉพาะ key ที่ต้องการ ไม่แทนทั้งไฟล์จนค่า public URL หรือ config อื่นหาย ตัวอย่างส่วนที่เพิ่ม:

```json
{
  "commandSandbox": "prefer"
}
```

นี่เป็นเพียง fragment ให้รวมกับ JSON เดิมแล้ว Restart JUJU สำหรับ STDIO ให้ reconnect MCP ในแอป

| ค่า | พฤติกรรมเมื่อคำสั่งร้องขอ/default ให้ใช้ sandbox |
|---|---|
| `off` | ปิดโดยค่าเริ่มต้น; tool บางตัวร้องขอเปิดเป็นรายคำสั่งได้ |
| `prefer` | ใช้เมื่อมี backend; หากไม่มีอาจรันแบบ unsandboxed |
| `require` | ถ้าจะใช้ sandbox แต่ backend ไม่มี ให้ปฏิเสธ |

ข้อจำกัดของ implementation ปัจจุบัน: ตัวเลือก `sandbox:false` ของคำสั่งสามารถ override ค่า default ได้ จึง **ไม่ควรถือว่า `require` เป็นข้อบังคับที่ client ข้ามไม่ได้** ตรวจค่า `sandboxed` ของผลลัพธ์งานจริง

macOS ใช้ `sandbox-exec`; Linux มี adapter สำหรับ `bwrap` ขอบเขตเน้นจำกัดการเขียนให้อยู่ใน workspace และ cache/temp ที่อนุญาต ไม่ใช่การรับประกันว่าโค้ดอ่านข้อมูลนอก workspace ไม่ได้ และไม่ได้ป้องกัน hostile process ที่รันด้วยผู้ใช้เดียวกัน

Config อื่น เช่น limits, secret denies, env allowlist, `allowWebFetch` และ LSP ดู [schema](schemas/global-config.schema.json) การเปลี่ยน security config ต้องทำโดยเจ้าของใน global config; `.juju.json` และ AGENTS.md ใน repository ไม่ได้มีอำนาจเพิ่มสิทธิ์

<a id="desktop"></a>
## อ่านภาพและควบคุมหน้าต่าง (0.4.1)

`read_image` อ่านภาพใน workspace ได้อยู่แล้ว รุ่นนี้เพิ่ม `desktop_status`,
`desktop_windows`, `desktop_capture` (พร้อม OCR), `desktop_accessibility` และ
`desktop_action` สำหรับ macOS 14+ ให้ใช้ helper ที่ compile จาก Swift source
ในแพ็กเกจด้วยคำสั่ง `juju desktop setup` แล้วขอ Screen Recording/Accessibility
จาก OS ตาม [คู่มือ Desktop](docs/DESKTOP.md)

ตั้งครั้งเดียวในโฟลเดอร์โปรเจกต์ แล้วเปิด server:

```bash
juju desktop allow --app com.google.Chrome --mode control --persist --yes
juju
```

ครั้งต่อไปพิมพ์ `juju` ในพาธเดิมได้เลย ไม่ต้องอนุญาตซ้ำ ใช้ `juju desktop status`
จาก Terminal อีกอันในพาธเดียวกันเพื่อตรวจค่า ใช้ `juju desktop disable`
เพื่อปิดและลืมสิทธิ์ (ทำได้แม้เซิร์ฟเวอร์หยุดอยู่) หรือกดปิดใน Local Config
หากต้องการชั่วคราว ใช้ `--minutes 60` แทน `--persist` โดย server ต้องรันอยู่

สิทธิ์นี้แยกจาก trusted/bypass และไม่ให้พาธอื่นตามไปด้วย เฉพาะแบบชั่วคราว
รีเซ็ตเมื่อ restart/สลับ workspace; แบบจำค่าจะกลับมาเมื่อใช้พาธเดิม Client
ต้องมี juju:exec; การส่ง input ยังตรวจ trust/local approval ภาพที่ได้มี
snapshotId อายุไม่เกิน 30 วินาทีและพิกัดในภาพ การคลิก/พิมพ์ต้อง capture ใหม่
เพื่อยืนยันผล ไม่บันทึกภาพหรือข้อความที่พิมพ์ลง audit/state

ทดสอบจับภาพและ OCR ของหน้าต่าง fixture จริงบน macOS arm64 แล้ว ส่วน input/AX
สำเร็จจริงยังเป็น MANUAL_NOT_RUN ในรายงานทดสอบ (ครั้งนั้น Accessibility เป็น false)
แอปที่อนุญาตอาจมีข้อมูลนอก workspace; app allowlist ไม่ใช่ OS sandbox

<a id="tools"></a>
## 7. AI ทำอะไรได้บ้าง

JUJU รุ่น 0.4.3 มี **48 tools** ไม่ต้องติดตั้ง LLM ใน JUJU เพื่อใช้ semantic analysis ของ TypeScript/JavaScript

| งาน | เครื่องมือ |
|---|---|
| สำรวจโปรเจกต์ | `project_overview`, `list_files`, `glob_files`, `read_files`, `read_image`, `read_instructions`, `environment_info` |
| ค้นหา | `search_code` |
| เพิ่ม/แก้/ย้าย/ลบ | `write_file`, `edit_file`, `apply_patch`, `replace_in_files`, `delete_path`, `move_path`, `make_directory` |
| Semantic analysis | `symbols`, `references`, `preview_rename` |
| ตรวจแผนและย้อนกลับ | `preview_changes`, `apply_changes`, `rollback_changes`, `change_history` |
| Git | `git_status`, `git_diff`, `git_log`, `git_commit` |
| รันงาน | `run_command`, `run_commands`, `run_task`, `exec_command` |
| ติดตามงาน | `job_status`, `job_output`, `job_wait`, `job_input`, `job_cancel`, `list_jobs` |
| สถานะและส่งต่องาน | `diagnostics`, `approval_status`, `todo_write`, `todo_read`, `handoff_read`, `handoff_write`, `fetch_url` |

`fetch_url` ต้องเปิด `allowWebFetch` โดยเจ้าของและผ่าน policy; ไม่ใช่ browser automation ส่วน `git_commit` ไม่มีการ push ในตัว แต่คำสั่งทั่วไปใน trusted/allow-all/bypass mode ทำสิ่งอื่นได้ตามสิทธิ์ OS

### ตัวอย่างข้อความสั่ง AI

> ใช้ JUJU สำรวจโปรเจกต์ก่อน แล้วค้นหาฟังก์ชัน login แสดงไฟล์และบรรทัดที่เกี่ยวข้อง

> แสดง preview การแก้บั๊กนี้ ตรวจ hash ก่อน apply แล้วรัน test ที่เกี่ยวข้อง รายงาน command, exit code และ log

> ใช้ run_commands รัน lint และ typecheck พร้อมกันถ้างานทั้งสองไม่เขียน output ชุดเดียวกัน

> เปิด dev server แบบ background แล้วส่ง jobId ให้ฉัน ใช้ job_output ดู log และ job_cancel เมื่อเสร็จ

> ติดตั้ง dependency ที่ตกลงกันด้วย package manager ของโปรเจกต์ แล้วตรวจ diff ของ manifest และ lockfile

`run_commands` รองรับสูงสุด 8 คำสั่งต่อการเรียกหนึ่งครั้ง งานที่เขียนไฟล์ร่วมกัน เช่น install กับ build อาจต้องรันตามลำดับ Background jobs ใช้ polling และ log แบบ bounded ไม่ใช่ terminal ที่ส่งข้อมูลไม่จำกัด อย่าสั่งงานเดิมซ้ำเพียงเพราะยังไม่จบ

AI ต้องเรียก `project_overview` เพื่อรับ workspaceId/workspaceEpoch แล้วส่ง context นี้ให้ tools อื่น ตัวอย่างข้อความด้านบนเป็น prompt ไม่ใช่ JSON payload สำหรับเรียก MCP โดยตรง

### แก้ไขและ recovery

การแก้ไฟล์ผ่าน file tools ใช้ hash, immutable plans และ journal พร้อม backup; stale hash จะถูกปฏิเสธ Rollback ไม่ควรทับ human edits ที่เกิดหลัง apply และ multi-file writes ไม่ใช่ transaction ที่ atomic ทั้งโปรเจกต์

**ไฟล์ที่เปลี่ยนจาก shell, tests หรือ package manager ไม่ได้รับการ journal อัตโนมัติเหมือน file tools** ใช้ Git และตรวจ diff ประกอบ อย่าถือว่า rollback ของ JUJU ย้อนผลทุกคำสั่งได้

### ภาษาอื่นนอกเหนือจาก TS/JS

ติดตั้ง language server ของภาษานั้นเอง แล้วลงทะเบียนด้วย `juju lsp add` ดู `juju lsp add --help` และ [LSP.md](docs/LSP.md) ก่อนตั้ง args/extensions จากนั้น Restart JUJU

```bash
juju lsp list
```

LSP เป็นโปรแกรมที่ทำงานด้วยสิทธิ์คุณ ไม่ใช่ส่วนของ OS sandbox สำหรับ jobs การมี adapter ไม่ได้แปลว่าทุกภาษาและ language server ผ่านการทดสอบแล้ว

<a id="large-inputs"></a>
## คำสั่งยาวและไฟล์ใหญ่

ตั้งครั้งเดียวจากโฟลเดอร์ไหนก็ได้:

```bash
juju limits --profile large
```

หยุดเซิร์ฟเวอร์ตัวเดิมด้วย Ctrl+C แล้วเปิด `juju` ใหม่ สำหรับ STDIO ให้แอป
เริ่ม subprocess ใหม่ ค่า large รองรับ **shell source 8 MiB, ไฟล์ 16 MiB,
request รวม 32 MiB** โดยเก็บ OAuth และสิทธิ์เดิมไว้ ไม่เปิด unlimited

คำสั่งยาวทำงานผ่านไฟล์สคริปต์ส่วนตัวของ JUJU เพื่อไม่ชนข้อจำกัด native argv
สำหรับ HTML/CSS/JS ให้ AI ใช้ `write_file` / `edit_file` แล้วใช้คำสั่งสั้น
สำหรับ build/test/dev server ได้เลย ไม่ต้องลดฟีเจอร์เว็บเพราะเพดานเดิม
8,192 ตัวอักษร อ่านค่าจริงจาก `project_overview.policy.limits`

ขนาดนับเป็น UTF-8 bytes และต้องเผื่อ JSON/escaping ข้อจำกัดฝั่งแอป AI
หรือ proxy ยังอาจต่ำกว่า JUJU ดู [วิธีใช้และแก้ error](docs/LARGE_INPUTS.md)

<a id="operations"></a>
## 8. ใช้งานประจำวันและอัปเดต

| คำสั่ง | ใช้เมื่อ |
|---|---|
| `juju` / `juju start` | เปิด HTTP server และ local config จากโฟลเดอร์ปัจจุบัน |
| `juju stdio --root PATH` | ให้ local MCP client เปิดใช้งาน |
| `juju status` | ตรวจ workspace/server |
| `juju stop` | หยุด server ของ workspace นี้ |
| `juju kill` | หยุด JUJU ทุกโปรเจกต์ใน state ชุดนี้จากโฟลเดอร์ไหนก็ได้ เก็บ OAuth login ไว้ |
| `juju limits` | ดูขนาดคำสั่ง/ไฟล์/แผน/request ที่บันทึกไว้ |
| `juju limits --profile large` | เพิ่มเพดานข้อมูล แล้ว restart เพื่อใช้งาน |
| `juju doctor` | ตรวจ environment และ config |
| `juju setup` | ตรวจ/ติดตั้ง dependency และ native backend ที่ขาด แล้วทำ capability probes |
| `juju setup --check` | ตรวจ readiness อย่างเดียว ไม่ติดตั้ง/ไม่เปลี่ยน config |
| `juju audit --limit 20` | ตรวจ audit ของ workspace |
| `juju auth clients` | ดู client ที่ลงทะเบียน |
| `juju auth list` | ดู grants |
| `juju auth revoke --help` | ดูวิธียกเลิก grant |
| `juju recover --help` | ตรวจคำสั่ง recovery ที่รองรับ |

Ctrl+C ใน terminal ของ `juju start` ใช้หยุดเซิร์ฟเวอร์ได้ อย่าเปิด HTTP และ STDIO ซ้อนใน workspace เดียวกันเมื่อใช้ IPC/profile เดียวกัน เปลี่ยน workspace ต้องตั้ง root และ trust ให้ตรง แล้วเชื่อม/อนุมัติใหม่ตามที่จำเป็น identity token ใช้กับ root ใหม่ได้เฉพาะเมื่อเจ้าของให้ client/path access แล้ว; token รุ่นเก่ายังคงผูก root เดิม

### ปิด JUJU ทั้งหมดแล้วเปิดใหม่ โดยเก็บการล็อกอิน

รันจากโฟลเดอร์ไหนก็ได้:

```bash
juju kill
```

หยุดเฉพาะเซิร์ฟเวอร์ JUJU และ jobs ที่มันรัน ไม่ปิดแอป Terminal, GPT หรือ
โปรแกรมอื่น แล้วเข้าโฟลเดอร์โปรเจกต์ที่ต้องการและพิมพ์ `juju` ใหม่
ถ้าต้องการดูผลเป็น JSON ใช้ `juju kill --json`; `--timeout 30` คือเวลารอปิดต่อ server

คำสั่งนี้เก็บ client registration, signing keys, access/refresh grants,
public URL และสิทธิ์ที่บันทึกไว้ ไม่ต้องลงทะเบียน connector ใหม่เพราะการ kill
แต่ต้องใช้ state/config และ public URL เดิม โทเคนต้องยัง valid และ client
ต้องมีสิทธิ์ในพาธนั้น ระหว่างปิด endpoint จะ offline; การ retry ของ GPT
ขึ้นกับ client และยังไม่อ้างว่าทดสอบ UI จริงแล้ว ให้ AI เรียก `project_overview`
อีกครั้งหลังเปิดเพื่อรับ epoch ใหม่ หากใช้ `JUJU_CONFIG_DIR` จะหยุดเฉพาะ state
ชุดที่ระบุ ไม่แตะเซิร์ฟเวอร์ใน config อื่น ถ้าไม่มีตัวที่กำลังรัน คำสั่งจบสำเร็จ

ถ้าเซิร์ฟเวอร์ไม่ตอบ IPC/ปิดไม่เสร็จ จะรายงานข้อผิดพลาดโดยไม่ force-kill
โปรแกรมที่ระบุตัวตนไม่ได้ โดยเฉพาะ process รุ่นเก่าที่ไม่มี socket เหลืออยู่
ต้องหยุดจาก Terminal เดิมเอง

### อัปเดตจาก npm

ตอนนี้ **ยังไม่มี `juju update`** ใช้ npm:

```bash
npm view juju-mcp version
npm install -g juju-mcp@latest
juju --version
```

หยุด server เดิมก่อนอัปเดตแล้วเปิดใหม่ สำหรับ STDIO ให้ Restart/reconnect MCP แอป การติดตั้งใหม่ไม่เปลี่ยนโค้ดใน process ที่กำลังรันอยู่ และ `@latest` ไม่ได้รับประกันว่าจะมีแพตช์ที่ยังไม่ได้ publish

### อัปเกรดเป็น 0.8.2

1. รอ jobs ให้เสร็จ แล้วหยุด HTTP server/STDIO process เดิม
2. รัน `npm install -g juju-mcp@0.8.2` และตรวจ `juju --version`
3. รัน `juju setup` จาก terminal ของเจ้าของเครื่อง แล้วใช้ `juju setup --check` ยืนยัน dependency/native backends; การเปิด web และ Desktop app consent ยังเป็นสิทธิ์แยก
4. เปิด JUJU ใหม่จาก workspace เดิม แล้วให้ MCP client reconnect/refresh tool catalog และเรียก `project_overview` ใหม่เพราะ epoch เปลี่ยน

ถ้า Windows/Mac/Linux เป็นคนละเครื่องหรือคนละ MCP server ต้องติดตั้ง/รัน `juju setup` **แยกบนแต่ละเครื่อง** การอัปเดต source หรือ global npm บนเครื่องหนึ่งไม่เปลี่ยนอีกเครื่อง Existing OAuth/workspace ACL/trust ไม่ถูกล้างจากการอัปเกรด

<a id="อัปเกรดเป็น-063"></a>
### ประวัติ: อัปเกรดเป็น 0.7.0

1. รอ jobs ให้เสร็จ แล้วหยุด HTTP server เดิมด้วย `Ctrl+C` หรือหยุด MCP subprocess จากแอปที่ใช้ STDIO
2. รัน `npm install -g juju-mcp@0.7.0` แล้วตรวจ `juju --version` ให้เป็น `0.7.0` การอัปเกรดไม่จำเป็นต้องเปลี่ยนโปรไฟล์ข้อมูลหรือค่าความปลอดภัย; ส่วนสื่อที่ใช้ Chromium/FFmpeg/Whisper ให้ตรวจด้วย `juju-media-setup --check`
3. สำหรับ HTTP ให้ `cd` เข้าโปรเจกต์แล้วรัน `juju` เปิด **Private config URL อันใหม่** จาก terminal ปิดแท็บ config เก่าที่ถือ token ของ process เดิม
4. สำหรับ STDIO ให้ตั้ง command เป็น `juju` และ arguments เป็น `stdio`, `--root`, `/absolute/path/to/project` แล้ว reconnect แอป ไม่ใช้ bare `juju` เป็น subprocess
5. ให้ AI เรียก `project_overview` ใหม่ก่อนอ่านหรือแก้ไฟล์ เพราะ epoch เปลี่ยนทุกครั้งที่เริ่ม server หรือสลับ workspace

ไม่ต้องลบ state DB, signing keys หรือ OAuth clients เพื่ออัปเกรด การซ่อม scopes เก่าด้วย migration ยังคงอยู่ สิทธิ์แต่ละ path ยังต้องได้รับอนุญาตจากเจ้าของ หากมาจาก 0.1.x ให้ลงชื่อเข้าใช้ OAuth ใหม่หนึ่งครั้งเพื่อรับ identity grant รุ่น 2 ก่อนใช้สิทธิ์ข้ามโปรเจกต์ ดูรายละเอียดใน [การเปลี่ยนโปรเจกต์](#quickstart)

หากอัปเดตจาก 0.5.x ให้ลบคำแนะนำรายแชตที่เคยคัดลอกให้ AI แล้วโหลดรายการเครื่องมือใหม่ ไม่ต้องเรียก `usage_request` หรือส่ง `chat`/`usageId` อีก งาน Cron และสิทธิ์ Desktop ยังแยกอนุมัติตามเดิม ดู [สิ่งที่เปลี่ยนจากระบบยืนยันรายแชต](docs/CONFIRMATION.md)

หน้า **Client access** แสดงเฉพาะ client ที่มีสิทธิ์ในโฟลเดอร์ปัจจุบัน หากยังว่าง ให้เลือก **เพิ่ม client ให้โฟลเดอร์นี้** เพื่อใช้การเชื่อมต่อเดิม ส่วน **ล้าง client ที่ไม่ใช้** เป็นการลบทะเบียนและเพิกถอนการเชื่อมต่อที่เลือกในทุกโฟลเดอร์ ใช้เฉพาะเมื่อไม่ต้องการ client นั้นแล้ว การอัปเกรดเองไม่ลบ client

ถ้าหน้า config แจ้ง `Workspace changed or is switching` ให้โหลดหน้าใหม่ ตรวจชื่อและ path แล้วเลือกสิทธิ์อีกครั้ง ข้อความนี้ป้องกันการบันทึกจากแท็บที่ยังแสดงโปรเจกต์เก่า ไม่ควรกดส่งซ้ำโดยไม่ตรวจ path

ดูรายการเปลี่ยนแปลงและข้อจำกัดของรุ่นนี้ใน [Release notes](docs/RELEASE_NOTES.md)

การถอนการติดตั้ง CLI:

```bash
npm uninstall -g juju-mcp
```

คำสั่งนี้ไม่ได้ลบ state, grants, backups หรือ config ของ JUJU อัตโนมัติ อย่าลบฐานข้อมูลเพื่อแก้ login โดยไม่ตรวจสาเหตุและสำรองสิ่งจำเป็น

<a id="troubleshooting"></a>
## 9. แก้ปัญหาที่พบบ่อย

| อาการ | ตรวจหรือแก้ |
|---|---|
| `juju: command not found` | ติดตั้ง `juju-mcp`, ตรวจ PATH และ `command -v juju`; GUI อาจต้อง absolute path |
| ใช้ root ผิด/ถูกปฏิเสธ home directory | ตั้ง `--root` เป็นโฟลเดอร์โปรเจกต์จริง |
| `EADDRINUSE` | ถ้าเป็น JUJU ตัวเดิม ใช้ `juju kill` จากโฟลเดอร์ใดก็ได้แล้วเปิดใหม่; โปรแกรมอื่นต้องหยุดเอง JUJU ไม่เปลี่ยนพอร์ตเงียบ ๆ |
| HTTP locked/setup-required | ตั้ง public origin ด้วย `juju init --public-url ...` แล้ว Restart |
| URL เปิดได้แต่ MCP ไม่เชื่อม | Server URL ต้องลงท้าย `/mcp`; tunnel ต้องส่งทุก path |
| DCR/CIMD unavailable | เลือก static/user-defined OAuth client แล้วกรอก ID/Secret |
| `invalid_client` | ตรวจ Client ID, Secret และ `client_secret_basic`; public client ใช้ `none` |
| redirect URI mismatch | คัดลอก callback ปัจจุบันจาก client และลงทะเบียนให้ตรงทุกตัวอักษร |
| `request is consumed` | ID นั้นถูกใช้แล้ว อย่า approve ซ้ำ; ตรวจคำขอใหม่กับ phrase ใน browser |
| Request ID เปลี่ยนหลายครั้ง | ปิดหน้าเก่า เริ่มเชื่อมครั้งเดียว ตรวจคำขอที่ตรงกับ browser ไม่อนุมัติทุก ID |
| `Exec: local approval required` | ตั้ง trust ตามต้องการ หรือใช้ `juju pending` / `juju approve` |
| `OS sandbox: NOT enabled` | รัน `juju setup --components sandbox` และ `juju setup --check --components sandbox`; ถ้าตั้ง `commandSandbox=require` จะ fail-closed จน probe ผ่าน |
| `WORKSPACE_ACCESS_REQUIRED` | เปิด Client access ของพาธปัจจุบัน ไม่ต้องลบ OAuth client |
| Secret path ถูกปฏิเสธ | เป็น path policy ไม่ใช่ OAuth เสีย; อย่าเปิดสิทธิ์ทุกไฟล์เพื่อแก้ |
| คำสั่งไม่เห็น credentials ใน environment | JUJU ไม่ส่ง environment ทั้งหมดให้ child jobs; ตรวจ owner-controlled allowlist |

### อนุมัติแล้ววนกลับมาขอใหม่: บั๊ก `openid`

พบจากการเชื่อมจริงเมื่อ 9 กันยายน 2026: ChatGPT ส่ง `openid juju:read juju:write juju:exec` แต่ interaction adapter เดิมบันทึกเฉพาะ JUJU scopes ทำให้ provider กลับมาขอ consent ใหม่แม้ terminal แสดง `approved`

แพตช์ใน source เพิ่ม `openid` ที่ OIDC grant เฉพาะเมื่อ client ขอ โดยไม่เพิ่มสิทธิ์ workspace ทดสอบก่อนแก้พบ redirect ไป interaction ใหม่; หลังแก้ผ่าน code exchange และ authenticated MCP dispatch ดู [ADR-016](docs/adr/016-oidc-openid-consent.md)

หากใช้รุ่นที่มีแพตช์แล้ว ให้ Restart JUJU, ปิดหน้าอนุมัติเก่า และเชื่อมใหม่ โดยปกติไม่ต้องสร้าง Client ID/Secret ใหม่ หากยังล้มเหลวให้เก็บข้อความ error/HTTP status ที่ไม่รวม tokens หรือ secrets แทนการอนุมัติซ้ำไม่จบ

<a id="verification"></a>
## 10. ผลทดสอบและข้อจำกัด

รุ่นปัจจุบัน **0.8.2**: macOS arm64 / Node 22 ผ่าน full typecheck/lint/core/integration/security/compatibility + packaging gate โดยไม่มี failure (Windows-native cases ที่ skip บน macOS ไม่นับเป็น Windows pass) และมี native acceptance แยกบน Windows Server x64 / Node 24 กับ Debian arm64 / Node 22 สำหรับ `juju setup`, Desktop และ OS sandbox ดู [TEST_REPORT](docs/TEST_REPORT.md) และ [RELEASE_0.8.2](docs/RELEASE_0.8.2.md). ผลรุ่น 0.7.x ด้านล่างเป็นประวัติ

ประวัติ **0.6.3**: 293/293 tests ใน 37 ไฟล์ ผ่าน รวมคำสั่งอนุมัติ OAuth ที่มี ID ขึ้นต้นด้วย `-` และ `--`

ผลทดสอบรุ่น **0.6.2**: `npm run test:all` exit 0 — **289/289 tests ใน 36 ไฟล์** ผ่าน รวม typecheck/lint, Client access แยกตามโฟลเดอร์, การเพิ่ม/ถอนสิทธิ์/ลบทะเบียน client, HTTP/STDIO, ขอบเขตสิทธิ์เดิม และแพ็กเกจติดตั้งในโฟลเดอร์ภาษาไทย/มีช่องว่าง รายการรุ่นก่อนด้านล่างเป็นประวัติ ไม่ใช่วิธีใช้งานรุ่นนี้

- มี local fixtures สำหรับ HTTP/OAuth, MCP modern/legacy, STDIO, file safety, jobs, semantic analysis และ packaging ดู [TEST_REPORT](docs/TEST_REPORT.md)
- ประวัติรุ่น **0.5.3 (local)**: `npm run test:all` exit 0 — **325/325 tests ใน 37 ไฟล์** ผ่าน รวมผลรายการโฟลเดอร์ใน HTTP/STDIO CLI และแพ็กเกจติดตั้งใหม่
- ประวัติรุ่น **0.5.2 (local)**: `npm run test:all` exit 0 — **325/325 tests ใน 37 ไฟล์** ผ่าน เพิ่ม regression สำหรับ WEB URL ผ่าน CLI/เว็บ API/MCP/STDIO และแพ็กเกจติดตั้งใหม่
- ประวัติรุ่น **0.5.1 (local)**: `npm run test:all` exit 0 — **312/312 tests ใน 37 ไฟล์** ผ่าน รวม URL whitelist, CLI/เว็บ, reset, restart และแพ็กเกจติดตั้งใหม่; ยังไม่ได้ publish npm ในรอบนี้
- ประวัติรุ่น **0.5.0**: `npm run test:all` exit 0 — typecheck/lint และ **284/284 tests ใน 35 ไฟล์** ผ่าน รวม usage confirmation, scheduled jobs และ fresh tarball STDIO; การเชื่อมแชตจริงยังเป็น manual gate
- รุ่น **0.4.3**: `npm run test:all` exit 0 — typecheck/lint และ **272/272 tests ใน 33 ไฟล์** ผ่านเมื่อ 9 กันยายน 2026 รวมคำสั่ง 8 MiB, ไฟล์ 11 MiB ผ่าน STDIO, modern/legacy HTTP, safe editing/rollback, สิทธิ์ Desktop, `juju kill` และ OAuth หลัง restart
- ทดสอบหน้า config สองแท็บกับ fixture ในเครื่อง: หลังแท็บหนึ่งสลับโปรเจกต์ การบันทึกจากแท็บเก่าถูกปฏิเสธ ส่วนการทดสอบกับบัญชี ChatGPT/tunnel จริงยังเป็น `MANUAL_NOT_RUN`
- ผล SDK fixture ไม่เท่ากับยืนยันว่า ChatGPT/Codex ทุกเวอร์ชันหรือ tunnel จริงผ่านแล้ว การเชื่อม ChatGPT หลังแพตช์ยังต้องตรวจด้วยบัญชีและโดเมนจริง
- Windows x64 รองรับตาม 0.8.2 native acceptance; Linux coding/media/sandbox รองรับ และ Desktop จำกัดที่ X11/XWayland + XTEST/X-Resource/AT-SPI. Windows ARM64, macOS Intel และ pure Wayland-only ยังไม่มี native acceptance ในรอบนี้ ดู [COMPATIBILITY](docs/COMPATIBILITY.md)
- Directory guard ไม่ใช่ OS sandbox; process descendants ที่หลุด process group อาจไม่ถูกยกเลิกพร้อม job
- ไม่รับประกันการป้องกัน hostile process ที่มี UID เดียวกัน มีหน้าเว็บ config สำหรับเจ้าของในเครื่อง Desktop access ต้องอนุญาตแยก ส่วน autonomous LLM agent และ tunnel management ไม่รวมอยู่ใน JUJU

ขั้นตอนตรวจภายนอกและ expected results: [MANUAL_ACCEPTANCE](docs/MANUAL_ACCEPTANCE.md) อย่าส่ง access token, client secret, private key หรือ state DB ลง issue/แชต

<a id="release"></a>
## 11. สำหรับผู้พัฒนาและเจ้าของแพ็กเกจ

จาก source checkout ที่มี lockfile:

```bash
npm ci
npm run build
npm run test:all
npm pack
```

Scripts แยก: `typecheck`, `lint`, `test:unit`, `test:integration`, `test:security`, `test:compat`, `test:pack` ค่า dependencies ที่ติดตั้งจริงให้ยึด lockfile

### README จะขึ้นหน้า npm อย่างไร

npm ใช้ **README.md ที่ root ของแพ็กเกจ** เป็นคำอธิบายหน้า package คู่มือนี้จึงอยู่ใน tarball ด้วย แต่การแก้ไฟล์ในเครื่องอย่างเดียวยังไม่เปลี่ยนหน้าเว็บ npm

ก่อนเผยแพร่:

1. ตรวจ diff, changelog และผลทดสอบให้ตรงกับสิ่งที่ส่งจริง
2. ตรวจ registry ว่าเวอร์ชันใดเผยแพร่แล้ว เลือกเวอร์ชันใหม่ที่ยังไม่เคยใช้ และอัปเดต package.json/lockfile/release notes ให้ตรงกัน
3. Build และทดสอบ tarball ติดตั้งใน fixture ตรวจว่าไม่มี tokens, keys หรือ state DB
4. ตรวจรายการไฟล์ด้วย `npm pack --dry-run` และยืนยันว่า README รวมอยู่
5. เมื่อเจ้าของพร้อมเผยแพร่ ใช้บัญชีที่มีสิทธิ์ใน `juju-mcp` และรัน `npm publish --access public`

npm ไม่ให้ publish ทับเวอร์ชันที่เผยแพร่แล้ว หากพบ E403 ระบุว่าต้องใช้ 2FA หรือ granular token ที่มี bypass 2FA ให้ดำเนินการยืนยันผ่าน npm บนเครื่องเจ้าของตามนโยบายบัญชี ไม่ใส่ token/OTP ใน README หรือส่งในแชต และอย่าถือว่า `npm notice Publishing...` ยืนยันความสำเร็จ ต้องตรวจ exit code และ registry หลังจบ

การ build หรือแก้คู่มือไม่ใช่การ publish ต้องตรวจ version, dist-tag และ integrity จาก registry หลังคำสั่งเผยแพร่สำเร็จเสมอ

## เอกสารเพิ่มเติม

- [RELEASE_0.8.2](docs/RELEASE_0.8.2.md) — setup ข้าม OS, native Desktop/Speech/Sandbox และหลักฐาน release
- [RELEASE_0.7.0](docs/RELEASE_0.7.0.md) — ประวัติรุ่นที่เพิ่ม Assistance/Multimodal
- [ASSISTANCE](docs/ASSISTANCE.md) — เข้าใจงาน วิเคราะห์ผลกระทบ อ่าน/แก้ symbol และตรวจผล
- [MULTIMODAL](docs/MULTIMODAL.md) — ภาพ วิดีโอ เสียง เบราว์เซอร์ เกม และ workflow
- [ARCHITECTURE](docs/ARCHITECTURE.md) — โครงสร้างระบบ
- [RELEASE_NOTES](docs/RELEASE_NOTES.md) — สิ่งที่เปลี่ยนและวิธีอัปเกรด
- [SECURITY](docs/SECURITY.md) — ขอบเขตสิทธิ์และข้อจำกัด
- [AUTH](docs/AUTH.md) — OAuth และ owner consent
- [TUNNEL](docs/TUNNEL.md) — routing และการตรวจ connection
- [DESKTOP](docs/DESKTOP.md) — อ่านภาพ/OCR/Accessibility และควบคุมหน้าต่างแบบอนุญาตรายแอป
- [LARGE_INPUTS](docs/LARGE_INPUTS.md) — เพดานข้อมูล โปรไฟล์ large และวิธีให้ AI เขียนโค้ดยาว
- [LSP](docs/LSP.md) — language servers เพิ่มเติม
- [Schemas](schemas/tools.json) — wire contract ของ tools
- [ADRs](docs/adr/README.md) — เหตุผลการตัดสินใจออกแบบ

## License

[MIT License](LICENSE)

Copyright (c) 2026 **JuJu org, uminoe, and poundchan**.
