@groupby/ai-dev 0.2.1 → 0.3.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 +3 -1
- package/dist/index.js +86 -19
- package/package.json +4 -4
- package/skills/library/implementation-plan/README.md +19 -0
- package/skills/library/implementation-plan/SKILL.md +337 -0
- package/skills/library/jira-plan/README.md +17 -0
- package/skills/library/jira-plan/SKILL.md +163 -0
- package/toolsets/rzlv-flow/README.md +54 -9
- package/toolsets/rzlv-flow/resources/confluence-file-structure.md +129 -23
- package/toolsets/rzlv-flow/resources/sync-state-format.md +109 -0
- package/toolsets/rzlv-flow/skills/jira-daily-triage/SKILL.md +13 -5
- package/toolsets/rzlv-flow/skills/jira-sprint-status/SKILL.md +28 -1
- package/toolsets/rzlv-flow/skills/jira-ticket-focus/SKILL.md +6 -1
- package/toolsets/rzlv-flow/skills/jira-wrap-sync/SKILL.md +41 -8
- package/skills/skills/README.md +0 -61
- package/skills/skills/archived/README.md +0 -3
- package/skills/skills/library/README.md +0 -3
- package/skills/skills/library/frontend-design/LICENSE.txt +0 -177
- package/skills/skills/library/frontend-design/SKILL.md +0 -42
- package/teams/teams/brain-studio/skills/code-review/SKILL.md +0 -46
- package/toolsets/toolsets/rzlv-flow/README.md +0 -102
- package/toolsets/toolsets/rzlv-flow/docs/mcp-setup.md +0 -126
- package/toolsets/toolsets/rzlv-flow/resources/README.md +0 -16
- package/toolsets/toolsets/rzlv-flow/resources/confluence-file-structure.md +0 -285
- package/toolsets/toolsets/rzlv-flow/resources/confluence-page-templates/README.md +0 -19
- package/toolsets/toolsets/rzlv-flow/resources/confluence-page-templates/decisions.md +0 -36
- package/toolsets/toolsets/rzlv-flow/resources/confluence-page-templates/initiative-overview.md +0 -40
- package/toolsets/toolsets/rzlv-flow/resources/confluence-page-templates/strategic-context.md +0 -44
- package/toolsets/toolsets/rzlv-flow/resources/confluence-page-templates/technical-architecture.md +0 -48
- package/toolsets/toolsets/rzlv-flow/resources/fcmp-protocol.md +0 -331
- package/toolsets/toolsets/rzlv-flow/resources/jira-file-structure.md +0 -177
- package/toolsets/toolsets/rzlv-flow/resources/sync-state-format.md +0 -318
- package/toolsets/toolsets/rzlv-flow/skills/atlassian-orchestrator/SKILL.md +0 -643
- package/toolsets/toolsets/rzlv-flow/skills/context-analyst/SKILL.md +0 -265
- package/toolsets/toolsets/rzlv-flow/skills/jira-comment/SKILL.md +0 -89
- package/toolsets/toolsets/rzlv-flow/skills/jira-daily-triage/SKILL.md +0 -143
- package/toolsets/toolsets/rzlv-flow/skills/jira-sprint-status/SKILL.md +0 -143
- package/toolsets/toolsets/rzlv-flow/skills/jira-status/SKILL.md +0 -97
- package/toolsets/toolsets/rzlv-flow/skills/jira-sync/SKILL.md +0 -148
- package/toolsets/toolsets/rzlv-flow/skills/jira-ticket-focus/SKILL.md +0 -245
- package/toolsets/toolsets/rzlv-flow/skills/jira-ticket-trace/SKILL.md +0 -112
- package/toolsets/toolsets/rzlv-flow/skills/jira-wrap-sync/SKILL.md +0 -260
- /package/toolsets/{toolsets/rzlv-flow → rzlv-flow}/docs/getting-started.md +0 -0
- /package/toolsets/{toolsets/rzlv-flow → rzlv-flow}/skills/confluence-fetch/SKILL.md +0 -0
- /package/toolsets/{toolsets/rzlv-flow → rzlv-flow}/skills/confluence-publish/SKILL.md +0 -0
package/README.md
CHANGED
|
@@ -57,6 +57,7 @@ When installing a team's skills, you will be prompted to optionally include skil
|
|
|
57
57
|
| Flag | Description |
|
|
58
58
|
| --- | --- |
|
|
59
59
|
| `--target <dir>` | Install into a specific directory (defaults to cwd) |
|
|
60
|
+
| `--ai-dir <path>` | Override the AI skills/resources directory (defaults to `docs/ai`) |
|
|
60
61
|
| `--dry-run` | Preview what would be installed without writing files |
|
|
61
62
|
| `--force` | Overwrite existing files without prompting |
|
|
62
63
|
| `--skip-existing` | Skip files that already exist |
|
|
@@ -65,8 +66,9 @@ When installing a team's skills, you will be prompted to optionally include skil
|
|
|
65
66
|
|
|
66
67
|
1. **Discovery** — The CLI scans bundled `skills/` and `teams/` directories for `SKILL.md` files and reads their YAML frontmatter (name, description, etc.).
|
|
67
68
|
2. **Client detection** — It checks the target project for known config directories (`.github/`, `.claude/`, `.agents/`) to determine which LLM clients are in use.
|
|
68
|
-
3. **Installation** — Each selected skill is copied into `docs/ai/skills/<name>/` and a stub `SKILL.md` is generated in each client's skills directory pointing back to the full skill file.
|
|
69
|
+
3. **Installation** — Each selected skill is copied into `<ai-dir>/skills/<name>/` (default: `docs/ai/skills/<name>/`) and a stub `SKILL.md` is generated in each client's skills directory pointing back to the full skill file.
|
|
69
70
|
4. **Conflict handling** — If a file already exists and its content differs, you are prompted to overwrite or skip (unless `--force` or `--skip-existing` is set).
|
|
71
|
+
5. **Path patching** — When `--ai-dir` is set to a non-default value, any `docs/ai/` references inside installed `.md` files are replaced with the custom path so LLMs can find resource files at runtime.
|
|
70
72
|
|
|
71
73
|
## Supported clients
|
|
72
74
|
|
package/dist/index.js
CHANGED
|
@@ -22,9 +22,9 @@ function parseFrontmatter(content) {
|
|
|
22
22
|
content: parsed.content
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
-
function generateStub(frontmatter, skillName) {
|
|
25
|
+
function generateStub(frontmatter, skillName, aiDir = "docs/ai") {
|
|
26
26
|
const body = `
|
|
27
|
-
See
|
|
27
|
+
See \`${aiDir}/skills/${skillName}/SKILL.md\` and follow closely.
|
|
28
28
|
`;
|
|
29
29
|
return matter.stringify(body, frontmatter);
|
|
30
30
|
}
|
|
@@ -266,6 +266,7 @@ async function detectClients(targetDir) {
|
|
|
266
266
|
// src/lib/installer.ts
|
|
267
267
|
import path3 from "path";
|
|
268
268
|
import fs4 from "fs-extra";
|
|
269
|
+
var DEFAULT_AI_DIR = "docs/ai";
|
|
269
270
|
async function handleFile(srcPath, destPath, options, result, onConflict, contentOverride) {
|
|
270
271
|
const relativeDest = path3.relative(options.targetDir, destPath);
|
|
271
272
|
if (await fs4.pathExists(destPath)) {
|
|
@@ -309,6 +310,12 @@ async function handleFile(srcPath, destPath, options, result, onConflict, conten
|
|
|
309
310
|
result.created.push(relativeDest);
|
|
310
311
|
}
|
|
311
312
|
}
|
|
313
|
+
async function patchContent(srcPath, aiDir) {
|
|
314
|
+
if (aiDir === DEFAULT_AI_DIR) return void 0;
|
|
315
|
+
if (!srcPath.endsWith(".md")) return void 0;
|
|
316
|
+
const content = await fs4.readFile(srcPath, "utf-8");
|
|
317
|
+
return content.replaceAll(`${DEFAULT_AI_DIR}/`, `${aiDir}/`);
|
|
318
|
+
}
|
|
312
319
|
async function installSkill(skill, options, onConflict) {
|
|
313
320
|
const result = {
|
|
314
321
|
skill: skill.name,
|
|
@@ -316,14 +323,15 @@ async function installSkill(skill, options, onConflict) {
|
|
|
316
323
|
skipped: [],
|
|
317
324
|
overwritten: []
|
|
318
325
|
};
|
|
319
|
-
const destFolder = path3.join(options.targetDir,
|
|
326
|
+
const destFolder = path3.join(options.targetDir, options.aiDir, "skills", skill.name);
|
|
320
327
|
const sourceFiles = await fs4.readdir(skill.sourcePath);
|
|
321
328
|
for (const file of sourceFiles) {
|
|
322
329
|
const srcFile = path3.join(skill.sourcePath, file);
|
|
323
330
|
const stat = await fs4.stat(srcFile);
|
|
324
331
|
if (stat.isFile()) {
|
|
325
332
|
const destFile = path3.join(destFolder, file);
|
|
326
|
-
await
|
|
333
|
+
const contentOverride = await patchContent(srcFile, options.aiDir);
|
|
334
|
+
await handleFile(srcFile, destFile, options, result, onConflict, contentOverride);
|
|
327
335
|
}
|
|
328
336
|
}
|
|
329
337
|
for (const client of options.clients) {
|
|
@@ -333,7 +341,7 @@ async function installSkill(skill, options, onConflict) {
|
|
|
333
341
|
skill.name,
|
|
334
342
|
"SKILL.md"
|
|
335
343
|
);
|
|
336
|
-
const stubContent = generateStub(skill.frontmatter, skill.name);
|
|
344
|
+
const stubContent = generateStub(skill.frontmatter, skill.name, options.aiDir);
|
|
337
345
|
await handleFile("", stubPath, options, result, onConflict, stubContent);
|
|
338
346
|
}
|
|
339
347
|
return result;
|
|
@@ -355,14 +363,15 @@ async function installResources(toolset, options, onConflict) {
|
|
|
355
363
|
if (!toolset.hasResources) return result;
|
|
356
364
|
const entries = await fs4.readdir(toolset.resourcesPath);
|
|
357
365
|
const resourceFiles = entries.filter((e) => e !== "README.md");
|
|
358
|
-
const destDir = path3.join(options.targetDir,
|
|
366
|
+
const destDir = path3.join(options.targetDir, options.aiDir, "resources");
|
|
359
367
|
const fileResult = { skill: toolset.name, created: [], skipped: [], overwritten: [] };
|
|
360
368
|
for (const file of resourceFiles) {
|
|
361
369
|
const srcFile = path3.join(toolset.resourcesPath, file);
|
|
362
370
|
const stat = await fs4.stat(srcFile);
|
|
363
371
|
if (!stat.isFile()) continue;
|
|
364
372
|
const destFile = path3.join(destDir, file);
|
|
365
|
-
await
|
|
373
|
+
const contentOverride = await patchContent(srcFile, options.aiDir);
|
|
374
|
+
await handleFile(srcFile, destFile, options, fileResult, onConflict, contentOverride);
|
|
366
375
|
}
|
|
367
376
|
result.created = fileResult.created;
|
|
368
377
|
result.skipped = fileResult.skipped;
|
|
@@ -371,7 +380,7 @@ async function installResources(toolset, options, onConflict) {
|
|
|
371
380
|
}
|
|
372
381
|
|
|
373
382
|
// src/lib/prompts.ts
|
|
374
|
-
import { select, checkbox, confirm } from "@inquirer/prompts";
|
|
383
|
+
import { select, checkbox, confirm, input } from "@inquirer/prompts";
|
|
375
384
|
import chalk2 from "chalk";
|
|
376
385
|
async function promptSelectSkills(skills) {
|
|
377
386
|
const librarySkills = skills.filter((s) => s.sourceType === "library");
|
|
@@ -457,12 +466,22 @@ async function promptIncludeLibrary() {
|
|
|
457
466
|
default: false
|
|
458
467
|
});
|
|
459
468
|
}
|
|
460
|
-
async function
|
|
469
|
+
async function promptInstallDir() {
|
|
470
|
+
const raw = await input({
|
|
471
|
+
message: "Install location for AI skills and resources:",
|
|
472
|
+
default: "docs/ai"
|
|
473
|
+
});
|
|
474
|
+
return raw.replace(/\/+$/, "") || "docs/ai";
|
|
475
|
+
}
|
|
476
|
+
async function promptConfirmInstall(skills, clients, targetDir, aiDir = "docs/ai") {
|
|
461
477
|
console.log();
|
|
462
478
|
console.log(chalk2.bold("Install summary:"));
|
|
463
479
|
console.log(` Skills: ${skills.map((s) => s.name).join(", ")}`);
|
|
464
480
|
console.log(` Clients: ${clients.map((c) => c.name).join(", ") || chalk2.dim("none")}`);
|
|
465
481
|
console.log(` Target: ${targetDir}`);
|
|
482
|
+
if (aiDir !== "docs/ai") {
|
|
483
|
+
console.log(` AI directory: ${aiDir}`);
|
|
484
|
+
}
|
|
466
485
|
console.log();
|
|
467
486
|
return confirm({ message: "Proceed with installation?", default: true });
|
|
468
487
|
}
|
|
@@ -485,6 +504,14 @@ function formatTeamName2(name) {
|
|
|
485
504
|
}
|
|
486
505
|
|
|
487
506
|
// src/commands/install.ts
|
|
507
|
+
function normalizeAiDir(raw) {
|
|
508
|
+
const trimmed = raw.replace(/\/+$/, "") || DEFAULT_AI_DIR;
|
|
509
|
+
if (path4.isAbsolute(trimmed)) {
|
|
510
|
+
console.log(chalk3.red(`--ai-dir must be a relative path, got: ${trimmed}`));
|
|
511
|
+
process.exit(1);
|
|
512
|
+
}
|
|
513
|
+
return trimmed;
|
|
514
|
+
}
|
|
488
515
|
function printResults(results, options, resourceResult) {
|
|
489
516
|
const prefix = options.dryRun ? chalk3.yellow("[DRY RUN] ") : "";
|
|
490
517
|
const createdWord = options.dryRun ? "would create" : "created";
|
|
@@ -525,6 +552,7 @@ async function installSkillCmd(name, _opts, cmd) {
|
|
|
525
552
|
const targetDir = path4.resolve(
|
|
526
553
|
parentOpts.target || process.cwd()
|
|
527
554
|
);
|
|
555
|
+
const aiDir = normalizeAiDir(parentOpts.aiDir || DEFAULT_AI_DIR);
|
|
528
556
|
const skill = await findSkill(name);
|
|
529
557
|
if (!skill) {
|
|
530
558
|
const all = await discoverSkills();
|
|
@@ -541,6 +569,7 @@ async function installSkillCmd(name, _opts, cmd) {
|
|
|
541
569
|
}
|
|
542
570
|
const options = {
|
|
543
571
|
targetDir,
|
|
572
|
+
aiDir,
|
|
544
573
|
clients,
|
|
545
574
|
force,
|
|
546
575
|
skipExisting,
|
|
@@ -564,6 +593,7 @@ async function installTeamCmd(name, _opts, cmd) {
|
|
|
564
593
|
const targetDir = path4.resolve(
|
|
565
594
|
parentOpts.target || process.cwd()
|
|
566
595
|
);
|
|
596
|
+
const aiDir = normalizeAiDir(parentOpts.aiDir || DEFAULT_AI_DIR);
|
|
567
597
|
const teams = await discoverTeams();
|
|
568
598
|
const team = teams.find(
|
|
569
599
|
(t) => t.name === name || t.name.toLowerCase() === name.toLowerCase()
|
|
@@ -589,6 +619,7 @@ async function installTeamCmd(name, _opts, cmd) {
|
|
|
589
619
|
}
|
|
590
620
|
const options = {
|
|
591
621
|
targetDir,
|
|
622
|
+
aiDir,
|
|
592
623
|
clients,
|
|
593
624
|
force,
|
|
594
625
|
skipExisting,
|
|
@@ -609,6 +640,7 @@ async function installToolsetCmd(name, _opts, cmd) {
|
|
|
609
640
|
const targetDir = path4.resolve(
|
|
610
641
|
parentOpts.target || process.cwd()
|
|
611
642
|
);
|
|
643
|
+
const aiDir = normalizeAiDir(parentOpts.aiDir || DEFAULT_AI_DIR);
|
|
612
644
|
const toolset = await findToolset(name);
|
|
613
645
|
if (!toolset) {
|
|
614
646
|
const allToolsets = await discoverToolsets();
|
|
@@ -627,6 +659,7 @@ async function installToolsetCmd(name, _opts, cmd) {
|
|
|
627
659
|
}
|
|
628
660
|
const options = {
|
|
629
661
|
targetDir,
|
|
662
|
+
aiDir,
|
|
630
663
|
clients,
|
|
631
664
|
force,
|
|
632
665
|
skipExisting,
|
|
@@ -640,11 +673,18 @@ async function installToolsetCmd(name, _opts, cmd) {
|
|
|
640
673
|
const results = await installSkills(toolset.skills, options, conflictHandler);
|
|
641
674
|
printResults(results, options, resourceResult);
|
|
642
675
|
}
|
|
676
|
+
var INHERITED_OPTIONS_HELP = `
|
|
677
|
+
Parent options (pass before subcommand):
|
|
678
|
+
--force Overwrite existing files without prompting
|
|
679
|
+
--skip-existing Skip files that already exist without prompting
|
|
680
|
+
--dry-run Show what would be installed without writing files
|
|
681
|
+
--target <dir> Install to a different directory (default: CWD)
|
|
682
|
+
--ai-dir <path> Override the AI skills/resources directory (default: docs/ai)`;
|
|
643
683
|
function registerInstallCommand(program2) {
|
|
644
|
-
const install = program2.command("install").description("Install skills").option("--force", "Overwrite existing files without prompting").option("--skip-existing", "Skip files that already exist without prompting").option("--dry-run", "Show what would be installed without writing files").option("--target <dir>", "Install to a different directory (default: CWD)");
|
|
645
|
-
install.command("skill <name>").description("Install a specific skill").action(installSkillCmd);
|
|
646
|
-
install.command("team <name>").description("Install all skills for a team").action(installTeamCmd);
|
|
647
|
-
install.command("toolset <name>").description("Install all skills and resources for a toolset").action(installToolsetCmd);
|
|
684
|
+
const install = program2.command("install").description("Install skills").option("--force", "Overwrite existing files without prompting").option("--skip-existing", "Skip files that already exist without prompting").option("--dry-run", "Show what would be installed without writing files").option("--target <dir>", "Install to a different directory (default: CWD)").option("--ai-dir <path>", "Override the AI skills/resources directory (default: docs/ai)");
|
|
685
|
+
install.command("skill <name>").description("Install a specific skill").addHelpText("after", INHERITED_OPTIONS_HELP).action(installSkillCmd);
|
|
686
|
+
install.command("team <name>").description("Install all skills for a team").addHelpText("after", INHERITED_OPTIONS_HELP).action(installTeamCmd);
|
|
687
|
+
install.command("toolset <name>").description("Install all skills and resources for a toolset").addHelpText("after", INHERITED_OPTIONS_HELP).action(installToolsetCmd);
|
|
648
688
|
}
|
|
649
689
|
|
|
650
690
|
// src/commands/interactive.ts
|
|
@@ -757,20 +797,32 @@ async function runInteractive() {
|
|
|
757
797
|
const selectedSkills = await promptSelectSkills(allSkills);
|
|
758
798
|
const detected = await detectClients(targetDir);
|
|
759
799
|
const clients = await promptSelectClients(ALL_CLIENTS, detected);
|
|
760
|
-
const
|
|
800
|
+
const aiDir = await promptInstallDir();
|
|
801
|
+
const confirmed = await promptConfirmInstall(selectedSkills, clients, targetDir, aiDir);
|
|
761
802
|
if (!confirmed) {
|
|
762
803
|
console.log(chalk4.dim("Cancelled."));
|
|
763
804
|
return;
|
|
764
805
|
}
|
|
765
806
|
const options = {
|
|
766
807
|
targetDir,
|
|
808
|
+
aiDir,
|
|
767
809
|
clients,
|
|
768
810
|
force: false,
|
|
769
811
|
skipExisting: false,
|
|
770
812
|
dryRun: false
|
|
771
813
|
};
|
|
772
814
|
const results = await installSkills(selectedSkills, options, promptConflict);
|
|
773
|
-
|
|
815
|
+
let resourceResult;
|
|
816
|
+
const toolsetNames = new Set(
|
|
817
|
+
selectedSkills.filter((s) => s.sourceType === "toolset" && s.toolsetName).map((s) => s.toolsetName)
|
|
818
|
+
);
|
|
819
|
+
for (const tsName of toolsetNames) {
|
|
820
|
+
const toolset = await findToolset(tsName);
|
|
821
|
+
if (toolset && toolset.hasResources) {
|
|
822
|
+
resourceResult = await installResources(toolset, options, promptConflict);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
printResults2(results, options, resourceResult);
|
|
774
826
|
} else if (action === "install-team") {
|
|
775
827
|
const teams = await discoverTeams();
|
|
776
828
|
if (teams.length === 0) {
|
|
@@ -787,20 +839,32 @@ async function runInteractive() {
|
|
|
787
839
|
}
|
|
788
840
|
const detected = await detectClients(targetDir);
|
|
789
841
|
const clients = await promptSelectClients(ALL_CLIENTS, detected);
|
|
790
|
-
const
|
|
842
|
+
const aiDir = await promptInstallDir();
|
|
843
|
+
const confirmed = await promptConfirmInstall(skillsToInstall, clients, targetDir, aiDir);
|
|
791
844
|
if (!confirmed) {
|
|
792
845
|
console.log(chalk4.dim("Cancelled."));
|
|
793
846
|
return;
|
|
794
847
|
}
|
|
795
848
|
const options = {
|
|
796
849
|
targetDir,
|
|
850
|
+
aiDir,
|
|
797
851
|
clients,
|
|
798
852
|
force: false,
|
|
799
853
|
skipExisting: false,
|
|
800
854
|
dryRun: false
|
|
801
855
|
};
|
|
802
856
|
const results = await installSkills(skillsToInstall, options, promptConflict);
|
|
803
|
-
|
|
857
|
+
let resourceResult;
|
|
858
|
+
const toolsetNames = new Set(
|
|
859
|
+
skillsToInstall.filter((s) => s.sourceType === "toolset" && s.toolsetName).map((s) => s.toolsetName)
|
|
860
|
+
);
|
|
861
|
+
for (const tsName of toolsetNames) {
|
|
862
|
+
const toolset = await findToolset(tsName);
|
|
863
|
+
if (toolset && toolset.hasResources) {
|
|
864
|
+
resourceResult = await installResources(toolset, options, promptConflict);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
printResults2(results, options, resourceResult);
|
|
804
868
|
} else if (action === "install-toolset") {
|
|
805
869
|
const toolsets = await discoverToolsets();
|
|
806
870
|
if (toolsets.length === 0) {
|
|
@@ -810,13 +874,15 @@ async function runInteractive() {
|
|
|
810
874
|
const toolset = await promptSelectToolset(toolsets);
|
|
811
875
|
const detected = await detectClients(targetDir);
|
|
812
876
|
const clients = await promptSelectClients(ALL_CLIENTS, detected);
|
|
813
|
-
const
|
|
877
|
+
const aiDir = await promptInstallDir();
|
|
878
|
+
const confirmed = await promptConfirmInstall(toolset.skills, clients, targetDir, aiDir);
|
|
814
879
|
if (!confirmed) {
|
|
815
880
|
console.log(chalk4.dim("Cancelled."));
|
|
816
881
|
return;
|
|
817
882
|
}
|
|
818
883
|
const options = {
|
|
819
884
|
targetDir,
|
|
885
|
+
aiDir,
|
|
820
886
|
clients,
|
|
821
887
|
force: false,
|
|
822
888
|
skipExisting: false,
|
|
@@ -846,6 +912,7 @@ Examples:
|
|
|
846
912
|
$ npx @groupby/ai-dev install skill frontend-design Install a single skill
|
|
847
913
|
$ npx @groupby/ai-dev install team brain-studio Install all team skills
|
|
848
914
|
$ npx @groupby/ai-dev install toolset rzlv-flow Install all skills + resources for a toolset
|
|
849
|
-
$ npx @groupby/ai-dev install team brain-studio --dry-run
|
|
915
|
+
$ npx @groupby/ai-dev install team brain-studio --dry-run
|
|
916
|
+
$ npx @groupby/ai-dev install skill frontend-design --ai-dir .ai`
|
|
850
917
|
);
|
|
851
918
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@groupby/ai-dev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Interactive installer for Rezolve Ai development skills",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"toolsets/"
|
|
14
14
|
],
|
|
15
15
|
"scripts": {
|
|
16
|
-
"prebuild": "cp -r ../skills ./skills && cp -r ../teams ./teams && cp -r ../toolsets ./toolsets",
|
|
16
|
+
"prebuild": "rm -rf skills teams toolsets && cp -r ../skills ./skills && cp -r ../teams ./teams && cp -r ../toolsets ./toolsets",
|
|
17
17
|
"build": "tsup",
|
|
18
18
|
"prepublishOnly": "npm run build",
|
|
19
19
|
"test": "vitest run",
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
},
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "git+https://github.com/
|
|
25
|
+
"url": "git+https://github.com/groupby/ai-dev-shared.git",
|
|
26
26
|
"directory": "cli"
|
|
27
27
|
},
|
|
28
28
|
"engines": {
|
|
29
|
-
"node": ">=
|
|
29
|
+
"node": ">=20"
|
|
30
30
|
},
|
|
31
31
|
"publishConfig": {
|
|
32
32
|
"access": "public"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# implementation-plan
|
|
2
|
+
|
|
3
|
+
Generate structured implementation plans from any written input — documents, notes, specs, or descriptions.
|
|
4
|
+
|
|
5
|
+
Produces phased checklists with architecture justification, a clarifications file for surfacing and resolving ambiguities before planning, and self-contained sub-plan files for larger work.
|
|
6
|
+
|
|
7
|
+
## Output
|
|
8
|
+
|
|
9
|
+
Plans are written to `docs/planning/<story-name>/` (folder) or `docs/planning/<story-name>.md` (single file), depending on scope. A `clarifications.md` file is always generated alongside the plan.
|
|
10
|
+
|
|
11
|
+
## Example prompts
|
|
12
|
+
|
|
13
|
+
- `/implementation-plan` with a pasted feature description
|
|
14
|
+
- `/implementation-plan` pointing to `docs/planning/tasks/configurable-install-path.md`
|
|
15
|
+
- "Plan the implementation for adding OAuth support"
|
|
16
|
+
|
|
17
|
+
## Related
|
|
18
|
+
|
|
19
|
+
- [`jira-plan`](../jira-plan/) — wrapper that fetches Jira ticket context and delegates to this skill for plan generation
|