@aaronshaf/ger 1.2.11 → 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 (180) hide show
  1. package/.ast-grep/rules/no-as-casting.yml +13 -0
  2. package/.claude-plugin/plugin.json +22 -0
  3. package/.github/workflows/ci-simple.yml +53 -0
  4. package/.github/workflows/ci.yml +171 -0
  5. package/.github/workflows/claude-code-review.yml +83 -0
  6. package/.github/workflows/claude.yml +50 -0
  7. package/.github/workflows/dependency-update.yml +84 -0
  8. package/.github/workflows/release.yml +166 -0
  9. package/.github/workflows/security-scan.yml +113 -0
  10. package/.github/workflows/security.yml +96 -0
  11. package/.husky/pre-commit +16 -0
  12. package/.husky/pre-push +25 -0
  13. package/.lintstagedrc.json +6 -0
  14. package/.tool-versions +1 -0
  15. package/CLAUDE.md +105 -0
  16. package/DEVELOPMENT.md +361 -0
  17. package/EXAMPLES.md +457 -0
  18. package/README.md +831 -16
  19. package/bin/ger +3 -18
  20. package/biome.json +36 -0
  21. package/bun.lock +678 -0
  22. package/bunfig.toml +8 -0
  23. package/docs/adr/0001-use-effect-for-side-effects.md +65 -0
  24. package/docs/adr/0002-use-bun-runtime.md +64 -0
  25. package/docs/adr/0003-store-credentials-in-home-directory.md +75 -0
  26. package/docs/adr/0004-use-commander-for-cli.md +76 -0
  27. package/docs/adr/0005-use-effect-schema-for-validation.md +93 -0
  28. package/docs/adr/0006-use-msw-for-api-mocking.md +89 -0
  29. package/docs/adr/0007-git-hooks-for-quality.md +94 -0
  30. package/docs/adr/0008-no-as-typecasting.md +83 -0
  31. package/docs/adr/0009-file-size-limits.md +82 -0
  32. package/docs/adr/0010-llm-friendly-xml-output.md +93 -0
  33. package/docs/adr/0011-ai-tool-strategy-pattern.md +102 -0
  34. package/docs/adr/0012-build-status-message-parsing.md +94 -0
  35. package/docs/adr/0013-git-subprocess-integration.md +98 -0
  36. package/docs/adr/0014-group-management-support.md +95 -0
  37. package/docs/adr/0015-batch-comment-processing.md +111 -0
  38. package/docs/adr/0016-flexible-change-identifiers.md +94 -0
  39. package/docs/adr/0017-git-worktree-support.md +102 -0
  40. package/docs/adr/0018-auto-install-commit-hook.md +103 -0
  41. package/docs/adr/0019-sdk-package-exports.md +95 -0
  42. package/docs/adr/0020-code-coverage-enforcement.md +105 -0
  43. package/docs/adr/0021-typescript-isolated-declarations.md +83 -0
  44. package/docs/adr/0022-biome-oxlint-tooling.md +124 -0
  45. package/docs/adr/README.md +30 -0
  46. package/docs/prd/README.md +12 -0
  47. package/docs/prd/architecture.md +325 -0
  48. package/docs/prd/commands.md +425 -0
  49. package/docs/prd/data-model.md +349 -0
  50. package/docs/prd/overview.md +124 -0
  51. package/index.ts +219 -0
  52. package/oxlint.json +24 -0
  53. package/package.json +82 -15
  54. package/scripts/check-coverage.ts +69 -0
  55. package/scripts/check-file-size.ts +38 -0
  56. package/scripts/fix-test-mocks.ts +55 -0
  57. package/skills/gerrit-workflow/SKILL.md +247 -0
  58. package/skills/gerrit-workflow/examples.md +572 -0
  59. package/skills/gerrit-workflow/reference.md +728 -0
  60. package/src/api/gerrit.ts +696 -0
  61. package/src/cli/commands/abandon.ts +65 -0
  62. package/src/cli/commands/add-reviewer.ts +156 -0
  63. package/src/cli/commands/build-status.ts +282 -0
  64. package/src/cli/commands/checkout.ts +422 -0
  65. package/src/cli/commands/comment.ts +460 -0
  66. package/src/cli/commands/comments.ts +85 -0
  67. package/src/cli/commands/diff.ts +71 -0
  68. package/src/cli/commands/extract-url.ts +266 -0
  69. package/src/cli/commands/groups-members.ts +104 -0
  70. package/src/cli/commands/groups-show.ts +169 -0
  71. package/src/cli/commands/groups.ts +137 -0
  72. package/src/cli/commands/incoming.ts +226 -0
  73. package/src/cli/commands/init.ts +164 -0
  74. package/src/cli/commands/mine.ts +115 -0
  75. package/src/cli/commands/open.ts +57 -0
  76. package/src/cli/commands/projects.ts +68 -0
  77. package/src/cli/commands/push.ts +430 -0
  78. package/src/cli/commands/rebase.ts +52 -0
  79. package/src/cli/commands/remove-reviewer.ts +123 -0
  80. package/src/cli/commands/restore.ts +50 -0
  81. package/src/cli/commands/review.ts +486 -0
  82. package/src/cli/commands/search.ts +162 -0
  83. package/src/cli/commands/setup.ts +286 -0
  84. package/src/cli/commands/show.ts +491 -0
  85. package/src/cli/commands/status.ts +35 -0
  86. package/src/cli/commands/submit.ts +108 -0
  87. package/src/cli/commands/vote.ts +119 -0
  88. package/src/cli/commands/workspace.ts +200 -0
  89. package/src/cli/index.ts +53 -0
  90. package/src/cli/register-commands.ts +659 -0
  91. package/src/cli/register-group-commands.ts +88 -0
  92. package/src/cli/register-reviewer-commands.ts +97 -0
  93. package/src/prompts/default-review.md +86 -0
  94. package/src/prompts/system-inline-review.md +135 -0
  95. package/src/prompts/system-overall-review.md +206 -0
  96. package/src/schemas/config.test.ts +245 -0
  97. package/src/schemas/config.ts +84 -0
  98. package/src/schemas/gerrit.ts +681 -0
  99. package/src/services/commit-hook.ts +314 -0
  100. package/src/services/config.test.ts +150 -0
  101. package/src/services/config.ts +250 -0
  102. package/src/services/git-worktree.ts +342 -0
  103. package/src/services/review-strategy.ts +292 -0
  104. package/src/test-utils/mock-generator.ts +138 -0
  105. package/src/utils/change-id.test.ts +98 -0
  106. package/src/utils/change-id.ts +63 -0
  107. package/src/utils/comment-formatters.ts +153 -0
  108. package/src/utils/diff-context.ts +103 -0
  109. package/src/utils/diff-formatters.ts +141 -0
  110. package/src/utils/formatters.ts +85 -0
  111. package/src/utils/git-commit.test.ts +277 -0
  112. package/src/utils/git-commit.ts +122 -0
  113. package/src/utils/index.ts +55 -0
  114. package/src/utils/message-filters.ts +26 -0
  115. package/src/utils/review-formatters.ts +89 -0
  116. package/src/utils/review-prompt-builder.ts +110 -0
  117. package/src/utils/shell-safety.ts +117 -0
  118. package/src/utils/status-indicators.ts +100 -0
  119. package/src/utils/url-parser.test.ts +271 -0
  120. package/src/utils/url-parser.ts +118 -0
  121. package/tests/abandon.test.ts +230 -0
  122. package/tests/add-reviewer.test.ts +579 -0
  123. package/tests/build-status-watch.test.ts +344 -0
  124. package/tests/build-status.test.ts +789 -0
  125. package/tests/change-id-formats.test.ts +268 -0
  126. package/tests/checkout/integration.test.ts +653 -0
  127. package/tests/checkout/parse-input.test.ts +55 -0
  128. package/tests/checkout/validation.test.ts +178 -0
  129. package/tests/comment-batch-advanced.test.ts +431 -0
  130. package/tests/comment-gerrit-api-compliance.test.ts +414 -0
  131. package/tests/comment.test.ts +708 -0
  132. package/tests/comments.test.ts +323 -0
  133. package/tests/config-service-simple.test.ts +100 -0
  134. package/tests/diff.test.ts +419 -0
  135. package/tests/extract-url.test.ts +517 -0
  136. package/tests/groups-members.test.ts +256 -0
  137. package/tests/groups-show.test.ts +323 -0
  138. package/tests/groups.test.ts +334 -0
  139. package/tests/helpers/build-status-test-setup.ts +83 -0
  140. package/tests/helpers/config-mock.ts +27 -0
  141. package/tests/incoming.test.ts +357 -0
  142. package/tests/init.test.ts +70 -0
  143. package/tests/integration/commit-hook.test.ts +246 -0
  144. package/tests/interactive-incoming.test.ts +173 -0
  145. package/tests/mine.test.ts +285 -0
  146. package/tests/mocks/msw-handlers.ts +80 -0
  147. package/tests/open.test.ts +233 -0
  148. package/tests/projects.test.ts +259 -0
  149. package/tests/rebase.test.ts +271 -0
  150. package/tests/remove-reviewer.test.ts +357 -0
  151. package/tests/restore.test.ts +237 -0
  152. package/tests/review.test.ts +135 -0
  153. package/tests/search.test.ts +712 -0
  154. package/tests/setup.test.ts +63 -0
  155. package/tests/show-auto-detect.test.ts +324 -0
  156. package/tests/show.test.ts +813 -0
  157. package/tests/status.test.ts +145 -0
  158. package/tests/submit.test.ts +316 -0
  159. package/tests/unit/commands/push.test.ts +194 -0
  160. package/tests/unit/git-branch-detection.test.ts +82 -0
  161. package/tests/unit/git-worktree.test.ts +55 -0
  162. package/tests/unit/patterns/push-patterns.test.ts +148 -0
  163. package/tests/unit/schemas/gerrit.test.ts +85 -0
  164. package/tests/unit/services/commit-hook.test.ts +132 -0
  165. package/tests/unit/services/review-strategy.test.ts +349 -0
  166. package/tests/unit/test-utils/mock-generator.test.ts +154 -0
  167. package/tests/unit/utils/comment-formatters.test.ts +415 -0
  168. package/tests/unit/utils/diff-context.test.ts +171 -0
  169. package/tests/unit/utils/diff-formatters.test.ts +165 -0
  170. package/tests/unit/utils/formatters.test.ts +411 -0
  171. package/tests/unit/utils/message-filters.test.ts +227 -0
  172. package/tests/unit/utils/shell-safety.test.ts +230 -0
  173. package/tests/unit/utils/status-indicators.test.ts +137 -0
  174. package/tests/vote.test.ts +317 -0
  175. package/tests/workspace.test.ts +295 -0
  176. package/tsconfig.json +36 -5
  177. package/src/commands/branch.ts +0 -196
  178. package/src/ger.ts +0 -22
  179. package/src/types.d.ts +0 -35
  180. package/src/utils.ts +0 -130
@@ -0,0 +1,113 @@
1
+ name: Security Scan
2
+
3
+ on:
4
+ schedule:
5
+ # Run daily at 2 AM UTC
6
+ - cron: '0 2 * * *'
7
+ workflow_dispatch: # Allow manual triggering
8
+
9
+ permissions:
10
+ contents: read
11
+ security-events: write
12
+
13
+ jobs:
14
+ dependency-scan:
15
+ name: Dependency Security Scan
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - name: Checkout code
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Setup Bun
22
+ uses: oven-sh/setup-bun@v1
23
+ with:
24
+ bun-version: "1.2.17"
25
+
26
+ - name: Cache dependencies
27
+ uses: actions/cache@v4
28
+ with:
29
+ path: |
30
+ ~/.bun/install/cache
31
+ node_modules
32
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
33
+ restore-keys: |
34
+ ${{ runner.os }}-bun-
35
+
36
+ - name: Install dependencies
37
+ run: bun install --frozen-lockfile
38
+
39
+ - name: Run security audit
40
+ run: bun audit --audit-level moderate
41
+
42
+ # Dependency review only works on PRs, so we skip it in scheduled runs
43
+
44
+ codeql-analysis:
45
+ name: CodeQL Analysis
46
+ runs-on: ubuntu-latest
47
+ permissions:
48
+ actions: read
49
+ contents: read
50
+ security-events: write
51
+ strategy:
52
+ fail-fast: false
53
+ matrix:
54
+ language: ['typescript']
55
+ steps:
56
+ - name: Checkout code
57
+ uses: actions/checkout@v4
58
+
59
+ - name: Initialize CodeQL
60
+ uses: github/codeql-action/init@v3
61
+ with:
62
+ languages: ${{ matrix.language }}
63
+ queries: +security-and-quality
64
+
65
+ - name: Setup Bun
66
+ uses: oven-sh/setup-bun@v1
67
+ with:
68
+ bun-version: "1.2.17"
69
+
70
+ - name: Cache dependencies
71
+ uses: actions/cache@v4
72
+ with:
73
+ path: |
74
+ ~/.bun/install/cache
75
+ node_modules
76
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
77
+ restore-keys: |
78
+ ${{ runner.os }}-bun-
79
+
80
+ - name: Install dependencies
81
+ run: bun install --frozen-lockfile
82
+
83
+ - name: Build for analysis
84
+ run: bun run build
85
+
86
+ - name: Perform CodeQL Analysis
87
+ uses: github/codeql-action/analyze@v3
88
+ with:
89
+ category: "/language:${{ matrix.language }}"
90
+
91
+ secret-scan:
92
+ name: Secret Scanning
93
+ runs-on: ubuntu-latest
94
+ steps:
95
+ - name: Checkout code
96
+ uses: actions/checkout@v4
97
+ with:
98
+ fetch-depth: 0
99
+
100
+ - name: Run Trivy secret scanner
101
+ uses: aquasecurity/trivy-action@master
102
+ with:
103
+ scan-type: 'fs'
104
+ scan-ref: '.'
105
+ format: 'sarif'
106
+ output: 'trivy-secrets.sarif'
107
+ scanners: 'secret'
108
+
109
+ - name: Upload Trivy scan results
110
+ uses: github/codeql-action/upload-sarif@v3
111
+ if: always()
112
+ with:
113
+ sarif_file: 'trivy-secrets.sarif'
@@ -0,0 +1,96 @@
1
+ name: Weekly Security Audit
2
+
3
+ on:
4
+ schedule:
5
+ # Run every Monday at 8:00 AM UTC
6
+ - cron: '0 8 * * 1'
7
+ workflow_dispatch: # Allow manual triggering
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ security-audit:
15
+ name: Security Audit
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - name: Checkout code
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Setup Bun
22
+ uses: oven-sh/setup-bun@v1
23
+ with:
24
+ bun-version: "1.2.17"
25
+
26
+ - name: Cache dependencies
27
+ uses: actions/cache@v4
28
+ with:
29
+ path: |
30
+ ~/.bun/install/cache
31
+ node_modules
32
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
33
+ restore-keys: |
34
+ ${{ runner.os }}-bun-
35
+
36
+ - name: Install dependencies
37
+ run: bun install --frozen-lockfile
38
+
39
+ - name: Run security audit
40
+ run: |
41
+ echo "Running security audit..."
42
+ bun audit --audit-level moderate > audit-report.txt 2>&1 || true
43
+
44
+ # Display the audit results
45
+ echo "📊 Security Audit Results:"
46
+ cat audit-report.txt
47
+
48
+ # Check if there are any vulnerabilities
49
+ if grep -q "vulnerabilities" audit-report.txt; then
50
+ echo "⚠️ Security vulnerabilities found. Please review the audit report."
51
+ # Don't fail the workflow, just report the findings
52
+ exit 0
53
+ else
54
+ echo "✅ No security vulnerabilities found."
55
+ fi
56
+
57
+ - name: Upload audit report
58
+ uses: actions/upload-artifact@v4
59
+ if: always()
60
+ with:
61
+ name: security-audit-report
62
+ path: audit-report.txt
63
+ retention-days: 30
64
+
65
+ dependency-updates:
66
+ name: Check for Dependency Updates
67
+ runs-on: ubuntu-latest
68
+ needs: security-audit
69
+ steps:
70
+ - name: Checkout code
71
+ uses: actions/checkout@v4
72
+
73
+ - name: Setup Bun
74
+ uses: oven-sh/setup-bun@v1
75
+ with:
76
+ bun-version: "1.2.17"
77
+
78
+ - name: Install dependencies
79
+ run: bun install --frozen-lockfile
80
+
81
+ - name: Check for outdated packages
82
+ run: |
83
+ echo "Checking for outdated packages..."
84
+ bun outdated > outdated-report.txt 2>&1 || true
85
+
86
+ # Display the results
87
+ echo "📦 Outdated Dependencies:"
88
+ cat outdated-report.txt
89
+
90
+ - name: Upload outdated report
91
+ uses: actions/upload-artifact@v4
92
+ if: always()
93
+ with:
94
+ name: outdated-dependencies-report
95
+ path: outdated-report.txt
96
+ retention-days: 30
@@ -0,0 +1,16 @@
1
+ # Husky pre-commit hook
2
+
3
+ # Run lint-staged
4
+ bun lint-staged
5
+
6
+ # Check file sizes
7
+ bun scripts/check-file-size.ts
8
+
9
+ # Run ast-grep to check for banned 'as' typecasting
10
+ echo "Checking for banned patterns..."
11
+ # Temporarily disabled - need to fix rule for 'as unknown as T' pattern
12
+ # ast-grep scan --rule .ast-grep/rules/no-as-casting.yml src/
13
+
14
+ # Check test coverage
15
+ echo "Checking test coverage..."
16
+ bun run test:coverage:check
@@ -0,0 +1,25 @@
1
+ # Husky pre-push hook
2
+
3
+ # Type checking
4
+ echo "Running type check..."
5
+ bun tsc --noEmit
6
+
7
+ # Run all tests with coverage and check thresholds
8
+ echo "Running tests with coverage check..."
9
+ bun run test:coverage:check
10
+
11
+ # Run linters and formatter
12
+ echo "Running linters..."
13
+ bun oxlint src/ tests/
14
+ bun biome format --write src/ tests/
15
+
16
+ # Check file sizes
17
+ echo "Checking file sizes..."
18
+ bun scripts/check-file-size.ts
19
+
20
+ # Run ast-grep to check for banned 'as' typecasting
21
+ echo "Checking for banned patterns..."
22
+ # Temporarily disabled - need to fix rule for 'as unknown as T' pattern
23
+ # ast-grep scan --rule .ast-grep/rules/no-as-casting.yml src/
24
+
25
+ # Security audit runs weekly in CI, not on every push
@@ -0,0 +1,6 @@
1
+ {
2
+ "*.ts": [
3
+ "bun oxlint",
4
+ "bun biome format --write"
5
+ ]
6
+ }
package/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ bun 1.2.17
package/CLAUDE.md ADDED
@@ -0,0 +1,105 @@
1
+ # Gerrit CLI Tool - Project Rules
2
+
3
+ ## Technology Stack
4
+ - **Runtime**: Bun
5
+ - **Language**: TypeScript with isolatedDeclarations: true
6
+ - **CLI Framework**: Ink with ink-spinner and ink-text-input
7
+ - **State Management**: Effect and Effect Schema
8
+ - **Testing**: Bun test with MSW
9
+ - **Database**: SQLite for local-first caching
10
+ - **Linting**: oxlint
11
+ - **Formatting**: Biome
12
+ - **i18n**: i18next
13
+
14
+ ## Strict Requirements
15
+
16
+ ### Code Quality
17
+ - **NO** implicit any or noExplicitAny in TypeScript
18
+ - **MUST** use isolatedDeclarations: true in tsconfig.json
19
+ - **ONLY** use .ts files (no .js/.jsx/.tsx files - this is a CLI tool)
20
+ - **NEVER** use `as` typecasting except for `as const` or `as unknown`
21
+ - **NEVER** use --no-verify flag with git commands
22
+ - **NO** files over 700 lines (block in pre-commit/pre-push)
23
+ - **WARN** for files over 500 lines (but don't block)
24
+
25
+ ### Testing & Coverage
26
+ - **ENFORCE** minimum 80% code coverage
27
+ - **RUN** all tests in pre-commit and pre-push hooks
28
+ - **USE** MSW (Mock Service Worker) for all HTTP request mocking
29
+ - **REQUIRE** meaningful integration tests for all commands that simulate full workflows
30
+ - **IMPLEMENT** both unit tests and integration tests for every command modification/addition
31
+ - **ENSURE** integration tests use realistic MSW handlers that match Gerrit API responses
32
+ - **EXCLUDE** generated code and tmp/ from coverage
33
+
34
+ ### Security
35
+ - **NEVER** commit sensitive data, API keys, or secrets
36
+ - **NEVER** expose sensitive information in error messages
37
+ - **USE** Effect Schema for all input validation
38
+ - **IMPLEMENT** SQL injection prevention
39
+
40
+ ### Development Workflow
41
+ - **RUN** type-checking in pre-commit and pre-push hooks
42
+ - **RUN** oxlint in pre-commit and pre-push hooks
43
+ - **RUN** biome formatter before commits
44
+ - **RUN** `bun run build` after making changes to ensure compilation succeeds
45
+ - **USE** ast-grep to enforce no `as` typecasting rule
46
+ - **CHECK** file sizes in pre-commit and pre-push hooks
47
+ - **EXCLUDE** generated code and tmp/ from all checks
48
+
49
+ ### Architecture Patterns
50
+ - **USE** Effect for all service implementations
51
+ - **USE** Effect Schema for all data models
52
+ - **IMPLEMENT** cache-first strategy with SQLite
53
+ - **USE** regional error boundaries for error handling
54
+ - **FOLLOW** functional programming patterns with Effect
55
+
56
+ ### Testing Requirements for Commands
57
+ - **UNIT TESTS**: Test individual functions, schemas, and utilities
58
+ - **INTEGRATION TESTS**: Test complete command flows with mocked HTTP requests
59
+ - **HTTP MOCKING**: Use MSW handlers with http.get/http.post patterns for mocking
60
+ - **SCHEMA VALIDATION**: Ensure mocks return data that validates against Effect Schemas
61
+ - **COMMAND COVERAGE**: Every command must have integration tests covering:
62
+ - Happy path execution
63
+ - Error handling (network errors, API errors, validation errors)
64
+ - Interactive UI behavior (where applicable)
65
+ - Cache behavior verification
66
+
67
+ ### Git Workflow
68
+ - **USE** conventional commit messages
69
+ - **CREATE** feature branches from main
70
+ - **NEVER** commit directly to main
71
+ - **INCLUDE** test coverage report in README.md
72
+
73
+ ### CLI Specific
74
+ - **USE** Ink components for all UI
75
+ - **IMPLEMENT** proper loading states with ink-spinner
76
+ - **USE** ink-text-input for user input
77
+ - **SUPPORT** internationalization with i18next
78
+ - **PROVIDE** helpful error messages without sensitive data
79
+
80
+ ### File Organization
81
+ - src/cli/ - Ink components and commands
82
+ - src/services/ - Effect services
83
+ - src/api/ - Gerrit API client
84
+ - src/db/ - SQLite layer
85
+ - src/schemas/ - Effect Schema definitions
86
+ - src/i18n/ - Internationalization
87
+ - tests/ - All test files
88
+ - scripts/ - Build and hook scripts
89
+ - docs/adr/ - Architecture Decision Records
90
+ - docs/prd/ - Product Requirements Documents
91
+
92
+ ### Performance
93
+ - **IMPLEMENT** efficient caching strategies
94
+ - **USE** SQLite for offline-first functionality
95
+ - **MINIMIZE** API calls through smart caching
96
+ - **OPTIMIZE** bundle size for fast CLI startup
97
+
98
+ ## Commands
99
+ - **show** - Comprehensive change information including metadata, diff, and all comments
100
+ - **comment** - Post comments with piped input support for AI integration
101
+ - **diff** - Get diffs with various formatting options
102
+ - **comments** - View all comments on a change with context
103
+ - **incoming/mine/abandon/open** - Change management commands
104
+
105
+ Remember: This is a CLI tool, not a web app. No React components, no .tsx files, no Playwright tests.