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

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

ตลอดสี่สัปดาห์ที่ผ่านมา เราใช้ 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
  • คำสั่งที่รันนานไม่ยึด turn ไว้ คำสั่งที่ยังรันอยู่เมื่อครบสิบวินาทีจะกลายเป็น background job มันคือโพรเซสเดิม ไม่ถูกฆ่าหรือรีสตาร์ต และโมเดลได้ turn คืนมา ความสามารถนี้มาใน 0.13 และ 0.14
  • หนึ่ง 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):

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

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

claude mcp add --scope user octofs -- octofs mcp

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

3. ปิด editor ในตัว ใน ~/.claude/settings.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:

[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 ถูกปิดโดยระบุว่า not planned) ดังนั้นให้บอกโมเดลไว้ใน AGENTS.md:

## 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) จากหน้ารีลีส มีข้อสังเกตด้านพฤติกรรมหนึ่งข้อ: view บนลิงก์ของ background job จะไม่บล็อกรอจนกว่า job จะจบอีกต่อไป ถ้ามีอะไรที่คุณสร้างไว้ซึ่งพึ่งพฤติกรรมนั้น ให้อ่านลิงก์อีกครั้งเมื่อ job จบแล้ว


Octofs เป็นโอเพนซอร์ส (Apache 2.0) ที่ github.com/Muvon/octofs บทความ แนะนำ Octofs เล่าว่าทำไมเราสร้างเซิร์ฟเวอร์ระบบไฟล์ของเราเอง 0.9.0 เล่าว่าทำไมเชื่อเลขบรรทัดไม่ได้ และ 0.14 เล่าว่าทำไม tool call ที่ถูกบล็อกก็เชื่อไม่ได้เหมือนกัน โพสต์นี้คือผลตอบแทนของทั้งสามเรื่อง: เอเจนต์ที่เลิกตรวจซ้ำในสิ่งที่รู้อยู่แล้ว จะทำงานเดิมเสร็จเร็วขึ้นสองถึงสองเท่าครึ่ง