Genoffice logo

Genoffice

OrganizationPopular
genspark-ai
genoffice

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.

Overview

Publishergenspark-ai
Repositorygenoffice
Skill namegenoffice
Stars
7K
Forks
926
Bundled files
Instructions only
LicenseApache-2.0
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by genspark-ai on GitHub. Read the source before you install it.

Installation

Install the Genoffice AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/genspark-ai/genoffice.git /tmp/genoffice
mkdir -p .claude/skills
cp -r /tmp/genoffice/skills/genoffice .claude/skills/genoffice
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Genoffice in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Genoffice on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Genoffice is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

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>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>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] / genoffice slides apply <pptx> --ops <file> [--dry-run]Inspect ids, geometry 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, text overflow, overlap): issues[] with a code, level, path (s_n/e_*) and, for bounds and overflow, 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]]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 / 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 guide <slides|docs|sheets> [group|op|design|spec] [--json] [--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]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).

Which command

TaskCommand pathNot for
A presentation from a brief, however shortguide slides designstyle.md + outline.jsonslides check per page → create --type pptx --specrender --gridslides 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 readslides apply --opsslides auditrender --pagerestyling the whole deck (applyTheme op, or rebuild through the staged path)
A workbook from datacreate --type xlsx --from data.csv | table.jsonsheet 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 readguide sheets <op>sheet apply --opssheet checkrefresh_pivot, session tables and shapes (refused: needs the editor)
A Word document from textcreate --type docx --from report.md | fragment.htmldocs checkrendera real web page (convert page.html --to docx)
Edit an existing Word documentdocs readdocs apply --opsdocs 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/--pageselection <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 listskill 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 delete_note come from docs read --notes. 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. 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.

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
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)

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). 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 --jsondetail.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.

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.

Frequently asked questions

What does the Genoffice AI skill do?

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, workb...

Why use Genoffice on TypingMind?

Because you install it once and use it with any model. Genoffice is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Genoffice in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/genspark-ai/genoffice/tree/main/skills/genoffice. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Genoffice?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Genoffice?

As many as you like. As long as a model supports skills, you can use Genoffice with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Genoffice AI skill free?

Yes. It is published on GitHub by genspark-ai under the Apache-2.0 license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇