Content
<p align="center"><img src="./assets/brand/autohwp-banner.png" alt="AutoHWP — AI-powered HWP Editor" width="100%"></p>
# Tool List
**AI-powered HWP Editor.** `.hwp`/`.hwpx` files are opened, and the original document is rendered as is —
point or voice commands are recognized, and AI suggests edits, which are then confirmed on the screen.
The entire process is handled locally (WebAssembly · MCP · CLI) without server interaction.
[English](./README.en.md) · [Live Demo](https://kwakseongjae.github.io/auto-hwp/) ·
[Embedding Guide](./docs/EMBED-GUIDE.md) · [MCP](./docs/MCP-GUIDE.md) · [Contributing](./CONTRIBUTING.md)
## HWP is an "Invisible Document" to AI
Existing methods for providing HWP to LLM result in **text extraction**. Although extraction is possible,
the document splits into two worlds. **What AI reads** (plain text) and **what humans see** (formatted layout)
are expressed differently, making it difficult for AI to understand the document's structure.
In documents where **formatting is crucial**, such as official forms and applications, this gap is fatal.
## Structural Choices
The structure of AutoHWP is based on **engine ownership** — parsing → layout → rendering → editing → saving
are all handled on a single **IR (SemanticDoc)**:
```
.hwp / .hwpx ──▶ SemanticDoc(IR) ──▶ Layout (hwp-typeset) ──▶ SVG Pages (screen · hit-test)
│ ├▶ PDF (layout preservation, krilla)
│ └▶ Document Profile · Markdown (AI-readable)
└── Intent JSON ──▶ Op ──▶ IR Mutation (editing · undo/redo) ──▶ HWPX Saving
```
This structure enables three key features:
**① AI reads what is displayed on the screen.** Immediately after upload, the engine deterministically extracts
the **document profile** (title, table of contents, table inventory, and body summary) and attaches it to every request.
The profile's address `[s0/b3]` corresponds to the same IR coordinates on the screen, allowing precise editing.
**② AI's input is typed Intent.** The model can only output **Intent JSON** for 19 whitelist operations
(find and replace, character formatting, table and chart insertion, etc.), which are verified and applied to the document.
**③ Results are numerically verified.** Engine ownership allows for **precise verification** of editing results —
page count and line breaks are matched with **98.9%+ accuracy**, and unchanged content is **round-tripped** without modification.
## Packages (npm)
| Package | Layer | Role |
|---|---|---|
| **`@auto-hwp/engine`** | L1 | **headless engine (wasm)** — parsing, layout, SVG/HTML/PDF/HWPX, Intent editing, and undo. No UI. |
| `@auto-hwp/editor-core` | L2 | headless editor state (selection, editing, session) — minimal DOM, React-agnostic. |
| `@auto-hwp/ai-protocol` | L2′ | Vibes editing LLM protocol (prompt/context/validation) — no fetch, no keys. |
| `@auto-hwp/react` | L3 | **optional** layer: reference editor `<HwpWorkspace/>` + React bindings. |
```bash
npm i @auto-hwp/engine # use headless engine only
npm i @auto-hwp/react @auto-hwp/engine @auto-hwp/editor-core @auto-hwp/ai-protocol
```
## Quick Start ① — Headless Engine Only (Custom UI)
The engine returns SVG strings and byte arrays:
```js
import { initEngine, HwpDoc } from '@auto-hwp/engine';
await initEngine(); // instantiate wasm engine once
const bytes = new Uint8Array(await file.arrayBuffer());
const doc = HwpDoc.open(bytes, file.name); // auto-detect .hwp / .hwpx
// rendering — page-by-page SVG strings. customize rendering as needed.
for (let p = 0; p < doc.pageCount(); p++) {
container.insertAdjacentHTML('beforeend', doc.renderPageSvgSanitized(p));
}
// editing — Intent JSON (schema v0, docs/INTENT-SCHEMA.md)
doc.applyIntent({ intent: 'SetTableCell', section: 0, index: 1, row: 0, col: 0, text: 'value' });
doc.undo();
// exporting
const html = doc.exportHtml(); // semantic reflow HTML
const pdf = doc.exportPdf(); // layout-preserving PDF (Uint8Array)
const hwpx = doc.toHwpx(); // round-trip safe HWPX (Uint8Array)
doc.free();
```
## Quick Start ② — Reference Editor (React)
```tsx
import { HwpWorkspace, WasmAdapter } from '@auto-hwp/react';
import '@auto-hwp/react/styles.css';
<HwpWorkspace
adapter={adapter} // WasmAdapter (web) or custom adapter
document={{ bytes, name }}
enableEditing
onAiRequest={myLlmBridge} // optional: vibes editing — LLM on your server (BYOK)
/>
```
## AI Tools / Terminal Usage (Local, No Website)
- **MCP Server** — install on Claude Code/Desktop·Cursor: `cargo install --git https://github.com/kwakseongjae/auto-hwp hwp-mcp --features rhwp` → `claude mcp add auto-hwp -- hwp-mcp`.
Open/structure/context/editing/preview/approval/find&replace/undo/HWPX·PDF export (15 tools). Documents stay local.
- **Claude Code Skill** — `cp -r skills/hwp ~/.claude/skills/` and use "convert this hwp to pdf" in any session:
use CLI (`auto-hwp`) for conversion/extraction/preview/editing locally.
## Local Demo
```bash
git clone --recurse-submodules https://github.com/kwakseongjae/auto-hwp
cd auto-hwp
# build wasm engine (Rust + wasm-bindgen required — see CONTRIBUTING.md)
cargo build -p hwp-wasm --profile wasm-size --target wasm32-unknown-unknown
wasm-bindgen --target web --out-dir packages/engine/pkg target/wasm32-unknown-unknown/wasm-size/hwp_wasm.wasm
# demo app
cd apps/hwp-lab && npm install && npm run dev # http://localhost:3000
```
## AI-powered Editing
Click on a cell/paragraph/table to select it as an anchor — or **just speak**: the engine extracts the **document profile**
(title, structure, table of contents, table list, and body summary, with 0 LLM calls) and attaches it to every request.
The LLM outputs **Intent JSON** (19 whitelist operations), which are verified and applied to the document.
## Design Notes — What is the Authoritative Version?
The initial plan was "HWP → XML(structure) + CSS(styles) → LLM decides what to edit". However, we pivoted to
**format-agnostic IR(SemanticDoc) + typed Intent editing** ([`docs/PIVOT-DESIGN.md`](./docs/PIVOT-DESIGN.md)):
- rendering authority: **SemanticDoc → layout → SVG** (pixel-level matching with original HWP)
- editing authority: **Intent JSON → Op → IR mutation** (LLM output locked with schema — accurate undo)
## Accuracy
| Benchmark | Hancom Renderer | auto-hwp | Verdict |
|---|---|---|---|
| benchmark.hwp (government form, 8 pages) | 8 pages | 8 pages | ✅ match |
| benchmark1.hwp (application, 18 pages) | 18 pages | 18 pages | ✅ match |
| line break accuracy | — | 98.9%+ | gate |
## Known Limitations
- **PDF math formulas and charts**: rendered as placeholder boxes (warnings provided during export).
- **password-protected .hwp**: not supported.
- **.hwp (binary) resaving**: not supported; edited documents are saved as HWPX.
## Fonts (all OFL — redistributable and embeddable in PDFs)
Default fonts are Nanum Gothic/Nanum Myeongjo (automatically distinguished). Choose from 8 cataloged fonts
(Pretendard, Noto Sans/Serif KR, IBM Plex Sans KR, etc.) for screen and PDF rendering.
## Rust Crates (Engine Internals)
`hwp-model`(IR) · `hwp-hwpx`(HWPX codec) · `hwp-rhwp`(.hwp parsing bootstrap, [rhwp](https://github.com/kwakseongjae/rhwp) MIT) ·
`hwp-typeset`(layout: spacing, etc.) · `hwp-render`(PaintOp→SVG) · `hwp-export`(PDF/HTML) ·
`hwp-ops`(op-bus·undo) · `hwp-mcp`(Intent schema) · `hwp-session`(geometry) · `hwp-wasm`(bindings) ·
`hwp-crypto`(document decryption) · `auto-hwp-cli`(CLI)
## License
MIT OR Apache-2.0 ([LICENSE-MIT](./LICENSE-MIT) / [LICENSE-APACHE](./LICENSE-APACHE)).
Third-party notices: [NOTICE](./NOTICE) — includes rhwp(MIT), Nanum fonts(OFL), and Oracle's GPL isolation mechanism.