@glrs-dev/harness-plugin-opencode 2.4.1 → 2.7.0

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.
@@ -24,22 +24,13 @@ Every cognitive task is a subagent. You launch subagents and pass their outputs
24
24
 
25
25
  ## How to Invoke Research Agents
26
26
 
27
- The four research agents are available:
27
+ Dispatch research subagents via the task tool:
28
28
 
29
- 1. **`@research`** (this agent) umbrella orchestrator for multi-workstream research
30
- 2. **`@research-local`** — deep codebase research using parallel Explore subagents
31
- 3. **`@research-web`** — multi-agent web research with skeleton-file pattern
32
- 4. **`@research-auto`** — autonomous experimentation with `.lab/` directory
29
+ - **`@research-local`** deep codebase research using parallel Explore subagents
30
+ - **`@research-web`** — multi-agent web research with skeleton-file pattern
31
+ - **`@research-auto`** — autonomous experimentation with `.lab/` directory
33
32
 
34
- **To dispatch a research subagent:** Use the task tool with the agent name and pass the sub-question as the prompt:
35
-
36
- ```
37
- task tool:
38
- agent: "research-web"
39
- prompt: "Research the competitive landscape for X. Focus on: {specific angle}."
40
- ```
41
-
42
- The research agents are thin shims that load their matching bundled skill and follow it end-to-end. Trust the brief — the task-tool arguments ARE the research query.
33
+ Each is a thin shim that loads its matching bundled skill. The task-tool arguments ARE the research query.
43
34
 
44
35
  ## 7-Phase Flow
45
36
 
@@ -73,7 +73,12 @@ After the user approves the summary, use Serena MCP tools and file-reading tools
73
73
  Resolve the plan directory:
74
74
 
75
75
  ```bash
76
- PLAN_DIR="$(the inline bash snippet below (git rev-parse --git-common-dir))"
76
+ PLAN_BASE="${GLORIOUS_PLAN_DIR:-$HOME/.glorious/opencode}"
77
+ GIT_COMMON="$(git rev-parse --git-common-dir)"
78
+ [[ "$GIT_COMMON" != /* ]] && GIT_COMMON="$PWD/$GIT_COMMON"
79
+ REPO_FOLDER="$(basename "$(dirname "$GIT_COMMON")")"
80
+ PLAN_DIR="$PLAN_BASE/$REPO_FOLDER/plans"
81
+ mkdir -p "$PLAN_DIR"
77
82
  ```
78
83
 
79
84
  Write `$PLAN_DIR/<slug>/scope.md` (create the slug directory if needed). Use this structure:
@@ -122,7 +127,7 @@ If you have been asked 8 questions and the wizard sends: "You have asked enough
122
127
  - **Always present a scope summary for user approval before writing scope.md.** Never skip the approval gate.
123
128
  - **Do NOT call the `question` tool.** Emit questions as plain assistant text per the strict contract.
124
129
  - Every response is EXACTLY a question (≤200 chars, ends with `?`), a scope summary (starts with `SCOPE_SUMMARY:`), or the SCOPE_COMPLETE sentinel. Nothing else.
125
- - Write scope.md to the plan directory resolved via `the inline bash snippet below (git rev-parse --git-common-dir)`. Do not write to any other path.
130
+ - Write scope.md to the plan directory resolved via the bash snippet in Phase 4. Do not write to any other path.
126
131
  - The `SCOPE_COMPLETE:` sentinel must be the entire content of your response, with the absolute path.
127
132
  - Do not begin implementation. Do not write code. Do not modify any file except scope.md.
128
133
 
@@ -0,0 +1,29 @@
1
+ You are generating a YAML spec file from a markdown plan phase, enriched with codebase context.
2
+
3
+ Read the markdown plan content below and write `${specPath}` (relative to the plan directory: ${planDir}) using the write/edit tool.
4
+
5
+ The output file should follow this schema:
6
+
7
+ ${schemaExample}
8
+
9
+ For each acceptance-criteria item in the plan:
10
+ 1. Extract `id`, `intent`, `files`, `tests`, `verify` from the markdown.
11
+ 2. Set `checked: false` for all items.
12
+ 3. Add enrichment fields by reading the actual codebase:
13
+ - **mirror**: Find the most similar existing file in the codebase and set `mirror: <path>`. This is the pattern-match target the executor will follow.
14
+ - **context**: For each file being MODIFIED (not NEW), read the relevant function/section and add 10-20 lines of the current code. For NEW files, add the key function signatures the file should export.
15
+ - **conventions**: List project-specific patterns: import style (named vs default), export pattern, test framework (vitest/jest/bun:test), naming conventions, error handling pattern.
16
+
17
+ Rules:
18
+ - Read actual files from the codebase to get accurate code pointers. Do not hallucinate file contents.
19
+ - Be concise — 10-20 lines of context per file, not the whole file.
20
+ - Only add enrichment fields you can verify from the codebase.
21
+
22
+ Here is the plan file to convert:
23
+
24
+ ### {{file}}
25
+ ```markdown
26
+ {{content}}
27
+ ```
28
+
29
+ Write the file `${planDir}/${specPath}` using the write/edit tool, then respond with "SPEC_COMPLETE" when done.
@@ -0,0 +1,49 @@
1
+ import * as cmd_ts_dist_cjs_runner_js from 'cmd-ts/dist/cjs/runner.js';
2
+ import * as cmd_ts_dist_cjs_helpdoc_js from 'cmd-ts/dist/cjs/helpdoc.js';
3
+ import * as cmd_ts_dist_cjs_argparser_js from 'cmd-ts/dist/cjs/argparser.js';
4
+
5
+ interface InstallOptions {
6
+ dryRun?: boolean;
7
+ pin?: boolean;
8
+ nonInteractive?: boolean;
9
+ }
10
+ declare function install(opts?: InstallOptions): Promise<void>;
11
+
12
+ /**
13
+ * `bunx @glrs-dev/harness-plugin-opencode uninstall`
14
+ *
15
+ * Removes "@glrs-dev/harness-plugin-opencode" from the user's opencode.json plugin
16
+ * array. Writes a .bak backup before mutation. Does NOT touch skills (they
17
+ * live in node_modules, removed by `bun remove`). Does NOT touch ~/.claude/.
18
+ */
19
+ interface UninstallOptions {
20
+ dryRun?: boolean;
21
+ }
22
+ declare function uninstall(opts?: UninstallOptions): void;
23
+
24
+ /**
25
+ * `bunx @glrs-dev/harness-plugin-opencode doctor`
26
+ *
27
+ * Checks the installation health and reports per-check green/yellow/red.
28
+ */
29
+ declare function doctor(): void;
30
+
31
+ /**
32
+ * `glrs oc configure` — Interactive configuration editor.
33
+ *
34
+ * Shows the current opencode.json config as a navigable menu.
35
+ * The user selects a setting to change, picks from available options
36
+ * (no free-text for model selection), and saves.
37
+ *
38
+ * Unlike `install`, this command:
39
+ * - Never re-prompts for settings you don't want to change
40
+ * - Shows model choices from the Models.dev API (not free-text)
41
+ * - Supports changing a single tier without touching others
42
+ */
43
+ declare const configureCmd: Partial<cmd_ts_dist_cjs_argparser_js.Register> & {
44
+ parse(context: cmd_ts_dist_cjs_argparser_js.ParseContext): Promise<cmd_ts_dist_cjs_argparser_js.ParsingResult<{}>>;
45
+ } & cmd_ts_dist_cjs_helpdoc_js.PrintHelp & cmd_ts_dist_cjs_helpdoc_js.ProvidesHelp & cmd_ts_dist_cjs_helpdoc_js.Named & Partial<cmd_ts_dist_cjs_helpdoc_js.Versioned> & cmd_ts_dist_cjs_argparser_js.Register & cmd_ts_dist_cjs_runner_js.Handling<{}, Promise<void>> & {
46
+ run(context: cmd_ts_dist_cjs_argparser_js.ParseContext): Promise<cmd_ts_dist_cjs_argparser_js.ParsingResult<Promise<void>>>;
47
+ } & Partial<cmd_ts_dist_cjs_helpdoc_js.Versioned & cmd_ts_dist_cjs_helpdoc_js.Descriptive & cmd_ts_dist_cjs_helpdoc_js.Aliased>;
48
+
49
+ export { type InstallOptions, type UninstallOptions, configureCmd, doctor, install, uninstall };
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env bun
2
1
  import {
3
2
  getOpenCodeCachePackageDir,
4
3
  inspectCachePin,
@@ -11,16 +10,6 @@ import {
11
10
  promptMulti
12
11
  } from "./chunk-GILWWWMB.js";
13
12
 
14
- // src/cli.ts
15
- import {
16
- binary,
17
- command as command2,
18
- flag,
19
- positional,
20
- subcommands,
21
- run
22
- } from "cmd-ts";
23
-
24
13
  // src/cli/install.ts
25
14
  import * as fs2 from "fs";
26
15
  import * as path2 from "path";
@@ -977,17 +966,17 @@ function getOpencodeConfigPath2() {
977
966
  function uninstall(opts = {}) {
978
967
  const { dryRun = false } = opts;
979
968
  const configPath = getOpencodeConfigPath2();
980
- const c4 = {
969
+ const c3 = {
981
970
  reset: "\x1B[0m",
982
971
  green: "\x1B[32m",
983
972
  yellow: "\x1B[33m",
984
973
  blue: "\x1B[34m"
985
974
  };
986
- const ok3 = (msg) => console.log(`${c4.green}\u2713${c4.reset} ${msg}`);
987
- const info3 = (msg) => console.log(`${c4.blue}\u2022${c4.reset} ${msg}`);
988
- const warn2 = (msg) => console.log(`${c4.yellow}!${c4.reset} ${msg}`);
975
+ const ok3 = (msg) => console.log(`${c3.green}\u2713${c3.reset} ${msg}`);
976
+ const info3 = (msg) => console.log(`${c3.blue}\u2022${c3.reset} ${msg}`);
977
+ const warn2 = (msg) => console.log(`${c3.yellow}!${c3.reset} ${msg}`);
989
978
  console.log(`
990
- ${c4.blue}Uninstalling ${PLUGIN_NAME2}${c4.reset}
979
+ ${c3.blue}Uninstalling ${PLUGIN_NAME2}${c3.reset}
991
980
  `);
992
981
  if (!fs3.existsSync(configPath)) {
993
982
  warn2(`No opencode.json found at ${configPath} \u2014 nothing to do`);
@@ -1057,9 +1046,9 @@ function getOpencodeConfigPath3() {
1057
1046
  const configHome = process.env["XDG_CONFIG_HOME"] ?? path4.join(os3.homedir(), ".config");
1058
1047
  return path4.join(configHome, "opencode", "opencode.json");
1059
1048
  }
1060
- function cmd(command3) {
1049
+ function cmd(command2) {
1061
1050
  try {
1062
- return execSync(command3, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
1051
+ return execSync(command2, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
1063
1052
  } catch {
1064
1053
  return null;
1065
1054
  }
@@ -1068,18 +1057,18 @@ function which(bin) {
1068
1057
  return cmd(`which ${bin}`) !== null;
1069
1058
  }
1070
1059
  function doctor() {
1071
- const c4 = {
1060
+ const c3 = {
1072
1061
  reset: "\x1B[0m",
1073
1062
  green: "\x1B[32m",
1074
1063
  yellow: "\x1B[33m",
1075
1064
  red: "\x1B[31m",
1076
1065
  bold: "\x1B[1m"
1077
1066
  };
1078
- const ok3 = (msg) => console.log(`${c4.green}\u2713${c4.reset} ${msg}`);
1079
- const warn2 = (msg) => console.log(`${c4.yellow}!${c4.reset} ${msg}`);
1080
- const fail = (msg) => console.log(`${c4.red}\u2717${c4.reset} ${msg}`);
1067
+ const ok3 = (msg) => console.log(`${c3.green}\u2713${c3.reset} ${msg}`);
1068
+ const warn2 = (msg) => console.log(`${c3.yellow}!${c3.reset} ${msg}`);
1069
+ const fail = (msg) => console.log(`${c3.red}\u2717${c3.reset} ${msg}`);
1081
1070
  console.log(`
1082
- ${c4.bold}Doctor \u2014 ${PLUGIN_NAME3}${c4.reset}
1071
+ ${c3.bold}Doctor \u2014 ${PLUGIN_NAME3}${c3.reset}
1083
1072
  `);
1084
1073
  const ocVersion = cmd("opencode --version 2>/dev/null | head -1");
1085
1074
  if (ocVersion) {
@@ -1150,15 +1139,15 @@ ${c4.bold}Doctor \u2014 ${PLUGIN_NAME3}${c4.reset}
1150
1139
  for (const entry of invalid) {
1151
1140
  fail(`invalid model override at ${entry.keyPath}: "${entry.value}"`);
1152
1141
  if (entry.reason) {
1153
- console.log(` ${c4.yellow}reason:${c4.reset} ${entry.reason}`);
1142
+ console.log(` ${c3.yellow}reason:${c3.reset} ${entry.reason}`);
1154
1143
  }
1155
1144
  if (entry.suggestion) {
1156
1145
  console.log(
1157
- ` ${c4.yellow}fix:${c4.reset} remove this key, or replace with \`${entry.suggestion}\``
1146
+ ` ${c3.yellow}fix:${c3.reset} remove this key, or replace with \`${entry.suggestion}\``
1158
1147
  );
1159
1148
  } else {
1160
1149
  console.log(
1161
- ` ${c4.yellow}fix:${c4.reset} remove this key, or run \`bunx ${PLUGIN_NAME3} install\` to pick a current preset`
1150
+ ` ${c3.yellow}fix:${c3.reset} remove this key, or run \`bunx ${PLUGIN_NAME3} install\` to pick a current preset`
1162
1151
  );
1163
1152
  }
1164
1153
  }
@@ -1384,7 +1373,7 @@ var configureCmd = command({
1384
1373
  const configPath = getOpencodeConfigPath4();
1385
1374
  const config = readConfig(configPath);
1386
1375
  if (!config) {
1387
- console.log(`No config found at ${configPath}. Run ${c2.green}glrs oc install${c2.reset} first.`);
1376
+ console.log(`No config found at ${configPath}. Run ${c2.green}glrs harness install${c2.reset} first.`);
1388
1377
  process.exit(1);
1389
1378
  }
1390
1379
  const opts = extractPluginOptions2(config);
@@ -1447,259 +1436,9 @@ ${c2.bold}Done.${c2.reset} Restart opencode to pick up changes.
1447
1436
  }
1448
1437
  }
1449
1438
  });
1450
-
1451
- // src/cli/cli-update.ts
1452
- import * as fs6 from "fs";
1453
- import * as path6 from "path";
1454
- import * as os5 from "os";
1455
- import { spawn } from "child_process";
1456
- import { fileURLToPath as fileURLToPath2 } from "url";
1457
- var PACKAGE_NAME = "@glrs-dev/harness-plugin-opencode";
1458
- var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
1459
- var c3 = {
1460
- reset: "\x1B[0m",
1461
- green: "\x1B[32m",
1462
- yellow: "\x1B[33m",
1463
- blue: "\x1B[34m",
1464
- dim: "\x1B[2m",
1465
- bold: "\x1B[1m"
1439
+ export {
1440
+ configureCmd,
1441
+ doctor,
1442
+ install,
1443
+ uninstall
1466
1444
  };
1467
- function parseSemver(v) {
1468
- const m = /^(\d+)\.(\d+)\.(\d+)/.exec(v);
1469
- if (!m) return null;
1470
- return { major: +m[1], minor: +m[2], patch: +m[3] };
1471
- }
1472
- function isNewer(current, latest) {
1473
- if (latest.major !== current.major) return latest.major > current.major;
1474
- if (latest.minor !== current.minor) return latest.minor > current.minor;
1475
- return latest.patch > current.patch;
1476
- }
1477
- function isMajorBump(current, latest) {
1478
- return latest.major > current.major;
1479
- }
1480
- function getStateFilePath() {
1481
- const cacheHome = process.env["XDG_CACHE_HOME"] ?? path6.join(os5.homedir(), ".cache");
1482
- return path6.join(cacheHome, "harness-opencode", "cli-update.json");
1483
- }
1484
- function readState() {
1485
- try {
1486
- const raw = fs6.readFileSync(getStateFilePath(), "utf8");
1487
- return JSON.parse(raw);
1488
- } catch {
1489
- return null;
1490
- }
1491
- }
1492
- function writeState(state) {
1493
- try {
1494
- const statePath = getStateFilePath();
1495
- fs6.mkdirSync(path6.dirname(statePath), { recursive: true });
1496
- fs6.writeFileSync(statePath, JSON.stringify(state));
1497
- } catch {
1498
- }
1499
- }
1500
- function readInstalledVersion() {
1501
- const here = path6.dirname(fileURLToPath2(import.meta.url));
1502
- const candidates = [
1503
- path6.join(here, "..", "package.json"),
1504
- path6.join(here, "..", "..", "package.json"),
1505
- path6.join(here, "package.json")
1506
- ];
1507
- for (const candidate of candidates) {
1508
- try {
1509
- const raw = fs6.readFileSync(candidate, "utf8");
1510
- const parsed = JSON.parse(raw);
1511
- if (parsed.name === PACKAGE_NAME && typeof parsed.version === "string") {
1512
- return parsed.version;
1513
- }
1514
- } catch {
1515
- }
1516
- }
1517
- return "0.0.0";
1518
- }
1519
- async function fetchLatestVersion() {
1520
- try {
1521
- const controller = new AbortController();
1522
- const timer = setTimeout(() => controller.abort(), 3e3);
1523
- const res = await fetch(
1524
- `https://registry.npmjs.org/${PACKAGE_NAME}/latest`,
1525
- { signal: controller.signal }
1526
- );
1527
- clearTimeout(timer);
1528
- if (!res.ok) return null;
1529
- const data = await res.json();
1530
- return data.version ?? null;
1531
- } catch {
1532
- return null;
1533
- }
1534
- }
1535
- function spawnBackgroundUpdate() {
1536
- try {
1537
- const child = spawn("bun", ["update", "-g", PACKAGE_NAME], {
1538
- detached: true,
1539
- stdio: "ignore"
1540
- });
1541
- child.unref();
1542
- } catch {
1543
- }
1544
- }
1545
- function startUpdateCheck() {
1546
- if (process.env["HARNESS_OPENCODE_UPDATE_CHECK"] === "0") {
1547
- return () => {
1548
- };
1549
- }
1550
- const currentVersionStr = readInstalledVersion();
1551
- const current = parseSemver(currentVersionStr);
1552
- if (!current) return () => {
1553
- };
1554
- const state = readState();
1555
- if (state && Date.now() - state.last_check_ts < CHECK_INTERVAL_MS) {
1556
- if (state.latest_version) {
1557
- const cached = parseSemver(state.latest_version);
1558
- if (cached && isNewer(current, cached) && isMajorBump(current, cached)) {
1559
- return () => printMajorNotice(currentVersionStr, state.latest_version);
1560
- }
1561
- }
1562
- return () => {
1563
- };
1564
- }
1565
- let action = null;
1566
- fetchLatestVersion().then((latestStr) => {
1567
- writeState({
1568
- last_check_ts: Date.now(),
1569
- latest_version: latestStr ?? void 0
1570
- });
1571
- if (!latestStr) return;
1572
- const latest = parseSemver(latestStr);
1573
- if (!latest || !isNewer(current, latest)) return;
1574
- if (isMajorBump(current, latest)) {
1575
- action = () => printMajorNotice(currentVersionStr, latestStr);
1576
- } else {
1577
- action = () => {
1578
- process.stderr.write(
1579
- `
1580
- ${c3.blue}\u2022${c3.reset} Updating ${PACKAGE_NAME} ${c3.dim}${currentVersionStr}${c3.reset} \u2192 ${c3.green}${latestStr}${c3.reset} in the background...
1581
- `
1582
- );
1583
- spawnBackgroundUpdate();
1584
- };
1585
- }
1586
- }).catch(() => {
1587
- });
1588
- return () => {
1589
- if (action) action();
1590
- };
1591
- }
1592
- function printMajorNotice(current, latest) {
1593
- process.stderr.write(
1594
- `
1595
- ${c3.yellow}${c3.bold}Major update available:${c3.reset} ${current} \u2192 ${c3.green}${latest}${c3.reset}
1596
- ${c3.dim}Review the changelog before upgrading:${c3.reset}
1597
- bun update -g ${PACKAGE_NAME}
1598
- `
1599
- );
1600
- }
1601
-
1602
- // src/cli.ts
1603
- {
1604
- const dispatched = process.env["GLRS_CLI_DISPATCHED"];
1605
- if (!dispatched || dispatched === "") {
1606
- const argv1 = process.argv[1] ?? "harness-opencode";
1607
- const invoke = argv1.replace(/\\/g, "/").split("/").pop() ?? "harness-opencode";
1608
- process.stderr.write(`[${invoke}] This binary is deprecated when invoked standalone.
1609
- `);
1610
- process.stderr.write(`[${invoke}] Install @glrs-dev/cli and use 'glrs oc' instead:
1611
- `);
1612
- process.stderr.write(`[${invoke}] npm i -g @glrs-dev/cli
1613
- `);
1614
- process.stderr.write(`[${invoke}] glrs oc <args>
1615
- `);
1616
- process.stderr.write(`[${invoke}] Docs: https://glrs.dev/install
1617
- `);
1618
- process.exit(1);
1619
- }
1620
- }
1621
- if (!process.versions.bun) {
1622
- const [majorStr = "0", minorStr = "0"] = (process.versions.node ?? "0.0").split(".");
1623
- const major = Number(majorStr);
1624
- const minor = Number(minorStr);
1625
- if (major < 20 || major === 20 && minor < 10) {
1626
- process.stderr.write(
1627
- `harness-opencode requires Node.js >= 20.10 (you are on ${process.versions.node}).
1628
- Upgrade Node or run via a compatible Bun runtime. See the "engines" field in package.json.
1629
- `
1630
- );
1631
- process.exit(1);
1632
- }
1633
- }
1634
- var VERSION = "0.1.0";
1635
- var installCmd = command2({
1636
- name: "install",
1637
- description: 'Add "@glrs-dev/harness-plugin-opencode" to your opencode.json plugin array.',
1638
- args: {
1639
- dryRun: flag({
1640
- long: "dry-run",
1641
- description: "Preview changes without writing."
1642
- }),
1643
- pin: flag({
1644
- long: "pin",
1645
- description: "Pin to the current exact version (e.g. @0.1.0)."
1646
- })
1647
- },
1648
- handler: async ({ dryRun, pin }) => {
1649
- await install({ dryRun, pin });
1650
- }
1651
- });
1652
- var uninstallCmd = command2({
1653
- name: "uninstall",
1654
- description: 'Remove "@glrs-dev/harness-plugin-opencode" from your opencode.json plugin array.',
1655
- args: {
1656
- dryRun: flag({
1657
- long: "dry-run",
1658
- description: "Preview changes without writing."
1659
- })
1660
- },
1661
- handler: ({ dryRun }) => {
1662
- uninstall({ dryRun });
1663
- }
1664
- });
1665
- var doctorCmd = command2({
1666
- name: "doctor",
1667
- description: "Check installation health (OpenCode CLI, plugin registration, MCP backends).",
1668
- args: {},
1669
- handler: () => {
1670
- doctor();
1671
- }
1672
- });
1673
- var installPluginCmd = command2({
1674
- name: "install-plugin",
1675
- description: 'Add "@glrs-dev/harness-plugin-opencode" to your opencode.json plugin array.',
1676
- args: {
1677
- dryRun: flag({
1678
- long: "dry-run",
1679
- description: "Preview changes without writing."
1680
- }),
1681
- pin: flag({
1682
- long: "pin",
1683
- description: "Pin to the current exact version (e.g. @0.1.0)."
1684
- })
1685
- },
1686
- handler: async ({ dryRun, pin }) => {
1687
- await install({ dryRun, pin });
1688
- }
1689
- });
1690
- var cli = subcommands({
1691
- name: "glrs-oc",
1692
- description: "OpenCode agent harness CLI.",
1693
- version: VERSION,
1694
- cmds: {
1695
- "install-plugin": installPluginCmd,
1696
- install: installCmd,
1697
- uninstall: uninstallCmd,
1698
- configure: configureCmd,
1699
- doctor: doctorCmd
1700
- // Note: `loop` and `autopilot` commands have moved to @glrs-dev/cli.
1701
- }
1702
- });
1703
- var printUpdate = startUpdateCheck();
1704
- process.on("exit", printUpdate);
1705
- void run(binary(cli), process.argv);