@atlashub/smartstack-cli 1.36.0 → 2.0.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.
Files changed (103) hide show
  1. package/config/mcp-defaults.json +62 -0
  2. package/dist/index.js +57 -4
  3. package/dist/index.js.map +1 -1
  4. package/dist/mcp-entry.mjs +16984 -0
  5. package/dist/mcp-entry.mjs.map +1 -0
  6. package/package.json +14 -5
  7. package/templates/agents/gitflow/start.md +5 -4
  8. package/templates/agents/mcp-healthcheck.md +15 -13
  9. package/templates/mcp-scaffolding/component.tsx.hbs +298 -0
  10. package/templates/mcp-scaffolding/controller.cs.hbs +184 -0
  11. package/templates/mcp-scaffolding/entity-extension.cs.hbs +231 -0
  12. package/templates/mcp-scaffolding/frontend/api-client.ts.hbs +116 -0
  13. package/templates/mcp-scaffolding/frontend/nav-routes.ts.hbs +133 -0
  14. package/templates/mcp-scaffolding/frontend/routes.tsx.hbs +134 -0
  15. package/templates/mcp-scaffolding/migrations/seed-roles.cs.hbs +261 -0
  16. package/templates/mcp-scaffolding/service-extension.cs.hbs +53 -0
  17. package/templates/mcp-scaffolding/tests/controller.test.cs.hbs +413 -0
  18. package/templates/mcp-scaffolding/tests/entity.test.cs.hbs +239 -0
  19. package/templates/mcp-scaffolding/tests/repository.test.cs.hbs +441 -0
  20. package/templates/mcp-scaffolding/tests/security.test.cs.hbs +442 -0
  21. package/templates/mcp-scaffolding/tests/service.test.cs.hbs +390 -0
  22. package/templates/mcp-scaffolding/tests/validator.test.cs.hbs +428 -0
  23. package/templates/ralph/README.md +3 -3
  24. package/templates/ralph/ralph.config.yaml +2 -2
  25. package/templates/skills/admin/SKILL.md +42 -0
  26. package/templates/skills/application/steps/step-01-navigation.md +226 -43
  27. package/templates/skills/application/steps/step-03-roles.md +160 -38
  28. package/templates/skills/application/steps/step-04-backend.md +109 -2
  29. package/templates/skills/application/templates-seed.md +200 -1
  30. package/templates/skills/business-analyse/_shared.md +24 -1
  31. package/templates/skills/business-analyse/questionnaire/01-context.md +4 -4
  32. package/templates/skills/business-analyse/questionnaire/02-stakeholders.md +3 -3
  33. package/templates/skills/business-analyse/questionnaire/03-scope.md +4 -4
  34. package/templates/skills/business-analyse/questionnaire/04-data.md +7 -7
  35. package/templates/skills/business-analyse/questionnaire/05-integrations.md +1 -1
  36. package/templates/skills/business-analyse/questionnaire/06-security.md +3 -3
  37. package/templates/skills/business-analyse/questionnaire/07-ui.md +1 -1
  38. package/templates/skills/business-analyse/questionnaire/08-performance.md +3 -3
  39. package/templates/skills/business-analyse/questionnaire/09-constraints.md +4 -4
  40. package/templates/skills/business-analyse/questionnaire/10-documentation.md +2 -2
  41. package/templates/skills/business-analyse/questionnaire/11-data-lifecycle.md +2 -2
  42. package/templates/skills/business-analyse/questionnaire/12-migration.md +1 -1
  43. package/templates/skills/business-analyse/questionnaire/13-cross-module.md +2 -2
  44. package/templates/skills/business-analyse/steps/step-01-discover.md +50 -25
  45. package/templates/skills/business-analyse/steps/step-05-handoff.md +133 -34
  46. package/templates/skills/cc-agent/SKILL.md +129 -0
  47. package/templates/skills/cc-agent/references/agent-frontmatter.md +213 -0
  48. package/templates/skills/cc-agent/references/permission-modes.md +102 -0
  49. package/templates/skills/cc-agent/references/tools-reference.md +144 -0
  50. package/templates/skills/cc-agent/steps/step-00-init.md +134 -0
  51. package/templates/skills/cc-agent/steps/step-01-design.md +186 -0
  52. package/templates/skills/cc-agent/steps/step-02-generate.md +204 -0
  53. package/templates/skills/cc-agent/steps/step-03-validate.md +130 -0
  54. package/templates/skills/cc-agent/templates/agent-categorized.md +67 -0
  55. package/templates/skills/cc-agent/templates/agent-standalone.md +56 -0
  56. package/templates/skills/cc-agent/templates/agent-with-skills.md +94 -0
  57. package/templates/skills/cc-audit/SKILL.md +108 -0
  58. package/templates/skills/cc-audit/references/agent-checklist.md +91 -0
  59. package/templates/skills/cc-audit/references/hook-checklist.md +110 -0
  60. package/templates/skills/cc-audit/references/skill-checklist.md +70 -0
  61. package/templates/skills/cc-audit/steps/step-00-init.md +98 -0
  62. package/templates/skills/cc-audit/steps/step-01-scan.md +142 -0
  63. package/templates/skills/cc-audit/steps/step-02-analyze.md +158 -0
  64. package/templates/skills/cc-audit/steps/step-03-report.md +142 -0
  65. package/templates/skills/cc-skill/SKILL.md +134 -0
  66. package/templates/skills/cc-skill/references/best-practices.md +167 -0
  67. package/templates/skills/cc-skill/references/frontmatter-reference.md +182 -0
  68. package/templates/skills/cc-skill/references/skill-patterns.md +199 -0
  69. package/templates/skills/cc-skill/steps/step-00-init.md +119 -0
  70. package/templates/skills/cc-skill/steps/step-01-design.md +199 -0
  71. package/templates/skills/cc-skill/steps/step-02-generate.md +145 -0
  72. package/templates/skills/cc-skill/steps/step-03-steps.md +151 -0
  73. package/templates/skills/cc-skill/steps/step-04-validate.md +124 -0
  74. package/templates/skills/cc-skill/templates/skill-forked.md +85 -0
  75. package/templates/skills/cc-skill/templates/skill-progressive.md +102 -0
  76. package/templates/skills/cc-skill/templates/skill-simple.md +75 -0
  77. package/templates/skills/cc-skill/templates/step-template.md +82 -0
  78. package/templates/skills/check-version/SKILL.md +6 -0
  79. package/templates/skills/debug/SKILL.md +4 -0
  80. package/templates/skills/documentation/SKILL.md +1 -0
  81. package/templates/skills/efcore/SKILL.md +5 -0
  82. package/templates/skills/efcore/steps/db/step-deploy.md +26 -5
  83. package/templates/skills/efcore/steps/shared/step-00-init.md +21 -7
  84. package/templates/skills/explore/SKILL.md +28 -32
  85. package/templates/skills/feature-full/SKILL.md +1 -0
  86. package/templates/skills/gitflow/SKILL.md +8 -0
  87. package/templates/skills/gitflow/steps/step-start.md +45 -10
  88. package/templates/skills/mcp/SKILL.md +38 -18
  89. package/templates/skills/quick-search/SKILL.md +8 -1
  90. package/templates/skills/ralph-loop/SKILL.md +1 -1
  91. package/templates/skills/ralph-loop/steps/step-00-init.md +8 -68
  92. package/templates/skills/ralph-loop/steps/step-04-check.md +1 -1
  93. package/templates/skills/refactor/SKILL.md +1 -0
  94. package/templates/skills/review-code/SKILL.md +7 -1
  95. package/templates/skills/ui-components/SKILL.md +31 -438
  96. package/templates/skills/ui-components/accessibility.md +170 -0
  97. package/templates/skills/ui-components/patterns/data-table.md +39 -0
  98. package/templates/skills/ui-components/patterns/entity-card.md +77 -0
  99. package/templates/skills/ui-components/patterns/grid-layout.md +91 -0
  100. package/templates/skills/ui-components/patterns/kanban.md +43 -0
  101. package/templates/skills/ui-components/style-guide.md +86 -0
  102. package/templates/skills/utils/SKILL.md +1 -0
  103. package/templates/skills/validate/SKILL.md +1 -0
@@ -0,0 +1,428 @@
1
+ {{!-- SmartStack Validator Test Template --}}
2
+ {{!-- Generates unit tests for FluentValidation validators following SmartStack conventions --}}
3
+
4
+ using FluentAssertions;
5
+ using FluentValidation.TestHelper;
6
+ using Xunit;
7
+ using {{namespace}}.Application.DTOs;
8
+ using {{namespace}}.Application.Validators;
9
+
10
+ namespace {{namespace}}.Tests.Unit.Validators;
11
+
12
+ /// <summary>
13
+ /// Unit tests for <see cref="{{name}}Validator"/>.
14
+ /// Follows SmartStack testing conventions: {Method}_When{Condition}_Should{Result}
15
+ /// </summary>
16
+ public class {{name}}ValidatorTests
17
+ {
18
+ private readonly Create{{name}}RequestValidator _createValidator;
19
+ private readonly Update{{name}}RequestValidator _updateValidator;
20
+
21
+ public {{name}}ValidatorTests()
22
+ {
23
+ _createValidator = new Create{{name}}RequestValidator();
24
+ _updateValidator = new Update{{name}}RequestValidator();
25
+ }
26
+
27
+ #region Create Request - Code Validation
28
+
29
+ [Fact]
30
+ public void CreateValidator_WhenCodeIsValid_ShouldNotHaveErrors()
31
+ {
32
+ // Arrange
33
+ var request = new Create{{name}}Request { Code = "VALID-001" };
34
+
35
+ // Act
36
+ var result = _createValidator.TestValidate(request);
37
+
38
+ // Assert
39
+ result.ShouldNotHaveValidationErrorFor(x => x.Code);
40
+ }
41
+
42
+ [Theory]
43
+ [InlineData(null)]
44
+ [InlineData("")]
45
+ [InlineData(" ")]
46
+ public void CreateValidator_WhenCodeIsNullOrEmpty_ShouldHaveError(string? invalidCode)
47
+ {
48
+ // Arrange
49
+ var request = new Create{{name}}Request { Code = invalidCode! };
50
+
51
+ // Act
52
+ var result = _createValidator.TestValidate(request);
53
+
54
+ // Assert
55
+ result.ShouldHaveValidationErrorFor(x => x.Code)
56
+ .WithErrorMessage("*required*");
57
+ }
58
+
59
+ [Fact]
60
+ public void CreateValidator_WhenCodeExceedsMaxLength_ShouldHaveError()
61
+ {
62
+ // Arrange
63
+ var request = new Create{{name}}Request
64
+ {
65
+ Code = new string('A', 101) // Exceeds 100 char limit
66
+ };
67
+
68
+ // Act
69
+ var result = _createValidator.TestValidate(request);
70
+
71
+ // Assert
72
+ result.ShouldHaveValidationErrorFor(x => x.Code)
73
+ .WithErrorMessage("*100 characters*");
74
+ }
75
+
76
+ [Theory]
77
+ [InlineData("valid-code")]
78
+ [InlineData("VALID_CODE_123")]
79
+ [InlineData("Code.With.Dots")]
80
+ public void CreateValidator_WhenCodeHasValidFormat_ShouldNotHaveErrors(string validCode)
81
+ {
82
+ // Arrange
83
+ var request = new Create{{name}}Request { Code = validCode };
84
+
85
+ // Act
86
+ var result = _createValidator.TestValidate(request);
87
+
88
+ // Assert
89
+ result.ShouldNotHaveValidationErrorFor(x => x.Code);
90
+ }
91
+
92
+ [Theory]
93
+ [InlineData("code with spaces")]
94
+ [InlineData("code<script>")]
95
+ [InlineData("code;drop")]
96
+ public void CreateValidator_WhenCodeHasInvalidCharacters_ShouldHaveError(string invalidCode)
97
+ {
98
+ // Arrange
99
+ var request = new Create{{name}}Request { Code = invalidCode };
100
+
101
+ // Act
102
+ var result = _createValidator.TestValidate(request);
103
+
104
+ // Assert
105
+ result.ShouldHaveValidationErrorFor(x => x.Code)
106
+ .WithErrorMessage("*invalid characters*");
107
+ }
108
+
109
+ #endregion
110
+
111
+ #region Create Request - Name Validation
112
+
113
+ [Fact]
114
+ public void CreateValidator_WhenNameIsValid_ShouldNotHaveErrors()
115
+ {
116
+ // Arrange
117
+ var request = new Create{{name}}Request
118
+ {
119
+ Code = "TEST",
120
+ Name = "Valid Name"
121
+ };
122
+
123
+ // Act
124
+ var result = _createValidator.TestValidate(request);
125
+
126
+ // Assert
127
+ result.ShouldNotHaveValidationErrorFor(x => x.Name);
128
+ }
129
+
130
+ [Fact]
131
+ public void CreateValidator_WhenNameExceedsMaxLength_ShouldHaveError()
132
+ {
133
+ // Arrange
134
+ var request = new Create{{name}}Request
135
+ {
136
+ Code = "TEST",
137
+ Name = new string('A', 256) // Exceeds 255 char limit
138
+ };
139
+
140
+ // Act
141
+ var result = _createValidator.TestValidate(request);
142
+
143
+ // Assert
144
+ result.ShouldHaveValidationErrorFor(x => x.Name)
145
+ .WithErrorMessage("*255 characters*");
146
+ }
147
+
148
+ #endregion
149
+
150
+ #region Update Request Validation
151
+
152
+ [Fact]
153
+ public void UpdateValidator_WhenValidData_ShouldNotHaveErrors()
154
+ {
155
+ // Arrange
156
+ var request = new Update{{name}}Request
157
+ {
158
+ Name = "Updated Name",
159
+ // Add other updatable properties
160
+ };
161
+
162
+ // Act
163
+ var result = _updateValidator.TestValidate(request);
164
+
165
+ // Assert
166
+ result.ShouldNotHaveAnyValidationErrors();
167
+ }
168
+
169
+ [Fact]
170
+ public void UpdateValidator_WhenOptionalFieldsAreNull_ShouldNotHaveErrors()
171
+ {
172
+ // Arrange
173
+ var request = new Update{{name}}Request
174
+ {
175
+ Name = null, // Optional field can be null
176
+ };
177
+
178
+ // Act
179
+ var result = _updateValidator.TestValidate(request);
180
+
181
+ // Assert
182
+ result.ShouldNotHaveAnyValidationErrors();
183
+ }
184
+
185
+ #endregion
186
+
187
+ #region Date Validation (if applicable)
188
+
189
+ [Fact]
190
+ public void CreateValidator_WhenStartDateIsInPast_ShouldHaveError()
191
+ {
192
+ // Arrange
193
+ var request = new Create{{name}}Request
194
+ {
195
+ Code = "TEST",
196
+ StartDate = DateTime.UtcNow.AddDays(-1)
197
+ };
198
+
199
+ // Act
200
+ var result = _createValidator.TestValidate(request);
201
+
202
+ // Assert
203
+ result.ShouldHaveValidationErrorFor(x => x.StartDate)
204
+ .WithErrorMessage("*future*");
205
+ }
206
+
207
+ [Fact]
208
+ public void CreateValidator_WhenEndDateBeforeStartDate_ShouldHaveError()
209
+ {
210
+ // Arrange
211
+ var request = new Create{{name}}Request
212
+ {
213
+ Code = "TEST",
214
+ StartDate = DateTime.UtcNow.AddDays(10),
215
+ EndDate = DateTime.UtcNow.AddDays(5)
216
+ };
217
+
218
+ // Act
219
+ var result = _createValidator.TestValidate(request);
220
+
221
+ // Assert
222
+ result.ShouldHaveValidationErrorFor(x => x.EndDate)
223
+ .WithErrorMessage("*after start date*");
224
+ }
225
+
226
+ #endregion
227
+
228
+ #region Numeric Validation (if applicable)
229
+
230
+ [Theory]
231
+ [InlineData(-1)]
232
+ [InlineData(-100)]
233
+ public void CreateValidator_WhenQuantityIsNegative_ShouldHaveError(int invalidQuantity)
234
+ {
235
+ // Arrange
236
+ var request = new Create{{name}}Request
237
+ {
238
+ Code = "TEST",
239
+ Quantity = invalidQuantity
240
+ };
241
+
242
+ // Act
243
+ var result = _createValidator.TestValidate(request);
244
+
245
+ // Assert
246
+ result.ShouldHaveValidationErrorFor(x => x.Quantity)
247
+ .WithErrorMessage("*greater than*0*");
248
+ }
249
+
250
+ [Theory]
251
+ [InlineData(0)]
252
+ [InlineData(1)]
253
+ [InlineData(1000)]
254
+ public void CreateValidator_WhenQuantityIsValid_ShouldNotHaveErrors(int validQuantity)
255
+ {
256
+ // Arrange
257
+ var request = new Create{{name}}Request
258
+ {
259
+ Code = "TEST",
260
+ Quantity = validQuantity
261
+ };
262
+
263
+ // Act
264
+ var result = _createValidator.TestValidate(request);
265
+
266
+ // Assert
267
+ result.ShouldNotHaveValidationErrorFor(x => x.Quantity);
268
+ }
269
+
270
+ #endregion
271
+
272
+ #region Email Validation (if applicable)
273
+
274
+ [Theory]
275
+ [InlineData("valid@example.com")]
276
+ [InlineData("user.name@domain.org")]
277
+ [InlineData("user+tag@example.co.uk")]
278
+ public void CreateValidator_WhenEmailIsValid_ShouldNotHaveErrors(string validEmail)
279
+ {
280
+ // Arrange
281
+ var request = new Create{{name}}Request
282
+ {
283
+ Code = "TEST",
284
+ Email = validEmail
285
+ };
286
+
287
+ // Act
288
+ var result = _createValidator.TestValidate(request);
289
+
290
+ // Assert
291
+ result.ShouldNotHaveValidationErrorFor(x => x.Email);
292
+ }
293
+
294
+ [Theory]
295
+ [InlineData("invalid")]
296
+ [InlineData("invalid@")]
297
+ [InlineData("@invalid.com")]
298
+ [InlineData("invalid@.com")]
299
+ public void CreateValidator_WhenEmailIsInvalid_ShouldHaveError(string invalidEmail)
300
+ {
301
+ // Arrange
302
+ var request = new Create{{name}}Request
303
+ {
304
+ Code = "TEST",
305
+ Email = invalidEmail
306
+ };
307
+
308
+ // Act
309
+ var result = _createValidator.TestValidate(request);
310
+
311
+ // Assert
312
+ result.ShouldHaveValidationErrorFor(x => x.Email)
313
+ .WithErrorMessage("*valid email*");
314
+ }
315
+
316
+ #endregion
317
+
318
+ #region Collection Validation (if applicable)
319
+
320
+ [Fact]
321
+ public void CreateValidator_WhenItemsCollectionIsEmpty_ShouldHaveError()
322
+ {
323
+ // Arrange
324
+ var request = new Create{{name}}Request
325
+ {
326
+ Code = "TEST",
327
+ Items = new List<string>()
328
+ };
329
+
330
+ // Act
331
+ var result = _createValidator.TestValidate(request);
332
+
333
+ // Assert
334
+ result.ShouldHaveValidationErrorFor(x => x.Items)
335
+ .WithErrorMessage("*at least one item*");
336
+ }
337
+
338
+ [Fact]
339
+ public void CreateValidator_WhenItemsExceedMaxCount_ShouldHaveError()
340
+ {
341
+ // Arrange
342
+ var request = new Create{{name}}Request
343
+ {
344
+ Code = "TEST",
345
+ Items = Enumerable.Range(1, 101).Select(i => $"Item-{i}").ToList()
346
+ };
347
+
348
+ // Act
349
+ var result = _createValidator.TestValidate(request);
350
+
351
+ // Assert
352
+ result.ShouldHaveValidationErrorFor(x => x.Items)
353
+ .WithErrorMessage("*maximum*100*");
354
+ }
355
+
356
+ #endregion
357
+
358
+ #region Cross-Field Validation
359
+
360
+ [Fact]
361
+ public void CreateValidator_WhenDependentFieldsMissing_ShouldHaveError()
362
+ {
363
+ // Arrange
364
+ var request = new Create{{name}}Request
365
+ {
366
+ Code = "TEST",
367
+ RequiresApproval = true,
368
+ ApproverEmail = null // Required when RequiresApproval is true
369
+ };
370
+
371
+ // Act
372
+ var result = _createValidator.TestValidate(request);
373
+
374
+ // Assert
375
+ result.ShouldHaveValidationErrorFor(x => x.ApproverEmail)
376
+ .WithErrorMessage("*required when*");
377
+ }
378
+
379
+ #endregion
380
+
381
+ #region Security Validation
382
+
383
+ [Theory]
384
+ [InlineData("<script>alert('xss')</script>")]
385
+ [InlineData("'; DROP TABLE Users; --")]
386
+ [InlineData("{{'{{'}}constructor{{'}}'}}")]
387
+ public void CreateValidator_WhenInputContainsMaliciousContent_ShouldHaveError(string maliciousInput)
388
+ {
389
+ // Arrange
390
+ var request = new Create{{name}}Request
391
+ {
392
+ Code = "TEST",
393
+ Description = maliciousInput
394
+ };
395
+
396
+ // Act
397
+ var result = _createValidator.TestValidate(request);
398
+
399
+ // Assert
400
+ result.ShouldHaveValidationErrorFor(x => x.Description)
401
+ .WithErrorMessage("*invalid characters*");
402
+ }
403
+
404
+ #endregion
405
+
406
+ #region Error Message Format
407
+
408
+ [Fact]
409
+ public void CreateValidator_WhenMultipleErrors_ShouldReturnAllErrors()
410
+ {
411
+ // Arrange
412
+ var request = new Create{{name}}Request
413
+ {
414
+ Code = "", // Invalid
415
+ Name = new string('A', 500), // Too long
416
+ };
417
+
418
+ // Act
419
+ var result = _createValidator.TestValidate(request);
420
+
421
+ // Assert
422
+ result.Errors.Should().HaveCountGreaterThan(1);
423
+ result.ShouldHaveValidationErrorFor(x => x.Code);
424
+ result.ShouldHaveValidationErrorFor(x => x.Name);
425
+ }
426
+
427
+ #endregion
428
+ }
@@ -27,15 +27,15 @@ Edit `ralph.config.yaml` to customize:
27
27
 
28
28
  Ralph **requires** these MCP servers to function:
29
29
 
30
- ### 1. Download MCP packages
30
+ ### 1. Install packages
31
31
  ```bash
32
- npm install -g @atlashub/smartstack-mcp
32
+ npm install -g @atlashub/smartstack-cli
33
33
  npm install -g @upstash/context7-mcp
34
34
  ```
35
35
 
36
36
  ### 2. Register in Claude Code
37
37
  ```bash
38
- claude mcp add smartstack -- npx @atlashub/smartstack-mcp
38
+ claude mcp add smartstack -- npx -p @atlashub/smartstack-cli smartstack-mcp
39
39
  claude mcp add context7 -- npx @upstash/context7-mcp
40
40
  ```
41
41
 
@@ -13,8 +13,8 @@ mcp:
13
13
  health_check: true
14
14
 
15
15
  - name: smartstack
16
- description: "SmartStack validation and scaffolding"
17
- install_command: "npm install -g @atlashub/smartstack-mcp && claude mcp add smartstack -- npx @atlashub/smartstack-mcp"
16
+ description: "SmartStack validation and scaffolding (bundled in CLI)"
17
+ install_command: "claude mcp add smartstack -- npx -p @atlashub/smartstack-cli smartstack-mcp"
18
18
  health_check: true
19
19
 
20
20
  # Behavior when MCP is unavailable
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: admin
3
+ description: Admin account management - reset passwords, manage local admin accounts
4
+ argument-hint: "<subcommand> [options]"
5
+ disable-model-invocation: true
6
+ ---
7
+
8
+ <objective>
9
+ Manage SmartStack admin accounts. Wraps the `smartstack admin` CLI command with guided workflows.
10
+
11
+ **WARNING:** This skill modifies database records directly. Always confirm before executing.
12
+ </objective>
13
+
14
+ <quick_start>
15
+ ```bash
16
+ /admin reset # Reset local admin password (guided)
17
+ /admin reset --force # Reset without confirmation
18
+ ```
19
+ </quick_start>
20
+
21
+ <workflow>
22
+
23
+ ## Subcommands
24
+
25
+ | Command | Description |
26
+ |---------|-------------|
27
+ | `/admin reset` | Reset the localAdmin account password |
28
+
29
+ ## /admin reset
30
+
31
+ 1. **Detect SmartStack.app** - Look for `.smartstack/config.json` or `SmartStack.Api/` directory
32
+ 2. **Run CLI command:**
33
+ ```bash
34
+ smartstack admin reset
35
+ ```
36
+ 3. **If `--force` flag passed:**
37
+ ```bash
38
+ smartstack admin reset --force
39
+ ```
40
+ 4. **Report result** - Show new credentials or error message
41
+
42
+ </workflow>