@staff0rd/assist 0.84.0 → 0.85.1

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.
@@ -0,0 +1,10 @@
1
+ Never use `pip install` directly. All Python dependency management uses `uv`.
2
+
3
+ **The venv MUST live in `~/.assist/voice/.venv`, NEVER in this directory or anywhere in the repo.**
4
+
5
+ Every `uv` command that touches this project MUST set `UV_PROJECT_ENVIRONMENT` to point to the home dir venv. This includes `uv sync`, `uv run`, and any other uv command. There must be no `.venv/`, `__pycache__/`, `*.egg-info/`, or any other generated artifacts in this directory.
6
+
7
+ - Dependencies are declared in `pyproject.toml`
8
+ - Bootstrap uses `uv sync --project <dir> --no-install-project` with `UV_PROJECT_ENVIRONMENT=~/.assist/voice/.venv`
9
+ - To add a dependency: edit `pyproject.toml`, then run `UV_PROJECT_ENVIRONMENT=~/.assist/voice/.venv uv lock --project src/commands/voice/python`
10
+ - No build system — this is a virtual project, not an installable package
@@ -185,20 +185,62 @@ class VoiceDaemon:
185
185
  return process_name in self._submit_windows
186
186
 
187
187
  def _update_typed_text(self, new_text: str) -> None:
188
- """Diff old typed text vs new, backspace + type the difference."""
188
+ """Diff old typed text vs new at word level, minimising deletions.
189
+
190
+ Only deletes back to the first word that changed; appends everything
191
+ after the common word prefix. This avoids the jarring full-delete
192
+ that character-level diffing causes when earlier words shift slightly.
193
+ """
189
194
  old = self._typed_text
190
- # Find common prefix
191
- common = 0
192
- for a, b in zip(old, new_text):
195
+ if old == new_text:
196
+ return
197
+
198
+ old_words = old.split()
199
+ new_words = new_text.split()
200
+
201
+ # Find the longest common word prefix
202
+ common_words = 0
203
+ for a, b in zip(old_words, new_words):
193
204
  if a == b:
194
- common += 1
205
+ common_words += 1
195
206
  else:
196
207
  break
197
- # Backspace what's wrong, type new suffix
198
- to_delete = len(old) - common
199
- to_type = new_text[common:]
208
+
209
+ # Character position where the common word prefix ends (including
210
+ # the trailing space after the last common word, if any).
211
+ if common_words == 0:
212
+ keep_chars = 0
213
+ else:
214
+ # Rejoin the common words and add one space (the separator before
215
+ # the next word that was already typed).
216
+ keep = " ".join(old_words[:common_words])
217
+ # Only count the trailing space if there were more old words after
218
+ # the common prefix (meaning that space is already on screen).
219
+ if common_words < len(old_words):
220
+ keep_chars = len(keep) + 1 # +1 for the space
221
+ else:
222
+ keep_chars = len(keep)
223
+
224
+ to_delete = len(old) - keep_chars
200
225
  if to_delete > 0:
201
226
  keyboard.backspace(to_delete)
227
+
228
+ # Build the new suffix to type from the first divergent word onward
229
+ if common_words == 0:
230
+ to_type = new_text
231
+ else:
232
+ suffix = " ".join(new_words[common_words:])
233
+ if suffix:
234
+ # Need a space separator if we kept text and are appending
235
+ if keep_chars > 0 and common_words < len(old_words):
236
+ to_type = suffix
237
+ elif keep_chars > 0:
238
+ to_type = " " + suffix
239
+ else:
240
+ to_type = suffix
241
+ else:
242
+ to_type = ""
243
+
202
244
  if to_type:
203
245
  keyboard.type_text(to_type)
204
246
  self._typed_text = new_text
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.84.0",
9
+ version: "0.85.1",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -459,6 +459,7 @@ var expectedScripts = {
459
459
  "verify:duplicate-code": "jscpd --format 'typescript,tsx' --exitCode 1 --ignore '**/*.test.*' -r consoleFull src",
460
460
  "verify:test": "vitest run --reporter=dot --silent",
461
461
  "verify:hardcoded-colors": "assist verify hardcoded-colors",
462
+ "verify:no-venv": "assist verify no-venv",
462
463
  "verify:maintainability": "assist complexity maintainability ./src --threshold 60"
463
464
  };
464
465
 
@@ -1348,7 +1349,7 @@ function lint() {
1348
1349
  }
1349
1350
 
1350
1351
  // src/commands/new/registerNew/newCli/index.ts
1351
- import { execSync as execSync9 } from "child_process";
1352
+ import { execSync as execSync10 } from "child_process";
1352
1353
  import { basename as basename2, resolve } from "path";
1353
1354
 
1354
1355
  // src/commands/verify/hardcodedColors.ts
@@ -1439,6 +1440,38 @@ function list() {
1439
1440
  }
1440
1441
  }
1441
1442
 
1443
+ // src/commands/verify/noVenv.ts
1444
+ import { execSync as execSync6 } from "child_process";
1445
+ function noVenv() {
1446
+ try {
1447
+ const output = execSync6(
1448
+ "find . -type d -name venv -not -path '*/node_modules/*'",
1449
+ {
1450
+ encoding: "utf-8"
1451
+ }
1452
+ ).trim();
1453
+ if (output.length === 0) {
1454
+ console.log("No venv folders found.");
1455
+ process.exit(0);
1456
+ }
1457
+ const folders = output.split("\n");
1458
+ console.log("venv folders found:\n");
1459
+ for (const folder of folders) {
1460
+ console.log(` ${folder}`);
1461
+ }
1462
+ console.log(`
1463
+ Total: ${folders.length} venv folder(s)`);
1464
+ console.log(
1465
+ "\nRemove venv folders and use a project-level virtual environment manager instead."
1466
+ );
1467
+ console.log("Add 'venv/' to .gitignore if needed.");
1468
+ process.exit(1);
1469
+ } catch {
1470
+ console.log("No venv folders found.");
1471
+ process.exit(0);
1472
+ }
1473
+ }
1474
+
1442
1475
  // src/commands/verify/run/createTimerCallback/printTaskStatuses.ts
1443
1476
  function formatDuration(ms) {
1444
1477
  if (ms < 1e3) {
@@ -1485,9 +1518,9 @@ function initTaskStatuses(scripts) {
1485
1518
  import { minimatch as minimatch2 } from "minimatch";
1486
1519
 
1487
1520
  // src/commands/verify/run/getChangedFiles.ts
1488
- import { execSync as execSync6 } from "child_process";
1521
+ import { execSync as execSync7 } from "child_process";
1489
1522
  function getChangedFiles() {
1490
- const output = execSync6("git diff --name-only HEAD", {
1523
+ const output = execSync7("git diff --name-only HEAD", {
1491
1524
  encoding: "utf-8"
1492
1525
  }).trim();
1493
1526
  if (output === "") return [];
@@ -1601,25 +1634,25 @@ async function run(options2 = {}) {
1601
1634
  }
1602
1635
 
1603
1636
  // src/commands/new/registerNew/initGit.ts
1604
- import { execSync as execSync7 } from "child_process";
1637
+ import { execSync as execSync8 } from "child_process";
1605
1638
  import { writeFileSync as writeFileSync6 } from "fs";
1606
1639
  function initGit() {
1607
1640
  console.log("Initializing git repository...");
1608
- execSync7("git init", { stdio: "inherit" });
1641
+ execSync8("git init", { stdio: "inherit" });
1609
1642
  writeFileSync6(".gitignore", "dist\nnode_modules\n");
1610
1643
  }
1611
1644
 
1612
1645
  // src/commands/new/registerNew/newCli/initPackageJson.ts
1613
- import { execSync as execSync8 } from "child_process";
1646
+ import { execSync as execSync9 } from "child_process";
1614
1647
  function initPackageJson(name) {
1615
1648
  console.log("Initializing package.json...");
1616
- execSync8("npm init -y", { stdio: "inherit" });
1649
+ execSync9("npm init -y", { stdio: "inherit" });
1617
1650
  console.log("Configuring package.json...");
1618
- execSync8("npm pkg delete main", { stdio: "inherit" });
1619
- execSync8("npm pkg set type=module", { stdio: "inherit" });
1620
- execSync8(`npm pkg set bin.${name}=./dist/index.js`, { stdio: "inherit" });
1621
- execSync8("npm pkg set scripts.build=tsup", { stdio: "inherit" });
1622
- execSync8('npm pkg set scripts.start="node dist/index.js"', {
1651
+ execSync9("npm pkg delete main", { stdio: "inherit" });
1652
+ execSync9("npm pkg set type=module", { stdio: "inherit" });
1653
+ execSync9(`npm pkg set bin.${name}=./dist/index.js`, { stdio: "inherit" });
1654
+ execSync9("npm pkg set scripts.build=tsup", { stdio: "inherit" });
1655
+ execSync9('npm pkg set scripts.start="node dist/index.js"', {
1623
1656
  stdio: "inherit"
1624
1657
  });
1625
1658
  }
@@ -1684,8 +1717,8 @@ async function newCli() {
1684
1717
  initGit();
1685
1718
  initPackageJson(name);
1686
1719
  console.log("Installing dependencies...");
1687
- execSync9("npm install commander", { stdio: "inherit" });
1688
- execSync9("npm install -D tsup typescript @types/node", {
1720
+ execSync10("npm install commander", { stdio: "inherit" });
1721
+ execSync10("npm install -D tsup typescript @types/node", {
1689
1722
  stdio: "inherit"
1690
1723
  });
1691
1724
  writeCliTemplate(name);
@@ -1694,11 +1727,11 @@ async function newCli() {
1694
1727
  }
1695
1728
 
1696
1729
  // src/commands/new/registerNew/newProject.ts
1697
- import { execSync as execSync11 } from "child_process";
1730
+ import { execSync as execSync12 } from "child_process";
1698
1731
  import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync9 } from "fs";
1699
1732
 
1700
1733
  // src/commands/deploy/init/index.ts
1701
- import { execSync as execSync10 } from "child_process";
1734
+ import { execSync as execSync11 } from "child_process";
1702
1735
  import chalk21 from "chalk";
1703
1736
  import enquirer3 from "enquirer";
1704
1737
 
@@ -1751,7 +1784,7 @@ Created ${WORKFLOW_PATH}`));
1751
1784
  // src/commands/deploy/init/index.ts
1752
1785
  async function ensureNetlifyCli() {
1753
1786
  try {
1754
- execSync10("netlify sites:create --disable-linking", { stdio: "inherit" });
1787
+ execSync11("netlify sites:create --disable-linking", { stdio: "inherit" });
1755
1788
  } catch (error) {
1756
1789
  if (!(error instanceof Error) || !error.message.includes("command not found"))
1757
1790
  throw error;
@@ -1766,9 +1799,9 @@ async function ensureNetlifyCli() {
1766
1799
  process.exit(1);
1767
1800
  }
1768
1801
  console.log(chalk21.dim("\nInstalling netlify-cli...\n"));
1769
- execSync10("npm install -g netlify-cli", { stdio: "inherit" });
1802
+ execSync11("npm install -g netlify-cli", { stdio: "inherit" });
1770
1803
  console.log();
1771
- execSync10("netlify sites:create --disable-linking", { stdio: "inherit" });
1804
+ execSync11("netlify sites:create --disable-linking", { stdio: "inherit" });
1772
1805
  }
1773
1806
  }
1774
1807
  function printSetupInstructions() {
@@ -1811,7 +1844,7 @@ async function init5() {
1811
1844
  // src/commands/new/registerNew/newProject.ts
1812
1845
  async function newProject() {
1813
1846
  console.log("Initializing Vite with react-ts template...");
1814
- execSync11("npm create vite@latest . -- --template react-ts", {
1847
+ execSync12("npm create vite@latest . -- --template react-ts", {
1815
1848
  stdio: "inherit"
1816
1849
  });
1817
1850
  initGit();
@@ -2964,11 +2997,11 @@ function registerDeploy(program2) {
2964
2997
  }
2965
2998
 
2966
2999
  // src/commands/devlog/list/index.ts
2967
- import { execSync as execSync13 } from "child_process";
3000
+ import { execSync as execSync14 } from "child_process";
2968
3001
  import { basename as basename3 } from "path";
2969
3002
 
2970
3003
  // src/commands/devlog/shared.ts
2971
- import { execSync as execSync12 } from "child_process";
3004
+ import { execSync as execSync13 } from "child_process";
2972
3005
  import chalk37 from "chalk";
2973
3006
 
2974
3007
  // src/commands/devlog/loadDevlogEntries.ts
@@ -3012,7 +3045,7 @@ function loadDevlogEntries(repoName) {
3012
3045
  // src/commands/devlog/shared.ts
3013
3046
  function getCommitFiles(hash) {
3014
3047
  try {
3015
- const output = execSync12(`git show --name-only --format="" ${hash}`, {
3048
+ const output = execSync13(`git show --name-only --format="" ${hash}`, {
3016
3049
  encoding: "utf-8"
3017
3050
  });
3018
3051
  return output.trim().split("\n").filter(Boolean);
@@ -3083,7 +3116,7 @@ function list3(options2) {
3083
3116
  const devlogEntries = loadDevlogEntries(repoName);
3084
3117
  const reverseFlag = options2.reverse ? "--reverse " : "";
3085
3118
  const limitFlag = options2.reverse ? "" : "-n 500 ";
3086
- const output = execSync13(
3119
+ const output = execSync14(
3087
3120
  `git log ${reverseFlag}${limitFlag}--pretty=format:'%ad|%h|%s' --date=short`,
3088
3121
  { encoding: "utf-8" }
3089
3122
  );
@@ -3109,11 +3142,11 @@ function list3(options2) {
3109
3142
  }
3110
3143
 
3111
3144
  // src/commands/devlog/getLastVersionInfo.ts
3112
- import { execSync as execSync14 } from "child_process";
3145
+ import { execSync as execSync15 } from "child_process";
3113
3146
  import semver from "semver";
3114
3147
  function getVersionAtCommit(hash) {
3115
3148
  try {
3116
- const content = execSync14(`git show ${hash}:package.json`, {
3149
+ const content = execSync15(`git show ${hash}:package.json`, {
3117
3150
  encoding: "utf-8"
3118
3151
  });
3119
3152
  const pkg = JSON.parse(content);
@@ -3128,7 +3161,7 @@ function stripToMinor(version2) {
3128
3161
  }
3129
3162
  function getLastVersionInfoFromGit() {
3130
3163
  try {
3131
- const output = execSync14(
3164
+ const output = execSync15(
3132
3165
  "git log -1 --pretty=format:'%ad|%h' --date=short",
3133
3166
  {
3134
3167
  encoding: "utf-8"
@@ -3171,7 +3204,7 @@ function bumpVersion(version2, type) {
3171
3204
  }
3172
3205
 
3173
3206
  // src/commands/devlog/next/displayNextEntry/index.ts
3174
- import { execSync as execSync15 } from "child_process";
3207
+ import { execSync as execSync16 } from "child_process";
3175
3208
  import chalk40 from "chalk";
3176
3209
 
3177
3210
  // src/commands/devlog/next/displayNextEntry/displayVersion.ts
@@ -3205,7 +3238,7 @@ function findTargetDate(commitsByDate, skipDays) {
3205
3238
  return Array.from(commitsByDate.keys()).filter((d) => !skipDays.has(d)).sort()[0];
3206
3239
  }
3207
3240
  function fetchCommitsByDate(ignore2, lastDate) {
3208
- const output = execSync15(
3241
+ const output = execSync16(
3209
3242
  "git log --pretty=format:'%ad|%h|%s' --date=short -n 500",
3210
3243
  { encoding: "utf-8" }
3211
3244
  );
@@ -3336,7 +3369,7 @@ import { tmpdir as tmpdir2 } from "os";
3336
3369
  import { join as join12 } from "path";
3337
3370
 
3338
3371
  // src/commands/prs/shared.ts
3339
- import { execSync as execSync16 } from "child_process";
3372
+ import { execSync as execSync17 } from "child_process";
3340
3373
  function isGhNotInstalled(error) {
3341
3374
  if (error instanceof Error) {
3342
3375
  const msg = error.message.toLowerCase();
@@ -3352,14 +3385,14 @@ function isNotFound(error) {
3352
3385
  }
3353
3386
  function getRepoInfo() {
3354
3387
  const repoInfo = JSON.parse(
3355
- execSync16("gh repo view --json owner,name", { encoding: "utf-8" })
3388
+ execSync17("gh repo view --json owner,name", { encoding: "utf-8" })
3356
3389
  );
3357
3390
  return { org: repoInfo.owner.login, repo: repoInfo.name };
3358
3391
  }
3359
3392
  function getCurrentPrNumber() {
3360
3393
  try {
3361
3394
  const prInfo = JSON.parse(
3362
- execSync16("gh pr view --json number", { encoding: "utf-8" })
3395
+ execSync17("gh pr view --json number", { encoding: "utf-8" })
3363
3396
  );
3364
3397
  return prInfo.number;
3365
3398
  } catch (error) {
@@ -3373,7 +3406,7 @@ function getCurrentPrNumber() {
3373
3406
  function getCurrentPrNodeId() {
3374
3407
  try {
3375
3408
  const prInfo = JSON.parse(
3376
- execSync16("gh pr view --json id", { encoding: "utf-8" })
3409
+ execSync17("gh pr view --json id", { encoding: "utf-8" })
3377
3410
  );
3378
3411
  return prInfo.id;
3379
3412
  } catch (error) {
@@ -3444,10 +3477,10 @@ function comment(path31, line, body) {
3444
3477
  }
3445
3478
 
3446
3479
  // src/commands/prs/fixed.ts
3447
- import { execSync as execSync18 } from "child_process";
3480
+ import { execSync as execSync19 } from "child_process";
3448
3481
 
3449
3482
  // src/commands/prs/resolveCommentWithReply.ts
3450
- import { execSync as execSync17 } from "child_process";
3483
+ import { execSync as execSync18 } from "child_process";
3451
3484
  import { unlinkSync as unlinkSync5, writeFileSync as writeFileSync14 } from "fs";
3452
3485
  import { tmpdir as tmpdir3 } from "os";
3453
3486
  import { join as join14 } from "path";
@@ -3477,7 +3510,7 @@ function deleteCommentsCache(prNumber) {
3477
3510
 
3478
3511
  // src/commands/prs/resolveCommentWithReply.ts
3479
3512
  function replyToComment(org, repo, prNumber, commentId, message) {
3480
- execSync17(
3513
+ execSync18(
3481
3514
  `gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
3482
3515
  { stdio: "inherit" }
3483
3516
  );
@@ -3487,7 +3520,7 @@ function resolveThread(threadId) {
3487
3520
  const queryFile = join14(tmpdir3(), `gh-mutation-${Date.now()}.graphql`);
3488
3521
  writeFileSync14(queryFile, mutation);
3489
3522
  try {
3490
- execSync17(
3523
+ execSync18(
3491
3524
  `gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
3492
3525
  { stdio: "inherit" }
3493
3526
  );
@@ -3539,7 +3572,7 @@ function resolveCommentWithReply(commentId, message) {
3539
3572
  // src/commands/prs/fixed.ts
3540
3573
  function verifySha(sha) {
3541
3574
  try {
3542
- return execSync18(`git rev-parse --verify ${sha}`, {
3575
+ return execSync19(`git rev-parse --verify ${sha}`, {
3543
3576
  encoding: "utf-8"
3544
3577
  }).trim();
3545
3578
  } catch {
@@ -3575,7 +3608,7 @@ function isClaudeCode2() {
3575
3608
  }
3576
3609
 
3577
3610
  // src/commands/prs/fetchThreadIds.ts
3578
- import { execSync as execSync19 } from "child_process";
3611
+ import { execSync as execSync20 } from "child_process";
3579
3612
  import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
3580
3613
  import { tmpdir as tmpdir4 } from "os";
3581
3614
  import { join as join15 } from "path";
@@ -3584,7 +3617,7 @@ function fetchThreadIds(org, repo, prNumber) {
3584
3617
  const queryFile = join15(tmpdir4(), `gh-query-${Date.now()}.graphql`);
3585
3618
  writeFileSync15(queryFile, THREAD_QUERY);
3586
3619
  try {
3587
- const result = execSync19(
3620
+ const result = execSync20(
3588
3621
  `gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
3589
3622
  { encoding: "utf-8" }
3590
3623
  );
@@ -3606,9 +3639,9 @@ function fetchThreadIds(org, repo, prNumber) {
3606
3639
  }
3607
3640
 
3608
3641
  // src/commands/prs/listComments/fetchReviewComments.ts
3609
- import { execSync as execSync20 } from "child_process";
3642
+ import { execSync as execSync21 } from "child_process";
3610
3643
  function fetchJson(endpoint) {
3611
- const result = execSync20(`gh api ${endpoint}`, { encoding: "utf-8" });
3644
+ const result = execSync21(`gh api ${endpoint}`, { encoding: "utf-8" });
3612
3645
  if (!result.trim()) return [];
3613
3646
  return JSON.parse(result);
3614
3647
  }
@@ -3734,7 +3767,7 @@ async function listComments() {
3734
3767
  }
3735
3768
 
3736
3769
  // src/commands/prs/prs/index.ts
3737
- import { execSync as execSync21 } from "child_process";
3770
+ import { execSync as execSync22 } from "child_process";
3738
3771
 
3739
3772
  // src/commands/prs/prs/displayPaginated/index.ts
3740
3773
  import enquirer5 from "enquirer";
@@ -3840,7 +3873,7 @@ async function displayPaginated(pullRequests) {
3840
3873
  async function prs(options2) {
3841
3874
  const state = options2.open ? "open" : options2.closed ? "closed" : "all";
3842
3875
  try {
3843
- const result = execSync21(
3876
+ const result = execSync22(
3844
3877
  `gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100`,
3845
3878
  { encoding: "utf-8" }
3846
3879
  );
@@ -3863,7 +3896,7 @@ async function prs(options2) {
3863
3896
  }
3864
3897
 
3865
3898
  // src/commands/prs/wontfix.ts
3866
- import { execSync as execSync22 } from "child_process";
3899
+ import { execSync as execSync23 } from "child_process";
3867
3900
  function validateReason(reason) {
3868
3901
  const lowerReason = reason.toLowerCase();
3869
3902
  if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
@@ -3880,7 +3913,7 @@ function validateShaReferences(reason) {
3880
3913
  const invalidShas = [];
3881
3914
  for (const sha of shas) {
3882
3915
  try {
3883
- execSync22(`git cat-file -t ${sha}`, { stdio: "pipe" });
3916
+ execSync23(`git cat-file -t ${sha}`, { stdio: "pipe" });
3884
3917
  } catch {
3885
3918
  invalidShas.push(sha);
3886
3919
  }
@@ -3984,7 +4017,7 @@ Refactor check failed:
3984
4017
  }
3985
4018
 
3986
4019
  // src/commands/refactor/check/getViolations/index.ts
3987
- import { execSync as execSync23 } from "child_process";
4020
+ import { execSync as execSync24 } from "child_process";
3988
4021
  import fs15 from "fs";
3989
4022
  import { minimatch as minimatch4 } from "minimatch";
3990
4023
 
@@ -4034,7 +4067,7 @@ function getGitFiles(options2) {
4034
4067
  }
4035
4068
  const files = /* @__PURE__ */ new Set();
4036
4069
  if (options2.staged || options2.modified) {
4037
- const staged = execSync23("git diff --cached --name-only", {
4070
+ const staged = execSync24("git diff --cached --name-only", {
4038
4071
  encoding: "utf-8"
4039
4072
  });
4040
4073
  for (const file of staged.trim().split("\n").filter(Boolean)) {
@@ -4042,7 +4075,7 @@ function getGitFiles(options2) {
4042
4075
  }
4043
4076
  }
4044
4077
  if (options2.unstaged || options2.modified) {
4045
- const unstaged = execSync23("git diff --name-only", { encoding: "utf-8" });
4078
+ const unstaged = execSync24("git diff --name-only", { encoding: "utf-8" });
4046
4079
  for (const file of unstaged.trim().split("\n").filter(Boolean)) {
4047
4080
  files.add(file);
4048
4081
  }
@@ -5320,6 +5353,7 @@ function registerVerify(program2) {
5320
5353
  verifyCommand.command("list").description("List configured verify commands").action(list);
5321
5354
  verifyCommand.command("init").description("Add verify scripts to a project").action(init2);
5322
5355
  verifyCommand.command("hardcoded-colors").description("Check for hardcoded hex colors in src/").action(hardcodedColors);
5356
+ verifyCommand.command("no-venv").description("Check that no venv folders exist in the repo").action(noVenv);
5323
5357
  }
5324
5358
 
5325
5359
  // src/commands/voice/devices.ts
@@ -5393,7 +5427,7 @@ import { mkdirSync as mkdirSync8 } from "fs";
5393
5427
  import { join as join26 } from "path";
5394
5428
 
5395
5429
  // src/commands/voice/checkLockFile.ts
5396
- import { execSync as execSync24 } from "child_process";
5430
+ import { execSync as execSync25 } from "child_process";
5397
5431
  import { existsSync as existsSync24, mkdirSync as mkdirSync7, readFileSync as readFileSync18, writeFileSync as writeFileSync18 } from "fs";
5398
5432
  import { join as join25 } from "path";
5399
5433
  function isProcessAlive(pid) {
@@ -5422,7 +5456,7 @@ function bootstrapVenv() {
5422
5456
  if (existsSync24(getVenvPython())) return;
5423
5457
  console.log("Setting up Python environment...");
5424
5458
  const pythonDir = getPythonDir();
5425
- execSync24(`uv sync --project "${pythonDir}" --no-install-project`, {
5459
+ execSync25(`uv sync --project "${pythonDir}" --no-install-project`, {
5426
5460
  stdio: "inherit",
5427
5461
  env: { ...process.env, UV_PROJECT_ENVIRONMENT: voicePaths.venv }
5428
5462
  });
@@ -5586,11 +5620,11 @@ import { randomBytes } from "crypto";
5586
5620
  import chalk51 from "chalk";
5587
5621
 
5588
5622
  // src/lib/openBrowser.ts
5589
- import { execSync as execSync25 } from "child_process";
5623
+ import { execSync as execSync26 } from "child_process";
5590
5624
  function tryExec(commands) {
5591
5625
  for (const cmd of commands) {
5592
5626
  try {
5593
- execSync25(cmd);
5627
+ execSync26(cmd);
5594
5628
  return true;
5595
5629
  } catch {
5596
5630
  }
@@ -6043,7 +6077,7 @@ function syncCommands(claudeDir, targetBase) {
6043
6077
  }
6044
6078
 
6045
6079
  // src/commands/update.ts
6046
- import { execSync as execSync26 } from "child_process";
6080
+ import { execSync as execSync27 } from "child_process";
6047
6081
  import * as path30 from "path";
6048
6082
  import { fileURLToPath as fileURLToPath6 } from "url";
6049
6083
  var __filename3 = fileURLToPath6(import.meta.url);
@@ -6053,7 +6087,7 @@ function getInstallDir() {
6053
6087
  }
6054
6088
  function isGitRepo(dir) {
6055
6089
  try {
6056
- execSync26("git rev-parse --is-inside-work-tree", {
6090
+ execSync27("git rev-parse --is-inside-work-tree", {
6057
6091
  cwd: dir,
6058
6092
  stdio: "pipe"
6059
6093
  });
@@ -6064,7 +6098,7 @@ function isGitRepo(dir) {
6064
6098
  }
6065
6099
  function isGlobalNpmInstall(dir) {
6066
6100
  try {
6067
- const globalPrefix = execSync26("npm prefix -g", { stdio: "pipe" }).toString().trim();
6101
+ const globalPrefix = execSync27("npm prefix -g", { stdio: "pipe" }).toString().trim();
6068
6102
  return path30.resolve(dir).toLowerCase().startsWith(path30.resolve(globalPrefix).toLowerCase());
6069
6103
  } catch {
6070
6104
  return false;
@@ -6075,16 +6109,16 @@ async function update() {
6075
6109
  console.log(`Assist is installed at: ${installDir}`);
6076
6110
  if (isGitRepo(installDir)) {
6077
6111
  console.log("Detected git repo installation, pulling latest...");
6078
- execSync26("git pull", { cwd: installDir, stdio: "inherit" });
6112
+ execSync27("git pull", { cwd: installDir, stdio: "inherit" });
6079
6113
  console.log("Building...");
6080
- execSync26("npm run build", { cwd: installDir, stdio: "inherit" });
6114
+ execSync27("npm run build", { cwd: installDir, stdio: "inherit" });
6081
6115
  console.log("Syncing commands...");
6082
- execSync26("assist sync", { stdio: "inherit" });
6116
+ execSync27("assist sync", { stdio: "inherit" });
6083
6117
  } else if (isGlobalNpmInstall(installDir)) {
6084
6118
  console.log("Detected global npm installation, updating...");
6085
- execSync26("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
6119
+ execSync27("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
6086
6120
  console.log("Syncing commands...");
6087
- execSync26("assist sync", { stdio: "inherit" });
6121
+ execSync27("assist sync", { stdio: "inherit" });
6088
6122
  } else {
6089
6123
  console.error(
6090
6124
  "Could not determine installation method. Expected a git repo or global npm install."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.84.0",
3
+ "version": "0.85.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {