Back to Blog

Building Re-Shell CLI: My Open Source Journey

The story behind Re-Shell CLI, an open-source platform for building modern distributed applications with unified microservices and microfrontends.

Umut Korkmaz

Published: 8 min read

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:

# 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:

// 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:

// 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:

// 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:

# 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:

# 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!

About the author

Umut Korkmaz

Lead Software Engineer

I'm a senior software engineer in Istanbul. Here I write about the tools and releases I've shipped to production myself, and what they taught me along the way.

Picked by shared topics.

  • 7 min read

    Quorate: A Council of AI Reviewers for Your Code

    I built Quorate, an open-source CLI that runs several AI models over the same diff as independent reviewers, then synthesizes their verdicts. A council catches what one model misses and punctures false confidence.

    • AI
    • Code Review
    • Open Source
  • 7 min read

    Shipping re-shell cli to 0.29 - Lessons From Fast Iteration

    Lessons from shipping a developer CLI fast as a solo maintainer: what pre-1.0 versioning really lets you do, keeping breaking changes honest, the discipline of small frequent releases, dogfooding, and using AI agents without letting quality slip.

    • CLI
    • Open Source
    • Versioning