Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
91dab2b
feat(cli): Add unified Angular/React support with MCP integration and…
rohit-sourcefuse Oct 29, 2025
8e06a1e
fix(cli): Address all security vulnerabilities and code quality issues
rohit-sourcefuse Oct 29, 2025
cf784f3
fix: resolve all remaining SonarQube issues
rohit-sourcefuse Oct 29, 2025
6d900f2
fix: resolve all critical SonarQube issues and security hotspots
rohit-sourcefuse Oct 30, 2025
8a8189c
fix: resolve ESLint errors (no-shadow and prefer-nullish-coalescing)
rohit-sourcefuse Oct 30, 2025
12701bc
fix: use correct NOSONAR syntax for SonarQube security hotspots
rohit-sourcefuse Oct 30, 2025
5d70928
fix: place NOSONAR comments inline and revert README version line
rohit-sourcefuse Oct 31, 2025
7fa6dc9
fix: place NOSONAR comments inline and revert README version line
rohit-sourcefuse Oct 31, 2025
ee3f0bc
refactor(cli): refactored the react cli
Nov 11, 2025
7b94e0c
refactor(cli): refactored the angular cli
Nov 11, 2025
5cb8b09
fix(cli): fix crtitical high sonar issues
Nov 11, 2025
3ccf2ad
docs(cli): update README with unified CLI features and MCP integration
rohit-sourcefuse Nov 13, 2025
7c8cd8a
fix(cli): address all Copilot review comments
rohit-sourcefuse Nov 13, 2025
79f0ebe
fix(security): add detailed justifications for security hotspots
rohit-sourcefuse Nov 14, 2025
e06d9d3
refactor: migrate Angular and React commands to use Yeoman generators
rohit-sourcefuse Nov 18, 2025
c460e5e
fix: resolve ESLint errors in Angular and React generators
rohit-sourcefuse Nov 18, 2025
a02a2ee
refactor(cli): remove Angular/React generate, config, and info commands
rohit-sourcefuse Nov 18, 2025
65897d7
refactor(cli): Refactor CLI Command: Remove Angular/React Non-Scaffol…
piyushsinghgaur1 Nov 19, 2025
642a9a6
fix(cli): expose commands through MCP (#2369)
piyushsinghgaur1 Nov 25, 2025
41716b7
refactor(cli): update code structure to follow backend structure (#2379)
piyushsinghgaur1 Dec 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9,335 changes: 2,791 additions & 6,544 deletions package-lock.json

Large diffs are not rendered by default.

182 changes: 175 additions & 7 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,59 @@
# sourceloop-cli

This is a `sourceloop` based cli that provides commands to scaffold a monorepo, add extensions, facades and microservices to it.
A unified CLI for scaffolding and managing SourceLoop projects across the full stack - backend (LoopBack4 microservices), Angular, and React applications. The CLI provides AI-powered development assistance through the Model Context Protocol (MCP).

## Building
## Features

To install sourceloop-cli, run
- **🏗️ Backend Development**: Scaffold ARC monorepos, microservices, and extensions
- **⚛️ React Support**: Scaffold React projects from ARC boilerplate
- **🅰️ Angular Support**: Scaffold Angular projects from ARC boilerplate
- **🤖 AI Integration**: Built-in MCP server for AI-assisted development (Claude Code, etc.)
- **📦 Template Management**: Smart template fetching from GitHub with local development support

## Installation

```shell
npm install @sourceloop/cli
npm install -g @sourceloop/cli
```

Once the above command is executed, you will be able to access the CLI commands directly from your terminal. You can use either `sl` or `arc` as shorthand to run any of the `sourceloop` commands listed below. A sample usage is provided for reference:
Once installed, you can use either `sl` or `arc` as shorthand to run any command.

## Quick Start

```bash
# Scaffold a backend ARC monorepo
sl scaffold my-backend

# Scaffold an Angular project
sl angular:scaffold my-angular-app

# Scaffold a React project
sl react:scaffold my-react-app

# For component generation, use the framework-specific CLI:
# - Angular: Use Angular CLI (ng generate)
# - React: Use your preferred tool (create-react-app, Vite, etc.)
```

## MCP Integration

All scaffolded projects automatically include MCP configuration in `mcp.json`. This enables AI assistants like Roo Code to interact with your project intelligently.

To use the CLI as an MCP server, add this to your MCP client configuration:

```json
{
"mcpServers": {
"sourceloop": {
"command": "sl",
"args": ["mcp"],
"alwaysAllow": ["Scaffold", "Microservice", "Extension", "help"],
"timeout": 300,
"disabled": false
}
}
}
```

## Usage

Expand All @@ -20,7 +63,7 @@ $ npm install -g @sourceloop/cli
$ sl COMMAND
running command...
$ sl (-v|--version|version)
@sourceloop/cli/12.1.0 linux-x64 node-v20.19.5
@sourceloop/cli/12.0.0 darwin-arm64 node-v22.16.0
$ sl --help [COMMAND]
USAGE
$ sl COMMAND
Expand All @@ -31,15 +74,41 @@ USAGE
## Commands

<!-- commands -->
* [`sl angular:scaffold [NAME]`](#sl-angularscaffold-name)
* [`sl autocomplete [SHELL]`](#sl-autocomplete-shell)
* [`sl cdk`](#sl-cdk)
* [`sl extension [NAME]`](#sl-extension-name)
* [`sl help [COMMAND]`](#sl-help-command)
* [`sl mcp`](#sl-mcp)
* [`sl microservice [NAME]`](#sl-microservice-name)
* [`sl react:scaffold [NAME]`](#sl-reactscaffold-name)
* [`sl scaffold [NAME]`](#sl-scaffold-name)
* [`sl update`](#sl-update)

## `sl angular:scaffold [NAME]`

Scaffold a new Angular project from ARC boilerplate

```
USAGE
$ sl angular:scaffold [NAME]

ARGUMENTS
NAME Project name

OPTIONS
--help Show manual pages
--installDeps Install dependencies after scaffolding
--localPath=localPath Local path to use instead of remote template

--templateRepo=templateRepo [default: sourcefuse/angular-boilerplate] Template repository (owner/repo or local
path)

--templateVersion=templateVersion Template branch, tag, or version
```

_See code: [src/commands/angular/scaffold.ts](https://github.com/sourcefuse/loopback4-microservice-catalog/blob/v12.0.0/src/commands/angular/scaffold.ts)_

## `sl autocomplete [SHELL]`

display autocomplete installation instructions
Expand Down Expand Up @@ -194,6 +263,27 @@ OPTIONS

_See code: [src/commands/microservice.ts](https://github.com/sourcefuse/loopback4-microservice-catalog/blob/v12.1.0/src/commands/microservice.ts)_

## `sl react:scaffold [NAME]`

Scaffold a new React project from ARC boilerplate

```
USAGE
$ sl react:scaffold [NAME]

ARGUMENTS
NAME Project name

OPTIONS
--help Show manual pages
--installDeps Install dependencies after scaffolding
--localPath=localPath Local path to template
--templateRepo=templateRepo [default: sourcefuse/react-boilerplate-ts-ui] Template repository (org/repo)
--templateVersion=templateVersion Template branch or version
```

_See code: [src/commands/react/scaffold.ts](https://github.com/sourcefuse/loopback4-microservice-catalog/blob/v12.0.0/src/commands/react/scaffold.ts)_

## `sl scaffold [NAME]`

Setup a ARC based monorepo using npm workspaces with an empty services, facades and packages folder
Expand Down Expand Up @@ -230,5 +320,83 @@ OPTIONS
--help show manual pages
```

_See code: [src/commands/update.ts](https://github.com/sourcefuse/loopback4-microservice-catalog/blob/v12.1.0/src/commands/update.ts)_
_See code: [src/commands/update.ts](https://github.com/sourcefuse/loopback4-microservice-catalog/blob/v12.0.0/src/commands/update.ts)_
<!-- commandsstop -->

---

## Architecture

### Backend Commands

Backend commands work with the ARC (Accelerated Reference Catalog) monorepo structure:

```
my-project/
├── services/ # Microservices
├── facades/ # Facade services
├── packages/ # Shared packages
└── package.json
```

### Frontend Commands

Frontend commands work with official SourceFuse boilerplates:

**Angular**: Uses [angular-boilerplate](https://github.com/sourcefuse/angular-boilerplate)

- Multi-project workspace (arc, arc-lib, arc-docs, saas-ui)
- Material Design components
- Built-in authentication and theming

**React**: Uses [react-boilerplate-ts-ui](https://github.com/sourcefuse/react-boilerplate-ts-ui)

- Vite + TypeScript
- Material-UI (MUI) components
- Redux Toolkit for state management
- RTK Query for API calls

### Template Fetching

The CLI uses a smart template fetching strategy:

1. **GitHub Fetching** (Production): Downloads templates from official repositories
2. **Version Control**: Use `--templateVersion` to pin specific template versions

### MCP Auto-Configuration

When you scaffold any project (backend, Angular, or React), the CLI automatically:

1. Creates `.claude/mcp.json` with SourceLoop CLI server configuration
2. Generates `.claude/README.md` with usage instructions
3. Configures the project for AI-assisted development

## Common Workflows

### Full-Stack Development

```bash
# 1. Create backend monorepo
sl scaffold my-fullstack-app

# 2. Add authentication microservice
cd my-fullstack-app
sl microservice auth-service --baseService=authentication-service

# 3. Create Angular admin panel
cd ..
sl angular:scaffold admin-panel

# 4. Create React customer portal
sl react:scaffold customer-portal
```

## Related Projects

- [loopback4-microservice-catalog](https://github.com/sourcefuse/loopback4-microservice-catalog) - Backend microservices
- [angular-boilerplate](https://github.com/sourcefuse/angular-boilerplate) - Angular template
- [react-boilerplate-ts-ui](https://github.com/sourcefuse/react-boilerplate-ts-ui) - React template

## License

MIT
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,4 @@
"@types/aws-lambda": "^8.10.110"
}
}
}
}
73 changes: 73 additions & 0 deletions packages/cli/src/__tests__/commands/angular-scaffold.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// sonarignore:start
import {Config} from '@oclif/config';
import {assert} from 'chai';
import {createStubInstance, stub} from 'sinon';
import Environment from 'yeoman-environment';
import {AngularScaffold} from '../../commands/angular/scaffold';

const DEFAULT_FLAGS = [
'--templateRepo',
'sourcefuse/angular-boilerplate',
'--templateVersion',
'main',
'--localPath',
'./template',
];

type RunOptions = Record<string, unknown>;

describe('angular scaffold', () => {
it('throws an error when project name is not provided', async () => {
const prompt = stub().resolves({name: ''});
const env = createStubInstance(Environment);
env.run.callsFake(
async (_namespace: string | string[], options?: RunOptions) => {
const name = (options?.name as string | undefined) ?? '';
if (name.trim().length === 0) {
throw new Error('Project name is required');
}
},
);
const command = new AngularScaffold(
[...DEFAULT_FLAGS],
new Config({root: ''}),
prompt,
env,
);

let error: Error | undefined;
try {
await command.run();
} catch (err) {
error = err as Error;
}

assert.isTrue(prompt.calledOnce);
assert.isTrue(env.run.calledOnce);
assert.exists(error);
assert.include(error?.message ?? '', 'Project name is required');
});

it('runs successfully when project name is provided', async () => {
const prompt = stub().resolves({});
const env = createStubInstance(Environment);
env.run.callsFake(
async (_namespace: string | string[], options?: RunOptions) => {
const name = options?.name as string;
assert.equal(name, 'angular-ui');
},
);
const command = new AngularScaffold(
['angular-ui', ...DEFAULT_FLAGS],
new Config({root: ''}),
prompt,
env,
);

await command.run();

assert.isFalse(prompt.called);
assert.isTrue(env.run.calledOnce);
});
});
// sonarignore:end
73 changes: 73 additions & 0 deletions packages/cli/src/__tests__/commands/react-scaffold.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// sonarignore:start
import {Config} from '@oclif/config';
import {assert, expect} from 'chai';
import {createStubInstance, stub} from 'sinon';
import Environment from 'yeoman-environment';
import {ReactScaffold} from '../../commands/react/scaffold';

const DEFAULT_FLAGS = [
'--templateRepo',
'sourcefuse/react-boilerplate-ts-ui',
'--templateVersion',
'main',
'--localPath',
'./template',
];

type RunOptions = Record<string, unknown>;

describe('react scaffold', () => {
it('throws an error when project name is not provided', async () => {
const prompt = stub().resolves({name: ''});
const env = createStubInstance(Environment);
env.run.callsFake(
async (_namespace: string | string[], options?: RunOptions) => {
const name = (options?.name as string | undefined) ?? '';
if (name.trim().length === 0) {
throw new Error('Project name is required');
}
},
);
const command = new ReactScaffold(
[...DEFAULT_FLAGS],
new Config({root: ''}),
prompt,
env,
);

let error: Error | undefined;
try {
await command.run();
} catch (err) {
error = err as Error;
}

assert.isTrue(prompt.calledOnce);
assert.isTrue(env.run.calledOnce);
assert.exists(error);
assert.include(error?.message ?? '', 'Project name is required');
});

it('runs successfully when project name is provided', async () => {
const prompt = stub().resolves({});
const env = createStubInstance(Environment);
env.run.callsFake(
async (_namespace: string | string[], options?: RunOptions) => {
const name = options?.name as string;
expect(name).to.equal('react-ui');
},
);
const command = new ReactScaffold(
['react-ui', ...DEFAULT_FLAGS],
new Config({root: ''}),
prompt,
env,
);

await command.run();

assert.isFalse(prompt.called);
assert.isTrue(env.run.calledOnce);
});
});
// sonarignore:end
Loading
Loading