Ruby vs. Java vs. TypeScript: my experience on building a Cowork DOCX plugin
An author shares their journey building a Claude Cowork DOCX plugin, re-implementing it across Ruby, Java, and TypeScript to navigate different platform requirements and language quirks. The post offers a candid, firsthand account of the trade-offs in tooling, library maturity, and future-proofing across these popular development ecosystems. It resonates with developers facing similar language and framework selection dilemmas for complex document processing and plugin architectures.
The Lowdown
The author recounts their experience developing a DOCX plugin for Claude Cowork, an application that requires handling ZIP files containing XML. What began as a Ruby prototype evolved into Java for desktop compatibility, and then TypeScript for a smaller, more modern deployment target, all within a month. This iterative development provided a unique opportunity to compare the languages and their ecosystems directly.
- Ruby Prototype Challenges: The initial Ruby implementation faced significant hurdles due to its lack of static typing, leading to runtime errors that were difficult to debug. Additionally, core libraries like
rubyzipandnokogiripresented obscure bugs related to DOCX processing and XML formatting. - Java's Strengths: A subsequent Java implementation for a desktop application proved more robust. Java's built-in support for ZIP and XML processing was seamless, and its static typing was praised for simplifying development. The resulting binary was 88MB due to an embedded JDK, and AI assisted in porting thousands of lines of code in just three days.
- TypeScript for Future Potential: The team then moved to TypeScript, aiming for future support of MCPB (Micro-Containerized Plugin Bundle) which would allow for a much smaller application size (~1MB) by leveraging a Node runtime. While
fflateandxmldomworked adequately for ZIP and XML, a lack of XML pretty-printing was noted. AI again aided in a swift 1.5-day port from Java. - Bun for Single-Executable: As Cowork plugins didn't support MCPB at the time, Bun was adopted to create a single-executable binary with Node runtime. This resulted in binaries around 70-120MB, but presented issues with PostHog source map uploads.
- Claude vs. Codex Plugin Mechanisms: The author observed that Claude's plugin mechanism, particularly its
CLAUDE_PLUGIN_ROOTenvironment variable, offered more flexibility for executing binaries compared to Codex's less documented approach.
Ultimately, despite Java being deemed superior for its mature libraries and robust type system, TypeScript was chosen due to the strategic possibility of future MCPB support, which promises significantly smaller binary sizes. The author acknowledged Bun's relative newness compared to Java's long-standing maturity but noted its current functionality was satisfactory, aside from the source map hiccup.