@wooksjs/event-cli 0.6.2 → 0.6.4

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
@@ -44,3 +44,27 @@ app.run()
44
44
  ## Documentation
45
45
 
46
46
  To check out docs, visit [wooks.moost.org](https://wooks.moost.org/cliapp/).
47
+
48
+ ## AI Agent Skills
49
+
50
+ This package ships with structured skill files for AI coding agents (Claude Code, Cursor, Windsurf, Codex, etc.).
51
+
52
+ ```bash
53
+ # Project-local (recommended — version-locked, commits with your repo)
54
+ npx @wooksjs/event-cli setup-skills
55
+
56
+ # Global (available across all your projects)
57
+ npx @wooksjs/event-cli setup-skills --global
58
+ ```
59
+
60
+ To keep skills automatically up-to-date, add a postinstall script to your `package.json`:
61
+
62
+ ```json
63
+ {
64
+ "scripts": {
65
+ "postinstall": "npx @wooksjs/event-cli setup-skills --postinstall"
66
+ }
67
+ }
68
+ ```
69
+
70
+ This ensures the skill files are refreshed whenever dependencies are installed, without needing a separate command.
package/dist/index.cjs CHANGED
@@ -27,6 +27,7 @@ const wooks = __toESM(require("wooks"));
27
27
  const __wooksjs_event_core = __toESM(require("@wooksjs/event-core"));
28
28
 
29
29
  //#region packages/event-cli/src/event-cli.ts
30
+ /** Creates a new async event context for a CLI command invocation. */
30
31
  function createCliContext(data, options) {
31
32
  return (0, __wooksjs_event_core.createAsyncEventContext)({
32
33
  event: {
@@ -47,7 +48,9 @@ function useCliContext() {
47
48
 
48
49
  //#endregion
49
50
  //#region packages/event-cli/src/cli-adapter.ts
51
+ /** Shortcut mappings for CLI event methods. */
50
52
  const cliShortcuts = { cli: "CLI" };
53
+ /** Wooks adapter for building CLI applications with command routing and help generation. */
51
54
  var WooksCli = class extends wooks.WooksAdapterBase {
52
55
  logger;
53
56
  cliHelp;
@@ -213,10 +216,16 @@ var WooksCli = class extends wooks.WooksAdapterBase {
213
216
  }
214
217
  };
215
218
  /**
216
- * Factory for WooksCli App
217
- * @param opts TWooksCliOptions
218
- * @param wooks Wooks | WooksAdapterBase
219
- * @returns WooksCli
219
+ * Creates a new WooksCli application instance.
220
+ * @param opts - CLI adapter configuration options
221
+ * @param wooks - Optional existing Wooks or adapter instance to attach to
222
+ * @returns A new WooksCli instance
223
+ * @example
224
+ * ```ts
225
+ * const app = createCliApp()
226
+ * app.cli('greet/:name', () => `Hello, ${useRouteParams().get('name')}!`)
227
+ * app.run()
228
+ * ```
220
229
  */
221
230
  function createCliApp(opts, wooks$1) {
222
231
  return new WooksCli(opts, wooks$1);
@@ -243,6 +252,13 @@ function useCliOptions() {
243
252
  *
244
253
  * @param name name of the option
245
254
  * @returns value of a CLI option
255
+ * @example
256
+ * ```ts
257
+ * const verbose = useCliOption('verbose')
258
+ * if (verbose) {
259
+ * console.log('Verbose mode enabled')
260
+ * }
261
+ * ```
246
262
  */
247
263
  function useCliOption(name) {
248
264
  try {
@@ -251,7 +267,7 @@ function useCliOption(name) {
251
267
  if (opt) {
252
268
  for (const key of opt.keys) if (useCliOptions()[key]) return useCliOptions()[key];
253
269
  }
254
- } catch (error) {}
270
+ } catch {}
255
271
  return useCliOptions()[name];
256
272
  }
257
273
 
@@ -357,7 +373,7 @@ function useCommandLookupHelp(lookupDepth = 3) {
357
373
  break;
358
374
  } catch (error) {
359
375
  const variants = cliHelp.lookup(pathParams);
360
- if (variants.length > 0) throw new Error(`Wrong command, did you mean:\n${variants.slice(0, 7).map((c) => ` $ ${cmd} ${c.main.command}`).join("\n")}`);
376
+ if (variants.length > 0) throw new Error(`Wrong command, did you mean:\n${variants.slice(0, 7).map((c) => ` $ ${cmd} ${c.main.command}`).join("\n")}`, { cause: error });
361
377
  }
362
378
  }
363
379
  if (data) {
package/dist/index.d.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  import * as wooks from 'wooks';
2
2
  import { TWooksHandler, TWooksOptions, WooksAdapterBase, Wooks } from 'wooks';
3
3
  import * as _prostojs_cli_help from '@prostojs/cli-help';
4
- import { CliHelpRenderer, TCliHelpOptions, TCliEntry } from '@prostojs/cli-help';
4
+ import { CliHelpRenderer, TCliEntry, TCliHelpOptions } from '@prostojs/cli-help';
5
5
  import { TConsoleBase } from '@prostojs/logger';
6
6
  import * as _wooksjs_event_core from '@wooksjs/event-core';
7
7
  import { TEventOptions, TEmpty } from '@wooksjs/event-core';
8
8
  import minimist from 'minimist';
9
9
  import { TProstoRouterPathHandle } from '@prostojs/router';
10
10
 
11
+ /** Event data describing a CLI command invocation. */
11
12
  interface TCliEventData {
12
13
  argv: string[];
13
14
  pathParams: string[];
@@ -16,9 +17,11 @@ interface TCliEventData {
16
17
  type: 'CLI';
17
18
  cliHelp: TCliHelpRenderer;
18
19
  }
20
+ /** Context store for CLI events, holding parsed flags. */
19
21
  interface TCliContextStore {
20
22
  flags?: Record<string, boolean | string>;
21
23
  }
24
+ /** Custom data attached to CLI help entries for handler resolution. */
22
25
  interface TCliHelpCustom {
23
26
  handler: TWooksHandler<any>;
24
27
  /**
@@ -29,11 +32,14 @@ interface TCliHelpCustom {
29
32
  */
30
33
  cb?: <T>(path: string, aliasType: number, route?: TProstoRouterPathHandle<T>) => void;
31
34
  }
35
+ /** CLI help renderer type parameterized with custom help data. */
32
36
  type TCliHelpRenderer = CliHelpRenderer<TCliHelpCustom>;
33
37
 
38
+ /** Shortcut mappings for CLI event methods. */
34
39
  declare const cliShortcuts: {
35
40
  cli: string;
36
41
  };
42
+ /** Configuration options for the WooksCli adapter. */
37
43
  interface TWooksCliOptions {
38
44
  onError?: (e: Error) => void;
39
45
  onNotFound?: TWooksHandler;
@@ -43,10 +49,12 @@ interface TWooksCliOptions {
43
49
  cliHelp?: TCliHelpRenderer | TCliHelpOptions;
44
50
  router?: TWooksOptions['router'];
45
51
  }
52
+ /** Entry definition for registering a CLI command with its handler and help metadata. */
46
53
  interface TWooksCliEntry<T> extends Omit<TCliEntry<TWooksHandler<T>>, 'custom' | 'command'> {
47
54
  onRegister?: TCliHelpCustom['cb'];
48
55
  handler: TWooksHandler<T>;
49
56
  }
57
+ /** Wooks adapter for building CLI applications with command routing and help generation. */
50
58
  declare class WooksCli extends WooksAdapterBase {
51
59
  protected opts?: TWooksCliOptions | undefined;
52
60
  protected logger: TConsoleBase;
@@ -112,10 +120,16 @@ declare class WooksCli extends WooksAdapterBase {
112
120
  protected error(e: string | Error): void;
113
121
  }
114
122
  /**
115
- * Factory for WooksCli App
116
- * @param opts TWooksCliOptions
117
- * @param wooks Wooks | WooksAdapterBase
118
- * @returns WooksCli
123
+ * Creates a new WooksCli application instance.
124
+ * @param opts - CLI adapter configuration options
125
+ * @param wooks - Optional existing Wooks or adapter instance to attach to
126
+ * @returns A new WooksCli instance
127
+ * @example
128
+ * ```ts
129
+ * const app = createCliApp()
130
+ * app.cli('greet/:name', () => `Hello, ${useRouteParams().get('name')}!`)
131
+ * app.run()
132
+ * ```
119
133
  */
120
134
  declare function createCliApp(opts?: TWooksCliOptions, wooks?: Wooks | WooksAdapterBase): WooksCli;
121
135
 
@@ -208,9 +222,17 @@ declare function useCliOptions(): Record<string, string | boolean>;
208
222
  *
209
223
  * @param name name of the option
210
224
  * @returns value of a CLI option
225
+ * @example
226
+ * ```ts
227
+ * const verbose = useCliOption('verbose')
228
+ * if (verbose) {
229
+ * console.log('Verbose mode enabled')
230
+ * }
231
+ * ```
211
232
  */
212
233
  declare function useCliOption(name: string): string | boolean;
213
234
 
235
+ /** Creates a new async event context for a CLI command invocation. */
214
236
  declare function createCliContext(data: Omit<TCliEventData, 'type'>, options: TEventOptions): <T>(cb: (...a: any[]) => T) => T;
215
237
  /**
216
238
  * Wrapper on top of useEventContext that provides
@@ -219,4 +241,5 @@ declare function createCliContext(data: Omit<TCliEventData, 'type'>, options: TE
219
241
  */
220
242
  declare function useCliContext<T extends TEmpty>(): _wooksjs_event_core.TCtxHelpers<TCliContextStore & T & _wooksjs_event_core.TGenericContextStore<TCliEventData>>;
221
243
 
222
- export { type TCliContextStore, type TCliEventData, type TCliHelpCustom, type TCliHelpRenderer, type TWooksCliEntry, type TWooksCliOptions, WooksCli, cliShortcuts, createCliApp, createCliContext, useAutoHelp, useCliContext, useCliHelp, useCliOption, useCliOptions, useCommandLookupHelp };
244
+ export { WooksCli, cliShortcuts, createCliApp, createCliContext, useAutoHelp, useCliContext, useCliHelp, useCliOption, useCliOptions, useCommandLookupHelp };
245
+ export type { TCliContextStore, TCliEventData, TCliHelpCustom, TCliHelpRenderer, TWooksCliEntry, TWooksCliOptions };
package/dist/index.mjs CHANGED
@@ -4,6 +4,7 @@ import { WooksAdapterBase } from "wooks";
4
4
  import { createAsyncEventContext, useAsyncEventContext } from "@wooksjs/event-core";
5
5
 
6
6
  //#region packages/event-cli/src/event-cli.ts
7
+ /** Creates a new async event context for a CLI command invocation. */
7
8
  function createCliContext(data, options) {
8
9
  return createAsyncEventContext({
9
10
  event: {
@@ -24,7 +25,9 @@ function useCliContext() {
24
25
 
25
26
  //#endregion
26
27
  //#region packages/event-cli/src/cli-adapter.ts
28
+ /** Shortcut mappings for CLI event methods. */
27
29
  const cliShortcuts = { cli: "CLI" };
30
+ /** Wooks adapter for building CLI applications with command routing and help generation. */
28
31
  var WooksCli = class extends WooksAdapterBase {
29
32
  logger;
30
33
  cliHelp;
@@ -190,10 +193,16 @@ var WooksCli = class extends WooksAdapterBase {
190
193
  }
191
194
  };
192
195
  /**
193
- * Factory for WooksCli App
194
- * @param opts TWooksCliOptions
195
- * @param wooks Wooks | WooksAdapterBase
196
- * @returns WooksCli
196
+ * Creates a new WooksCli application instance.
197
+ * @param opts - CLI adapter configuration options
198
+ * @param wooks - Optional existing Wooks or adapter instance to attach to
199
+ * @returns A new WooksCli instance
200
+ * @example
201
+ * ```ts
202
+ * const app = createCliApp()
203
+ * app.cli('greet/:name', () => `Hello, ${useRouteParams().get('name')}!`)
204
+ * app.run()
205
+ * ```
197
206
  */
198
207
  function createCliApp(opts, wooks) {
199
208
  return new WooksCli(opts, wooks);
@@ -220,6 +229,13 @@ function useCliOptions() {
220
229
  *
221
230
  * @param name name of the option
222
231
  * @returns value of a CLI option
232
+ * @example
233
+ * ```ts
234
+ * const verbose = useCliOption('verbose')
235
+ * if (verbose) {
236
+ * console.log('Verbose mode enabled')
237
+ * }
238
+ * ```
223
239
  */
224
240
  function useCliOption(name) {
225
241
  try {
@@ -228,7 +244,7 @@ function useCliOption(name) {
228
244
  if (opt) {
229
245
  for (const key of opt.keys) if (useCliOptions()[key]) return useCliOptions()[key];
230
246
  }
231
- } catch (error) {}
247
+ } catch {}
232
248
  return useCliOptions()[name];
233
249
  }
234
250
 
@@ -334,7 +350,7 @@ function useCommandLookupHelp(lookupDepth = 3) {
334
350
  break;
335
351
  } catch (error) {
336
352
  const variants = cliHelp.lookup(pathParams);
337
- if (variants.length > 0) throw new Error(`Wrong command, did you mean:\n${variants.slice(0, 7).map((c) => ` $ ${cmd} ${c.main.command}`).join("\n")}`);
353
+ if (variants.length > 0) throw new Error(`Wrong command, did you mean:\n${variants.slice(0, 7).map((c) => ` $ ${cmd} ${c.main.command}`).join("\n")}`, { cause: error });
338
354
  }
339
355
  }
340
356
  if (data) {
package/package.json CHANGED
@@ -1,48 +1,48 @@
1
1
  {
2
2
  "name": "@wooksjs/event-cli",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "description": "@wooksjs/event-cli",
5
- "main": "dist/index.cjs",
6
- "module": "dist/index.mjs",
7
- "types": "dist/index.d.ts",
8
- "files": [
9
- "dist"
10
- ],
11
- "exports": {
12
- "./package.json": "./package.json",
13
- ".": {
14
- "require": "./dist/index.cjs",
15
- "import": "./dist/index.mjs",
16
- "types": "./dist/index.d.ts"
17
- }
18
- },
19
- "repository": {
20
- "type": "git",
21
- "url": "git+https://github.com/wooksjs/wooksjs.git",
22
- "directory": "packages/event-cli"
23
- },
24
5
  "keywords": [
25
- "http",
26
- "wooks",
6
+ "api",
7
+ "app",
27
8
  "composables",
28
- "web",
29
9
  "framework",
30
- "app",
31
- "api",
10
+ "http",
11
+ "prostojs",
32
12
  "rest",
33
13
  "restful",
34
- "prostojs"
14
+ "web",
15
+ "wooks"
35
16
  ],
36
- "author": "Artem Maltsev",
37
- "license": "MIT",
17
+ "homepage": "https://github.com/wooksjs/wooksjs/tree/main/packages/event-cli#readme",
38
18
  "bugs": {
39
19
  "url": "https://github.com/wooksjs/wooksjs/issues"
40
20
  },
41
- "peerDependencies": {
42
- "@prostojs/logger": "^0.4.3",
43
- "@prostojs/router": "^0.2.1",
44
- "@wooksjs/event-core": "^0.6.2",
45
- "wooks": "^0.6.2"
21
+ "license": "MIT",
22
+ "author": "Artem Maltsev",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/wooksjs/wooksjs.git",
26
+ "directory": "packages/event-cli"
27
+ },
28
+ "bin": {
29
+ "setup-skills": "scripts/setup-skills.js"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "skills",
34
+ "scripts"
35
+ ],
36
+ "main": "dist/index.cjs",
37
+ "module": "dist/index.mjs",
38
+ "types": "dist/index.d.ts",
39
+ "exports": {
40
+ "./package.json": "./package.json",
41
+ ".": {
42
+ "types": "./dist/index.d.ts",
43
+ "require": "./dist/index.cjs",
44
+ "import": "./dist/index.mjs"
45
+ }
46
46
  },
47
47
  "dependencies": {
48
48
  "@prostojs/cli-help": "^0.0.11",
@@ -50,11 +50,20 @@
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/minimist": "^1.2.5",
53
- "typescript": "^5.8.3",
54
- "vitest": "^3.2.4"
53
+ "typescript": "^5.9.3",
54
+ "vitest": "^3.2.4",
55
+ "@wooksjs/event-core": "^0.6.4",
56
+ "wooks": "^0.6.4"
57
+ },
58
+ "peerDependencies": {
59
+ "@prostojs/logger": "^0.4.3",
60
+ "@prostojs/router": "^0.2.1",
61
+ "wooks": "^0.6.4",
62
+ "@wooksjs/event-core": "^0.6.4"
55
63
  },
56
- "homepage": "https://github.com/wooksjs/wooksjs/tree/main/packages/event-cli#readme",
57
64
  "scripts": {
58
- "build": "rolldown -c ../../rolldown.config.mjs"
65
+ "build": "rolldown -c ../../rolldown.config.mjs",
66
+ "postinstall": "node scripts/setup-skills.js",
67
+ "setup-skills": "node scripts/setup-skills.js"
59
68
  }
60
69
  }
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ /* prettier-ignore */
3
+ 'use strict'
4
+
5
+ const fs = require('fs')
6
+ const path = require('path')
7
+ const os = require('os')
8
+
9
+ const SKILL_NAME = 'wooksjs-event-cli'
10
+ const SKILL_SRC = path.join(__dirname, '..', 'skills', SKILL_NAME)
11
+
12
+ if (!fs.existsSync(SKILL_SRC)) {
13
+ console.error(`No skills found at ${SKILL_SRC}`)
14
+ console.error('Add your SKILL.md files to the skills/' + SKILL_NAME + '/ directory first.')
15
+ process.exit(1)
16
+ }
17
+
18
+ const AGENTS = {
19
+ 'Claude Code': { dir: '.claude/skills', global: path.join(os.homedir(), '.claude', 'skills') },
20
+ 'Cursor': { dir: '.cursor/skills', global: path.join(os.homedir(), '.cursor', 'skills') },
21
+ 'Windsurf': { dir: '.windsurf/skills', global: path.join(os.homedir(), '.windsurf', 'skills') },
22
+ 'Codex': { dir: '.codex/skills', global: path.join(os.homedir(), '.codex', 'skills') },
23
+ 'OpenCode': { dir: '.opencode/skills', global: path.join(os.homedir(), '.opencode', 'skills') },
24
+ }
25
+
26
+ const args = process.argv.slice(2)
27
+ const isGlobal = args.includes('--global') || args.includes('-g')
28
+ const isPostinstall = args.includes('--postinstall')
29
+ let installed = 0, skipped = 0
30
+ const installedDirs = []
31
+
32
+ for (const [agentName, cfg] of Object.entries(AGENTS)) {
33
+ const targetBase = isGlobal ? cfg.global : path.join(process.cwd(), cfg.dir)
34
+ const agentRootDir = path.dirname(cfg.global) // Check if the agent has ever been installed globally
35
+
36
+ // In postinstall mode: silently skip agents that aren't set up globally
37
+ if (isPostinstall || isGlobal) {
38
+ if (!fs.existsSync(agentRootDir)) { skipped++; continue }
39
+ }
40
+
41
+ const dest = path.join(targetBase, SKILL_NAME)
42
+ try {
43
+ fs.mkdirSync(dest, { recursive: true })
44
+ fs.cpSync(SKILL_SRC, dest, { recursive: true })
45
+ console.log(`✅ ${agentName}: installed to ${dest}`)
46
+ installed++
47
+ if (!isGlobal) installedDirs.push(cfg.dir + '/' + SKILL_NAME)
48
+ } catch (err) {
49
+ console.warn(`⚠️ ${agentName}: failed — ${err.message}`)
50
+ }
51
+ }
52
+
53
+ // Add locally-installed skill dirs to .gitignore
54
+ if (!isGlobal && installedDirs.length > 0) {
55
+ const gitignorePath = path.join(process.cwd(), '.gitignore')
56
+ let gitignoreContent = ''
57
+ try { gitignoreContent = fs.readFileSync(gitignorePath, 'utf8') } catch {}
58
+ const linesToAdd = installedDirs.filter(d => !gitignoreContent.includes(d))
59
+ if (linesToAdd.length > 0) {
60
+ const hasHeader = gitignoreContent.includes('# AI agent skills')
61
+ const block = (gitignoreContent && !gitignoreContent.endsWith('\n') ? '\n' : '')
62
+ + (hasHeader ? '' : '\n# AI agent skills (auto-generated by setup-skills)\n')
63
+ + linesToAdd.join('\n') + '\n'
64
+ fs.appendFileSync(gitignorePath, block)
65
+ console.log(`📝 Added ${linesToAdd.length} entries to .gitignore`)
66
+ }
67
+ }
68
+
69
+ if (installed === 0 && isPostinstall) {
70
+ // Silence is fine — no agents present, nothing to do
71
+ } else if (installed === 0 && skipped === Object.keys(AGENTS).length) {
72
+ console.log('No agent directories detected. Try --global or run without it for project-local install.')
73
+ } else if (installed === 0) {
74
+ console.log('Nothing installed. Run without --global to install project-locally.')
75
+ } else {
76
+ console.log(`\n✨ Done! Restart your AI agent to pick up the "${SKILL_NAME}" skill.`)
77
+ }
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: wooksjs-event-cli
3
+ description: Wooks CLI framework — composable, command-line application framework for Node.js. Load when building CLI apps with wooks; defining CLI commands or using the wooks router for command routing; using CLI composables (useCliOptions, useCliOption, useCliHelp, useAutoHelp, useCommandLookupHelp, useRouteParams); creating custom event context composables; working with @wooksjs/event-core context store (init, get, set, hook); parsing CLI flags and options; generating command help and usage text; handling unknown commands; building multi-command CLI tools.
4
+ ---
5
+
6
+ # @wooksjs/event-cli
7
+
8
+ A composable CLI framework for Node.js built on async context (AsyncLocalStorage). Instead of imperative argument parsing libraries, you call composable functions (`useCliOptions()`, `useCliHelp()`, etc.) anywhere in your command handler — flags are parsed on demand and cached per invocation.
9
+
10
+ ## How to use this skill
11
+
12
+ Read the domain file that matches the task. Do not load all files — only what you need.
13
+
14
+ | Domain | File | Load when... |
15
+ |--------|------|------------|
16
+ | Event context (core machinery) | [event-core.md](event-core.md) | Understanding the context store API (`init`/`get`/`set`/`hook`), creating custom composables, lazy evaluation and caching, building your own `use*()` functions |
17
+ | CLI app setup | [core.md](core.md) | Creating a CLI app, running commands, `createCliApp`, `app.run()`, error handling, unknown command handling, sharing routers, testing |
18
+ | Commands & help | [commands.md](commands.md) | Defining commands with `app.cli()`, command syntax (args, aliases, options, examples), help generation (`useCliHelp`, `useAutoHelp`, `useCommandLookupHelp`), accessing flags (`useCliOptions`, `useCliOption`), route params in CLI |
19
+
20
+ ## Quick reference
21
+
22
+ ```ts
23
+ import { useRouteParams } from '@wooksjs/event-core'
24
+ import { createCliApp, useCliOptions } from '@wooksjs/event-cli'
25
+
26
+ const app = createCliApp()
27
+ app.cli('greet/:name', () => {
28
+ const { get } = useRouteParams<{ name: string }>()
29
+ const flags = useCliOptions()
30
+ return `Hello, ${get('name')}!`
31
+ })
32
+ app.run()
33
+ ```
34
+
35
+ Key composables: `useCliOptions()`, `useCliOption(name)`, `useCliHelp()`, `useAutoHelp()`, `useCommandLookupHelp()`, `useRouteParams()`, `useEventId()`, `useEventLogger()`.