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

kumo-enjin

v1.0.0

Published

雲エンジン (Cloud Engine) - Transform your VPS into a WebContainer-like development environment

Readme

Kumo Enjin (雲エンジン) - Cloud Engine

Transform your VPS into a WebContainer-like development environment, similar to StackBlitz's WebContainer and Daytona. Connect securely via SSH and manage your remote development workflow seamlessly.

Features

🔐 Secure SSH Connection - Support for both password and SSH key authentication
📁 File Operations - Upload/download files and directories with progress tracking
🖥️ Remote Command Execution - Run commands interactively with real-time streaming output
🌐 Smart Port Management - Public URLs or local port forwarding
🔄 Auto-Reconnection - Gracefully handle connection drops with retry logic
🏗️ Session Isolation - Each project operates in its own working directory
⚙️ Dual API Design - Both simplified and advanced APIs available
🛡️ Security Best Practices - Command sanitization and secure credential handling
📝 Full TypeScript Support - Complete type definitions and JSDoc comments
🚀 Template Mounting - Direct project template deployment without local files

Installation

npm install kumo-enjin

Quick Start (Simplified API)

import { KumoEnjin } from "kumo-enjin";

const enjin = new KumoEnjin({
  host: "your-vps.com",
  username: "user",
  password: "password" // or privateKey: "/path/to/key"
});

await enjin.connect();

// Mount project files directly (no local files needed)
await enjin.mount({
    directory: {
        "package.json": {
            file: {
                contents: JSON.stringify({
                    name: "express-app",
                    version: "1.0.0",
                    main: "index.js",
                    scripts: {
                        dev: "node index.js"
                    },
                    dependencies: {
                        express: "^4.18.0"
                    }
                }, null, 2)
            }
        },
        "index.js": {
            file: {
                contents: `
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello from Kumo Enjin + Express!');
});

app.listen(port, '0.0.0.0', () => {
  console.log(\`🚀 Express server running at http://localhost:\${port}\`);
});
        `.trim()
            }
        }
    }
});

// Install dependencies (auto uses project directory)
await enjin.run("npm install", { stream: true });

// Start dev server (returns public URL)
const { url } = await enjin.start(); // defaults: 'npm run dev', port 5173

console.log(`🌐 Live at: ${url}`);

// One-click cleanup: stops server, deletes files, disconnects
await enjin.stopDevServer();
await enjin.cleanup();

Advanced API Usage

import { KumoEnjin } from "kumo-enjin";

const enjin = new KumoEnjin({
  host: "your-vps.com",
  port: 22,
  username: "user",
  privateKey: "/path/to/your/private/key"
});

// Connect to your VPS
await enjin.connect();

// Upload your project
await enjin.upload("./my-app", "/remote/my-app");

// Install dependencies
await enjin.exec("npm install", { cwd: "/remote/my-app" });

// Start development server with port forwarding
const { url, pid } = await enjin.startDevServer("npm run dev", {
  cwd: "/remote/my-app",
  port: 3000,
  usePublicUrl: false // Use local port forwarding instead
});

console.log("Preview at:", url);

// Stop server when done
await enjin.stop(pid);
await enjin.disconnect();

Configuration

Basic Configuration

const config = {
  host: "your-vps.com",
  port: 22, // optional, defaults to 22
  username: "user",
  
  // Authentication (choose one)
  password: "your-password",
  // OR
  privateKey: "/path/to/private/key",
  passphrase: "key-passphrase", // optional
  
  // Connection settings
  timeout: 10000, // optional, defaults to 10s
  
  // Auto-reconnection
  autoReconnect: {
    enabled: true,
    maxRetries: 3,
    retryDelay: 2000
  }
};

API Reference

Constructor

new KumoEnjin(config: KumoEnjinConfig)

Connection Methods

  • connect() - Establish SSH connection
  • disconnect() - Close SSH connection and cleanup
  • isConnected() - Check connection status

Simplified API Methods

  • mount(template, templateName?) - Mount project template to remote server
  • run(command, options?) - Execute command in project directory
  • start(command?, port?) - Start dev server with public URL
  • stopDevServer() - Stop server, cleanup files, and disconnect

Advanced API Methods

  • exec(command, options) - Execute remote command with full control
  • upload(localPath, remotePath) - Upload files/directories
  • download(remotePath, localPath) - Download files/directories
  • startDevServer(command, options) - Start dev server with advanced options
  • stop(pid) - Stop specific process by PID

Utility Methods

  • getRunningProcesses() - Get map of running processes
  • getActivePortForwards() - Get active port forwarding mappings

Project Templates

Simple Static Site

const staticTemplate = {
  directory: {
    "index.html": {
      file: { contents: "<h1>Hello World!</h1>" }
    },
    "style.css": {
      file: { contents: "body { font-family: Arial; }" }
    }
  }
};

await enjin.mount(staticTemplate);
await enjin.start("python3 -m http.server 8000", 8000);

Node.js Project

const nodeTemplate = {
  directory: {
    "package.json": {
      file: { contents: JSON.stringify({
        name: "my-node-app",
        scripts: {
          dev: "node server.js"
        },
        dependencies: {
          express: "^4.18.0"
        }
      }, null, 2) }
    },
    "server.js": {
      file: { contents: `
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello from Kumo Enjin!');
});

app.listen(port, '0.0.0.0', () => {
  console.log(\`Server running at http://localhost:\${port}\`);
});
      `.trim() }
    }
  }
};

await enjin.mount(nodeTemplate);
await enjin.run("npm install");
await enjin.start("npm run dev", 3000);

Multiple Templates

const templates = {
  "vite-vanilla": {
    directory: {
      "package.json": { file: { contents: "..." } },
      "index.html": { file: { contents: "..." } }
    }
  },
  "express-api": {
    directory: {
      "package.json": { file: { contents: "..." } },
      "server.js": { file: { contents: "..." } }
    }
  }
};

await enjin.mount(templates, "vite-vanilla");

Events

Listen to various events during operation:

enjin.on('connect', () => {
  console.log('Connected to VPS');
});

enjin.on('disconnect', () => {
  console.log('Disconnected from VPS');
});

enjin.on('error', (error) => {
  console.error('Error:', error.message);
});

enjin.on('reconnecting', (attempt) => {
  console.log(`Reconnection attempt ${attempt}`);
});

enjin.on('upload-progress', (progress) => {
  console.log(`${progress.file}: ${progress.percentage}%`);
});

enjin.on('command-output', (data) => {
  process.stdout.write(data);
});

Examples

Vite React Project

const enjin = new KumoEnjin({ /* config */ });
await enjin.connect();

await enjin.mount({
  directory: {
    "package.json": {
      file: { contents: JSON.stringify({
        name: "vite-react-app",
        scripts: { dev: "vite --host 0.0.0.0" },
        dependencies: { vite: "^4.0.0", react: "^18.0.0" }
      }, null, 2) }
    },
    "index.html": {
      file: { contents: `<!DOCTYPE html>
<html><head><title>Vite React</title></head>
<body><div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body></html>` }
    },
    "src": {
      directory: {
        "main.jsx": {
          file: { contents: `import React from 'react'
import ReactDOM from 'react-dom/client'
ReactDOM.createRoot(document.getElementById('root')).render(<h1>Hello Vite!</h1>)` }
        }
      }
    }
  }
});

await enjin.run("npm install");
const { url } = await enjin.start("npm run dev", 5173);
console.log(`React app running at: ${url}`);

Security Considerations

  • Use SSH keys instead of passwords for production
  • Commands are sanitized to prevent basic injection attacks
  • Each session uses isolated temporary directories
  • Automatic cleanup prevents file accumulation
  • Connection timeouts prevent hanging connections

Error Handling

try {
  await enjin.connect();
  await enjin.mount(template);
  const { url } = await enjin.start();
  console.log(`Server running at: ${url}`);
} catch (error) {
  console.error('Failed to start server:', error.message);
} finally {
  await enjin.stopDevServer(); // Always cleanup
}

Requirements

  • Node.js >= 16.0.0
  • SSH access to your VPS
  • VPS with required runtime environments (Node.js, Python, etc.)

License

MIT