Appendix E — The rs2 CLI command reference

The rs2 CLI covers the developer loop plus a small set of admin/ops tasks. It is not a general API client — use plain HTTP for everything outside these commands. Run it as the installed rs2 binary or cargo run -p rs2-cli -- <args>.

Verbs

Command Does
rs2 new <name> [--js] Scaffold a custom-service project. Default Rust/Wasm against the published WIT (compiles as-is with cargo build --target wasm32-wasip2 --release); --js is a single-file ESM scaffold with manifest.json
rs2 dev [serverConfig.json] Run a local node (same code as rs2-server)
rs2 test [projectDir] [--component <path>] Validate manifest.json and the built component (wasm header; engine compile-check when built --features wasm)
rs2 deploy <file> --name <n> [--server <url>] [--token <t>] [--bundle] Keyless POST to <server>/code/<n>/; the content-addressed store derives the version. .js/.mjs → JS bundle; \0asm → component. --bundle runs npx esbuild … --bundle --format=esm --platform=browser first
`rs2 template build <entry.jsx tsx> [--out ]`
rs2 migrate <services.json> [-o tenant.json] Convert a v1 Restspace config to an RS2 tenant config (Part 11)
rs2 login [--host <url>] [--email <e>] [--password <p>] Log in through /auth/login and save the token, expiry, and issuing host to rsconfig.json
rs2 send <path> --file <local> [--content-type <ct>] PUT one local file to the configured host; content type is inferred when omitted; uses a saved valid token when present
rs2 service add <mount.json> [--path <p>] ETag-safe read/append/write of one new mount; refuses an occupied path
rs2 service set-access <path> --access <json> [--set k=v]… ETag-safe update of an existing mount's access and optional config keys
rs2 auth init --admin-email <e> [options] One-shot auth bootstrap on a fresh open node: enable auth, create/login first admin, lock user store and services mount
rs2 auth enable [options] Idempotently add auth settings/mount and temporarily open a user store for bootstrap
rs2 auth create-admin --email <e> [options] Hash a password locally and seed the first operator while that user store is open; skips an existing visible record
rs2 pull [--host <url>] [--dir <d>] Mirror the tenant's instruction plane (config + every specSubtree store + code pins) into a local rs2/ directory for git-based editing; records baseline ETags in rs2/mirror.json (§3.6)
rs2 push [--dir <d>] [--dry-run] [--allow-secret-rotation] Push local instruction-plane edits back through the validated APIs (config If-Match, spec If-Match/412); aborts on a remote change rather than clobbering. --dry-run shows the diff; refuses a real secret value in a "<secret>" slot without --allow-secret-rotation
rs2 run <script> Run one rs2 command per line, skipping blanks/comments and aborting on the first failure; dev is rejected because it never returns

rsconfig.json

The admin commands walk upward from the current directory to the nearest rsconfig.json:

{
  "host": "https://api.example.com",
  "login": { "email": "admin@example.com" },
  "auth": { "token": "<jwt>", "exp": 1799999999,
            "host": "https://api.example.com" }
}

login writes auth; other commands reuse it only while it is unexpired and matches host. Prefer RS2_PASSWORD (or the command flag) to storing login.password in this file. send and service add also work anonymously when the server's access policy permits it, which is useful during first-node bootstrap.

rs2 deploy flags

Flag Default Notes
--name <n> The bundle name in the code store
--server <url> http://127.0.0.1:3100/services The services API base
--token <t> Bearer token for a protected services mount
--bundle off esbuild the entry first (Node.js on PATH required)

Typical workflows

A new JS service:

rs2 new my-svc --js
# edit my-svc/…
rs2 deploy my-svc/entry.ts --name my-svc --bundle --token $admin
# then mount code:my-svc@<version> via PUT /services/raw

A new Wasm service:

rs2 new my-svc
cargo build --target wasm32-wasip2 --release
rs2 test my-svc
rs2 deploy target/wasm32-wasip2/release/my_svc.wasm --name my-svc

Bootstrap a fresh node, then make a small change:

rs2 auth init --admin-email admin@example.com
rs2 service add notes.mount.json --path /notes
rs2 send /notes/welcome.txt --file .\welcome.txt

For a multi-file/versioned config change, use rs2 pull, edit the local rs2/ mirror, inspect rs2 push --dry-run, then push. The mirror contains config, specs, and code pins — not data, site assets, or bundle bytes.

Migrate from v1:

rs2 migrate services.json -o tenant.json
# read the warnings; follow the post-migration checklist (11.3)

Windows notes

  • --bundle shells to npx (npx.cmd) — Node.js must be on PATH.
  • JSON files the CLI reads tolerate UTF-8 BOMs (PowerShell -Encoding utf8 adds one).
  • For scripting HTTP against a running node, prefer Invoke-RestMethod with ConvertTo-Json bodies, or curl.exe — PowerShell 5.1 mangles inline JSON quotes in some contexts.

Appendix D — Default limits · Manual home · Next: Appendix F — Further reading →