@a5c-ai/babysitter-github 0.1.1-staging.0a3fc67d

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/AGENTS.md ADDED
@@ -0,0 +1,41 @@
1
+ # Babysitter Orchestration Agent
2
+
3
+ You are operating under Babysitter orchestration. Babysitter manages complex, multi-step
4
+ workflows with event-sourced state management, hook-based extensibility, and human-in-the-loop
5
+ approval gates.
6
+
7
+ ## Key Behaviors
8
+
9
+ 1. **Follow the process definition exactly.** Each task in the workflow has been defined with
10
+ specific inputs, outputs, and quality criteria. Do not skip steps or improvise alternatives
11
+ unless explicitly told to by the orchestrator.
12
+
13
+ 2. **Report completion accurately.** When you finish a task, your output must match the expected
14
+ result schema. Do not fabricate results or claim success without evidence.
15
+
16
+ 3. **Respect breakpoints.** When you encounter a breakpoint (human approval gate), stop and wait.
17
+ Do not attempt to bypass or auto-approve breakpoints.
18
+
19
+ 4. **Use structured output.** When the orchestrator requests JSON output, respond with valid JSON
20
+ only. Do not wrap it in markdown code fences or add commentary outside the JSON.
21
+
22
+ 5. **Completion proof.** When you have completed all assigned work, output the completion proof
23
+ token provided by the orchestrator: `<promise>COMPLETION_PROOF</promise>`. This signals the
24
+ Stop hook to allow the session to end.
25
+
26
+ ## Environment
27
+
28
+ - **Harness**: GitHub Copilot CLI (`copilot`)
29
+ - **SDK CLI**: `babysitter` (installed globally or via npx)
30
+ - **State directory**: `.a5c/` in the project root
31
+ - **Run directory**: `.a5c/runs/<runId>/`
32
+
33
+ ## Commands
34
+
35
+ You can invoke babysitter CLI commands directly:
36
+
37
+ ```bash
38
+ babysitter run:status --run-id <id> --json # Check run status
39
+ babysitter task:list --run-id <id> --json # List pending tasks
40
+ babysitter task:post --run-id <id> --effect-id <eid> --json # Post task result
41
+ ```
package/README.md ADDED
@@ -0,0 +1,507 @@
1
+ # @a5c-ai/babysitter-github
2
+
3
+ Babysitter orchestration plugin for [GitHub Copilot CLI](https://docs.github.com/en/copilot/using-github-copilot/using-github-copilot-in-the-command-line).
4
+
5
+ This package ships a complete Copilot CLI plugin bundle -- skills, lifecycle
6
+ hooks, and SDK integration -- that lets you run Babysitter's event-sourced,
7
+ multi-step orchestration engine directly inside GitHub Copilot CLI sessions.
8
+ It uses the Babysitter SDK CLI and the shared `~/.a5c` process-library state.
9
+ The installer registers the plugin bundle and materializes the active skills
10
+ and hooks so Copilot CLI can execute Babysitter commands and hook scripts
11
+ directly.
12
+
13
+ ## Prerequisites
14
+
15
+ - **Node.js 22+**
16
+ - **GitHub Copilot CLI** (`copilot`) -- requires an active GitHub Copilot
17
+ subscription
18
+ - **Babysitter SDK CLI** (`@a5c-ai/babysitter-sdk`) -- installed globally
19
+
20
+ ## Installation
21
+
22
+ Install the SDK CLI first:
23
+
24
+ ```bash
25
+ npm install -g @a5c-ai/babysitter-sdk
26
+ ```
27
+
28
+ Then install the GitHub Copilot plugin globally:
29
+
30
+ ```bash
31
+ npm install -g @a5c-ai/babysitter-github
32
+ babysitter-github install
33
+ ```
34
+
35
+ Or install from source:
36
+
37
+ ```bash
38
+ cd plugins/babysitter-github
39
+ node bin/install.js
40
+ ```
41
+
42
+ Install into a specific workspace:
43
+
44
+ ```bash
45
+ babysitter-github install --workspace /path/to/repo
46
+ ```
47
+
48
+ If the workspace does not already have an active process-library binding, the
49
+ installer bootstraps the shared global SDK process library automatically:
50
+
51
+ ```bash
52
+ babysitter process-library:active --json
53
+ ```
54
+
55
+ ## Uninstallation
56
+
57
+ ```bash
58
+ babysitter-github uninstall
59
+ ```
60
+
61
+ ## Integration Model
62
+
63
+ The plugin provides:
64
+
65
+ - `skills/babysit/SKILL.md` as the core orchestration entrypoint
66
+ - Mode wrapper skills such as `$call`, `$plan`, and `$resume`
67
+ - Plugin-level lifecycle hooks for `SessionStart`, `UserPromptSubmit`, and
68
+ `Stop`
69
+
70
+ The process library is fetched and bound through the SDK CLI in
71
+ `~/.a5c/active/process-library.json`.
72
+
73
+ ### Active Process-Library Model
74
+
75
+ Process discovery prefers active roots in this order:
76
+
77
+ 1. `.a5c/processes` in the current workspace
78
+ 2. The SDK-managed active process-library binding returned by
79
+ `babysitter process-library:active --json`
80
+ 3. The cloned process-library repo root from `defaultSpec.cloneDir` when
81
+ adjacent reference material is needed
82
+ 4. Installed extension content only as a compatibility fallback
83
+
84
+ ## Available Skills
85
+
86
+ The plugin registers ten skills that surface as slash commands within Copilot
87
+ CLI:
88
+
89
+ | Skill | Description |
90
+ |-------|-------------|
91
+ | `babysit` | Core entrypoint. Orchestrate `.a5c/runs/<runId>/` through iterative execution. Invoke when asked to babysit, orchestrate, or run a workflow. |
92
+ | `call` | Start a new orchestration run. Everything after `$call` becomes the initial Babysitter request. Always creates an interactive run. |
93
+ | `plan` | Design a process definition without executing it. Useful for reviewing or refining a workflow before committing to a run. |
94
+ | `resume` | Resume an incomplete or paused orchestration run from where it left off. |
95
+ | `doctor` | Diagnose run health -- journal integrity, state cache, effects, locks, sessions, logs, and disk usage. |
96
+ | `retrospect` | Analyze a completed run: results, process quality, and suggestions for process improvements and optimizations. |
97
+ | `observe` | Launch the real-time observer dashboard to watch active runs. |
98
+ | `assimilate` | Assimilate an external methodology, harness, or specification into Babysitter process definitions. |
99
+ | `help` | Show documentation for Babysitter command usage, processes, skills, agents, and methodologies. |
100
+ | `user-install` | Set up Babysitter for yourself -- installs dependencies, interviews you about preferences, and configures user-level defaults. |
101
+
102
+ ## How the Hook-Driven Orchestration Loop Works
103
+
104
+ GitHub Copilot CLI supports plugin lifecycle hooks. This plugin registers
105
+ three hooks that drive the orchestration loop:
106
+
107
+ ### SessionStart
108
+
109
+ Fires when a new Copilot CLI session begins. The hook:
110
+
111
+ 1. Initializes a Babysitter session for the active Copilot session
112
+ 2. Ensures the SDK CLI is installed at the correct version (pinned in
113
+ `versions.json`)
114
+ 3. Creates baseline session state in the `.a5c` state directory
115
+
116
+ ### Stop
117
+
118
+ The orchestration loop driver. When Copilot CLI attempts to end its turn,
119
+ this hook intercepts the exit and:
120
+
121
+ 1. Checks whether the active run has completed or emitted a completion proof
122
+ 2. If the run is still in progress, re-injects the next orchestration step
123
+ to continue iteration
124
+ 3. Only allows the session to exit when the run finishes or reaches a
125
+ breakpoint requiring human input
126
+
127
+ This is what keeps Babysitter iterating autonomously within the Copilot CLI
128
+ session -- each turn performs one orchestration phase, and the Stop hook
129
+ decides whether to loop or yield.
130
+
131
+ ### UserPromptSubmit
132
+
133
+ Fires before a user prompt reaches the model. The hook applies
134
+ density-filter compression to long user prompts to reduce token usage while
135
+ preserving semantic content.
136
+
137
+ ## Configuration
138
+
139
+ ### AGENTS.md
140
+
141
+ The plugin uses `AGENTS.md` (the Copilot CLI equivalent of `CLAUDE.md`) for
142
+ custom agent instructions. This file is set via the `contextFileName` field
143
+ in `plugin.json` and is read by Copilot CLI to configure agent behavior
144
+ within sessions.
145
+
146
+ ### Environment Variables
147
+
148
+ | Variable | Default | Description |
149
+ |----------|---------|-------------|
150
+ | `CLAUDE_PROJECT_DIR` | CWD | Project root directory (set by Copilot CLI) |
151
+ | `BABYSITTER_LOG_DIR` | `<plugin>/.a5c/logs` | Log output directory |
152
+ | `BABYSITTER_STATE_DIR` | `<cwd>/.a5c` | State directory for session data |
153
+
154
+ ### SDK Version Pinning
155
+
156
+ The plugin pins its required SDK version in `versions.json`. The
157
+ SessionStart hook reads this file and ensures the correct version of
158
+ `@a5c-ai/babysitter-sdk` is installed globally before proceeding.
159
+
160
+ ## Copilot CLI Plugin Structure
161
+
162
+ This section documents the Copilot CLI plugin format that this package
163
+ conforms to. Understanding this structure is useful when extending the plugin
164
+ or building new ones.
165
+
166
+ ### Plugin Manifest Location
167
+
168
+ Copilot CLI looks for the plugin manifest in these paths, checked in order:
169
+
170
+ 1. `.plugin/plugin.json`
171
+ 2. `.github/plugin/plugin.json`
172
+ 3. `.claude-plugin/plugin.json`
173
+ 4. `plugin.json` (repository root)
174
+
175
+ The first match wins. This plugin uses `plugin.json` at the package root.
176
+
177
+ ### plugin.json Schema
178
+
179
+ The manifest declares metadata, skills, hooks, and optional integrations:
180
+
181
+ | Field | Required | Type | Description |
182
+ |-------|----------|------|-------------|
183
+ | `name` | Yes | `string` | Plugin identifier (e.g., `"babysitter"`) |
184
+ | `description` | No | `string` | Human-readable summary |
185
+ | `version` | No | `string` | Semver version string |
186
+ | `author` | No | `object` | Author info: `{ "name": "...", "email": "..." }` |
187
+ | `license` | No | `string` | SPDX license identifier |
188
+ | `keywords` | No | `string[]` | Searchable tags for marketplace discovery |
189
+ | `agents` | No | `string` | Path to agents directory |
190
+ | `skills` | No | `array` | Array of skill directory paths (see below) |
191
+ | `hooks` | No | `string` | Path to `hooks.json` |
192
+ | `mcpServers` | No | `string` | Path to `.mcp.json` for MCP server configuration |
193
+
194
+ Example from this plugin:
195
+
196
+ ```json
197
+ {
198
+ "name": "babysitter",
199
+ "version": "0.1.0",
200
+ "description": "Orchestrate complex, multi-step workflows ...",
201
+ "author": "a5c.ai",
202
+ "license": "MIT",
203
+ "hooks": {
204
+ "sessionStart": "hooks/session-start.sh",
205
+ "sessionEnd": "hooks/session-end.sh",
206
+ "userPromptSubmitted": "hooks/user-prompt-submitted.sh"
207
+ },
208
+ "skills": [
209
+ { "name": "babysit", "file": "skills/babysit/SKILL.md" },
210
+ { "name": "call", "file": "skills/call/SKILL.md" }
211
+ ],
212
+ "keywords": ["orchestration", "workflow", "automation"]
213
+ }
214
+ ```
215
+
216
+ ### Skills Format
217
+
218
+ Each skill lives in its own directory under `skills/` and is defined by a
219
+ Markdown file with YAML frontmatter:
220
+
221
+ ```
222
+ skills/
223
+ babysit/
224
+ SKILL.md
225
+ call/
226
+ SKILL.md
227
+ plan/
228
+ SKILL.md
229
+ ```
230
+
231
+ The `SKILL.md` file uses frontmatter to declare metadata:
232
+
233
+ ```markdown
234
+ ---
235
+ name: babysit
236
+ description: Orchestrate a multi-step workflow using the Babysitter SDK
237
+ ---
238
+
239
+ Skill body with instructions for the agent...
240
+ ```
241
+
242
+ The `name` and `description` fields in the frontmatter are required. The
243
+ body of the Markdown file contains the instructions the agent follows when
244
+ the skill is invoked.
245
+
246
+ ### hooks.json Format
247
+
248
+ The `hooks.json` file declares lifecycle hook handlers as an array of
249
+ command descriptors per event type:
250
+
251
+ ```json
252
+ {
253
+ "version": 1,
254
+ "hooks": {
255
+ "sessionStart": [
256
+ {
257
+ "type": "command",
258
+ "bash": "./hooks/session-start.sh",
259
+ "powershell": "./hooks/session-start.ps1",
260
+ "timeoutSec": 30
261
+ }
262
+ ],
263
+ "sessionEnd": [
264
+ {
265
+ "type": "command",
266
+ "bash": "./hooks/session-end.sh",
267
+ "powershell": "./hooks/session-end.ps1",
268
+ "timeoutSec": 30
269
+ }
270
+ ],
271
+ "userPromptSubmitted": [
272
+ {
273
+ "type": "command",
274
+ "bash": "./hooks/user-prompt-submitted.sh",
275
+ "powershell": "./hooks/user-prompt-submitted.ps1",
276
+ "timeoutSec": 30
277
+ }
278
+ ],
279
+ "preToolUse": [...],
280
+ "postToolUse": [...],
281
+ "errorOccurred": [...]
282
+ }
283
+ }
284
+ ```
285
+
286
+ Each hook entry specifies a `bash` and/or `powershell` command, a `type`
287
+ (currently always `"command"`), and an optional `timeoutSec`.
288
+
289
+ **Supported hook event types:**
290
+
291
+ | Event | Description |
292
+ |-------|-------------|
293
+ | `sessionStart` | Fires when a new CLI session begins |
294
+ | `sessionEnd` | Fires when a CLI session ends |
295
+ | `userPromptSubmitted` | Fires before a user prompt reaches the model |
296
+ | `preToolUse` | Fires before a tool is executed |
297
+ | `postToolUse` | Fires after a tool has executed |
298
+ | `errorOccurred` | Fires when an error is encountered |
299
+
300
+ **Flow-control decisions:** Only `preToolUse` hooks can return flow-control
301
+ decisions via the `permissionDecision` field in stdout JSON. Valid values
302
+ are `"deny"`, `"allow"`, and `"ask"`. All other hook event outputs are
303
+ ignored by the runtime.
304
+
305
+ ## Marketplace Distribution
306
+
307
+ Copilot CLI plugins can be distributed through marketplaces -- Git
308
+ repositories that contain a manifest listing available plugins.
309
+
310
+ ### Creating a Marketplace
311
+
312
+ A marketplace is a Git repository with a `marketplace.json` file in
313
+ `.github/plugin/` or `.claude-plugin/`:
314
+
315
+ ```json
316
+ {
317
+ "name": "a5c.ai",
318
+ "owner": {
319
+ "name": "a5c.ai",
320
+ "email": "support@a5c.ai"
321
+ },
322
+ "metadata": {
323
+ "description": "Babysitter orchestration plugins",
324
+ "version": "1.0.0"
325
+ },
326
+ "plugins": [
327
+ {
328
+ "name": "babysitter",
329
+ "description": "Multi-step workflow orchestration with event-sourced state",
330
+ "version": "0.1.0",
331
+ "source": "./plugins/babysitter-github"
332
+ }
333
+ ]
334
+ }
335
+ ```
336
+
337
+ The `source` field points to the plugin directory relative to the
338
+ marketplace repository root.
339
+
340
+ ### User Commands
341
+
342
+ Copilot CLI provides built-in commands for plugin and marketplace
343
+ management:
344
+
345
+ **Marketplace commands:**
346
+
347
+ ```bash
348
+ copilot plugin marketplace add OWNER/REPO # Register a marketplace
349
+ copilot plugin marketplace list # List registered marketplaces
350
+ copilot plugin marketplace browse NAME # Browse plugins in a marketplace
351
+ ```
352
+
353
+ **Plugin installation:**
354
+
355
+ ```bash
356
+ copilot plugin install PLUGIN@MARKETPLACE # Install from a marketplace
357
+ copilot plugin install OWNER/REPO # Install directly from a GitHub repo
358
+ copilot plugin install ./PATH # Install from a local path
359
+ ```
360
+
361
+ **Plugin management:**
362
+
363
+ ```bash
364
+ copilot plugin list # List installed plugins
365
+ copilot plugin update PLUGIN # Update a plugin
366
+ copilot plugin uninstall PLUGIN # Remove a plugin
367
+ ```
368
+
369
+ ### Plugin Storage
370
+
371
+ Installed plugins are stored under `~/.copilot/installed-plugins/`:
372
+
373
+ - **Marketplace installs:** `~/.copilot/installed-plugins/MARKETPLACE/PLUGIN-NAME/`
374
+ - **Direct installs:** `~/.copilot/installed-plugins/_direct/SOURCE-ID/`
375
+
376
+ ### Default Registries
377
+
378
+ Copilot CLI ships with two built-in registries:
379
+
380
+ - `copilot-plugins` -- official first-party plugins
381
+ - `awesome-copilot` -- community-curated plugin collection
382
+
383
+ These registries are available without running `marketplace add`.
384
+
385
+ ## Plugin Structure (Directory Layout)
386
+
387
+ ```
388
+ plugins/babysitter-github/
389
+ plugin.json # Plugin manifest (skills, hooks, metadata)
390
+ hooks.json # Hook configuration (sessionStart, sessionEnd, userPromptSubmitted)
391
+ hooks/
392
+ session-start.sh # SessionStart lifecycle hook
393
+ session-end.sh # SessionEnd lifecycle hook
394
+ user-prompt-submitted.sh # UserPromptSubmitted hook (prompt compression)
395
+ skills/
396
+ babysit/SKILL.md # Core orchestration skill
397
+ call/SKILL.md # Start a new run
398
+ plan/SKILL.md # Plan without executing
399
+ resume/SKILL.md # Resume an incomplete run
400
+ doctor/SKILL.md # Diagnose run health
401
+ retrospect/SKILL.md # Analyze completed runs
402
+ observe/SKILL.md # Observer dashboard
403
+ assimilate/SKILL.md # Assimilate external methodologies
404
+ help/SKILL.md # Help and documentation
405
+ user-install/SKILL.md # User setup
406
+ bin/
407
+ cli.js # CLI entry point (babysitter-github command)
408
+ install.js # Installation script
409
+ uninstall.js # Uninstallation script
410
+ scripts/
411
+ team-install.js # Team-level installation
412
+ versions.json # SDK version pinning
413
+ package.json # npm package metadata
414
+ AGENTS.md # Custom instructions for Copilot CLI
415
+ ```
416
+
417
+ ## Verification
418
+
419
+ Verify the installed plugin:
420
+
421
+ ```bash
422
+ npm ls -g @a5c-ai/babysitter-github --depth=0
423
+ ```
424
+
425
+ Verify the active shared process-library binding:
426
+
427
+ ```bash
428
+ babysitter process-library:active --json
429
+ ```
430
+
431
+ ## Troubleshooting
432
+
433
+ ### Hook not firing
434
+
435
+ Run the doctor skill from within a Copilot CLI session to diagnose hook and
436
+ session health:
437
+
438
+ ```text
439
+ $doctor
440
+ ```
441
+
442
+ ### Run stuck or not progressing
443
+
444
+ Check the run status and diagnose:
445
+
446
+ ```text
447
+ $doctor [run-id]
448
+ ```
449
+
450
+ You can also inspect the run directory directly:
451
+
452
+ ```bash
453
+ babysitter run:status --run-id <runId> --json
454
+ babysitter run:events --run-id <runId> --json
455
+ ```
456
+
457
+ ### SDK version mismatch
458
+
459
+ If the plugin reports version incompatibility, ensure the pinned SDK version
460
+ is installed:
461
+
462
+ ```bash
463
+ SDK_VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('versions.json','utf8')).sdkVersion)")
464
+ npm install -g @a5c-ai/babysitter-sdk@$SDK_VERSION
465
+ ```
466
+
467
+ ### Windows limitations
468
+
469
+ On native Windows, Copilot CLI may not execute hook scripts depending on
470
+ shell configuration. The plugin still installs correctly, but lifecycle hooks
471
+ may not fire. Using WSL or Git Bash is recommended. The `hooks.json` file
472
+ includes `powershell` entries alongside `bash` entries to improve Windows
473
+ compatibility where PowerShell execution is available.
474
+
475
+ ## Development / Contributing
476
+
477
+ ### Local development
478
+
479
+ ```bash
480
+ git clone https://github.com/a5c-ai/babysitter.git
481
+ cd babysitter
482
+ npm install
483
+ cd plugins/babysitter-github
484
+ node bin/install.js
485
+ ```
486
+
487
+ ### Publishing
488
+
489
+ ```bash
490
+ cd plugins/babysitter-github
491
+ npm run deploy # Publish to npm (public)
492
+ npm run deploy:staging # Publish to npm with staging tag
493
+ ```
494
+
495
+ ### Team installation
496
+
497
+ ```bash
498
+ cd plugins/babysitter-github
499
+ npm run team:install
500
+ ```
501
+
502
+ This sets up the plugin for all team members in a shared workspace,
503
+ writing team-level configuration to `.a5c/team/`.
504
+
505
+ ## License
506
+
507
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const path = require('path');
5
+ const { spawnSync } = require('child_process');
6
+
7
+ const PACKAGE_ROOT = path.resolve(__dirname, '..');
8
+
9
+ function printUsage() {
10
+ console.error([
11
+ 'Usage:',
12
+ ' babysitter-github install [--global]',
13
+ ' babysitter-github install --workspace [path]',
14
+ ' babysitter-github uninstall',
15
+ ].join('\n'));
16
+ }
17
+
18
+ function parseInstallArgs(argv) {
19
+ let scope = 'global';
20
+ let workspace = null;
21
+ const passthrough = [];
22
+
23
+ for (let i = 0; i < argv.length; i += 1) {
24
+ const arg = argv[i];
25
+ if (arg === '--global') {
26
+ if (scope === 'workspace') {
27
+ throw new Error('install accepts either --global or --workspace, not both');
28
+ }
29
+ scope = 'global';
30
+ continue;
31
+ }
32
+ if (arg === '--workspace') {
33
+ if (scope === 'global' && workspace !== null) {
34
+ throw new Error('install accepts either --global or --workspace, not both');
35
+ }
36
+ scope = 'workspace';
37
+ const next = argv[i + 1];
38
+ if (next && !next.startsWith('-')) {
39
+ workspace = path.resolve(next);
40
+ i += 1;
41
+ } else {
42
+ workspace = process.cwd();
43
+ }
44
+ continue;
45
+ }
46
+ passthrough.push(arg);
47
+ }
48
+
49
+ return {
50
+ scope,
51
+ workspace,
52
+ passthrough,
53
+ };
54
+ }
55
+
56
+ function runNodeScript(scriptPath, args, extraEnv = {}) {
57
+ const result = spawnSync(process.execPath, [scriptPath, ...args], {
58
+ cwd: process.cwd(),
59
+ stdio: 'inherit',
60
+ env: {
61
+ ...process.env,
62
+ ...extraEnv,
63
+ },
64
+ });
65
+ process.exitCode = result.status ?? 1;
66
+ }
67
+
68
+ function main() {
69
+ const [command, ...rest] = process.argv.slice(2);
70
+ if (!command || command === '--help' || command === '-h' || command === 'help') {
71
+ printUsage();
72
+ process.exitCode = command ? 0 : 1;
73
+ return;
74
+ }
75
+
76
+ if (command === 'install') {
77
+ const parsed = parseInstallArgs(rest);
78
+ if (parsed.scope === 'workspace') {
79
+ const args = [];
80
+ if (parsed.workspace) {
81
+ args.push('--workspace', parsed.workspace);
82
+ }
83
+ args.push(...parsed.passthrough);
84
+ runNodeScript(
85
+ path.join(PACKAGE_ROOT, 'scripts', 'team-install.js'),
86
+ args,
87
+ { BABYSITTER_PACKAGE_ROOT: PACKAGE_ROOT },
88
+ );
89
+ return;
90
+ }
91
+ runNodeScript(path.join(PACKAGE_ROOT, 'bin', 'install.js'), parsed.passthrough);
92
+ return;
93
+ }
94
+
95
+ if (command === 'uninstall') {
96
+ runNodeScript(path.join(PACKAGE_ROOT, 'bin', 'uninstall.js'), rest);
97
+ return;
98
+ }
99
+
100
+ printUsage();
101
+ process.exitCode = 1;
102
+ }
103
+
104
+ main();