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

@versionstory/vs-cli

v0.1.7

Published

Agent-first CLI wrapper for Version Story API

Readme

Version Story Command Line

Agent-first CLI for the Version Story API (/api/v1).

This tool wraps Repository, document, version/artifact, review, and notification endpoints so an AI agent can run deterministic workflows without UI dependencies.

Design Goals (for AI agents)

  • Non-interactive only: every command is flag-driven.
  • API endpoint wrapper commands output JSON.
  • Local workspace commands (vs init, vs status, vs read, vs commit, vs pull, vs edit, vs open) output human-readable text (legacy-style).
  • JSON errors for API endpoint wrapper commands, human-readable errors for local workspace commands.
  • Workspace format support is split:
    • vs init, vs pull, vs commit, and vs open support .doc, .docx, .pdf, .md, and .markdown
    • vs read and vs edit are .docx-only
  • No hidden prompts or wizard flows.
  • One command = one API operation (or one explicit multi-step operation, like upload).

Agent Skill

For agents that need to operate this CLI consistently, use:

  • skills/vs/SKILL.md

The skill is adapted from the legacy CLI skill but aligned to this repo's commands and behavior (vs auth ..., local .versionstory/state.json, human-readable local workflow commands, and endpoint-wrapper JSON commands).

Install

npm install -g @versionstory/vs-cli

Then use:

vs --help

For local development from this repo:

npm install
npm run build
npm link

Then use:

vs --help

Publish

Build and inspect the package:

npm run build:full
npm pack --dry-run

npm run build:full now:

  1. builds native edit-docx binaries into bin/
  2. auto-bumps the package version if that version is already published on npm
  3. prepares platform-specific npm packages in packages/native/
  4. builds the CLI into dist/
  5. runs npm pack for the main npm package

Publish the native packages first, then publish the main CLI package.

Publish to npm:

npm login
bash scripts/publish-packages.sh --otp <code>

Publish through GitHub Actions:

  1. Add repository secret NPM_TOKEN
  2. Run the Publish CLI workflow from GitHub Actions

The workflow uses npm run build:full and then publishes the native packages plus the main CLI package with the configured token.

Install the published package:

npm install -g @versionstory/vs-cli

Configuration

Set environment and authenticate once:

vs config set-environment prod
vs auth login

Environment targets:

  • Local:
vs config set-environment local
  • Dev:
vs config set-environment dev
  • Production:
vs config set-environment prod

Runtime precedence is strict and explicit:

  1. CLI flags (vs --environment <local|dev|prod> <command>)
  2. Local config (~/.version-story-cli/config.json)
  3. Default environment (when none is set): prod

vs --environment by itself is invalid. The global flag must be followed by a command, for example:

vs --environment dev repositories list
vs --environment local init --name "Acme"

Data Path Rule

CLI environment selects the API host only. Database selection is controlled by that API's DATABASE_URL, not CLI config.

Quick Preflight

Before debugging auth/data issues:

  • Run vs config show and confirm environment
  • Confirm web VITE_API_URL if testing both web and CLI
  • Confirm DATABASE_URL in the API process being targeted

Core Commands

Local Workspace (Git-style)

These commands use a project-local .versionstory/state.json file and working files in your current directory.

# Initialize local state and perform first sync
vs init --repository-id <repository-id> --branch-id <branch-id>

# Create a new Repository and initialize local state
vs init --name "VS CLI test"

# Reinitialize and overwrite local state
vs init --repository-id <repository-id> --branch-id <branch-id> --force

# Use local API mode (legacy-style command flag)
vs init --repository-id <repository-id> --branch-id <branch-id> --local

# After state exists, pull reuses stored repository/branch unless you override selectors
vs pull

# Compare working tree, index, and local commit queue
vs status

# Stage changes
vs add SPA.docx

# Create a local commit from staged changes
vs commit -m "Update SPA"

# Upload local commits to the current branch
vs push

# Show local and remote branch history
vs log

# Read tracked document from cached preprocessed working state (.docx only)
vs read NDA.docx

# Show only changed lines with one line of context
vs read NDA.docx --changes --context 1

# Search document text and return matching paragraph IDs/snippets (.docx only)
vs read NDA.docx --search "Acme, Inc."

# Return only matching paragraph IDs
vs read NDA.docx --search "Acme, Inc." --return-ids

# Print document structure IDs for tables, rows, cells, and paragraphs
vs read NDA.docx --return-ids

# Note: redline mode is not supported in preprocessed working-state reads
# vs read NDA.docx --redline

# Create and list branches
vs branch "NDA updates"
vs branch

# Switch local workspace state to another branch
vs switch "NDA updates"

# Apply edits (with target paragraph IDs), then create a local commit automatically
vs edit NDA.docx --edits '[...]' --chat-context "request context" -m "Update clause"

# Validate target IDs without changing files
vs edit NDA.docx --edits '[...]' --chat-context "request context" -m "Update clause" --validate

# Open the current repository workspace in browser
vs open

# Open using explicit local web mode
vs open --local

# Register the browser-to-CLI protocol on macOS
vs protocol register

# Print a versionstory:// URL for a tracked DOCX
vs protocol print-open-word-url --relative-path NDA.docx

# Open a tracked DOCX locally and start a short-lived watch session
vs protocol open-word --relative-path NDA.docx

# Check whether the watched DOCX changed on disk
vs protocol status --relative-path NDA.docx

vs status reports staged changes, unstaged changes, untracked files, and unpushed local commits.

Legacy-style output examples:

$ vs status
On repository <repository-name> (branch <branch-name>)

Changes to be committed:
  (use "vs commit -m <message>" to create a local commit)
        modify:   NDA.docx

1 staged, 0 unstaged, 0 untracked, 0 unpushed
$ vs commit -m "Update NDA"
✓ Created local commit 1234abcd Update NDA
$ vs push
Pushing 1234abcd Update NDA
  ✓ NDA.docx
✓ Pushed 1 local commit
$ vs pull
Pulling latest versions...
  ✓ NDA.docx
  ✓ SPA.docx

✓ Pulled 2 documents
$ vs edit NDA.docx --edits '[...]' --chat-context "..." -m "Update NDA"
Applying edits...
Accepting track changes for clean commit version...

Creating local commit...
✓ Created local commit 1234abcd
Pushing commit...
✓ Edit complete. Edit set ID: <uuid>
✓ Pushed commit 1234abcd (#12)
$ vs read NDA.docx --changes --context 1
--- Change 1 of 2 [2b48b62c3ef64df090e10b0741b91ffe] ---
...
... {.deletion}
... {.insertion}  <- CHANGE
...
$ vs open --local
Opening: http://localhost:5173/#section=repositories&screen=workspace&view=documents&repository=<repository-id>&branch=<branch-id>
$ vs protocol open-word --relative-path NDA.docx
Opened NDA.docx and started local watch session.
Status: vs protocol status --workspace "/path/to/repo" --relative-path "NDA.docx"

Environment convention:

  • vs --environment local <command> selects the local API environment for commands that use the global runtime context
  • --local on vs init, vs pull, vs push, vs log, vs branch, vs switch, vs edit is a legacy shortcut that also targets the local API at http://localhost:3001
  • --local on vs open uses local web at http://localhost:5173
  • vs init, vs pull, and vs switch link the current workspace directory to the current repository branch in local CLI config.
  • The web app uses that local link to invoke versionstory://open-word?... for tracked .doc and .docx files without requiring vs open.
  • After Word saves are detected, the web app can pull the changed local file through the localhost bridge, upload it as a new version, and refresh the redline viewer.
  • Without --local, vs open maps:
    • https://api.development.versionstory.com -> https://web.development.versionstory.com
    • https://api.versionstory.com -> https://web.versionstory.com
    • local API hosts (localhost, 127.0.0.1, api-local.versionstory.com) -> http://localhost:5173

Local browser-to-CLI integration:

  • vs protocol register installs a macOS versionstory:// handler backed by this CLI package.
  • vs protocol open-word --relative-path <path> opens a tracked .doc or .docx file in the default local app and starts a short-lived localhost watch session on 127.0.0.1:32107.
  • vs protocol status --relative-path <path> reports whether the watched file has changed on disk since it was opened.
  • vs protocol print-open-word-url --relative-path <path> prints the versionstory://open-word?... URL that the web app can invoke.
  • The bridge exits after an idle timeout; it is not intended to be a permanent daemon.

vs edit runs a local native binary in this repo:

  • bin/osx-arm64/edit-docx
  • bin/osx-x64/edit-docx
  • bin/linux-x64/edit-docx
  • bin/win-x64/edit-docx.exe

When installed from npm, vs edit resolves the matching binary from the installed platform package at runtime.

If those binaries are missing, vs edit falls back to:

  • dotnet run --project apps/edit-docx/edit-docx.csproj -- ...

Auth

vs auth login
vs auth me
vs auth switch-organization --organization-id <org-id>

vs auth login opens the Version Story web app sign-in page, where you can use email/password or any configured OAuth provider, and stores the returned token in local CLI config.

Repository and Tree

vs repositories list
vs repositories create --name "Our Repository"
vs repositories branches --repository-id <repository-id>
vs repositories create-branch --repository-id <repository-id> --name "NDA updates"
vs repositories merge-branch --repository-id <repository-id> --branch-id <branch-id>
vs repositories close-branch --repository-id <repository-id> --branch-id <branch-id>
vs repositories delete-branch --repository-id <repository-id> --branch-id <branch-id>
vs repositories tree --repository-id <repository-id> --branch-id <branch-id>
vs repositories create-document --repository-id <repository-id> --name "NDA.docx" --path "NDAs"

Document Versions (Upversion)

Upload flow is fully wrapped:

  1. uploads/start
  2. signed PUT to S3
  3. uploads/complete
vs versions upload --document-id <doc-id> --branch-id <branch-id> --file ./NDA.pdf
vs versions upversion --document-id <doc-id> --branch-id <branch-id> --file ./NDA.pdf

Artifact / Redline Download

Get signed URL only:

vs versions download --version-id <version-id> --variant redline --format html

Download to file:

vs versions download \
  --version-id <version-id> \
  --variant redline \
  --format changed-pages-pdf \
  --output ./nda-redline-cpor.pdf

Supported options:

  • --variant clean|redline
  • --format original|pdf|docx|html|txt|xml|preprocessed-docx|changed-pages-pdf

Notes:

  • changed-pages-pdf is redline-only.
  • Clean docx is not a separate derived endpoint; use --format original.

Reviews

vs reviews list --repository-id <repository-id>
vs reviews create \
  --repository-id <repository-id> \
  --branch-id <branch-id> \
  --title "Review NDA updates" \
  --description "Please check section 2" \
  --reviewer-user-id <user-1> \
  --reviewer-user-id <user-2>

vs reviews comments --repository-id <repository-id> --review-id <review-id>
vs reviews comment-create \
  --repository-id <repository-id> \
  --review-id <review-id> \
  --document-version-id <version-id> \
  --paragraph-anchor-id <anchor-id> \
  --paragraph-text "selected text" \
  --body "needs update" \
  --comment-type issue

Generic Request Escape Hatch

vs request GET /api/v1/repositories --query organizationId=<id>
vs request POST /api/v1/repositories/<repository-id>/reviews --body-file ./review-create.json

Local State System

The CLI stores local sync metadata at:

  • .versionstory/state.json

It stores only tracked working-file state (not full version history caches).

State shape:

{
  "repositoryId": "uuid",
  "repositoryName": "VS CLI test",
  "branchId": "uuid",
  "branchName": "main",
  "files": [
    {
      "documentId": "uuid",
      "documentName": "NDA.docx",
      "relativePath": "NDAs/NDA.docx",
      "versionId": "uuid",
      "sha256": "hex",
      "preprocessedRelativePath": ".versionstory/preprocessed/NDAs/NDA.docx",
      "preprocessedSourceSha256": "hex",
      "downloadedAt": "2026-03-02T14:00:00.000Z",
      "lastCommittedAt": "2026-03-02T14:15:00.000Z"
    }
  ],
  "initializedAt": "2026-03-02T14:00:00.000Z",
  "lastPulledAt": "2026-03-02T14:00:00.000Z"
}

Behavior:

  • vs init:
    • with --repository-*: creates .versionstory/state.json for a selected repository/branch and performs initial pull.
  • with --name: creates a new Repository, uploads local .doc/.docx/.pdf/.md/.markdown working files as new documents/versions directly to main, then initializes .versionstory/state.json.
  • vs pull: downloads latest versions for documents in the selected branch, overwrites tracked working files, refreshes .versionstory/preprocessed/... cache copies for DOCX-derived files, removes stale previously-tracked files, and rewrites state.json.
  • vs status: reports the current branch plus staged changes, unstaged changes, untracked files, and unpushed local commits.
  • vs read: .docx only. Always reads from cached preprocessed working state. If the tracked working file changed locally, it preprocesses the working file first and refreshes the cached preprocessed state before reading.
  • vs read --search: .docx only. Searches paragraph text in cached preprocessed working state and returns matching paragraph IDs/snippets.
  • vs read --return-ids: .docx only. Without --search, prints document structure IDs for tables, table rows, table cells, and paragraphs from cached preprocessed working state.
  • vs add: stages modified tracked files, tracked deletions, and untracked supported files into the local index.
  • vs commit: creates a local commit from the staged index and updates the local workspace head in state.json without network I/O.
  • vs push: uploads unpushed local commits in order. Normal tracked-file commits use the repository-level commit endpoints. vs edit commits with a redline artifact use the single-document finalize path during push.
  • vs log: shows local unpushed commits first, then remote commits for the current branch.
  • vs branch: lists branches or creates a new branch.
  • vs switch: switches the workspace to another branch and performs a pull, but only when the workspace is clean.
  • vs edit: .docx only. If the tracked working file changed locally, refreshes preprocessed cache and exits with instructions to re-run vs read for fresh UUIDs. Otherwise it validates target IDs, applies tracked edits with the legacy edit-docx tool, accepts revisions into a clean file, stages the result plus redline artifact, creates one local commit automatically, and pushes that commit immediately.

Agent Workflow Example

# 1) Login
vs auth login

# 2) Find Repository and branch
vs repositories list
vs repositories branches --repository-id <repository-id>

# 3) Upload a new version
vs versions upload --document-id <doc-id> --branch-id <branch-id> --file ./contract-v2.pdf

# 4) Poll conversion operations
vs versions operations --version-id <new-version-id>

# 5) Download redline HTML
vs versions download --version-id <new-version-id> --variant redline --format html --output ./redline.html

Exit Codes

  • 0 success
  • 1 any API/client error

Development

npm run dev -- --help
npm run build
npm run build:native
npm run build:all
npm run build:full
bash scripts/build.sh --native

Legacy-style distribution packaging:

  • scripts/build.sh --native now:
  1. builds native edit-docx binaries for all target platforms
  2. prepares platform-specific npm packages in packages/native/<platform>/
  3. builds the CLI TypeScript bundle
  4. runs npm pack to produce the npm package

Native edit-docx Build

Source is now in this repo at:

  • apps/edit-docx/Program.cs
  • apps/edit-docx/edit-docx.csproj

Native build script:

  • scripts/build-native.sh

What it does:

  1. Runs dotnet publish for osx-arm64, osx-x64, linux-x64, win-x64
  2. Uses self-contained single-file publish output
  3. Writes executables to bin/<platform>/edit-docx (or .exe on Windows)
  4. scripts/package-native-packages.sh prepares platform-specific npm packages for distribution

Compatibility note:

  • apps/edit-docx/edit-docx.csproj resolves OpenXmlPowerTools.csproj from VSOXT_PATH.
  • Set VSOXT_PATH to your local version-story-open-xml-tools checkout before running npm run build:native.