Building Re-Shell CLI: My Open Source Journey
Every developer eventually builds their own tools. For me, that tool became Re-Shell CLI—a comprehensive platform for building modern distributed applications that unites microservices and microfrontends under a single powerful CLI.
The Problem
Working on multiple projects with microservices and microfrontends, I noticed the same patterns emerging:
- Repetitive boilerplate for each new service
- Inconsistent project structures across teams
- Complex deployment orchestration
- Difficulty maintaining shared configurations
The existing tools either did too much (vendor lock-in) or too little (just scaffolding).
The Vision
Re-Shell aims to be the middle ground—opinionated enough to provide real productivity gains, but flexible enough to adapt to different tech stacks:
bash# Create a new distributed application
reshell init my-platform
# Add a new microservice
reshell add service user-service --template node-fastify
# Add a microfrontend
reshell add frontend dashboard --template react-vite
# Run everything locally
reshell dev
# Deploy to production
reshell deploy --env production
Technical Architecture
The CLI is built with TypeScript and follows a plugin-based architecture:
typescript// Core CLI structure
import { Command } from 'commander';
import { loadPlugins } from './plugin-loader';
const program = new Command();
program
.name('reshell')
.description('Unified CLI for distributed applications')
.version('1.0.0');
// Dynamic command loading from plugins
const plugins = await loadPlugins();
plugins.forEach(plugin => {
plugin.registerCommands(program);
});
program.parse();
Plugin System
Each capability is a separate plugin:
typescript// Plugin interface
export interface ReShellPlugin {
name: string;
version: string;
registerCommands: (program: Command) => void;
hooks?: {
preInit?: () => Promise<void>;
postInit?: () => Promise<void>;
preBuild?: () => Promise<void>;
postBuild?: () => Promise<void>;
};
}
// Example: Service Generator Plugin
export const serviceGeneratorPlugin: ReShellPlugin = {
name: 'service-generator',
version: '1.0.0',
registerCommands: (program) => {
program
.command('add service <name>')
.description('Add a new microservice')
.option('-t, --template <template>', 'Service template', 'node-express')
.option('-p, --port <port>', 'Default port')
.action(async (name, options) => {
await generateService(name, options);
});
}
};
Template Engine
Services and frontends are generated from customizable templates:
typescript// Template processing
export const processTemplate = async (
templatePath: string,
outputPath: string,
variables: Record<string, string>
) => {
const files = await glob(`${templatePath}/**/*`, { nodir: true });
for (const file of files) {
let content = await fs.readFile(file, 'utf-8');
// Replace template variables
for (const [key, value] of Object.entries(variables)) {
content = content.replace(
new RegExp(`\\{\\{${key}\\}\\}`, 'g'),
value
);
}
// Process filename variables
const relativePath = path.relative(templatePath, file);
const processedPath = relativePath.replace(
/\{\{(\w+)\}\}/g,
(_, key) => variables[key] || ''
);
const outputFile = path.join(outputPath, processedPath);
await fs.mkdir(path.dirname(outputFile), { recursive: true });
await fs.writeFile(outputFile, content);
}
};
Workspace Configuration
A central configuration file manages all services:
yaml# reshell.yaml
name: my-platform
version: 1.0.0
services:
user-service:
type: microservice
template: node-fastify
port: 3001
dependencies:
- database
- cache
product-service:
type: microservice
template: node-express
port: 3002
dependencies:
- database
frontends:
dashboard:
type: microfrontend
template: react-vite
port: 5173
remotes:
- shared-ui
customer-portal:
type: microfrontend
template: react-vite
port: 5174
shared:
database:
type: postgres
version: 15
cache:
type: redis
version: 7
environments:
development:
compose: true
production:
provider: kubernetes
namespace: my-platform
Lessons from Open Source
1. Documentation is Everything
No matter how good your code is, poor documentation kills adoption. I spent as much time on docs as on code.
2. Start Small
The first version only had init and dev commands. Features grew based on actual usage feedback.
3. Dogfood Your Own Tool
I use Re-Shell for my own projects. Nothing finds bugs faster than real usage.
4. Community Matters
Even with a small user base, the feedback and contributions have been invaluable.
What's Next
Current development focuses on:
- Cloud provider plugins - AWS, GCP, Azure deployment automation
- Monitoring integration - Built-in observability setup
- AI assistance - Natural language service generation
Contributing
Re-Shell is open source and welcomes contributions:
bash# Clone the repository
git clone https://github.com/Re-Shell/cli.git
# Install dependencies
npm install
# Run in development mode
npm run dev
# Run tests
npm test
Whether you're building a small side project or a complex enterprise system, Re-Shell aims to make distributed application development more accessible. Check it out at github.com/Re-Shell/cli and let me know what you think!