Agent skill

Sanity Check

Run an E2E smoke test that installs rivetkit packages from npm in an isolated temp project, starts the hello-world counter actor, then verifies both HTTP actions and WebSocket actions + events work end-to-end. Use when the user asks to sanity check, smoke test, or verify a rivetkit release/preview-publish works.

Get started

Get the complete skill folder, including its scripts and reference files.

·

When to use this skill

Use Sanity Check when an AI agent needs a reusable SKILL.md workflow for this job: Run an E2E smoke test that installs rivetkit packages from npm in an isolated temp project, starts the hello-world counter actor, then verifies both HTTP actions and WebSocket actions + events work end-to-end. Use when the user asks to sanity check, smoke test, or verify a rivetkit release/preview-publish works.

When not to use it

Skip Sanity Check when the task is outside the coding category, or when a more specific skill in this directory already covers the same workflow with clearer triggers.

How to install

  1. Claude Code personal install: place the skill and its bundled files at ~/.claude/skills/sanity-check/SKILL.md. For a shared project, commit the folder at .claude/skills/sanity-check/ instead.
  2. Current Claude Code detects SKILL.md changes in watched directories during the session. If you just created a top-level skills directory, run /reload-skills. Check that the skill is listed before testing its trigger.
  3. For Claude chat or Cowork in the Desktop app, manage uploaded skills in Customize > Skills; copying files into a local Claude Code folder is not a Desktop install. Other agents may use different install locations.

Full install guide for Claude, Cursor, and Codex

What supports this recommendation?

83/100 provisional content score. This measures documentation, practical detail and source signals. It is not a measured task success rate or a security certification.

Documentation
92/100
Practical detail
92/100
Source evidence
63/100
Source signals
72/100
Model compatibility evidence
  • claude · inferred

    The skill text mentions Claude or a closely associated term. This is keyword-derived compatibility; no hands-on model test is recorded.

  • chatgpt · untested

    No model-specific signal or recorded compatibility test was found.

  • gemini · untested

    No model-specific signal or recorded compatibility test was found.

  • copilot · untested

    No model-specific signal or recorded compatibility test was found.

  • llama · untested

    No model-specific signal or recorded compatibility test was found.

  • perplexity · untested

    No model-specific signal or recorded compatibility test was found.

  • mistral · untested

    No model-specific signal or recorded compatibility test was found.

  • grok · untested

    No model-specific signal or recorded compatibility test was found.

Inferred compatibility is based on content signals. Check the app, its available tools and setup requirements before running a skill.

What this skill does

# Sanity Check

Run a quick end-to-end sanity check of a published rivetkit version: copy the hello-world example to a temp directory, install the specified package version from the public npm registry, start the dev server, and run a client test script that verifies both HTTP actions and WebSocket connections with event broadcasting.

## When to use - User wants to verify a published rivetkit version works (e.g., `[email protected]`, `rivetkit@latest`, `[email protected]`) - After a preview publish to verify the build is functional - After a release to verify the package installs and runs correctly - User says "sanity check", "smoke test", "verify the build", or "test this version"

## Inputs 1. **Version or tag** (required) — explicit pkg-pr-new preview, npm dist-tag, or semver. If not provided in the user's message, ask for it. 2. **Additional test behavior** (optional) — e.g., "also verify workflows persist" or "check that KV works." If provided, extend `src/index.ts` + `test.mjs` using the menu in "Extending with custom tests" below.

## Usage - `/sanity-check <version>` — run in a temp directory on the host - `/sanity-check docker <version>` — run inside a `node:22` Docker container - `/sanity-check <version> <custom instructions>` — any extra instructions (e.g. "also hit a KV action", "verify state persists across restart", "use pnpm", "test on node 20")

`<version>` is any npm-resolvable spec: an explicit pkg-pr-new preview (`0.0.0-pr.4701.a818b77`), an npm dist-tag (`latest`, `rc`, `next`), or a semver (`2.3.0-rc.4`). If the user omits it, ask for it.

## What it tests

1. `npm install` of `rivetkit`, `@rivetkit/react`, and the platform-specific `@rivetkit/rivetkit-napi-*` native binding from the public npm registry 2. Boot the hello-world counter actor server via `registry.start()` on port 6420 3. **HTTP path**: call `counter.increment(5)`, `counter.increment(3)`, `counter.getCount()` and assert the values 4. **WebSocket path**: open a `.connect()` conn, subscribe to the `newCount` event, call `increment(10)`, assert the action response AND the broadcast event value match 5. Report the resolved versions of `rivetkit` + `@rivetkit/rivetkit-napi`

## Requirements

- Node.js 22+ (or Docker with `node:22`) - This repo available locally — only used to copy `examples/hello-world/src/` as the seed. Does NOT use any of its `node_modules` or workspace links.

## Steps

### 1. Set up the test project

```bash REPO_ROOT=$(git rev-parse --show-toplevel) SANITY_DIR=$(mktemp -d /tmp/rivetkit-sanity-XXXXXX) cp -r "$REPO_ROOT/examples/hello-world/src" "$REPO_ROOT/examples/hello-world/tsconfig.json" "$SANITY_DIR/" cd "$SANITY_DIR" ```

Write `package.json` with `<VERSION>` substituted:

```json { "name": "rivetkit-sanity", "private": true, "type": "module", "dependencies": { "rivetkit": "<VERSION>", "@rivetkit/react": "<VERSION>" }, "devDependencies": { "tsx": "^4", "typescript": "^5" } } ```

For pkg-pr-new previews, `<VERSION>` can be the bare version string (`0.0.0-pr.4701.a818b77`) — npm resolves it directly. If that fails, fall back to the URL form: `"rivetkit": "https://pkg.pr.new/rivet-dev/rivet/rivetkit@<short-sha>"`.

### 2. Write `test.mjs`

```js import { createClient } from "rivetkit/client"; import { spawn } from "node:child_process";

const ENDPOINT = "http://localhost:6420";

console.log("Starting counter actor server..."); const server = spawn("npx", ["tsx", "src/index.ts"], { stdio: ["ignore", "pipe", "pipe"], }); let log = ""; server.stdout.on("data", (d) => (log += d)); server.stderr.on("data", (d) => (log += d));

async function waitForServer(timeoutMs = 30000) { const deadline = Date.now() + timeoutMs; while (Date.now() < deadline) { try { const r = await fetch(`${ENDPOINT}/health`); if (r.ok) return; } catch {} await new Promise((r) => setTimeout(r, 500)); } console.error("--- server log ---\n" + log); throw new Error("server did not become ready"); }

let exitCode = 0; try { await waitForServer(); const client = createClient(ENDPOINT);

// --- HTTP actions --- console.log("Testing HTTP actions..."); const counter = client.counter.getOrCreate(["sanity"]); const a = await counter.increment(5); const b = await counter.increment(3); const c = await counter.getCount(); if (a !== 5) throw new Error(`increment(5) => ${a}, expected 5`); if (b !== 8) throw new Error(`increment(3) => ${b}, expected 8`); if (c !== 8) throw new Error(`getCount() => ${c}, expected 8`); console.log(` HTTP: increment(5)=${a}, increment(3)=${b}, getCount()=${c}`);

// --- WebSocket actions + events --- console.log("Testing WebSocket + events..."); const ws = client.counter.getOrCreate(["sanity-ws"]).connect(); await new Promise((res, rej) => { const t = setTimeout(() => rej(new Error("ws open timeout")), 10000); ws.onOpen(() => { clearTimeout(t); res(); }); ws.onError(rej); }); const eventPromise = new Promise((res, rej) => { const t = setTimeout(() => rej(new Error("newCount event timeout")), 5000); ws.on("newCount", (v) => { clearTimeout(t); res(v); }); }); const wsCount = await ws.increment(10); const eventValue = await eventPromise; if (wsCount !== 10) throw new Error(`ws increment(10) => ${wsCount}, expected 10`); if (eventValue !== 10) throw new Error(`newCount event => ${eventValue}, expected 10`); console.log(` WS: increment(10)=${wsCount}, event=${eventValue}`); await ws.dispose();

console.log("\n✅ E2E TEST PASSED"); } catch (err) { console.error(`\n❌ E2E TEST FAILED: ${err.message || err}`); console.error("--- server log (last 2KB) ---\n" + log.slice(-2000)); exitCode = 1; } finally { server.kill("SIGKILL"); process.exit(exitCode); } ```

### 3. Install + run

**Default (host):** ```bash cd "$SANITY_DIR" npm install node test.mjs ```

If you need to inspect a failure after the fact, tee the output: ```bash node test.mjs 2>&1 | tee /tmp/sanity-check.log echo "exit=$?" ```

**Docker mode:** ```bash docker run --rm \ -v "$SANITY_DIR":/app \ -w /app \ node:22 \ bash -c "npm install && timeout 120 node test.mjs" ```

### 4. Report installed versions

Surface the resolved versions (rivetkit's `exports` doesn't expose `./package.json`, so read the file directly):

```bash node -e " for (const p of ['rivetkit','@rivetkit/react','@rivetkit/rivetkit-napi']) { try { const v = JSON.parse(require('fs').readFileSync('node_modules/'+p+'/package.json','utf8')).version; console.log(p, v); } catch (e) { console.log(p, '(not installed:', e.code || e.message, ')'); } } " ```

### 5. Report results

Tell the user: - Resolved versions (rivetkit + @rivetkit/rivetkit-napi) - HTTP path results - WebSocket path results + event value - ✅ or ❌ with the last 2KB of server log on failure

### 6. Clean up

```bash rm -rf "$SANITY_DIR" ```

## Extending with custom tests

If the user asks for extra behavior, modify `src/index.ts` and add assertions to `test.mjs` before running. Common asks and where to slot them:

- **KV round-trip**: add `kv` actions (`setKv: (c, key, val) => c.kv.set(key, val)`, `getKv: (c, key) => c.kv.get(key)`), then in test.mjs call set → get and assert. - **Workflow**: add a workflow action, await its completion, assert the final state. - **SQLite + migrations**: add a migration and a query action, call it, assert rows. - **State persistence**: increment, kill the server (`server.kill("SIGTERM")`), await exit, respawn, call `getCount()`, assert value preserved. - **Multiple actor instances**: use different keys, verify isolation.

Start from the base test above; layer additions rather than rewriting it.

## Rules - Always use a fresh temp directory — never run in the repo itself. - Always install from the public npm registry or pkg-pr-new — never use local workspace links / `file:` deps. - Pin `rivetkit` + `@rivetkit/react` to the exact user-specified version; let npm's `optionalDependencies` resolve the right `@rivetkit/rivetkit-napi-<platform>` binary automatically. - If `npm install` fails to resolve a bare pkg-pr-new version string, retry using the `https://pkg.pr.new/rivet-dev/rivet/<pkg>@<short-sha>` URL form. - If the server doesn't reach `/health` in 30s, dump the last 2KB of server stderr/stdout before failing — most install/runtime issues show up there (missing native binary, wrong Node version, port collision). - On Docker mode, run `rm -rf $SANITY_DIR` only after `docker run --rm` exits so container-created `node_modules` get cleaned by the `--rm` flag.

Try it, then tell us how it went

A copied prompt does not tell us whether the task worked. Report your result after checking the output. We collect your tool and outcome, never your files or prompt.

Open your saved library

Intended uses

  • User wants to verify a published rivetkit version works (e.g., [email protected], rivetkit@latest, [email protected])
  • After a preview publish to verify the build is functional
  • After a release to verify the package installs and runs correctly
  • User says "sanity check", "smoke test", "verify the build", or "test this version"

Related skills

Related skills in this directory, for comparison before you install another skill.

coding

Agent skill

Add Ave Record

The main workflow for this repo. Adds one new AVE record end to end.

Content score 65/100 · provisional

View skill

coding

Agent skill

Add Backend

Guide for adding a backend (Rust or Python) to the agent-sec-core security middleware. Use when creating new backends, integrating Rust or Python code into the security middleware, or extending with new backend actions.

Content score 70/100 · provisional

View skill

Ranked Claude skills