@superdoc/cli
v0.41.0
Published
Command-line interface for SuperDoc: inspect, convert, and edit .docx files from a terminal or a script.
Keywords
Readme
@superdoc/cli
LLM-first CLI for deterministic DOCX operations through SuperDoc's Document API.
Install
npm install -g @superdoc/cliThe package automatically installs a native binary for your platform via optionalDependencies. Supported platforms:
| Platform | Package |
|----------|---------|
| macOS (Apple Silicon) | @superdoc/cli-darwin-arm64 |
| macOS (Intel) | @superdoc/cli-darwin-x64 |
| Linux (x64) | @superdoc/cli-linux-x64 |
| Linux (ARM64) | @superdoc/cli-linux-arm64 |
| Windows (x64) | @superdoc/cli-windows-x64 |
Usage
superdoc <command> [options]Getting Started
Stateful editing flow (recommended for multi-step edits):
superdoc open ./contract.docx
# Use query match to find a mutation-grade target
superdoc query match --select-json '{"type":"text","pattern":"termination"}' --require exactlyOne
# Mutate using the returned target
superdoc replace --target-json '{"kind":"text","blockId":"p1","range":{"start":0,"end":11}}' --text "expiration"
superdoc save --in-place
superdoc closeEncrypted Documents
Open password-protected .docx files with --password or the SUPERDOC_DOC_PASSWORD env var:
# Explicit flag
superdoc open ./secret.docx --password 'mypassword'
# Env var (preferred — avoids password in process listings)
SUPERDOC_DOC_PASSWORD='mypassword' superdoc open ./secret.docx
# Via call
superdoc call doc.open --input-json '{"doc":"./secret.docx","password":"mypassword"}'If the password is missing or incorrect, the CLI returns a structured error with one of these codes:
DOCX_PASSWORD_REQUIRED— encrypted file, no password suppliedDOCX_PASSWORD_INVALID— wrong passwordDOCX_ENCRYPTION_UNSUPPORTED— recognized but unsupported encryption methodDOCX_DECRYPTION_FAILED— crypto failure or corrupt data
Choosing the Right Command
Search the CLI contract when you know the intent but not the operation name:
superdoc discover "create a footnote"
superdoc discover "add an sdt"
superdoc discover "change table cell padding"discover uses the generated Document API contract plus CLI vocabulary and operation relationships. It returns an adaptive relevant set with at most ten results. The leading result includes a compact input shape, CLI parameters, a command template, and the exact describe command follow-up. Use --limit <1-10> to request a smaller ceiling.
Which command should I use?
| I want to... | Use this command |
|--------------|------------------|
| Find a mutation target (block ID, text range) | query match |
| Search/browse document content | find |
| Insert inline text within a block | insert |
| Create a new standalone paragraph | create paragraph |
| Create a new heading | create heading |
| Insert a list item before/after another list item | lists insert |
| Apply formatting to a text range | format apply or format helpers (format bold, etc.) |
| Apply multiple changes in one operation | mutations apply |
Mutation targeting workflow
Always use query match to discover targets before mutating:
# Step 1: Find the target
superdoc query match --select-json '{"type":"text","pattern":"Introduction"}' --require exactlyOne
# Step 2: Use the returned address in a mutation
superdoc replace --block-id <returned-blockId> --start <start> --end <end> --text "Overview"find is for content discovery and inspection. query match is for mutation targeting — it returns exact addresses with cardinality guarantees.
Block-oriented editing workflow
Use blocks list for ordered inspection, then blocks delete-range for contiguous removal:
superdoc open ./contract.docx
# 1. Inspect block order, IDs, and text previews
superdoc blocks list --limit 30
# 2. Preview the deletion (no mutation, shows what would be removed)
superdoc blocks delete-range \
--start-json '{"kind":"block","nodeType":"paragraph","nodeId":"abc123"}' \
--end-json '{"kind":"block","nodeType":"paragraph","nodeId":"def456"}' \
--dry-run
# 3. Apply the deletion
superdoc blocks delete-range \
--start-json '{"kind":"block","nodeType":"paragraph","nodeId":"abc123"}' \
--end-json '{"kind":"block","nodeType":"paragraph","nodeId":"def456"}'
superdoc save --in-placeThis replaces the pattern of calling blocks delete once per block. A 17-block removal becomes one command.
Preview-before-apply workflow
Use --dry-run and --expected-revision for safe, auditable mutations:
superdoc open ./contract.docx
# 1. Check session state
superdoc status
# 2. Find the mutation target
superdoc query match --select-json '{"type":"text","pattern":"termination"}' --require exactlyOne
# 3. Preview the change (validates input, shows what would change, no mutation)
superdoc replace --block-id p1 --start 0 --end 11 --text "expiration" --dry-run
# 4. Apply with revision guard (fails if document changed since preview)
superdoc replace --block-id p1 --start 0 --end 11 --text "expiration" --expected-revision 1
superdoc save --in-placeCommon mistakes
- Do not use
findoutput to construct mutation targets.findreturns discovery-grade data, not mutation-grade addresses. Usequery matchinstead. - Do not use
insert --block-idfor sibling block insertion.insertinserts inline text within a block. To create a new block adjacent to another, usecreate paragraph,create heading, orlists insert. - Do not use
create paragraphto continue a list. If you want to add a list item adjacent to existing list items, uselists insert.create paragraphcreates a standalone (non-list) paragraph.
Command Index
| Category | Commands |
|----------|----------|
| query | find, query match, get-node, get-node-by-id, get-text, info |
| mutation | insert, replace, delete, blocks delete, blocks delete-range, blocks list, mutations apply, mutations preview |
| format | format apply, format bold, format italic, format underline, format strikethrough |
| create | create paragraph, create heading, create table-of-contents |
| lists | lists list, lists get, lists insert, lists create, lists attach, lists detach, lists join, lists separate, lists set-level, lists indent, lists outdent, lists set-value, lists set-type, lists convert-to-text |
| comments | comments add, comments reply, comments delete, comments get, comments list |
| trackChanges | track-changes list, track-changes get, track-changes accept, track-changes reject, track-changes accept-all, track-changes reject-all |
| history | history get, history undo, history redo |
| lifecycle | open, save, close |
| session | session list, session save, session close, session set-default, session use |
| introspection | status, discover, describe, describe command |
| low-level | call <operationId> |
| legacy compat | search, replace-legacy <find> <to> <files...>, read |
For full command help and examples, run:
superdoc --help
superdoc discover "<natural-language intent>"
superdoc save --help
superdoc create paragraph --help
superdoc describe command <command-name>
superdoc describe command doc.saveUse --help or -h with a command to read its usage without opening a document or executing the command. Operation help includes schemaCommand, an executable command for retrieving the complete parameter schema. Add --pretty for terminal-readable output.
v1 Breaking Changes
This CLI replaces the previous @superdoc-dev/cli package surface with the v1 contract-driven command set.
| Legacy command | v1 status | Migration |
|---------------|-----------|-----------|
| superdoc replace <find> <to> <files...> | Renamed to replace-legacy | Use replace-legacy, or use query match + replace --target-json for the v1 workflow. |
Legacy compatibility is retained for search, read, and replace-legacy.
Normative Policy
- Canonical contract/version metadata comes from
@superdoc/document-api(CONTRACT_VERSION, operation metadata, and schemas). - This README is usage guidance for CLI consumers.
- If guidance here conflicts with
superdoc describe/describe commandoutput or document-api contract exports, those are authoritative.
Host mode (stdio JSON-RPC)
superdoc host --stdio- Starts a persistent JSON-RPC 2.0 host over newline-delimited stdio frames.
- Intended for SDK/runtime integrations that need long-lived command execution in a single process.
- Supported methods:
host.pinghost.capabilitieshost.describehost.describe.command(requiresparams.operationId)host.shutdowncli.invoke(executes canonical CLI command semantics)
API introspection commands
superdoc discover "set padding on one table cell"
superdoc describe
superdoc describe command doc.find
superdoc statusdiscover <intent>ranks relevant operations and expands the leading input shape without opening a document.describereturns contract + protocol metadata and the exhaustive operation catalog.describe command <operationId>returns one operation definition (inputs, response schema, errors, examples).statusshows current session status and document metadata.
Discovery evaluation
The repository includes a canonical intent corpus with expected operations in eval/discovery-cases.json.
pnpm eval:discovery
pnpm eval:discovery -- --case sdt-ambiguous-add
pnpm eval:discovery -- --query "add a repeating section control"
pnpm eval:discovery -- --jsonThe suite reports Top-1 accuracy, MRR, Recall@3, Recall@10, mean result count, payload size, and p95 search latency. It exits nonzero when an expected ranking, result-set bound, command helper, or ambiguity classification fails.
Stateful session commands
superdoc open ./contract.docx
superdoc status
superdoc query match --select-json '{"type":"text","pattern":"termination"}' --require exactlyOne
superdoc replace --target-json '{...}' --text "Updated clause"
superdoc save --in-place
superdoc closeopencreates a new session id automatically unless--session <id>is provided.- If
<doc>is omitted, commands run against the active default session. - Explicit
<doc>(or--doc) always runs in stateless mode and does not use session state.
Session management
superdoc session list
superdoc session save <sessionId> [--in-place] [--out <path>] [--force]
superdoc session set-default <sessionId>
superdoc session use <sessionId>
superdoc session close <sessionId> [--discard]Read / locate commands
superdoc info [<doc>]
superdoc find [<doc>] --type text --pattern "termination" --limit 5
superdoc query match [<doc>] --select-json '{"type":"text","pattern":"termination"}' --require exactlyOne
superdoc get-node [<doc>] --address-json '{"kind":"block","nodeType":"paragraph","nodeId":"p1"}'
superdoc get-node-by-id [<doc>] --id p1 --node-type paragraphfindreturns discovery-grade results for content search and browsing.query matchreturns mutation-grade addresses and text ranges — use this before any mutation.- For text queries, use the returned
blocks[].rangeas targets forreplace,comments add, and formatting commands.
Mutating commands
superdoc replace [<doc>] --target-json '{...}' --text "Updated text" [--out ./updated.docx]
superdoc insert [<doc>] --value "New text" [--out ./inserted.docx]
superdoc blocks delete [<doc>] --node-type paragraph --node-id abc123
superdoc blocks delete-range --start-json '{"kind":"block",...}' --end-json '{"kind":"block",...}'
superdoc create paragraph [<doc>] --text "New paragraph" [--at-json '{"kind":"after","target":{"kind":"block","nodeType":"paragraph","nodeId":"p1"}}']
superdoc lists insert [<doc>] --node-id li1 --position after --text "New item"
superdoc format bold [<doc>] --target-json '{...}' [--out ./bolded.docx]
superdoc comments add [<doc>] --block-id p1 --start 0 --end 10 --text "Please revise" [--out ./with-comment.docx]- In stateless mode (
<doc>provided), mutating commands require--out. - In stateful mode (after
open), mutating commands update the active working document and--outis optional. - Use
--dry-runto preview any mutation without applying it. - Use
--expected-revision <n>with stateful mutating commands for optimistic concurrency checks.
Block inspection
superdoc blocks list
superdoc blocks list --limit 20 --offset 10
superdoc blocks list --node-types-json '["paragraph","heading"]'- Returns ordered block metadata: ordinal, nodeId, nodeType, textPreview, isEmpty.
- Use the returned nodeIds as targets for
blocks delete,blocks delete-range, or other block-oriented commands.
Low-level invocation
superdoc call <operationId> --input-json '{...}'- Invokes any document-api operation directly with a JSON payload.
Save command modes
superdoc save --in-place
superdoc save --out ./final.docxsavepersists the active session but keeps it open for more edits.- If no source path exists (for example stdin-opened docs),
saverequires--out <path>. save --in-placechecks for source-file drift and refuses overwrite unless--forceis passed.
Close command modes
superdoc close
superdoc close --discard- Dirty contexts require explicit
--discard(or runsavefirst, thenclose).
Output modes
- Default:
--output json(machine-oriented envelope) - Human mode:
--output pretty(or--pretty)
superdoc info ./contract.docx --output json
superdoc info ./contract.docx --prettyGlobal flags
--output <json|pretty>--json--pretty--session <id>--timeout-ms <n>--help--version,-v
Input payload flags
--query-json,--query-file(find,lists list)--address-json,--address-file(get-node,lists get)--target-json(mutation commands — no--target-filecounterpart; use flat flags--block-id/--start/--endas alternative)--input-json,--input-file(call,create paragraph)--at-json,--at-file(create paragraph)
Stdin support
Use - as <doc> to read DOCX bytes from stdin:
cat ./contract.docx | superdoc open -
cat ./contract.docx | superdoc info -JSON envelope contract
Normative operation/version metadata comes from @superdoc/document-api; use superdoc describe for the runtime contract surface.
Success:
{
"ok": true,
"command": "find",
"data": {},
"meta": {
"version": "1.0.0",
"elapsedMs": 42
}
}Error:
{
"ok": false,
"error": {
"code": "INVALID_TARGET",
"message": "Expected paragraph:abc123 but found listItem:abc123.",
"details": {
"requestedNodeType": "paragraph",
"actualNodeType": "listItem",
"nodeId": "abc123",
"remediation": "Use lists.insert to add an item to a list sequence."
}
},
"meta": {
"version": "1.0.0",
"elapsedMs": 8
}
}Part of SuperDoc
This CLI is part of SuperDoc — open-source DOCX editing and tooling. Renders, edits, and automates .docx in the browser and on the server.
License
AGPL-3.0 · Enterprise license available
