@indigoai-us/hq-cli 5.345.18 → 5.345.19

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/CHANGELOG.md CHANGED
@@ -2,10 +2,17 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.345.19] — 2026-10-06
6
+ - Fix installation and updates of the published hq-anywhere pack through its built-in alias while continuing to reject reserved names from user-supplied remote sources.
7
+ - With `hq-anywhere-runtime` enabled, hqd now starts on Windows through the user-scoped named-pipe host and refuses service only when secure pipe setup or ACL verification fails. `hq doctor` describes unsafe named-pipe startup as an ACL setup failure and recommends the daemon install or restart action based on service state.
8
+
5
9
  ## [5.345.18] — 2026-10-06
6
10
  - Git Bash forwarders now keep slash commands intact and convert file path arguments that hq needs on Windows.
7
11
  - Lane placement and Claude account-balance refusals now show the requested placement, actual host, balance host when different, and the model values and sources used for an unavailable-account decision.
8
12
 
13
+ ## [5.345.17] — 2026-10-06
14
+ - Git Bash forwarders now keep slash commands intact and convert file path arguments that hq needs on Windows.
15
+
9
16
  ## [5.345.16] — 2026-10-06
10
17
  - Claude account model settings are defaults, so explicit lane models remain eligible; explicit account selections on create, resume, and message are recorded as CLI choices.
11
18
  - When `hq-anywhere-runtime` is enabled, `hq install --global --runtime claude --via plugin` installs the `hq` plugin from the `indigoai-us/hq-packages` Claude marketplace, and `hq install @indigoai-us/hq-anywhere` installs the Codex pack from that repository. The flag-off path refuses the HQ Anywhere alias without fetching a package source.
@@ -35,16 +35,23 @@ die() { echo "hq-delegate-grant: $*" >&2; exit 1; }
35
35
 
36
36
  command -v jq >/dev/null 2>&1 || die "jq is required but not installed"
37
37
 
38
- # jq.exe's binary mode avoids CRT newline conversion without changing real CR bytes.
38
+ # jq.exe on MSYS may use CRT text mode unless --binary is supported.
39
39
  case "${OSTYPE:-}:${MSYSTEM:-}" in
40
40
  msys*:*|*:MINGW*)
41
41
  jq() {
42
- local stdout_file stderr_file status
42
+ local stdout_file stderr_file status binary_supported
43
43
  stdout_file="$(mktemp)" || return $?
44
44
  stderr_file="$(mktemp)" || { status=$?; rm -f "$stdout_file"; return "$status"; }
45
- if command jq --binary "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
46
- command sed -b 's/\r$//' "$stdout_file"
47
- command sed -b 's/\r$//' "$stderr_file" >&2
45
+ if command jq --binary -n 'null' >/dev/null 2>&1; then binary_supported=1; else binary_supported=0; fi
46
+ if [[ "$binary_supported" == 1 ]]; then
47
+ if command jq --binary "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
48
+ command cat "$stdout_file"
49
+ command cat "$stderr_file" >&2
50
+ else
51
+ if command jq "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
52
+ command sed -b 's/\r$//' "$stdout_file"
53
+ command sed -b 's/\r$//' "$stderr_file" >&2
54
+ fi
48
55
  rm -f "$stdout_file" "$stderr_file"
49
56
  return "$status"
50
57
  }
@@ -40,16 +40,23 @@ die() { echo "hq-delegate-send: $*" >&2; exit 1; }
40
40
 
41
41
  command -v jq >/dev/null 2>&1 || die "jq is required but not installed"
42
42
 
43
- # jq.exe's binary mode avoids CRT newline conversion without changing real CR bytes.
43
+ # jq.exe on MSYS may use CRT text mode unless --binary is supported.
44
44
  case "${OSTYPE:-}:${MSYSTEM:-}" in
45
45
  msys*:*|*:MINGW*)
46
46
  jq() {
47
- local stdout_file stderr_file status
47
+ local stdout_file stderr_file status binary_supported
48
48
  stdout_file="$(mktemp)" || return $?
49
49
  stderr_file="$(mktemp)" || { status=$?; rm -f "$stdout_file"; return "$status"; }
50
- if command jq --binary "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
51
- command sed -b 's/\r$//' "$stdout_file"
52
- command sed -b 's/\r$//' "$stderr_file" >&2
50
+ if command jq --binary -n 'null' >/dev/null 2>&1; then binary_supported=1; else binary_supported=0; fi
51
+ if [[ "$binary_supported" == 1 ]]; then
52
+ if command jq --binary "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
53
+ command cat "$stdout_file"
54
+ command cat "$stderr_file" >&2
55
+ else
56
+ if command jq "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
57
+ command sed -b 's/\r$//' "$stdout_file"
58
+ command sed -b 's/\r$//' "$stderr_file" >&2
59
+ fi
53
60
  rm -f "$stdout_file" "$stderr_file"
54
61
  return "$status"
55
62
  }
@@ -120,16 +120,23 @@ done
120
120
  command -v yq >/dev/null 2>&1 || die "yq is required (mikefarah/yq)"
121
121
  command -v jq >/dev/null 2>&1 || die "jq is required"
122
122
 
123
- # jq.exe's binary mode avoids CRT newline conversion without changing real CR bytes.
123
+ # jq.exe on MSYS may use CRT text mode unless --binary is supported.
124
124
  case "${OSTYPE:-}:${MSYSTEM:-}" in
125
125
  msys*:*|*:MINGW*)
126
126
  jq() {
127
- local stdout_file stderr_file status
127
+ local stdout_file stderr_file status binary_supported
128
128
  stdout_file="$(mktemp)" || return $?
129
129
  stderr_file="$(mktemp)" || { status=$?; rm -f "$stdout_file"; return "$status"; }
130
- if command jq --binary "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
131
- command sed -b 's/\r$//' "$stdout_file"
132
- command sed -b 's/\r$//' "$stderr_file" >&2
130
+ if command jq --binary -n 'null' >/dev/null 2>&1; then binary_supported=1; else binary_supported=0; fi
131
+ if [[ "$binary_supported" == 1 ]]; then
132
+ if command jq --binary "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
133
+ command cat "$stdout_file"
134
+ command cat "$stderr_file" >&2
135
+ else
136
+ if command jq "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
137
+ command sed -b 's/\r$//' "$stdout_file"
138
+ command sed -b 's/\r$//' "$stderr_file" >&2
139
+ fi
133
140
  rm -f "$stdout_file" "$stderr_file"
134
141
  return "$status"
135
142
  }
@@ -40,16 +40,23 @@ command -v jq >/dev/null 2>&1 || {
40
40
  exit 2
41
41
  }
42
42
 
43
- # jq.exe's binary mode avoids CRT newline conversion without changing real CR bytes.
43
+ # jq.exe on MSYS may use CRT text mode unless --binary is supported.
44
44
  case "${OSTYPE:-}:${MSYSTEM:-}" in
45
45
  msys*:*|*:MINGW*)
46
46
  jq() {
47
- local stdout_file stderr_file status
47
+ local stdout_file stderr_file status binary_supported
48
48
  stdout_file="$(mktemp)" || return $?
49
49
  stderr_file="$(mktemp)" || { status=$?; rm -f "$stdout_file"; return "$status"; }
50
- if command jq --binary "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
51
- command sed -b 's/\r$//' "$stdout_file"
52
- command sed -b 's/\r$//' "$stderr_file" >&2
50
+ if command jq --binary -n 'null' >/dev/null 2>&1; then binary_supported=1; else binary_supported=0; fi
51
+ if [[ "$binary_supported" == 1 ]]; then
52
+ if command jq --binary "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
53
+ command cat "$stdout_file"
54
+ command cat "$stderr_file" >&2
55
+ else
56
+ if command jq "$@" >"$stdout_file" 2>"$stderr_file"; then status=0; else status=$?; fi
57
+ command sed -b 's/\r$//' "$stdout_file"
58
+ command sed -b 's/\r$//' "$stderr_file" >&2
59
+ fi
53
60
  rm -f "$stdout_file" "$stderr_file"
54
61
  return "$status"
55
62
  }
@@ -128,16 +128,65 @@ resolve_session_key() {
128
128
  }
129
129
 
130
130
  # Read-modify-write on the counter must not interleave across concurrent tasks.
131
+ reclaim_stale_counter_lock() {
132
+ local lockdir="$1" owner_pid current_owner claim stale_dir suffix=0
133
+ owner_pid="$(cat "$lockdir/pid" 2>/dev/null || true)"
134
+ case "$owner_pid" in ''|*[!0-9]*) return 1 ;; esac
135
+ [ "$owner_pid" -gt 1 ] 2>/dev/null || return 1
136
+ kill -0 "$owner_pid" 2>/dev/null && return 1
137
+
138
+ claim="${lockdir}.reclaim"
139
+ mkdir "$claim" 2>/dev/null || return 1
140
+ if ! printf '%s\n' "$$" > "$claim/pid" 2>/dev/null; then
141
+ rmdir "$claim" 2>/dev/null || true
142
+ return 1
143
+ fi
144
+
145
+ current_owner="$(cat "$lockdir/pid" 2>/dev/null || true)"
146
+ if [ "$current_owner" = "$owner_pid" ] && ! kill -0 "$owner_pid" 2>/dev/null; then
147
+ stale_dir="${lockdir}.stale.$$.$RANDOM"
148
+ while [ -e "$stale_dir" ]; do
149
+ suffix=$((suffix + 1))
150
+ stale_dir="${lockdir}.stale.$$.$RANDOM.$suffix"
151
+ done
152
+ if mv "$lockdir" "$stale_dir" 2>/dev/null; then
153
+ rm -rf "$stale_dir" 2>/dev/null || true
154
+ rm -rf "$claim" 2>/dev/null || true
155
+ return 0
156
+ fi
157
+ fi
158
+
159
+ rm -rf "$claim" 2>/dev/null || true
160
+ return 1
161
+ }
162
+
131
163
  with_counter_lock() {
132
164
  local lockdir="$1"; shift
133
- local i=0
134
- while ! mkdir "$lockdir" 2>/dev/null; do
165
+ local i=0 acquired=0 rc=0 tries="${HQ_JOURNAL_COUNTER_LOCK_TRIES:-250}"
166
+ case "$tries" in ''|*[!0-9]*) tries=250 ;; esac
167
+ while [ "$i" -lt "$tries" ]; do
168
+ if mkdir "$lockdir" 2>/dev/null; then
169
+ acquired=1
170
+ if ! printf '%s\n' "$$" > "$lockdir/pid" 2>/dev/null; then
171
+ rm -rf "$lockdir" 2>/dev/null || true
172
+ return 0
173
+ fi
174
+ break
175
+ fi
176
+ reclaim_stale_counter_lock "$lockdir" && continue
135
177
  i=$((i + 1))
136
- [ "$i" -ge 50 ] && break
137
- sleep 0.02 2>/dev/null || sleep 1
178
+ [ "$i" -ge "$tries" ] || sleep 0.02 2>/dev/null || sleep 1
138
179
  done
139
- "$@"
140
- rmdir "$lockdir" 2>/dev/null || true
180
+ if [ "$acquired" -ne 1 ]; then
181
+ warn "tool-counter: lock remained busy; skipped update"
182
+ return 0
183
+ fi
184
+
185
+ "$@" || rc=$?
186
+ if [ "$(cat "$lockdir/pid" 2>/dev/null || true)" = "$$" ]; then
187
+ rm -rf "$lockdir" 2>/dev/null || true
188
+ fi
189
+ return "$rc"
141
190
  }
142
191
 
143
192
  counter_read_raw() {
@@ -210,7 +210,7 @@ function runToolCounter(root, action, sessionArg, env, now, writers) {
210
210
  fs.writeFileSync(counter, `${readCounter(counter) + 1}\n`);
211
211
  }
212
212
  catch (error) {
213
- reportDirectoryWriteFailure(error, 346);
213
+ reportDirectoryWriteFailure(error, 395);
214
214
  }
215
215
  });
216
216
  }
@@ -223,7 +223,7 @@ function runToolCounter(root, action, sessionArg, env, now, writers) {
223
223
  fs.writeFileSync(counter, "0\n");
224
224
  }
225
225
  catch (error) {
226
- reportDirectoryWriteFailure(error, 354);
226
+ reportDirectoryWriteFailure(error, 403);
227
227
  }
228
228
  });
229
229
  }
@@ -46,6 +46,8 @@ export interface ResolveLatestOptions {
46
46
  export type Transport = 'npm' | 'git' | 'local' | 'marketplace';
47
47
  /** Prefix that routes a source through the HQ marketplace transport (US-006). */
48
48
  export declare const MARKETPLACE_PREFIX = "marketplace:";
49
+ /** Pinned source allowed to claim the reserved hq-anywhere pack name via its CLI alias. */
50
+ export declare const PINNED_HQ_ANYWHERE_SOURCE = "github:indigoai-us/hq-packages#packages/hq-pack-hq-anywhere";
49
51
  export declare function classify(source: string): Transport;
50
52
  /**
51
53
  * Parse a git source's '#<...>' fragment into { url, subpath, ref }.
@@ -411,6 +413,8 @@ export declare function runScanPackages(hqRoot: string, opts?: {
411
413
  }): void;
412
414
  export interface InstallPackOptions {
413
415
  allowHooks?: boolean;
416
+ /** Internal grant used only by the @indigoai-us/hq-anywhere CLI alias. */
417
+ allowPinnedHqAnywhereName?: true;
414
418
  /** Company context for online authorization of install-time MCP secret refs. */
415
419
  company?: string;
416
420
  /**
@@ -112,6 +112,8 @@ async function latestWithDiskCache(cacheKey, opts, refresh) {
112
112
  }
113
113
  /** Prefix that routes a source through the HQ marketplace transport (US-006). */
114
114
  export const MARKETPLACE_PREFIX = 'marketplace:';
115
+ /** Pinned source allowed to claim the reserved hq-anywhere pack name via its CLI alias. */
116
+ export const PINNED_HQ_ANYWHERE_SOURCE = 'github:indigoai-us/hq-packages#packages/hq-pack-hq-anywhere';
115
117
  export function classify(source) {
116
118
  // US-006: marketplace:<slug>[@version] is recognized BEFORE the legacy
117
119
  // registry fallback and ahead of every other transport. The slug is resolved
@@ -1727,10 +1729,16 @@ async function installPackWithoutLease(source, opts) {
1727
1729
  });
1728
1730
  break;
1729
1731
  }
1730
- // Only an explicit local directory source may use the reserved bundled
1731
- // pack name. Publisher is self-declared package metadata and is not proof
1732
- // of registry identity, so remote transports never receive this exception.
1733
- const pkg = validateManifest(fetched.payloadDir, hqVersion, { allowReservedName: transport === 'local' });
1732
+ // Local directories retain their existing reserved-name behavior. For
1733
+ // remote sources, publisher is self-declared and cannot prove registry
1734
+ // identity, so accept the reserved name only when the top-level CLI alias
1735
+ // supplied its internal grant for the exact pinned GitHub source.
1736
+ const allowPinnedAliasName = transport === 'git' &&
1737
+ source === PINNED_HQ_ANYWHERE_SOURCE &&
1738
+ opts.allowPinnedHqAnywhereName === true;
1739
+ const pkg = validateManifest(fetched.payloadDir, hqVersion, {
1740
+ allowReservedName: transport === 'local' || allowPinnedAliasName,
1741
+ });
1734
1742
  // M0 — pack-to-pack dependency pre-flight. Runs BEFORE any prompts or writes
1735
1743
  // so a missing/unsatisfied `requires.packs` aborts with no partial state, and
1736
1744
  // before we bother the operator with hook/MCP trust prompts for a pack that
@@ -26,7 +26,7 @@ import chalk from 'chalk';
26
26
  import semverSatisfies from 'semver/functions/satisfies.js';
27
27
  import { findHqRoot } from '../utils/manifest.js';
28
28
  import { resolveHqRoot as resolveDetectedHqRoot } from './doctor.js';
29
- import { classify, resolveLatest, resolveLatestMarketplace, runScanPackages, installPack, } from './pack-install.js';
29
+ import { classify, PINNED_HQ_ANYWHERE_SOURCE, resolveLatest, resolveLatestMarketplace, runScanPackages, installPack, } from './pack-install.js';
30
30
  import { contributionLinks, linkStatus, listInstalledPacks, findDependentPacks, readPackManifest, unwirePack, unwirePackMcp, readHqVersion, readRecommendedPackages, packagesDir, } from '../utils/pack-contributions.js';
31
31
  import { syncCodexPackHooks, syncCodexPackSkills } from '../lib/install/codex-pack-contributions.js';
32
32
  function resolveRoot(opts) {
@@ -267,6 +267,9 @@ async function runUpdate(name, opts) {
267
267
  allowMcp: opts.yes || opts.allowMcp,
268
268
  followBranch: opts.branch,
269
269
  quiet: wantsJson(opts),
270
+ ...(pname === 'hq-anywhere' && source === PINNED_HQ_ANYWHERE_SOURCE
271
+ ? { allowPinnedHqAnywhereName: true }
272
+ : {}),
270
273
  });
271
274
  }
272
275
  finally {
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import { peekHqApiKey, requireApiKeyCapability, } from '../utils/resolve-vault-credential.js';
3
- import { MARKETPLACE_PREFIX, installPack, sourceMatchesPackPattern, } from './pack-install.js';
3
+ import { MARKETPLACE_PREFIX, PINNED_HQ_ANYWHERE_SOURCE, installPack, sourceMatchesPackPattern, } from './pack-install.js';
4
4
  import { anywhereRuntimeEnabled } from './anywhere-runtime-flag.js';
5
5
  /**
6
6
  * True when `source` installs through the marketplace — an explicit
@@ -99,11 +99,12 @@ export function registerPackageInstallCommand(parent) {
99
99
  console.error(chalk.red('Install failed:'), 'HQ Anywhere installation is disabled by the hq-anywhere-runtime flag.');
100
100
  process.exit(1);
101
101
  }
102
- await installPack('github:indigoai-us/hq-packages#packages/hq-pack-hq-anywhere', {
102
+ await installPack(PINNED_HQ_ANYWHERE_SOURCE, {
103
103
  company: opts.company,
104
104
  allowHooks: opts.allowHooks,
105
105
  allowMcp: opts.allowMcp,
106
106
  followBranch: opts.branch,
107
+ allowPinnedHqAnywhereName: true,
107
108
  });
108
109
  return;
109
110
  }
@@ -21,8 +21,8 @@ export interface DaemonLockConflictOutcome {
21
21
  }
22
22
  /** Preserve the legacy lock failure unless Anywhere explicitly enables the no-op behavior. */
23
23
  export declare function daemonLockConflictOutcome(lock: DaemonLockResult, anywhereEnabled: boolean): DaemonLockConflictOutcome | null;
24
- /** Node's Windows named-pipe API uses a default DACL that is not user-scoped. */
25
- export declare function hqdStartupRefusal(platform: NodeJS.Platform, anywhereEnabled: boolean): string | null;
24
+ /** hqd is available on every platform while Anywhere is enabled; its listener fails closed if setup is unsafe. */
25
+ export declare function shouldStartHqd(anywhereEnabled: boolean): boolean;
26
26
  /** Route an updater request through the daemon's existing graceful handoff. */
27
27
  export declare function handoffForPackageUpdateRequest(requested: boolean, restartDaemon: () => void): void;
28
28
  export interface RunDaemonOptions {
@@ -63,11 +63,9 @@ export function daemonLockConflictOutcome(lock, anywhereEnabled) {
63
63
  : "another hq daemon is starting up.\n",
64
64
  };
65
65
  }
66
- /** Node's Windows named-pipe API uses a default DACL that is not user-scoped. */
67
- export function hqdStartupRefusal(platform, anywhereEnabled) {
68
- if (platform !== "win32" || !anywhereEnabled)
69
- return null;
70
- return "hqd is disabled on Windows because the default named-pipe ACL grants read access to Everyone and Anonymous accounts.";
66
+ /** hqd is available on every platform while Anywhere is enabled; its listener fails closed if setup is unsafe. */
67
+ export function shouldStartHqd(anywhereEnabled) {
68
+ return anywhereEnabled;
71
69
  }
72
70
  /** Route an updater request through the daemon's existing graceful handoff. */
73
71
  export function handoffForPackageUpdateRequest(requested, restartDaemon) {
@@ -838,8 +836,7 @@ export async function runDaemon(opts) {
838
836
  // hqd: the session/company socket every runtime talks to (hq-anywhere US-008).
839
837
  let hqd = null;
840
838
  let hqdShutdown = null;
841
- if (anywhereRuntimeEnabled()) {
842
- const refusal = hqdStartupRefusal(platform, true);
839
+ if (shouldStartHqd(anywhereRuntimeEnabled())) {
843
840
  try {
844
841
  const startConfig = readDaemonConfig(paths.configPath);
845
842
  hqd = await startHqdServer({
@@ -852,10 +849,7 @@ export async function runDaemon(opts) {
852
849
  });
853
850
  }
854
851
  catch (err) {
855
- if (refusal && err.message === refusal)
856
- log("error", refusal);
857
- else
858
- log("error", `hqd socket did not start; services run without it: ${err.message}`);
852
+ log("error", `hqd socket did not start; services run without it: ${err.message}`);
859
853
  }
860
854
  }
861
855
  // US-012: 60s presence heartbeat with version and session count.
@@ -182,7 +182,7 @@ function runtimeHealthCheck(health, healthUnsupported = false, serviceState) {
182
182
  ? "Windows named pipe (mode and owner are not reported)"
183
183
  : `mode ${socket.mode ?? "unknown"}; owner matches current user: ${socket.ownerMatchesUser === null ? "unknown" : socket.ownerMatchesUser ? "yes" : "no"}; user-only: ${socket.userOnly === null ? "unknown" : socket.userOnly ? "yes" : "no"}`;
184
184
  const unreachableMessage = socket.transport === "windows_named_pipe"
185
- ? `hqd is not reachable on ${socket.path}; Windows daemon startup is refused because named-pipe ACLs are unsupported`
185
+ ? `hqd is not reachable on ${socket.path}; secure Windows named-pipe setup may have refused an unsafe ACL`
186
186
  : `hqd is not reachable on ${socket.path}; version, uptime, flag state, and cwd binding are unavailable`;
187
187
  const socketNotUserOnly = health.reachable && socket.transport === "unix_socket" && (socket.userOnly !== true || socket.ownerMatchesUser !== true);
188
188
  const warningNotes = [
@@ -192,7 +192,7 @@ function runtimeHealthCheck(health, healthUnsupported = false, serviceState) {
192
192
  const message = health.reachable
193
193
  ? `hqd reachable; version ${health.version ?? "unknown"}; uptime ${health.uptimeMs === null ? "unknown" : `${new Intl.NumberFormat("en-US").format(health.uptimeMs)} ms`}; runtime flag ${flagLabel}; last successful flag read ${age} ago; held through read error: ${flag.heldThroughReadError ? "yes" : "no"}; cwd binding ${binding}; socket ${socket.path}; ${socketSecurity}${warningNotes.length ? `; ${warningNotes.join("; ")}` : ""}`
194
194
  : unreachableMessage;
195
- const remediation = !health.reachable && socket.transport === "unix_socket" && serviceState
195
+ const remediation = !health.reachable && serviceState
196
196
  ? serviceState.installed ? REMEDIATION.daemonRestart : REMEDIATION.daemonInstall
197
197
  : healthUnsupported || socketNotUserOnly ? REMEDIATION.daemonRestart : undefined;
198
198
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.345.18",
3
+ "version": "5.345.19",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {