Skip to content

Latest commit

 

History

1,940 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Docxy

CI codecov OpenSSF Scorecard crates.io License: MIT

A fast terminal (TUI) viewer and editor for Microsoft Word .docx and Markdown — right where you live, in the terminal.

Docxy opens real .docx files — text, tables, lists, styles, even images — renders them faithfully in a character grid, and lets you edit and save them losslessly. It reads and writes Markdown too, converts between the two, and exports to PDF. No Office, no browser, no network: it's a single static binary on top of a small, dependency-free OOXML engine.

docxy editing a Word document in the terminal

Docxy deliberately doesn't reproduce Word's pixel-perfect layout — it renders a faithful, readable view of the document in a character grid, with a familiar ribbon, mouse support, and an optional Vim mode.

Why docxy?

  • Stay in the terminal. Read and edit Word documents over SSH, in tmux, or from your editor's shell — no GUI required.
  • Lossless by design. Anything docxy doesn't model (bookmarks, fields, content controls, section properties) is preserved byte-for-faithful on save.
  • Zero-dependency core. The docxcore crate is pure std — its own ZIP/DEFLATE, XML parser, renderer, and PDF writer — so it's auditable and trivially embeddable.
  • One file does it all. .docx ⇄ .md conversion and .docx → .pdf export are built in, scriptable, and headless.

Quick start

cargo install docxy          # or grab a prebuilt binary (see Install)

docxy report.docx            # open a Word document
docxy notes.md               # open / edit Markdown
docxy                        # launch the welcome screen (new file or open)

Want to see it immediately? Generate the showcase document and open it:

cargo run -p docxcore --example gen_sample   # writes assets/sample.docx
docxy assets/sample.docx

Features

Documents & editing

  • View & edit paragraphs and runs (bold / italic / underline / strike / color / highlight / sub- & superscript) and tables, including merged cells — navigate and type directly into cells.
  • Styles resolved from styles.xml; lists numbered from numbering.xml; headings, indents, alignment, tab stops, and horizontal rules.
  • Bidirectional DOCX layout in the terminal editor for Hebrew, Arabic, and mixed LTR/RTL text: paragraph w:bidi, run w:rtl, style-inherited direction, and Unicode bidi controls render in visual order while editing, copy/export, and save offsets remain logical.
  • Lossless save — unmodeled parts are preserved exactly.
  • Find & replace, full clipboard (syncs with the OS clipboard), selection + formatting, word navigation, and show-invisibles.
  • Headers & footers, multi-section page layout, and print/page view.
  • Tracked-change review for insertions, deletions, and run/paragraph/table/ row/cell/section property changes. Review previous/next, accept or reject the current change, or confirm accept/reject all; each action is undoable and survives save/reload. Unsupported move/custom records stay lossless.
  • DOCX protection honored across TUI and automation edits: read-only, comments-only, and formatting-only restrictions are enforced; unsupported forms-only and tracked-changes-only editing fails closed. Recommendation-only write protection remains editable with a warning; password-backed write protection fails closed as read-only until password verification is supported.
  • Watermark previews in page view: applied text watermarks render as non-interactive overlays, while picture or unsupported watermarks show a preview-unavailable label. Overlay text never enters copy/export output or saved OOXML.

Markdown

  • Open and edit .md files directly; Save As to a .md or .docx name converts between the two.
  • View ▸ Markdown toggles a .md file between the rendered document and its raw source.
  • Headings, bold/italic/strike, inline code, fenced code blocks, blockquotes, links, bullet/ordered lists, thematic rules, and pipe tables all map across — and round-trip through .docx via real Word styles.
  • Scientific formulas: $…$ inline and $$…$$ display math (LaTeX) convert to and from native Word equations (OMML) — fractions, roots, \sum/\int with limits, Greek, scripts, \left…\right, and named functions.
  • Mermaid diagrams: a ```mermaid block becomes a native Word drawing (DrawingML shapes + connectors, laid out automatically); the Mermaid source is embedded so Word → Markdown restores the exact block. Flowcharts are laid out fully; other diagram types are best-effort.

Images

  • Raster (PNG / JPEG / GIF / BMP / TIFF) rendered as real pixels via kitty / iTerm2 / Sixel graphics.
  • Legacy WMF/EMF vector images rasterized through the OS (Windows).
  • Floating, frame-anchored images projected to their real page positions.

Niceties

  • Welcome screen on launch with no file: create a .docx/.md or open one — keyboard- and mouse-driven.
  • Mouse everywhere: click to move, click a link to open, wheel/drag to scroll/select, and a fully clickable ribbon and File menu.
  • Safe clickable links — only http(s), shown for confirmation, opened without a shell.
  • Vim mode (--vim): motions, operators, visual mode, / search, :w/:q.
  • PDF export, including headless.

Usage

docxy <file.docx|.md>           # open a Word or Markdown file
docxy                           # welcome screen (new .docx/.md, or open)
docxy <file> --vim              # open with Vim keybindings

# Headless conversion / export (no UI):
docxy in.docx  --pdf  out.pdf   # export to PDF
docxy in.docx  --md   out.md    # convert Word → Markdown
docxy in.md    --docx out.docx  # convert Markdown → Word
docxy in.docx  --html in.docx.html  # editable HTML (see below)

Editable HTML

docxy sample.docx --html sample.docx.html writes one self-contained HTML file that opens offline in any browser as a docxy editor, with the desktop suite's title bar, ribbon, Backstage and page view, in light or dark. It holds the original .docx untouched, plus the docxwasm engine and the page. A Content-Security-Policy of default-src 'none' means the page makes no network requests at all.

  • In the browser, Save writes the page back with your edits. Chromium saves in place; other browsers download sample.docx.html. Download sample.docx under File › Save As gives the Word file.
  • In docxy (terminal or desktop suite), sample.docx.html opens like a .docx. Save keeps it editable HTML, and Save As .docx writes plain Word. docxy sample.docx.html --docx out.docx returns the embedded Word file byte for byte when nobody edited it.
  • If sample.docx next to the page has changed since the export, docxy says so. It never overwrites that file.

Making new pages embeds the engine, which the html-export feature compiles in. Release binaries have it. From source, run cargo build -p docxy --features html-export, which needs rustup target add wasm32-unknown-unknown. Opening and re-saving an existing page works in any build. Tables, headers and footers, and comments are edited in docxy for now: the browser shows those ribbon commands dimmed.

Keys

Keys Action
type · Enter · Backspace · Delete edit text
arrows · Home/End · PgUp/PgDn move (Ctrl-←/→ by word)
Shift + move select (Esc clears)
Ctrl-B / Ctrl-I / Ctrl-U bold / italic / underline (over selection)
Ctrl-L / Ctrl-E / Ctrl-R align left / center / right
Ctrl-A · Ctrl-C · Ctrl-X · Ctrl-V select all · copy · cut · paste
Ctrl-F find / replace (Tab toggles replace, Ctrl-A replaces all)
Ctrl-S · Ctrl-Z · Ctrl-Y save · undo · redo
Ctrl-Q / Esc quit
F2 · F3 · F4 page view · show marks · table borders
F6 · F7 edit header · edit footer (Esc returns)
F8 · F9 insert landscape · portrait section at cursor
Alt-Shift-←/→ previous / next tracked change
Alt-Shift-A/R accept / reject current tracked change
mouse click to move · click a link to open · wheel/drag to scroll/select

Xlsxy — spreadsheets too

The workspace now ships a sibling app: xlsxy, a terminal editor for Microsoft Excel .xlsx workbooks built on gridcore, a dependency-free SpreadsheetML engine with a real recalculation engine — a dependency graph over your formulas, ~170 Excel functions, Excel-faithful semantics (error values, coercions, the 1900 leap-year quirk), whole-column references, defined names, structured table references, 3D sheet spans, INDIRECT/OFFSET, XLOOKUP and the *IFS family, the full number-format runtime, dynamic arrays (FILTER/SORT/UNIQUE/ SEQUENCE spill into neighboring cells, A1# spill references, @, LET, #SPILL! blocking and recovery), LAMBDA (custom functions via defined names, MAP/REDUCE/SCAN/BYROW/BYCOL/MAKEARRAY, elementwise lifting like ABS(A1:A3)), pivot-table refresh and editing (a columnar group-by/aggregate engine recomputes pivots from current data — F9 in the TUI, automatic under --recalc; Ctrl-P edits a pivot's fields — or creates a new pivot from the selected data range), a data model (gridcore::model: multiple tables with relationships, Excel-formula measures plus DAX-style row-context iterators like SUMX(Sales,[@Qty]*[@Price]), filter context through star schemas, CSV sources — xlsxy data.csv imports directly; Ctrl-M manages the model in the TUI and materializes reports, with definitions persisted in the file), and the same lossless round-trip guarantee: anything it doesn't model (pivots, conditional formatting…) is preserved byte-for-byte. The one deliberate exception is a chart you edit — repoint its range, switch which way round it reads that range (Excel's Switch Row/Column), rename or reorder its series, recolour it, in the desktop suite's Chart panel — which is regenerated from the model, and a drawing you move or delete, whose anchor is rewritten in place. Only column, bar, line and pie charts can be regenerated; a scatter, a doughnut or anything stacked or combined is kept verbatim and can't be repointed. Charts and drawings you leave alone still round-trip verbatim. Inserting a chart from a selection writes a live chart: each series is bound to its own cells, so Excel updates it when the data changes. Formulas it can't evaluate yet keep Excel's cached results and are saved untouched.

xlsxy book.xlsx                   # open a workbook (grid, formula bar, tabs)
xlsxy in.xlsx --recalc out.xlsx   # headless: recalculate everything, save
xlsxy in.xlsx --csv out.csv       # headless: export the first sheet as CSV
xlsxy corpus/xlsx/*.xlsx --verify # conformance scoreboard: recalc + diff
                                  # against cached values (461/461 = 100%
                                  # on the LibreOffice-oracle corpus)

Type to replace, F2 to edit, = starts a formula; copy/paste and fill-down translate relative references like Excel; insert/delete rows and columns rewrites every affected formula workbook-wide — and every chart reference with them; find, Save As, and sheet add/rename/delete round out the basics; range selections show Sum/Average/Count in the status bar. Try it: cargo run -p gridcore --example gen_sample_xlsx && xlsxy assets/sample.xlsx. The design and roadmap (conformance scoreboard, dynamic arrays, pivot engine) live in SPREADSHEET.md.

Yppxy — project schedules too

Completing the trilogy (doc→docx, xls→xlsx, mpp→yppx), the workspace ships yppxy, a terminal editor for project schedules built on projcore, a dependency-free scheduling engine. It reads Microsoft Project's open MSPDI XML (what Project produces via Save As → XML), schedules it with a real Critical Path Method engine — forward/backward passes over working-time calendars, computing early/late start & finish, total/free slack, and the critical path — and saves to a native .yppx package (an OPC ZIP container, the project analog of .docx/.xlsx). The TUI is a task outline beside a live terminal Gantt chart that reschedules on every edit; critical tasks show in amber, summaries roll up over their children, milestones as diamonds. Dependencies (FS/SS/FF/SF with lag/lead) and hard constraints (SNET/FNET/MSO/MFO…) are modeled; a schedule exports to a Markdown/Mermaid Gantt block that renders anywhere docxy's diagrams do.

yppxy plan.xml                    # open MSPDI XML (or a .yppx package)
yppxy plan.yppx --gantt-md out.md # headless: export a Markdown Gantt chart
yppxy plan.xml  --save out.yppx   # headless: convert to the native package

Like docxy and xlsxy, yppxy has the same ribbon — with Microsoft Project's tabs, groups and command names (File · Task · Resource · Report · Project · View, e.g. Project › Schedule › Set Baseline; F9 to engage) — the same File backstage (Alt-F: New / Open / Info / Save / Save As / Export / Exit with a folder browser and live preview), a start screen, a light/dark theme toggle (the ◐ Theme button at the right of the tab strip, or T), and mouse support. Try it: yppxy corpus/mspdi/10-summary.xml.

Keys

Keys Action
↑ ↓ · j / k · g / G move the selection (top / bottom)
← → · h / l scroll the Gantt timeline
n · Insert add a task below (1 day? unless the plan's NewTasksEstimated is off; inserted into a finish-to-start chain, it is linked in when the plan's Autolink is on, the default)
N insert a blank row above (typing into it makes a task)
x · Delete delete the task (a summary asks first, then takes its subtasks)
Tab · Shift-Tab indent / outdent (auto-forms summary tasks)
Enter · F2 rename the task
d set duration (3d / 4h / 2w)
p add a predecessor by task ID
c set a date constraint (SNET 2026-03-05, MSO …, none)
a assign a resource to the task (created on first use; Name[25%] sets units, Cement[5 tons] a material quantity; empty clears)
b set the baseline (planned-vs-current variance in the header)
L toggle resource leveling (delay bars to fit resource capacity)
m switch the task between Manually Scheduled (📌, pinned at its current dates) and Auto Scheduled
M switch the plan's mode for new tasks (the status line's New Tasks: …; click it too)
T toggle the light / dark theme
Ctrl-F · F3 find task by name · repeat
Ctrl-Z · Ctrl-Y undo · redo
F9 · Alt-F engage the ribbon · open the File menu
Ctrl-S · Ctrl-E save · export a Markdown Gantt
Ctrl-Q · q quit (q warns on unsaved changes)
mouse click a tab/button, click a task row, wheel to scroll/pan

Launch with --vim for a modal mode (:w/:q/:wq/:q!, u undo, / search). The light/dark theme persists between sessions.

A separate crate, mppread, reads the OLE2 Compound File container of legacy binary .mpp files. It decodes OLE property-set metadata and validates the counted task tables in supported MPP9 and current Project files before importing task names, dates, outline levels, and predecessor links. Unsupported layouts return an import error. Nonzero link lag remains unvalidated against a real-file oracle.

The design, the CPM engine, resource leveling, and the format landscape are written up in PROJECT.md.

Lookxy — Outlook/Exchange mail too

The workspace also ships lookxy, a terminal client for Outlook / Exchange Online mail built on mailcore, a headless engine over Microsoft Graph: OAuth2 authorization-code + PKCE sign-in (a system-browser round trip via a loopback redirect — no password ever touches lookxy itself), a SQLite local store with FTS5 full-text search, and a background sync thread that keeps folders and messages current (per-folder delta sync, an outbox of pending mutations with retry/back-off, and automatic token refresh) — all fully testable against an in-process fake Graph server, no network or secrets required. The TUI is a three-pane Outlook-like layout — folders | message list | reading pane — with triage keys (mark read/unread, flag, delete, move), attachment save/open, and full-text search, all optimistic-local-write-then-sync so the UI never blocks on the network.

lookxy   # sign in once (opens your browser), then read and triage mail

client_id/backfill_days/refresh_secs are configurable via %APPDATA%\lookxy\config.json or LOOKXY_* environment variables. Sign-in, keybindings, storage locations, configuration, and the security/privacy model (DPAPI-encrypted token cache, plaintext local mail store like Outlook's own OST) are written up in LOOKXY.md.

Offxy in VS Code — the same engines, in an editor tab

Because docxcore and gridcore are pure std with no third-party crates, they compile straight to WebAssembly — so both engines (parse → render → edit → lossless save) run inside a VS Code editor tab. The offxy-vscode extension opens a .docx or .xlsx on the same faithful character-grid rendering the terminal apps use, at the editor's own font and size and honoring your color theme — no ribbon, just the keyboard and command palette, like editing code. Each format is a binary custom editor (offxy.docxEditor / offxy.gridEditor) with native dirty state, undo/redo, Save/Save As, and hot-exit backups, and because it edits the real OOXML model (not HTML or an intermediate form), it keeps the document/workbook's structure intact on save — the lossless round-trip that the crowded field of HTML-based .docx/.xlsx extensions lacks. The Excel editor adds a virtualized grid, formula bar, and full gridcore recalculation on edit.

The engines are two small .wasm builds — docxwasm and gridwasm, each a hand-written C-ABI bridge, no wasm-bindgen. The architecture — the wasm ABIs, the host ↔ webview split, and how VS Code's edit events stay in lockstep with each engine's own undo stack — is written up in VSCODE.md.

Bidi note: terminal docxy injects Unicode bidi projection for DOCX lines. The wasm-backed Offxy editors currently use docxcore's identity render path, so Hebrew, Arabic, and mixed-direction DOCX text remains logical-order there until a wasm projector is added.

Offxy in JetBrains IDEs — native, no webview

The offxy-jetbrains plugin brings the Word and Excel editors to IntelliJ-platform IDEs (2024.2+) with no webview at all: the same docxwasm.wasm/gridwasm.wasm artifacts run on the JVM via Chicory (a pure-Java wasm runtime — no native code, no per-platform builds). A .docx renders in a real IntelliJ editor over a live, editable Document — typing is native-editor fast on any document size, the engine follows and reconciles asynchronously, structure is guarded, platform find/undo/save just work. An .xlsx opens in a virtualized native grid over gridwasm's windowed viewport protocol — formulas with live recalculation, formatting, structural edits, sheets, TSV clipboard, one-transaction-one-undo. Every open tab advertises on the same agent control surface the terminal apps use, so Claude Code and Junie can read and edit it live. See offxy-jetbrains/README.md.

Bidi note: the JetBrains plugin uses the same wasm DOCX bridge as Offxy for VS Code, so DOCX bidi projection is not yet applied in IDE editor tabs.

Install

cargo install docxy   # the document editor
cargo install xlsxy   # the spreadsheet editor
cargo install yppxy   # the project scheduler
cargo install lookxy  # the mail client

Or grab prebuilt binaries (Linux / Windows / macOS) from the latest release — both apps ship with every release, each checksummed, cosign-signed, and carrying a build-provenance attestation.

Image support

Real image pixels need a graphics-capable terminal:

  • WezTerm (kitty + Sixel + iTerm2) — best.
  • Windows Terminal ≥ 1.22 (Sixel).
  • Most other terminals fall back to a labeled placeholder box.

WMF/EMF vector images are rasterized via the OS GDI on Windows; on other platforms they show as boxes.

Building from source

git clone https://github.com/yeroo/docxy
cd docxy
cargo build --release
cargo test

The workspace has twenty-one crates; these are the ones a reader of this README will meet (CONTRIBUTING.md lists the rest):

  • opccore — pure, std-only OPC container plumbing (ZIP read/write, DEFLATE, XML pull parser) shared by every engine.
  • docxcore — the WordprocessingML engine (document model, rendering, and the from-scratch PDF writer). No third-party dependencies. Embedders constructing docxcore::render::RenderOptions directly should set bidi: None for identity visual order or provide an Rc<dyn BidiProjector> when the host supplies Unicode bidi projection.
  • gridcore — the SpreadsheetML engine (workbook model, formula parser/evaluator, dependency-graph recalculation, lossless xlsx I/O).
  • projcore — the project-scheduling engine (task/calendar model, MSPDI read/write, Critical Path Method scheduler, Markdown/Mermaid Gantt export, native .yppx OPC package). std-only, on top of opccore.
  • mppread — std-only reader for the OLE2 Compound File container of legacy binary .mpp/.doc/.xls files (MS-CFB).
  • htmlbundle — std-only packer for editable HTML (*.docx.html): wraps a package, the wasm engine and the web UI (htmlbundle/web/) into one file and unwraps it again. Browser tests live in webapp/ (npm ci && npm test, Playwright).
  • docxy — the document TUI (ratatui), Unicode bidi projection (unicode-bidi), clipboard (arboard), and image rendering (ratatui-image).
  • xlsxy — the spreadsheet TUI (ratatui + arboard).
  • yppxy — the project-scheduler TUI with a live terminal Gantt chart (ratatui).
  • mailcore — the headless mail engine: OAuth2 auth-code+PKCE, a Microsoft Graph REST client, SQLite storage with FTS5 full-text search, and a background sync thread (no UI dependency; ureq/rustls for HTTP, bundled rusqlite for storage, DPAPI on Windows for the token cache).
  • lookxy — the mail TUI (ratatui) over mailcore: folder tree, message list, reading pane, and triage keys.

Examples

cargo run -p docxcore --example gen_sample [out.docx]   # build the showcase doc
cargo run -p docxcore --example dump_doc -- assets/sample.docx   # inspect a .docx
cargo run -p gridcore --example gen_sample_xlsx   # build the showcase workbook
cargo run -p projcore --example gantt_md -- corpus/mspdi/10-summary.xml  # Gantt → Markdown
cargo run -p projcore --example convert  -- in.xml out.yppx   # MSPDI ⇄ .yppx
cargo run -p mppread  --example streams  -- some.mpp   # list a .mpp's streams
cargo run -p mppread  --example tasknames -- some.mpp  # decode a .mpp's tasks + dates

License

MIT © yeroo

About

TUI Office Suite

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages