@staff0rd/assist 0.147.4 → 0.148.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.
package/README.md CHANGED
@@ -152,6 +152,7 @@ After installation, the `assist` command will be available globally. You can als
152
152
  - `assist seq query <filter> --json` - Output raw JSON
153
153
  - `assist seq query <filter> -n <count>` - Fetch a specific number of events (default 50)
154
154
  - `assist screenshot <process>` - Capture a screenshot of a running application window (e.g. `assist screenshot notepad`). Output directory is configurable via `screenshot.outputDir` (default `./screenshots`)
155
+ - `assist coverage` - Print global statement coverage percentage
155
156
  - `assist complexity <pattern>` - Analyze a file (all metrics if single match, maintainability if multiple)
156
157
  - `assist complexity cyclomatic [pattern]` - Calculate cyclomatic complexity per function
157
158
  - `assist complexity halstead [pattern]` - Calculate Halstead metrics per function
@@ -7,7 +7,9 @@ You are increasing test coverage for this project. Your goal is to pick the high
7
7
 
8
8
  ## Step 1: Measure current coverage
9
9
 
10
- Run coverage against all source files to identify what is untested:
10
+ Run `assist coverage` to get the current global statement coverage percentage.
11
+
12
+ Then run coverage with JSON output to identify what is untested:
11
13
 
12
14
  ```
13
15
  npx vitest run --coverage --coverage.include='src/**/*.ts' --coverage.all --coverage.reporter=json 2>&1
@@ -116,4 +118,4 @@ File | Before | After
116
118
  <file path> | 0% | 95%
117
119
  ```
118
120
 
119
- And the new repo-wide coverage number.
121
+ And the new repo-wide coverage number (run `assist coverage`).
@@ -49,6 +49,7 @@
49
49
  "Bash(assist ravendb auth list:*)",
50
50
  "Bash(assist seq query:*)",
51
51
  "Bash(assist seq auth list:*)",
52
+ "Bash(assist coverage:*)",
52
53
  "Bash(assist screenshot:*)",
53
54
  "Bash(assist roam show-claude-code-icon:*)",
54
55
  "SlashCommand(/verify)",
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@staff0rd/assist",
9
- version: "0.147.4",
9
+ version: "0.148.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -483,6 +483,21 @@ function configList() {
483
483
  console.log(stringifyYaml2(config, { lineWidth: 0 }).trimEnd());
484
484
  }
485
485
 
486
+ // src/commands/coverage.ts
487
+ import { execSync as execSync2 } from "child_process";
488
+ function coverage() {
489
+ const output = execSync2(
490
+ "npx vitest run --coverage --coverage.include='src/**/*.ts' --coverage.all --coverage.reporter=text 2>&1",
491
+ { encoding: "utf-8", timeout: 12e4 }
492
+ );
493
+ const match = output.match(/All files\s*\|\s*([\d.]+)/);
494
+ if (!match) {
495
+ console.error("Could not determine coverage from vitest output.");
496
+ process.exit(1);
497
+ }
498
+ console.log(`${match[1]}%`);
499
+ }
500
+
486
501
  // src/commands/verify/init/index.ts
487
502
  import chalk17 from "chalk";
488
503
 
@@ -555,7 +570,7 @@ function findPackageJsonWithVerifyScripts(startDir) {
555
570
  }
556
571
 
557
572
  // src/commands/verify/installPackage.ts
558
- import { execSync as execSync2 } from "child_process";
573
+ import { execSync as execSync3 } from "child_process";
559
574
  import { writeFileSync as writeFileSync2 } from "fs";
560
575
  import chalk5 from "chalk";
561
576
  function writePackageJson(filePath, pkg) {
@@ -574,7 +589,7 @@ function addScript(pkg, name, command) {
574
589
  function installPackage(name, cwd) {
575
590
  console.log(chalk5.dim(`Installing ${name}...`));
576
591
  try {
577
- execSync2(`npm install -D ${name}`, { stdio: "inherit", cwd });
592
+ execSync3(`npm install -D ${name}`, { stdio: "inherit", cwd });
578
593
  return true;
579
594
  } catch {
580
595
  console.error(chalk5.red(`Failed to install ${name}`));
@@ -720,7 +735,7 @@ import * as path5 from "path";
720
735
  import chalk13 from "chalk";
721
736
 
722
737
  // src/commands/lint/init.ts
723
- import { execSync as execSync4 } from "child_process";
738
+ import { execSync as execSync5 } from "child_process";
724
739
  import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
725
740
  import { dirname as dirname6, join as join4 } from "path";
726
741
  import { fileURLToPath } from "url";
@@ -744,7 +759,7 @@ async function promptConfirm(message, initial = true) {
744
759
  }
745
760
 
746
761
  // src/shared/removeEslint/index.ts
747
- import { execSync as execSync3 } from "child_process";
762
+ import { execSync as execSync4 } from "child_process";
748
763
  import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
749
764
 
750
765
  // src/shared/removeEslint/removeEslintConfigFiles.ts
@@ -779,7 +794,7 @@ function removeEslint(options2 = {}) {
779
794
  const removedConfigFiles = removeEslintConfigFiles();
780
795
  if (removedFromPackageJson || removedConfigFiles) {
781
796
  console.log("Running npm install...");
782
- execSync3("npm install", { stdio: "inherit" });
797
+ execSync4("npm install", { stdio: "inherit" });
783
798
  return true;
784
799
  }
785
800
  return false;
@@ -861,7 +876,7 @@ async function init() {
861
876
  const biomeConfigPath = "biome.json";
862
877
  if (!existsSync7(biomeConfigPath)) {
863
878
  console.log("Initializing Biome...");
864
- execSync4("npx @biomejs/biome init", { stdio: "inherit" });
879
+ execSync5("npx @biomejs/biome init", { stdio: "inherit" });
865
880
  }
866
881
  if (!existsSync7(biomeConfigPath)) {
867
882
  console.log("No biome.json found, skipping linter config");
@@ -1615,17 +1630,17 @@ function lint(options2 = {}) {
1615
1630
  }
1616
1631
 
1617
1632
  // src/commands/new/registerNew/newCli/index.ts
1618
- import { execSync as execSync10 } from "child_process";
1633
+ import { execSync as execSync11 } from "child_process";
1619
1634
  import { basename as basename2, resolve } from "path";
1620
1635
 
1621
1636
  // src/commands/verify/hardcodedColors.ts
1622
- import { execSync as execSync5 } from "child_process";
1637
+ import { execSync as execSync6 } from "child_process";
1623
1638
  import { minimatch } from "minimatch";
1624
1639
  var pattern = "0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}";
1625
1640
  function hardcodedColors() {
1626
1641
  const ignoreGlobs = loadConfig().hardcodedColors?.ignore ?? [];
1627
1642
  try {
1628
- const output = execSync5(`grep -rEnH '${pattern}' src/`, {
1643
+ const output = execSync6(`grep -rEnH '${pattern}' src/`, {
1629
1644
  encoding: "utf-8"
1630
1645
  });
1631
1646
  const lines = output.trim().split("\n").filter((line) => {
@@ -1704,10 +1719,10 @@ function list() {
1704
1719
  }
1705
1720
 
1706
1721
  // src/commands/verify/noVenv.ts
1707
- import { execSync as execSync6 } from "child_process";
1722
+ import { execSync as execSync7 } from "child_process";
1708
1723
  function noVenv() {
1709
1724
  try {
1710
- const output = execSync6(
1725
+ const output = execSync7(
1711
1726
  "find . -type d -name venv -not -path '*/node_modules/*'",
1712
1727
  {
1713
1728
  encoding: "utf-8"
@@ -1739,9 +1754,9 @@ Total: ${folders.length} venv folder(s)`);
1739
1754
  import { minimatch as minimatch2 } from "minimatch";
1740
1755
 
1741
1756
  // src/commands/verify/run/getChangedFiles.ts
1742
- import { execSync as execSync7 } from "child_process";
1757
+ import { execSync as execSync8 } from "child_process";
1743
1758
  function getChangedFiles() {
1744
- const output = execSync7("git diff --name-only HEAD", {
1759
+ const output = execSync8("git diff --name-only HEAD", {
1745
1760
  encoding: "utf-8"
1746
1761
  }).trim();
1747
1762
  if (output === "") return [];
@@ -1903,25 +1918,25 @@ async function run(options2 = {}) {
1903
1918
  }
1904
1919
 
1905
1920
  // src/commands/new/registerNew/initGit.ts
1906
- import { execSync as execSync8 } from "child_process";
1921
+ import { execSync as execSync9 } from "child_process";
1907
1922
  import { writeFileSync as writeFileSync7 } from "fs";
1908
1923
  function initGit() {
1909
1924
  console.log("Initializing git repository...");
1910
- execSync8("git init", { stdio: "inherit" });
1925
+ execSync9("git init", { stdio: "inherit" });
1911
1926
  writeFileSync7(".gitignore", "dist\nnode_modules\n");
1912
1927
  }
1913
1928
 
1914
1929
  // src/commands/new/registerNew/newCli/initPackageJson.ts
1915
- import { execSync as execSync9 } from "child_process";
1930
+ import { execSync as execSync10 } from "child_process";
1916
1931
  function initPackageJson(name) {
1917
1932
  console.log("Initializing package.json...");
1918
- execSync9("npm init -y", { stdio: "inherit" });
1933
+ execSync10("npm init -y", { stdio: "inherit" });
1919
1934
  console.log("Configuring package.json...");
1920
- execSync9("npm pkg delete main", { stdio: "inherit" });
1921
- execSync9("npm pkg set type=module", { stdio: "inherit" });
1922
- execSync9(`npm pkg set bin.${name}=./dist/index.js`, { stdio: "inherit" });
1923
- execSync9("npm pkg set scripts.build=tsup", { stdio: "inherit" });
1924
- execSync9('npm pkg set scripts.start="node dist/index.js"', {
1935
+ execSync10("npm pkg delete main", { stdio: "inherit" });
1936
+ execSync10("npm pkg set type=module", { stdio: "inherit" });
1937
+ execSync10(`npm pkg set bin.${name}=./dist/index.js`, { stdio: "inherit" });
1938
+ execSync10("npm pkg set scripts.build=tsup", { stdio: "inherit" });
1939
+ execSync10('npm pkg set scripts.start="node dist/index.js"', {
1925
1940
  stdio: "inherit"
1926
1941
  });
1927
1942
  }
@@ -1986,8 +2001,8 @@ async function newCli() {
1986
2001
  initGit();
1987
2002
  initPackageJson(name);
1988
2003
  console.log("Installing dependencies...");
1989
- execSync10("npm install commander", { stdio: "inherit" });
1990
- execSync10("npm install -D tsup typescript @types/node", {
2004
+ execSync11("npm install commander", { stdio: "inherit" });
2005
+ execSync11("npm install -D tsup typescript @types/node", {
1991
2006
  stdio: "inherit"
1992
2007
  });
1993
2008
  writeCliTemplate(name);
@@ -1996,11 +2011,11 @@ async function newCli() {
1996
2011
  }
1997
2012
 
1998
2013
  // src/commands/new/registerNew/newProject.ts
1999
- import { execSync as execSync12 } from "child_process";
2014
+ import { execSync as execSync13 } from "child_process";
2000
2015
  import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync10 } from "fs";
2001
2016
 
2002
2017
  // src/commands/deploy/init/index.ts
2003
- import { execSync as execSync11 } from "child_process";
2018
+ import { execSync as execSync12 } from "child_process";
2004
2019
  import chalk24 from "chalk";
2005
2020
  import enquirer3 from "enquirer";
2006
2021
 
@@ -2053,7 +2068,7 @@ Created ${WORKFLOW_PATH}`));
2053
2068
  // src/commands/deploy/init/index.ts
2054
2069
  async function ensureNetlifyCli() {
2055
2070
  try {
2056
- execSync11("netlify sites:create --disable-linking", { stdio: "inherit" });
2071
+ execSync12("netlify sites:create --disable-linking", { stdio: "inherit" });
2057
2072
  } catch (error) {
2058
2073
  if (!(error instanceof Error) || !error.message.includes("command not found"))
2059
2074
  throw error;
@@ -2068,9 +2083,9 @@ async function ensureNetlifyCli() {
2068
2083
  process.exit(1);
2069
2084
  }
2070
2085
  console.log(chalk24.dim("\nInstalling netlify-cli...\n"));
2071
- execSync11("npm install -g netlify-cli", { stdio: "inherit" });
2086
+ execSync12("npm install -g netlify-cli", { stdio: "inherit" });
2072
2087
  console.log();
2073
- execSync11("netlify sites:create --disable-linking", { stdio: "inherit" });
2088
+ execSync12("netlify sites:create --disable-linking", { stdio: "inherit" });
2074
2089
  }
2075
2090
  }
2076
2091
  function printSetupInstructions() {
@@ -2113,7 +2128,7 @@ async function init5() {
2113
2128
  // src/commands/new/registerNew/newProject.ts
2114
2129
  async function newProject() {
2115
2130
  console.log("Initializing Vite with react-ts template...");
2116
- execSync12("npm create vite@latest . -- --template react-ts", {
2131
+ execSync13("npm create vite@latest . -- --template react-ts", {
2117
2132
  stdio: "inherit"
2118
2133
  });
2119
2134
  initGit();
@@ -3477,7 +3492,7 @@ import { homedir as homedir4 } from "os";
3477
3492
  import { join as join13 } from "path";
3478
3493
 
3479
3494
  // src/shared/getInstallDir.ts
3480
- import { execSync as execSync13 } from "child_process";
3495
+ import { execSync as execSync14 } from "child_process";
3481
3496
  import { dirname as dirname15, resolve as resolve4 } from "path";
3482
3497
  import { fileURLToPath as fileURLToPath5 } from "url";
3483
3498
  var __filename3 = fileURLToPath5(import.meta.url);
@@ -3487,7 +3502,7 @@ function getInstallDir() {
3487
3502
  }
3488
3503
  function isGitRepo(dir) {
3489
3504
  try {
3490
- const result = execSync13("git rev-parse --show-toplevel", {
3505
+ const result = execSync14("git rev-parse --show-toplevel", {
3491
3506
  cwd: dir,
3492
3507
  stdio: "pipe"
3493
3508
  }).toString().trim();
@@ -3498,7 +3513,7 @@ function isGitRepo(dir) {
3498
3513
  }
3499
3514
 
3500
3515
  // src/commands/permitCliReads/assertCliExists.ts
3501
- import { execSync as execSync14 } from "child_process";
3516
+ import { execSync as execSync15 } from "child_process";
3502
3517
  function assertCliExists(cli) {
3503
3518
  const binary = cli.split(/\s+/)[0];
3504
3519
  const opts = {
@@ -3506,10 +3521,10 @@ function assertCliExists(cli) {
3506
3521
  stdio: ["ignore", "pipe", "pipe"]
3507
3522
  };
3508
3523
  try {
3509
- execSync14(`command -v ${binary}`, opts);
3524
+ execSync15(`command -v ${binary}`, opts);
3510
3525
  } catch {
3511
3526
  try {
3512
- execSync14(`where ${binary}`, opts);
3527
+ execSync15(`where ${binary}`, opts);
3513
3528
  } catch {
3514
3529
  console.error(`CLI "${cli}" not found in PATH`);
3515
3530
  process.exit(1);
@@ -4365,7 +4380,7 @@ function registerDeploy(program2) {
4365
4380
  }
4366
4381
 
4367
4382
  // src/commands/devlog/list/index.ts
4368
- import { execSync as execSync16 } from "child_process";
4383
+ import { execSync as execSync17 } from "child_process";
4369
4384
  import { basename as basename3 } from "path";
4370
4385
 
4371
4386
  // src/commands/devlog/loadBlogSkipDays.ts
@@ -4380,7 +4395,7 @@ function loadBlogSkipDays(repoName) {
4380
4395
  }
4381
4396
 
4382
4397
  // src/commands/devlog/shared.ts
4383
- import { execSync as execSync15 } from "child_process";
4398
+ import { execSync as execSync16 } from "child_process";
4384
4399
  import chalk48 from "chalk";
4385
4400
 
4386
4401
  // src/commands/devlog/loadDevlogEntries.ts
@@ -4450,7 +4465,7 @@ function loadAllDevlogLatestDates() {
4450
4465
  // src/commands/devlog/shared.ts
4451
4466
  function getCommitFiles(hash) {
4452
4467
  try {
4453
- const output = execSync15(`git show --name-only --format="" ${hash}`, {
4468
+ const output = execSync16(`git show --name-only --format="" ${hash}`, {
4454
4469
  encoding: "utf-8"
4455
4470
  });
4456
4471
  return output.trim().split("\n").filter(Boolean);
@@ -4521,7 +4536,7 @@ function list3(options2) {
4521
4536
  const devlogEntries = loadDevlogEntries(repoName);
4522
4537
  const reverseFlag = options2.reverse ? "--reverse " : "";
4523
4538
  const limitFlag = options2.reverse ? "" : "-n 500 ";
4524
- const output = execSync16(
4539
+ const output = execSync17(
4525
4540
  `git log ${reverseFlag}${limitFlag}--pretty=format:'%ad|%h|%s' --date=short`,
4526
4541
  { encoding: "utf-8" }
4527
4542
  );
@@ -4547,11 +4562,11 @@ function list3(options2) {
4547
4562
  }
4548
4563
 
4549
4564
  // src/commands/devlog/getLastVersionInfo.ts
4550
- import { execSync as execSync17 } from "child_process";
4565
+ import { execSync as execSync18 } from "child_process";
4551
4566
  import semver from "semver";
4552
4567
  function getVersionAtCommit(hash) {
4553
4568
  try {
4554
- const content = execSync17(`git show ${hash}:package.json`, {
4569
+ const content = execSync18(`git show ${hash}:package.json`, {
4555
4570
  encoding: "utf-8"
4556
4571
  });
4557
4572
  const pkg = JSON.parse(content);
@@ -4566,7 +4581,7 @@ function stripToMinor(version2) {
4566
4581
  }
4567
4582
  function getLastVersionInfoFromGit() {
4568
4583
  try {
4569
- const output = execSync17(
4584
+ const output = execSync18(
4570
4585
  "git log -1 --pretty=format:'%ad|%h' --date=short",
4571
4586
  {
4572
4587
  encoding: "utf-8"
@@ -4609,7 +4624,7 @@ function bumpVersion(version2, type) {
4609
4624
  }
4610
4625
 
4611
4626
  // src/commands/devlog/next/displayNextEntry/index.ts
4612
- import { execSync as execSync18 } from "child_process";
4627
+ import { execSync as execSync19 } from "child_process";
4613
4628
  import chalk51 from "chalk";
4614
4629
 
4615
4630
  // src/commands/devlog/next/displayNextEntry/displayVersion.ts
@@ -4643,7 +4658,7 @@ function findTargetDate(commitsByDate, skipDays) {
4643
4658
  return Array.from(commitsByDate.keys()).filter((d) => !skipDays.has(d)).sort()[0];
4644
4659
  }
4645
4660
  function fetchCommitsByDate(ignore2, lastDate) {
4646
- const output = execSync18(
4661
+ const output = execSync19(
4647
4662
  "git log --pretty=format:'%ad|%h|%s' --date=short -n 500",
4648
4663
  { encoding: "utf-8" }
4649
4664
  );
@@ -4721,7 +4736,7 @@ function next2(options2) {
4721
4736
  }
4722
4737
 
4723
4738
  // src/commands/devlog/repos/index.ts
4724
- import { execSync as execSync19 } from "child_process";
4739
+ import { execSync as execSync20 } from "child_process";
4725
4740
 
4726
4741
  // src/commands/devlog/repos/printReposTable.ts
4727
4742
  import chalk52 from "chalk";
@@ -4756,7 +4771,7 @@ function getStatus(lastPush, lastDevlog) {
4756
4771
  return lastDevlog < lastPush ? "outdated" : "ok";
4757
4772
  }
4758
4773
  function fetchRepos(days, all) {
4759
- const json = execSync19(
4774
+ const json = execSync20(
4760
4775
  "gh repo list staff0rd --json name,pushedAt,isArchived --limit 200",
4761
4776
  { encoding: "utf-8" }
4762
4777
  );
@@ -5116,7 +5131,7 @@ async function deps(csprojPath, options2) {
5116
5131
  }
5117
5132
 
5118
5133
  // src/commands/dotnet/getChangedCsFiles.ts
5119
- import { execSync as execSync20 } from "child_process";
5134
+ import { execSync as execSync21 } from "child_process";
5120
5135
  var SCOPE_ALL = "all";
5121
5136
  var SCOPE_BASE = "base:";
5122
5137
  var SCOPE_COMMIT = "commit:";
@@ -5140,7 +5155,7 @@ function getChangedCsFiles(scope) {
5140
5155
  } else {
5141
5156
  cmd = "git diff --name-only HEAD";
5142
5157
  }
5143
- const output = execSync20(cmd, { encoding: "utf-8" }).trim();
5158
+ const output = execSync21(cmd, { encoding: "utf-8" }).trim();
5144
5159
  if (output === "") return [];
5145
5160
  return output.split("\n").filter((f) => f.toLowerCase().endsWith(".cs"));
5146
5161
  }
@@ -5338,14 +5353,14 @@ function parseInspectReport(json) {
5338
5353
  }
5339
5354
 
5340
5355
  // src/commands/dotnet/runInspectCode.ts
5341
- import { execSync as execSync21 } from "child_process";
5356
+ import { execSync as execSync22 } from "child_process";
5342
5357
  import { existsSync as existsSync25, readFileSync as readFileSync20, unlinkSync as unlinkSync4 } from "fs";
5343
5358
  import { tmpdir as tmpdir2 } from "os";
5344
5359
  import path26 from "path";
5345
5360
  import chalk62 from "chalk";
5346
5361
  function assertJbInstalled() {
5347
5362
  try {
5348
- execSync21("jb inspectcode --version", { stdio: "pipe" });
5363
+ execSync22("jb inspectcode --version", { stdio: "pipe" });
5349
5364
  } catch {
5350
5365
  console.error(chalk62.red("jb is not installed. Install with:"));
5351
5366
  console.error(
@@ -5359,7 +5374,7 @@ function runInspectCode(slnPath, include, swea) {
5359
5374
  const includeFlag = include ? ` --include="${include}"` : "";
5360
5375
  const sweaFlag = swea ? " --swea" : "";
5361
5376
  try {
5362
- execSync21(
5377
+ execSync22(
5363
5378
  `jb inspectcode "${slnPath}" -o="${reportPath}"${includeFlag}${sweaFlag} --verbosity=OFF`,
5364
5379
  { stdio: "pipe" }
5365
5380
  );
@@ -5380,7 +5395,7 @@ function runInspectCode(slnPath, include, swea) {
5380
5395
  }
5381
5396
 
5382
5397
  // src/commands/dotnet/runRoslynInspect.ts
5383
- import { execSync as execSync22 } from "child_process";
5398
+ import { execSync as execSync23 } from "child_process";
5384
5399
  import chalk63 from "chalk";
5385
5400
  function resolveMsbuildPath() {
5386
5401
  const config = loadConfig();
@@ -5390,7 +5405,7 @@ function resolveMsbuildPath() {
5390
5405
  function assertMsbuildInstalled() {
5391
5406
  const msbuild = resolveMsbuildPath();
5392
5407
  try {
5393
- execSync22(`"${msbuild}" -version`, { stdio: "pipe" });
5408
+ execSync23(`"${msbuild}" -version`, { stdio: "pipe" });
5394
5409
  } catch {
5395
5410
  console.error(chalk63.red(`msbuild not found at: ${msbuild}`));
5396
5411
  console.error(
@@ -5416,7 +5431,7 @@ function runRoslynInspect(slnPath) {
5416
5431
  const msbuild = resolveMsbuildPath();
5417
5432
  let output;
5418
5433
  try {
5419
- output = execSync22(
5434
+ output = execSync23(
5420
5435
  `"${msbuild}" "${slnPath}" -t:Build -v:minimal -maxcpucount -p:EnforceCodeStyleInBuild=true -p:RunAnalyzersDuringBuild=true 2>&1`,
5421
5436
  { encoding: "utf-8", stdio: "pipe", maxBuffer: 50 * 1024 * 1024 }
5422
5437
  );
@@ -5548,12 +5563,12 @@ function adfToText(doc) {
5548
5563
  }
5549
5564
 
5550
5565
  // src/commands/jira/fetchIssue.ts
5551
- import { execSync as execSync23 } from "child_process";
5566
+ import { execSync as execSync24 } from "child_process";
5552
5567
  import chalk65 from "chalk";
5553
5568
  function fetchIssue(issueKey, fields) {
5554
5569
  let result;
5555
5570
  try {
5556
- result = execSync23(
5571
+ result = execSync24(
5557
5572
  `acli jira workitem view ${issueKey} -f ${fields} --json`,
5558
5573
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
5559
5574
  );
@@ -5599,7 +5614,7 @@ function acceptanceCriteria(issueKey) {
5599
5614
  }
5600
5615
 
5601
5616
  // src/commands/jira/jiraAuth.ts
5602
- import { execSync as execSync24 } from "child_process";
5617
+ import { execSync as execSync25 } from "child_process";
5603
5618
 
5604
5619
  // src/shared/loadJson.ts
5605
5620
  import { existsSync as existsSync26, mkdirSync as mkdirSync5, readFileSync as readFileSync21, writeFileSync as writeFileSync18 } from "fs";
@@ -5663,7 +5678,7 @@ async function jiraAuth() {
5663
5678
  console.error("All fields are required.");
5664
5679
  process.exit(1);
5665
5680
  }
5666
- execSync24(`acli jira auth login --site ${site} --email "${email}" --token`, {
5681
+ execSync25(`acli jira auth login --site ${site} --email "${email}" --token`, {
5667
5682
  encoding: "utf-8",
5668
5683
  input: token,
5669
5684
  stdio: ["pipe", "inherit", "inherit"]
@@ -5944,7 +5959,7 @@ import { tmpdir as tmpdir3 } from "os";
5944
5959
  import { join as join20 } from "path";
5945
5960
 
5946
5961
  // src/commands/prs/shared.ts
5947
- import { execSync as execSync25 } from "child_process";
5962
+ import { execSync as execSync26 } from "child_process";
5948
5963
  function isGhNotInstalled(error) {
5949
5964
  if (error instanceof Error) {
5950
5965
  const msg = error.message.toLowerCase();
@@ -5960,14 +5975,14 @@ function isNotFound(error) {
5960
5975
  }
5961
5976
  function getRepoInfo() {
5962
5977
  const repoInfo = JSON.parse(
5963
- execSync25("gh repo view --json owner,name", { encoding: "utf-8" })
5978
+ execSync26("gh repo view --json owner,name", { encoding: "utf-8" })
5964
5979
  );
5965
5980
  return { org: repoInfo.owner.login, repo: repoInfo.name };
5966
5981
  }
5967
5982
  function getCurrentPrNumber() {
5968
5983
  try {
5969
5984
  const prInfo = JSON.parse(
5970
- execSync25("gh pr view --json number", { encoding: "utf-8" })
5985
+ execSync26("gh pr view --json number", { encoding: "utf-8" })
5971
5986
  );
5972
5987
  return prInfo.number;
5973
5988
  } catch (error) {
@@ -5981,7 +5996,7 @@ function getCurrentPrNumber() {
5981
5996
  function getCurrentPrNodeId() {
5982
5997
  try {
5983
5998
  const prInfo = JSON.parse(
5984
- execSync25("gh pr view --json id", { encoding: "utf-8" })
5999
+ execSync26("gh pr view --json id", { encoding: "utf-8" })
5985
6000
  );
5986
6001
  return prInfo.id;
5987
6002
  } catch (error) {
@@ -6052,10 +6067,10 @@ function comment(path49, line, body) {
6052
6067
  }
6053
6068
 
6054
6069
  // src/commands/prs/fixed.ts
6055
- import { execSync as execSync27 } from "child_process";
6070
+ import { execSync as execSync28 } from "child_process";
6056
6071
 
6057
6072
  // src/commands/prs/resolveCommentWithReply.ts
6058
- import { execSync as execSync26 } from "child_process";
6073
+ import { execSync as execSync27 } from "child_process";
6059
6074
  import { unlinkSync as unlinkSync7, writeFileSync as writeFileSync20 } from "fs";
6060
6075
  import { tmpdir as tmpdir4 } from "os";
6061
6076
  import { join as join22 } from "path";
@@ -6085,7 +6100,7 @@ function deleteCommentsCache(prNumber) {
6085
6100
 
6086
6101
  // src/commands/prs/resolveCommentWithReply.ts
6087
6102
  function replyToComment(org, repo, prNumber, commentId, message) {
6088
- execSync26(
6103
+ execSync27(
6089
6104
  `gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
6090
6105
  { stdio: ["inherit", "pipe", "inherit"] }
6091
6106
  );
@@ -6095,7 +6110,7 @@ function resolveThread(threadId) {
6095
6110
  const queryFile = join22(tmpdir4(), `gh-mutation-${Date.now()}.graphql`);
6096
6111
  writeFileSync20(queryFile, mutation);
6097
6112
  try {
6098
- execSync26(
6113
+ execSync27(
6099
6114
  `gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
6100
6115
  { stdio: ["inherit", "pipe", "inherit"] }
6101
6116
  );
@@ -6147,7 +6162,7 @@ function resolveCommentWithReply(commentId, message) {
6147
6162
  // src/commands/prs/fixed.ts
6148
6163
  function verifySha(sha) {
6149
6164
  try {
6150
- return execSync27(`git rev-parse --verify ${sha}`, {
6165
+ return execSync28(`git rev-parse --verify ${sha}`, {
6151
6166
  encoding: "utf-8"
6152
6167
  }).trim();
6153
6168
  } catch {
@@ -6161,7 +6176,7 @@ function fixed(commentId, sha) {
6161
6176
  const { org, repo } = getRepoInfo();
6162
6177
  const repoUrl = `https://github.com/${org}/${repo}`;
6163
6178
  const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
6164
- execSync27("git push", { stdio: "inherit" });
6179
+ execSync28("git push", { stdio: "inherit" });
6165
6180
  resolveCommentWithReply(commentId, message);
6166
6181
  } catch (error) {
6167
6182
  if (isGhNotInstalled(error)) {
@@ -6179,7 +6194,7 @@ import { join as join24 } from "path";
6179
6194
  import { stringify } from "yaml";
6180
6195
 
6181
6196
  // src/commands/prs/fetchThreadIds.ts
6182
- import { execSync as execSync28 } from "child_process";
6197
+ import { execSync as execSync29 } from "child_process";
6183
6198
  import { unlinkSync as unlinkSync8, writeFileSync as writeFileSync21 } from "fs";
6184
6199
  import { tmpdir as tmpdir5 } from "os";
6185
6200
  import { join as join23 } from "path";
@@ -6188,7 +6203,7 @@ function fetchThreadIds(org, repo, prNumber) {
6188
6203
  const queryFile = join23(tmpdir5(), `gh-query-${Date.now()}.graphql`);
6189
6204
  writeFileSync21(queryFile, THREAD_QUERY);
6190
6205
  try {
6191
- const result = execSync28(
6206
+ const result = execSync29(
6192
6207
  `gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
6193
6208
  { encoding: "utf-8" }
6194
6209
  );
@@ -6210,9 +6225,9 @@ function fetchThreadIds(org, repo, prNumber) {
6210
6225
  }
6211
6226
 
6212
6227
  // src/commands/prs/listComments/fetchReviewComments.ts
6213
- import { execSync as execSync29 } from "child_process";
6228
+ import { execSync as execSync30 } from "child_process";
6214
6229
  function fetchJson(endpoint) {
6215
- const result = execSync29(`gh api --paginate ${endpoint}`, {
6230
+ const result = execSync30(`gh api --paginate ${endpoint}`, {
6216
6231
  encoding: "utf-8"
6217
6232
  });
6218
6233
  if (!result.trim()) return [];
@@ -6351,7 +6366,7 @@ async function listComments() {
6351
6366
  }
6352
6367
 
6353
6368
  // src/commands/prs/prs/index.ts
6354
- import { execSync as execSync30 } from "child_process";
6369
+ import { execSync as execSync31 } from "child_process";
6355
6370
 
6356
6371
  // src/commands/prs/prs/displayPaginated/index.ts
6357
6372
  import enquirer8 from "enquirer";
@@ -6457,7 +6472,7 @@ async function displayPaginated(pullRequests) {
6457
6472
  async function prs(options2) {
6458
6473
  const state = options2.open ? "open" : options2.closed ? "closed" : "all";
6459
6474
  try {
6460
- const result = execSync30(
6475
+ const result = execSync31(
6461
6476
  `gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100`,
6462
6477
  { encoding: "utf-8" }
6463
6478
  );
@@ -6480,7 +6495,7 @@ async function prs(options2) {
6480
6495
  }
6481
6496
 
6482
6497
  // src/commands/prs/wontfix.ts
6483
- import { execSync as execSync31 } from "child_process";
6498
+ import { execSync as execSync32 } from "child_process";
6484
6499
  function validateReason(reason) {
6485
6500
  const lowerReason = reason.toLowerCase();
6486
6501
  if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
@@ -6497,7 +6512,7 @@ function validateShaReferences(reason) {
6497
6512
  const invalidShas = [];
6498
6513
  for (const sha of shas) {
6499
6514
  try {
6500
- execSync31(`git cat-file -t ${sha}`, { stdio: "pipe" });
6515
+ execSync32(`git cat-file -t ${sha}`, { stdio: "pipe" });
6501
6516
  } catch {
6502
6517
  invalidShas.push(sha);
6503
6518
  }
@@ -6611,10 +6626,10 @@ import chalk74 from "chalk";
6611
6626
  import Enquirer2 from "enquirer";
6612
6627
 
6613
6628
  // src/commands/ravendb/searchItems.ts
6614
- import { execSync as execSync32 } from "child_process";
6629
+ import { execSync as execSync33 } from "child_process";
6615
6630
  import chalk73 from "chalk";
6616
6631
  function opExec(args) {
6617
- return execSync32(`op ${args}`, {
6632
+ return execSync33(`op ${args}`, {
6618
6633
  encoding: "utf-8",
6619
6634
  stdio: ["pipe", "pipe", "pipe"]
6620
6635
  }).trim();
@@ -6766,7 +6781,7 @@ ${errorText}`
6766
6781
  }
6767
6782
 
6768
6783
  // src/commands/ravendb/resolveOpSecret.ts
6769
- import { execSync as execSync33 } from "child_process";
6784
+ import { execSync as execSync34 } from "child_process";
6770
6785
  import chalk78 from "chalk";
6771
6786
  function resolveOpSecret(reference) {
6772
6787
  if (!reference.startsWith("op://")) {
@@ -6774,7 +6789,7 @@ function resolveOpSecret(reference) {
6774
6789
  process.exit(1);
6775
6790
  }
6776
6791
  try {
6777
- return execSync33(`op read "${reference}"`, {
6792
+ return execSync34(`op read "${reference}"`, {
6778
6793
  encoding: "utf-8",
6779
6794
  stdio: ["pipe", "pipe", "pipe"]
6780
6795
  }).trim();
@@ -7023,7 +7038,7 @@ Refactor check failed:
7023
7038
  }
7024
7039
 
7025
7040
  // src/commands/refactor/check/getViolations/index.ts
7026
- import { execSync as execSync34 } from "child_process";
7041
+ import { execSync as execSync35 } from "child_process";
7027
7042
  import fs16 from "fs";
7028
7043
  import { minimatch as minimatch4 } from "minimatch";
7029
7044
 
@@ -7073,7 +7088,7 @@ function getGitFiles(options2) {
7073
7088
  }
7074
7089
  const files = /* @__PURE__ */ new Set();
7075
7090
  if (options2.staged || options2.modified) {
7076
- const staged = execSync34("git diff --cached --name-only", {
7091
+ const staged = execSync35("git diff --cached --name-only", {
7077
7092
  encoding: "utf-8"
7078
7093
  });
7079
7094
  for (const file of staged.trim().split("\n").filter(Boolean)) {
@@ -7081,7 +7096,7 @@ function getGitFiles(options2) {
7081
7096
  }
7082
7097
  }
7083
7098
  if (options2.unstaged || options2.modified) {
7084
- const unstaged = execSync34("git diff --name-only", { encoding: "utf-8" });
7099
+ const unstaged = execSync35("git diff --name-only", { encoding: "utf-8" });
7085
7100
  for (const file of unstaged.trim().split("\n").filter(Boolean)) {
7086
7101
  files.add(file);
7087
7102
  }
@@ -9376,7 +9391,7 @@ import { mkdirSync as mkdirSync10 } from "fs";
9376
9391
  import { join as join34 } from "path";
9377
9392
 
9378
9393
  // src/commands/voice/checkLockFile.ts
9379
- import { execSync as execSync35 } from "child_process";
9394
+ import { execSync as execSync36 } from "child_process";
9380
9395
  import { existsSync as existsSync35, mkdirSync as mkdirSync9, readFileSync as readFileSync26, writeFileSync as writeFileSync24 } from "fs";
9381
9396
  import { join as join33 } from "path";
9382
9397
  function isProcessAlive(pid) {
@@ -9405,7 +9420,7 @@ function bootstrapVenv() {
9405
9420
  if (existsSync35(getVenvPython())) return;
9406
9421
  console.log("Setting up Python environment...");
9407
9422
  const pythonDir = getPythonDir();
9408
- execSync35(
9423
+ execSync36(
9409
9424
  `uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
9410
9425
  {
9411
9426
  stdio: "inherit",
@@ -9572,11 +9587,11 @@ import { randomBytes } from "crypto";
9572
9587
  import chalk101 from "chalk";
9573
9588
 
9574
9589
  // src/lib/openBrowser.ts
9575
- import { execSync as execSync36 } from "child_process";
9590
+ import { execSync as execSync37 } from "child_process";
9576
9591
  function tryExec(commands) {
9577
9592
  for (const cmd of commands) {
9578
9593
  try {
9579
- execSync36(cmd);
9594
+ execSync37(cmd);
9580
9595
  return true;
9581
9596
  } catch {
9582
9597
  }
@@ -9802,7 +9817,7 @@ function registerRoam(program2) {
9802
9817
  }
9803
9818
 
9804
9819
  // src/commands/run/index.ts
9805
- import { execSync as execSync37 } from "child_process";
9820
+ import { execSync as execSync38 } from "child_process";
9806
9821
 
9807
9822
  // src/commands/run/resolveParams.ts
9808
9823
  function resolveParams(params, cliArgs) {
@@ -9965,7 +9980,7 @@ function listRunConfigs() {
9965
9980
  function runPreCommands(pre) {
9966
9981
  for (const cmd of pre) {
9967
9982
  try {
9968
- execSync37(cmd, { stdio: "inherit" });
9983
+ execSync38(cmd, { stdio: "inherit" });
9969
9984
  } catch (err) {
9970
9985
  const code = err && typeof err === "object" && "status" in err ? err.status : 1;
9971
9986
  process.exit(code);
@@ -9983,7 +9998,7 @@ function run3(name, args) {
9983
9998
  }
9984
9999
 
9985
10000
  // src/commands/screenshot/index.ts
9986
- import { execSync as execSync38 } from "child_process";
10001
+ import { execSync as execSync39 } from "child_process";
9987
10002
  import { existsSync as existsSync38, mkdirSync as mkdirSync13, unlinkSync as unlinkSync10, writeFileSync as writeFileSync27 } from "fs";
9988
10003
  import { tmpdir as tmpdir6 } from "os";
9989
10004
  import { join as join38, resolve as resolve5 } from "path";
@@ -10126,7 +10141,7 @@ function runPowerShellScript(processName, outputPath) {
10126
10141
  const scriptPath = join38(tmpdir6(), `assist-screenshot-${Date.now()}.ps1`);
10127
10142
  writeFileSync27(scriptPath, captureWindowPs1, "utf-8");
10128
10143
  try {
10129
- execSync38(
10144
+ execSync39(
10130
10145
  `powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
10131
10146
  { stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
10132
10147
  );
@@ -10325,7 +10340,7 @@ function syncCommands(claudeDir, targetBase) {
10325
10340
  }
10326
10341
 
10327
10342
  // src/commands/update.ts
10328
- import { execSync as execSync39 } from "child_process";
10343
+ import { execSync as execSync40 } from "child_process";
10329
10344
  import * as path48 from "path";
10330
10345
  function isGlobalNpmInstall(dir) {
10331
10346
  try {
@@ -10333,7 +10348,7 @@ function isGlobalNpmInstall(dir) {
10333
10348
  if (resolved.split(path48.sep).includes("node_modules")) {
10334
10349
  return true;
10335
10350
  }
10336
- const globalPrefix = execSync39("npm prefix -g", { stdio: "pipe" }).toString().trim();
10351
+ const globalPrefix = execSync40("npm prefix -g", { stdio: "pipe" }).toString().trim();
10337
10352
  return resolved.toLowerCase().startsWith(path48.resolve(globalPrefix).toLowerCase());
10338
10353
  } catch {
10339
10354
  return false;
@@ -10344,18 +10359,18 @@ async function update() {
10344
10359
  console.log(`Assist is installed at: ${installDir}`);
10345
10360
  if (isGitRepo(installDir)) {
10346
10361
  console.log("Detected git repo installation, pulling latest...");
10347
- execSync39("git pull", { cwd: installDir, stdio: "inherit" });
10362
+ execSync40("git pull", { cwd: installDir, stdio: "inherit" });
10348
10363
  console.log("Installing dependencies...");
10349
- execSync39("npm i", { cwd: installDir, stdio: "inherit" });
10364
+ execSync40("npm i", { cwd: installDir, stdio: "inherit" });
10350
10365
  console.log("Building...");
10351
- execSync39("npm run build", { cwd: installDir, stdio: "inherit" });
10366
+ execSync40("npm run build", { cwd: installDir, stdio: "inherit" });
10352
10367
  console.log("Syncing commands...");
10353
- execSync39("assist sync", { stdio: "inherit" });
10368
+ execSync40("assist sync", { stdio: "inherit" });
10354
10369
  } else if (isGlobalNpmInstall(installDir)) {
10355
10370
  console.log("Detected global npm installation, updating...");
10356
- execSync39("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
10371
+ execSync40("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
10357
10372
  console.log("Syncing commands...");
10358
- execSync39("assist sync", { stdio: "inherit" });
10373
+ execSync40("assist sync", { stdio: "inherit" });
10359
10374
  } else {
10360
10375
  console.error(
10361
10376
  "Could not determine installation method. Expected a git repo or global npm install."
@@ -10392,6 +10407,7 @@ program.command("notify").description(
10392
10407
  "Show notification from Claude Code hook (reads JSON from stdin)"
10393
10408
  ).action(notify);
10394
10409
  program.command("update").description("Update assist to the latest version and sync commands").action(update);
10410
+ program.command("coverage").description("Print global statement coverage percentage").action(coverage);
10395
10411
  program.command("screenshot").description("Capture a screenshot of a running application window").argument("<process>", "Name of the running process (e.g. notepad, code)").action(screenshot);
10396
10412
  registerCliHook(program);
10397
10413
  registerJira(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.147.4",
3
+ "version": "0.148.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {