# Office Transform

Extract or edit a selection from xlsx, docx, pdf, or pptx into a new file; the source...

- Repository: https://github.com/CherryHQ/cherry-studio (53164 stars)
- Category: Documents
- License: AGPL-3.0
- Last updated: 2026-11-01
- Runs scripts: yes, review before use

## Install

Claude Code: `npx skills add CherryHQ/cherry-studio --skill office-transform -g -a claude-code -y`
Codex: `npx skills add CherryHQ/cherry-studio --skill office-transform -g -a codex -y`
Cursor: `npx skills add CherryHQ/cherry-studio --skill office-transform -g -a cursor -y`
Gemini CLI: `npx skills add CherryHQ/cherry-studio --skill office-transform -g -a gemini-cli -y`

## Description

Extract or edit a selection from xlsx, docx, pdf, or pptx into a new file; the source is never modified.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Office Transform

Turn a structural selection of an Office/PDF document into a new derived file.

Two invariants hold for every operation:

1. **The source file is read-only.** Every result is a new file; both scripts refuse to
   write to the source path or overwrite an existing file. Never work around this with
   ad-hoc shell edits to the original.
2. **Anchors are structural.** Selections address the document's own coordinates, worksheet + A1 range, body-level paragraph ordinal, one-based page number, never
   screen or DOM positions.

## When to use which tool

- Only need to *read* a document to summarize or answer questions → use
  `mcp__cherry-tools__to_markdown` instead (see the cherry-tool-guide skill); it is
  lossy but built for reading.
- The user wants a *file* out, an extracted range, a converted fragment, an edited
  copy → this skill.

## Input: selection references

Chat surfaces may hand you a fenced `selection-ref` block:

```selection-ref
{"path": "/abs/report.xlsx", "anchor": {"format": "xlsx", "sheet": "Sheet1", "range": "A1:C10"}, "excerpt": "…", "fileStamp": {"size": 1024, "mtimeMs": 1700000000000}}
```

The `anchor` object is exactly what the scripts take via `--anchor`.

A block may also carry `comment`: what the user wants done at that location, in their own words.
Treat it as the user's instruction for that anchor. It is not part of the anchor, so never pass it
to a script.

**Freshness check.** `fileStamp.mtimeMs` is milliseconds since the Unix epoch, floored to
whole milliseconds. Do not compare it to `stat`'s default output: `stat -f %m` (macOS) and
`stat -c %Y` (GNU) give whole *seconds*, so multiplying by 1000 loses the sub-second part and
never matches. Read whole milliseconds the way the app wrote them:

```bash
uv run python -c "import os,sys;st=os.stat(sys.argv[1]);print(st.st_size, st.st_mtime_ns//1_000_000)" '/abs/report.xlsx'
```

The rest: https://github.com/CherryHQ/cherry-studio/blob/HEAD/resources/skills/office-transform/SKILL.md
