You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: PLUGIN-HELP.md
+81-5Lines changed: 81 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,9 +6,46 @@ This document describes how c8ctl plugins can provide help text that gets integr
6
6
7
7
When users load plugins, their commands automatically appear in the help text. Plugins can optionally provide descriptions for their commands to make the help more informative.
8
8
9
+
## Global Plugin System
10
+
11
+
c8ctl uses a global plugin system where plugins are installed to a user-specific directory. This means:
12
+
13
+
-**No local package.json required**: Plugins work from any directory
14
+
-**Global installation**: Plugins are installed to OS-specific directories:
1.**Automatic Discovery**: When `c8ctl help` is invoked, it scans all loaded plugins
48
+
1.**Automatic Discovery**: When `c8ctl help` is invoked, it scans all loaded plugins from the global plugins directory
12
49
2.**Plugin Section**: If plugins are loaded, a "Plugin Commands" section appears at the bottom of the help text
13
50
3.**Command Listing**: Each plugin command is listed with its optional description
14
51
@@ -83,6 +120,7 @@ export const commands = {
83
120
## Help Output Example
84
121
85
122
Without plugins loaded:
123
+
86
124
```
87
125
c8ctl - Camunda 8 CLI v2.0.0
88
126
@@ -95,6 +133,7 @@ Commands:
95
133
```
96
134
97
135
With plugins loaded:
136
+
98
137
```
99
138
c8ctl - Camunda 8 CLI v2.0.0
100
139
@@ -121,6 +160,7 @@ The plugin loader ([src/plugin-loader.ts](src/plugin-loader.ts)) provides:
121
160
-`getPluginCommandNames()`: Returns array of command names
122
161
-`getPluginCommandsInfo()`: Returns detailed info including descriptions
123
162
- Automatic metadata extraction during plugin loading
163
+
- Scans the [global plugins directory](#global-plugin-system) for installed plugins
124
164
125
165
### Help Command
126
166
@@ -150,25 +190,59 @@ interface PluginMetadata {
150
190
2.**Keep descriptions concise**: Aim for one line (< 60 characters)
151
191
3.**Use imperative verbs**: Start with action words (Analyze, Deploy, Check, etc.)
152
192
4.**Match command names**: Ensure metadata command names match exported functions
153
-
5.**TypeScript plugins**: The `c8ctl-plugin.js` entry point must be JavaScript. Node.js doesn't support type stripping in `node_modules`. Transpile TypeScript to JavaScript before publishing your plugin.
6.**TypeScript plugins**: The `c8ctl-plugin.js` entry point must be JavaScript. Node.js doesn't support type stripping in `node_modules`. Transpile TypeScript to JavaScript before publishing your plugin.
Copy file name to clipboardExpand all lines: README.md
+41-8Lines changed: 41 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -308,9 +308,24 @@ Debug output is written to stderr with timestamps and won't interfere with norma
308
308
309
309
### Plugin Management
310
310
311
-
c8ctl supports a plugin system that allows extending the CLI with custom commands via npm packages. Plugins are tracked in a registry file (`~/.config/c8ctl/plugins.json` on Linux, similar locations on other platforms) for persistence across npm operations.
311
+
c8ctl supports a global plugin system that allows extending the CLI with custom commands via npm packages. Plugins are installed globally to a user-specific directory and tracked in a registry file.
-`✓ Installed` - Plugin is in registry and installed
343
-
-`⚠ Not installed` - Plugin is in registry but not in node_modules (run `sync`)
344
-
-`⚠ Not in registry` - Plugin is in package.json but not tracked in registry
370
+
-`⚠ Not installed` - Plugin is in registry but not in global directory (run `sync`)
371
+
-`⚠ Not in registry` - Plugin is installed but not tracked in registry
345
372
-`c8ctl sync plugins` synchronizes plugins from the registry, rebuilding or reinstalling as needed
346
373
374
+
**Plugin Development:**
375
+
- Use `c8ctl init plugin <name>` to scaffold a new plugin with TypeScript template
376
+
- Generated scaffold includes all necessary files and build configuration
377
+
- Plugins have access to the c8ctl runtime via `globalThis.c8ctl`
378
+
- See the bundled `hello-world` plugin in `default-plugins/` for a complete example
379
+
347
380
**Plugin Requirements:**
348
381
- Plugin packages must be regular Node.js modules
349
382
- They must include a `c8ctl-plugin.js` or `c8ctl-plugin.ts` file in the root directory
350
383
- The plugin file must export a `commands` object
351
384
- Optionally export a `metadata` object to provide help text
352
-
- Plugins are installed in `node_modules` like regular npm packages
385
+
- Plugins are installed globally and work from any directory
353
386
- The runtime object `c8ctl` provides environment information to plugins
354
387
-**Important**: `c8ctl-plugin.js` must be JavaScript. Node.js doesn't support type stripping in `node_modules`. If writing in TypeScript, transpile to JS before publishing.
> **Note:** Override with `C8CTL_DATA_DIR` environment variable if needed.
60
+
61
+
### Runtime Access
62
+
63
+
The plugin can access c8ctl runtime via `globalThis.c8ctl`:
64
+
65
+
```javascript
66
+
globalThis.c8ctl= {
67
+
version: string; // c8ctl version
68
+
nodeVersion: string; // Node.js version
69
+
platform: string; // OS platform
70
+
arch: string; // CPU architecture
71
+
cwd: string; // Current working directory
72
+
outputMode:'text'|'json'; // Output format
73
+
activeProfile?: string; // Active connection profile
74
+
activeTenant?: string; // Active tenant
75
+
};
76
+
```
77
+
78
+
### Command Implementation
79
+
80
+
Commands receive arguments and return promises:
81
+
82
+
```javascript
83
+
exportconstcommands= {
84
+
'command-name':async (args) => {
85
+
// args is an array of strings
86
+
// Use console.log for output
87
+
// Return a promise or async function
88
+
},
89
+
};
90
+
```
91
+
92
+
### Metadata
93
+
94
+
Provide help text via metadata export:
95
+
96
+
```javascript
97
+
exportconstmetadata= {
98
+
name:'plugin-name',
99
+
description:'Plugin description',
100
+
commands: {
101
+
'command-name': {
102
+
description:'Command description shown in help',
103
+
},
104
+
},
105
+
};
106
+
```
107
+
108
+
## Important Limitations
109
+
110
+
### Command Precedence
111
+
112
+
**Plugin commands cannot override built-in commands.** The c8ctl CLI always checks for built-in commands first. If a plugin exports a command with the same name as a built-in command (e.g., `list`, `get`, `create`), the built-in command will always execute, and the plugin command will be ignored.
113
+
114
+
For example, if a plugin tries to export a `list` command:
115
+
116
+
```javascript
117
+
exportconstcommands= {
118
+
'list':async (args) => {
119
+
console.log('This will NEVER execute');
120
+
}
121
+
};
122
+
```
123
+
124
+
When users run `c8ctl list`, the built-in `list` command will execute instead. Choose unique command names for your plugins to avoid conflicts.
125
+
126
+
## Development
127
+
128
+
To create a similar plugin:
129
+
130
+
1. Use the scaffolding command:
131
+
132
+
```bash
133
+
c8ctl init plugin my-plugin
134
+
```
135
+
136
+
2. Or manually create the structure following this example
137
+
138
+
3. Test locally:
139
+
140
+
```bash
141
+
c8ctl load plugin --from file:///path/to/plugin
142
+
```
143
+
144
+
4. Publish to npm:
145
+
146
+
```bash
147
+
npm publish
148
+
```
149
+
150
+
5. Users can install:
151
+
152
+
```bash
153
+
c8ctl load plugin your-plugin-name
154
+
```
155
+
156
+
## License
157
+
158
+
You decide, but our [own Drink-ware](/LICENSE.md) is of course the most fitting :)
0 commit comments