@qodalis/react-cli 2.0.0-beta.9 → 2.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,614 +1,273 @@
1
- <h1 align="center">Qodalis Web CLI</h1>
1
+ <h1 align="center">Qodalis CLI</h1>
2
2
 
3
- <p align="center">A web-based terminal for Angular, React, and Vue — extensible, themeable, and packed with built-in developer tools.</p>
3
+ <p align="center">A web terminal for Angular, React, Vue and plain TypeScript, extended through command modules.</p>
4
4
 
5
5
  <div align="center">
6
6
 
7
- [![npm version](https://img.shields.io/npm/v/@qodalis/cli.svg?label=cli)](https://www.npmjs.com/package/@qodalis/cli)
8
- [![npm version](https://img.shields.io/npm/v/@qodalis/angular-cli.svg?label=angular)](https://www.npmjs.com/package/@qodalis/angular-cli)
9
- [![npm version](https://img.shields.io/npm/v/@qodalis/react-cli.svg?label=react)](https://www.npmjs.com/package/@qodalis/react-cli)
10
- [![npm version](https://img.shields.io/npm/v/@qodalis/vue-cli.svg?label=vue)](https://www.npmjs.com/package/@qodalis/vue-cli)
11
- [![Build Status](https://github.com/qodalis-solutions/web-cli/actions/workflows/deploy.yml/badge.svg?branch=main)](https://github.com/qodalis-solutions/web-cli/actions)
12
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![npm](https://img.shields.io/npm/v/@qodalis/cli.svg?label=%40qodalis%2Fcli)](https://www.npmjs.com/package/@qodalis/cli)
8
+ [![npm](https://img.shields.io/npm/v/@qodalis/angular-cli.svg?label=angular)](https://www.npmjs.com/package/@qodalis/angular-cli)
9
+ [![npm](https://img.shields.io/npm/v/@qodalis/react-cli.svg?label=react)](https://www.npmjs.com/package/@qodalis/react-cli)
10
+ [![npm](https://img.shields.io/npm/v/@qodalis/vue-cli.svg?label=vue)](https://www.npmjs.com/package/@qodalis/vue-cli)
11
+ [![Build](https://github.com/qodalis-solutions/web-cli/actions/workflows/build.yml/badge.svg?branch=develop)](https://github.com/qodalis-solutions/web-cli/actions/workflows/build.yml)
12
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/qodalis-solutions/web-cli/blob/main/LICENSE)
13
+
14
+ [Documentation](https://cli.qodalis.com/docs) &middot;
15
+ [Live demo](https://cli.qodalis.com/) &middot;
16
+ [Playground](https://cli.qodalis.com/docs/playground) &middot;
17
+ [Migrating to 2.0](https://cli.qodalis.com/docs/migration)
13
18
 
14
19
  </div>
15
20
 
16
- <p align="center">
17
- <a href="https://cli.qodalis.com/">Live Demo</a> &middot;
18
- <a href="https://cli.qodalis.com/docs/">Documentation</a> &middot;
19
- <a href="https://www.npmjs.com/package/@qodalis/cli">npm</a>
20
- </p>
21
+ ![Help command](https://raw.githubusercontent.com/qodalis-solutions/web-cli/main/assets/help_command.gif)
22
+
23
+ Qodalis CLI renders an [xterm.js](https://xtermjs.org/) terminal in your app with a shell-like command line, built-in commands, themes and a runtime package manager. You add commands as **modules** (`ICliModule`): the 40 official plugins, your own commands, or packages installed at runtime with `pkg add`. It can also connect to a Node.js, .NET or Python backend to run server-side commands.
24
+
25
+ ## Try it online
21
26
 
22
- ---
27
+ Starter projects for each framework, using the published npm packages:
23
28
 
24
- ## Try It Online
29
+ | Framework | StackBlitz | CodeSandbox | Gitpod | Repository |
30
+ |---|---|---|---|---|
31
+ | **Angular** | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/qodalis-solutions/qodalis-cli-angular-example) | [![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/github/qodalis-solutions/qodalis-cli-angular-example) | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/qodalis-solutions/qodalis-cli-angular-example) | [source](https://github.com/qodalis-solutions/qodalis-cli-angular-example) |
32
+ | **React** | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/qodalis-solutions/qodalis-cli-react-example) | [![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/github/qodalis-solutions/qodalis-cli-react-example) | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/qodalis-solutions/qodalis-cli-react-example) | [source](https://github.com/qodalis-solutions/qodalis-cli-react-example) |
33
+ | **Vue** | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/qodalis-solutions/qodalis-cli-vue-example) | [![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/github/qodalis-solutions/qodalis-cli-vue-example) | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/qodalis-solutions/qodalis-cli-vue-example) | [source](https://github.com/qodalis-solutions/qodalis-cli-vue-example) |
34
+ | **Vanilla TypeScript** | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/qodalis-solutions/qodalis-cli-vanilla-example) | [![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/github/qodalis-solutions/qodalis-cli-vanilla-example) | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/qodalis-solutions/qodalis-cli-vanilla-example) | [source](https://github.com/qodalis-solutions/qodalis-cli-vanilla-example) |
25
35
 
26
- | Framework | StackBlitz | CodeSandbox | Gitpod |
27
- |-----------|------------|-------------|--------|
28
- | **Angular** | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/qodalis-solutions/qodalis-cli-angular-example) | [![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/github/qodalis-solutions/qodalis-cli-angular-example) | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/qodalis-solutions/qodalis-cli-angular-example) |
29
- | **React** | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/qodalis-solutions/qodalis-cli-react-example) | [![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/github/qodalis-solutions/qodalis-cli-react-example) | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/qodalis-solutions/qodalis-cli-react-example) |
30
- | **Vue** | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/qodalis-solutions/qodalis-cli-vue-example) | [![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/github/qodalis-solutions/qodalis-cli-vue-example) | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/qodalis-solutions/qodalis-cli-vue-example) |
31
- | **Vanilla** | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/qodalis-solutions/qodalis-cli-vanilla-example) | [![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/github/qodalis-solutions/qodalis-cli-vanilla-example) | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/qodalis-solutions/qodalis-cli-vanilla-example) |
36
+ Or try the terminal and write your own commands in the [docs playground](https://cli.qodalis.com/docs/playground).
32
37
 
33
- ---
38
+ ## Install
34
39
 
35
- ![Help command](assets/help_command.gif)
40
+ | Framework | Package | Install |
41
+ | ---------- | -------------------------------------------------------------------------- | ------------------------------------- |
42
+ | Angular | [`@qodalis/angular-cli`](https://www.npmjs.com/package/@qodalis/angular-cli) | `npm install @qodalis/angular-cli` |
43
+ | React | [`@qodalis/react-cli`](https://www.npmjs.com/package/@qodalis/react-cli) | `npm install @qodalis/react-cli` |
44
+ | Vue 3 | [`@qodalis/vue-cli`](https://www.npmjs.com/package/@qodalis/vue-cli) | `npm install @qodalis/vue-cli` |
45
+ | Vanilla TS | [`@qodalis/cli`](https://www.npmjs.com/package/@qodalis/cli) | `npm install @qodalis/cli @qodalis/cli-core` |
46
+ | Electron | [`@qodalis/electron-cli`](https://www.npmjs.com/package/@qodalis/electron-cli) | `npm install @qodalis/electron-cli` (with a wrapper above) |
36
47
 
37
- ## Packages
48
+ Plugins are separate packages, for example `npm install @qodalis/cli-guid`.
38
49
 
39
- | Package | Description |
40
- |---------|-------------|
41
- | [`@qodalis/cli-core`](https://www.npmjs.com/package/@qodalis/cli-core) | Shared interfaces, models, and types |
42
- | [`@qodalis/cli`](https://www.npmjs.com/package/@qodalis/cli) | Framework-agnostic terminal engine (50+ built-in commands) |
43
- | [`@qodalis/angular-cli`](https://www.npmjs.com/package/@qodalis/angular-cli) | Angular wrapper |
44
- | [`@qodalis/react-cli`](https://www.npmjs.com/package/@qodalis/react-cli) | React wrapper |
45
- | [`@qodalis/vue-cli`](https://www.npmjs.com/package/@qodalis/vue-cli) | Vue 3 wrapper |
50
+ ## Quick start
46
51
 
47
- ## Quick Start
52
+ Each example shows a terminal with the `guid` plugin. Pass any number of modules.
48
53
 
49
54
  ### Angular
50
55
 
51
- ```bash
52
- npm install @qodalis/angular-cli
56
+ Angular 22 or later. Add the stylesheet to `angular.json`:
57
+
58
+ ```json
59
+ "styles": ["node_modules/@qodalis/angular-cli/src/assets/styles.css"]
53
60
  ```
54
61
 
55
62
  ```typescript
63
+ import { Component } from '@angular/core';
56
64
  import { CliModule } from '@qodalis/angular-cli';
65
+ import { ICliModule } from '@qodalis/cli-core';
66
+ import { guidModule } from '@qodalis/cli-guid';
57
67
 
58
- @NgModule({
59
- imports: [CliModule],
68
+ @Component({
69
+ selector: 'app-root',
70
+ imports: [CliModule],
71
+ template: `<cli [modules]="modules" height="100vh" />`,
60
72
  })
61
- export class AppModule {}
62
- ```
63
-
64
- Add styles to `angular.json`:
65
-
66
- ```json
67
- {
68
- "styles": [
69
- "node_modules/@qodalis/angular-cli/src/assets/styles.sass"
70
- ]
73
+ export class AppComponent {
74
+ modules: ICliModule[] = [guidModule];
71
75
  }
72
76
  ```
73
77
 
74
- ```html
75
- <!-- Full terminal -->
76
- <cli [options]="cliOptions" />
77
-
78
- <!-- Collapsible panel -->
79
- <cli-panel />
80
- ```
78
+ `<cli-panel>` is a collapsible panel docked to the page. To register modules app-wide through DI instead of the `modules` input, add `resolveCliModuleProvider(guidModule)` to your providers.
81
79
 
82
80
  ### React
83
81
 
84
- ```bash
85
- npm install @qodalis/react-cli
86
- ```
82
+ React 18 or 19.
87
83
 
88
84
  ```tsx
85
+ import '@qodalis/react-cli/styles.css';
89
86
  import { Cli } from '@qodalis/react-cli';
87
+ import { guidModule } from '@qodalis/cli-guid';
90
88
 
91
- function App() {
92
- return <Cli style={{ width: '100vw', height: '100vh' }} />;
89
+ export function App() {
90
+ return <Cli modules={[guidModule]} style={{ height: '100vh' }} />;
93
91
  }
94
92
  ```
95
93
 
96
94
  ### Vue
97
95
 
98
- ```bash
99
- npm install @qodalis/vue-cli
100
- ```
101
-
102
96
  ```vue
103
97
  <script setup lang="ts">
98
+ import '@qodalis/vue-cli/styles.css';
104
99
  import { Cli } from '@qodalis/vue-cli';
100
+ import { guidModule } from '@qodalis/cli-guid';
105
101
  </script>
106
102
 
107
103
  <template>
108
- <Cli :style="{ width: '100vw', height: '100vh' }" />
104
+ <Cli :modules="[guidModule]" :style="{ height: '100vh' }" />
109
105
  </template>
110
106
  ```
111
107
 
112
- ### Configuration (all frameworks)
108
+ React and Vue also export `CliPanel`, and `CliConfigProvider` to share `modules` and `options` with every terminal below it.
113
109
 
114
- Pass options to customize the terminal:
110
+ ### Vanilla TypeScript
115
111
 
116
112
  ```typescript
117
- const options = {
118
- welcomeMessage: {
119
- message: '-- your custom welcome message --',
120
- show: 'daily', // 'never', 'once', 'daily', 'always'
121
- },
122
- usersModule: {
123
- enabled: true,
124
- },
125
- };
126
- ```
127
-
128
- ## Built-in Commands
129
-
130
- ### System
131
-
132
- | Command | Aliases | Description |
133
- |---------|---------|-------------|
134
- | `help` | `man` | Show all commands or help for a specific command |
135
- | `version` | `ver` | Display CLI version and documentation link |
136
- | `hotkeys` | `shortcuts`, `keys` | Show keyboard shortcuts |
137
- | `history` | `hist` | Browse and clear command history |
138
- | `theme` | `themes` | Apply, customize, and save terminal themes (interactive selection with live preview) |
139
- | `feedback` | `support` | Report bugs or request features on GitHub |
140
- | `pkg` | `packages` | Install, update, remove, and browse packages |
141
-
142
- ### Utilities
143
-
144
- | Command | Aliases | Description |
145
- |---------|---------|-------------|
146
- | `clear` | `cls` | Clear the terminal (or `Ctrl+L`) |
147
- | `echo` | `print` | Print text to the terminal |
148
- | `eval` | `calc`, `js` | Evaluate JavaScript expressions |
149
- | `sleep` | `wait` | Pause execution for N milliseconds |
150
- | `time` | `date` | Show current local and UTC time |
151
- | `uptime` | — | Show session uptime |
152
- | `uname` | `sysinfo` | System and browser information |
153
- | `screen` | `display` | Screen, viewport, and terminal dimensions |
154
- | `open` | — | Open a URL in a new browser tab |
155
- | `alias` / `unalias` | — | Create and remove command aliases |
156
- | `yes` | — | Output a string repeatedly |
157
- | `seq` | `sequence` | Print number sequences |
158
- | `cal` | `calendar` | Display a monthly calendar |
159
-
160
- ### Developer Tools
161
-
162
- | Command | Aliases | Description |
163
- |---------|---------|-------------|
164
- | `base64` | `b64` | Encode / decode Base64 |
165
- | `json` | — | Format, minify, and validate JSON |
166
- | `url` | — | Encode, decode, and parse URLs |
167
- | `jwt` | — | Decode and inspect JWT tokens |
168
- | `hash` | — | SHA-256, SHA-1, SHA-384, SHA-512 hashes |
169
- | `hex` | — | Hex encode/decode and base conversion (2-36) |
170
- | `color` | `colour` | Convert between hex, rgb, hsl with preview |
171
- | `random` | `rand` | Random numbers, strings, UUIDs, coin flip, dice |
172
- | `lorem` | `lipsum` | Generate placeholder text |
173
- | `timestamp` | `ts`, `epoch` | Convert between Unix timestamps and dates |
174
- | `convert` | `conv` | Unit conversion (length, weight, temperature, data) |
175
- | `clipboard` | `cb`, `pbcopy` | Copy to / paste from clipboard |
176
-
177
- ### Users
178
-
179
- | Command | Aliases | Description |
180
- |---------|---------|-------------|
181
- | `whoami` | `me` | Display current user |
182
- | `su` | `switch-user` | Switch user session |
183
- | `adduser` | `useradd` | Add a new user |
184
- | `listusers` | `users` | List all users |
185
-
186
- ## Package Manager
187
-
188
- Install additional commands at runtime from npm — no rebuild needed.
189
-
190
- ![Install packages](assets/install_packages.gif)
191
-
192
- ```bash
193
- pkg browse # Browse available packages
194
- pkg add guid # Install a package
195
- pkg remove guid # Remove a package
196
- pkg update # Update all packages
197
- pkg update guid@1.0.2 # Pin a specific version
198
- pkg check # Check for updates
199
- pkg versions guid # Show all published versions
200
- pkg source set # Interactively select a package source (CDN)
201
- pkg source set unpkg # Set package source directly
202
- ```
203
-
204
- ### Available Packages
205
-
206
- | Package | Command | Description |
207
- |---------|---------|-------------|
208
- | [@qodalis/cli-guid](https://www.npmjs.com/package/@qodalis/cli-guid) | `guid` | Generate and validate UUIDs |
209
- | [@qodalis/cli-string](https://www.npmjs.com/package/@qodalis/cli-string) | `string` | String manipulation (case, trim, reverse, slug, wc, etc.) |
210
- | [@qodalis/cli-curl](https://www.npmjs.com/package/@qodalis/cli-curl) | `curl` | HTTP requests (GET, POST, PUT, DELETE) |
211
- | [@qodalis/cli-todo](https://www.npmjs.com/package/@qodalis/cli-todo) | `todo` | Task management |
212
- | [@qodalis/cli-regex](https://www.npmjs.com/package/@qodalis/cli-regex) | `regex` | Regular expression testing |
213
- | [@qodalis/cli-qr](https://www.npmjs.com/package/@qodalis/cli-qr) | `qr` | QR code generation |
214
- | [@qodalis/cli-speed-test](https://www.npmjs.com/package/@qodalis/cli-speed-test) | `speed-test` | Internet speed test |
215
- | [@qodalis/cli-server-logs](https://www.npmjs.com/package/@qodalis/cli-server-logs) | `server-logs` | Live server log streaming |
216
- | [@qodalis/cli-browser-storage](https://www.npmjs.com/package/@qodalis/cli-browser-storage) | `local-storage`, `cookies` | Browser storage operations |
217
- | [@qodalis/cli-text-to-image](https://www.npmjs.com/package/@qodalis/cli-text-to-image) | `text-to-image` | Generate images from text |
218
- | [@qodalis/cli-password-generator](https://www.npmjs.com/package/@qodalis/cli-password-generator) | `generate-password` | Password generation |
219
-
220
- Any npm package with UMD support can also be loaded:
221
-
222
- ```bash
223
- pkg add lodash
224
- eval _.map([1, 2, 3], n => n * 2)
225
- ```
226
-
227
- ## Creating a CLI Plugin
228
-
229
- ### Quick Start
230
-
231
- Scaffold a complete plugin project with a single command:
232
-
233
- ```bash
234
- npx @qodalis/create-cli-plugin
235
- ```
236
-
237
- The interactive prompts will ask for:
238
-
239
- | Prompt | Description | Example |
240
- |--------|-------------|---------|
241
- | **Plugin name** | Lowercase, no spaces, no `cli-` prefix (added automatically) | `weather` |
242
- | **Description** | Short description of the plugin | `Weather forecasts` |
243
- | **Processor class name** | PascalCase name for the command processor class | `Weather` |
244
-
245
- You can also skip the prompts by passing arguments directly:
246
-
247
- ```bash
248
- npx @qodalis/create-cli-plugin --name weather --description "Weather forecasts" --processor-name Weather
249
- ```
250
-
251
- Or install globally:
252
-
253
- ```bash
254
- npm install -g @qodalis/create-cli-plugin
255
- create-cli-plugin
256
- ```
257
-
258
- ### Standalone vs Monorepo Mode
259
-
260
- The tool auto-detects whether you're inside the `web-cli` monorepo:
261
-
262
- | Mode | Detection | Output directory | Package manager |
263
- |------|-----------|-----------------|-----------------|
264
- | **Standalone** | Any directory outside web-cli | `./qodalis-cli-<name>/` | npm or pnpm (auto-detected) |
265
- | **Monorepo** | Inside web-cli workspace | `packages/plugins/<name>/` | pnpm (workspace) |
266
-
267
- In monorepo mode, the tool also:
268
- - Creates `project.json` (Nx build + test targets)
269
- - Creates `tsconfig.spec.json` (Karma/Jasmine test config)
270
- - Updates `tsconfig.base.json` with the path alias `@qodalis/cli-<name>` → `dist/<name>`
271
-
272
- ### Generated Project Structure
273
-
274
- ```
275
- qodalis-cli-weather/ # or packages/plugins/weather/ in monorepo
276
- package.json # npm package with CJS/ESM/UMD exports
277
- tsup.config.ts # Build config (library + IIFE bundles)
278
- tsconfig.json # TypeScript config
279
- README.md # Auto-generated README
280
- src/
281
- public-api.ts # Public exports + ICliModule declaration
282
- cli-entrypoint.ts # IIFE entrypoint for browser runtime loading
283
- lib/
284
- version.ts # LIBRARY_VERSION + API_VERSION constants
285
- index.ts # Barrel re-exports
286
- processors/
287
- cli-weather-command-processor.ts # Command processor (your main logic goes here)
288
- tests/
289
- index.spec.ts # Jasmine test scaffold
290
- ```
291
-
292
- ### Step-by-Step Workflow
293
-
294
- #### 1. Scaffold the plugin
113
+ import '@qodalis/cli/assets/styles.css';
114
+ import { CliEngine } from '@qodalis/cli';
115
+ import { guidModule } from '@qodalis/cli-guid';
295
116
 
296
- ```bash
297
- npx @qodalis/create-cli-plugin --name weather
117
+ const engine = new CliEngine(document.getElementById('terminal')!);
118
+ engine.registerModule(guidModule);
119
+ await engine.start();
298
120
  ```
299
121
 
300
- #### 2. Implement your command processor
122
+ ## Your own commands
301
123
 
302
- Edit `src/lib/processors/cli-weather-command-processor.ts`:
124
+ A command is an `ICliCommandProcessor`; a module groups processors (and optional services, translations and lifecycle hooks):
303
125
 
304
126
  ```typescript
305
127
  import {
128
+ API_VERSION,
306
129
  CliProcessCommand,
307
- DefaultLibraryAuthor,
308
130
  ICliCommandProcessor,
309
131
  ICliExecutionContext,
132
+ ICliModule,
310
133
  } from '@qodalis/cli-core';
311
- import { LIBRARY_VERSION } from '../version';
312
-
313
- export class CliWeatherCommandProcessor implements ICliCommandProcessor {
314
- command = 'weather';
315
- description = 'Weather forecasts';
316
- author = DefaultLibraryAuthor;
317
- version = LIBRARY_VERSION;
318
-
319
- // Sub-commands
320
- processors?: ICliCommandProcessor[] = [
321
- {
322
- command: 'forecast',
323
- description: 'Get weather forecast for a city',
324
- parameters: [
325
- {
326
- name: 'city',
327
- aliases: ['c'],
328
- description: 'City name',
329
- required: true,
330
- type: 'string',
331
- },
332
- {
333
- name: 'days',
334
- aliases: ['d'],
335
- description: 'Number of days',
336
- required: false,
337
- type: 'number',
338
- defaultValue: '3',
339
- },
340
- ],
341
- processCommand: async (command, context) => {
342
- const city = command.args['city'];
343
- const days = parseInt(command.args['days'] ?? '3');
344
- context.writer.writeln(`Forecast for ${city} (${days} days):`);
345
- context.writer.writeSuccess('Sunny, 25°C');
346
- },
347
- },
348
- {
349
- command: 'current',
350
- description: 'Get current weather',
351
- acceptsRawInput: true, // command.value = text after 'current'
352
- valueRequired: true, // error if no value provided
353
- processCommand: async (command, context) => {
354
- context.writer.writeln(`Current weather in ${command.value}: Sunny, 25°C`);
355
- },
356
- },
357
- ];
358
-
359
- // Default handler (runs when user types just 'weather')
134
+
135
+ class GreetCommandProcessor implements ICliCommandProcessor {
136
+ command = 'greet';
137
+ description = 'Greet someone by name';
138
+ valueRequired = true;
139
+
360
140
  async processCommand(command: CliProcessCommand, context: ICliExecutionContext): Promise<void> {
361
- context.executor.showHelp(command, context);
141
+ context.writer.writeSuccess(`Hello, ${command.value}!`);
362
142
  }
363
143
  }
364
- ```
365
-
366
- #### 3. Build the plugin
367
-
368
- **Standalone:**
369
-
370
- ```bash
371
- cd qodalis-cli-weather
372
- npm run build # or: npx tsup
373
- ```
374
-
375
- **Monorepo:**
376
-
377
- ```bash
378
- pnpm nx build weather
379
- ```
380
-
381
- Build output goes to `dist/weather/` with three bundles:
382
- - `public-api.js` (CJS) + `public-api.mjs` (ESM) + `public-api.d.ts` (types)
383
- - `umd/index.js` (IIFE — self-contained browser bundle for runtime `pkg add`)
384
-
385
- #### 4. Test the plugin
386
-
387
- **Standalone:** Add your preferred test runner.
388
-
389
- **Monorepo:**
390
-
391
- ```bash
392
- pnpm nx test weather
393
- ```
394
144
 
395
- #### 5. Publish to npm
396
-
397
- ```bash
398
- cd dist/weather # or: cd qodalis-cli-weather/dist
399
- npm publish --access public
400
- ```
401
-
402
- Users can then install your plugin at runtime in any Qodalis CLI terminal:
403
-
404
- ```bash
405
- pkg add @qodalis/cli-weather
406
- weather forecast --city "New York"
407
- ```
408
-
409
- ### The ICliModule Export
410
-
411
- Every plugin exports an `ICliModule` object in `public-api.ts`. This is how frameworks register your plugin:
412
-
413
- ```typescript
414
- import { ICliModule } from '@qodalis/cli-core';
415
- import { CliWeatherCommandProcessor } from './lib/processors/cli-weather-command-processor';
416
- import { API_VERSION } from './lib/version';
417
-
418
- export const weatherModule: ICliModule = {
419
- apiVersion: API_VERSION, // must be >= 2
420
- name: '@qodalis/cli-weather',
421
- processors: [new CliWeatherCommandProcessor()],
422
- };
423
- ```
424
-
425
- `ICliModule` also supports optional lifecycle hooks and configuration:
426
-
427
- ```typescript
428
- export const weatherModule: ICliModule = {
429
- apiVersion: 2,
430
- name: '@qodalis/cli-weather',
431
- processors: [new CliWeatherCommandProcessor()],
432
- dependencies: ['@qodalis/cli-curl'], // boot other modules first
433
- priority: 0, // boot order (lower = first)
434
- configure(config) { /* ... */ return this; },
435
- onInit(context) { /* before processors initialize */ },
436
- onAfterBoot(context) { /* after all modules boot */ },
437
- onDestroy(context) { /* teardown */ },
438
- };
439
- ```
440
-
441
- ### The IIFE Entrypoint
442
-
443
- `src/cli-entrypoint.ts` enables runtime loading via `pkg add`. It calls `bootCliModule()` which registers the module with the global `window.__cliModuleRegistry`:
444
-
445
- ```typescript
446
- import { bootCliModule, ICliModule } from '@qodalis/cli-core';
447
- import { CliWeatherCommandProcessor } from './lib/processors/cli-weather-command-processor';
448
- import { API_VERSION } from './lib/version';
449
-
450
- const module: ICliModule = {
145
+ export const greetModule: ICliModule = {
451
146
  apiVersion: API_VERSION,
452
- name: '@qodalis/cli-weather',
453
- processors: [new CliWeatherCommandProcessor()],
147
+ name: 'my-app-commands',
148
+ processors: [new GreetCommandProcessor()],
454
149
  };
455
-
456
- bootCliModule(module);
457
- ```
458
-
459
- ### Execution Context API
460
-
461
- The `ICliExecutionContext` passed to `processCommand` provides:
462
-
463
- | Property | Description |
464
- |----------|-------------|
465
- | `context.writer` | Terminal output — `writeln()`, `writeInfo()`, `writeSuccess()`, `writeError()`, `wrapInColor()` |
466
- | `context.reader` | User input — `readLine()`, `readPassword()`, `readConfirm()`, `readSelect()`, `readMultiSelect()`, `readNumber()` |
467
- | `context.executor` | Command execution — `showHelp(command, context)` |
468
- | `context.clipboard` | Clipboard — `write()`, `read()` |
469
- | `context.state` | Persistent key-value store |
470
- | `context.progressBar` | Progress bar widget |
471
- | `context.spinner` | Spinner widget |
472
- | `context.terminal` | Raw xterm.js `Terminal` instance |
473
- | `context.onAbort` | `Subject<void>` for Ctrl+C cancellation |
474
- | `context.enterFullScreenMode()` | Switch to full-screen TUI mode |
475
- | `context.createInterval()` / `context.createTimeout()` | Managed timers (auto-cleaned on abort) |
476
-
477
- ### Registering Plugins in Your App
478
-
479
- #### Angular (via providers)
480
-
481
- ```typescript
482
- import { CliModule, resolveCliModuleProvider } from '@qodalis/angular-cli';
483
- import { weatherModule } from '@qodalis/cli-weather';
484
-
485
- @NgModule({
486
- imports: [CliModule],
487
- providers: [resolveCliModuleProvider(weatherModule)],
488
- })
489
- export class AppModule {}
490
- ```
491
-
492
- #### Angular (via template input)
493
-
494
- ```typescript
495
- import { weatherModule } from '@qodalis/cli-weather';
496
-
497
- export class AppComponent {
498
- modules = [weatherModule];
499
- }
500
- ```
501
-
502
- ```html
503
- <cli [modules]="modules" />
504
- ```
505
-
506
- #### React
507
-
508
- ```tsx
509
- import { CliConfigProvider, Cli } from '@qodalis/react-cli';
510
- import { weatherModule } from '@qodalis/cli-weather';
511
-
512
- function App() {
513
- return (
514
- <CliConfigProvider modules={[weatherModule]}>
515
- <Cli />
516
- </CliConfigProvider>
517
- );
518
- }
519
150
  ```
520
151
 
521
- #### Vue
522
-
523
- ```vue
524
- <script setup lang="ts">
525
- import { CliConfigProvider, Cli } from '@qodalis/vue-cli';
526
- import { weatherModule } from '@qodalis/cli-weather';
527
- </script>
528
-
529
- <template>
530
- <CliConfigProvider :modules="[weatherModule]">
531
- <Cli />
532
- </CliConfigProvider>
533
- </template>
534
- ```
152
+ Register it like any plugin: the `modules` input/prop, `resolveCliModuleProvider(greetModule)` in Angular, or `engine.registerModule(greetModule)`. To publish a reusable plugin, scaffold it with [`npx @qodalis/create-cli-plugin`](https://www.npmjs.com/package/@qodalis/create-cli-plugin). See [Core concepts](https://cli.qodalis.com/docs/core-concepts) and [Create a plugin](https://cli.qodalis.com/docs/create-plugin).
535
153
 
536
- ## Extending with Inline Commands
154
+ ## Configuration
537
155
 
538
- For quick one-off commands without creating a full plugin, implement `ICliCommandProcessor` directly in your app:
156
+ Options go to the `options` input/prop or the `CliEngine` constructor:
539
157
 
540
158
  ```typescript
541
- import {
542
- ICliCommandProcessor,
543
- CliProcessCommand,
544
- ICliExecutionContext,
545
- } from '@qodalis/cli-core';
546
-
547
- export class GreetCommandProcessor implements ICliCommandProcessor {
548
- command = 'greet';
549
- description = 'Greet someone by name';
550
- acceptsRawInput = true;
551
- valueRequired = true;
552
-
553
- async processCommand(
554
- command: CliProcessCommand,
555
- context: ICliExecutionContext,
556
- ): Promise<void> {
557
- context.writer.writeln(`Hello, ${command.value}!`);
558
- }
559
- }
560
- ```
561
-
562
- Register it with your framework (Angular: `resolveCommandProcessorProvider(GreetCommandProcessor)`, React/Vue: pass via `processors` prop), or wrap it in an inline `ICliModule`:
159
+ import { CliEngineOptions } from '@qodalis/cli';
563
160
 
564
- ```typescript
565
- const myModule: ICliModule = {
566
- apiVersion: 2,
567
- name: 'my-app-commands',
568
- processors: [new GreetCommandProcessor()],
161
+ const options: CliEngineOptions = {
162
+ welcome: { message: 'Welcome to My App', show: 'daily' }, // or false
163
+ servers: [{ name: 'node', url: 'http://localhost:8047' }],
164
+ terminalOptions: { fontSize: 14 },
569
165
  };
570
166
  ```
571
167
 
572
- ```bash
573
- ~$ greet World
574
- Hello, World!
575
- ```
576
-
577
- ## Using the Engine Directly
578
-
579
- For advanced use cases or non-framework environments, use `CliEngine` directly:
580
-
581
- ```typescript
582
- import { CliEngine } from '@qodalis/cli';
583
-
584
- const engine = new CliEngine(document.getElementById('terminal')!, {
585
- welcomeMessage: { message: 'Welcome!', show: 'always' },
586
- });
587
-
588
- engine.registerProcessors([new GreetCommandProcessor()]);
589
- await engine.start();
590
- ```
168
+ All options are listed in [Configuration](https://cli.qodalis.com/docs/configuration).
591
169
 
592
170
  ## Features
593
171
 
594
- - **Multi-framework** — Angular, React, Vue, or vanilla JS
595
- - **Command chaining** with `&&`, `||`, `|`, and `>>` operators
596
- - **Command history** with arrow key navigation
597
- - **Tab-like completions** and keyboard shortcuts (`Ctrl+C`, `Ctrl+L`, `Escape`)
598
- - **Theming** with built-in themes and custom color support
599
- - **User sessions** with multi-user support
600
- - **State persistence** across sessions
601
- - **Interactive prompts** with live preview (select menus with real-time feedback)
602
- - **Full-screen mode API** for rich TUI commands
603
- - **Progress bars, spinners, and text animations**
604
- - **Runtime package installation** from npm
172
+ - **Shell-like command line**: `&&`, `||`, `;`, pipes, `>`/`>>` redirects, aliases, history search, tab completion and readline shortcuts (`hotkeys` lists them).
173
+ - **Built-in commands**: `help`, `theme`, `pkg`, `history`, `alias`, `json`, `diff`, `random`, `timestamp`, `convert`, `color`, `clipboard`, `ps`/`kill`, `htop` and more. See [Built-in commands](https://cli.qodalis.com/docs/built-in-commands).
174
+ - **Runtime packages**: `pkg add guid` installs a plugin from npm (unpkg or jsdelivr) without rebuilding the app.
175
+ - **Interactive input**: line, password, confirm, select, multi-select and number prompts, progress bars, spinners and a full-screen mode for editors and games.
176
+ - **Themes**: 29 built-in themes, custom colors and fonts.
177
+ - **Panel**: a dockable panel with tabs, split panes, resizing and maximize.
178
+ - **Users and permissions** (users plugin): login, `su`, groups, permissions and per-user history.
179
+ - **Server integration**: run commands on a backend, stream output, open a remote shell, browse the server filesystem, query databases with the data explorer.
180
+ - **i18n**: 10 language packs.
181
+
182
+ ## Plugins
183
+
184
+ Install from npm and pass the module, or run `pkg add <name>` in the terminal.
185
+
186
+ | Package | Module | Commands |
187
+ | --- | --- | --- |
188
+ | [`@qodalis/cli-browser-storage`](https://www.npmjs.com/package/@qodalis/cli-browser-storage) | `browserStorageModule` | `local-storage`, `cookies` |
189
+ | [`@qodalis/cli-chart`](https://www.npmjs.com/package/@qodalis/cli-chart) | `chartModule` | `chart` |
190
+ | [`@qodalis/cli-cron`](https://www.npmjs.com/package/@qodalis/cli-cron) | `cronModule` | `cron` |
191
+ | [`@qodalis/cli-csv`](https://www.npmjs.com/package/@qodalis/cli-csv) | `csvModule` | `csv` |
192
+ | [`@qodalis/cli-curl`](https://www.npmjs.com/package/@qodalis/cli-curl) | `curlModule` | `curl` |
193
+ | [`@qodalis/cli-data-explorer`](https://www.npmjs.com/package/@qodalis/cli-data-explorer) | `dataExplorerModule` | `data-explorer` (SQL, MongoDB, Redis, Elasticsearch via a server) |
194
+ | [`@qodalis/cli-encode`](https://www.npmjs.com/package/@qodalis/cli-encode) | `encodeModule` | `base64`, `hex`, `url`, `jwt`, `hash`, `rot`, `morse`, `binary` |
195
+ | [`@qodalis/cli-files`](https://www.npmjs.com/package/@qodalis/cli-files) | `filesModule` | `ls`, `cd`, `cat`, `nano`, `mkdir`, `touch`, `rm`, `cp`, `grep`, `tree` |
196
+ | [`@qodalis/cli-guid`](https://www.npmjs.com/package/@qodalis/cli-guid) | `guidModule` | `guid` |
197
+ | [`@qodalis/cli-markdown`](https://www.npmjs.com/package/@qodalis/cli-markdown) | `markdownModule` | `md` |
198
+ | [`@qodalis/cli-password-generator`](https://www.npmjs.com/package/@qodalis/cli-password-generator) | `passwordGeneratorModule` | `generate-password` |
199
+ | [`@qodalis/cli-qr`](https://www.npmjs.com/package/@qodalis/cli-qr) | `qrModule` | `qr` |
200
+ | [`@qodalis/cli-regex`](https://www.npmjs.com/package/@qodalis/cli-regex) | `regexModule` | `regex` |
201
+ | [`@qodalis/cli-scp`](https://www.npmjs.com/package/@qodalis/cli-scp) | `scpModule` | `scp` |
202
+ | [`@qodalis/cli-server-jobs`](https://www.npmjs.com/package/@qodalis/cli-server-jobs) | `jobsModule` | `server jobs` |
203
+ | [`@qodalis/cli-server-logs`](https://www.npmjs.com/package/@qodalis/cli-server-logs) | `serverLogsModule` | `server logs` |
204
+ | [`@qodalis/cli-speed-test`](https://www.npmjs.com/package/@qodalis/cli-speed-test) | `speedTestModule` | `speed-test` |
205
+ | [`@qodalis/cli-stopwatch`](https://www.npmjs.com/package/@qodalis/cli-stopwatch) | `stopwatchModule` | `stopwatch` |
206
+ | [`@qodalis/cli-string`](https://www.npmjs.com/package/@qodalis/cli-string) | `stringModule` | `string` |
207
+ | [`@qodalis/cli-text-to-image`](https://www.npmjs.com/package/@qodalis/cli-text-to-image) | `textToImageModule` | `text-to-image` |
208
+ | [`@qodalis/cli-todo`](https://www.npmjs.com/package/@qodalis/cli-todo) | `todoModule` | `todo` |
209
+ | [`@qodalis/cli-users`](https://www.npmjs.com/package/@qodalis/cli-users) | `usersModule` | `login`, `su`, `whoami`, `adduser`, `perms`, `sessions`, ... |
210
+ | [`@qodalis/cli-wget`](https://www.npmjs.com/package/@qodalis/cli-wget) | `wgetModule` | `wget` |
211
+ | [`@qodalis/cli-yesno`](https://www.npmjs.com/package/@qodalis/cli-yesno) | `yesnoModule` | `yesno` |
212
+
213
+ **Games**: [`@qodalis/cli-2048`](https://www.npmjs.com/package/@qodalis/cli-2048) (`game2048Module`), [`@qodalis/cli-minesweeper`](https://www.npmjs.com/package/@qodalis/cli-minesweeper), [`@qodalis/cli-snake`](https://www.npmjs.com/package/@qodalis/cli-snake), [`@qodalis/cli-sudoku`](https://www.npmjs.com/package/@qodalis/cli-sudoku), [`@qodalis/cli-tetris`](https://www.npmjs.com/package/@qodalis/cli-tetris), [`@qodalis/cli-wordle`](https://www.npmjs.com/package/@qodalis/cli-wordle).
214
+
215
+ **Language packs**: `@qodalis/cli-lang-<code>` for `de`, `es`, `fr`, `it`, `ja`, `ko`, `pt`, `ro`, `ru`, `zh` (`langDeModule`, ...).
216
+
217
+ Details and examples for each plugin: [Plugins](https://cli.qodalis.com/docs/plugins).
218
+
219
+ ## Ecosystem
220
+
221
+ | Repository | What it is |
222
+ | --- | --- |
223
+ | [cli-server-node](https://github.com/qodalis-solutions/cli-server-node) | Node.js server (`@qodalis/cli-server-node`): server commands, shell, filesystem, data explorer, jobs, MCP |
224
+ | [cli-server-dotnet](https://github.com/qodalis-solutions/cli-server-dotnet) | The same server for ASP.NET Core (NuGet `Qodalis.Cli`) |
225
+ | [cli-server-python](https://github.com/qodalis-solutions/cli-server-python) | The same server for FastAPI (PyPI `qodalis-cli-server`) |
226
+ | [cli-server-dashboard](https://github.com/qodalis-solutions/cli-server-dashboard) | Admin dashboard the servers serve at `/qcli/admin` |
227
+ | [mcp-cli](https://github.com/qodalis-solutions/mcp-cli) | `@qodalis/mcp-cli`: MCP server for Claude Code and other AI clients |
228
+ | [pwa-cli](https://github.com/qodalis-solutions/pwa-cli) | The terminal as an installable PWA and an [Android app](https://play.google.com/store/apps/details?id=com.qodalis.cli) |
229
+ | [Angular](https://github.com/qodalis-solutions/qodalis-cli-angular-example), [React](https://github.com/qodalis-solutions/qodalis-cli-react-example), [Vue](https://github.com/qodalis-solutions/qodalis-cli-vue-example) and [vanilla](https://github.com/qodalis-solutions/qodalis-cli-vanilla-example) examples | Starter apps using the npm packages ([try them online](#try-it-online)) |
230
+
231
+ Connecting a server: [Server integration](https://cli.qodalis.com/docs/server-integration).
232
+
233
+ ## AI-assisted development
234
+
235
+ - **[`@qodalis/mcp-cli`](https://www.npmjs.com/package/@qodalis/mcp-cli)** gives Claude Code (or any MCP client) the docs, the published API declarations and the plugin scaffolder, with no server needed:
236
+
237
+ ```bash
238
+ claude mcp add qcli -- npx -y @qodalis/mcp-cli
239
+ ```
240
+
241
+ Set `QCLI_URL` (and `QCLI_TOKEN`) to also expose a running server's commands, filesystem and data sources as MCP tools.
242
+ - **[llms.txt](https://cli.qodalis.com/llms.txt)** and **[llms-full.txt](https://cli.qodalis.com/llms-full.txt)**: the plugin API guide for language models.
243
+
244
+ See [AI plugin development](https://cli.qodalis.com/docs/ai-plugin-development).
245
+
246
+ ## Development
247
+
248
+ This repository is a pnpm 12 + Nx 24 monorepo (Node 22):
605
249
 
606
- ## Contributing
607
-
608
- 1. Fork this repository
609
- 2. Create a branch for your feature or bugfix
610
- 3. Submit a pull request
250
+ ```bash
251
+ pnpm install
252
+ pnpm run build # all packages, in dependency order
253
+ pnpm exec nx test <project> # Jasmine + Karma (ChromeHeadless), e.g. nx test guid
254
+ pnpm run lint
255
+ pnpm run serve:docs # docs site on http://localhost:4300
256
+ pnpm run serve:angular-demo # also serve:react-demo, serve:vue-demo, serve:vanilla-demo
257
+ pnpm run create-plugin -- --name <name> --description "<desc>" --processor-name <Name>
258
+ ```
259
+
260
+ | Path | Contents |
261
+ | --- | --- |
262
+ | `packages/core` | `@qodalis/cli-core`: interfaces, models, themes, utilities |
263
+ | `packages/cli` | `@qodalis/cli`: the engine and built-in commands |
264
+ | `packages/angular-cli`, `react-cli`, `vue-cli`, `electron-cli` | Framework wrappers |
265
+ | `packages/create-cli-plugin` | Plugin scaffolder |
266
+ | `packages/plugins/*` | The 40 plugins |
267
+ | `apps/` | Docs site and demo apps |
268
+
269
+ [CONTRIBUTING.md](https://github.com/qodalis-solutions/web-cli/blob/main/CONTRIBUTING.md) covers branches and pull requests, [DEVELOPER.md](https://github.com/qodalis-solutions/web-cli/blob/main/DEVELOPER.md) the architecture and build details.
611
270
 
612
271
  ## License
613
272
 
614
- MIT
273
+ [MIT](https://github.com/qodalis-solutions/web-cli/blob/main/LICENSE)