An interactive shell for Node.js applications. Works with Express, NestJS, and any Node.js framework. Load your entire app context—models, services, configs, databases—and interact with them in a REPL with autocompletion.
Built with TypeScript for full type safety.
- 🚀 Framework Agnostic - Works with Express, NestJS, or vanilla Node.js
- 🔄 Auto-Detection - Automatically detects Express vs NestJS projects
- 📦 Auto-Loading - Automatically loads models, services, config files
- 🎯 Intelligent Autocompletion - Deep tab completion for object properties, methods, and prototype chains
- Completes instance methods:
userService.findById,orderService.create - Completes static methods:
User.find,User.create - Completes nested properties:
config.database.url - Discovers inherited methods from prototype chains
- Completes instance methods:
- 🔍 Object Introspection - Built-in helper methods to explore objects
info(obj)- Get detailed metadata about any objectmethods(obj)- List all methods of an objectprops(obj)- List all properties of an objecttype(obj)- Get the type of an object
- 🔄 Hot Reload - Reload your app without restarting the shell
- 🎨 Syntax Highlighting - Colorized output for better readability
- 📜 Command History - Persistent history across sessions
- 🔷 Full TypeScript Support - Written in TypeScript, includes type definitions
- 🔧 Customizable - Configure via
.nodesh.jsorpackage.json - 🗄️ Multi-Database Support - 7+ databases supported:
- 🍃 MongoDB (Mongoose)
- 🐘 PostgreSQL (pg)
- 🐬 MySQL (mysql2)
- ⚡ Redis (ioredis)
- 📊 Prisma (Universal ORM)
- 🕸️ Neo4j (Graph Database)
- 📦 DynamoDB (AWS)
- 🌐 API Client - Built-in HTTP client for testing external and local APIs
- 📬 Queue Management - Full BullMQ/Bull queue control (pause, resume, retry, clean)
- 🧪 Testing Helpers - API testing, seeding, timing utilities built-in
npm install -g @eftech93/nodeshThen use it with any project:
cd my-project
nodesh --yes
# Or use the shorter aliases:
nsh --yes # 3 characters
eft --yes # EFTECH93 brandnpm install --save-dev @eftech93/nodeshIf using MongoDB/Redis (see examples):
docker-compose -f docker-compose.yml up -d# Auto-detects Express or NestJS
cd my-project
nodesh
# Auto-generate config on first run
nodesh --yes
# Shorter aliases (all do the same thing):
nsh --yes # 3 characters - shortest!
eft --yes # EFTECH93 brand// Query database
node> await User.find({ isActive: true })
// Use services
node> await userService.create({ email: 'test@example.com' })
// Check cache
node> await cacheService.getStats()
// View queues
node> await queueService.getAllStatuses()
// Make HTTP requests
node> await apiService.get('https://api.example.com/users')
node> await apiService.local('GET', '/users')
// Reload after code changes
node> .reloadOn first run, nodesh automatically:
- Detects your framework (Express or NestJS)
- Detects TypeScript (checks for
tsconfig.json) - Generates appropriate config (
.nodesh.js)
| Detected | Prompt | Entry Point |
|---|---|---|
| Express | express> |
src/app.js |
| NestJS | nest> |
src/main.ts |
| TypeScript | Same | .ts extensions |
module.exports = {
// Path to your app entry file
appEntry: 'src/app.js',
// Directories to auto-load
modelsDir: 'src/models',
servicesDir: 'src/services',
helpersDir: 'helpers',
configDir: 'config',
// REPL settings
prompt: 'myapp> ',
useColors: true,
historyFile: '~/.myapp_history',
// Custom context
context: {
db: require('./src/database'),
redis: require('./src/redis'),
}
};{
"nodesh": {
"appEntry": "src/server.js",
"prompt": "api> ",
"useColors": true
}
}Type these in the shell (with the . prefix):
| Command | Description |
|---|---|
.reload |
Reload all application files |
.routes |
List all Express routes |
.models |
Show loaded models |
.services |
List loaded services |
.config |
Display configuration |
.env |
Show environment variables |
.clear |
Clear screen |
.help |
Show help |
.exit |
Exit shell |
nodesh [path] [options]
Options:
-e, --entry <file> Path to app entry file
-r, --root <path> Project root directory
--no-color Disable colored output
-p, --prompt <string> REPL prompt string
--env <environment> Set NODE_ENV (default: development)
--nestjs Force NestJS mode detection
--express Force Express mode (skip NestJS detection)
--init Create config file (auto-detects type)
-y, --yes Auto-generate config if not found
-h, --help Display help
-V, --version Display versionNodeSH includes a unified database connection manager supporting 7+ databases with automatic detection from environment variables:
| Database | Type | Adapter | Environment Variable |
|---|---|---|---|
| 🍃 MongoDB | Document | mongoose | MONGODB_URI |
| 🐘 PostgreSQL | Relational | pg | DATABASE_URL or PGHOST |
| 🐬 MySQL | Relational | mysql2 | DATABASE_URL or MYSQL_HOST |
| ⚡ Redis | Key-Value | ioredis | REDIS_URL or REDIS_HOST |
| 📊 Prisma | Universal ORM | @prisma/client | DATABASE_URL |
| 🕸️ Neo4j | Graph | neo4j-driver | NEO4J_URI |
| 📦 DynamoDB | NoSQL | aws-sdk | AWS_REGION |
Quick Start:
const { initDatabases, getConnectionManager } = require('@eftech93/nodesh');
// Auto-detect and connect all configured databases
const { manager, helpers } = await initDatabases();
// Access any connection
const mongo = manager.get('mongodb');
const postgres = manager.get('postgresql');
const redis = manager.get('redis');
const neo4j = manager.get('neo4j');
const dynamo = manager.get('dynamodb');
const prisma = manager.get('prisma');
// Get stats for all databases
await helpers.getDBStats();DynamoDB Table Creation:
const dynamo = manager.get('dynamodb');
// Create table with GSI support
await dynamo.createTable({
tableName: 'Users',
keySchema: [
{ attributeName: 'pk', keyType: 'HASH' },
{ attributeName: 'sk', keyType: 'RANGE' }
],
attributeDefinitions: [
{ attributeName: 'pk', attributeType: 'S' },
{ attributeName: 'sk', attributeType: 'S' },
{ attributeName: 'email', attributeType: 'S' }
],
billingMode: 'PAY_PER_REQUEST',
globalSecondaryIndexes: [
{
indexName: 'EmailIndex',
keySchema: [{ attributeName: 'email', keyType: 'HASH' }],
projectionType: 'ALL'
}
]
});In the NodeSH Shell:
// MongoDB operations
node> await User.find({ isActive: true })
node> await User.countDocuments()
// Redis operations
node> await cacheService.get('user:123')
node> await cacheService.set('user:123', user, 3600)
// PostgreSQL queries
node> const result = await pg.query('SELECT * FROM users WHERE active = $1', [true])See Database Guide for detailed configuration.
Built-in utilities for testing and debugging:
// Timing operations
const { run, measure, batch } = require('@eftech93/nodesh');
await run(() => User.find(), 'Find all users');
const { result, duration } = await measure(() => heavyOperation());
// Run multiple operations
await batch([
() => User.findById('1'),
() => User.findById('2'),
() => User.findById('3'),
]);Test API routes directly in the console:
const { http, ApiTester, debugApi } = require('@eftech93/nodesh');
// Simple HTTP calls
await http.get('/api/users');
await http.post('/api/users', { name: 'John', email: 'john@example.com' });
// Using ApiTester class
const api = new ApiTester('http://localhost:3000/api');
await api.get('/users', { page: '1', limit: '10' });
// Debug API calls step-by-step
await debugApi('/api/users/123', 'GET');Built-in seeding utilities:
const { seed, seedUsers, clear, showStats } = require('@eftech93/nodesh');
// Generic seeding
await seed({
count: 100,
create: (i) => User.create({ name: `User ${i}`, email: `user${i}@test.com` }),
batchSize: 10,
});
// User seeding with fake data
await seedUsers({
count: 50,
create: (data) => User.create(data),
roles: ['user', 'admin'],
});
// Show database stats
await showStats({
users: () => User.countDocuments(),
orders: () => Order.countDocuments(),
});
// Clear all data
await clear([
() => User.deleteMany({}),
() => Order.deleteMany({}),
]);const { formatTable, formatBytes, formatDuration } = require('@eftech93/nodesh');
// Format as table
console.log(formatTable([
{ name: 'User', count: 100 },
{ name: 'Order', count: 500 },
]));
// Format bytes
formatBytes(1024); // "1 KB"
formatBytes(1048576); // "1 MB"
// Format duration
formatDuration(500); // "500ms"
formatDuration(5000); // "5.00s"
formatDuration(120000); // "2m 0.00s"Built-in HTTP client for testing APIs directly in the console:
// Configure base URL
apiService.setBaseURL('https://api.example.com')
// Make HTTP requests
const users = await apiService.get('/users')
const user = await apiService.get('/users/1')
const newUser = await apiService.post('/users', { name: 'John', email: 'john@example.com' })
const updated = await apiService.put('/users/1', { name: 'Jane' })
const deleted = await apiService.delete('/users/1')
// Test connectivity
const ping = await apiService.ping('https://api.example.com/health')
// => { success: true, latency: 45, status: 200 }
// Call your own API (auto-uses localhost:3000)
const localUsers = await apiService.local('GET', '/users')
const newOrder = await apiService.local('POST', '/orders', { productId: '123', quantity: 2 })Full queue control for BullMQ/Bull queues:
// Get all queue statuses
await queueDashboardController.getAllQueueStatuses()
// Pause/Resume queues
await queueDashboardController.pauseQueue('email')
await queueDashboardController.resumeQueue('email')
// Get jobs with status filtering
await queueDashboardController.getJobs('email', 'failed')
await queueDashboardController.getJobs('email', 'waiting', 0, 19)
// Retry failed jobs
await queueDashboardController.retryJob('email', 'job-id-123')
// Retry all failed jobs
const failed = await queueDashboardController.getJobs('email', 'failed')
for (const job of failed) {
await queueDashboardController.retryJob('email', job.id)
}
// Clean old jobs
await queueDashboardController.cleanQueue('email', 'completed', 100)
// Schedule job for future
await queueDashboardController.scheduleJob(
'email',
'send-welcome',
{ to: 'user@example.com' },
new Date(Date.now() + 60000) // 1 minute from now
)
// Get queue metrics
await queueDashboardController.getQueueMetrics('email')See example/ directory for a complete Express application with:
- MongoDB (Mongoose)
- Redis (caching)
- BullMQ (job queues)
- Full CRUD services
cd example
npm install
npm run docker:up
npm run consoleSee example-nestjs/ directory for a complete NestJS application with:
- MongoDB (Mongoose)
- Redis (caching)
- BullMQ (queues with processors)
- Full feature modules
cd example-nestjs
npm install
npm run docker:up
npm run build
npm run consoleThe shell provides intelligent autocompletion for exploring your application's objects:
// Press TAB after the dot to see available methods
node> userService.<TAB>
// Shows: create, findById, findByEmail, findActive, update, delete, authenticate, getStats, clearCache
// Partial completion - type a few letters and press TAB
node> userService.find<TAB>
// Shows: findById, findByEmail, findActive
// Static/class methods on models
node> User.<TAB>
// Shows: find, findOne, findById, create, updateOne, deleteOne, countDocuments
// Deep nested property access
node> config.database.<TAB>
// Shows: url, host, port, name
// Array/Collection methods
node> users.map<TAB>
// Shows: map, filter, reduce, forEach, find, etc.Special helper functions are available in the shell to explore objects:
// Get detailed information about any object
node> info(userService)
// Returns:
// {
// name: 'userService',
// type: 'UserService',
// constructor: 'UserService',
// properties: [...],
// methods: [...]
// }
// List all methods of an object
node> methods(userService)
// Returns: ['create', 'findById', 'findByEmail', 'findActive', 'update', 'delete', ...]
// List all properties (non-methods) of an object
node> props(config)
// Returns: ['env', 'port', 'database', 'redis', 'jwt']
// Get the type of any value
node> type(userService)
// Returns: 'UserService'
node> type(User)
// Returns: 'Object' or the class nameexpress> await UserService.create({
email: 'alice@example.com',
password: 'password123',
name: { first: 'Alice', last: 'Smith' }
})
express> const user = await UserService.findByEmail('alice@example.com')
express> await OrderService.create(user._id, items, shippingAddress)
express> await QueueService.getAllStatuses()
express> await CacheService.getStats()nest> const user = await usersService.create({
email: 'bob@example.com',
password: 'password123',
name: { first: 'Bob', last: 'Jones' }
})
nest> await usersService.findById(user._id.toString())
nest> await ordersService.create(user._id.toString(), items, address)
nest> await queuesService.getAllStatuses()
nest> await cacheService.getStats()When installed globally (npm install -g @eftech93/nodesh), you can use it with any project:
# Navigate to any project
cd ~/projects/my-api
# Run shell (auto-detects project type)
nodesh
# Auto-generate config on first run
nodesh --yesThe library is written in TypeScript and includes full type definitions.
import { ExpressConsole, AppLoader } from '@eftech93/nodesh';
async function startConsole(): Promise<void> {
const console = new ExpressConsole({
rootPath: __dirname,
appEntry: 'app.ts',
prompt: 'dev> '
});
await console.start();
}You can use the autocomplete functionality in your own code:
import { IntelligentCompleter } from '@eftech93/nodesh';
const context = {
userService: new UserService(),
orderService: new OrderService()
};
const completer = new IntelligentCompleter(context);
// Get completions for a partial input
const [completions] = completer.complete('userService.find');
console.log(completions); // ['findById', 'findByEmail', 'findActive']
// Introspect an object
const metadata = completer.introspect('userService');
console.log(metadata.properties);
console.log(metadata.type);
console.log(metadata.constructor);
// Get type information
const type = completer.getTypeName(context.userService);
console.log(type); // 'UserService'import { createCompleter, addIntrospectionMethods } from '@eftech93/nodesh';
import repl from 'repl';
const context = {
myService: new MyService()
};
const replServer = repl.start({
prompt: 'myapp> ',
completer: createCompleter(context)
});
// Add introspection helpers
addIntrospectionMethods(replServer.context);
Object.assign(replServer.context, context);The library includes comprehensive unit tests and integration tests using Jest:
# Run all unit tests
npm test
# Run tests in watch mode
npm test -- --watch
# Run tests with coverage
npm test -- --coverageIntegration tests verify the CLI works with real projects and databases:
# Start test databases (Docker required)
npm run test:docker:up
# Run all integration tests
npm run test:integration
# Run specific integration tests
npm run test:integration:nextjs
npm run test:integration:nestjs
npm run test:integration:express
# Stop test databases
npm run test:docker:downTest infrastructure includes 6 databases running on custom ports:
- MongoDB (port 9000)
- Redis (port 9001)
- PostgreSQL (port 9002)
- MySQL (port 9003)
- Neo4j (ports 9004/9005)
- DynamoDB Local (port 9006)
Tests are organized in the tests/ directory:
autocomplete.test.ts- Tests for intelligent autocomplete functionalityconfig.test.ts- Tests for configuration loadingloader.test.ts- Tests for application loadingconsole.test.ts- Tests for the main console classtypes.test.ts- Tests for TypeScript type definitionsintegration/- Integration tests with real projects and databases
# Build TypeScript to JavaScript
npm run build
# Build in watch mode
npm run dev
# Clean build artifacts
npm run cleanMake sure your infrastructure is running:
docker-compose up -dThe shell will show warnings but continue. Fix paths in .nodesh.js:
module.exports = {
modelsDir: 'dist/models', // For compiled TS
servicesDir: 'dist/services'
};Specify the entry file explicitly:
nodesh --entry dist/main.jsIncluded docker-compose.yml provides:
| Service | Port | Description |
|---|---|---|
| MongoDB | 27017 | Database |
| Redis | 6379 | Cache & Queue |
| Redis Commander | 8081 | Redis UI |
docker-compose up -d
docker-compose downMIT