@kudusov.takhir/ba-toolkit 1.3.2 → 1.4.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/CHANGELOG.md +23 -1
- package/bin/ba-toolkit.js +351 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,27 @@ Versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
## [1.4.0] — 2026-04-08
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **`ba-toolkit uninstall --for <agent>`** — remove BA Toolkit skills from an agent's directory. Symmetric to `install`: same `--for`, `--global`, `--project`, `--dry-run` flag set, same project-vs-global default. Counts files in the destination, asks `Remove {dest}? (y/N)` (defaults to N), and prints `Removed N files` after the rm completes. The pre-removal safety guard refuses to proceed unless `path.basename(destDir) === 'ba-toolkit'` — this is the only place in the CLI that calls `fs.rmSync({recursive: true})`, so it gets the strictest validation against future bugs that could turn it into `rm -rf $HOME`.
|
|
19
|
+
- **`ba-toolkit upgrade --for <agent>`** (aliased as `update`) — refresh skills after a toolkit version bump. Reads the new version sentinel (see below), compares to `PKG.version`, and either prints `Already up to date` or wipes the destination wholesale and re-runs install with `force: true` (skipping the overwrite prompt). The wipe-and-reinstall approach guarantees that files removed from the toolkit between versions don't linger as ghost files in the destination — fixes the same class of bug that motivated `cmdUninstall`'s safety check. Pre-1.4 installs with no sentinel are treated as out-of-date and get a clean reinstall on first upgrade.
|
|
20
|
+
- **`ba-toolkit status`** — pure read-only inspection: scans every (agent × scope) combination — 5 agents × project/global where supported, 8 real locations in total — and reports which versions of BA Toolkit are installed where. Output is grouped per installation, multi-line for readability, with colored version labels (`green: current` / `yellow: outdated` / `gray: pre-1.4 install with no sentinel`) and a summary footer pointing at `upgrade` for stale installs. Drives the natural follow-up to the version sentinel: now there's something to read it back with.
|
|
21
|
+
- **Version sentinel `.ba-toolkit-version`** — `runInstall` now writes a hidden JSON marker file (`{"version": "1.4.0", "installedAt": "..."}`) into the install destination after a successful copy. The file has no `.md`/`.mdc` extension, so all five supported agents' skill loaders ignore it. Lets `upgrade` and `status` tell which package version is currently installed without diffing every file.
|
|
22
|
+
- **`runInstall({..., force: true})` option** — skips the existing-destination overwrite prompt. Used by `cmdUpgrade` because it has already wiped the destination (or is in dry-run) and the prompt would just be noise. Not exposed as a CLI flag — `force` is an internal API surface only.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **Five Tier 1 CLI fixes were already shipped in 1.3.2**, but they're worth restating in context here because 1.4.0 builds directly on the same `bin/ba-toolkit.js` improvements: `cmdInit` now honours `runInstall`'s return value (no false success message after a declined overwrite), `parseArgs` accepts `--key=value` form, the readline lifecycle and SIGINT handling are unified through a single shared interface with `INPUT_CLOSED` rejection, the slug-derivation path prints a clear error when the input has no ASCII letters, and `AGENTS.md` now lists all 21 skills (the previous template was missing the 8 cross-cutting utilities added in v1.1 and v1.2). See the 1.3.2 entry below for the per-fix detail.
|
|
27
|
+
|
|
28
|
+
### Internal
|
|
29
|
+
|
|
30
|
+
- **`resolveAgentDestination(...)` helper** — extracted scope-resolution logic from `runInstall`'s inline checks. `cmdUninstall` and `cmdUpgrade` reuse it. `runInstall` itself could be refactored to call the helper too in a follow-up — kept inline for now to keep this release's diff focused on the user-facing features.
|
|
31
|
+
- **Documentation:** `CLAUDE.md` added at the repo root, with project conventions, the release flow (including the `.claude/settings.local.json` stash dance), the npm publish CI gotchas (curl tarball bypass for the broken bundled npm, `_authToken` strip for OIDC), and the do-not-touch list. Future Claude Code sessions get the institutional context without reading the full git log.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
14
35
|
## [1.3.2] — 2026-04-08
|
|
15
36
|
|
|
16
37
|
### Fixed
|
|
@@ -246,7 +267,8 @@ CI scripts that relied on the old behaviour (`init` creates files only, `install
|
|
|
246
267
|
|
|
247
268
|
---
|
|
248
269
|
|
|
249
|
-
[Unreleased]: https://github.com/TakhirKudusov/ba-toolkit/compare/v1.
|
|
270
|
+
[Unreleased]: https://github.com/TakhirKudusov/ba-toolkit/compare/v1.4.0...HEAD
|
|
271
|
+
[1.4.0]: https://github.com/TakhirKudusov/ba-toolkit/compare/v1.3.2...v1.4.0
|
|
250
272
|
[1.3.2]: https://github.com/TakhirKudusov/ba-toolkit/compare/v1.3.1...v1.3.2
|
|
251
273
|
[1.3.1]: https://github.com/TakhirKudusov/ba-toolkit/compare/v1.3.0...v1.3.1
|
|
252
274
|
[1.3.0]: https://github.com/TakhirKudusov/ba-toolkit/compare/v1.2.5...v1.3.0
|
package/bin/ba-toolkit.js
CHANGED
|
@@ -497,10 +497,39 @@ async function cmdInit(args) {
|
|
|
497
497
|
log('');
|
|
498
498
|
}
|
|
499
499
|
|
|
500
|
-
//
|
|
501
|
-
//
|
|
502
|
-
//
|
|
503
|
-
|
|
500
|
+
// Marker file written into the install destination after a successful copy.
|
|
501
|
+
// Lets `upgrade` and `status` (future command) tell which package version
|
|
502
|
+
// is currently installed without diffing every file. Hidden file with no
|
|
503
|
+
// `.md` / `.mdc` extension so the agent's skill loader ignores it.
|
|
504
|
+
const SENTINEL_FILENAME = '.ba-toolkit-version';
|
|
505
|
+
|
|
506
|
+
function readSentinel(destDir) {
|
|
507
|
+
const p = path.join(destDir, SENTINEL_FILENAME);
|
|
508
|
+
if (!fs.existsSync(p)) return null;
|
|
509
|
+
try {
|
|
510
|
+
return JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
511
|
+
} catch {
|
|
512
|
+
return null;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function writeSentinel(destDir) {
|
|
517
|
+
const payload = {
|
|
518
|
+
version: PKG.version,
|
|
519
|
+
installedAt: new Date().toISOString(),
|
|
520
|
+
};
|
|
521
|
+
fs.writeFileSync(
|
|
522
|
+
path.join(destDir, SENTINEL_FILENAME),
|
|
523
|
+
JSON.stringify(payload, null, 2) + '\n',
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Core install logic. Shared between `cmdInstall` (standalone), `cmdInit`
|
|
528
|
+
// (full setup), and `cmdUpgrade`. Returns true on success, false if the
|
|
529
|
+
// user declined to overwrite an existing destination. Pass `force: true`
|
|
530
|
+
// to skip the overwrite prompt — `cmdUpgrade` uses this because it has
|
|
531
|
+
// already wiped the destination and explicitly knows the overwrite is ok.
|
|
532
|
+
async function runInstall({ agentId, isGlobal, isProject, dryRun, showHeader = true, force = false }) {
|
|
504
533
|
const agent = AGENTS[agentId];
|
|
505
534
|
if (!agent) {
|
|
506
535
|
logError(`Unknown agent: ${agentId}`);
|
|
@@ -538,7 +567,7 @@ async function runInstall({ agentId, isGlobal, isProject, dryRun, showHeader = t
|
|
|
538
567
|
log(` format: ${agent.format === 'mdc' ? '.mdc (converted from SKILL.md)' : 'SKILL.md (native)'}`);
|
|
539
568
|
if (dryRun) log(' ' + yellow('mode: dry-run (no files will be written)'));
|
|
540
569
|
|
|
541
|
-
if (fs.existsSync(destDir) && !dryRun) {
|
|
570
|
+
if (fs.existsSync(destDir) && !dryRun && !force) {
|
|
542
571
|
const answer = await prompt(` ${destDir} already exists. Overwrite? (y/N): `);
|
|
543
572
|
if (answer.toLowerCase() !== 'y') {
|
|
544
573
|
log(' cancelled.');
|
|
@@ -555,6 +584,10 @@ async function runInstall({ agentId, isGlobal, isProject, dryRun, showHeader = t
|
|
|
555
584
|
process.exit(1);
|
|
556
585
|
}
|
|
557
586
|
|
|
587
|
+
if (!dryRun) {
|
|
588
|
+
writeSentinel(destDir);
|
|
589
|
+
}
|
|
590
|
+
|
|
558
591
|
log(' ' + green(`${dryRun ? 'would copy' : 'copied'} ${copied.length} files.`));
|
|
559
592
|
if (!dryRun && agent.format === 'mdc') {
|
|
560
593
|
log(' ' + gray('SKILL.md files converted to .mdc rule format.'));
|
|
@@ -584,6 +617,271 @@ async function cmdInstall(args) {
|
|
|
584
617
|
log('');
|
|
585
618
|
}
|
|
586
619
|
|
|
620
|
+
// Resolve agent + scope (project vs global) into the target directory
|
|
621
|
+
// path. Shared validation for cmdUninstall — `runInstall` does its own
|
|
622
|
+
// version of this inline; both could be unified later.
|
|
623
|
+
function resolveAgentDestination({ agentId, isGlobal, isProject }) {
|
|
624
|
+
const agent = AGENTS[agentId];
|
|
625
|
+
if (!agent) {
|
|
626
|
+
logError(`Unknown agent: ${agentId}`);
|
|
627
|
+
log('Supported: ' + Object.keys(AGENTS).join(', '));
|
|
628
|
+
process.exit(1);
|
|
629
|
+
}
|
|
630
|
+
let effectiveGlobal = !!isGlobal;
|
|
631
|
+
if (!isGlobal && !isProject) {
|
|
632
|
+
effectiveGlobal = !agent.projectPath;
|
|
633
|
+
}
|
|
634
|
+
if (effectiveGlobal && !agent.globalPath) {
|
|
635
|
+
logError(`${agent.name} does not support --global install.`);
|
|
636
|
+
process.exit(1);
|
|
637
|
+
}
|
|
638
|
+
if (!effectiveGlobal && !agent.projectPath) {
|
|
639
|
+
logError(`${agent.name} does not support project-level install. Use --global.`);
|
|
640
|
+
process.exit(1);
|
|
641
|
+
}
|
|
642
|
+
const destDir = effectiveGlobal ? agent.globalPath : path.resolve(process.cwd(), agent.projectPath);
|
|
643
|
+
return { agent, destDir, effectiveGlobal };
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
function cmdStatus() {
|
|
647
|
+
log('');
|
|
648
|
+
log(' ' + cyan('BA Toolkit — Installation Status'));
|
|
649
|
+
log(' ' + cyan('================================'));
|
|
650
|
+
log('');
|
|
651
|
+
log(` package version: ${PKG.version}`);
|
|
652
|
+
log(` scanning from: ${process.cwd()}`);
|
|
653
|
+
log('');
|
|
654
|
+
|
|
655
|
+
// Walk every (agent × scope) combination and collect the ones whose
|
|
656
|
+
// destination directory actually exists. Project-scope paths resolve
|
|
657
|
+
// against the current working directory; global paths are absolute.
|
|
658
|
+
const rows = [];
|
|
659
|
+
for (const [agentId, agent] of Object.entries(AGENTS)) {
|
|
660
|
+
if (agent.projectPath) {
|
|
661
|
+
const projectDir = path.resolve(process.cwd(), agent.projectPath);
|
|
662
|
+
if (fs.existsSync(projectDir)) {
|
|
663
|
+
const sentinel = readSentinel(projectDir);
|
|
664
|
+
rows.push({
|
|
665
|
+
agentName: agent.name,
|
|
666
|
+
agentId,
|
|
667
|
+
scope: 'project',
|
|
668
|
+
path: projectDir,
|
|
669
|
+
version: sentinel ? sentinel.version : null,
|
|
670
|
+
installedAt: sentinel ? sentinel.installedAt : null,
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
if (agent.globalPath) {
|
|
675
|
+
if (fs.existsSync(agent.globalPath)) {
|
|
676
|
+
const sentinel = readSentinel(agent.globalPath);
|
|
677
|
+
rows.push({
|
|
678
|
+
agentName: agent.name,
|
|
679
|
+
agentId,
|
|
680
|
+
scope: 'global',
|
|
681
|
+
path: agent.globalPath,
|
|
682
|
+
version: sentinel ? sentinel.version : null,
|
|
683
|
+
installedAt: sentinel ? sentinel.installedAt : null,
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
if (rows.length === 0) {
|
|
690
|
+
log(' ' + gray('No BA Toolkit installations found in any known location.'));
|
|
691
|
+
log(' ' + gray("Run 'ba-toolkit install --for <agent>' to install one."));
|
|
692
|
+
log('');
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
log(` Found ${bold(rows.length)} installation${rows.length === 1 ? '' : 's'}:`);
|
|
697
|
+
log('');
|
|
698
|
+
|
|
699
|
+
for (const row of rows) {
|
|
700
|
+
let versionLabel;
|
|
701
|
+
if (!row.version) {
|
|
702
|
+
versionLabel = gray('(unknown — pre-1.4 install with no sentinel)');
|
|
703
|
+
} else if (row.version === PKG.version) {
|
|
704
|
+
versionLabel = green(row.version + ' (current)');
|
|
705
|
+
} else {
|
|
706
|
+
versionLabel = yellow(row.version + ' (outdated)');
|
|
707
|
+
}
|
|
708
|
+
log(` ${bold(row.agentName)} ${gray('(' + row.agentId + ', ' + row.scope + ')')}`);
|
|
709
|
+
log(` path: ${row.path}`);
|
|
710
|
+
log(` version: ${versionLabel}`);
|
|
711
|
+
if (row.installedAt) {
|
|
712
|
+
log(` installed: ${gray(row.installedAt)}`);
|
|
713
|
+
}
|
|
714
|
+
log('');
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
const stale = rows.filter((r) => !r.version || r.version !== PKG.version);
|
|
718
|
+
if (stale.length > 0) {
|
|
719
|
+
log(' ' + yellow(`${stale.length} installation${stale.length === 1 ? '' : 's'} not at version ${PKG.version}.`));
|
|
720
|
+
log(' ' + gray("Run 'ba-toolkit upgrade --for <agent>' to refresh."));
|
|
721
|
+
log('');
|
|
722
|
+
} else {
|
|
723
|
+
log(' ' + green('All installations are up to date.'));
|
|
724
|
+
log('');
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
async function cmdUpgrade(args) {
|
|
729
|
+
const agentId = args.flags.for;
|
|
730
|
+
if (!agentId || agentId === true) {
|
|
731
|
+
logError('--for <agent> is required.');
|
|
732
|
+
log('Supported agents: ' + Object.keys(AGENTS).join(', '));
|
|
733
|
+
process.exit(1);
|
|
734
|
+
}
|
|
735
|
+
const { agent, destDir, effectiveGlobal } = resolveAgentDestination({
|
|
736
|
+
agentId,
|
|
737
|
+
isGlobal: !!args.flags.global,
|
|
738
|
+
isProject: !!args.flags.project,
|
|
739
|
+
});
|
|
740
|
+
const dryRun = !!args.flags['dry-run'];
|
|
741
|
+
|
|
742
|
+
log('');
|
|
743
|
+
log(' ' + cyan(`BA Toolkit — Upgrade for ${agent.name}`));
|
|
744
|
+
log(' ' + cyan('================================'));
|
|
745
|
+
log('');
|
|
746
|
+
log(` destination: ${destDir}`);
|
|
747
|
+
log(` scope: ${effectiveGlobal ? 'global (user-wide)' : 'project-level'}`);
|
|
748
|
+
|
|
749
|
+
if (!fs.existsSync(destDir)) {
|
|
750
|
+
log('');
|
|
751
|
+
log(' ' + gray(`No installation found at ${destDir}.`));
|
|
752
|
+
log(' ' + gray(`Run \`ba-toolkit install --for ${agentId}\` first.`));
|
|
753
|
+
log('');
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
const sentinel = readSentinel(destDir);
|
|
758
|
+
const currentVersion = PKG.version;
|
|
759
|
+
const installedVersion = sentinel ? sentinel.version : null;
|
|
760
|
+
|
|
761
|
+
if (installedVersion === currentVersion) {
|
|
762
|
+
log(` installed: ${installedVersion} (current)`);
|
|
763
|
+
log(` package: ${currentVersion}`);
|
|
764
|
+
log('');
|
|
765
|
+
log(' ' + green('Already up to date.'));
|
|
766
|
+
log(' ' + gray(`To force a clean reinstall, run \`ba-toolkit install --for ${agentId}\`.`));
|
|
767
|
+
log('');
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
log(` installed: ${installedVersion || gray('(unknown — pre-1.4 install with no sentinel)')}`);
|
|
772
|
+
log(` package: ${currentVersion}`);
|
|
773
|
+
if (dryRun) log(' ' + yellow('mode: dry-run (no files will be written)'));
|
|
774
|
+
log('');
|
|
775
|
+
|
|
776
|
+
// Safety: same guard as cmdUninstall — never rmSync anything that
|
|
777
|
+
// doesn't look like a ba-toolkit folder.
|
|
778
|
+
if (path.basename(destDir) !== 'ba-toolkit') {
|
|
779
|
+
logError(`Refusing to upgrade suspicious destination (not a ba-toolkit folder): ${destDir}`);
|
|
780
|
+
process.exit(1);
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// Count files in the existing install for the dry-run preview.
|
|
784
|
+
if (dryRun) {
|
|
785
|
+
let existingCount = 0;
|
|
786
|
+
(function walk(d) {
|
|
787
|
+
for (const entry of fs.readdirSync(d, { withFileTypes: true })) {
|
|
788
|
+
const p = path.join(d, entry.name);
|
|
789
|
+
if (entry.isDirectory()) walk(p);
|
|
790
|
+
else existingCount++;
|
|
791
|
+
}
|
|
792
|
+
})(destDir);
|
|
793
|
+
log(' ' + yellow(`would remove ${existingCount} existing files`));
|
|
794
|
+
} else {
|
|
795
|
+
log(' ' + green('Removing previous install...'));
|
|
796
|
+
fs.rmSync(destDir, { recursive: true, force: true });
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
const ok = await runInstall({
|
|
800
|
+
agentId,
|
|
801
|
+
isGlobal: effectiveGlobal,
|
|
802
|
+
isProject: !effectiveGlobal,
|
|
803
|
+
dryRun,
|
|
804
|
+
showHeader: false,
|
|
805
|
+
force: true,
|
|
806
|
+
});
|
|
807
|
+
log('');
|
|
808
|
+
if (ok && !dryRun) {
|
|
809
|
+
log(' ' + cyan(`Upgraded to ${currentVersion}.`));
|
|
810
|
+
log(' ' + yellow(agent.restartHint));
|
|
811
|
+
}
|
|
812
|
+
log('');
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
async function cmdUninstall(args) {
|
|
816
|
+
const agentId = args.flags.for;
|
|
817
|
+
if (!agentId || agentId === true) {
|
|
818
|
+
logError('--for <agent> is required.');
|
|
819
|
+
log('Supported agents: ' + Object.keys(AGENTS).join(', '));
|
|
820
|
+
process.exit(1);
|
|
821
|
+
}
|
|
822
|
+
const { agent, destDir, effectiveGlobal } = resolveAgentDestination({
|
|
823
|
+
agentId,
|
|
824
|
+
isGlobal: !!args.flags.global,
|
|
825
|
+
isProject: !!args.flags.project,
|
|
826
|
+
});
|
|
827
|
+
const dryRun = !!args.flags['dry-run'];
|
|
828
|
+
|
|
829
|
+
log('');
|
|
830
|
+
log(' ' + cyan(`BA Toolkit — Uninstall from ${agent.name}`));
|
|
831
|
+
log(' ' + cyan('================================'));
|
|
832
|
+
log('');
|
|
833
|
+
log(` destination: ${destDir}`);
|
|
834
|
+
log(` scope: ${effectiveGlobal ? 'global (user-wide)' : 'project-level'}`);
|
|
835
|
+
if (dryRun) log(' ' + yellow('mode: dry-run (no files will be removed)'));
|
|
836
|
+
log('');
|
|
837
|
+
|
|
838
|
+
// Safety: this is the only place in the CLI that calls fs.rmSync with
|
|
839
|
+
// recursive: true. Refuse to proceed unless the destination is clearly
|
|
840
|
+
// a ba-toolkit folder (the install paths in AGENTS all end in
|
|
841
|
+
// `ba-toolkit/`). Without this check, a corrupted AGENTS entry or a
|
|
842
|
+
// future bug could turn this into `rm -rf $HOME`.
|
|
843
|
+
if (path.basename(destDir) !== 'ba-toolkit') {
|
|
844
|
+
logError(`Refusing to remove suspicious destination (not a ba-toolkit folder): ${destDir}`);
|
|
845
|
+
process.exit(1);
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
if (!fs.existsSync(destDir)) {
|
|
849
|
+
log(' ' + gray(`Nothing to uninstall — ${destDir} does not exist.`));
|
|
850
|
+
log('');
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// Count files for the preview message and final confirmation.
|
|
855
|
+
let fileCount = 0;
|
|
856
|
+
(function walk(d) {
|
|
857
|
+
for (const entry of fs.readdirSync(d, { withFileTypes: true })) {
|
|
858
|
+
const p = path.join(d, entry.name);
|
|
859
|
+
if (entry.isDirectory()) walk(p);
|
|
860
|
+
else fileCount++;
|
|
861
|
+
}
|
|
862
|
+
})(destDir);
|
|
863
|
+
|
|
864
|
+
log(` Found ${bold(fileCount)} files in the destination.`);
|
|
865
|
+
|
|
866
|
+
if (dryRun) {
|
|
867
|
+
log(' ' + yellow(`would remove ${fileCount} files from ${destDir}.`));
|
|
868
|
+
log('');
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
log('');
|
|
873
|
+
const answer = await prompt(` Remove ${destDir}? (y/N): `);
|
|
874
|
+
if (answer.toLowerCase() !== 'y') {
|
|
875
|
+
log(' Cancelled.');
|
|
876
|
+
log('');
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
fs.rmSync(destDir, { recursive: true, force: true });
|
|
880
|
+
log(' ' + green(`Removed ${fileCount} files from ${destDir}.`));
|
|
881
|
+
log(' ' + yellow(agent.restartHint));
|
|
882
|
+
log('');
|
|
883
|
+
}
|
|
884
|
+
|
|
587
885
|
function cmdHelp() {
|
|
588
886
|
log(`${bold('ba-toolkit')} v${PKG.version} — AI-powered Business Analyst pipeline
|
|
589
887
|
|
|
@@ -597,6 +895,18 @@ ${bold('COMMANDS')}
|
|
|
597
895
|
skills into the chosen agent's directory.
|
|
598
896
|
install --for <agent> Install (or re-install) skills into an
|
|
599
897
|
agent's directory without creating a project.
|
|
898
|
+
uninstall --for <agent> Remove BA Toolkit skills from an agent's
|
|
899
|
+
directory. Asks for confirmation before
|
|
900
|
+
deleting; supports --dry-run.
|
|
901
|
+
upgrade --for <agent> Refresh skills after a toolkit version bump.
|
|
902
|
+
Compares the installed version sentinel
|
|
903
|
+
against the package version, wipes the old
|
|
904
|
+
install on mismatch, and re-runs install.
|
|
905
|
+
Aliased as 'update'.
|
|
906
|
+
status Scan all known install locations for every
|
|
907
|
+
supported agent (project + global) and
|
|
908
|
+
report which versions are installed where.
|
|
909
|
+
Read-only; no flags.
|
|
600
910
|
|
|
601
911
|
${bold('INIT OPTIONS')}
|
|
602
912
|
--name <name> Skip the project name prompt
|
|
@@ -617,6 +927,20 @@ ${bold('INSTALL OPTIONS')}
|
|
|
617
927
|
--project Project-level install (default when supported)
|
|
618
928
|
--dry-run Preview without writing files
|
|
619
929
|
|
|
930
|
+
${bold('UNINSTALL OPTIONS')}
|
|
931
|
+
--for <agent> One of: ${Object.keys(AGENTS).join(', ')}
|
|
932
|
+
--global Remove the user-wide install
|
|
933
|
+
--project Remove the project-level install
|
|
934
|
+
(default when the agent supports it)
|
|
935
|
+
--dry-run Preview without removing files
|
|
936
|
+
|
|
937
|
+
${bold('UPGRADE OPTIONS')}
|
|
938
|
+
--for <agent> One of: ${Object.keys(AGENTS).join(', ')}
|
|
939
|
+
--global Upgrade the user-wide install
|
|
940
|
+
--project Upgrade the project-level install
|
|
941
|
+
(default when the agent supports it)
|
|
942
|
+
--dry-run Preview without writing or removing files
|
|
943
|
+
|
|
620
944
|
${bold('GENERAL OPTIONS')}
|
|
621
945
|
--version, -v Print version and exit
|
|
622
946
|
--help, -h Print this help and exit
|
|
@@ -635,6 +959,18 @@ ${bold('EXAMPLES')}
|
|
|
635
959
|
ba-toolkit install --for claude-code
|
|
636
960
|
ba-toolkit install --for cursor --dry-run
|
|
637
961
|
|
|
962
|
+
# Remove skills from an agent (asks for confirmation).
|
|
963
|
+
ba-toolkit uninstall --for claude-code
|
|
964
|
+
ba-toolkit uninstall --for claude-code --global
|
|
965
|
+
ba-toolkit uninstall --for cursor --dry-run
|
|
966
|
+
|
|
967
|
+
# After 'npm update -g @kudusov.takhir/ba-toolkit', refresh the skills.
|
|
968
|
+
ba-toolkit upgrade --for claude-code
|
|
969
|
+
ba-toolkit upgrade --for cursor --dry-run
|
|
970
|
+
|
|
971
|
+
# See where (and which version) BA Toolkit is installed.
|
|
972
|
+
ba-toolkit status
|
|
973
|
+
|
|
638
974
|
${bold('LEARN MORE')}
|
|
639
975
|
https://github.com/TakhirKudusov/ba-toolkit
|
|
640
976
|
`);
|
|
@@ -663,6 +999,16 @@ async function main() {
|
|
|
663
999
|
case 'install':
|
|
664
1000
|
await cmdInstall(args);
|
|
665
1001
|
break;
|
|
1002
|
+
case 'uninstall':
|
|
1003
|
+
await cmdUninstall(args);
|
|
1004
|
+
break;
|
|
1005
|
+
case 'upgrade':
|
|
1006
|
+
case 'update':
|
|
1007
|
+
await cmdUpgrade(args);
|
|
1008
|
+
break;
|
|
1009
|
+
case 'status':
|
|
1010
|
+
cmdStatus();
|
|
1011
|
+
break;
|
|
666
1012
|
case 'help':
|
|
667
1013
|
cmdHelp();
|
|
668
1014
|
break;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kudusov.takhir/ba-toolkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "AI-powered Business Analyst pipeline — 21 skills from project brief to development handoff. Works with Claude Code, Codex CLI, Gemini CLI, Cursor, and Windsurf.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"business-analyst",
|