rivet-dev/sanity-check
Run the deferred AgentOS E2E smoke test from public npm packages. Use when the user asks to sanity check, smoke test, or verify a release works.
npx skills add https://github.com/rivet-dev/rivet --skill sanity-check
This is a P6/full-validation check. It installs from npm in a fresh project,
boots an AgentOS VM, spawns a Pi agent session, writes a file, reads it back,
and verifies the contents.
/sanity-check — run in a temp directory on the host/sanity-check docker — run inside a node:22 Docker container/sanity-check <custom instructions> — extra instructions, such as "use rc.3", "use pnpm", or "test on node 20"npm install of @rivet-dev/agentos-core, @rivet-dev/agentos-pi, @agentos-software/common from the public npm registry/tmp/test.txt with "Hello from Agent OS!" and the bash tool to run cat /tmp/test.txtvm.readFile()ANTHROPIC_API_KEY must be set in the environment. If not set, load it from ~/misc/env.txt.node:22 image)Create a temp directory (e.g. /tmp/agentos-sanity-XXXX) with two files:
package.json:
{
"name": "agentos-sanity-check",
"private": true,
"type": "module",
"dependencies": {
"@rivet-dev/agentos-core": "*",
"@rivet-dev/agentos-pi": "*",
"@agentos-software/common": "*",
"@mariozechner/pi-coding-agent": "^0.60.0",
"@agentclientprotocol/sdk": "^0.16.1"
}
}
If the user specifies a version (e.g. "use rc.3"), pin @rivet-dev/agentos-core and @rivet-dev/agentos-pi to that version.
test.mjs:
import { AgentOs } from "@rivet-dev/agentos-core";
import common from "@agentos-software/common";
import pi from "@rivet-dev/agentos-pi";
const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
if (!ANTHROPIC_API_KEY) {
console.error("ANTHROPIC_API_KEY is required");
process.exit(1);
}
console.log("Creating VM with common + pi...");
const vm = await AgentOs.create({ software: [common, pi] });
console.log("Creating PI agent session...");
const { sessionId } = await vm.createSession("pi", {
env: { ANTHROPIC_API_KEY },
});
console.log(`Session created: ${sessionId}`);
vm.onSessionEvent(sessionId, (event) => {
const params = event.params;
if (params?.update?.sessionUpdate === "agent_message_chunk") {
process.stdout.write(params.update.content?.text ?? "");
}
});
console.log("\nSending prompt...");
const response = await vm.prompt(
sessionId,
'Write the text "Hello from Agent OS!" to /tmp/test.txt using the write tool. Then use the bash tool to run `cat /tmp/test.txt` and tell me what it says.',
);
console.log(`\n\nPrompt completed: ${response.stopReason}`);
console.log("\nVerifying file...");
try {
const data = await vm.readFile("/tmp/test.txt");
const text = new TextDecoder().decode(data);
console.log(`File contents: "${text.trim()}"`);
if (text.includes("Hello from Agent OS!")) {
console.log("\n✅ E2E TEST PASSED");
} else {
console.log("\n❌ E2E TEST FAILED: wrong content");
process.exit(1);
}
} catch (err) {
console.log(`\n❌ E2E TEST FAILED: ${err.message}`);
process.exit(1);
}
vm.closeSession(sessionId);
await vm.dispose();
Default (temp dir on host):
cd /tmp/agentos-sanity-XXXX
npm install
node test.mjs
Docker mode:
docker run --rm \
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
-v /tmp/agentos-sanity-XXXX:/app \
-w /app \
node:22 \
bash -c "npm install && timeout 120 node test.mjs"
✅ E2E TEST PASSEDRemove the temp directory after the test completes.
docker run --rm before removing the host temp dir.@rivet-dev/agentos-core and @agentos-software/common in the output.Take rivet-dev/sanity-check from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference npm, docker.
Without those the skill loads but fails at the first command.