@staff0rd/assist 0.36.1 → 0.37.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.
@@ -0,0 +1,3 @@
1
+ After any code change, run `/verify` to ensure all checks pass.
2
+
3
+ The tool is invoked using the `assist` command and is installed globally.
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import { Command } from "commander";
7
7
  // package.json
8
8
  var package_default = {
9
9
  name: "@staff0rd/assist",
10
- version: "0.36.1",
10
+ version: "0.37.0",
11
11
  type: "module",
12
12
  main: "dist/index.js",
13
13
  bin: {
@@ -621,8 +621,8 @@ Total: ${total} lines across ${files.length} files`)
621
621
  // src/commands/config/index.ts
622
622
  import chalk7 from "chalk";
623
623
  import { stringify as stringifyYaml2 } from "yaml";
624
- function getNestedValue(obj, path18) {
625
- const keys = path18.split(".");
624
+ function getNestedValue(obj, path19) {
625
+ const keys = path19.split(".");
626
626
  let current = obj;
627
627
  for (const key of keys) {
628
628
  if (current === null || current === void 0 || typeof current !== "object") {
@@ -632,8 +632,8 @@ function getNestedValue(obj, path18) {
632
632
  }
633
633
  return current;
634
634
  }
635
- function setNestedValue(obj, path18, value) {
636
- const keys = path18.split(".");
635
+ function setNestedValue(obj, path19, value) {
636
+ const keys = path19.split(".");
637
637
  const result = { ...obj };
638
638
  let current = result;
639
639
  for (let i = 0; i < keys.length - 1; i++) {
@@ -660,8 +660,8 @@ function configSet(key, value) {
660
660
  const result = assistConfigSchema.safeParse(updated);
661
661
  if (!result.success) {
662
662
  for (const issue of result.error.issues) {
663
- const path18 = issue.path.length > 0 ? issue.path.join(".") : key;
664
- console.error(chalk7.red(`${path18}: ${issue.message}`));
663
+ const path19 = issue.path.length > 0 ? issue.path.join(".") : key;
664
+ console.error(chalk7.red(`${path19}: ${issue.message}`));
665
665
  }
666
666
  process.exit(1);
667
667
  }
@@ -2949,31 +2949,61 @@ async function statusLine() {
2949
2949
  }
2950
2950
 
2951
2951
  // src/commands/sync.ts
2952
- import * as fs17 from "fs";
2952
+ import * as fs18 from "fs";
2953
2953
  import * as os from "os";
2954
- import * as path16 from "path";
2954
+ import * as path17 from "path";
2955
2955
  import { fileURLToPath as fileURLToPath3 } from "url";
2956
2956
 
2957
- // src/commands/sync/syncSettings.ts
2957
+ // src/commands/sync/syncClaudeMd.ts
2958
2958
  import * as fs16 from "fs";
2959
2959
  import * as path15 from "path";
2960
2960
  import chalk35 from "chalk";
2961
- async function syncSettings(claudeDir, targetBase) {
2962
- const source = path15.join(claudeDir, "settings.json");
2963
- const target = path15.join(targetBase, "settings.json");
2961
+ async function syncClaudeMd(claudeDir, targetBase) {
2962
+ const source = path15.join(claudeDir, "CLAUDE.md");
2963
+ const target = path15.join(targetBase, "CLAUDE.md");
2964
2964
  const sourceContent = fs16.readFileSync(source, "utf-8");
2965
- const normalizedSource = JSON.stringify(JSON.parse(sourceContent), null, 2);
2966
2965
  if (fs16.existsSync(target)) {
2967
2966
  const targetContent = fs16.readFileSync(target, "utf-8");
2967
+ if (sourceContent !== targetContent) {
2968
+ console.log(
2969
+ chalk35.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
2970
+ );
2971
+ console.log();
2972
+ printDiff(targetContent, sourceContent);
2973
+ const confirm = await promptConfirm(
2974
+ chalk35.red("Overwrite existing CLAUDE.md?"),
2975
+ false
2976
+ );
2977
+ if (!confirm) {
2978
+ console.log("Skipped CLAUDE.md");
2979
+ return;
2980
+ }
2981
+ }
2982
+ }
2983
+ fs16.copyFileSync(source, target);
2984
+ console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
2985
+ }
2986
+
2987
+ // src/commands/sync/syncSettings.ts
2988
+ import * as fs17 from "fs";
2989
+ import * as path16 from "path";
2990
+ import chalk36 from "chalk";
2991
+ async function syncSettings(claudeDir, targetBase) {
2992
+ const source = path16.join(claudeDir, "settings.json");
2993
+ const target = path16.join(targetBase, "settings.json");
2994
+ const sourceContent = fs17.readFileSync(source, "utf-8");
2995
+ const normalizedSource = JSON.stringify(JSON.parse(sourceContent), null, 2);
2996
+ if (fs17.existsSync(target)) {
2997
+ const targetContent = fs17.readFileSync(target, "utf-8");
2968
2998
  const normalizedTarget = JSON.stringify(JSON.parse(targetContent), null, 2);
2969
2999
  if (normalizedSource !== normalizedTarget) {
2970
3000
  console.log(
2971
- chalk35.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
3001
+ chalk36.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
2972
3002
  );
2973
3003
  console.log();
2974
3004
  printDiff(targetContent, sourceContent);
2975
3005
  const confirm = await promptConfirm(
2976
- chalk35.red("Overwrite existing settings.json?"),
3006
+ chalk36.red("Overwrite existing settings.json?"),
2977
3007
  false
2978
3008
  );
2979
3009
  if (!confirm) {
@@ -2982,34 +3012,35 @@ async function syncSettings(claudeDir, targetBase) {
2982
3012
  }
2983
3013
  }
2984
3014
  }
2985
- fs16.copyFileSync(source, target);
3015
+ fs17.copyFileSync(source, target);
2986
3016
  console.log("Copied settings.json to ~/.claude/settings.json");
2987
3017
  }
2988
3018
 
2989
3019
  // src/commands/sync.ts
2990
3020
  var __filename2 = fileURLToPath3(import.meta.url);
2991
- var __dirname4 = path16.dirname(__filename2);
3021
+ var __dirname4 = path17.dirname(__filename2);
2992
3022
  async function sync() {
2993
- const claudeDir = path16.join(__dirname4, "..", "claude");
2994
- const targetBase = path16.join(os.homedir(), ".claude");
3023
+ const claudeDir = path17.join(__dirname4, "..", "claude");
3024
+ const targetBase = path17.join(os.homedir(), ".claude");
2995
3025
  syncCommands(claudeDir, targetBase);
2996
3026
  await syncSettings(claudeDir, targetBase);
3027
+ await syncClaudeMd(claudeDir, targetBase);
2997
3028
  }
2998
3029
  function syncCommands(claudeDir, targetBase) {
2999
- const sourceDir = path16.join(claudeDir, "commands");
3000
- const targetDir = path16.join(targetBase, "commands");
3001
- fs17.mkdirSync(targetDir, { recursive: true });
3002
- const files = fs17.readdirSync(sourceDir);
3030
+ const sourceDir = path17.join(claudeDir, "commands");
3031
+ const targetDir = path17.join(targetBase, "commands");
3032
+ fs18.mkdirSync(targetDir, { recursive: true });
3033
+ const files = fs18.readdirSync(sourceDir);
3003
3034
  for (const file of files) {
3004
- fs17.copyFileSync(path16.join(sourceDir, file), path16.join(targetDir, file));
3035
+ fs18.copyFileSync(path17.join(sourceDir, file), path17.join(targetDir, file));
3005
3036
  console.log(`Copied ${file} to ${targetDir}`);
3006
3037
  }
3007
3038
  console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
3008
3039
  }
3009
3040
 
3010
3041
  // src/commands/transcript/shared.ts
3011
- import { existsSync as existsSync14, readdirSync as readdirSync3, statSync } from "fs";
3012
- import { basename as basename3, join as join13, relative } from "path";
3042
+ import { existsSync as existsSync15, readdirSync as readdirSync3, statSync } from "fs";
3043
+ import { basename as basename3, join as join14, relative } from "path";
3013
3044
  import * as readline2 from "readline";
3014
3045
  var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
3015
3046
  function getDatePrefix(daysOffset = 0) {
@@ -3024,13 +3055,13 @@ function isValidDatePrefix(filename) {
3024
3055
  return DATE_PREFIX_REGEX.test(filename);
3025
3056
  }
3026
3057
  function findFilesRecursive(dir, baseDir, extension, createEntry) {
3027
- if (!existsSync14(dir)) {
3058
+ if (!existsSync15(dir)) {
3028
3059
  return [];
3029
3060
  }
3030
3061
  const results = [];
3031
3062
  const entries = readdirSync3(dir);
3032
3063
  for (const entry of entries) {
3033
- const fullPath = join13(dir, entry);
3064
+ const fullPath = join14(dir, entry);
3034
3065
  const stat = statSync(fullPath);
3035
3066
  if (stat.isDirectory()) {
3036
3067
  results.push(
@@ -3120,8 +3151,8 @@ async function configure() {
3120
3151
  }
3121
3152
 
3122
3153
  // src/commands/transcript/format.ts
3123
- import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync11 } from "fs";
3124
- import { basename as basename4, dirname as dirname11, join as join15 } from "path";
3154
+ import { existsSync as existsSync16, mkdirSync as mkdirSync5, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "fs";
3155
+ import { basename as basename4, dirname as dirname11, join as join16 } from "path";
3125
3156
 
3126
3157
  // src/commands/transcript/parseVtt.ts
3127
3158
  function parseTimestamp(ts2) {
@@ -3283,7 +3314,7 @@ function formatChatLog(messages) {
3283
3314
 
3284
3315
  // src/commands/transcript/promptForDateFix.ts
3285
3316
  import { renameSync } from "fs";
3286
- import { join as join14 } from "path";
3317
+ import { join as join15 } from "path";
3287
3318
  async function promptForDateFix(vttFile, vttDir) {
3288
3319
  const rl = createReadlineInterface();
3289
3320
  console.log(
@@ -3324,8 +3355,8 @@ Error: File "${vttFile}" does not start with YYYY-MM-DD format.`
3324
3355
  rl.close();
3325
3356
  if (newPrefix) {
3326
3357
  const newFilename = `${newPrefix}.${vttFile}`;
3327
- const oldPath = join14(vttDir, vttFile);
3328
- const newPath = join14(vttDir, newFilename);
3358
+ const oldPath = join15(vttDir, vttFile);
3359
+ const newPath = join15(vttDir, newFilename);
3329
3360
  renameSync(oldPath, newPath);
3330
3361
  console.log(`Renamed to: ${newFilename}`);
3331
3362
  return newFilename;
@@ -3340,7 +3371,7 @@ Error: File "${vttFile}" does not start with YYYY-MM-DD format.`
3340
3371
  // src/commands/transcript/format.ts
3341
3372
  function processFile(inputPath, outputPath) {
3342
3373
  console.log(`Reading: ${inputPath}`);
3343
- const content = readFileSync13(inputPath, "utf-8");
3374
+ const content = readFileSync14(inputPath, "utf-8");
3344
3375
  const cues = parseVtt(content);
3345
3376
  console.log(`Parsed ${cues.length} cues`);
3346
3377
  const dedupedCues = deduplicateCues(cues);
@@ -3357,11 +3388,11 @@ function processFile(inputPath, outputPath) {
3357
3388
  }
3358
3389
  async function format() {
3359
3390
  const { vttDir, transcriptsDir } = getTranscriptConfig();
3360
- if (!existsSync15(vttDir)) {
3391
+ if (!existsSync16(vttDir)) {
3361
3392
  console.error(`VTT directory not found: ${vttDir}`);
3362
3393
  process.exit(1);
3363
3394
  }
3364
- if (!existsSync15(transcriptsDir)) {
3395
+ if (!existsSync16(transcriptsDir)) {
3365
3396
  mkdirSync5(transcriptsDir, { recursive: true });
3366
3397
  console.log(`Created output directory: ${transcriptsDir}`);
3367
3398
  }
@@ -3378,12 +3409,12 @@ async function format() {
3378
3409
  const vttFileDir = dirname11(vttFile.absolutePath);
3379
3410
  const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
3380
3411
  if (newFilename) {
3381
- const newRelativePath = join15(
3412
+ const newRelativePath = join16(
3382
3413
  dirname11(vttFile.relativePath),
3383
3414
  newFilename
3384
3415
  );
3385
3416
  vttFiles[i] = {
3386
- absolutePath: join15(vttFileDir, newFilename),
3417
+ absolutePath: join16(vttFileDir, newFilename),
3387
3418
  relativePath: newRelativePath,
3388
3419
  filename: newFilename
3389
3420
  };
@@ -3400,14 +3431,14 @@ async function format() {
3400
3431
  baseName = baseName.replace(/\s*Transcription\s*/g, " ").trim();
3401
3432
  const mdFile = `${baseName}.md`;
3402
3433
  const relativeDir = dirname11(vttFile.relativePath);
3403
- const outputDir = relativeDir === "." ? transcriptsDir : join15(transcriptsDir, relativeDir);
3404
- const outputPath = join15(outputDir, mdFile);
3405
- if (!existsSync15(outputDir)) {
3434
+ const outputDir = relativeDir === "." ? transcriptsDir : join16(transcriptsDir, relativeDir);
3435
+ const outputPath = join16(outputDir, mdFile);
3436
+ if (!existsSync16(outputDir)) {
3406
3437
  mkdirSync5(outputDir, { recursive: true });
3407
3438
  console.log(`Created output directory: ${outputDir}`);
3408
3439
  }
3409
- if (existsSync15(outputPath)) {
3410
- console.log(`Skipping (already exists): ${join15(relativeDir, mdFile)}`);
3440
+ if (existsSync16(outputPath)) {
3441
+ console.log(`Skipping (already exists): ${join16(relativeDir, mdFile)}`);
3411
3442
  skipped++;
3412
3443
  continue;
3413
3444
  }
@@ -3420,18 +3451,18 @@ Summary: ${processed} processed, ${skipped} skipped`);
3420
3451
 
3421
3452
  // src/commands/transcript/summarise.ts
3422
3453
  import {
3423
- existsSync as existsSync16,
3454
+ existsSync as existsSync17,
3424
3455
  mkdirSync as mkdirSync6,
3425
- readFileSync as readFileSync14,
3456
+ readFileSync as readFileSync15,
3426
3457
  renameSync as renameSync2,
3427
3458
  rmSync
3428
3459
  } from "fs";
3429
- import { basename as basename5, dirname as dirname12, join as join16, relative as relative2 } from "path";
3430
- import chalk36 from "chalk";
3431
- var STAGING_DIR = join16(process.cwd(), ".assist", "transcript");
3460
+ import { basename as basename5, dirname as dirname12, join as join17, relative as relative2 } from "path";
3461
+ import chalk37 from "chalk";
3462
+ var STAGING_DIR = join17(process.cwd(), ".assist", "transcript");
3432
3463
  var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
3433
3464
  function processStagedFile() {
3434
- if (!existsSync16(STAGING_DIR)) {
3465
+ if (!existsSync17(STAGING_DIR)) {
3435
3466
  return false;
3436
3467
  }
3437
3468
  const stagedFiles = findMdFilesRecursive(STAGING_DIR);
@@ -3440,12 +3471,12 @@ function processStagedFile() {
3440
3471
  }
3441
3472
  const { transcriptsDir, summaryDir } = getTranscriptConfig();
3442
3473
  const stagedFile = stagedFiles[0];
3443
- const content = readFileSync14(stagedFile.absolutePath, "utf-8");
3474
+ const content = readFileSync15(stagedFile.absolutePath, "utf-8");
3444
3475
  const firstLine = content.split("\n")[0];
3445
3476
  const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
3446
3477
  if (!match) {
3447
3478
  console.error(
3448
- chalk36.red(
3479
+ chalk37.red(
3449
3480
  `Staged file ${stagedFile.filename} missing [Full Transcript](<path>) link on first line.`
3450
3481
  )
3451
3482
  );
@@ -3454,7 +3485,7 @@ function processStagedFile() {
3454
3485
  const contentAfterLink = content.slice(firstLine.length).trim();
3455
3486
  if (!contentAfterLink) {
3456
3487
  console.error(
3457
- chalk36.red(
3488
+ chalk37.red(
3458
3489
  `Staged file ${stagedFile.filename} has no summary content after the transcript link.`
3459
3490
  )
3460
3491
  );
@@ -3467,16 +3498,16 @@ function processStagedFile() {
3467
3498
  );
3468
3499
  if (!matchingTranscript) {
3469
3500
  console.error(
3470
- chalk36.red(
3501
+ chalk37.red(
3471
3502
  `No transcript found matching staged file: ${stagedFile.filename}`
3472
3503
  )
3473
3504
  );
3474
3505
  process.exit(1);
3475
3506
  }
3476
3507
  const relativePath = matchingTranscript.relativePath;
3477
- const destPath = join16(summaryDir, relativePath);
3508
+ const destPath = join17(summaryDir, relativePath);
3478
3509
  const destDir = dirname12(destPath);
3479
- if (!existsSync16(destDir)) {
3510
+ if (!existsSync17(destDir)) {
3480
3511
  mkdirSync6(destDir, { recursive: true });
3481
3512
  }
3482
3513
  renameSync2(stagedFile.absolutePath, destPath);
@@ -3489,7 +3520,7 @@ function processStagedFile() {
3489
3520
  function summarise() {
3490
3521
  processStagedFile();
3491
3522
  const { transcriptsDir, summaryDir } = getTranscriptConfig();
3492
- if (!existsSync16(transcriptsDir)) {
3523
+ if (!existsSync17(transcriptsDir)) {
3493
3524
  console.log("No transcripts directory found.");
3494
3525
  return;
3495
3526
  }
@@ -3503,14 +3534,14 @@ function summarise() {
3503
3534
  summaryFiles.map((f) => {
3504
3535
  const relDir = dirname12(f.relativePath);
3505
3536
  const baseName = basename5(f.filename, ".md");
3506
- return relDir === "." ? baseName : join16(relDir, baseName);
3537
+ return relDir === "." ? baseName : join17(relDir, baseName);
3507
3538
  })
3508
3539
  );
3509
3540
  const missing = [];
3510
3541
  for (const transcript of transcriptFiles) {
3511
3542
  const transcriptBaseName = getTranscriptBaseName(transcript.filename);
3512
3543
  const relDir = dirname12(transcript.relativePath);
3513
- const fullKey = relDir === "." ? transcriptBaseName : join16(relDir, transcriptBaseName);
3544
+ const fullKey = relDir === "." ? transcriptBaseName : join17(relDir, transcriptBaseName);
3514
3545
  if (!summaryRelativePaths.has(fullKey)) {
3515
3546
  missing.push(transcript);
3516
3547
  }
@@ -3521,8 +3552,8 @@ function summarise() {
3521
3552
  }
3522
3553
  const next2 = missing[0];
3523
3554
  const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
3524
- const outputPath = join16(STAGING_DIR, outputFilename);
3525
- const summaryFileDir = join16(summaryDir, dirname12(next2.relativePath));
3555
+ const outputPath = join17(STAGING_DIR, outputFilename);
3556
+ const summaryFileDir = join17(summaryDir, dirname12(next2.relativePath));
3526
3557
  const relativeTranscriptPath = encodeURI(
3527
3558
  relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
3528
3559
  );
@@ -3573,7 +3604,7 @@ Total: ${lines.length} hardcoded color(s)`);
3573
3604
 
3574
3605
  // src/commands/verify/run.ts
3575
3606
  import { spawn as spawn4 } from "child_process";
3576
- import * as path17 from "path";
3607
+ import * as path18 from "path";
3577
3608
  function formatDuration(ms) {
3578
3609
  if (ms < 1e3) {
3579
3610
  return `${ms}ms`;
@@ -3603,7 +3634,7 @@ async function run2(options = {}) {
3603
3634
  return;
3604
3635
  }
3605
3636
  const { packageJsonPath, verifyScripts } = result;
3606
- const packageDir = path17.dirname(packageJsonPath);
3637
+ const packageDir = path18.dirname(packageJsonPath);
3607
3638
  console.log(`Running ${verifyScripts.length} verify script(s) in parallel:`);
3608
3639
  for (const script of verifyScripts) {
3609
3640
  console.log(` - ${script}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.36.1",
3
+ "version": "0.37.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {