@atlashub/smartstack-cli 1.26.0 → 1.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -317,7 +317,7 @@ code .
317
317
 
318
318
  In VS Code with Claude Code active:
319
319
  ```
320
- /gitflow:1-init
320
+ /gitflow init
321
321
  ```
322
322
 
323
323
  ---
@@ -468,73 +468,51 @@ smartstack license verify ABC123-DEF456 # Verify without activating
468
468
 
469
469
  ### GitFlow Workflow
470
470
 
471
- | Command | Description |
471
+ | Skill | Description |
472
472
  |---------|-------------|
473
473
  | `/gitflow` | Full GitFlow workflow |
474
- | `/gitflow:1-init` | Initialize GitFlow structure |
475
- | `/gitflow:2-status` | Show repository status |
476
- | `/gitflow:3-commit` | Smart commit with validation |
477
- | `/gitflow:4-plan` | Create integration plan |
478
- | `/gitflow:5-exec` | Execute integration plan |
479
- | `/gitflow:6-abort` | Rollback operations |
480
- | `/gitflow:10-start` | Start feature/release/hotfix |
481
- | `/gitflow:11-finish` | Finish and tag |
482
- | `/gitflow:12-cleanup` | Cleanup worktrees |
483
- | `/gitflow:13-sync` | Sync with remote |
484
- | `/gitflow:14-rebase` | Rebase on develop |
485
- | `/gitflow:7-pull-request` | Create a Pull Request |
486
- | `/gitflow:8-review` | Review a PR |
487
- | `/gitflow:9-merge` | Merge a PR |
474
+ | `/gitflow init` | Initialize GitFlow structure |
475
+ | `/gitflow status` | Show repository status |
476
+ | `/gitflow commit` | Smart commit with validation |
477
+ | `/gitflow start` | Start feature/release/hotfix |
478
+ | `/gitflow finish` | Finish and tag |
479
+ | `/gitflow pr` | Create a Pull Request |
480
+ | `/gitflow cleanup` | Cleanup worktrees |
488
481
 
489
482
  ### Development Methodologies
490
483
 
491
- | Command | Description |
484
+ | Skill | Description |
492
485
  |---------|-------------|
493
486
  | `/apex` | APEX methodology (Analyze-Plan-Execute-eXamine) |
494
- | `/epct` | Explore-Plan-Code-Test methodology |
495
- | `/oneshot` | Ultra-fast implementation |
496
487
  | `/debug` | Systematic debugging |
497
488
  | `/explore` | Deep codebase exploration |
498
- | `/explain` | Code explanation with diagrams |
499
- | `/review` | Quick code review |
500
- | `/implement` | Implementation from BA handoff |
489
+ | `/refactor` | Code refactoring |
490
+ | `/review-code` | Code review |
501
491
 
502
492
  ### Business Analysis
503
493
 
504
- | Command | Description |
494
+ | Skill | Description |
505
495
  |---------|-------------|
506
496
  | `/business-analyse` | Full BA workflow with orchestration |
507
- | `/business-analyse:1-init` | Initialize BA structure |
508
- | `/business-analyse:2-discover` | Requirements elicitation |
509
- | `/business-analyse:3-analyse` | Business analysis (BRD) |
510
- | `/business-analyse:4-specify` | Functional specification (FRD) |
511
- | `/business-analyse:5-validate` | User validation gate |
512
- | `/business-analyse:6-handoff` | Implementation brief |
513
- | `/business-analyse:7-doc-html` | Auto-generated HTML documentation |
514
- | `/business-analyse:bug` | Bug resolution documentation |
515
- | `/business-analyse:change-request` | Change request during development |
497
+ | `/business-analyse init` | Initialize BA structure |
498
+ | `/business-analyse discover` | Requirements elicitation |
499
+ | `/business-analyse analyse` | Business analysis (BRD) |
500
+ | `/business-analyse specify` | Functional specification (FRD) |
501
+ | `/business-analyse validate` | User validation gate |
502
+ | `/business-analyse handoff` | Implementation brief |
516
503
 
517
504
  ### EF Core Migrations
518
505
 
519
- | Command | Description |
506
+ | Skill | Description |
520
507
  |---------|-------------|
521
508
  | `/efcore` | EF Core orchestrator |
522
- | `/efcore:migration` | Create/recreate migration |
523
- | `/efcore:db-status` | Show migration status |
524
- | `/efcore:db-deploy` | Apply migrations |
525
- | `/efcore:db-seed` | Seed database |
526
- | `/efcore:db-reset` | Reset database |
527
- | `/efcore:scan` | Scan migrations across branches |
528
- | `/efcore:conflicts` | Detect conflicts |
529
- | `/efcore:rebase-snapshot` | Rebase ModelSnapshot |
530
- | `/efcore:squash` | Squash multiple migrations |
531
-
532
- ### Prompts & Tools
533
-
534
- | Command | Description |
535
- |---------|-------------|
536
- | `/prompts:create` | Expert prompt creation |
537
- | `/prompts:agent` | Agent prompt optimization |
509
+ | `/efcore migration` | Create/recreate migration |
510
+ | `/efcore db-status` | Show migration status |
511
+ | `/efcore db-deploy` | Apply migrations |
512
+ | `/efcore db-seed` | Seed database |
513
+ | `/efcore db-reset` | Reset database |
514
+ | `/efcore scan` | Scan migrations across branches |
515
+ | `/efcore conflicts` | Detect conflicts |
538
516
  | `/prompts:command` | Command prompt patterns |
539
517
  | `/prompts:claude-memory` | CLAUDE.md file management |
540
518
 
package/dist/index.js CHANGED
@@ -112189,7 +112189,7 @@ var import_child_process = require("child_process");
112189
112189
  var import_fs_extra = __toESM(require_lib());
112190
112190
  var PACKAGE_ROOT = (0, import_path.join)(__dirname, "..");
112191
112191
  var TEMPLATES_DIR = (0, import_path.join)(PACKAGE_ROOT, "templates");
112192
- var INSTALL_DIRS = ["commands", "agents", "hooks", "skills", "scripts"];
112192
+ var INSTALL_DIRS = ["agents", "hooks", "skills", "scripts"];
112193
112193
  var MANIFEST_FILE = ".smartstack-manifest.json";
112194
112194
  async function readManifest(claudeDir) {
112195
112195
  const manifestPath = (0, import_path.join)(claudeDir, MANIFEST_FILE);
@@ -112862,29 +112862,28 @@ var installCommand = new Command("install").alias("i").description("Install Smar
112862
112862
  `Files installed: ${source_default.cyan(result.installed)}`,
112863
112863
  `Files skipped: ${source_default.yellow(result.skipped)} (use --force to overwrite)`,
112864
112864
  "",
112865
- "Available commands in Claude Code:",
112865
+ "Available skills in Claude Code:",
112866
112866
  "",
112867
112867
  source_default.bold("GitFlow:"),
112868
- ` ${source_default.cyan("/gitflow")} - Full GitFlow workflow`,
112869
- ` ${source_default.cyan("/gitflow:1-init")} - Initialize GitFlow`,
112870
- ` ${source_default.cyan("/gitflow:2-status")} - Show status`,
112871
- ` ${source_default.cyan("/gitflow:3-commit")} - Smart commit`,
112868
+ ` ${source_default.cyan("/gitflow")} - Full GitFlow workflow`,
112869
+ ` ${source_default.cyan("/gitflow start")} - Start feature/release/hotfix`,
112870
+ ` ${source_default.cyan("/gitflow commit")} - Smart commit`,
112871
+ ` ${source_default.cyan("/gitflow finish")} - Finish and merge`,
112872
112872
  "",
112873
112873
  source_default.bold("Development:"),
112874
- ` ${source_default.cyan("/apex")} - APEX methodology`,
112875
- ` ${source_default.cyan("/epct")} - Explore-Plan-Code-Test`,
112876
- ` ${source_default.cyan("/debug")} - Systematic debugging`,
112874
+ ` ${source_default.cyan("/apex")} - APEX methodology`,
112875
+ ` ${source_default.cyan("/debug")} - Systematic debugging`,
112876
+ ` ${source_default.cyan("/refactor")} - Code refactoring`,
112877
112877
  "",
112878
112878
  source_default.bold("Business Analysis:"),
112879
- ` ${source_default.cyan("/business-analyse")} - Full BA workflow`,
112879
+ ` ${source_default.cyan("/business-analyse")} - Full BA workflow`,
112880
112880
  "",
112881
112881
  source_default.bold("EF Core:"),
112882
- ` ${source_default.cyan("/efcore")} - EF Core orchestrator`,
112883
- ` ${source_default.cyan("/efcore:migration")} - Migration management`,
112882
+ ` ${source_default.cyan("/efcore")} - EF Core orchestrator`,
112883
+ ` ${source_default.cyan("/efcore migration")} - Migration management`,
112884
112884
  "",
112885
112885
  source_default.bold("Ralph Loop:"),
112886
- ` ${source_default.cyan("/ralph-loop")} - Start iterative loop`,
112887
- ` ${source_default.cyan("/cancel-ralph")} - Cancel active loop`,
112886
+ ` ${source_default.cyan("/ralph-loop")} - Start iterative loop`,
112888
112887
  ...pluginSummary
112889
112888
  ];
112890
112889
  logger.box(summary, "success");
@@ -115575,6 +115574,68 @@ function validateCSharpNamespace(name) {
115575
115574
  }
115576
115575
  return { valid: true };
115577
115576
  }
115577
+ async function detectProjectContext(name, here) {
115578
+ const cwd = process.cwd();
115579
+ if (name && name.trim() && !here) {
115580
+ const projectDir = (0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(cwd, name);
115581
+ if (projectDir === cwd || (0, import_path4.basename)(cwd) === name) {
115582
+ } else {
115583
+ const projectName = (0, import_path4.basename)(name);
115584
+ return { projectName, projectDir, inPlace: false };
115585
+ }
115586
+ }
115587
+ const parentDir = (0, import_path4.dirname)(cwd);
115588
+ const currentFolderName = (0, import_path4.basename)(cwd);
115589
+ let detectedName;
115590
+ const gitflowConfigPath = (0, import_path4.join)(cwd, ".claude", "gitflow", "config.json");
115591
+ if (await import_fs_extra3.default.pathExists(gitflowConfigPath)) {
115592
+ try {
115593
+ const config = await import_fs_extra3.default.readJson(gitflowConfigPath);
115594
+ if (config.repository?.name) {
115595
+ detectedName = config.repository.name;
115596
+ }
115597
+ } catch {
115598
+ }
115599
+ }
115600
+ if (!detectedName) {
115601
+ const bareDir = (0, import_path4.join)(parentDir, ".bare");
115602
+ if (await import_fs_extra3.default.pathExists(bareDir)) {
115603
+ detectedName = (0, import_path4.basename)(parentDir);
115604
+ }
115605
+ }
115606
+ if (!detectedName) {
115607
+ const worktreePatterns = /^(\d+-)?(?:main|master|develop|development)$/i;
115608
+ if (worktreePatterns.test(currentFolderName)) {
115609
+ detectedName = (0, import_path4.basename)(parentDir);
115610
+ } else {
115611
+ detectedName = currentFolderName;
115612
+ }
115613
+ }
115614
+ return {
115615
+ projectName: detectedName,
115616
+ projectDir: cwd,
115617
+ inPlace: true
115618
+ };
115619
+ }
115620
+ async function validateInPlaceDirectory(projectDir) {
115621
+ if (await import_fs_extra3.default.pathExists((0, import_path4.join)(projectDir, ".smartstack", "config.json"))) {
115622
+ return 'SmartStack is already initialized in this directory. Use "ss update" to update.';
115623
+ }
115624
+ const files = await import_fs_extra3.default.readdir(projectDir);
115625
+ const hasSln = files.some((f) => f.endsWith(".sln"));
115626
+ if (hasSln) {
115627
+ return "A .NET solution already exists in this directory. Cannot initialize SmartStack here.";
115628
+ }
115629
+ const srcDir = (0, import_path4.join)(projectDir, "src");
115630
+ if (await import_fs_extra3.default.pathExists(srcDir)) {
115631
+ const srcFiles = await import_fs_extra3.default.readdir(srcDir);
115632
+ const hasCsproj = srcFiles.some((f) => f.endsWith(".csproj") || import_fs_extra3.default.statSync((0, import_path4.join)(srcDir, f)).isDirectory());
115633
+ if (hasCsproj) {
115634
+ return "A src/ directory with projects already exists. Cannot initialize SmartStack here.";
115635
+ }
115636
+ }
115637
+ return void 0;
115638
+ }
115578
115639
  async function checkMcpServers() {
115579
115640
  const result = {
115580
115641
  smartstack: { installed: false },
@@ -115713,7 +115774,7 @@ async function createDualDbContextStructure(projectDir, projectName, dryRun) {
115713
115774
  }
115714
115775
  async function createBackendStructure(config, dryRun) {
115715
115776
  const { name } = config;
115716
- const projectDir = (0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name);
115777
+ const projectDir = config.projectDir ?? ((0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name));
115717
115778
  const projectName = (0, import_path4.basename)(name);
115718
115779
  const srcDir = (0, import_path4.join)(projectDir, "src");
115719
115780
  const slnPath = (0, import_path4.join)(projectDir, `${projectName}.sln`);
@@ -115905,7 +115966,7 @@ app.Run();
115905
115966
  }
115906
115967
  async function createConfigFiles(config, dryRun) {
115907
115968
  const { name } = config;
115908
- const projectDir = (0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name);
115969
+ const projectDir = config.projectDir ?? ((0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name));
115909
115970
  const projectName = (0, import_path4.basename)(name);
115910
115971
  if (dryRun) {
115911
115972
  logger.info("[DRY RUN] Would create configuration files");
@@ -116304,7 +116365,7 @@ Generated with [SmartStack CLI](https://atlashub.io/products/smartstack-cli)
116304
116365
  }
116305
116366
  async function createFrontendStructure(config, dryRun) {
116306
116367
  const { name } = config;
116307
- const projectDir = (0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name);
116368
+ const projectDir = config.projectDir ?? ((0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name));
116308
116369
  const projectName = (0, import_path4.basename)(name);
116309
116370
  const webDir = (0, import_path4.join)(projectDir, "web", `${projectName.toLowerCase()}-web`);
116310
116371
  logger.info("Creating React frontend structure...");
@@ -116649,13 +116710,21 @@ Thumbs.db
116649
116710
  }
116650
116711
  async function initializeGit(config, dryRun) {
116651
116712
  const { name } = config;
116652
- const projectDir = (0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name);
116653
- logger.info("Initializing Git repository...");
116654
- execCommand("git init", projectDir, dryRun);
116655
- execCommand("git add .", projectDir, dryRun);
116656
- execCommand('git commit -m "chore: initial SmartStack project setup"', projectDir, dryRun);
116713
+ const projectDir = config.projectDir ?? ((0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name));
116714
+ const gitDir = (0, import_path4.join)(projectDir, ".git");
116715
+ const isGitInitialized = await import_fs_extra3.default.pathExists(gitDir);
116716
+ if (isGitInitialized) {
116717
+ logger.info("Git repository already initialized, adding SmartStack files...");
116718
+ execCommand("git add .", projectDir, dryRun);
116719
+ execCommand('git commit -m "feat: initialize SmartStack project structure"', projectDir, dryRun);
116720
+ } else {
116721
+ logger.info("Initializing Git repository...");
116722
+ execCommand("git init", projectDir, dryRun);
116723
+ execCommand("git add .", projectDir, dryRun);
116724
+ execCommand('git commit -m "chore: initial SmartStack project setup"', projectDir, dryRun);
116725
+ }
116657
116726
  }
116658
- var initCommand = new Command("init").description("Initialize a new SmartStack project").argument("<name>", "Project name").option("--dry-run", "Show what would be created without actually creating").option("-y, --yes", "Skip prompts and use defaults").option("--skip-mcp-check", "Skip MCP servers verification").option("--multi-tenant", "Enable multi-tenant mode").option("--b2c", "Enable B2C (user tenant management)").option("--preview", "Use preview/prerelease versions (NuGet --prerelease + npm @next)").action(async (name, options) => {
116727
+ var initCommand = new Command("init").description("Initialize a new SmartStack project").argument("[name]", "Project name (optional, uses current folder if not provided)").option("--dry-run", "Show what would be created without actually creating").option("-y, --yes", "Skip prompts and use defaults").option("--skip-mcp-check", "Skip MCP servers verification").option("--multi-tenant", "Enable multi-tenant mode").option("--b2c", "Enable B2C (user tenant management)").option("--preview", "Use preview/prerelease versions (NuGet --prerelease + npm @next)").option("--here", "Initialize in current directory (use folder name as project name)").action(async (name, options) => {
116659
116728
  logger.header("SmartStack Project Initialization");
116660
116729
  if (!options.skipMcpCheck) {
116661
116730
  logger.info("Checking MCP servers...");
@@ -116714,8 +116783,37 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
116714
116783
  logger.error(".NET SDK not found. Please install .NET 10.0 or later.");
116715
116784
  process.exit(1);
116716
116785
  }
116717
- const projectDir = (0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name);
116718
- const projectName = (0, import_path4.basename)(name);
116786
+ const context = await detectProjectContext(name, options.here ?? false);
116787
+ const { projectName, projectDir, inPlace } = context;
116788
+ if (inPlace) {
116789
+ logger.info(`Detected project: ${source_default.cyan(projectName)}`);
116790
+ logger.info(`Directory: ${source_default.cyan(projectDir)}`);
116791
+ const inPlaceError = await validateInPlaceDirectory(projectDir);
116792
+ if (inPlaceError) {
116793
+ logger.error(inPlaceError);
116794
+ process.exit(1);
116795
+ }
116796
+ if (!options.yes) {
116797
+ const { confirm } = await lib_default.prompt([
116798
+ {
116799
+ type: "confirm",
116800
+ name: "confirm",
116801
+ message: `Initialize SmartStack project "${projectName}" in current directory?`,
116802
+ default: true
116803
+ }
116804
+ ]);
116805
+ if (!confirm) {
116806
+ logger.info("Cancelled by user.");
116807
+ process.exit(0);
116808
+ }
116809
+ }
116810
+ } else {
116811
+ if (await import_fs_extra3.default.pathExists(projectDir)) {
116812
+ logger.error(`Directory '${projectDir}' already exists.`);
116813
+ logger.info(`Tip: Use ${source_default.cyan("--here")} to initialize in the current directory instead.`);
116814
+ process.exit(1);
116815
+ }
116816
+ }
116719
116817
  const validation = validateCSharpNamespace(projectName);
116720
116818
  if (!validation.valid) {
116721
116819
  logger.error(`Invalid project name: ${validation.error}`);
@@ -116724,17 +116822,14 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
116724
116822
  }
116725
116823
  process.exit(1);
116726
116824
  }
116727
- if (await import_fs_extra3.default.pathExists(projectDir)) {
116728
- logger.error(`Directory '${projectDir}' already exists.`);
116729
- process.exit(1);
116730
- }
116731
116825
  let config;
116732
116826
  if (options.yes) {
116733
116827
  config = {
116734
- name,
116735
- nameLower: name.toLowerCase(),
116828
+ name: projectName,
116829
+ nameLower: projectName.toLowerCase(),
116736
116830
  database: "sqlserver",
116737
116831
  preview: options.preview ?? false,
116832
+ projectDir: inPlace ? projectDir : void 0,
116738
116833
  multiTenant: {
116739
116834
  enabled: options.multiTenant ?? true,
116740
116835
  enableB2C: options.b2c ?? true,
@@ -116774,10 +116869,11 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
116774
116869
  }
116775
116870
  ]);
116776
116871
  config = {
116777
- name,
116778
- nameLower: name.toLowerCase(),
116872
+ name: projectName,
116873
+ nameLower: projectName.toLowerCase(),
116779
116874
  database: "sqlserver",
116780
116875
  preview: options.preview ?? false,
116876
+ projectDir: inPlace ? projectDir : void 0,
116781
116877
  multiTenant: {
116782
116878
  enabled: answers.multiTenantEnabled ?? true,
116783
116879
  enableB2C: answers.enableB2C ?? true,
@@ -116802,7 +116898,7 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
116802
116898
  }
116803
116899
  console.log();
116804
116900
  try {
116805
- if (!dryRun) {
116901
+ if (!dryRun && !inPlace) {
116806
116902
  await import_fs_extra3.default.ensureDir(projectDir);
116807
116903
  }
116808
116904
  await createBackendStructure(config, dryRun);