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 🙏

© 2025 – Pkg Stats / Ryan Hefner

jupyterhub

v1.0.5

Published

A comprehensive TypeScript SDK for JupyterHub - manage users, servers, files, kernels, and execute notebooks

Readme

JupyterHub SDK

A comprehensive TypeScript SDK for JupyterHub - manage users, servers, files, kernels, terminals, and execute notebooks programmatically.

Installation

pnpm add jupyterhub
# or
npm install jupyterhub
# or
yarn add jupyterhub

Requirements

  • Node.js >= 18.0.0
  • A running JupyterHub instance
  • An API token with appropriate permissions

Quick Start

import { JupyterHubClient } from "jupyterhub";

const client = new JupyterHubClient({
  baseUrl: "https://jupyterhub.example.com",
  token: "your-api-token",
});

// List users
const users = await client.hub.users.list();

// Start a server
await client.hub.servers.start("username");

// Work with files
const server = client.server("username");
const files = await server.contents.list("/");
await server.contents.writeFile("/hello.txt", "Hello World!");

// Execute code in a kernel
const result = await server.executeCode('print("Hello!")', "python3");

// Run shell commands in a terminal
const cmdResult = await server.runCommand("ls -la");

// Run a notebook
const output = await server.runNotebook("/analysis.ipynb");

Configuration Options

const client = new JupyterHubClient({
  // Required
  baseUrl: "https://jupyterhub.example.com",
  token: "your-api-token",

  // Optional
  timeout: 30000, // Request timeout in ms (default: 30000)
  retries: 3, // Number of retry attempts (default: 3)
  rejectUnauthorized: false, // Set to false for self-signed certificates (default: false)
});

Features

Hub API

Manage JupyterHub resources at the hub level.

Users

// List all users
const users = await client.hub.users.list();

// List users with pagination
const pagedUsers = await client.hub.users.list({ offset: 0, limit: 50 });

// Get a specific user
const user = await client.hub.users.get("username");

// Create a new user
await client.hub.users.create({ name: "newuser", admin: false });

// Create multiple users
await client.hub.users.createMany(["user1", "user2", "user3"]);

// Modify a user
await client.hub.users.modify("username", { admin: true });

// Delete a user
await client.hub.users.delete("username");

// Get current user (based on token)
const me = await client.hub.users.me();

// Get user activity
const activity = await client.hub.users.getActivity("username");

Groups

// List all groups
const groups = await client.hub.groups.list();

// Get a specific group
const group = await client.hub.groups.get("data-scientists");

// Create a group
await client.hub.groups.create({ name: "data-scientists" });

// Add users to a group
await client.hub.groups.addUsers("data-scientists", ["alice", "bob"]);

// Remove a user from a group
await client.hub.groups.removeUser("data-scientists", "alice");

// Set group properties
await client.hub.groups.setProperties("data-scientists", {
  description: "Data science team",
});

// Delete a group
await client.hub.groups.delete("data-scientists");

Servers

// Start a user's default server
await client.hub.servers.start("username");

// Start with options
await client.hub.servers.start("username", {
  user_options: { profile: "gpu" },
});

// Start a named server
await client.hub.servers.startNamed("username", "gpu-server");

// Wait for server to be ready
await client.hub.servers.waitForReady("username");
await client.hub.servers.waitForReady("username", "named-server", {
  timeout: 120000,
  pollInterval: 1000,
});

// Check if server is ready
const ready = await client.hub.servers.isReady("username");

// Get server status
const status = await client.hub.servers.getStatus("username");

// Stop a server
await client.hub.servers.stop("username");

// Stop a named server
await client.hub.servers.stopNamed("username", "gpu-server");

// Start and wait helper
const server = await client.startServerAndWait("username", {
  serverName: "my-server",
  userOptions: { profile: "large" },
  timeout: 120000,
});

Tokens

// List tokens for a user
const tokens = await client.hub.tokens.list("username");

// Create a new token
const token = await client.hub.tokens.create("username", {
  note: "API access",
  expires_in: 3600, // seconds
  scopes: ["read:users", "servers"],
});

// Get token info
const tokenInfo = await client.hub.tokens.get("username", "token-id");

// Revoke a token
await client.hub.tokens.revoke("username", "token-id");

Services

// List all services
const services = await client.hub.services.list();

// Get a specific service
const service = await client.hub.services.get("service-name");

Proxy Routes

// List all proxy routes
const routes = await client.hub.proxy.list();

// Add a route
await client.hub.proxy.add("/custom-path", {
  target: "http://localhost:8080",
});

// Remove a route
await client.hub.proxy.remove("/custom-path");

Hub Information

// Get hub version
const version = await client.getVersion();

// Get hub info
const info = await client.hub.getInfo();

Server API

Work with a user's running Jupyter server.

Contents (Files & Directories)

const server = client.server("username");

// List directory contents
const files = await server.contents.list("/");

// List with options
const items = await server.contents.list("/", { type: "notebook" });

// Check if file exists
const exists = await server.contents.exists("/notebook.ipynb");

// Read a text file
const content = await server.contents.read("/script.py");

// Read a notebook
const notebook = await server.contents.readNotebook("/analysis.ipynb");

// Get file info without content
const info = await server.contents.getInfo("/large-file.csv");

// Write a text file
await server.contents.writeFile("/data.txt", "Hello World");

// Write a notebook
await server.contents.writeNotebook("/new.ipynb", notebookContent);

// Create a directory
await server.contents.createDirectory("/new-folder");

// Create nested directories
await server.contents.createDirectory("/path/to/nested/folder");

// Rename/move a file
await server.contents.rename("/old-name.txt", "/new-name.txt");

// Copy a file
await server.contents.copy("/source.txt", "/destination-folder");

// Delete a file or directory
await server.contents.delete("/file-to-delete.txt");

// Upload binary data
const data = new Uint8Array([...]);
await server.contents.upload("/image.png", data);

// Download a file as binary
const binary = await server.contents.download("/image.png");

// Create/update checkpoints
const checkpoint = await server.contents.createCheckpoint("/notebook.ipynb");
const checkpoints = await server.contents.listCheckpoints("/notebook.ipynb");
await server.contents.restoreCheckpoint("/notebook.ipynb", checkpoint.id);
await server.contents.deleteCheckpoint("/notebook.ipynb", checkpoint.id);

Kernels

Manage and interact with Jupyter kernels.

Kernel Management

const server = client.server("username");

// List running kernels
const kernels = await server.kernels.list();

// Start a new kernel
const kernel = await server.kernels.start({ name: "python3" });

// Start with path context
const kernel = await server.kernels.start({
  name: "python3",
  path: "/notebooks",
});

// Get kernel info
const kernelInfo = await server.kernels.get(kernel.id);

// Wait for kernel to be ready
await server.kernels.waitForReady(kernel.id, {
  timeout: 30000,
  pollInterval: 500,
});

// Check if kernel is ready
const ready = await server.kernels.isReady(kernel.id);

// Restart a kernel
await server.kernels.restart(kernel.id);

// Interrupt a kernel
await server.kernels.interrupt(kernel.id);

// Shutdown a kernel
await server.kernels.shutdown(kernel.id);

// Shutdown all kernels
await server.kernels.shutdownAll();

Kernel Connection (WebSocket)

const server = client.server("username");

// Get or create a kernel with connection
const { kernel, connection, created } = await server.getOrCreateKernel("python3");

// Connect to the kernel
await connection.connect();

// Execute code
const result = await connection.execute('print("Hello World")');
console.log(result.outputs);

// Execute with options
const result = await connection.execute("import time; time.sleep(2)", {
  timeout: 10000,
  silent: false,
  storeHistory: true,
  stopOnError: true,
});

// Get code completions
const completions = await connection.complete("prin", 4);
console.log(completions.matches); // ['print']

// Get documentation/inspection
const docs = await connection.inspect("print", 5, 1);
console.log(docs.data);

// Get kernel info
const kernelInfo = await connection.kernelInfo();

// Listen for events
const unsubscribe = connection.on((event) => {
  switch (event.type) {
    case "connected":
      console.log("Connected to kernel");
      break;
    case "disconnected":
      console.log("Disconnected:", event.reason);
      break;
    case "status":
      console.log("Kernel status:", event.state);
      break;
    case "message":
      console.log("Message:", event.message);
      break;
    case "error":
      console.error("Error:", event.error);
      break;
  }
});

// Check connection status
console.log("Connected:", connection.isConnected);
console.log("Execution state:", connection.executionState);

// Disconnect when done
connection.disconnect();

// Clean up
await server.kernels.shutdown(kernel.id);

Direct Kernel Connection

import { createKernelConnection } from "jupyterhub";

// Create connection manually
const connection = createKernelConnection({
  url: "wss://jupyterhub.example.com/user/alice/api/kernels/kernel-id/channels",
  token: "your-token",
  timeout: 30000,
  rejectUnauthorized: false,
});

await connection.connect();
// ... use connection
connection.disconnect();

Terminals

Manage and interact with Jupyter terminals for shell access.

Terminal Management

const server = client.server("username");

// List all terminals
const terminals = await server.terminals.list();

// Create a new terminal
const terminal = await server.terminals.create();

// Create with options
const terminal = await server.terminals.create({ cwd: "/home/jovyan" });

// Get terminal info
const info = await server.terminals.get(terminal.name);

// Delete a terminal
await server.terminals.delete(terminal.name);

// Delete all terminals
await server.terminals.deleteAll();

// Get or create a terminal
const { terminal, created } = await server.terminals.getOrCreate();

Running Commands (High-Level)

The easiest way to run shell commands:

const server = client.server("username");

// Run a single command (auto-creates/cleans up terminal)
const result = await server.runCommand("ls -la");
console.log(result.output);
console.log(result.completed); // true if command finished

// Run with options
const result = await server.runCommand("python script.py", {
  timeout: 60000,
  waitForCompletion: true,
  promptPattern: /\$\s*$/, // Custom prompt pattern
});

// Run multiple commands in sequence
const results = await server.runCommands(["cd /home/jovyan", "pwd", "ls -la"]);
results.forEach((r, i) => console.log(`Command ${i}:`, r.output));

// Run command in specific terminal (no cleanup)
const result = await server.terminals.executeCommand("echo hello", {
  terminalName: "terminal-1",
  cleanup: false,
});

// Run multiple commands in specific terminal
const results = await server.terminals.executeCommands(["pip install numpy", "python -c 'import numpy; print(numpy.__version__)'"], {
  terminalName: "terminal-1",
  timeout: 120000,
});

Terminal Connection (WebSocket)

For interactive terminal sessions:

const server = client.server("username");

// Get or create a terminal with connection
const { terminal, connection, created } = await server.getOrCreateTerminal();

// Connect
await connection.connect();

// Send raw input
connection.send("echo hello\r");

// Send a command (auto-appends newline)
connection.sendCommand("ls -la");

// Run command and wait for output
const result = await connection.runCommand("pwd");
console.log(result.output);

// Run with options
const result = await connection.runCommand("python long_script.py", {
  timeout: 120000,
  waitForCompletion: true,
  promptPattern: /\$\s*$/,
});

// Listen for output
const unsubscribe = connection.on((event) => {
  switch (event.type) {
    case "connected":
      console.log("Connected to terminal");
      break;
    case "output":
      console.log("Output:", event.data);
      break;
    case "disconnected":
      console.log("Disconnected");
      break;
    case "error":
      console.error("Error:", event.error);
      break;
  }
});

// Get accumulated output
console.log(connection.getOutput());

// Clear output buffer
connection.clearOutput();

// Resize terminal
connection.resize(24, 80);

// Check connection status
console.log("Connected:", connection.isConnected);

// Disconnect
connection.disconnect();

// Clean up
if (created) {
  await server.terminals.delete(terminal.name);
}

Direct Terminal Connection

import { createTerminalConnection } from "jupyterhub";

// Create connection manually
const connection = createTerminalConnection({
  url: "wss://jupyterhub.example.com/user/alice/terminals/websocket/1",
  token: "your-token",
  timeout: 30000,
  rejectUnauthorized: false,
});

await connection.connect();
const result = await connection.runCommand("whoami");
console.log(result.output);
connection.disconnect();

Sessions

Manage notebook sessions (notebook + kernel associations).

const server = client.server("username");

// List all sessions
const sessions = await server.sessions.list();

// Create a session
const session = await server.sessions.create({
  path: "/notebook.ipynb",
  name: "notebook.ipynb",
  type: "notebook",
  kernel: { name: "python3" },
});

// Get a specific session
const session = await server.sessions.get(sessionId);

// Get or create a session for a notebook
const session = await server.sessions.getOrCreate("/notebook.ipynb", "python3");

// Modify a session
await server.sessions.modify(sessionId, {
  path: "/new-path.ipynb",
  kernel: { name: "python3" },
});

// Delete a session
await server.sessions.delete(sessionId);

// Delete all sessions
await server.sessions.deleteAll();

Kernel Specifications

Get information about available kernels.

const server = client.server("username");

// List all available kernels
const specs = await server.kernelspecs.list();
console.log(specs.default); // Default kernel name
console.log(specs.kernelspecs); // All available kernels

// Get the default kernel spec
const defaultSpec = await server.kernelspecs.getDefault();

// Get a specific kernel spec
const pythonSpec = await server.kernelspecs.get("python3");

// Find kernels by language
const pythonKernels = await server.kernelspecs.findByLanguage("python");
const rKernels = await server.kernelspecs.findByLanguage("R");

Code Execution

Execute code directly without managing kernels manually.

const server = client.server("username");

// Simple code execution
const result = await server.executeCode('print("Hello World")', "python3");
console.log(result.outputs);

// With timeout
const result = await server.executeCode("import time; time.sleep(5)", "python3", {
  timeout: 10000,
});

// Complex execution
const result = await server.executeCode(
  `
import pandas as pd
import numpy as np

df = pd.DataFrame({
    'a': np.random.randn(100),
    'b': np.random.randn(100)
})

print(df.describe())
df.head()
`,
  "python3"
);

// Handle outputs
result.outputs.forEach((output) => {
  switch (output.output_type) {
    case "stream":
      console.log(`${output.name}: ${output.text}`);
      break;
    case "execute_result":
      console.log("Result:", output.data);
      break;
    case "display_data":
      console.log("Display:", output.data);
      break;
    case "error":
      console.error(`${output.ename}: ${output.evalue}`);
      console.error(output.traceback.join("\n"));
      break;
  }
});

Notebook Execution

Run entire notebooks programmatically.

const server = client.server("username");

// Run a notebook from file
const result = await server.runNotebook("/analysis.ipynb");

// Run with options
const result = await server.runNotebook("/analysis.ipynb", {
  kernelName: "python3",
  stopOnError: true,
  saveOutput: true,
  cellTimeout: 300000, // 5 min per cell
  notebookTimeout: 3600000, // 1 hour total
  onCellComplete: (index, cellResult) => {
    console.log(`Cell ${index} completed:`, cellResult.status);
  },
});

// Check results
console.log(`Success: ${result.success}`);
console.log(`Execution time: ${result.execution_time}ms`);
console.log(`Cells executed: ${result.cells.length}`);

// Handle errors
if (!result.success && result.error) {
  console.error(`Error in cell ${result.error.cell_index}:`);
  console.error(`${result.error.error.name}: ${result.error.error.value}`);
}

// Access the executed notebook
const executedNotebook = result.notebook;

Create and Run Notebooks Programmatically

// Create a notebook
const notebook = client.createNotebook([
  { type: "markdown", source: "# My Analysis" },
  { type: "code", source: 'print("Hello World")' },
  { type: "code", source: "import pandas as pd\ndf = pd.DataFrame({'a': [1,2,3]})\ndf" },
]);

// Save it
const server = client.server("username");
await server.contents.writeNotebook("/generated.ipynb", notebook);

// Run it
const result = await server.runNotebook("/generated.ipynb", { saveOutput: true });

Named Servers

Work with named servers for multi-server setups.

// Start a named server
await client.hub.servers.startNamed("username", "gpu-server", {
  user_options: { profile: "gpu" },
});

// Wait for it
await client.hub.servers.waitForReady("username", "gpu-server");

// Get server API for named server
const server = client.namedServer("username", "gpu-server");

// Work with it like any other server
const files = await server.contents.list("/");
await server.executeCode('print("Running on GPU server")', "python3");

// Stop it
await client.hub.servers.stopNamed("username", "gpu-server");

Error Handling

The SDK provides typed errors for common scenarios:

import { ApiError, AuthenticationError, ForbiddenError, NotFoundError, TimeoutError, WebSocketError, KernelExecutionError, KernelNotReadyError, ServerNotRunningError, ValidationError } from "jupyterhub";

try {
  await client.hub.users.get("nonexistent");
} catch (error) {
  if (error instanceof NotFoundError) {
    console.log("User not found");
    console.log("URL:", error.url);
    console.log("Method:", error.method);
  } else if (error instanceof AuthenticationError) {
    console.log("Invalid or expired token");
  } else if (error instanceof ForbiddenError) {
    console.log("Insufficient permissions");
  } else if (error instanceof TimeoutError) {
    console.log("Request timed out after", error.timeout, "ms");
  } else if (error instanceof ApiError) {
    console.log(`API error: ${error.status} - ${error.message}`);
    console.log("Response body:", error.body);
  }
}

// Kernel execution errors
try {
  const result = await server.executeCode("raise ValueError('test')", "python3");
} catch (error) {
  if (error instanceof KernelExecutionError) {
    console.log("Error:", error.ename, error.evalue);
    console.log("Traceback:", error.traceback.join("\n"));
  }
}

// WebSocket errors
try {
  await connection.connect();
} catch (error) {
  if (error instanceof WebSocketError) {
    console.log("WebSocket error:", error.message);
    console.log("URL:", error.url);
  }
}

Advanced Usage

Custom HTTP Client

Access the underlying HTTP client for advanced scenarios:

import { HttpClient } from "jupyterhub";

// Create a custom HTTP client
const http = new HttpClient({
  baseUrl: "https://jupyterhub.example.com",
  token: "your-token",
  timeout: 60000,
  retries: 5,
  rejectUnauthorized: false,
});

// Make custom requests
const response = await http.get("/hub/api/custom-endpoint");
const result = await http.post("/hub/api/custom", { data: "value" });

Self-Signed Certificates

For JupyterHub instances with self-signed certificates:

const client = new JupyterHubClient({
  baseUrl: "https://jupyterhub.local",
  token: "your-token",
  rejectUnauthorized: false, // Disable SSL verification
});

Accessing Raw APIs

// Access individual API modules
const { hub } = client;
const server = client.server("username");

// Hub APIs
hub.users; // UsersApi
hub.groups; // GroupsApi
hub.servers; // ServersApi
hub.tokens; // TokensApi
hub.services; // ServicesApi
hub.proxy; // ProxyApi

// Server APIs
server.contents; // ContentsApi
server.kernels; // KernelsApi
server.sessions; // SessionsApi
server.terminals; // TerminalsApi
server.kernelspecs; // KernelspecsApi

TypeScript Types

All types are exported for TypeScript users:

import type {
  // Client options
  JupyterHubClientOptions,

  // Hub types
  User,
  Group,
  Token,
  Service,
  ServerStatus,

  // Server types
  ContentModel,
  Kernel,
  Session,
  Terminal,
  KernelSpec,
  NotebookContent,
  NotebookCell,

  // Execution types
  ExecutionResult,
  NotebookExecutionResult,
  CellOutput,
  CommandResult,

  // Connection types
  KernelConnectionOptions,
  TerminalConnectionOptions,
  ExecuteOptions,
  RunCommandOptions,
} from "jupyterhub";

Development

# Clone the repository
git clone https://github.com/pawan-osman/jupyterhub-sdk.git
cd jupyterhub-sdk

# Install dependencies
pnpm install

# Build
pnpm run build

# Type check
pnpm run typecheck

# Run tests
pnpm test

# Development mode (watch)
pnpm run dev

License

MIT