-
Notifications
You must be signed in to change notification settings - Fork 4
feat: Enhance frontmcp cli commands #118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds interactive and flag-driven scaffolding to the FrontMCP CLI create command, with per-target templates (Docker, Vercel, Lambda/SAM, Cloudflare), Redis and CI options, expanded docs, unit and e2e tests, Jest config, Verdaccio-based E2E infra, and updated CLI types/signatures. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
libs/cli/src/commands/create.ts (1)
109-202: Remove unusedupsertPackageJsonfunction.The function at lines 109–202 is never called. It was replaced by
upsertPackageJsonWithTarget(called at line 1437), but the original was not removed. Delete this dead code to reduce file size and avoid confusion.
🧹 Nitpick comments (4)
libs/cli/README.md (1)
38-43: Fix markdown formatting issues.Static analysis has identified a few formatting issues:
- Line 38: Table should be surrounded by blank lines (add a blank line before the table).
- Line 106: Use capitalized "GitHub" (
.github/→.github/directory...).- Line 158: The code block starting at line 158 should specify a language identifier (e.g.,
text` orbash`).Apply this diff to address the formatting issues:
**CLI Flags:** + | Flag | Description | Default | |------|-------------|---------| | `--yes`, `-y` | Skip prompts, use defaults | `false` |-| Cloudflare target | `frontmcp create test-app --yes --target cloudflare` | `wrangler.toml` created | -| No CI/CD | `frontmcp create test-app --yes --no-cicd` | `.github/` directory NOT created | +| Cloudflare target | `frontmcp create test-app --yes --target cloudflare` | `wrangler.toml` created | +| No CI/CD | `frontmcp create test-app --yes --no-cicd` | `.github/` directory not created | | No Redis | `frontmcp create test-app --yes --redis none` | `docker-compose.yml` has no Redis service |## Project Structure -``` +```text libs/cli/ ├── src/Also applies to: 106-106, 158-176
libs/cli/src/commands/__tests__/create.spec.ts (1)
60-125: Consider more robust assertions.The tests rely on console log string matching, which can be fragile. For file scaffolding tests, consider verifying actual file existence in the temp directory rather than relying solely on log output.
Example improvement for file scaffolding tests:
it('should create src directory with main.ts', async () => { await runCreate('my-app', { yes: true }); // Instead of just checking logs, verify the file exists const mainTsPath = path.join(tempDir, 'my-app', 'src', 'main.ts'); expect(fs.existsSync(mainTsPath)).toBe(true); });This would make tests more reliable and catch cases where files are logged but not actually created.
libs/cli/src/args.ts (1)
49-51: Consider validating enum values for--targetand--redisflags.The type assertions (
as DeploymentAdapterandas RedisSetupOption) accept any string without validation. While this is consistent with the existing--adapterhandling, invalid values like--target invalidwill pass through and may cause confusing errors downstream inrunCreate.You could add validation here or in the create command. Since the existing
--adapterflag follows the same pattern, this is a minor consistency note.libs/cli/jest.config.ts (1)
1-1: Add explicit type annotation for the configuration object.The exported configuration object lacks an explicit type annotation, which violates the strict TypeScript guidelines. Import and use the
Configtype from@jest/typesorjest.Apply this diff to add explicit typing:
+import type { Config } from '@jest/types'; + -export default { +const config: Config.InitialOptions = { displayName: '@frontmcp/cli', preset: '../../jest.preset.js', testEnvironment: 'node', testMatch: ['**/__tests__/**/*.spec.ts', '**/__tests__/**/*.test.ts'], testPathIgnorePatterns: ['/node_modules/', '/dist/'], transform: { '^.+\\.[tj]s$': [ '@swc/jest', { jsc: { target: 'es2022', parser: { syntax: 'typescript', decorators: true, dynamicImport: true, }, transform: { decoratorMetadata: true, legacyDecorator: true, }, keepClassNames: true, externalHelpers: true, loose: true, }, module: { type: 'es6', }, sourceMaps: true, swcrc: false, }, ], }, moduleFileExtensions: ['ts', 'js', 'html'], coverageDirectory: 'test-output/jest/coverage', }; + +export default config;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
docs/draft/docs/deployment/local-dev-server.mdx(2 hunks)docs/draft/docs/deployment/redis-setup.mdx(1 hunks)docs/draft/docs/deployment/serverless.mdx(3 hunks)docs/draft/docs/getting-started/installation.mdx(2 hunks)docs/draft/docs/getting-started/quickstart.mdx(3 hunks)libs/cli/.spec.swcrc(1 hunks)libs/cli/README.md(1 hunks)libs/cli/e2e/run-e2e.sh(1 hunks)libs/cli/e2e/verdaccio.config.yaml(1 hunks)libs/cli/jest.config.ts(1 hunks)libs/cli/project.json(1 hunks)libs/cli/src/__tests__/args.spec.ts(1 hunks)libs/cli/src/args.ts(3 hunks)libs/cli/src/cli.ts(3 hunks)libs/cli/src/commands/__tests__/create.spec.ts(1 hunks)libs/cli/src/commands/create.ts(4 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
libs/**
⚙️ CodeRabbit configuration file
libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).
Files:
libs/cli/README.mdlibs/cli/project.jsonlibs/cli/e2e/run-e2e.shlibs/cli/jest.config.tslibs/cli/src/args.tslibs/cli/src/cli.tslibs/cli/src/__tests__/args.spec.tslibs/cli/e2e/verdaccio.config.yamllibs/cli/src/commands/__tests__/create.spec.tslibs/cli/src/commands/create.ts
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Enable strict TypeScript mode with noanytypes without strong justification - useunknowninstead for generic type defaults
Avoid non-null assertions (!) - use proper error handling and throw specific errors instead
Use specific error classes with MCP error codes instead of generic errors
Use type parameters with constraints instead of unconstrained generics, and preferunknownoveranyfor generic type defaults
Follow the preset pattern for hierarchical configurations across the codebase
Files:
libs/cli/jest.config.tslibs/cli/src/args.tslibs/cli/src/cli.tslibs/cli/src/__tests__/args.spec.tslibs/cli/src/commands/__tests__/create.spec.tslibs/cli/src/commands/create.ts
libs/{sdk,adapters,plugins,cli}/src/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
libs/{sdk,adapters,plugins,cli}/src/**/*.ts: Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead ofunknownforexecute()andread()methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
UsegetCapabilities()for dynamic capability exposure instead of hardcoding capabilities in adapters
UsechangeScopeinstead ofscopefor change event properties to avoid confusion with the Scope class
Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows
Don't mutate rawInput in flows - use state.set() for managing flow state instead
Files:
libs/cli/src/args.tslibs/cli/src/cli.tslibs/cli/src/__tests__/args.spec.tslibs/cli/src/commands/__tests__/create.spec.tslibs/cli/src/commands/create.ts
docs/draft/docs/**
⚙️ CodeRabbit configuration file
docs/draft/docs/**: This folder holds the draft/source docs that humans are expected to edit. When authors want to add or change documentation, they should do it here. The Codex workflow uses these drafts, together with the code diff, to generate the latest docs under docs/docs/. As a reviewer: - Encourage contributors to add/update content here instead of docs/docs/. - It is fine to do structural/content feedback here (clarity, examples, etc).
Files:
docs/draft/docs/deployment/redis-setup.mdxdocs/draft/docs/deployment/serverless.mdxdocs/draft/docs/getting-started/quickstart.mdxdocs/draft/docs/getting-started/installation.mdxdocs/draft/docs/deployment/local-dev-server.mdx
docs/**
⚙️ CodeRabbit configuration file
docs/**: Repository documentation for the SDK, using MDX and hosted by Mintlify. See more specific rules for: - docs/docs/** (latest rendered docs, automation-only) - docs/v/** (archived versions, read-only) - docs/draft/docs/** (human-editable drafts) - docs/blogs/** (blogs, human edited) - docs/docs.json (Mintlify navigation)
Files:
docs/draft/docs/deployment/redis-setup.mdxdocs/draft/docs/deployment/serverless.mdxdocs/draft/docs/getting-started/quickstart.mdxdocs/draft/docs/getting-started/installation.mdxdocs/draft/docs/deployment/local-dev-server.mdx
🧠 Learnings (6)
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Use FrontMCP's TypeScript-first schema validation framework philosophy - all types should align with MCP protocol definitions
Applied to files:
libs/cli/README.mdlibs/cli/src/cli.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Use the Nx build system for all build commands (nx build sdk, nx test ast-guard, nx run-many -t test)
Applied to files:
libs/cli/project.json
📚 Learning: 2025-11-26T15:23:04.965Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-11-26T15:23:04.965Z
Learning: Applies to libs/ui/src/**/*.test.ts : Test behavior across platform configurations (OpenAI, Claude, Gemini, ngrok) where applicable
Applied to files:
libs/cli/project.jsonlibs/cli/e2e/run-e2e.shlibs/cli/jest.config.tslibs/cli/src/__tests__/args.spec.tslibs/cli/src/commands/__tests__/create.spec.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Follow the preset pattern for hierarchical configurations across the codebase
Applied to files:
libs/cli/jest.config.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.test.ts : Test all code paths including errors, constructor validation, and error class `instanceof` checks
Applied to files:
libs/cli/src/__tests__/args.spec.tslibs/cli/src/commands/__tests__/create.spec.ts
📚 Learning: 2025-11-26T15:23:04.965Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: libs/ui/CLAUDE.md:0-0
Timestamp: 2025-11-26T15:23:04.965Z
Learning: Applies to libs/ui/src/components/**/*.test.ts : Write validation tests covering invalid variant/options, unknown properties, and valid option acceptance
Applied to files:
libs/cli/src/__tests__/args.spec.tslibs/cli/src/commands/__tests__/create.spec.ts
🧬 Code graph analysis (2)
libs/cli/src/__tests__/args.spec.ts (1)
libs/cli/src/args.ts (1)
parseArgs(33-57)
libs/cli/src/commands/__tests__/create.spec.ts (1)
libs/cli/src/commands/create.ts (1)
runCreate(1633-1669)
🪛 GitHub Actions: On Push
libs/cli/src/__tests__/args.spec.ts
[warning] 1-1: ParsedArgs is defined but never used. @typescript-eslint/no-unused-vars
libs/cli/src/commands/__tests__/create.spec.ts
[error] 27-27: Unexpected empty arrow function. @typescript-eslint/no-empty-function
[error] 216-216: Unexpected empty arrow function. @typescript-eslint/no-empty-function
🪛 LanguageTool
libs/cli/README.md
[uncategorized] ~106-~106: The official name of this software platform is spelled with a capital “H”.
Context: ...e test-app --yes --no-cicd |.github/` directory NOT created ...
(GITHUB)
🪛 markdownlint-cli2 (0.18.1)
libs/cli/README.md
38-38: Tables should be surrounded by blank lines
(MD058, blanks-around-tables)
158-158: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🪛 Shellcheck (0.11.0)
libs/cli/e2e/run-e2e.sh
[warning] 49-49: i appears unused. Verify use (or export if used externally).
(SC2034)
🔇 Additional comments (18)
libs/cli/e2e/verdaccio.config.yaml (1)
1-38: LGTM!This Verdaccio configuration is well-structured for E2E testing. It correctly:
- Allows local publishing of
@frontmcp/*andfrontmcppackages without authentication- Proxies all other packages to the public npm registry
- Disables caching to ensure fresh package resolution during tests
- Uses appropriate logging and server settings
docs/draft/docs/deployment/serverless.mdx (1)
14-14: LGTM!The documentation updates accurately reflect the new CLI target scaffolding features:
- Updated table to reference
ci/template.yamlfor AWS Lambda- Added helpful Quick Start tip showing
--targetflag usage- Included target-specific tips for Lambda and Cloudflare with generated file references and deploy commands
These changes improve the developer experience by clearly showing what files are generated and how to deploy them.
Also applies to: 19-34, 138-143, 228-233
docs/draft/docs/deployment/local-dev-server.mdx (1)
32-34: LGTM!The documentation updates correctly reflect the new CLI behavior:
- Added helpful Info block explaining interactive vs non-interactive modes
- Added Docker-specific scripts section with proper references to
ci/docker-compose.yml- Clear usage examples for docker commands
These changes provide clear guidance for users working with the Docker target.
Also applies to: 66-89
docs/draft/docs/deployment/redis-setup.mdx (1)
21-36: LGTM!The documentation updates correctly reflect the new project structure with the
ci/folder:
- Updated all
docker-composecommands to referenceci/docker-compose.yml- Updated environment file reference to
ci/.env.docker- Maintained clear guidance and examples
These changes are consistent with the target-specific scaffolding introduced in this PR.
docs/draft/docs/getting-started/installation.mdx (1)
20-86: LGTM!The documentation excellently covers the new interactive create flow:
- Clear explanation of interactive vs non-interactive modes
- Comprehensive CLI flags table with descriptions and defaults
- Multiple usage examples covering common scenarios
- Accurate description of what gets generated for each target
The documentation will help users quickly understand and utilize the new CLI features.
libs/cli/project.json (1)
8-22: LGTM!The new
testandtest:e2etargets are well-configured. The test target correctly uses the Jest executor with coverage output, and the E2E target properly declares a dependency onbuildbefore executing the shell script.libs/cli/e2e/run-e2e.sh (2)
49-55: Unused loop variableiis intentional for retry logic.The shellcheck warning about
ibeing unused is a false positive—the variable serves as a loop counter for the 30-second retry timeout. You can suppress this warning if desired.
170-180: Test 6 correctly validates that--redis nonecreates a docker-compose.yml without Redis.The test logic is sound. With
--redis none, the create command generatesci/docker-compose.ymlusingTEMPLATE_DOCKER_COMPOSE_NO_REDIS, which contains only the app service with no Redis references. The grep check correctly validates this absence.libs/cli/src/cli.ts (1)
94-102: LGTM!The
createcommand correctly forwards the new flags (yes,target,redis,cicd) torunCreate. The help text updates clearly document the new options.docs/draft/docs/getting-started/quickstart.mdx (2)
46-62: LGTM!The documentation clearly explains the interactive nature of the
createcommand, the available prompts, and how to use--yesfor non-interactive mode. The deployment target options are well-documented.
372-379: Comprehensive flags reference.The Create Command Flags table accurately documents all new flags (
--yes/-y,--target,--redis,--cicd/--no-cicd) matching the implementation inargs.ts.libs/cli/src/__tests__/args.spec.ts (1)
190-209: Good test coverage for combined flags.The combined flag tests verify that multiple flags parse correctly together. This is important for ensuring the argument parser handles complex CLI invocations.
libs/cli/src/commands/create.ts (5)
1633-1651: Robust handling of non-interactive mode.The implementation correctly handles both
--yesflag and non-TTY environments for CI/CD pipelines. Flag overrides are applied properly to defaults, and a clear error message is shown when project name is missing.
1656-1668: Good error handling with proper cleanup.The interactive mode correctly uses a try/finally block to ensure
prompt.close()is called even when errors occur, preventing readline interface leaks.
40-73: Well-structured prompt utility.The
createPromptfactory provides a clean abstraction over readline withask,select, andconfirmmethods. Theselectfunction handles invalid input gracefully by falling back to the default option.
1311-1355: Deployment scaffolding handles all targets correctly.The
scaffoldDeploymentFilesfunction properly scaffolds target-specific files:
node: ci/Dockerfile, ci/docker-compose.yml, ci/.env.dockervercel: vercel.jsonlambda: ci/template.yamlcloudflare: wrangler.tomlThe
.env.examplefile adapts based on Redis configuration.
362-561: Remove unused template constants that were replaced by newer implementations.Four template constants are genuinely unused and should be removed to reduce file size:
TEMPLATE_DOCKER_COMPOSE(line 362)TEMPLATE_DOCKERFILE(line 400)TEMPLATE_ENV_DOCKER(line 448)TEMPLATE_README(line 465)Note:
TEMPLATE_ENV_EXAMPLEis actively used at line 1353 withinscaffoldDeploymentFilesand should be retained.Likely an incorrect or invalid review comment.
libs/cli/jest.config.ts (1)
11-21: > Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (4)
libs/cli/src/commands/create.ts (4)
119-467: Consider extracting templates to separate files.While inline template strings work for this CLI tool, the large number of templates (350+ lines) could benefit from extraction to separate template files or a dedicated templates module. This would improve:
- File navigability and maintainability
- Ability to test templates independently
- Separation of concerns between scaffolding logic and template content
This is a nice-to-have improvement that can be deferred if preferred.
473-503: Consider deduplicating Dockerfile templates.
TEMPLATE_DOCKERFILE_CI(lines 473-503) is nearly identical toTEMPLATE_DOCKERFILE(lines 305-335). Both define the same multi-stage Node.js build. Consider consolidating into a single template constant to reduce maintenance burden.
877-1151: README generation logic is correct.The dynamic README generation appropriately tailors content based on deployment target, Redis setup, and CI/CD preferences. While the function is lengthy (~275 lines), the logic is straightforward and easy to follow.
Optional: Consider extracting subsection generators (e.g.,
generateDockerSection,generateCICDSection) as helper functions if further customization is needed.
1258-1258: Forward reference to constant defined later.Line 1258 references
TEMPLATE_ENV_EXAMPLE_BASIC, which is defined at line 1263. While this works in JavaScript due to hoisting, it's unconventional and can reduce readability.Consider moving the
TEMPLATE_ENV_EXAMPLE_BASICdefinition (lines 1263-1267) before thescaffoldDeploymentFilesfunction for better code organization.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
libs/cli/src/__tests__/args.spec.ts(1 hunks)libs/cli/src/commands/__tests__/create.spec.ts(1 hunks)libs/cli/src/commands/create.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- libs/cli/src/commands/tests/create.spec.ts
- libs/cli/src/tests/args.spec.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Enable strict TypeScript mode with noanytypes without strong justification - useunknowninstead for generic type defaults
Avoid non-null assertions (!) - use proper error handling and throw specific errors instead
Use specific error classes with MCP error codes instead of generic errors
Use type parameters with constraints instead of unconstrained generics, and preferunknownoveranyfor generic type defaults
Follow the preset pattern for hierarchical configurations across the codebase
Files:
libs/cli/src/commands/create.ts
libs/{sdk,adapters,plugins,cli}/src/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
libs/{sdk,adapters,plugins,cli}/src/**/*.ts: Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead ofunknownforexecute()andread()methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
UsegetCapabilities()for dynamic capability exposure instead of hardcoding capabilities in adapters
UsechangeScopeinstead ofscopefor change event properties to avoid confusion with the Scope class
Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows
Don't mutate rawInput in flows - use state.set() for managing flow state instead
Files:
libs/cli/src/commands/create.ts
libs/**
⚙️ CodeRabbit configuration file
libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).
Files:
libs/cli/src/commands/create.ts
🧬 Code graph analysis (1)
libs/cli/src/commands/create.ts (4)
libs/cli/src/colors.ts (1)
c(13-13)libs/cli/src/utils/fs.ts (5)
ensureDir(82-84)fsp(96-96)isDirEmpty(86-94)readJSON(16-23)writeJSON(25-27)libs/cli/src/tsconfig.ts (1)
runInit(86-103)libs/cli/src/version.ts (1)
getSelfVersion(4-8)
🔇 Additional comments (2)
libs/cli/src/commands/create.ts (2)
14-29: LGTM! Clean type definitions for the public API.The exported types are well-structured and appropriate for the interactive scaffolding workflow. The separation between
CreateOptions(final choices) andCreateFlags(CLI flags) is clear.
1538-1574: LGTM! Well-structured entry point with proper mode handling.The
runCreatefunction correctly handles both interactive and non-interactive modes:
- Non-interactive mode uses defaults with flag overrides
- Interactive mode uses prompts with proper cleanup
- Error handling for missing project name is appropriate
- Finally block ensures readline cleanup
…ving error handling
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
libs/cli/src/commands/create.ts (2)
1348-1348: Consider documenting theprocess.chdirside effect.Calling
process.chdir(targetDir)mutates global process state. While acceptable for a CLI command, it could affect subsequent operations ifrunCreate()is called programmatically or in tests. Consider documenting this side effect in a JSDoc comment or passingtargetDirto downstream functions instead.
1551-1587: Main entry point is well-structured.The function cleanly handles both interactive and non-interactive modes, validates required inputs, and properly closes the readline interface in a
finallyblock. The logic is clear and defensive.Consider using a custom error class instead of checking
err.message === 'Project name is required'at line 1579. This makes error discrimination more robust and less prone to breaking if the error message text changes:class ProjectNameRequiredError extends Error { constructor() { super('Project name is required'); this.name = 'ProjectNameRequiredError'; } } // Then at line 1189: throw new ProjectNameRequiredError(); // And at line 1579: if (err instanceof ProjectNameRequiredError) { console.error(c('red', '\nError: Project name is required.')); process.exit(1); }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
libs/cli/src/commands/create.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Enable strict TypeScript mode with noanytypes without strong justification - useunknowninstead for generic type defaults
Avoid non-null assertions (!) - use proper error handling and throw specific errors instead
Use specific error classes with MCP error codes instead of generic errors
Use type parameters with constraints instead of unconstrained generics, and preferunknownoveranyfor generic type defaults
Follow the preset pattern for hierarchical configurations across the codebase
Files:
libs/cli/src/commands/create.ts
libs/{sdk,adapters,plugins,cli}/src/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
libs/{sdk,adapters,plugins,cli}/src/**/*.ts: Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead ofunknownforexecute()andread()methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
UsegetCapabilities()for dynamic capability exposure instead of hardcoding capabilities in adapters
UsechangeScopeinstead ofscopefor change event properties to avoid confusion with the Scope class
Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows
Don't mutate rawInput in flows - use state.set() for managing flow state instead
Files:
libs/cli/src/commands/create.ts
libs/**
⚙️ CodeRabbit configuration file
libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).
Files:
libs/cli/src/commands/create.ts
🧠 Learnings (10)
📓 Common learnings
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Use FrontMCP's TypeScript-first schema validation framework philosophy - all types should align with MCP protocol definitions
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Avoid non-null assertions (`!`) - use proper error handling and throw specific errors instead
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Enable strict TypeScript mode with no `any` types without strong justification - use `unknown` instead for generic type defaults
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Use type parameters with constraints instead of unconstrained generics, and prefer `unknown` over `any` for generic type defaults
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead of `unknown` for `execute()` and `read()` methods
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Use `changeScope` instead of `scope` for change event properties to avoid confusion with the Scope class
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.test.ts : Test all code paths including errors, constructor validation, and error class `instanceof` checks
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Use FrontMCP's TypeScript-first schema validation framework philosophy - all types should align with MCP protocol definitions
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Ensure all TypeScript builds complete without warnings and all tests pass with 100% pass rate before committing code
Applied to files:
libs/cli/src/commands/create.ts
🧬 Code graph analysis (1)
libs/cli/src/commands/create.ts (4)
libs/cli/src/colors.ts (1)
c(13-13)libs/cli/src/utils/fs.ts (5)
ensureDir(82-84)fsp(96-96)isDirEmpty(86-94)readJSON(16-23)writeJSON(25-27)libs/cli/src/tsconfig.ts (1)
runInit(86-103)libs/cli/src/version.ts (1)
getSelfVersion(4-8)
🔇 Additional comments (5)
libs/cli/src/commands/create.ts (5)
10-42: Well-typed interfaces and exports.The type definitions follow strict TypeScript practices with no
anytypes and proper use ofunknownfor the index signature inPackageJson. Exporting these types supports programmatic usage and maintains API clarity.
53-86: Interactive prompt utility looks solid.The
selectmethod at line 73 now includes the!isNaN(idx)guard that was flagged in past reviews, ensuring robust handling of non-numeric user input. The prompt wrapper is clean and defensively coded.
1332-1338: Proper error handling with type guards.The catch block now correctly uses
unknownand applies a type guard before accessing thecodeproperty. This addresses the past review comment about avoidinganytypes.
1437-1445: Good use of typed interfaces.The function now uses the
PackageJsoninterface instead ofany, addressing the past review comment. This provides proper type safety when reading and merging package.json files.
1533-1541: Dependency merging is correct.The logic correctly ensures that base
@frontmcp/*dependencies overwrite any existing versions, keeping the scaffolded project in sync with the CLI version. This is the appropriate precedence for framework dependencies.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
libs/cli/src/commands/create.ts (3)
890-1164: LGTM! Dynamic README generation works well.The
generateReadmefunction correctly generates target-specific documentation. While the function is large (274 lines), the sequential string-building logic is clear and maintainable.Optionally, consider extracting subsections (deployment instructions, CI/CD docs, etc.) into smaller helper functions to improve modularity, though the current implementation is acceptable.
1269-1273: Move constant definition before first use.Line 1271 references
TEMPLATE_ENV_EXAMPLE_BASICbefore it's defined at line 1276. While JavaScript hoisting allows this, it reduces readability and could confuse maintainers.Apply this diff to define the constant before use:
+// Basic .env.example without Redis +const TEMPLATE_ENV_EXAMPLE_BASIC = ` +# Application +PORT=3000 +NODE_ENV=development +`; + async function scaffoldDeploymentFiles(targetDir: string, options: CreateOptions): Promise<void> { const { deploymentTarget, redisSetup, projectName } = options; switch (deploymentTarget) { // ... existing switch cases ... } // Always create .env.example at root const envExample = deploymentTarget === 'node' && redisSetup !== 'none' ? TEMPLATE_ENV_EXAMPLE : TEMPLATE_ENV_EXAMPLE_BASIC; await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.env.example'), envExample); } - -// Basic .env.example without Redis -const TEMPLATE_ENV_EXAMPLE_BASIC = ` -# Application -PORT=3000 -NODE_ENV=development -`;
1545-1581: LGTM! Well-structured main entry point.The
runCreatefunction cleanly handles both interactive and non-interactive modes, with proper error handling and resource cleanup in the finally block.Optionally, consider creating specific error classes (e.g.,
ProjectNameRequiredError) instead of genericErrorinstances at lines 1189 and 1574. However, for CLI-specific errors (not MCP protocol errors), the current approach is acceptable.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
libs/cli/src/commands/create.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Enable strict TypeScript mode with noanytypes without strong justification - useunknowninstead for generic type defaults
Avoid non-null assertions (!) - use proper error handling and throw specific errors instead
Use specific error classes with MCP error codes instead of generic errors
Use type parameters with constraints instead of unconstrained generics, and preferunknownoveranyfor generic type defaults
Follow the preset pattern for hierarchical configurations across the codebase
Files:
libs/cli/src/commands/create.ts
libs/{sdk,adapters,plugins,cli}/src/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
libs/{sdk,adapters,plugins,cli}/src/**/*.ts: Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead ofunknownforexecute()andread()methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
UsegetCapabilities()for dynamic capability exposure instead of hardcoding capabilities in adapters
UsechangeScopeinstead ofscopefor change event properties to avoid confusion with the Scope class
Validate hooks match their entry type and fail fast with InvalidHookFlowError for unsupported flows
Don't mutate rawInput in flows - use state.set() for managing flow state instead
Files:
libs/cli/src/commands/create.ts
libs/**
⚙️ CodeRabbit configuration file
libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).
Files:
libs/cli/src/commands/create.ts
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Use FrontMCP's TypeScript-first schema validation framework philosophy - all types should align with MCP protocol definitions
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Avoid non-null assertions (`!`) - use proper error handling and throw specific errors instead
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Enable strict TypeScript mode with no `any` types without strong justification - use `unknown` instead for generic type defaults
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.ts : Use type parameters with constraints instead of unconstrained generics, and prefer `unknown` over `any` for generic type defaults
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Return strictly typed MCP protocol responses (GetPromptResult, ReadResourceResult, etc.) instead of `unknown` for `execute()` and `read()` methods
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to libs/{sdk,adapters,plugins,cli}/src/**/*.ts : Use `changeScope` instead of `scope` for change event properties to avoid confusion with the Scope class
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Applies to **/*.test.ts : Test all code paths including errors, constructor validation, and error class `instanceof` checks
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Ensure all TypeScript builds complete without warnings and all tests pass with 100% pass rate before committing code
Applied to files:
libs/cli/src/commands/create.ts
📚 Learning: 2025-12-01T00:33:33.644Z
Learnt from: CR
Repo: agentfront/frontmcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T00:33:33.644Z
Learning: Use FrontMCP's TypeScript-first schema validation framework philosophy - all types should align with MCP protocol definitions
Applied to files:
libs/cli/src/commands/create.ts
🧬 Code graph analysis (1)
libs/cli/src/commands/create.ts (3)
libs/cli/src/colors.ts (1)
c(13-13)libs/cli/src/utils/fs.ts (5)
ensureDir(82-84)fsp(96-96)isDirEmpty(86-94)readJSON(16-23)writeJSON(25-27)libs/cli/src/version.ts (1)
getSelfVersion(4-8)
🔇 Additional comments (6)
libs/cli/src/commands/create.ts (6)
10-42: LGTM! Well-structured type definitions.The new exported types and interfaces are properly defined with strict TypeScript typing. The
PackageJsoninterface appropriately uses optional fields and an index signature for extensibility.
44-90: LGTM! Clean interactive prompt implementation.The readline-based prompt utilities are well-implemented with proper type safety and input validation. The NaN check at line 73 correctly handles non-numeric input.
132-884: LGTM! Comprehensive template coverage.The template constants cover all deployment targets (Node.js/Docker, Vercel, Lambda, Cloudflare) and include CI/CD workflows. Well-organized and maintainable.
1170-1306: LGTM! Well-structured scaffolding helpers.The helper functions (
getDefaults,collectOptions,scaffoldDeploymentFiles,scaffoldGitHubActions) are properly typed and follow a clear, modular design.
1308-1431: LGTM! Main scaffolding orchestration is solid.The
scaffoldProjectfunction properly validates directories, handles errors with correct type narrowing (line 1332), and coordinates all scaffolding steps. TheprintNextStepsfunction provides clear guidance to users.Note: Line 1348 uses
process.chdir(targetDir)which mutates global process state. This is acceptable for a CLI command but should be noted for anyone callingrunCreate()programmatically.
1437-1539: LGTM! Package.json handling with proper type safety.The function correctly uses the
PackageJsoninterface throughout (addressing previous review concerns aboutanytypes). The script merging logic at lines 1515-1519 is clear and correct: base scripts are added first, then existing user scripts override them, preserving user customizations while filling in missing scripts.
Summary by CodeRabbit
New Features
Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.