# Octofs 0.16: ระบบไฟล์ระดับ state of the art สำหรับ Claude Code และ Codex

> เราใช้ octofs เป็นระบบไฟล์และ shell เพียงตัวเดียวภายใต้ Claude Code และ Codex ตลอดสี่สัปดาห์ และแก้ทุกอย่างที่ขวางทาง แปดรีลีสต่อมา งานเดิมเสร็จเร็วขึ้น 2–2.5 เท่าโดยใช้โทเคนพอ ๆ เดิม รวมบันทึกประจำรีลีส 0.15 และ 0.16 พร้อม config ที่ใช้จริงสำหรับสลับเครื่องมือในตัวออกแล้วลองด้วยตัวเอง โอเพนซอร์สภายใต้ Apache-2.0

# Octofs 0.16: ระบบไฟล์ระดับ state of the art สำหรับ Claude Code และ Codex

การอ่านไฟล์ 400 บรรทัดใช้เวลาไม่กี่ไมโครวินาที แต่การตัดสินใจว่าจะอ่านมันอีกรอบใช้ turn ของโมเดลหนึ่ง turn และ turn ของโมเดลใช้เวลาเป็นวินาที ความไม่สมมาตรนี้คือเรื่องทั้งหมดของความเร็วเอเจนต์: ดิสก์ไม่เคยเป็นคอขวด คอขวดคือจำนวนครั้งที่โมเดลต้องหยุด มองดู และถามซ้ำก่อนจะลงมือได้

ตลอดสี่สัปดาห์ที่ผ่านมา เราใช้ [octofs](https://github.com/Muvon/octofs) เป็นระบบไฟล์และ shell เพียงตัวเดียวภายใต้ Claude Code และ Codex เราปิดเครื่องมือไฟล์และ shell ในตัว แล้วแก้ทุกอย่างที่ขวางทาง แปดรีลีสต่อมา ตั้งแต่ 0.15.0 ถึง 0.16.0 นี่คือสิ่งที่เราวัดได้: **งานเดิมเสร็จเร็วขึ้น 2–2.5 เท่า โดยใช้โทเคนพอ ๆ เดิม** โมเดลเดิม โทเคนพอ ๆ เดิม ใช้เวลาน้อยลง

เร็วกว่าเครื่องมือที่มากับไคลเอนต์ โดยไม่เสียโทเคนเพิ่ม นั่นคือเกณฑ์ที่เราตั้งไว้ก่อนจะเรียกระบบไฟล์ว่า state of the art และ 0.16 ผ่านเกณฑ์นั้น โพสต์นี้คือบันทึกประจำรีลีสของทั้งแปดรีลีส พร้อม config ที่ใช้จริงให้คุณลองเอง

---

## เวลาหายไปไหน

Octofs ไม่ได้ทำให้โมเดลคิดเร็วขึ้น มันตัด turn ที่โมเดลแค่กำลังยืนยันสิ่งที่รู้อยู่แล้วซ้ำอีกรอบออกไป แต่ละข้อต่อไปนี้อยู่ใน tool contract ที่โมเดลมองเห็น:

- **การแก้ไขส่งกลับเฉพาะสิ่งที่เปลี่ยน พร้อม id ใหม่** ทุกบรรทัดที่ octofs แสดงมี id: เลขบรรทัดบวก hash สั้น ๆ ของเนื้อหา แสดงเป็น `N:hh|content` ส่วน `batch_edit` และ `text_editor` ตอบกลับด้วย diff ที่แต่ละบรรทัดมี id ใหม่ การแก้ไขครั้งถัดไปจึงเล็งไปที่บรรทัดเหล่านั้นได้ทันทีโดยไม่ต้องอ่านซ้ำคั่นกลาง 0.15.0 เพิ่มบรรทัด `shift:` ไว้ท้ายสุดเพื่อบอกว่าเลขบรรทัดที่อยู่ใต้การแก้ไขแต่ละจุดเลื่อนไปเท่าไร id ที่โมเดลยังถือไว้จากการอ่านครั้งก่อนจึงใช้ต่อได้ด้วย
- **การอ่านซ้ำส่งกลับเฉพาะส่วนต่าง** ตั้งแต่ 0.15.0 การดูไฟล์ทั้งไฟล์ที่เซสชันเคยเห็นแล้วจะส่งกลับเฉพาะ hunk ที่เปลี่ยน หรือเครื่องหมาย "unchanged" บรรทัดเดียว การแก้ไขของ octofs เองช่วยรักษา cache นั้นให้เป็นปัจจุบันเสมอ การตรวจการแก้ไขของตัวเองซ้ำจึงมีต้นทุนแค่บรรทัดเดียว
- **เป้าหมายที่ผิดจะล้มเหลวพร้อมคำตอบแนบมา** line id ที่ล้าสมัยไม่ได้แค่ล้มเหลวเฉย ๆ แต่ error จะแนบเนื้อหาปัจจุบันและตำแหน่งที่เป้าหมายย้ายไป การลองใหม่จึงทำได้โดยไม่ต้องอ่านอีกรอบ เป็นแบบนี้มาตั้งแต่ [0.9.0](/blog/octofs-0-9-0-content-verified-line-ids)
- **คำสั่งที่รันนานไม่ยึด turn ไว้** คำสั่งที่ยังรันอยู่เมื่อครบสิบวินาทีจะกลายเป็น background job มันคือโพรเซสเดิม ไม่ถูกฆ่าหรือรีสตาร์ต และโมเดลได้ turn คืนมา ความสามารถนี้มาใน [0.13 และ 0.14](/blog/octofs-0-14-waiting-is-not-a-tool-call)
- **หนึ่ง response หลาย call** คำแนะนำของเซิร์ฟเวอร์บอกโมเดลตรง ๆ ว่าทุก response มีต้นทุนเป็น round trip หนึ่งรอบ จึงควรขอทุก call ที่ไม่ขึ้นต่อกันพร้อมกันในครั้งเดียว 0.16.0 ปรับถ้อยคำนี้ให้คมขึ้น

เรายังไม่ได้แยกตัวเลข 2–2.5x ตามกลไก จึงขอให้อ่านรายการนี้ในฐานะการออกแบบ ไม่ใช่การระบุว่าส่วนไหนช่วยได้เท่าไร ไม่มีไอเดียไหนในนี้ที่ใหม่ในรีลีสนี้ สิ่งที่สี่สัปดาห์ภายใต้ไคลเอนต์จริงเพิ่มเข้ามาคือการขัดเกลาที่ทำให้โมเดลอยู่บนเส้นทางที่เร็ว แทนที่จะปล่อยให้หลุดออกไป

---

## อะไรเปลี่ยนไปใน 0.15 และ 0.16

### Claude Code มองเห็นเครื่องมืออีกครั้ง

นี่คือการแก้ไขที่ควรรู้ ถ้าคุณเคยลอง octofs ใน Claude Code รุ่นล่าสุดแล้วไม่ได้อะไรเลย MCP revision วันที่ 2026-07-28 กำหนดให้ cache hint (`ttlMs` และ `cacheScope`) เป็นสิ่งบังคับในผลลัพธ์ของ list และ read ไคลเอนต์แบบเข้มงวดของ Claude Code สำหรับ revision นั้นปฏิเสธผลลัพธ์ที่ไม่มี hint เหล่านี้ จึง **ไม่โหลดเครื่องมือของ octofs เลยแม้แต่ตัวเดียว** 0.16.0 ส่ง hint เหล่านี้ทุกครั้งที่ไคลเอนต์ใช้ revision 2026-07-28 และปล่อยการเชื่อมต่อแบบเก่าไว้ตามเดิม

### Background job ที่อ่านได้ด้วย `view`

Background job ถูกเปิดให้เข้าถึงเป็นลิงก์ `octofs://jobs/<id>` โมเดลมักหยิบ `view` มาใช้กับลิงก์นั้นเป็นอย่างแรก และ Claude Code ซ่อนตัวอ่าน resource ทั่วไปของตัวเองไว้หลัง tool search ซึ่งเสีย round trip เพิ่มอีกรอบ ดังนั้น `view` บนลิงก์ของ job จะส่งกลับสถานะของ job และส่วนท้ายของเอาต์พุต **ตั้งแต่ 0.16.0 มันส่งกลับทันทีแทนที่จะรอให้ job จบ** นี่คือ breaking change เพียงรายการเดียวในรอบนี้ และเหตุผลคือ: โมเดลตรวจดู build ระหว่างที่กำลังรันแล้วทำงานต่อได้

นอกจากนี้ Claude Code ไม่แสดง notification มาตรฐาน `resources/updated` ให้โมเดลเห็น การจบของ job จึงไม่ปลุกเซสชัน โมเดลจะรับผลลัพธ์ด้วยการ view ลิงก์เมื่อต้องการ ซึ่งเป็นเหตุผลที่การอ่านนั้นต้องไม่บล็อกเด็ดขาด

การป้องกันอีกข้อใน 0.16.0: เมื่อคำสั่งที่เก็บการเปลี่ยนแปลงไว้ชั่วคราว (`git stash`) ย้ายไป background ตัว response จะเตือนโมเดลว่า working tree ยังไม่มีการเปลี่ยนแปลงเหล่านั้นจนกว่าคำสั่งจะจบ โมเดลจะได้ไม่แก้ไฟล์หรือประกาศว่างานเสร็จในระหว่างนั้น

### การแก้ไขที่ทิ้งไฟล์ไว้ตรงตามเดิมทุกประการ

- **line ending ยังอยู่ครบ** ไฟล์ CRLF ยังเป็น CRLF หลังการแทนที่และการแทรก (0.15.5)
- **บรรทัดว่างท้ายไฟล์ยังอยู่ครบ** และการแทรกค่าว่างหมายถึงบรรทัดว่างหนึ่งบรรทัด ไม่ใช่ไม่มีอะไรเลย (0.16.0)
- **operation ที่กำกวมจะถูกปฏิเสธ ไม่ใช่ถูกเดา** การแทรกภายในช่วงที่ batch เดียวกันกำลังแทนที่หรือลบ ตอนนี้จะล้มเหลวพร้อมคำอธิบาย (0.15.0, 0.15.2)
- **diff ยาว ๆ ยังอ่านรู้เรื่อง** ในผลลัพธ์ของการแก้ไข ช่วงกลางของการแทนที่แบบ exact ที่ยาว หรือบล็อกที่เพิ่มเข้ามาที่ยาว จะถูกยุบเป็นช่วงของ id (0.16.0)

### Shell ที่ทำให้โมเดลใช้เครื่องมือเฉพาะทาง

Octofs ปฏิเสธคำสั่ง shell ที่ทำงานซ้ำกับเครื่องมือเฉพาะทาง เช่น `cat`, `grep` หรือ `ls` เพราะเครื่องมือเฉพาะทางส่งกลับ line id แต่เอาต์พุตดิบของ shell ไม่มี รอบนี้ทำให้ด่านตรวจนั้นแม่นยำขึ้น:

- **การอ่านที่ถูกบล็อกจะถูกจับได้ไม่ว่าจะเป็นจุดเริ่มของคำสั่งตรงไหน**: รันเดี่ยว ๆ ต่อกันด้วย `&&` หรือ `;` อยู่ใน `$(…)` หรืออยู่หัว pipeline (0.16.0) ส่วน pipe stage ที่อยู่ถัดไปอย่าง `cargo test 2>&1 | tail -20` ยังใช้ได้
- **`sed` และ `awk` แบบอ่านอย่างเดียวใช้ได้แล้ว** (0.15.6) การสตรีมข้อความออกไปที่ stdout ไม่ใช่สิ่งที่เครื่องมือเฉพาะทางครอบคลุม ส่วน `sed -i` ที่แก้ไฟล์ในที่เดิมยังถูกปฏิเสธ พร้อมชี้ไปที่เครื่องมือแก้ไข
- **redirect ถูก parse แล้ว** (0.16.0) Octofs ปฏิเสธการเขียนเนื้อหาไฟล์ลงในโปรเจกต์ด้วย `echo`, `printf` หรือ `cat` เพราะ quoting ทำให้เนื้อหาเสียหาย ส่วนการ redirect เอาต์พุตของโปรแกรม เช่น `cargo test > out.log` ใช้ได้
- **การปฏิเสธทุกครั้งระบุชื่อโปรแกรมที่ถูกบล็อก** และบอกว่าไม่มีอะไรถูกรัน โมเดลจึงแยกคำสั่งผสมออกเป็นส่วน ๆ แทนที่จะลองใหม่ทั้งก้อน (0.15.6)

### รีโมตโฮสต์และโปรโตคอล

- `ssh://host` และ `ssh://host/~/dir` จะ resolve เทียบกับ home ของผู้ใช้ที่ล็อกอิน เหมือนที่ `ssh host` ทำ (0.15.0)
- แก้การค้นหาเนื้อหาบน tree รีโมตแล้ว และการ list รีโมตแบบไม่ระบุอะไรเพิ่มจะลงลึกแค่หนึ่งระดับเป็นค่าเริ่มต้น เพราะทุก subdirectory มีต้นทุนเป็น SFTP round trip หนึ่งรอบ (0.15.1) เลเยอร์ SFTP ย้ายไปใช้ `russh-sftp` 3.0 (0.16.0)
- tool schema ที่เผยแพร่ออกไปไม่มีสิ่งรกจากตัว generator อย่าง `$schema`, tag `format` ของจำนวนเต็ม และ `default: null` อีกต่อไป (0.16.0) นิยามของเครื่องมือถูกส่งไปกับทุก request จึงควรบอกเฉพาะสิ่งที่โมเดลใช้ลงมือ

---

## สลับมาใช้: Claude Code

**1. ติดตั้ง octofs** (Homebrew, Cargo หรือ npm):

```bash
brew install muvon/tap/octofs
# or: cargo install octofs
# or: npm install -g @muvon/octofs
```

**2. ลงทะเบียนให้ใช้กับทุกโปรเจกต์:**

```bash
claude mcp add --scope user octofs -- octofs mcp
```

Claude Code เริ่มเซิร์ฟเวอร์ในไดเรกทอรีที่คุณเปิด `claude` และไดเรกทอรีนั้นจะกลายเป็น project root ของ octofs

**3. ปิด editor ในตัว** ใน `~/.claude/settings.json`:

```json
{
	"permissions": {
		"allow": ["mcp__octofs"],
		"deny": ["Edit", "Write", "NotebookEdit"]
	}
}
```

นี่คือการตั้งค่าเบื้องหลังตัวเลขของเรา ชื่อเครื่องมือเปล่า ๆ ใน `deny` จะเอาเครื่องมือนั้นออกจาก context ของโมเดลทั้งหมด และ `mcp__octofs` อนุญาตทุกเครื่องมือของ octofs โดยไม่ต้องถามยืนยัน ส่วน `Bash` และ `Read` ยังคงอยู่: ในการรันของเรา โมเดลส่งการอ่าน การแก้ไข และคำสั่งผ่าน octofs อยู่ดี และ `Read` คือวิธีที่ Claude Code ใช้ดูรูปภาพและ PDF การ deny `Bash` ด้วยจะได้ผลตรงข้าม เพราะมันดึงเครื่องมือ `Glob` และ `Grep` แบบแยกตัวของ Claude Code กลับเข้ามาในชุดเครื่องมือของโมเดล

## สลับมาใช้: Codex

**1. เพิ่ม octofs และปิด shell ในตัว** ใน `~/.codex/config.toml`:

```toml
[features]
shell_tool = false
unified_exec = false

[mcp_servers.octofs]
command = "octofs"
args = ["mcp"]
default_tools_approval_mode = "approve"
```

วางบล็อกนี้ตามที่เป็น และอย่ารัน `codex mcp add octofs` ควบคู่ไปด้วย เพราะมันจะเขียนตาราง `[mcp_servers.octofs]` เดียวกัน และ Codex จะไม่ยอมเริ่มทำงานถ้ามีตารางที่ถูกนิยามซ้ำสองครั้ง `shell_tool` และ `unified_exec` คือตัวรันคำสั่งสองตัวของ Codex เมื่อปิดทั้งคู่ ทุกคำสั่งจะผ่าน `shell` ของ octofs รวมถึงการเลื่อนไป background ด้วย และ `default_tools_approval_mode` ทำให้เครื่องมือของ octofs รันได้โดยไม่ต้องขออนุมัติ

**2. ชี้การแก้ไขไปที่ octofs** Codex ไม่มีสวิตช์ปิด editor `apply_patch` ในตัว ([openai/codex#8161](https://github.com/openai/codex/issues/8161) ถูกปิดโดยระบุว่า not planned) ดังนั้นให้บอกโมเดลไว้ใน `AGENTS.md`:

```markdown
## Tools

- Use octofs for all file and shell work: `view` to read, list and search; `batch_edit` or `text_editor` to edit; `shell` for builds, tests and git. Never use apply_patch.
- Put every call that doesn't depend on another call's result in one response.
- A command still running after ~10s becomes a background job. Don't wait for it: take the next step, and `view` its `octofs://jobs/<id>` link when you need the result.
```

บล็อกเดียวกันนี้ใช้ใน `CLAUDE.md` ได้ด้วย แม้ว่าในการรันของเรา Claude Code จะเลือกใช้ octofs เองโดยไม่ต้องมีบล็อกนี้

---

## ลองดูเอง

วิธีที่เร็วที่สุดในการตรวจตัวเลขของเราคือรันงานที่คุณเคยทำไปแล้วซ้ำอีกรอบ เลือกงานล่าสุดสักงาน เช่น การแก้บั๊กหรือการ refactor ที่แตะไฟล์ไม่กี่ไฟล์ รันหนึ่งครั้งด้วยเครื่องมือในตัว และอีกหนึ่งครั้งด้วย octofs ใช้โมเดลเดิมและ prompt เดิม แล้วเทียบเวลาจริงตามนาฬิกาและจำนวนโทเคน คาดได้ว่าโทเคนจะออกมาใกล้เคียงกัน ความต่างจะเห็นที่เวลา

ใช้ octofs อยู่แล้ว? อัปเกรดด้วย `brew upgrade muvon/tap/octofs`, `cargo install octofs` หรือ `npm install -g @muvon/octofs` หรือดาวน์โหลดไบนารีสำเร็จรูปสำหรับ Linux, macOS หรือ Windows (x86_64 และ ARM64) จาก[หน้ารีลีส](https://github.com/Muvon/octofs/releases) มีข้อสังเกตด้านพฤติกรรมหนึ่งข้อ: `view` บนลิงก์ของ background job จะไม่บล็อกรอจนกว่า job จะจบอีกต่อไป ถ้ามีอะไรที่คุณสร้างไว้ซึ่งพึ่งพฤติกรรมนั้น ให้อ่านลิงก์อีกครั้งเมื่อ job จบแล้ว

---

Octofs เป็นโอเพนซอร์ส (Apache 2.0) ที่ [github.com/Muvon/octofs](https://github.com/Muvon/octofs) บทความ [แนะนำ Octofs](/blog/introducing-octofs) เล่าว่าทำไมเราสร้างเซิร์ฟเวอร์ระบบไฟล์ของเราเอง [0.9.0](/blog/octofs-0-9-0-content-verified-line-ids) เล่าว่าทำไมเชื่อเลขบรรทัดไม่ได้ และ [0.14](/blog/octofs-0-14-waiting-is-not-a-tool-call) เล่าว่าทำไม tool call ที่ถูกบล็อกก็เชื่อไม่ได้เหมือนกัน โพสต์นี้คือผลตอบแทนของทั้งสามเรื่อง: เอเจนต์ที่เลิกตรวจซ้ำในสิ่งที่รู้อยู่แล้ว จะทำงานเดิมเสร็จเร็วขึ้นสองถึงสองเท่าครึ่ง
