BetterOffice

Agents

Search, inspect, and propose Office edits through the agents SDK and MCP server.

@betteroffice/agents gives agents a bounded document workflow: discover → grep → read → propose → render → verify → export. DOCX supports body text, headers, footers, and table cell stories. Initial XLSX and PPTX prototypes add cell input/formula and slide-text proposals; rendering and tracked changes remain DOCX-only.

MCP

bun add @betteroffice/agents
codex mcp add betteroffice -- /absolute/path/to/node_modules/.bin/betteroffice-mcp --root /absolute/path/to/documents

Start a new Codex session. Ask it to find a section, propose a precise edit, inspect the proposed page, and export a new file. The local server exposes literal search, bounded reads, reviewable edits, PNG page previews, and save/reopen checks. File paths are checked against the configured root and exports never overwrite existing files. Use --read-only to expose inspection tools only.

SDK

import { openDocx } from '@betteroffice/agents';
import { renderDocxPage } from '@betteroffice/agents/render';

const doc = await openDocx(bytes, { renderer: renderDocxPage });
try {
  const page = doc.grep({ query: 'Executive summary' });
  const paragraph = doc.read(page.matches[0].ref);
  const proposal = doc.propose({
    author: 'document-agent',
    edits: [{
      ref: paragraph.ref,
      revision: paragraph.revision,
      oldText: 'Executive summary',
      newText: 'Board summary',
    }],
  });
  const preview = await doc.render(1, proposal.id);
  const checks = await doc.verify(proposal.id);
  const revisedBytes = await doc.export(proposal.id);
} finally {
  doc.close();
}

Use attachDocx(session) with a directly owned YrsSession. The default React editor keeps its session in a worker; use its async ref methods, including readParagraphs and proposeChanges, for live editor integration. Proposals check target text and formatting before acceptance; unrelated edits survive. Acceptance is one undo step. Exporting a pending proposal leaves the live document unchanged.

Follow search nextCursor, outline nextOffset, and read nextStart values to retrieve more context. Paragraph refs belong to an open session. Text offsets use UTF-16. Edits replace text within one paragraph; embeds, structural changes, and existing tracked changes are outside this release's edit surface.

Save/reopen checks do not establish semantic or visual correctness. Inspect the rendered pages and their warnings before delivery.

The package guide contains the complete tool catalog, limits, host integration, and testing setup.

Spreadsheet and presentation prototypes

openXlsx(bytes) and openPptx(bytes) expose the same review, accept/reject, proposed export, and save/reopen workflow. Both own their sessions.

For XLSX, use office_outline to find sheet IDs, office_cells to read an A1 range, and office_propose_cells with {cell, input}. Inputs replace entire cells; prefix formulas with =. Search is case-sensitive over displayed values. For PPTX, use office_grep and office_propose with {match, newText} to replace one occurrence inside a slide paragraph.

Follow pagination, and narrow searches that report the 10,000-match cap. Any committed change invalidates outstanding XLSX/PPTX proposals. PNG rendering, tracked changes, and live-session attachment remain DOCX-only. Slide layout, notes, and media editing are outside the PPTX prototype. See the package guide for complete examples and formula calculation limits.

On this page