Skip to content

Conversation

@frontegg-david
Copy link
Contributor

@frontegg-david frontegg-david commented Dec 14, 2025

Summary by CodeRabbit

  • New Features

    • Interactive create flow with prompts for project name, deployment target (Docker, Vercel, Lambda, Cloudflare), Redis setup, and CI/CD; non‑interactive flags (--yes/-y, --target, --redis, --cicd/--no-cicd).
    • Added Docker helper scripts/docs for bring-up, build, and teardown commands.
  • Documentation

    • Updated installation, quickstart, and deployment guides to show interactive flow, per-target scaffolds, generated configs, and CLI flag usage.
    • Added a comprehensive CLI README.
  • Tests

    • Added unit and end‑to‑end test suites and test config to validate CLI parsing and scaffolding.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 14, 2025

Walkthrough

Adds 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

Cohort / File(s) Summary
Docs: Deployment & Getting Started
docs/draft/docs/deployment/local-dev-server.mdx, docs/draft/docs/deployment/redis-setup.mdx, docs/draft/docs/deployment/serverless.mdx, docs/draft/docs/getting-started/installation.mdx, docs/draft/docs/getting-started/quickstart.mdx
Surface interactive frontmcp create behavior and new flags (--yes, --target, --redis, --cicd/--no-cicd), reference target-specific generated files (docker, ci/.env.docker, vercel.json, ci/template.yaml, wrangler.toml), add Docker script examples, rework quickstart/project trees and troubleshooting.
CLI package: README & test config
libs/cli/README.md, libs/cli/jest.config.ts, libs/cli/project.json
Add package README, Jest configuration for the CLI package, and Nx targets test (jest) and test:e2e (runs E2E script).
E2E infra: Verdaccio & runner
libs/cli/e2e/run-e2e.sh, libs/cli/e2e/verdaccio.config.yaml
New E2E script to build workspace packages, run a local Verdaccio registry, publish packages, create test projects across targets, verify generated files and installs; add Verdaccio config for tests.
CLI: Argument parsing & surface
libs/cli/src/args.ts, libs/cli/src/cli.ts
Add RedisSetupOption type and new parsed flags (yes, target, redis, cicd), make create name optional (interactive), extend help/examples, and forward flags into runCreate.
Create command: scaffolding & API
libs/cli/src/commands/create.ts
Major rewrite: interactive prompts and non-interactive flags, new exported types/interfaces (DeploymentTarget, RedisSetup, CreateOptions, CreateFlags), per-target scaffolding helpers and templates (Docker, docker-compose, vercel.json, SAM template, wrangler.toml, GitHub Actions), updated runCreate(projectArg?, flags?) signature.
Tests: unit & create tests
libs/cli/src/__tests__/args.spec.ts, libs/cli/src/commands/__tests__/create.spec.ts
Add comprehensive unit tests for argument parsing and create command behaviors (interactive and non-interactive flows), file-scaffolding assertions, and name sanitization checks.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Focus review on: libs/cli/src/commands/create.ts (prompt flows, target templates, file writes, package.json handling).
  • Review libs/cli/e2e/run-e2e.sh and libs/cli/e2e/verdaccio.config.yaml for robustness, race conditions, and cleanup.
  • Verify CLI wiring and types in libs/cli/src/args.ts, libs/cli/src/cli.ts, and related tests (__tests__).

Possibly related PRs

Poem

🐇 I hopped through prompts and flags tonight,

Docker, Vercel, Lambda — choose the light.
Templates stitched, workflows spun with care,
Tests and Verdaccio danced in the air.
A tidy scaffold — hop! — and projects everywhere.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.05% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'feat: Enhance frontmcp cli commands' is vague and generic. It uses the non-descriptive term 'Enhance' without conveying what specific enhancements were made to the CLI. Consider a more specific title that highlights the key enhancement, such as 'feat: Add interactive prompts and deployment target scaffolding to create command' or 'feat: Support interactive mode and multiple deployment targets in CLI'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch enhance-cli

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 unused upsertPackageJson function.

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:

  1. Line 38: Table should be surrounded by blank lines (add a blank line before the table).
  2. Line 106: Use capitalized "GitHub" (.github/.github/ directory...).
  3. Line 158: The code block starting at line 158 should specify a language identifier (e.g., text` or bash`).

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 --target and --redis flags.

The type assertions (as DeploymentAdapter and as RedisSetupOption) accept any string without validation. While this is consistent with the existing --adapter handling, invalid values like --target invalid will pass through and may cause confusing errors downstream in runCreate.

You could add validation here or in the create command. Since the existing --adapter flag 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 Config type from @jest/types or jest.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 49a9f11 and 24e4c7d.

📒 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.md
  • libs/cli/project.json
  • libs/cli/e2e/run-e2e.sh
  • libs/cli/jest.config.ts
  • libs/cli/src/args.ts
  • libs/cli/src/cli.ts
  • libs/cli/src/__tests__/args.spec.ts
  • libs/cli/e2e/verdaccio.config.yaml
  • libs/cli/src/commands/__tests__/create.spec.ts
  • libs/cli/src/commands/create.ts
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Enable strict TypeScript mode with no any types without strong justification - use unknown instead 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 prefer unknown over any for generic type defaults
Follow the preset pattern for hierarchical configurations across the codebase

Files:

  • libs/cli/jest.config.ts
  • libs/cli/src/args.ts
  • libs/cli/src/cli.ts
  • libs/cli/src/__tests__/args.spec.ts
  • libs/cli/src/commands/__tests__/create.spec.ts
  • 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 of unknown for execute() and read() methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
Use getCapabilities() for dynamic capability exposure instead of hardcoding capabilities in adapters
Use changeScope instead of scope for 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.ts
  • libs/cli/src/cli.ts
  • libs/cli/src/__tests__/args.spec.ts
  • libs/cli/src/commands/__tests__/create.spec.ts
  • libs/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.mdx
  • docs/draft/docs/deployment/serverless.mdx
  • docs/draft/docs/getting-started/quickstart.mdx
  • docs/draft/docs/getting-started/installation.mdx
  • docs/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.mdx
  • docs/draft/docs/deployment/serverless.mdx
  • docs/draft/docs/getting-started/quickstart.mdx
  • docs/draft/docs/getting-started/installation.mdx
  • docs/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.md
  • libs/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.json
  • libs/cli/e2e/run-e2e.sh
  • libs/cli/jest.config.ts
  • libs/cli/src/__tests__/args.spec.ts
  • libs/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.ts
  • libs/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.ts
  • libs/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/* and frontmcp packages 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.yaml for AWS Lambda
  • Added helpful Quick Start tip showing --target flag 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-compose commands to reference ci/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 test and test:e2e targets are well-configured. The test target correctly uses the Jest executor with coverage output, and the E2E target properly declares a dependency on build before executing the shell script.

libs/cli/e2e/run-e2e.sh (2)

49-55: Unused loop variable i is intentional for retry logic.

The shellcheck warning about i being 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 none creates a docker-compose.yml without Redis.

The test logic is sound. With --redis none, the create command generates ci/docker-compose.yml using TEMPLATE_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 create command correctly forwards the new flags (yes, target, redis, cicd) to runCreate. 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 create command, the available prompts, and how to use --yes for 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 in args.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 --yes flag 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 createPrompt factory provides a clean abstraction over readline with ask, select, and confirm methods. The select function handles invalid input gracefully by falling back to the default option.


1311-1355: Deployment scaffolding handles all targets correctly.

The scaffoldDeploymentFiles function properly scaffolds target-specific files:

  • node: ci/Dockerfile, ci/docker-compose.yml, ci/.env.docker
  • vercel: vercel.json
  • lambda: ci/template.yaml
  • cloudflare: wrangler.toml

The .env.example file 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_EXAMPLE is actively used at line 1353 within scaffoldDeploymentFiles and 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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 to TEMPLATE_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_BASIC definition (lines 1263-1267) before the scaffoldDeploymentFiles function for better code organization.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 24e4c7d and 5b6bf39.

📒 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 no any types without strong justification - use unknown instead 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 prefer unknown over any for 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 of unknown for execute() and read() methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
Use getCapabilities() for dynamic capability exposure instead of hardcoding capabilities in adapters
Use changeScope instead of scope for 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) and CreateFlags (CLI flags) is clear.


1538-1574: LGTM! Well-structured entry point with proper mode handling.

The runCreate function 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

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 the process.chdir side effect.

Calling process.chdir(targetDir) mutates global process state. While acceptable for a CLI command, it could affect subsequent operations if runCreate() is called programmatically or in tests. Consider documenting this side effect in a JSDoc comment or passing targetDir to 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 finally block. 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

📥 Commits

Reviewing files that changed from the base of the PR and between 5b6bf39 and 01fb9ba.

📒 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 no any types without strong justification - use unknown instead 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 prefer unknown over any for 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 of unknown for execute() and read() methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
Use getCapabilities() for dynamic capability exposure instead of hardcoding capabilities in adapters
Use changeScope instead of scope for 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 any types and proper use of unknown for the index signature in PackageJson. Exporting these types supports programmatic usage and maintains API clarity.


53-86: Interactive prompt utility looks solid.

The select method 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 unknown and applies a type guard before accessing the code property. This addresses the past review comment about avoiding any types.


1437-1445: Good use of typed interfaces.

The function now uses the PackageJson interface instead of any, 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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 generateReadme function 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_BASIC before 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 runCreate function 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 generic Error instances 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

📥 Commits

Reviewing files that changed from the base of the PR and between 01fb9ba and 58ccacd.

📒 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 no any types without strong justification - use unknown instead 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 prefer unknown over any for 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 of unknown for execute() and read() methods
Validate URIs per RFC 3986 at metadata level using Zod validation with custom refinements
Use getCapabilities() for dynamic capability exposure instead of hardcoding capabilities in adapters
Use changeScope instead of scope for 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 PackageJson interface 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 scaffoldProject function properly validates directories, handles errors with correct type narrowing (line 1332), and coordinates all scaffolding steps. The printNextSteps function 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 calling runCreate() programmatically.


1437-1539: LGTM! Package.json handling with proper type safety.

The function correctly uses the PackageJson interface throughout (addressing previous review concerns about any types). 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.

@frontegg-david frontegg-david merged commit e9bb89c into main Dec 14, 2025
3 checks passed
@frontegg-david frontegg-david deleted the enhance-cli branch December 14, 2025 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants