npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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.

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

login 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 --json

drive 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>' --json

Record 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/OTL or .dbt/DB before domain calls.
  • Every mutation of an existing resource requires --confirm-new-file-id to equal its file.id; newly created Drive folders return their server-assigned ID for subsequent confirmation.
  • Deletion additionally requires --confirm-delete-file-id with 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, DBT Permissions.*, 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.
  • --json emits 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.