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

@deus-hq/sdk

v0.9.1

Published

Deus SDK — run AI coding agents in isolated sandboxes

Readme

@deus-hq/sdk

TypeScript SDK for running AI coding agents (Claude) inside isolated cloud sandboxes.

Install

npm install @deus-hq/sdk

Environment variables

| Variable | Required | Description | |----------|----------|-------------| | DEUS_API_KEY | Yes | Your Deus API key (starts with deus_sk_) | | ANTHROPIC_API_KEY | Yes* | Anthropic API key for the agent (*unless org-level key configured) | | DEUS_BASE_URL | No | API base URL (defaults to https://api.hivenet.app) |

All can also be passed directly to configure() or as options on individual function calls.

Quick start

Level 1: run() — fire-and-forget

One async call. Provisions a sandbox, clones a repo, runs the agent, returns the result.

import { configure, Image, run } from "@deus-hq/sdk";

configure({
  apiKey: process.env.DEUS_API_KEY,
  anthropicApiKey: process.env.ANTHROPIC_API_KEY,
});

const img = Image.from("node-20")
  .repo("acme/backend");  // Also accepts github.com/acme/backend, full URLs, or SSH

const result = await run({
  task: "Add a health-check endpoint at GET /healthz",
  image: img,
});

console.log(result.output);       // Agent's final response
console.log(`$${result.cost.usd}`); // Cost in USD
console.log(result.filesChanged);  // Files modified

RunResult

interface RunResult {
  id: string;             // Session ID
  workspaceId: string;    // Workspace ID
  output: string;         // Agent's final text output
  cost: Cost;             // { inputTokens, outputTokens, usd }
  turns: number;          // Number of agent turns
  duration: number;       // Wall-clock time in milliseconds
  filesChanged: string[]; // Files the agent modified
}

Level 2: stream() — real-time events

Pull-based async iteration over agent events. Supports multi-turn conversations.

import { configure, Image, createWorkspace, createSession, stream } from "@deus-hq/sdk";

configure({
  apiKey: process.env.DEUS_API_KEY,
  anthropicApiKey: process.env.ANTHROPIC_API_KEY,
});

const img = Image.from("node-20").repo("acme/backend");
const handle = await createWorkspace({ image: img });
const session = await createSession({ workspaceId: handle.id });

for await (const event of stream(session, "Fix the failing tests")) {
  switch (event.type) {
    case "message.delta":
      process.stdout.write(event.delta);
      break;
    case "message.complete":
      console.log();
      break;
    case "tool.start":
      console.log(`-> ${event.toolName}(...)`);
      break;
    case "tool.complete":
      console.log(`<- ${event.toolName}: ${event.isError ? "error" : "ok"}`);
      break;
    case "turn.started":
      console.log(`\n--- turn ${event.turnIndex} ---`);
      break;
    case "turn.ended":
      console.log(`Turn ${event.turnIndex} — $${event.cost.usd}`);
      break;
    case "session.complete":
      console.log(`Done — ${event.turns} turns, $${event.totalCost.usd}`);
      break;
    case "session.error":
      console.error(event.error.message);
      break;
  }
}

// Send a follow-up message on the same session
for await (const event of stream(session, "Now add integration tests")) {
  // ...
}

EventStream helpers

stream() returns an EventStream with additional methods:

const events = stream(session, "Add tests");

// Collapse to RunResult (consumes the stream)
const result = await events.result();

// Convert to Web ReadableStream (for SSE endpoints)
const readable = events.toReadableStream();

// Cancel the agent
events.abort();

Level 3: createSessionClient() — reactive UI

Push-based WebSocket client for browser frontends. Maintains full session state with subscribe/notify.

import { createSessionClient, createSessionToken } from "@deus-hq/sdk";

// Server-side: create a short-lived token (don't expose your API key to browsers)
const { token } = await createSessionToken(sessionId);

// Client-side: connect via WebSocket
const client = createSessionClient({
  sessionId,
  token,
  url: "https://api.deus.co",
});

client.subscribe((state) => {
  console.log(`Status: ${state.status}`);
  console.log(`Text: ${state.turn?.text}`);

  if (state.pendingQuestion) {
    client.answerQuestion(
      state.pendingQuestion.questionId,
      state.pendingQuestion.sessionId,
      ["yes"],
    );
  }

  if (state.pendingPermission) {
    client.respondToPermission(
      state.pendingPermission.requestId,
      state.pendingPermission.sessionId,
      { behavior: "allow" },
    );
  }
});

client.connect();
client.send("Fix the bug");

SessionState

interface SessionState {
  connected: boolean;
  status: "connecting" | "provisioning" | "ready" | "running" | "error";
  history: Message[];
  completedTurns: TurnState[];
  turn: TurnState | null;
  pendingQuestion: PendingQuestion | null;
  pendingPermission: PendingPermission | null;
  pendingHook: PendingHook | null;
  error: string | null;
}

Image configuration

Image.from() defines the sandbox VM: what template to use, which repo to clone, packages to install, and setup commands to run during provisioning.

const img = Image.from("node-20")
  .repo("github.com/acme/backend", "main")  // repo + optional branch
  .packages(["postgresql-client"])
  .setup(["npm install", "npm run db:migrate"])
  .env({ DATABASE_URL: "postgres://localhost:5432/test" })
  .timeout(600_000);

const result = await run({ task: "Run the test suite and fix failures", image: img });

Setup phases

Setup commands run in two phases: pre-clone (before the repo is cloned) and post-clone (after — the default). Multiple .setup() calls accumulate in order.

const img = Image.from("node-20")
  .repo("acme/backend")
  .setup("pre-clone", ["setup-credentials.sh"])   // runs before git clone
  .setup(["npm install"])                          // post-clone (default)
  .setup(["npm run db:migrate"]);                  // runs after npm install

Parallel setup

Use .setupParallel() to run independent branches concurrently. Each branch runs its commands sequentially; branches execute in parallel. The next call waits for all branches to finish.

const img = Image.from("node-20")
  .repo("acme/backend")
  .setupParallel(
    ["npm install"],                    // branch 1
    ["pip install -r requirements.txt"], // branch 2 (runs concurrently)
  )
  .setup(["npm run db:migrate"]);       // waits for both branches

// With a phase
Image.from("node-20")
  .setupParallel("pre-clone",
    ["setup-aws.sh"],
    ["setup-gcp.sh"],
  );

Image builder reference

| Method | Description | |--------|-------------| | Image.from(template) | Create from a template (e.g. "node-20") | | .repo(url, branch?) | Repository to clone, with optional branch | | .packages(list) | System packages to install via apt-get | | .setup(commands) | Sequential setup commands (post-clone) | | .setup(phase, commands) | Sequential setup commands in a specific phase | | .setupParallel(...branches) | Parallel branches (post-clone) | | .setupParallel(phase, ...branches) | Parallel branches in a specific phase | | .env(vars) | Environment variables for setup + agent | | .secrets(secrets) | Third-party API secrets (e.g. github_token) | | .timeout(ms) | Sandbox timeout (30s–24h, default 1h) | | .metadata(data) | Arbitrary key-value metadata |

MCP servers

Attach MCP tool servers to the agent:

const img = Image.from("node-20").repo("github.com/acme/backend");

const result = await run({
  task: "Look up the latest issues and fix the top one",
  image: img,
  mcpServers: {
    github: {
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-github"],
      env: { GITHUB_TOKEN: "ghp_..." },
    },
  },
});

Hooks

Intercept agent lifecycle events. Decision hooks (PreToolUse, Stop) block the agent until you respond:

const img = Image.from("node-20").repo("github.com/acme/backend");

const result = await run({
  task: "Refactor the auth module",
  image: img,
  hooks: {
    PreToolUse: (input) => {
      if (input.tool_name === "Bash" && input.tool_input?.command?.includes("rm")) {
        return { allow: false, reason: "Destructive commands are not allowed" };
      }
      return { allow: true };
    },
    Stop: (input) => {
      return { allow: true }; // Let the agent stop
    },
  },
});

Error handling

import { run, isDeusError } from "@deus-hq/sdk";

try {
  const img = Image.from("node-20").repo("github.com/acme/backend");
  await run({ task: "Fix tests", image: img });
} catch (err) {
  if (isDeusError(err)) {
    console.error(`[${err.code}] ${err.message}`);
    // err.code: "MISSING_API_KEY" | "API_ERROR" | "TIMEOUT" | "ABORTED"
    // err.statusCode: HTTP status (if from API)
  }
}

During streaming, errors arrive as events:

for await (const event of stream(session, "Fix tests")) {
  if (event.type === "session.error") {
    console.error(event.error.message);
    if (!event.recoverable) break;
  }
}

Workspace management

import {
  Image,
  createWorkspace,
  listWorkspaces,
  stopWorkspace,
  deleteWorkspace,
} from "@deus-hq/sdk";

const img = Image.from("node-20").repo("github.com/acme/backend");
const handle = await createWorkspace({ image: img });

const { items } = await listWorkspaces({ status: "active", limit: 10 });

await stopWorkspace(handle.id);    // Pause the sandbox
await deleteWorkspace(handle.id);  // Permanently remove

License

MIT