@mu-cabin/wps-cli
v0.1.5
Published
Agent-first CLI for WPS private Drive files and permissions, smart documents (.otl), and multidimensional tables (.dbt) through a dedicated Chrome profile.
Maintainers
Readme
wps-cli
Agent-first CLI for WPS private Drive metadata and guarded file/ACL mutations plus two smart file types:
- smart documents:
.otl/OTL - multidimensional tables:
.dbt/DB
It drives Chrome through CDP because the verified KDrive REST bridge and domain API live in the page's
main world. Drive commands can list metadata for all file types; content operations use
window.WPSOpenApi and do not support ordinary Writer, Spreadsheet, or Presentation files.
Setup
Running wps with no command prints the first-time setup guide. The CLI does not silently assume a
deployment origin when no base URL has been configured.
wps config init --base-url https://wps.example.invalid
wps browser status
# Run this when browser status says no supported browser was found:
wps browser install
wps login
wps whoami --json
wps doctor --online --jsonlogin opens a dedicated Chrome profile under ~/.wps-cli/chrome-profile/. All later commands reuse that profile headlessly. The CLI
never reads the default Chrome profile and does not accept passwords, cookies, or tokens.
Commands
wps doctor --online --json
wps drive files list --parent-id 0 --limit 100 --json
wps drive tree --root-id 0 --max-depth 20 --max-items 1000 --json
wps drive files path --file-id '<file-id>' --json
wps drive folders create --parent-id 0 --name 'POC folder' --json
wps drive files rename --file-id '<file-id>' --name 'Renamed folder' \
--confirm-new-file-id '<file-id>' --json
wps drive files move --file-id '<file-id>' --target-parent-id '<folder-id>' \
--confirm-new-file-id '<file-id>' --json
wps drive files copy --file-id '<file-id>' --target-parent-id '<folder-id>' \
--confirm-new-file-id '<file-id>' --json
wps drive files delete --file-id '<file-id>' --confirm-new-file-id '<file-id>' \
--confirm-delete-file-id '<file-id>' --json
wps drive permissions effective --file-id '<file-id>' --json
wps drive permissions list --file-id '<file-id>' --json
wps drive permissions defaults --file-id '<file-id>' --json
wps drive permission-roles list --file-id '<file-id>' --json
wps drive permissions update --file-id '<file-id>' --permission-id '<permission-id>' --role-id '<role-id>' \
--confirm-new-file-id '<file-id>' --json
wps drive permissions reset --file-id '<file-id>' --confirm-new-file-id '<file-id>' \
--confirm-delete-file-id '<file-id>' --json
wps otl create --name 'Release notes' --json
wps otl rename --url '<OTL URL>' --name 'Release notes' --confirm-new-file-id '<file.id>' --json
wps otl read --url '<OTL URL>' --json
wps otl read --url '<OTL URL>' --include-nodes all --json
wps otl selection get --url '<OTL URL>' --args '{"from":33,"to":38}' --json
wps otl replace-range --url '<OTL URL>' --args '{"from":33,"to":38,"expectedText":"old text","text":"replacement"}' \
--confirm-new-file-id '<file.id>' --json
wps otl format text --url '<OTL URL>' --args '{"from":33,"to":44,"toggles":["bold"]}' \
--confirm-new-file-id '<file.id>' --json
wps otl block insert --url '<OTL URL>' \
--args '{"type":"highlight","emoji":"💡","text":"Verified conclusion"}' \
--confirm-new-file-id '<file.id>' --json
wps otl document compile --xml-file document.xml --json
wps otl document compose --url '<blank OTL URL>' --xml-file document.xml \
--confirm-new-file-id '<file.id>' --json
wps otl document append --url '<existing OTL URL>' --xml-file append.xml \
--confirm-new-file-id '<file.id>' --json
wps otl spreadsheet list --url '<OTL URL>' --json
wps otl spreadsheet range get --url '<OTL URL>' \
--args '{"sourceId":"<sourceId>","range":"A1:D3"}' --json
wps otl spreadsheet range set-values --url '<OTL URL>' \
--args '{"sourceId":"<sourceId>","range":"A1:B2","values":[["item","count"],["A",2]]}' \
--confirm-new-file-id '<parent OTL file.id>' --json
wps otl capabilities --url '<OTL URL>' --json
wps dbt create --name 'Issue tracker' --json
wps dbt rename --url '<DBT URL>' --name 'Issue tracker' --confirm-new-file-id '<file.id>' --json
wps dbt schema --url '<DBT URL>' --json
wps dbt record export --url '<DBT URL>' --args '{"SheetId":2,"PageSize":1000}' \
--output records.ndjson --json
wps dbt view config --url '<DBT URL>' --args '{"SheetId":2,"ViewId":"C"}' --json
wps dbt view set-filter --url '<DBT URL>' \
--args '{"SheetId":2,"ViewId":"C","Mode":"AND","Filters":[{"Field":"状态","CriteriaOp":"Equals","Values":["进行中"]}]}' \
--confirm-new-file-id '<file.id>' --json
wps dbt selection get --url '<DBT URL>' --json
wps dbt range get --url '<DBT URL>' \
--args '{"SheetId":2,"ViewId":"C","RecordIds":["T"],"FieldIds":["G"]}' --json
wps dbt capabilities --url '<DBT URL>' --json
wps manifest --jsondrive files list is the one-page primitive. drive tree independently pages every folder and reports
complete:false plus continuation[] when --max-depth or --max-items stops traversal. Effective
permissions describe what the signed-in caller can do; permission subjects and role templates are separate
queries and must not be inferred from one another. Drive mutations require exact IDs, enforce the caller's
effective action, and report success only after task completion plus an independent readback. Folder creation is
the only exception to pre-confirmation because the server assigns its new ID; every later mutation of that folder
requires the returned ID. ACL writes always use overwrite:false, so they do not propagate to descendants.
DBT has typed resource groups for sheet, field, record, view, selection, and range. Complex SDK arguments can
be passed as JSON or loaded from a file. manifest includes their input JSON Schemas. Record field
keys may be field names or IDs; the CLI resolves known IDs to the names required by this deployment:
wps dbt record list --url '<DBT URL>' --args '{"SheetId":2}' --json
wps dbt record create --url '<DBT URL>' --file create-records.json \
--confirm-new-file-id '<file.id>' --json
wps dbt record attachment download --url '<DBT URL>' \
--args '{"SheetId":2,"RecordId":"T","Field":"附件","Attachment":1}' \
--output evidence.png --json
wps dbt record attachment download-all --url '<DBT URL>' \
--args '{"SheetId":2,"RecordId":"T","Field":"附件"}' \
--output-dir evidence-files --json
wps dbt record attachment upload --url '<DBT URL>' \
--args '{"SheetId":2,"ViewId":"C","RecordId":"T","Field":"附件","Files":[{"path":"./evidence.png"}]}' \
--confirm-new-file-id '<file.id>' --jsonRecord listing supports typed page filters, pagination, view/field projection, and field-ID mode.
With PreferId:true, pass field IDs in Fields; otherwise pass field names.
record export auto-pages into a private NDJSON file and a schema/query manifest containing row count,
completeness, continuation offset, column statistics, SHA-256, and file size. It requires a relative output
path and refuses replacement unless --overwrite is explicit. Persistent Grid-view filters, sorts, and groups
are replaced through named view set-* commands and verified only after save plus a full page reload.
Temporary filter values are strings even for Number fields (for example "13"); value-based Checkbox/Complete
filters are rejected because their private-deployment encoding is not verified. selection set succeeds only after
the activated sheet/view and normalized selected record IDs exactly match the request.
DBT Url fields accept complete HTTP(S) strings and persist as clickable links. Field creation can persist one non-empty
field-level displayText setting; record writes still pass URL strings, and this deployment reads each stored value back with
the URL as its own display text. The CLI verifies both shapes independently. Caller-supplied link objects remain unsupported.
DBT attachment downloads use the dedicated record attachment download command. It rereads the live field and record,
selects one exact attachment by file name or one-based position, resolves the short-lived WPS URL internally, and writes
a private relative-path artifact. The URL is never emitted; persisted size, SHA-256, and known file signatures are checked.
record attachment download-all materializes every attachment from the freshly read field into one new mode-0700
directory, with deterministic names and mode-0600 files; it is bounded to 50 files and 500 MiB total.
DBT attachment writes use the dedicated record attachment upload command. It reads local bytes, resolves an exact live
Grid view and Attachment field, uploads through that view's exact record range, saves, reloads, and independently
reads the record metadata back.
The default Mode:"require-empty" refuses to overwrite a non-empty field; Mode:"replace" must be explicit and
replaces the complete attachment field. One command accepts at most 10 files, 10 MiB each and 20 MiB total.
Generic record update remains closed to Attachment values and never accepts caller-supplied uploadId metadata.
Every typed DBT resource mutation now verifies persistence after reload: sheets and views through list readback,
fields through field-schema readback, records one ID at a time, deletes by absence, and range writes by exact matrix
comparison. A successful SDK return or save=result:ok alone is not the acceptance boundary.
Field creation also supports Attachment, Time, Currency, Percentage, and ID. Record writes validate Time as
HH:mm:ss, Currency/Percentage as finite numbers, and ID as a 15- or 18-character identity string before opening WPS.
OTL preserves the deployment-specific compatibility rules: complete structured reads use the full
GetContentAll.Params; editing focuses the outline and editor first; explicit Markdown appends use
InsertContent({Markdown}); constrained XML/JSON appends use the named otl document append command;
exact replacement deletes and inserts escaped inline HTML at the same position; selection positions are
passed as from,to positional arguments. Named commands cover selection reads, exact replacement,
text/paragraph formatting, and ordered/bullet/task lists.
otl document compile validates a versioned, constrained JSON or XML document locally. Plain structural input
keeps the exact allowlisted AP-JSON output; documents containing local pictures or embedded spreadsheets emit an
ordered compose plan after preflighting every image, without exposing base64 bytes. otl document compose uses the
same typed AST to import a complete document into a confirmed blank OTL only, then verifies the title, every node,
resource identity, dimensions, and top-level order before save and after reload. The document vocabulary includes
paragraphs, six heading levels, inline marks and colors, links, emoji, ordered/bullet/task lists, rich tables with
merge/alignment metadata, quote, code, divider, highlight, formula, date/time, cloud-document cards, local pictures,
and embedded spreadsheets. XML DTD/entity declarations, unknown tags/attributes, raw AP-JSON, caller-supplied
resource IDs, remote pictures, and non-HTTPS links fail before browser mutation.
otl document append adds one or more constrained non-resource XML/JSON blocks to an existing OTL. It preserves
the existing title and top-level node prefix, then verifies the appended suffix before save and again after reload.
Markdown remains an explicit input choice rather than an agent-authored intermediate format. Table widths are
optional and default to WPS layout; when supplied, the CLI verifies that every requested width survives readback.
Each embedded spreadsheet is a separate .xlsx backing object. Compose saves and reloads a verified checkpoint
after creating one before it appends later blocks; removing that boundary can make the current deployment persist
only the prefix before the spreadsheet. otl spreadsheet list returns entries under result.spreadsheets.
<document version="1" title="Structured report">
<h1>Delivery <b>summary</b></h1>
<p>Rich text with <span font-size="13" color="#C21C13">bounded styling</span>.</p>
<list style="ordered"><item>First result</item><item>Second result</item></list>
<table header-rows="1">
<row><cell>Item</cell><cell>Status</cell></row>
<row><cell>AP-JSON compiler</cell><cell align="center">Ready</cell></row>
</table>
</document>otl block insert adds one typed block at the document end and verifies it before and after save/reload.
The verified block surface is code, rectangular tables, quote, divider, HTTPS link, live-validated emoji,
local uploaded image, highlight block, LaTeX formula, date/time, OTL/DBT cloud-document card, and embedded
Spreadsheet. Spreadsheet creation uses the editor's own create-then-insert command and verifies the backing
object, parent document, exact requested dimensions, save, and reload. DBsheet embeds are intentionally closed:
this deployment renders them as an unsupported placeholder. Image URLs are intentionally rejected because the
deployment creates an invalid placeholder unless the
image bytes go through the attachment upload path. Raw Document.ImportJson and
Selection.InsertContent remain unavailable through generic otl call.
otl raw reads the deployment-versioned raw OTL envelope without requiring the editor SDK and can persist it as a private
relative .json artifact. otl resource materialize rereads persisted picture and embedded-spreadsheet nodes, resolves
their original attachment metadata internally, and writes verified PNG/JPEG/etc. and XLSX originals into one new private
directory without exposing resource IDs or signed URLs.
otl export pdf and otl export docx use the named editor export methods, download to a relative artifact, and accept success
only after the PDF/Office file signature is verified. If this deployment's native PDF conversion fails, PDF export falls back
to the verified WPS Docx export and local soffice; that fallback requires LibreOffice on PATH and is reported as
conversion:"wps-docx-libreoffice". All three artifact flows refuse silent replacement.
An embedded spreadsheet is backed by a separate .xlsx Office attachment (office_type=s), but this does
not enable arbitrary standalone Spreadsheet files. The otl spreadsheet module first proves that the source ID
belongs to the parent OTL and that the attachment points back to the confirmed parent ID. It currently exposes
bounded A1-range reads, typed value matrices, and local formula matrices. Each write is verified immediately,
saved through the attachment's own Office instance, reloaded, and verified again. Raw Excel Application/Range
members, external-resource formulas, clears, sheet structure changes, formatting, exports, and script execution
remain closed.
Columns, ProcessOn mind maps/flowcharts, DBsheet embeds, and protected regions remain closed because their creation dependencies or persistence contract have not passed isolated live QA.
capabilities classifies live members as methods, properties, collections, objects, or unknowns.
discovered is diagnostic only: generic call is allowed solely when the exact detail has
availableBy=call; named-only operations report availableBy=command, and broken wrappers remain blocked.
Safety
- Every page is strongly checked as
.otl/OTLor.dbt/DBbefore domain calls. - Every mutation of an existing resource requires
--confirm-new-file-idto equal itsfile.id; newly created Drive folders return their server-assigned ID for subsequent confirmation. - Deletion additionally requires
--confirm-delete-file-idwith the same value. - Drive ACL deletion additionally requires
--confirm-permission-id; restoring default ACLs uses both file-ID confirmations. Sharing links, owner transfer, descendant ACL propagation, DBTPermissions.*, webhook, external-import, data-source, and unbounded bulk methods remain unavailable. - Configuration is non-secret and mode
0600; browser profiles are dedicated and process-locked. --jsonemits one{ok,schemaVersion,data}or{ok:false,schemaVersion,code,message,hint?}envelope.
Environment overrides: WPS_CLI_API_BASE, WPS_CLI_CHROME, WPS_CLI_PROFILE, and
WPS_CLI_CONFIG_DIR. Resolution is CLI flag, then environment, then config/managed browser, then a
compatible system Chrome. Browser downloads are never implicit; browser install --build <version>
can override the tested default when validating a WPS upgrade.
