Agent skill

GenOffice Document CLI

by genspark-ai in genspark-ai/genoffice

Creates, converts, reads and edits real pptx, xlsx, docx and PDF files locally through the genoffice command line.

Apache-2.0Auto-check passedDocuments & Office

Install GenOffice Document CLI

skills CLI
$ npx skills add genspark-ai/genoffice --skill genoffice -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install genspark-ai/genoffice genoffice --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/genspark-ai/genoffice.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/genoffice .claude/skills/genoffice && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
genoffice
GitHub stars
9.2k
Token cost
~19k tokens
SKILL.md length
5,459 words
Files
1
Skills in repo
1
Repo updated
First seen
Licence
Apache-2.0

At a glance

Creates, converts, reads and edits real pptx, xlsx, docx and PDF files locally through the genoffice command line.

  • Works in 4 steps: genoffice info or genoffice read --json… → genoffice guide for the op fields (guide… → genoffice apply --dry-run when the batch… → …
  • Building a slide deck from a written brief as a real .pptx file
  • SKILL.md covers Commands, Which command, Behaviour to know and Workflow, plus 9 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

The skill drives the genoffice CLI that ships with GenOffice. It can build a presentation from a brief through a checked outline, per-page spec and render pipeline, a spreadsheet from CSV or JSON data with formulas, a Word document from Markdown or HTML, or a PDF. It also converts between pdf, docx, xlsx, pptx, md, html and csv, reads the structure and text of an existing file, including your own documents used as source material, and applies structured edits to it.

The agent first runs genoffice --version, and if the command is not found it reads the launcher directory that GenOffice records in ~/.genoffice/launcher, with default install locations listed for macOS, Windows and Linux. Commands run headless on the app's own engines, so documents are processed locally. Only the search, image and media commands send a query or file to the provider configured in GenOffice. The result can also be opened in the GenOffice editor.

When a program reads the output, the agent adds --json, which gives one JSON object with a status of ok, partial or error plus a summary, output path and warnings. Exit codes separate usage errors or rejected operations, missing files or an output that already exists, conversion failures and the app being unavailable. Errors carry a machine-readable code and a suggestion, so message text is never parsed.

When your agent uses it

  • Building a slide deck from a written brief as a real .pptx file
  • Generating a spreadsheet with formulas from CSV or JSON data
  • Converting a Word document to PDF, or Markdown to Word
  • Applying structured edits to part of an existing docx, xlsx or pptx

Example prompts

  • “Build a ten-slide pptx on our roadmap from the brief in brief.md.”
  • “Turn sales.csv into an xlsx workbook with a totals formula for each region.”
  • “Convert report.docx to PDF and open the result in GenOffice.”
  • “Read the structure of proposal.pptx and rewrite the text on the pricing slide.”

Requirements

  • GenOffice installed, which provides the genoffice CLI
  • A provider configured in GenOffice, for the search, image and media commands

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. genoffice info or genoffice read --json to learn the structure: block indexes (docx), s_ / e_* ids and EMU geometry (pptx), sheet names…
  2. genoffice guide for the op fields (guide --json for one op's schema), then write the ops JSON yourself.
  3. genoffice apply --dry-run when the batch is large; a rejected op comes back as op_rejected with the executor's usage line — fix that op…
  4. The QA gate below, then report the output path.

What it can do on your machine

Read from SKILL.md and the folder at commit c8e9467. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are json).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

GenOffice Document CLI loads about 19k tokens when it runs. Until then it costs about 229 tokens; SKILL.md has 5,459 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~229
When it runs · the whole SKILL.md, loaded when a task matches
~19k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from genspark-ai/genoffice at commit c8e9467, republished under its Apache-2.0 licence (© genspark-ai). 5,459 words, ~19,474 tokens.

Download SKILL.mdSave it as .claude/skills/genoffice/SKILL.md (or your agent's skills folder).
name
genoffice
description
Create, convert, read and edit Office documents locally with GenOffice's command line. Build a new presentation (pptx) from a brief through a checked outline, per-page spec and render pipeline, a new spreadsheet (xlsx) from CSV or JSON data with formulas, a new Word document (docx) from Markdown or HTML, or a PDF; convert between pdf, docx, xlsx, pptx, md, html and csv; read the structure and text of an existing file (including the user's own docx / xlsx / pptx as source material) and apply structured edits to it. Use whenever the user asks for a slide deck, presentation, spreadsheet, workbook, report, Word document or any real Office file, a format conversion, a rewrite of part of an existing document, or wants the result opened in the GenOffice editor. Documents are processed locally; only search, image and media send the query or the referenced file to the provider configured in GenOffice.
metadata.version
2.67.1
metadata.cli
>=0.9.0

genoffice — GenOffice from the terminal

genoffice is installed with GenOffice. Run genoffice --version first. If the command is not found, GenOffice writes the launcher directory to ~/.genoffice/launcher (Windows: %USERPROFILE%\.genoffice\launcher) on every start: read that one line and run "<dir>/genoffice" from bash or "<dir>\genoffice.cmd" from PowerShell / cmd, quoted, in place of genoffice below. Default locations when that file is missing: macOS /Applications/GenOffice.app/Contents/Resources/cli, Windows %LOCALAPPDATA%\Programs\GenOffice\resources\cli, Linux /opt/GenOffice/resources/cli. Every command runs headless on the app's own engines; only search, image and media send data off the machine, to the provider configured in GenOffice.

Always add --json when a program reads the output: one JSON object on stdout, { "status": "ok" | "partial", "command", "summary", "output_path"?, "warnings"?, "detail"? } (partial: an apply with --best-effort / --stop-on-error wrote the file but lost ops) or { "status": "error", "code", "error", "message", "suggestion"?, "detail"? }. Exit codes: 0 ok, 1 usage or rejected ops, 2 file not found / output exists / file open in GenOffice, 3 conversion failed, 4 app not available. error is the machine-readable reason (table under "When a command fails"), suggestion the next step in one sentence, including did you mean "…"? when a command, option, op name, element id or sheet name is one typo away. detail carries facts as fields (failures[] with index, op, error, reason, valid_range, available, supported, usage; sheets, options, commands); never parse message.

Commands

CommandWhat it does
genoffice info <file> [--password <pw>]Metadata and structure summary (docx blocks and headings, pptx slides, xlsx sheets, pdf pages)
genoffice convert <file> --to <fmt> [--out <path>] [--force]pdf→docx/pptx/xlsx, csv→xlsx, xls/xlsb/ods→xlsx, md→docx/html, docx→html/md, html→docx, xlsx→csv (--sheet), and docx/xlsx/pptx/md/html→pdf
genoffice create --type pptx --ops <file> --out <path>New deck from a list of slide ops
genoffice create --type pptx --spec <dir|file> [--outline <file>] --out <path> [--render [dir]] [--audit]New deck from page spec files (one per slide, name order) or one deck spec file: px-positioned text, shapes and images (the designed-deck path, see below)
genoffice create --type xlsx --from <data.csv | table.json> [--header] [--decimal ,] --out <path>New workbook from CSV or a 2-D array / {sheets:[{name,rows}]}; "=..." cells are formulas; --header freezes row 1 and filters the range
genoffice create --type docx --from <text.md | fragment.html> --out <path>New Word document from Markdown or a restricted-HTML fragment
genoffice create --type pdf --from <document> --out <path>PDF printed by the GenOffice renderer from any md/html/docx/xlsx/pptx file
genoffice slides read <pptx> [--slide n] [--full | --max-chars n] [--layouts] [--units in|cm|pt|px] / genoffice slides apply <pptx> --ops <file> [--dry-run]Inspect ids, geometry (box and size in EMU, or converted with unit named when --units is given) and text previews (clipped to 300 characters, ending in …(+n chars) with truncated: true; --max-chars moves the cap, --full: whole text, every table row, speaker notes), then edit with ops Text elements carry effective (first run's font size/family/color/bold/italic and paragraph align) with src naming where each value comes from: run, paragraph defRPr, shape lstStyle, layout placeholder, master placeholder, master titleStyle/bodyStyle, presentation defaultTextStyle, theme major/minor; setFont writes the run level and overrides all of them, applyTheme changes the theme fonts and colors. Elements with a hyperlink carry link (url, slide jump or a PowerPoint action: nextslide / previousslide / firstslide / lastslide / lastslideviewed / endshow); setLink and setText run link fields write the same three kinds.
genoffice slides audit <pptx> [--slide n] / genoffice slides render <pptx> --out <dir> [--scale 2]Geometry audit (out_of_bounds, off_slide, text_overflow, text_overflow_width, overlap, picture_distorted = box aspect off the cropped source by >5%): issues[] with a code, level, path (s_n/e_*) and, except for overlap, a suggest setTransform op you can pass to slides apply as is; one PNG per slide to look at
genoffice render <file> --out <dir> [--page n] [--scale 2] [--el e_12 [--pad px]] [--grid [--cols 4] [--tile 320]]One PNG per page of a docx, xlsx, pptx, md, html or pdf file, laid out by the GenOffice renderer: look at it before reporting a document or workbook as done; --el (pptx) also writes the page cropped to one element (<stem>-NN-e_12.png, ids from slides read) so a small box is legible; --grid also writes every page onto one contact sheet (<stem>-grid.png, row-major, tile positions in grid.tiles) to see a whole deck at once
genoffice slides check <outline.json|page.json> / genoffice slides replace <pptx> --slide n --spec <page.json>Validate a deck outline (exit 1 on errors) or build-and-audit one page file and check it against its outline entry and style.md; rebuild one slide from its page file, other slides untouched
genoffice sheet read <xlsx> [--sheet name] [--range A1:D20] [--cols A,C:E] [--max-rows n] [--where formula|error|empty|number|text] [--stats] [--formats] / genoffice sheet apply <xlsx> --ops <file> | --cells <file> / genoffice sheet check <xlsx>Read a range plus features (panes, filter, charts, tables, rule counts for the sheet; merges and links in the range; --formats adds cell formats, widths, heights); keep the output small with --cols (only those columns, named in columns), --max-rows (rowsShown / rowsTotal and a note with the --range to continue), --where (only cells of one kind as {ref, value, formula}, no grid) or --stats (counts, used range and the sheet list, no cells); edit with the workbook DSL or by cell address; check lists formula errors, references to missing sheets, broken defined names, chart ranges off the data, ### columns (with a set_col_width suggestion), placeholder text and existing rules
genoffice docs read <docx> [--range a-b] [--html] [--full | --max-chars n] [--comments] [--revisions] [--header-footer] [--sections] [--fields] [--notes] / genoffice docs apply <docx> --ops <file> [--dry-run] / genoffice docs check <docx>Read blocks by index (previews are clipped to 200 characters and end in …(+n chars) with truncated: true; --max-chars moves the cap, --full lifts it; plus comment threads, tracked changes, header/footer text, page setup per section, fields with their cached results, footnotes/endnotes), then edit with ops (incl. applyStyle, insertField for SEQ / REF / DATE / PAGE… fields, insertBookmark, updateFields), restricted HTML, insert_image / insert_picture (sized, floating) / insert_text_box, insert_chart / edit_chart, set_header_footer, set_watermark (text, or a washed-out picture via image), define_style, set_page_setup / insert_section_break, add_comment / reply_comment / resolve_comment / delete_comment, accept_changes / reject_changes (selector: all, ids from --revisions, author, type, blockIndex, blockRange, before; apply --track [--author name] records the batch's own edits as tracked changes), insert_footnote / insert_endnote / edit_note / delete_note; --styles lists style ids; check lists fields without results (a fresh TOC), references to missing bookmarks, a TOC that no longer matches the headings, missing images, empty charts or headings, level skips, placeholder text, pending tracked changes and open comments
genoffice merge <template.docx|pptx|xlsx> --data <values.json | inline JSON> --out <path> [--force] [--strict]Fill {{key}} placeholders in a Word, PowerPoint or Excel template from a JSON object (nested objects flatten to dotted keys a.b; whitespace inside the braces is tolerated) through the engines' own find/replace (Word, PowerPoint: text, tables, speaker notes) and typed set_cell writes (Excel: a whole-cell placeholder takes the value's type, a number stays a number; substituted text stays text even when it starts with =). detail.used_keys, detail.unused_keys and detail.unresolved_placeholders[] ({placeholder, key, reason: no_key | split_placeholder | unreachable_nested, location} — block index / slide + element id / sheet + cell) tell what happened; unresolved placeholders stay in place with a unresolved_placeholder warning unless --strict makes them an error. split_placeholder = Word split the {{…}} over runs with different formatting; retype it in the template in one run (PowerPoint fills a placeholder that spans runs). unreachable_nested = inside a nested pptx group (or a table in a group), which deck findReplace does not reach; ungroup it. A Word table nothing fills is left untouched
genoffice pdf read <pdf> [--page n | --range a-b] [--password <pw>] [--full | --max-chars n]Text layer of a PDF page by page: 1-based page, width_pt / height_pt, text clipped to 4000 characters ending in …(+n chars) with truncated: true (--max-chars moves the cap, --full lifts it and reads every page), plus page count, encrypted and title / author / producer metadata; without --page / --range the first 20 pages come back and detail.truncated names the rest; scanned pages have empty text (convert --to docx runs OCR)
genoffice guide <slides|docs|sheets> [group|op|design|spec] [--json] [--index] [--fingerprint]The op reference for each domain, generated from the same definitions apply validates against (read this before writing ops); one group or one op with its JSON schema on request; slides design / slides spec for building a deck
genoffice search <query> [--images] [--max n]Web / image search via the provider configured in GenOffice; detail.results[] {title,url,snippet}
genoffice image <prompt> [--out f.png] [--aspect 16:9] [--ref a.png,b.png] [--model <name>]Generate an image with the configured provider and save it; detail.mime, output_path
genoffice media <file|url> [--ask <question>]Describe / question an image, video or audio file; answer in summary and detail.text
genoffice capabilitiesWhich cloud features are configured in GenOffice (search, image search, image generation, media analysis) and whether the app is installed; no network call
genoffice open <file> [--slide n [--el e_12] | --block n | --range [Sheet!]B2:D5 | --page n]Open the file in the GenOffice app (only when the user asks to see it there); with a target, also scroll to and select that slide element / block / range / page so the user is looking at the same spot you are (target_not_found / out_of_range come back with the valid ids or range)
genoffice selection <file> --jsonWhat the user has selected in the editor showing the file: {slide, elements[], types[]}, {blocks:[a,b], text, collapsed}, {sheet, range, values?} or {page, text?} — resolve "this one" / "here" from it before editing; file_not_open_in_gui when no tab shows the file
genoffice skill list / genoffice skill install <agent|all> [--dir <path>] [--force] / genoffice skill pathCoding agents found on this machine (Claude Code, Codex, Cursor, Gemini CLI, Copilot, OpenCode, Windsurf) with the skill version each has; copy or update this skill into their skills directory, or print the bundled SKILL.md; nothing is installed without this command or a click in Settings → Integrations

--ops - and --cells - read stdin. --out defaults to the input file's folder with the new extension (convert) or edits in place (apply). Unknown options are rejected (exit 1). The mcp server runs on stdio by default; mcp [--http <port> [--host <addr>] [--token <secret>]] serves Streamable HTTP instead; genoffice mcp install <agent|all> [--dir <path>] [--force] registers the stdio server in a coding agent's MCP config (mcp uninstall <agent> removes it, mcp list shows each agent).

genoffice mcp as an MCP client sees it:

  • Tools mirror the commands one-to-one (info, convert, create_docx / create_xlsx / create_pptx / create_pdf, docs_read / docs_apply / docs_check, sheet_read / sheet_apply / sheet_check, slides_read / slides_apply / slides_audit / slides_render / slides_check / slides_replace, render, guide, capabilities, search, image, media, open, selection); ops, cells, specs and Markdown go inline, results are the --json envelope (a partial batch is not isError, its first text block lists the lost ops), open and selection exist on stdio only.
  • deck_start / deck_page / deck_build / deck_replace are the staged deck flow above with the deck folder as state; a short deck with concrete content is one create_pptx call.
  • The op references are resources: genoffice://guide/docs, …/sheets, …/slides, …/slides/design, …/slides/spec.
  • ops, cells and data carry the per-op schema of guide <domain> --json (one variant per op: op, fields, required); mcp --compact-schemas (or GENOFFICE_MCP_COMPACT_SCHEMAS=1) advertises plain arrays for clients with a small context budget.
  • --http: files travel with the calls (PUT /files/<name> uploads one and returns a URL, every path parameter also takes an http(s) URL, out omitted returns the file as a download URL).
  • The GenOffice app runs its own MCP server on 127.0.0.1:3093 (Settings → Integrations) whose tools (create_session, read_document, apply_ops, apply_slide_ops, apply_sheet_ops, read_pdf, open_documents) edit the documents already open in the visible editor; genoffice mcp works on files on disk.

Which command

TaskCommand pathNot for
A presentation from a brief, however shortguide slides design → style.md + outline.json → slides check per page → create --type pptx --spec → render --grid → slides auditediting a deck that exists (slides apply); a fixture deck (create --type pptx --ops)
Change text, a picture or one slide of an existing deckslides read → slides apply --ops → slides audit → render --pagerestyling the whole deck (applyTheme op, or rebuild through the staged path)
A workbook from datacreate --type xlsx --from data.csv | table.json → sheet apply --ops for formats/charts → sheet checkone cell fix in an existing file (sheet apply --cells)
Edit cells, formats, charts, rules of an existing workbooksheet read → guide sheets <op> → sheet apply --ops → sheet checkrefresh_pivot, session tables and shapes (refused: needs the editor)
A Word document from textcreate --type docx --from report.md | fragment.html → docs check → rendera real web page (convert page.html --to docx)
Edit an existing Word documentdocs read → docs apply --ops → docs checkreading its text (convert --to md or docs read --full)
Read the user's file as source materialconvert --to md/csv or <domain> read --full --jsonunzip/cat on the Office file; render (pixels, not text)
Change the file formatconvert <file> --to <fmt>any content change (edit first, convert after)
See what a page looks likerender (--page, --el, --grid)extracting text or ids (read)
Point the user at a spot, or act on what they selectedopen <file> --slide/--el/--block/--range/--page → selection <file> --jsonreading content (read); files the user has not opened (selection needs the tab)
Look up op fieldsguide <domain> [group|op] [--json]guessing from this file: the guide is generated from the validator and is always current
Give another agent (or a fresh machine) this skillskill list → skill install <agent> (or skill path and copy the file)writing the skill by hand; install-cli (that puts genoffice on the PATH)

Behaviour to know

  • Word (docs): block indexes inside one batch are live — after insert_content adds two blocks, later indexes shift by two. A target that matches no block fails the whole batch (exit 1). findReplace does not reach table cells (use replace_blocks on the table). Tags outside the restricted set are stripped silently. convert docx→md writes GFM: & < > become entities, formulas become $…$, images are dropped and counted in detail.skipped. create --from x.md embeds local images referenced by relative path. insert_image takes a local path (relative to the current directory, then to the ops file), a data: URL or an http(s) URL (png/jpg/gif) and appends unless afterBlockIndex is given; edit_chart targets blocks docs read lists with kind chart; set_header_footer writes plain text with {PAGE} / {NUMPAGES} tokens, view: "first" switches the different-first-page setting on; comment ids come from docs read --comments; add_comment anchors a new thread to a block or to an exact text span inside it (occurrence picks one of several matches) without touching the document text; delete_comment on a thread root with replies needs withReplies: true; revision ids (r1, r2, …) come from docs read --revisions and are positional, so read again after any edit before accept_changes / reject_changes. insertField computes SEQ numbers, REF text, DATE and MERGEFIELD locally; PAGE / NUMPAGES / AUTHOR-style results are placeholders Word recomputes on open (docs check reports them as info), so say so when you hand over the file. Note ids for edit_note / delete_note come from docs read --notes; edit_note is findReplace inside one note ({ id, find, replace, matchCase? }, kind only when a footnote and an endnote share the id) and keeps the note's id, reference mark and formatting — findReplace itself never reaches note text. define_style patches only the fields given (an existing style keeps the rest); applyStyle takes a paragraph style id from docs read --styles and turns blocks into headings when the style is a heading style; set_watermark with text: null removes the watermark; insert_picture / insert_text_box lengths take 2.54cm / 1in / 72pt / 96px or points. set_page_setup changes paper / orientation / margins / columns / titlePg / page numbering of every section or of one (section: N or blockIndex), lengths as "2.54cm" / "1in" / "72pt"; insert_section_break splits a section after a block (the copy is then changed with set_page_setup section: N); docs read --sections lists sections with their block ranges. Native tables take structure ops: insertTableRow / deleteTableRow / insertTableColumn / deleteTableColumn (0-based, position: "before"|"after", count), mergeTableCells / splitTableCell (grid range / cell; a merge that cuts an existing merged cell is refused), setTableCellFormat (fill, vAlign, borders, width in twips or "2.5cm"), setTableStyle (a style id from docs read's tableStyles, plus look flags); target them with nodeType: "table" and docs read shows each table's rows, cols and merged cells.
  • Excel (sheet): ops run in order, each seeing the previous result: after insert_rows/delete_cols the following ops address the shifted grid (a formula written after the shift is stored as given, one written before it is shifted like the existing ones), a sheet added or renamed earlier in the batch is addressed by its new name; rules, links, notes, filters and visuals must come after any row/column op on their sheet, and defined-name ops cannot share a batch with sheet or row/column ops. set_cell with a string starting with = writes a formula; type: "text" keeps it literal text. Beyond cells, sheet apply --ops writes charts (add_chart, edit_chart on xl/charts/chartN.xml), images and shapes, Excel tables, freeze panes, hidden rows/columns, filters with checked values, conditional formats, data validation, hyperlinks, notes, page setup, sheet protection, defined names and tab order/visibility (genoffice guide sheets has every field). --cells style takes the same object as format_range.format ({bold, fillColor, numberFormat, …}). Colors are #RRGGBB or theme slots that follow the workbook theme: "accent1", "accent1+40%" (lighter), "dk2-25%" (darker) or {theme, tint}; fill: {pattern: "lightGray", fg, bg?} or fill: {gradient: {angle, stops: [{position, color}]}} writes pattern and gradient fills, and --formats echoes them back with the slot, tint and resolved rgb. sheet read returns raw values (0.25, serial dates) and formulas separately, features (sheet-wide panes, filter, charts, tables and rule counts; merges and links of the range), and with --formats the styled cells, column widths (px) and row heights (pt); convert --to csv returns the displayed text (percent, dates), UTF-8 with BOM, CRLF line ends, active sheet unless --sheet. create --from x.csv: a sep=; first line is honoured, ISO dates (2024-01-01, 2024-01-02 09:30) become real dates with a date format, --decimal , reads 1.234,5 as 1234.5. Formulas using functions the local engine cannot evaluate (FILTER, SORT, UNIQUE, LET, …) are written without a cached value and Excel computes them on open; spill formulas are stored as dynamic arrays so they spill in Excel 365; the formulas_not_cached warning names those cells.
  • PowerPoint (slides): picture ops (addPicture, replacePicture, addMedia, setImageFill, setBackground) take a local path or data URL in bytes; the extension is inferred. setText runs inherit the element's first run style unless a field is set explicitly (bold: false). Ops in one apply batch run in order, so a later op may target a slide an earlier op added; atomic still writes nothing unless every op applied; --best-effort (formerly --isolation per_op) and --stop-on-error write what applied and answer status: "partial". Created elements get new e_* ids: run slides read again before targeting them. convert pptx→pdf is rendered like the app's export: one bitmap per slide, no text layer. Every EMU length field (box, offset, dx/dy, wEmu/hEmu, colWidthsEmu, insets) also takes a string with a unit suffix: "2.54cm", "1in", "10mm", "12pt", "96px". slides read lists each page's animations[] (seq, el, effect, kind, trigger, durationMs, delayMs, direction); addAnimation / removeAnimation / reorderAnimation edit one timeline item (presetXml passes a PowerPoint-exported effect through verbatim), insertEquation adds a typeset formula from LaTeX (PowerPoint renders it, previews show the linear text).
  • Conversions in the app (→pdf, docx→html, html→docx, create --type pdf, render): a hidden GenOffice process per call, 1–6 s, up to 180 s timeout, safe to run concurrently. html→docx is html2docx for real web pages; a restricted-HTML fragment with <formula> goes through create --type docx --from fragment.html instead.
  • Cloud (search, image, media): --images returns detail.images[] {title,imageUrl,sourceUrl,source,width,height}; providers may return fewer than --max. image saves with the provider's real format (output_path tells you; a .png request may come back .jpg, noted in detail.note); --aspect / --size are validated locally.
Show full SKILL.md (2,257 more words)Show less

Workflow

  1. genoffice info or genoffice <domain> read --json to learn the structure: block indexes (docx), s_<n> / e_* ids and EMU geometry (pptx), sheet names and cell values (xlsx).
  2. genoffice guide <domain> for the op fields (guide <domain> <op> --json for one op's schema), then write the ops JSON yourself.
  3. genoffice <domain> apply --dry-run when the batch is large; a rejected op comes back as op_rejected with the executor's usage line — fix that op and resend the whole batch. Atomic by default: on rejection the file is untouched and detail.batch is {total, applied: 0, failed, skipped}. --best-effort applies every op that can apply, --stop-on-error applies in order up to the first rejection; both write the file and answer status: "partial" (exit 0) with the lost ops in detail.failures and the counts in detail.batch — a program must check status, not only the exit code.
  4. The QA gate below, then report the output path.

Pitfalls

PitfallRule
slides read/audit/render/replace --slide n and op targets { "slide": n } are 0-based; render --page n is 1-based; docx block indexes are 0-baseds_0 is page 1 of the PNGs.
--ops -, --cells - and --spec - read stdin (--from does not); any other value must be an existing fileA path that does not exist is file_not_found, not an empty batch.
Structural edits renumber: new e_* ids after addElement, s_* after adding slides, docx block indexes after insert_content/delete_blocksInside one batch indexes are live (later ops see earlier results); before the next batch run read again.
EMU fields (offset, box, dx/dy, wEmu/hEmu, colWidthsEmu, insets) take integers or unit strings "2.54cm", "1in", "10mm", "12pt", "96px"Do not multiply by 914400 yourself; slides read returns EMU integers.
CSV import: a sep=; first line is honoured and removed, ISO dates become real dates, --decimal , for 1.234,5--header freezes row 1 and adds a filter; without it the first row is data.
Formulas the local engine cannot evaluate (FILTER, SORT, UNIQUE, LET, LAMBDA …) are written without a cached valueformulas_not_cached warning lists them; sheet read shows the formula and no value until Excel opens the file. Not an error.
sheet apply addresses sheets by the current tab name in the file, spelled as in the tabsheet_not_found carries detail.sheets and a did you mean.
Structural sheet ops (insert/delete rows, columns, sheets) shift the addresses of the ops after them in the same batch; defined-name ops do not mix with sheet or row/column opsWrite later ops in post-shift coordinates (or put the structural op last); rules, links, notes, filters and visuals go after the row/column op of their sheet.
GenOffice has the file open in a tab → apply refuses (exit 2, file_open_in_gui)Ask the user to close the tab, or --out other.ext; --force only if the user accepts the editor may overwrite it.
create/convert/image never overwrite (exit 2, output_exists); apply --out onto an existing file also refusesPick another name, or --force when the user asked for replacement.
apply --best-effort / --stop-on-error (formerly slides apply --isolation per_op) answer status: "partial" with exit 0; check/audit exit 0 with problems inside detailRead status, detail.batch, detail.failures / detail.issues; exit 0 is not "clean".
Deck specs are px on a 1280×720 canvas; ops are EMUNever mix the two in one file.
convert pptx→pdf has no text layer; convert docx→md drops images (detail.skipped)Use docs read --full when you need every word.
docs findReplace skips table cells; unknown HTML tags in insert_content are stripped silentlyreplace_blocks on the table block; stay inside the restricted HTML set (guide docs).

When a command fails

Branch on error, do what suggestion says, then resend the whole batch (atomic apply wrote nothing). detail has the facts as fields, never parse message.

errorNext command
unknown_command, unknown_optionUse suggestion's did you mean; detail.commands / detail.options list the valid ones; genoffice <command> --help when this skill is older than the app
missing_argument, invalid_argumentFix the flag named in message; genoffice <command> --help shows the flags
invalid_jsonRe-serialize the ops file; check quoting when piping through --ops -
unknown_opdetail.failures[].supported and did_you_mean; genoffice guide <domain> for the list
op_rejecteddetail.failures[].usage is the executor's usage line; genoffice guide <domain> <op> --json for the schema; fix that one op
unresolved_placeholdermerge --strict: detail.unresolved_placeholders[] names each placeholder and where it is; add the keys to --data (or fix a split_placeholder in the template) and rerun
target_not_founddetail.failures[].available lists the ids on that slide / the matching blocks; otherwise genoffice <domain> read <file> --json and retarget
out_of_rangedetail.failures[].valid_range (or detail.valid_range); read shows the current count
sheet_not_founddetail.sheets has the tab names as in the file; use one verbatim
file_not_foundCheck the path (relative to the current directory); for --ops, - means stdin
output_existsAnother --out, or --force if the user asked to replace
file_open_in_guiAsk the user to close the tab, or write with --out; --force only with consent
file_not_open_in_guiselection/open --el need the file in a tab: genoffice open <file> first, then ask the user to select
outside_allowed_rootsStay inside GENOFFICE_ALLOWED_ROOTS; do not try another location
resource_limitThe package has too many or too large parts, an implausible compression ratio or an entry path that escapes the archive; detail names the entry and the limit. Do not retry; tell the user
unsupporteddetail.supported lists what this command accepts; pick another route from the table above
conversion_failed, app_unavailableThe file or the app: retry once; if capabilities --json says the app is missing, tell the user (PDF and →html/html→ routes need GenOffice)
app_crashedGenOffice crashed during a headless export (detail.signal): retry once; if it repeats, tell the user and name the document and the crash log path from suggestion

A successful result may still carry warnings[] ({code, message, suggestion?}): formulas_not_cached, op_warning (a sheets op was adjusted), images_dropped (convert docx→md), output_renamed (image saved with the provider's real extension), unresolved_placeholder (merge left placeholders without a value in place). Read them, report what matters, do not retry.

Before you say "done"

Three lines per artifact, every time:

Artifact1. Check2. Look3. Report
Deckslides audit deck.pptx --json → detail.issues empty (apply suggest ops otherwise)render deck.pptx --out shots --grid --json, open the contact sheetThe .pptx path and anything you left as is
Workbooksheet check book.xlsx --json → no formula_error, missing_sheet_ref, number_overflow (apply the set_col_width suggests)render book.xlsx --out shots --json, look at the sheet PNGThe .xlsx path; name uncached formulas if any
Documentdocs check report.docx --json → no broken_ref, placeholder_left, field_not_evaluated you can fixrender report.docx --out shots --json, look at page 1 and the lastThe .docx path

check/audit exit 0 whether or not they found something; the findings are in detail.issues[] with a stable code, a path and, when possible, a suggest op to pass to apply as is. Do not run genoffice open unless the user asks to see the file in GenOffice.

Reading the user's files

Source material the user hands you (a report to turn into slides, a workbook to summarize) is read by you, not by genoffice: md, txt, csv, pdf and images you open directly. Office files are zipped XML, so go through the CLI first:

  • docx: genoffice convert file.docx --to md --out file.md for the whole text (images are dropped), or genoffice docs read file.docx --full --json / --html for blocks with indexes.
  • xlsx: genoffice convert file.xlsx --to csv --sheet <name> --out file.csv for a whole sheet as displayed text, or genoffice sheet read file.xlsx --range A1:H200 --json for raw values (without --range it stops at 500 rows and says truncated: true; --stats first to size a workbook, --cols/--max-rows to page through a wide or long sheet, --where formula for the formulas alone).
  • pptx: genoffice slides read file.pptx --full --json for every slide's text, tables and speaker notes; genoffice slides render file.pptx --out shots when you need to see the pages.
  • pdf: genoffice pdf read file.pdf --range 1-20 --json when you cannot open the PDF yourself (a password-protected file, or page sizes and metadata are needed).

Take figures and wording from that material; never cat or unzip the Office file itself.

Designing a deck

Whenever the user wants a presentation, however short, do not hand-place ops: follow the staged pipeline the GenOffice app itself uses. You are the model, genoffice is the engine, and each stage is a file the CLI checks before the next one starts. Ops (create --ops, slides apply) are for editing a deck that already exists.

  1. genoffice guide slides design once per session, then genoffice guide slides spec. Run genoffice capabilities --json once: it says whether search, image search and image generation are configured in GenOffice; use them for facts and photos only when they are, and plan photo-free pages otherwise.
  2. Make a folder for the deck. Write the style sheet to deck/style.md (colors, fonts, layout variants, one sentence of style). Then the outline to deck/outline.json (core hook + one entry per page: title, type, layout, brief with real figures, image_queries) and run genoffice slides check deck/outline.json --json; fix every error before going on. Show the outline to the user only if they asked to review it.
  3. One page per step: re-read deck/style.md and the page's outline entry, resolve its photos, write deck/pages/NN.json (one page object echoing the entry's title, type, layout), run genoffice slides check deck/pages/NN.json --json; it finds outline.json and style.md one folder up and checks the page against entry N and the palette. Fix until detail.audit, detail.outline.findings and detail.style.offPalette are empty (a disagreement with the outline exits 1), then the next page. Never write several pages in one file or one step.
  4. genoffice create --type pptx --spec deck/pages --outline deck/outline.json --out deck/deck.pptx --json (refuses to run while an outline page has no file or a page disagrees with its entry). Then genoffice slides render deck/deck.pptx --out deck/shots --json and look at the PNGs; genoffice slides audit deck/deck.pptx --json for the geometry findings. Fix a page in its file and genoffice slides replace deck/deck.pptx --slide n --spec deck/pages/NN.json --json. At most two fix rounds.
  5. Report the path. Photos come from genoffice search --images results, genoffice image, or local files the user gave you; never draw a grey box in place of a photo. Figures come from the user's material or genoffice search; say so when a number is illustrative.

Editing an existing deck

A rewrite of one slide, a new title, a swapped picture: use ops, not the staged pipeline, and keep the deck's own design.

  1. genoffice slides read deck.pptx --slide n --full --json for the element ids and the current text; genoffice slides render deck.pptx --slide n --out shots --json when the words alone do not tell you what the page looks like.
  2. setText on the existing element (runs you leave unstyled inherit the original font, size and color), addElement / addPicture for new content, deleteElement for what goes. Write with --out when the user wants the original kept.
  3. genoffice slides audit deck.pptx --slide n --json after the edit: a longer sentence in the same box overflows; apply the suggest ops it returns (they grow or move the box), then render once more and look.
  4. Ids of edited elements change: run slides read again before a second round of ops. slides replace --slide n --spec rebuilds the page from a spec and is for decks the staged pipeline built, not for restyling a deck the user brought.

Examples

Deck from ops (an existing deck's edits, or a fixture; a presentation for a person goes through the staged path above):

json
[
  {
    "op": "addElement",
    "target": { "slide": 0 },
    "kind": "textbox",
    "offset": { "x": 914400, "y": 685800, "cx": 7315200, "cy": 914400 },
    "paragraphs": [{ "runs": [{ "text": "Q3 Review", "bold": true, "fontSize": 36 }] }]
  },
  { "op": "addBlankSlide", "target": { "slide": 0 } },
  {
    "op": "addTable",
    "target": { "slide": 1 },
    "rows": 3,
    "cols": 3,
    "offset": { "x": 914400, "y": 1828800, "cx": 7315200, "cy": 2286000 }
  }
]
genoffice create --type pptx --ops deck.json --out q3.pptx --json

Workbook with formulas, then a formatted header:

echo '[["item","qty","price"],["Apple",2,1.5],["Total","=SUM(B2:B2)",""]]' > table.json
genoffice create --type xlsx --from table.json --out sales.xlsx
echo '[{"op":"format_range","range":"A1:C1","format":{"bold":true,"fillColor":"#FFFF00"}}]' | genoffice sheet apply sales.xlsx --ops - --json

Word from Markdown, then insert a paragraph after block 0:

genoffice create --type docx --from report.md --out report.docx
echo '[{"op":"insert_content","afterBlockIndex":0,"html":"<p>Executive summary.</p>"}]' | genoffice docs apply report.docx --ops -

Path rules

  • Pass absolute paths or paths relative to the current directory; genoffice never writes outside the --out path or the file being edited.
  • create and convert refuse to overwrite an existing output without --force. apply edits in place unless --out is given; --out onto another existing file also needs --force.
  • genoffice refuses to rewrite a file the GenOffice window currently has open (exit 2, message "GenOffice has this file open"). Ask the user to close that tab, write to another path with --out, or pass --force only if they accept that the editor may overwrite the change.
  • If GENOFFICE_ALLOWED_ROOTS is set in the environment, genoffice only reads and writes inside those directories (exit 2 otherwise); stay within them. Every executed command is logged to ~/.genoffice/cli-audit.jsonl (GENOFFICE_AUDIT_LOG moves or disables it). GENOFFICE_USER_DATA points genoffice at a non-default GenOffice profile (open-documents registry, AI settings).
  • Image ops (addPicture, setImageFill, addMedia) accept a local file path in their bytes field; genoffice reads it.

Limits

  • Conversions to PDF run inside the GenOffice app (hidden, a few seconds each); they need GenOffice installed, or GENOFFICE_APP_BIN pointing at it; the same holds for docx→html and html→docx.
  • add_pivot writes the pivot's cells at targetCell (no values or formulas there, on a sheet that already exists in the file) plus a native pivot Excel refreshes, source formulas are evaluated from the file so set them in an earlier batch; add_sparkline writes one in-cell sparkline per data row (at most 200 rows per op); convert_to_values replaces formulas with the values the workbook engine computes from the file (error results keep their formula; cell edits go in an earlier batch); set_page_setup also takes printTitles, header/footer and rowBreaks/colBreaks. Excel ops that still need the live editor (refresh_pivot, edits to session-created tables and shapes) are refused with the reason. add_conditional_format and set_data_validation add to the rules a sheet already has (set_data_validation on a range that has one replaces it, null removes it); clear_conditional_formats starts over.
  • Formulas are evaluated with the workbook engine after writing, so sheet read and cached-value readers see numbers.

© genspark-ai, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/genoffice of genspark-ai/genoffice.

Open the folder on GitHubat commit c8e9467

Compare with similar skills

GenOffice Document CLI next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

GenOffice Document CLI compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
GenOffice Document CLI this skillgenspark-ai/genoffice9.2k—~19kAutomated safety check: PassApache-2.0
MarkitdownImCa0/just-laws78114 repos~3.2kAutomated safety check: NotesMIT
PDFzai-org/ZCode7.7k—~18kAutomated safety check: NotesProprietary
Markitdownjimmc414/Kosmos5952 repos~1.7kAutomated safety check: PassNone
Office DocumentsZS520L/HanakoPro103—~1.6kAutomated safety check: PassApache-2.0
PaperJSX Document Generatorcomposio-community/awesome-codex-skills17k—~842Automated safety check: PassApache-2.0

Similar skills

  • Markitdown

    ImCa0/just-laws

    Convert files and office documents to Markdown. An agent skill from ImCa0/just-laws.

    781 GitHub starsUsed in 14 repos~3.2k tokens
    Documents & OfficeAuto-check: notes
  • PDF

    zai-org/ZCode

    Professional PDF toolkit covering four production workflows: reports, creative visuals, academic LaTeX, and existing PDF processing.

    7.7k GitHub stars~18k tokensUpdated yesterday
    Documents & OfficeAuto-check: notes
  • Markitdown

    jimmc414/Kosmos

    Convert various file formats (PDF, Office documents, images, audio, web content, structured data) to Markdown optimized for LLM processing.

    595 GitHub starsUsed in 2 repos~1.7k tokens
    Documents & OfficeAuto-check passed
  • Office Documents

    ZS520L/HanakoPro

    A skill your agent uses when the user asks to open, read, inspect, understand, summarize, analyze, extract tables/text from, modify, update, repair, split, merge, rotate, or convert information from…

    103 GitHub stars~1.6k tokensUpdated 4 mo ago
    Documents & OfficeAuto-check passed
  • PaperJSX Document Generator

    composio-community/awesome-codex-skills

    Generates PPTX, DOCX, XLSX and PDF files from a JSON layout spec through PaperJSX's packages, creating new documents rather than editing them.

    17k GitHub stars~842 tokensUpdated 2 mo ago
    Documents & OfficeAuto-check passed
  • Skill Doc Delivery

    nyldn/claude-octopus

    Convert markdown to DOCX, PPTX, XLSX, PDF office documents — use when you need exportable deliverables

    4.2k GitHub starsUsed in 1 repo~2.4k tokens
    Documents & OfficeAuto-check passed

Questions about GenOffice Document CLI

What does GenOffice Document CLI do?

Creates, converts, reads and edits real pptx, xlsx, docx and PDF files locally through the genoffice command line. The skill drives the genoffice CLI that ships with GenOffice. It can build a presentation from a brief through a checked outline, per-page spec and render pipeline, a spreadsheet from CSV or JSON data with formulas, a Word document from Markdown or HTML, or a PDF.

When should I use GenOffice Document CLI?

GenOffice Document CLI fits situations like: building a slide deck from a written brief as a real .pptx file; generating a spreadsheet with formulas from CSV or JSON data; converting a Word document to PDF, or Markdown to Word; applying structured edits to part of an existing docx, xlsx or pptx.

How do I install GenOffice Document CLI in Claude Code?

Run `npx skills add genspark-ai/genoffice --skill genoffice -a claude-code`. Or copy the skill folder (skills/genoffice in genspark-ai/genoffice) into .claude/skills/genoffice in your project. Claude Code loads it when a task matches its description.

How do I install GenOffice Document CLI in Codex?

Run `npx skills add genspark-ai/genoffice --skill genoffice -a codex`. Or copy the skill folder (skills/genoffice in genspark-ai/genoffice) into .agents/skills/genoffice in your project. Codex loads it when a task matches its description.

Can I use GenOffice Document CLI in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add genspark-ai/genoffice --skill genoffice -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/genoffice, .gemini/skills/genoffice, .github/skills/genoffice and .opencode/skills/genoffice in your project.

What does GenOffice Document CLI need to run?

SKILL.md names no scripts, command-line tools or credentials: GenOffice Document CLI is instructions for the agent only. Our summary lists: GenOffice installed, which provides the genoffice CLI; A provider configured in GenOffice, for the search, image and media commands.

Does GenOffice Document CLI access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is GenOffice Document CLI safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does GenOffice Document CLI use?

GenOffice Document CLI is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does GenOffice Document CLI use?

About 19k tokens (SKILL.md is roughly 78k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to GenOffice Document CLI?

Skills that share tags, products or a category with GenOffice Document CLI: Markitdown (ImCa0/just-laws, 781 stars), PDF (zai-org/ZCode, 7.7k stars), Markitdown (jimmc414/Kosmos, 595 stars) and Office Documents (ZS520L/HanakoPro, 103 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains GenOffice Document CLI?

genspark-ai (a GitHub organization) maintains it in genspark-ai/genoffice, which has 9,239 GitHub stars. The repository was last updated on October 10, 2026.

Source: genspark-ai/genoffice on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.