Skip to content

feat: add skill directory generator and CLI commands for skills management#311

Open
frontegg-david wants to merge 20 commits intorelease/1.0.xfrom
add-skills
Open

feat: add skill directory generator and CLI commands for skills management#311
frontegg-david wants to merge 20 commits intorelease/1.0.xfrom
add-skills

Conversation

@frontegg-david
Copy link
Contributor

@frontegg-david frontegg-david commented Mar 26, 2026

Summary by CodeRabbit

  • New Features

    • Added a publishable FrontMCP "skills" catalog/package and new CLI group frontmcp skills (list, search, show, install) with category/tag/bundle filters, search limits, provider selection, custom install dir; project scaffolder now supports --skills bundles and an Nx skill-dir generator.
  • Documentation

    • Large curated skills catalog with templates, usage, deployment, development, and testing guides.
  • Tests

    • New E2E CLI tests plus extensive catalog/manifest and SKILL.md validation suites.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 26, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a publishable @frontmcp/skills library and curated skills catalog, loader/manifest types and APIs, extensive SKILL.md content and templates, CLI commands (skills search/list/show/install) with TF‑IDF indexing, scaffold/Nx generator integration, parser/test coverage, and build/test/publish configuration across CLI, nx-plugin, sdk, and libs/skills.

Changes

Cohort / File(s) Summary
Skills Library Core
libs/skills/src/manifest.ts, libs/skills/src/loader.ts, libs/skills/src/index.ts, libs/skills/package.json, libs/skills/project.json, libs/skills/tsconfig*.json, libs/skills/jest.config.ts, libs/skills/eslint.config.mjs
New publishable @frontmcp/skills package: manifest types, loader/filter helpers, public exports, build/test/publish targets, TS/Jest/ESLint configs, and packaging rules (copies catalog/** into dist).
Skills Catalog & Content
libs/skills/catalog/**, libs/skills/catalog/skills-manifest.json, libs/skills/catalog/TEMPLATE.md
Adds full catalog content and 24-entry manifest plus templates. Check manifest entries for path/install/destination/bundle/enum correctness and resource flags.
SKILL.md Parsing & SDK Tests
libs/sdk/src/skill/skill-md-parser.ts, libs/sdk/src/skill/__tests__/skill-md-parser.spec.ts
Expanded SKILL.md frontmatter parsing (tools, parameters, examples, priority, visibility, kebab-case aliases), preserve unknown keys into specMetadata, and added comprehensive parser tests.
Skills Tests & Validation
libs/skills/__tests__/*
New loader and manifest validation tests asserting manifest/filesystem sync, enumerations, resource flags, install config shape, uniqueness constraints, and per-SKILL.md parsing/quality checks.
CLI: Skills Commands & Index
libs/cli/src/commands/skills/*, libs/cli/src/commands/skills/catalog.ts
Implements skills command group and subcommands (search, list, show, install) with TF‑IDF index, catalog resolution fallbacks, weighted tokenization, and metadata filters (tag, category, bundle).
CLI Integration / Scaffold
libs/cli/src/commands/scaffold/create.ts, libs/cli/src/commands/scaffold/register.ts, libs/cli/src/core/program.ts, libs/cli/src/core/__tests__/program.spec.ts
Adds --skills <bundle> option to scaffolder, wires scaffoldSkills into project creation, forwards flags in non-interactive flows, and registers skills commands in the program.
CLI E2E Helpers & Tests
apps/e2e/demo-e2e-cli-exec/e2e/helpers/exec-cli.ts, apps/e2e/demo-e2e-cli-exec/e2e/cli-skills.e2e.spec.ts
New helper to run the built CLI JS and E2E tests validating skills list/search/install behaviors, CLI output, exit codes, and filesystem side effects for installs.
Nx Plugin & Generators
libs/nx-plugin/generators.json, libs/nx-plugin/src/generators/skill-dir/**, libs/nx-plugin/src/generators/server/**, libs/nx-plugin/package.json
Adds skill-dir generator and a skills option to server generator; generator/server logic can scaffold skills into a project Tree and now depends on @frontmcp/skills. Inspect Tree copy/write and silent-failure fallbacks.
Build / Config Changes
tsconfig.base.json, libs/cli/package.json, libs/nx-plugin/package.json
Adds TS path alias @frontmcp/skills, runtime dep vectoriadb to CLI, and adds @frontmcp/skills dependency to nx-plugin; verify path mapping and dependency additions.
Documentation & Templates
libs/skills/README.md, libs/skills/catalog/** (many SKILL.md files, references, templates)
Extensive documentation and templates for skill authoring, deployment, testing, NX workflows, and generator usage—ensure docs match manifest/schema and parser behavior.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as rgba(40, 116, 240, 0.5)
    participant Catalog as rgba(34, 197, 94, 0.5)
    participant Index as rgba(236, 72, 153, 0.5)
    participant Formatter as rgba(250, 204, 21, 0.5)

    User->>CLI: frontmcp skills search "auth" --limit 5
    CLI->>Catalog: loadCatalog()
    Catalog-->>CLI: SkillManifest + catalogDir
    CLI->>Index: getSearchIndex() (lazy build if needed)
    Index->>Index: build documents from manifest
    Index-->>CLI: ranked results [{skill,score},...]
    CLI->>Formatter: format & group results
    Formatter-->>User: colorized, grouped output
Loading
sequenceDiagram
    actor User
    participant CLI as rgba(40, 116, 240, 0.5)
    participant Catalog as rgba(34, 197, 94, 0.5)
    participant Installer as rgba(99, 102, 241, 0.5)
    participant FS as rgba(148, 163, 184, 0.5)

    User->>CLI: frontmcp skills install configure-auth --provider claude --dir /tmp/x
    CLI->>Catalog: loadCatalog()
    Catalog-->>CLI: SkillManifest + catalogDir
    CLI->>Installer: installSkill(name, {provider, dir})
    Installer->>FS: verify SKILL.md exists at source
    FS-->>Installer: exists
    Installer->>FS: create target dir + copyDirRecursive(source,target)
    FS-->>Installer: files copied
    Installer-->>CLI: print success with installed path
    CLI-->>User: success message
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Poem

🐇📚 I hopped the repo, found skills to share,

Cataloged carrots with careful care.
I listed, searched, and copied each one,
Installed with joy — a job well done.
A rabbit cheers: "New skills, everyone!"

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-skills

@github-actions
Copy link
Contributor

github-actions bot commented Mar 26, 2026

Performance Test Results

Status: ✅ All tests passed

Summary

Project Tests Passed Warnings Failed Leaks
✅ demo-e2e-agents 4 4 0 0 0
✅ demo-e2e-cache 11 11 0 0 0
✅ demo-e2e-codecall 4 4 0 0 0
✅ demo-e2e-config 4 4 0 0 0
✅ demo-e2e-direct 3 3 0 0 0
✅ demo-e2e-elicitation 1 1 0 0 0
✅ demo-e2e-errors 4 4 0 0 0
✅ demo-e2e-hooks 3 3 0 0 0
✅ demo-e2e-multiapp 4 4 0 0 0
✅ demo-e2e-notifications 3 3 0 0 0
✅ demo-e2e-openapi 2 2 0 0 0
✅ demo-e2e-providers 4 4 0 0 0
✅ demo-e2e-public 4 4 0 0 0
✅ demo-e2e-redis 15 15 0 0 0
✅ demo-e2e-remember 4 4 0 0 0
✅ demo-e2e-remote 5 5 0 0 0
✅ demo-e2e-serverless 2 2 0 0 0
✅ demo-e2e-skills 15 15 0 0 0
✅ demo-e2e-standalone 2 2 0 0 0
✅ demo-e2e-transport-recreation 3 3 0 0 0
✅ demo-e2e-ui 4 4 0 0 0

Total: 101 tests across 21 projects

📊 View full report in workflow run


Generated at: 2026-03-27T11:19:44.404Z
Commit: a10f66b2

# Conflicts:
#	libs/sdk/src/elicitation/flows/elicitation-result.flow.ts
#	libs/sdk/src/transport/flows/handle.sse.flow.ts
#	libs/sdk/src/transport/flows/handle.stateless-http.flow.ts
Base automatically changed from refactor-code to release/1.0.x March 27, 2026 01:52
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: 10

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (19)
CLAUDE.md-17-17 (1)

17-17: ⚠️ Potential issue | 🟡 Minor

Clarify whether installation is current or future functionality.

Line 17 describes this as "scaffold and install tooling," while line 89 states "scaffolding and future skill installation." This inconsistency creates ambiguity about whether the installation feature is currently available or planned for the future.

📝 Suggested harmonization

If installation is not yet implemented, align the brief description:

-- **skills** (`libs/skills`) - Curated SKILL.md catalog for scaffold and install tooling
+- **skills** (`libs/skills`) - Curated SKILL.md catalog for scaffolding and future installation

If installation is implemented, remove "future" from line 89:

-- **Purpose**: Curated SKILL.md catalog for scaffolding and future skill installation
+- **Purpose**: Curated SKILL.md catalog for scaffolding and skill installation
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` at line 17, Update the CLAUDE.md wording to remove the
inconsistency: if the install feature is not yet implemented, change the brief
at "**skills** (`libs/skills`) - Curated SKILL.md catalog for scaffold and
install tooling" to say "scaffold tooling" (or similar) to match "scaffolding
and future skill installation"; otherwise, if installation is implemented,
change the phrase "scaffolding and future skill installation" to remove "future"
so both places consistently state that installation is available. Target the
"**skills** (`libs/skills`)" description and the "scaffolding and future skill
installation" phrase to ensure both lines match.
libs/skills/catalog/development/create-agent/references/llm-config.md-29-37 (1)

29-37: ⚠️ Potential issue | 🟡 Minor

Fix TypeScript syntax in code example.

Line 32 uses a semicolon instead of a comma in the object literal, which is invalid TypeScript syntax.

Proposed fix
 // From environment variable (recommended)
 apiKey: {
-  env: 'ANTHROPIC_API_KEY';
+  env: 'ANTHROPIC_API_KEY'
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/development/create-agent/references/llm-config.md` around
lines 29 - 37, The code example for the apiKey configuration contains invalid
TypeScript object literal syntax: in the apiKey object (the block starting with
"apiKey: {") there is a semicolon after 'ANTHROPIC_API_KEY' — replace that
semicolon with a comma so the object literal is valid TypeScript (i.e., ensure
the property definition uses a comma between key/value pairs and the overall
apiKey forms a valid object), keeping the two examples (env-based object and
direct string) unchanged otherwise.
libs/skills/catalog/deployment/build-for-sdk/SKILL.md-67-78 (1)

67-78: ⚠️ Potential issue | 🟡 Minor

Replace eval() in example code with a safer alternative.

Using eval(input.expression) in documentation examples can encourage unsafe patterns if developers copy this code. Consider a safer example that demonstrates the concept without security risks.

Suggested safer example
     tool({
       name: 'calculate',
-      description: 'Perform calculation',
-      inputSchema: { expression: z.string() },
+      description: 'Add two numbers',
+      inputSchema: { a: z.number(), b: z.number() },
       outputSchema: { result: z.number() },
-    })((input) => ({ result: eval(input.expression) })),
+    })((input) => ({ result: input.a + input.b })),
   ],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/deployment/build-for-sdk/SKILL.md` around lines 67 - 78,
The example uses eval(input.expression) inside the tool handler (in the
create(...) tools array) which is unsafe; replace it with a safe, demonstrative
implementation (e.g., parse and evaluate a limited expression, perform a simple
arithmetic operation, or call a dedicated safe-evaluator) so the calculate tool
shows functionality without encouraging eval. Update the tool callback (the
function passed to tool({ name: 'calculate', ... }) ) to validate
input.expression, perform only allowed operations (or use a safe-eval library),
and return the numeric result in the same { result: ... } shape.
libs/skills/catalog/plugins/create-plugin-hooks/SKILL.md-277-280 (1)

277-280: ⚠️ Potential issue | 🟡 Minor

Add language specifier to fenced code block.

The stage sequence diagram lacks a language specifier, which triggers a markdownlint warning. Consider using text or plaintext for non-code content.

📝 Suggested fix
-```
+```text
 parseInput → findTool → checkToolAuthorization → createToolCallContext
   → validateInput → execute → validateOutput → finalize
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/plugins/create-plugin-hooks/SKILL.md around lines 277 -
280, The fenced code block containing the stage sequence "parseInput → findTool
→ checkToolAuthorization → createToolCallContext → validateInput → execute →
validateOutput → finalize" should include a language specifier (e.g., text or
plaintext) to satisfy markdownlint; update the fence around that sequence in
SKILL.md to use text (or plaintext) so the block is recognized as
non-code/plain text while keeping the exact sequence content unchanged.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/testing/setup-testing/references/test-tool-unit.md-4-38 (1)</summary><blockquote>

`4-38`: _⚠️ Potential issue_ | _🟡 Minor_

**Missing `zod` import in example snippet.**

`z` is used on Line 37 but never imported, so the sample won’t run as pasted.

<details>
<summary>Proposed doc fix</summary>

```diff
 import { ToolContext } from '@frontmcp/sdk';
+import { z } from 'zod';
 import { AddTool } from '../tools/add.tool';
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/testing/setup-testing/references/test-tool-unit.md`
around lines 4 - 38, The test example uses z (in the schema variable) but never
imports it; add an import for z from 'zod' at the top of the file so the
schema.parse call in the AddTool tests works. Locate the test file referencing
ToolContext and AddTool, and add "import { z } from 'zod'" near the other
imports so the schema variable and its parse call are valid.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/setup/frontmcp-skills-usage/SKILL.md-100-118 (1)</summary><blockquote>

`100-118`: _⚠️ Potential issue_ | _🟡 Minor_

**Add a language to the directory-tree fence.**

markdownlint is already flagging this block. `text` is the usual choice for directory-tree snippets.

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/setup/frontmcp-skills-usage/SKILL.md around lines 100 -
118, The fenced directory-tree block in SKILL.md is missing a language tag, so
update the code fence that contains the project tree (the triple-backtick block
shown) to include a language indicator (use "text"), i.e. change totext
in the SKILL.md file so markdownlint no longer flags the snippet.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/config/configure-http/SKILL.md-64-72 (1)</summary><blockquote>

`64-72`: _⚠️ Potential issue_ | _🟡 Minor_

**Don't use `||` in the env-port example when `0` is valid.**

Line 66 turns `PORT=0` into `3001`, which conflicts with the random-port example on Lines 69-72. Fall back only when the variable is absent/invalid, not when it is `0`.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/config/configure-http/SKILL.md` around lines 64 - 72, The
env-port example uses Number(process.env.PORT) || 3001 which treats PORT=0 as
falsy and falls back to 3001; change it so 0 is accepted. Replace the expression
for http.port to parse the env var into a number and only fall back when it's
missing or not a valid number (e.g., const p = Number(process.env.PORT); http: {
port: Number.isNaN(p) ? 3001 : p }), keeping http.port, process.env.PORT and the
random-port example semantics intact.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/testing/setup-testing/references/test-cli-binary.md-13-27 (1)</summary><blockquote>

`13-27`: _⚠️ Potential issue_ | _🟡 Minor_

**Probe the same port the binary actually binds to.**

This example sets `PORT: '0'` on Line 14, then hits `http://localhost:3001/health` on Line 26. Those two choices conflict, so the sample can wait for startup and still probe the wrong address. Either pin the port in the test or capture the emitted listen port before checking `/health`.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/testing/setup-testing/references/test-cli-binary.md`
around lines 13 - 27, The test sets PORT: '0' when spawning the child (spawn,
BINARY, env PORT) but then probes a hardcoded http://localhost:3001/health with
fetch; change the test so the port probed matches the actual bound port: either
set a fixed port (e.g., env PORT: '3001') and keep the existing fetch URL, or
parse the listen message from child.stdout (child.stdout.on('data') that
includes 'listening') to extract the assigned port and use that dynamic port in
the fetch call to /health.
```

</details>

</blockquote></details>
<details>
<summary>libs/nx-plugin/src/generators/server/server.ts-73-83 (1)</summary><blockquote>

`73-83`: _⚠️ Potential issue_ | _🟡 Minor_

**Preserve raw bytes when copying skill resources.**

The skill contract allows `references/` and `assets/`, but Line 82 forces every file through UTF-8 decoding. That will mangle any non-text resource copied into the generated project. Copy file contents as bytes instead of text here.  

As per coding guidelines, `libs/skills/README.md`: optional subdirectories include `scripts/`, `references/`, and `assets/`.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/nx-plugin/src/generators/server/server.ts` around lines 73 - 83, The
copyDirToTree function currently reads every file with fs.readFileSync(srcPath,
'utf-8') which decodes to UTF-8 and corrupts binary assets; change the read to
fs.readFileSync(srcPath) to get a Buffer and write the raw bytes into the Tree
(preserve binary data) when calling tree.write(destPath, ...); update
copyDirToTree to read files as Buffer and pass the raw bytes so references/ and
assets/ are copied without text decoding.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/testing/setup-testing/references/test-browser-build.md-37-55 (1)</summary><blockquote>

`37-55`: _⚠️ Potential issue_ | _🟡 Minor_

**Make the Playwright example serve the built artifacts explicitly.**

This section is supposed to validate `frontmcp build --target browser`, but it only opens `http://localhost:3000` and never shows how `DIST_DIR` is being served or how the backing MCP server is started. As written, the test can pass against a dev server without covering the built bundle at all.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/testing/setup-testing/references/test-browser-build.md`
around lines 37 - 55, The tests currently just navigate to http://localhost:3000
and may hit a dev server; update the two tests ("browser MCP client loads tools"
and "browser client can call a tool") to explicitly serve the built browser
artifacts from DIST_DIR and start the backing MCP server before navigating:
invoke the build target (frontmcp build --target browser) or point to the build
output path (DIST_DIR), spawn a simple static HTTP server (or use a helper like
serveStatic/distServer) bound to a chosen port and start the MCP server process
(startMCPServer or similar helper) so the page.goto loads the built bundle, then
wait for the servers to be ready, run the Playwright interactions, and ensure
both servers are terminated/cleaned up after each test.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/testing/setup-testing/references/test-auth.md-79-86 (1)</summary><blockquote>

`79-86`: _⚠️ Potential issue_ | _🟡 Minor_

**OAuth authorization URL assertion appears incorrect.**

The `authorizationUrl` returned from `startFlow()` typically contains parameters like `client_id`, `redirect_uri`, `scope`, `state`, and `code_challenge` (for PKCE), but not `code=`. The authorization code is returned in the callback URL *after* the user authorizes, not in the initial authorization URL.

Consider updating the assertion to check for expected authorization URL parameters:

```diff
   it('should complete OAuth authorization code flow', async () => {
     const { authorizationUrl } = await mockOAuth.startFlow({
       clientId: 'test-client',
       redirectUri: 'http://localhost:3001/callback',
       scopes: ['openid', 'profile'],
     });
-    expect(authorizationUrl).toContain('code=');
+    expect(authorizationUrl).toContain('client_id=test-client');
+    expect(authorizationUrl).toContain('redirect_uri=');
   });
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/testing/setup-testing/references/test-auth.md` around
lines 79 - 86, The test's assertion is wrong: mockOAuth.startFlow() returns an
authorizationUrl that should include query parameters (e.g., response_type=code,
client_id, redirect_uri, scope, state, code_challenge) but not code=; update the
expectation in the 'should complete OAuth authorization code flow' test to
assert on those parameters instead (for example check authorizationUrl contains
'response_type=code' and 'client_id=test-client' and that redirect_uri and scope
are present/URL-encoded, or validate presence of 'state' and 'code_challenge'),
using mockOAuth.startFlow and authorizationUrl to locate the assertion to
change.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/setup/nx-workflow/SKILL.md-255-255 (1)</summary><blockquote>

`255-255`: _⚠️ Potential issue_ | _🟡 Minor_

**Add a language tag to the workspace layout code fence.**

At Line 255, use an explicit language (typically `text`) to satisfy MD040 and keep markdown lint clean.

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/setup/nx-workflow/SKILL.md at line 255, The workspace
layout code fence in SKILL.md is missing a language tag which triggers MD040;
update the opening triple-backtick fence for the "workspace layout" block to
include an explicit language (e.g., change totext) so the markdown
linter is satisfied and the block is treated as plain text.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/development/decorators-guide/SKILL.md-64-65 (1)</summary><blockquote>

`64-65`: _⚠️ Potential issue_ | _🟡 Minor_

**Use hyphenated compound adjective in table descriptions.**

At Line 64 and Line 141, “Rate limiting …” should be “Rate-limiting …” when used as a modifier.

<details>
<summary>✍️ Suggested wording tweak</summary>

```diff
-| `throttle?`     | Rate limiting config                                |
+| `throttle?`     | Rate-limiting config                                |

-| `rateLimit?`         | Rate limiting configuration                                |
+| `rateLimit?`         | Rate-limiting configuration                                |
```
</details>


Also applies to: 141-141

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/development/decorators-guide/SKILL.md` around lines 64 -
65, Update the table descriptions to use the hyphenated compound adjective
"Rate-limiting" where it's used as a modifier: change the description for the
`throttle?` entry (the table row with `throttle?`) from "Rate limiting config"
to "Rate-limiting config", and make the same change at the other occurrence
referenced (the description near `pagination?`/the second occurrence at the
later line). Ensure both instances in SKILL.md use "Rate-limiting" consistently.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/testing/setup-testing/SKILL.md-209-209 (1)</summary><blockquote>

`209-209`: _⚠️ Potential issue_ | _🟡 Minor_

**Fix fenced code blocks missing language identifiers.**

markdownlint (MD040) flags these blocks; add a language tag (e.g., `typescript` or `bash`) on the opening fences.



Also applies to: 278-278

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/testing/setup-testing/SKILL.md at line 209, The markdown
code fences around the test snippets (for example the block containing
"expect(rpc.data).toEqual({ uri: 'test://resource' });") are missing a language
tag and trigger markdownlint MD040; update those fenced code blocks (including
the one at the other mention around line with similar test) to include an
appropriate language identifier such as "typescript" (or "bash" where
applicable) on the opening ``` fence so the blocks are properly annotated.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/setup/project-structure-standalone/SKILL.md-16-16 (1)</summary><blockquote>

`16-16`: _⚠️ Potential issue_ | _🟡 Minor_

**Add explicit language identifiers to all directory-tree code fences.**

These fences should be tagged (e.g., `text`) to satisfy MD040 and keep docs lint-compliant.



Also applies to: 123-123, 145-145

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/setup/project-structure-standalone/SKILL.md at line 16,
Add explicit language identifiers to every directory-tree code fence (the
triple-backtick blocks that show folder trees) by replacing bare fences with tagged fences (e.g.,text) so the markdown linter rule MD040 passes; update
all occurrences called out in the review (the directory-tree code fences and the
two other occurrences referenced) to use a language tag like text.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/testing/setup-testing/SKILL.md-531-531 (1)</summary><blockquote>

`531-531`: _⚠️ Potential issue_ | _🟡 Minor_

**Remove the invalid `McpTestClient.builder()` reference and use the correct API.**

The document references `McpTestClient.builder()` which does not exist in the codebase. The correct API is `McpTestClient.create(config)`, which returns a fluent builder instance. Update line 531 to reflect the actual, working API.

<details>
<summary>Corrected snippet</summary>

```
- Test client builder: `McpTestClient.create(config)` — fluent API for test setup
```

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/testing/setup-testing/SKILL.md` at line 531, Update the
documentation to remove the invalid reference to McpTestClient.builder() and
instead reference the real API: replace the line mentioning "Test client
builder: `McpTestClient.builder()`" with "Test client builder:
`McpTestClient.create(config)`" and ensure the text explains that
McpTestClient.create(config) returns the fluent builder instance used for test
setup.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/deployment/deploy-to-cloudflare/SKILL.md-75-80 (1)</summary><blockquote>

`75-80`: _⚠️ Potential issue_ | _🟡 Minor_

**Add a language identifier to the fenced code block.**

Line 75 uses a bare fenced block, which triggers MD040. Please annotate it (e.g., `text`) to keep docs lint-clean.

<details>
<summary>Suggested patch</summary>

```diff
-```
+```text
 dist/
   main.js      # Your compiled server (CommonJS)
   index.js     # Cloudflare handler wrapper
 wrangler.toml  # Wrangler configuration
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/deployment/deploy-to-cloudflare/SKILL.md around lines 75

  • 80, The fenced code block that shows the deployment artifacts (the block
    containing "dist/", "main.js", "index.js", and "wrangler.toml") is missing a
    language identifier and triggers MD040; update that fenced block (the
    triple-backtick block around the dist/ listing) to include a neutral language
    tag such as text (e.g., change totext) so the markdown linter stops
    flagging it.

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/development/create-skill/SKILL.md-220-220 (1)</summary><blockquote>

`220-220`: _⚠️ Potential issue_ | _🟡 Minor_

**Add language identifiers to fenced code blocks.**

`markdownlint` MD040 is triggered on these fences; adding a language keeps docs lint clean.


<details>
<summary>✏️ Suggested patch</summary>

```diff
-```
+```text
 skills/
   coding-standards/
     SKILL.md           # Instructions with YAML frontmatter
@@
-```
+```

-```
+```text
 GET /llm.txt

 # Skills
@@
-```
+```

-```
+```text
 GET /skills

 [
@@
-```
+```
```
</details>


Also applies to: 373-373, 387-387

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/development/create-skill/SKILL.md at line 220, Several
fenced code blocks in SKILL.md (the directory tree block starting with "skills/
coding-standards/ SKILL.md", the example block containing "GET /llm.txt", and
the block containing "GET /skills") are missing language identifiers and trigger
markdownlint MD040; add a language tag (e.g., "text") to each opening so the three affected fences becometext to silence the linter and keep docs
standards consistent.


</details>

</blockquote></details>
<details>
<summary>libs/skills/__tests__/loader.spec.ts-63-66 (1)</summary><blockquote>

`63-66`: _⚠️ Potential issue_ | _🟡 Minor_

**Test name contradicts expected behavior.**

The assertion includes `'all-skill'`, so this is not an “empty” result case.


<details>
<summary>✏️ Suggested patch</summary>

```diff
-    it('should return empty for unknown target', () => {
+    it('should still include all-target skills for unknown target', () => {
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/__tests__/loader.spec.ts` around lines 63 - 66, The test case
name is misleading: update the it(...) description for the test that calls
getSkillsByTarget(skills, 'browser') so it reflects that the function returns
the fallback 'all-skill' instead of "empty". Locate the test in loader.spec.ts
that uses getSkillsByTarget and change the string from something like "should
return empty for unknown target" to a correct description such as "should return
fallback 'all-skill' for unknown target" (or alternatively adjust the
expectation if the intended behavior is different).
```

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (23)</summary><blockquote>

<details>
<summary>CLAUDE.md (1)</summary><blockquote>

`92-92`: **Consider clarifying the build customization note.**

The parenthetical "(not stock Nx lib generator)" may be unclear to developers unfamiliar with Nx library generation patterns. Consider rephrasing for broader clarity.



<details>
<summary>✏️ Suggested rephrase</summary>

```diff
-- **Build**: Custom asset-aware build that copies `catalog/**` into dist (not stock Nx lib generator)
+- **Build**: Custom build configuration that copies `catalog/**` into dist (unlike standard Nx libraries)
```

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` at line 92, Reword the Build note in CLAUDE.md to clarify the
customization: replace "- **Build**: Custom asset-aware build that copies
`catalog/**` into dist (not stock Nx lib generator)" with a clearer phrase
explaining the deviation from default Nx behavior—for example: "- **Build**:
Custom asset-aware build that copies `catalog/**` into dist; this is a bespoke
build process rather than the default Nx library generator behavior"—so remove
or expand the unclear parenthetical and explicitly state that the build differs
from Nx's standard lib generator.
```

</details>

</blockquote></details>
<details>
<summary>libs/sdk/src/skill/skill-md-parser.ts (2)</summary><blockquote>

`183-187`: **Consider using `SkillVisibility` type for visibility validation.**

The inline literal union check works at runtime, but importing the `SkillVisibility` type from `common/metadata` would align with project conventions and ensure consistency if the visibility options change.



<details>
<summary>Suggested approach</summary>

```typescript
import type { SkillVisibility } from '../common/metadata/skill.metadata';

const VALID_VISIBILITY: SkillVisibility[] = ['mcp', 'http', 'both'];

// ...

const vis = frontmatter['visibility'];
if (typeof vis === 'string' && VALID_VISIBILITY.includes(vis as SkillVisibility)) {
  result.visibility = vis as SkillVisibility;
}
```
</details>

As per coding guidelines: "Use `SkillVisibility` type from common/metadata instead of inline literal unions for visibility properties."

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/sdk/src/skill/skill-md-parser.ts` around lines 183 - 187, Replace the
inline literal check for visibility with a typed validation using the
SkillVisibility type: import type SkillVisibility from the common metadata
module, define a VALID_VISIBILITY: SkillVisibility[] array (e.g.,
['mcp','http','both']), then when reading frontmatter['visibility'] (the vis
variable) ensure it's a string and VALID_VISIBILITY.includes(vis as
SkillVisibility) before assigning to result.visibility (cast to
SkillVisibility). This keeps validation consistent with the SkillVisibility type
used across the codebase.
```

</details>

---

`149-161`: **Parameter `type` field accepts any string without validation.**

Line 157 casts the `type` field directly to `SkillParameter['type']` without validating it's a valid type value. Invalid types from YAML will pass through silently.



<details>
<summary>Proposed validation</summary>

```diff
-        if (typeof p['type'] === 'string') param.type = p['type'] as SkillParameter['type'];
+        if (typeof p['type'] === 'string') {
+          const validTypes = ['string', 'number', 'boolean', 'object', 'array'];
+          if (validTypes.includes(p['type'])) {
+            param.type = p['type'] as SkillParameter['type'];
+          }
+        }
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/sdk/src/skill/skill-md-parser.ts` around lines 149 - 161, The mapping
that builds result.parameters in skill-md-parser.ts assigns p['type'] directly
to SkillParameter['type'] without validation; update the map callback used when
creating each SkillParameter (the function that constructs const param:
SkillParameter = { name: String(p['name']) }) to validate p['type'] against the
allowed SkillParameter type values (e.g., an array of permitted strings derived
from the SkillParameter union) — only set param.type when typeof p['type'] ===
'string' && allowedTypes.includes(p['type']), otherwise omit or default the
field so invalid YAML types do not silently pass through.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/development/create-provider/SKILL.md (1)</summary><blockquote>

`176-179`: **Example uses non-null assertion instead of proper error handling.**

The documentation example uses `process.env.API_URL!` and `process.env.API_KEY!` with non-null assertions. Per coding guidelines, proper error handling should be used instead. Consider validating these values to demonstrate best practices.


<details>
<summary>📝 Suggested improvement</summary>

```diff
   async onInit() {
-    this.baseUrl = process.env.API_URL!;
-    this.apiKey = process.env.API_KEY!;
+    const baseUrl = process.env.API_URL;
+    const apiKey = process.env.API_KEY;
+    if (!baseUrl || !apiKey) {
+      throw new Error('API_URL and API_KEY environment variables are required');
+    }
+    this.baseUrl = baseUrl;
+    this.apiKey = apiKey;
   }
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/development/create-provider/SKILL.md` around lines 176 -
179, The example's onInit() uses non-null assertions for process.env.API_URL and
process.env.API_KEY which bypasses validation; update onInit() (method onInit)
to explicitly read process.env.API_URL and process.env.API_KEY into baseUrl and
apiKey, validate they are present (and optionally validate format), and throw a
clear error or return a failed initialization if missing so callers get a
descriptive failure instead of a runtime undefined; reference the onInit method
and the baseUrl and apiKey properties when making the change.
```

</details>

</blockquote></details>
<details>
<summary>libs/nx-plugin/src/generators/skill-dir/files/__name__/SKILL.md__tmpl__ (1)</summary><blockquote>

`2-4`: **Quote frontmatter values to prevent YAML parsing edge cases.**

Unquoted template values can generate invalid YAML for names/descriptions/tags containing reserved characters. Please emit quoted scalars (and normalized tag list) in the template.

<details>
<summary>♻️ Suggested template hardening</summary>

```diff
-name: <%= name %>
-description: <%= description %>
-tags: [<%= tags %>]
+name: "<%= name %>"
+description: "<%= description %>"
+tags:
+<% (tags ?? '').split(',').map((t) => t.trim()).filter(Boolean).forEach((tag) => { %>
+  - "<%= tag %>"
+<% }) %>
```
</details>



As per coding guidelines, `libs/skills/README.md` requires YAML frontmatter in `SKILL.md`, so generated metadata must remain parser-safe.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/nx-plugin/src/generators/skill-dir/files/__name__/SKILL.md__tmpl__`
around lines 2 - 4, The SKILL.md template emits unquoted frontmatter values
which can break YAML parsing for names, descriptions, or tags containing special
characters; update the template (in SKILL.md__tmpl__) so that name and
description are emitted as quoted scalars (e.g. wrap <%= name %> and <%=
description %> in quotes) and normalize/emit tags as a quoted, comma-separated
or YAML list of quoted strings (ensure <%= tags %> is rendered as a safe, quoted
list), preserving parser-safe YAML frontmatter required by
libs/skills/README.md.
```

</details>

</blockquote></details>
<details>
<summary>libs/cli/src/commands/scaffold/register.ts (1)</summary><blockquote>

`16-16`: **Use Commander choice validation for `--skills` to enforce type-safety at parse time.**

The `--skills` option currently accepts arbitrary strings with an unsafe cast (`as SkillsBundle`), bypassing validation. Use Commander's built-in `.choices()` to constrain valid values (`'recommended'`, `'minimal'`, `'full'`, `'none'`) at the parser layer, eliminating the cast and strengthening type-safety.

<details>
<summary>Suggested fix</summary>

```diff
-import { Command } from 'commander';
+import { Command, Option } from 'commander';
 import type { DeploymentTarget, RedisSetup, PackageManager, SkillsBundle } from './create.js';

 export function registerScaffoldCommands(program: Command): void {
   program
     .command('create')
     .description('Scaffold a new FrontMCP project (interactive if name omitted)')
     .argument('[name]', 'Project name')
     .option('-y, --yes', 'Use defaults (non-interactive mode)')
     .option('--target <target>', 'Deployment target: node, vercel, lambda, cloudflare')
     .option('--redis <setup>', 'Redis setup: docker, existing, none (node target only)')
     .option('--pm <pm>', 'Package manager: npm, yarn, pnpm')
     .option('--cicd', 'Enable GitHub Actions CI/CD')
     .option('--no-cicd', 'Disable GitHub Actions CI/CD')
     .option('--nx', 'Scaffold an Nx monorepo instead of standalone project')
-    .option('--skills <bundle>', 'Skills bundle: recommended, minimal, full, none (default: recommended)')
+    .addOption(
+      new Option('--skills <bundle>', 'Skills bundle: recommended, minimal, full, none (default: recommended)')
+        .choices(['recommended', 'minimal', 'full', 'none'])
+    )
     .action(
       async (
         name: string | undefined,
         options: {
           yes?: boolean;
           target?: string;
           redis?: string;
           pm?: string;
           cicd?: boolean;
           nx?: boolean;
-          skills?: string;
+          skills?: SkillsBundle;
         },
       ) => {
         const { runCreate } = await import('./create.js');
         await runCreate(name, {
           yes: options.yes,
           target: options.target as DeploymentTarget | undefined,
           redis: options.redis as RedisSetup | undefined,
           cicd: options.cicd,
           pm: options.pm as PackageManager | undefined,
           nx: options.nx,
-          skills: options.skills as SkillsBundle | undefined,
+          skills: options.skills,
         });
       },
     );
 }
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/cli/src/commands/scaffold/register.ts` at line 16, The .option('--skills
<bundle>') call accepts arbitrary strings and uses an unsafe cast; replace it
with Commander Option choices to validate at parse time: import Option from
commander (or use commander.Option) and replace the .option(...) with
.addOption(new Option('--skills <bundle>', 'Skills
bundle').choices(['recommended','minimal','full','none']).default('recommended')),
remove the unsafe cast to SkillsBundle, and update any downstream variables to
use the validated value (e.g., the parsed option name where you previously used
the cast).
```

</details>

</blockquote></details>
<details>
<summary>libs/nx-plugin/src/generators/skill-dir/schema.json (1)</summary><blockquote>

`8-14`: **Enforce kebab-case in schema (currently only documented).**

`name` is described as kebab-case, but the schema does not validate it. Add a `pattern` to fail early on invalid input.

<details>
<summary>Proposed schema tightening</summary>

```diff
     "name": {
       "type": "string",
       "description": "The skill name (kebab-case)",
+      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
       "$default": { "$source": "argv", "index": 0 },
       "x-prompt": "What name would you like for the skill?",
       "x-priority": "important"
     },
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/nx-plugin/src/generators/skill-dir/schema.json` around lines 8 - 14, The
schema's "name" property currently only documents kebab-case but doesn't
validate it; update the "name" property in
libs/nx-plugin/src/generators/skill-dir/schema.json to include a "pattern" that
enforces kebab-case (e.g. lowercase letters/numbers separated by single hyphens
such as ^[a-z0-9]+(?:-[a-z0-9]+)*$) so invalid input fails fast, and optionally
add a clear "patternErrorMessage" or "errorMessage" entry to give users a
helpful validation message.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/setup/project-structure-nx/SKILL.md (2)</summary><blockquote>

`16-52`: **Add language specifier to fenced code blocks.**

Static analysis flagged missing language identifiers. For directory trees, use `text` or `plaintext`:

```diff
-```
+```text
 my-workspace/
 ├── apps/                     # `@App` classes (one app per directory)
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/setup/project-structure-nx/SKILL.md around lines 16 -
52, The fenced directory-tree code block in SKILL.md is missing a language
specifier; update the opening triple-backticks for the directory tree (the block
containing "my-workspace/" and the tree under it) to include a language like
text or plaintext (e.g., change totext) and scan SKILL.md for any other
fenced blocks without a language specifier and add an appropriate language to
each.


</details>

---

`178-180`: **Add language specifier to dependency graph code block.**

```diff
-```
+```text
 servers/ --> apps/ --> libs/
 ```
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/setup/project-structure-nx/SKILL.md around lines 178 -
180, Update the fenced dependency-graph code block that currently shows
"servers/ --> apps/ --> libs/" so it includes a language specifier (e.g., change
the opening fence from totext or ```dot) to ensure proper syntax
highlighting and rendering; locate the block in SKILL.md containing the line
"servers/ --> apps/ --> libs/" and add the chosen language after the opening
triple backticks.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/adapters/create-adapter/SKILL.md (1)</summary><blockquote>

`73-85`: **Example code uses non-null assertion on environment variable.**

The coding guidelines specify "Use proper error handling instead of non-null assertions." While this is documentation, example code should demonstrate best practices:

```diff
 `@App`({
   name: 'MyApp',
   adapters: [
     MyApiAdapter.init({
       name: 'my-api',
       endpoint: 'https://api.example.com/schema',
-      apiKey: process.env.API_KEY!,
+      apiKey: process.env.API_KEY ?? '',
     }),
   ],
 })
```

Or better, show validation:

```typescript
const apiKey = process.env.API_KEY;
if (!apiKey) throw new Error('API_KEY environment variable is required');
```

As per coding guidelines: "Use proper error handling instead of non-null assertions."

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/adapters/create-adapter/SKILL.md` around lines 73 - 85,
Replace the non-null assertion on process.env.API_KEY in the example with
explicit runtime validation: retrieve the env var into a local const (e.g.,
apiKey), check if it's present, and throw a clear error if missing before
calling MyApiAdapter.init; then pass that validated apiKey into
MyApiAdapter.init in the MyApp `@App` adapters array so the example shows proper
error handling instead of using process.env.API_KEY! directly.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/README.md (2)</summary><blockquote>

`22-28`: **Add language specifier to skill directory format block.**

```diff
-```
+```text
 skill-name/
 ├── SKILL.md          # Required: frontmatter + instructions
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/README.md around lines 22 - 28, The README's directory example
code block lacks a language specifier; update the fenced code block around the
skill directory example (the block showing "skill-name/" and "SKILL.md") to use
a language tag (e.g., ```text) so syntax highlighters render it as plain text;
edit the README.md code fence enclosing the "skill-name/ ├── SKILL.md ..."
snippet and add the specifier immediately after the opening backticks.


</details>

---

`7-16`: **Add language specifier to directory structure code block.**

Per static analysis (MD040), fenced code blocks should specify a language:

```diff
-```
+```text
 catalog/
 ├── skills-manifest.json    # Machine-readable index of all skills
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/README.md around lines 7 - 16, Update the fenced code block that
lists the directory structure (the block beginning with and containing "catalog/ ├── skills-manifest.json ...") to include a language specifier by changing the opening fence from to text so the block becomes text and
satisfies the MD040 static analysis rule.


</details>

</blockquote></details>
<details>
<summary>libs/cli/src/commands/skills/list.ts (1)</summary><blockquote>

`12-15`: **Remove non-null assertions in filter/grouping paths.**

Lines 12, 15, and 28 use `!` where narrowing/branching can keep this fully safe and strict-typed.

<details>
<summary>Suggested patch</summary>

```diff
   if (options.tag) {
-    skills = skills.filter((s) => s.tags.includes(options.tag!));
+    const tag = options.tag;
+    skills = skills.filter((s) => s.tags.includes(tag));
   }
   if (options.bundle) {
-    skills = skills.filter((s) => s.bundle?.includes(options.bundle!));
+    const bundle = options.bundle;
+    skills = skills.filter((s) => s.bundle?.includes(bundle));
   }
@@
   const grouped = new Map<string, typeof skills>();
   for (const skill of skills) {
     const cat = skill.category;
-    if (!grouped.has(cat)) grouped.set(cat, []);
-    grouped.get(cat)!.push(skill);
+    const existing = grouped.get(cat);
+    if (existing) {
+      existing.push(skill);
+    } else {
+      grouped.set(cat, [skill]);
+    }
   }
```
</details>
   
As per coding guidelines, avoid non-null assertions and use proper error-safe handling instead of `!`.


Also applies to: 24-29

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/cli/src/commands/skills/list.ts` around lines 12 - 15, Remove the
non-null assertions by using proper narrowing and safe checks: inside the
existing conditionals that check options.tag and options.bundle, stop using
options.tag!/options.bundle! and instead rely on the branch plus safe access on
the skill fields (e.g., use s.tags?.includes(options.tag) ?? false or s.tags &&
s.tags.includes(options.tag) inside the if (options.tag) block, and similarly
s.bundle?.includes(options.bundle) for the bundle branch); apply the same
safe-access pattern to the grouping/aggregation code that currently uses
non-null assertions (references: skills variable, options.tag, options.bundle,
s.tags, s.bundle, and any group/aggregation functions in this file) so the code
is strict-typed without using "!".
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/plugins/official-plugins/SKILL.md (1)</summary><blockquote>

`433-435`: **Add language specifier to fenced code block.**

The code block showing the cache bypass header should have a language specified for consistency and proper syntax highlighting.


<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```http
 x-frontmcp-disable-cache: true
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/plugins/official-plugins/SKILL.md around lines 433 -
435, The fenced code block that shows the cache-bypass header currently lacks a
language specifier; update the block surrounding "x-frontmcp-disable-cache:
true" in SKILL.md to include a language (e.g., add ```http) so it becomes a
highlighted HTTP header block, ensuring consistency and proper syntax
highlighting.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/setup/setup-sqlite/SKILL.md (2)</summary><blockquote>

`209-213`: **Add language specifier to fenced code block.**

This code block showing WAL mode file structure should have a language identifier.


<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```text
 sessions.sqlite       # main database
 sessions.sqlite-wal   # write-ahead log
 sessions.sqlite-shm   # shared memory index
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/setup/setup-sqlite/SKILL.md around lines 209 - 213, The
fenced code block that lists the WAL-mode files (sessions.sqlite,
sessions.sqlite-wal, sessions.sqlite-shm) is missing a language specifier;
update that fenced block in SKILL.md to include a language identifier (e.g.,
change the opening totext) so the snippet is properly
highlighted/treated as plain text and ensure the closing fence remains correct.


</details>

---

`278-280`: **Add language specifier to fenced code block.**

This code block showing log output should have a language identifier for consistency.


<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```text
 [SessionStoreFactory] Creating SQLite session store
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/setup/setup-sqlite/SKILL.md around lines 278 - 280, The
fenced code block containing the log line "[SessionStoreFactory] Creating SQLite
session store" in SKILL.md should include a language specifier for consistency;
update the triple-backtick fence to include a language token (e.g., "text") so
the block reads text before the log line and closes with after it,
targeting the fenced block that contains the SessionStoreFactory log output.


</details>

</blockquote></details>
<details>
<summary>libs/sdk/src/skill/__tests__/skill-md-parser.spec.ts (1)</summary><blockquote>

`452-453`: **Avoid non-null assertions in this test assertion path.**

Prefer an explicit defined check plus optional access instead of `!`.


<details>
<summary>♻️ Suggested patch</summary>

```diff
-      expect(result.specMetadata!['author']).toBe('alice');
-      expect(result.specMetadata!['user-invocable']).toBe('true');
+      expect(result.specMetadata).toBeDefined();
+      expect(result.specMetadata?.['author']).toBe('alice');
+      expect(result.specMetadata?.['user-invocable']).toBe('true');
```
</details>
As per coding guidelines, “Use proper error handling instead of non-null assertions… rather than using non-null assertion operator (!).”

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/sdk/src/skill/__tests__/skill-md-parser.spec.ts` around lines 452 - 453,
The test uses a non-null assertion on result.specMetadata
(result.specMetadata!['author']) which violates the guideline; change it to
first assert result.specMetadata is defined (e.g.,
expect(result.specMetadata).toBeDefined()) and then access properties safely
(e.g., using optional access like result.specMetadata?.['author'] and
result.specMetadata?.['user-invocable']) when asserting their values so the test
fails clearly if specMetadata is missing instead of throwing.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/development/create-resource/SKILL.md (1)</summary><blockquote>

`388-390`: **Use a specific MCP error type in the not-found example.**

`this.fail(new Error(...))` here teaches a generic error path; for resource-not-found, show a typed MCP error with the proper code instead.


As per coding guidelines, “Create specific error classes with MCP error codes … and implement `toJsonRpcError()` method.”

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/development/create-resource/SKILL.md` around lines 388 -
390, Replace the generic new Error in the not-found branch with the MCP-specific
resource-not-found error type: construct and pass an MCP error (e.g.,
ResourceNotFound or MCPError with code "RESOURCE_NOT_FOUND") to this.fail,
include params.key in the error message/details, and ensure the MCP error
implements toJsonRpcError() so it serializes correctly when reported; update the
example around this.fail(...) (the not-found branch referencing params.key) to
use that typed error class instead of Error.
```

</details>

</blockquote></details>
<details>
<summary>libs/cli/src/commands/skills/catalog.ts (1)</summary><blockquote>

`8-9`: **Use `@frontmcp/utils` for file system operations.**

Similar to `create.ts`, this file directly imports `fs` instead of using utilities from `@frontmcp/utils`. The `readFileSync` and `existsSync` calls throughout should use the project's standardized file system utilities.



As per coding guidelines: "Use `@frontmcp/utils` for all file system operations. Do NOT use `fs/promises` or `node:fs` directly."

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/cli/src/commands/skills/catalog.ts` around lines 8 - 9, In catalog.ts
replace direct node fs usage with the project's utilities: remove the import of
'fs' (and any direct uses of fs.readFileSync / fs.existsSync) and instead import
and use the standardized file helpers from '@frontmcp/utils' (e.g.,
readFileSync, existsSync) for all file checks and reads; update any call sites
in functions inside catalog.ts that reference readFileSync or existsSync to call
the utils versions and ensure any error handling or encoding args remain
compatible (also remove or replace any direct node:fs/promises usage), keeping
path usage as needed but prefer path helpers from the utils if provided.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/development/create-skill-with-tools/SKILL.md (1)</summary><blockquote>

`218-230`: **Add language specifier to fenced code blocks.**

The directory structure and HTTP endpoint examples should specify a language identifier for markdown linting compliance.



<details>
<summary>♻️ Proposed fixes</summary>

Line 218 (directory structure):
```diff
-```
+```text
 skills/
   deploy-service/
```

Line 433 (HTTP request):
```diff
-```
+```http
 GET /llm.txt
```

Line 448 (HTTP request):
```diff
-```
+```http
 GET /skills
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/development/create-skill-with-tools/SKILL.md around
lines 218 - 230, The fenced code blocks in SKILL.md lack language specifiers;
update the directory structure block to use a text specifier (e.g., change totext) and update the HTTP examples that show requests like "GET /llm.txt"
and "GET /skills" to use the http specifier (e.g., change tohttp) so
markdown linting passes; locate the directory structure code block and the HTTP
request example blocks and add the appropriate language identifiers.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/setup/setup-redis/SKILL.md (1)</summary><blockquote>

`339-342`: **Add language specifier to fenced code block.**

The log output example should specify a language (e.g., `text` or `log`) for consistency and to satisfy markdown linting.

```diff
-```
+```text
 [SessionStoreFactory] Creating Redis session store
 [RedisStorageAdapter] Connected to Redis at localhost:6379
 ```
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/setup/setup-redis/SKILL.md around lines 339 - 342, The
fenced code block showing Redis log output needs a language specifier for
linting; update the block around the two log lines (the triple-backtick block
containing "[SessionStoreFactory] Creating Redis session store" and
"[RedisStorageAdapter] Connected to Redis at localhost:6379") to use a language
like text or log (e.g., ```text) so the code fence is explicitly typed.


</details>

</blockquote></details>
<details>
<summary>libs/skills/src/manifest.ts (2)</summary><blockquote>

`35-40`: **Add install-field validator constants to maintain consistency with other manifest fields**

The codebase exports `VALID_TARGETS`, `VALID_CATEGORIES`, and `VALID_BUNDLES` for manifest validation, but does not export equivalent constants for `SkillDestination` and `SkillMergeStrategy`. The test file `skills-validation.spec.ts` hardcodes merge strategy values `['overwrite', 'skip-existing']` instead of referencing a constant, and `libs/cli/src/commands/skills/install.ts` hardcodes destination mappings. Adding `VALID_DESTINATIONS` and `VALID_MERGE_STRATEGIES` constants would eliminate duplication and keep validation consistent with other manifest fields.

<details>
<summary>♻️ Proposed diff</summary>

```diff
 export const VALID_BUNDLES: readonly SkillBundle[] = ['recommended', 'minimal', 'full'];
+
+/** Valid install destinations for manifest validation */
+export const VALID_DESTINATIONS: readonly SkillDestination[] = [
+  'project-local',
+  '.claude/skills',
+  'codex',
+  'gemini',
+];
+
+/** Valid merge strategies for manifest validation */
+export const VALID_MERGE_STRATEGIES: readonly SkillMergeStrategy[] = ['overwrite', 'skip-existing'];
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/src/manifest.ts` around lines 35 - 40, Add and export two new
validator constants VALID_DESTINATIONS and VALID_MERGE_STRATEGIES in the same
module that defines SkillDestination and SkillMergeStrategy so manifest
validation uses canonical lists rather than hardcoded strings; ensure
VALID_DESTINATIONS lists all values of SkillDestination and
VALID_MERGE_STRATEGIES lists all values of SkillMergeStrategy, export them
alongside VALID_TARGETS/VALID_CATEGORIES/VALID_BUNDLES, then update references
(e.g., the test skills-validation.spec.ts and the install mapping in
libs/cli/src/commands/skills/install.ts) to import and use VALID_DESTINATIONS
and VALID_MERGE_STRATEGIES instead of duplicating literals.
```

</details>

---

`74-74`: **Narrow `storageDefault` keys to known targets for stronger type safety**

Line 74 uses `Record<string, string>`, which allows unknown keys to compile. Prefer a target-constrained map so manifest mistakes fail at compile time.

<details>
<summary>♻️ Proposed diff</summary>

```diff
 export type SkillTarget = 'node' | 'vercel' | 'lambda' | 'cloudflare' | 'all';
+export type SkillStorageTarget = Exclude<SkillTarget, 'all'>;
@@
-  storageDefault?: Record<string, string>;
+  storageDefault?: Partial<Record<SkillStorageTarget, string>>;
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/src/manifest.ts` at line 74, The manifest's storageDefault
currently uses an open Record<string,string> which permits arbitrary keys;
replace it with a constrained map keyed by a union or enum of allowed storage
targets (e.g. define a StorageTarget = 'local' | 's3' | 'gcs' | 'azure' or an
enum and then use storageDefault?: Partial<Record<StorageTarget, string>> or a
dedicated interface) so invalid keys fail at compile time; update the
storageDefault type in manifest.ts and any places that construct or read
manifest.storageDefault to use the new StorageTarget type/enum.
```

</details>

</blockquote></details>

</blockquote></details>

---

<details>
<summary>ℹ️ Review info</summary>

<details>
<summary>⚙️ Run configuration</summary>

**Configuration used**: Path: .coderabbit.yaml

**Review profile**: CHILL

**Plan**: Pro

**Run ID**: `b7604e10-07e6-4f98-a372-83c06189a439`

</details>

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between bbb5464399e3e1a7c31fb19e4346969a8c43d8ec and 224fc2d1b33ad11f9c24b13b412578b50b62a99a.

</details>

<details>
<summary>📒 Files selected for processing (91)</summary>

* `CLAUDE.md`
* `apps/e2e/demo-e2e-cli-exec/e2e/cli-skills.e2e.spec.ts`
* `apps/e2e/demo-e2e-cli-exec/e2e/helpers/exec-cli.ts`
* `libs/cli/package.json`
* `libs/cli/src/commands/scaffold/create.ts`
* `libs/cli/src/commands/scaffold/register.ts`
* `libs/cli/src/commands/skills/catalog.ts`
* `libs/cli/src/commands/skills/install.ts`
* `libs/cli/src/commands/skills/list.ts`
* `libs/cli/src/commands/skills/register.ts`
* `libs/cli/src/commands/skills/search.ts`
* `libs/cli/src/commands/skills/show.ts`
* `libs/cli/src/core/__tests__/program.spec.ts`
* `libs/cli/src/core/program.ts`
* `libs/nx-plugin/generators.json`
* `libs/nx-plugin/src/generators/server/schema.json`
* `libs/nx-plugin/src/generators/server/schema.ts`
* `libs/nx-plugin/src/generators/server/server.ts`
* `libs/nx-plugin/src/generators/skill-dir/files/__name__/SKILL.md__tmpl__`
* `libs/nx-plugin/src/generators/skill-dir/schema.json`
* `libs/nx-plugin/src/generators/skill-dir/schema.ts`
* `libs/nx-plugin/src/generators/skill-dir/skill-dir.ts`
* `libs/sdk/src/skill/__tests__/skill-md-parser.spec.ts`
* `libs/sdk/src/skill/skill-md-parser.ts`
* `libs/skills/README.md`
* `libs/skills/__tests__/loader.spec.ts`
* `libs/skills/__tests__/manifest.spec.ts`
* `libs/skills/__tests__/skills-validation.spec.ts`
* `libs/skills/catalog/TEMPLATE.md`
* `libs/skills/catalog/adapters/create-adapter/SKILL.md`
* `libs/skills/catalog/adapters/official-adapters/SKILL.md`
* `libs/skills/catalog/auth/configure-auth/SKILL.md`
* `libs/skills/catalog/auth/configure-auth/references/auth-modes.md`
* `libs/skills/catalog/auth/configure-session/SKILL.md`
* `libs/skills/catalog/config/configure-elicitation/SKILL.md`
* `libs/skills/catalog/config/configure-http/SKILL.md`
* `libs/skills/catalog/config/configure-throttle/SKILL.md`
* `libs/skills/catalog/config/configure-throttle/references/guard-config.md`
* `libs/skills/catalog/config/configure-transport/SKILL.md`
* `libs/skills/catalog/config/configure-transport/references/protocol-presets.md`
* `libs/skills/catalog/deployment/build-for-browser/SKILL.md`
* `libs/skills/catalog/deployment/build-for-cli/SKILL.md`
* `libs/skills/catalog/deployment/build-for-sdk/SKILL.md`
* `libs/skills/catalog/deployment/deploy-to-cloudflare/SKILL.md`
* `libs/skills/catalog/deployment/deploy-to-lambda/SKILL.md`
* `libs/skills/catalog/deployment/deploy-to-node/SKILL.md`
* `libs/skills/catalog/deployment/deploy-to-node/references/Dockerfile.example`
* `libs/skills/catalog/deployment/deploy-to-vercel/SKILL.md`
* `libs/skills/catalog/deployment/deploy-to-vercel/references/vercel.json.example`
* `libs/skills/catalog/development/create-agent/SKILL.md`
* `libs/skills/catalog/development/create-agent/references/llm-config.md`
* `libs/skills/catalog/development/create-job/SKILL.md`
* `libs/skills/catalog/development/create-prompt/SKILL.md`
* `libs/skills/catalog/development/create-provider/SKILL.md`
* `libs/skills/catalog/development/create-resource/SKILL.md`
* `libs/skills/catalog/development/create-skill-with-tools/SKILL.md`
* `libs/skills/catalog/development/create-skill/SKILL.md`
* `libs/skills/catalog/development/create-tool/SKILL.md`
* `libs/skills/catalog/development/create-tool/references/output-schema-types.md`
* `libs/skills/catalog/development/create-tool/references/tool-annotations.md`
* `libs/skills/catalog/development/create-workflow/SKILL.md`
* `libs/skills/catalog/development/decorators-guide/SKILL.md`
* `libs/skills/catalog/plugins/create-plugin-hooks/SKILL.md`
* `libs/skills/catalog/plugins/create-plugin/SKILL.md`
* `libs/skills/catalog/plugins/official-plugins/SKILL.md`
* `libs/skills/catalog/setup/frontmcp-skills-usage/SKILL.md`
* `libs/skills/catalog/setup/multi-app-composition/SKILL.md`
* `libs/skills/catalog/setup/nx-workflow/SKILL.md`
* `libs/skills/catalog/setup/project-structure-nx/SKILL.md`
* `libs/skills/catalog/setup/project-structure-standalone/SKILL.md`
* `libs/skills/catalog/setup/setup-project/SKILL.md`
* `libs/skills/catalog/setup/setup-redis/SKILL.md`
* `libs/skills/catalog/setup/setup-sqlite/SKILL.md`
* `libs/skills/catalog/skills-manifest.json`
* `libs/skills/catalog/testing/setup-testing/SKILL.md`
* `libs/skills/catalog/testing/setup-testing/references/test-auth.md`
* `libs/skills/catalog/testing/setup-testing/references/test-browser-build.md`
* `libs/skills/catalog/testing/setup-testing/references/test-cli-binary.md`
* `libs/skills/catalog/testing/setup-testing/references/test-direct-client.md`
* `libs/skills/catalog/testing/setup-testing/references/test-e2e-handler.md`
* `libs/skills/catalog/testing/setup-testing/references/test-tool-unit.md`
* `libs/skills/jest.config.ts`
* `libs/skills/package.json`
* `libs/skills/project.json`
* `libs/skills/src/index.ts`
* `libs/skills/src/loader.ts`
* `libs/skills/src/manifest.ts`
* `libs/skills/tsconfig.json`
* `libs/skills/tsconfig.lib.json`
* `libs/skills/tsconfig.spec.json`
* `tsconfig.base.json`

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@libs/skills/eslint.config.mjs`:
- Around line 8-12: Update the inline comment above the
'@nx/enforce-module-boundaries' rule to reference the correct package name:
replace `@frontmcp/guard` with `@frontmcp/sdk` so the note correctly explains
that the validation test imports the SDK parser via relative path
(`../../sdk/src/skill/skill-md-parser`) and prevents the rule's fixer from
crashing on that package resolution.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ff168587-82da-4eb2-ab2e-f2bbfd5a1254

📥 Commits

Reviewing files that changed from the base of the PR and between 2406f13 and 0b56350.

📒 Files selected for processing (2)
  • libs/skills/__tests__/skills-validation.spec.ts
  • libs/skills/eslint.config.mjs
✅ Files skipped from review due to trivial changes (1)
  • libs/skills/tests/skills-validation.spec.ts

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: 6

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (16)
libs/skills/catalog/testing/setup-testing/SKILL.md-90-96 (1)

90-96: ⚠️ Potential issue | 🟡 Minor

Add a language to the fenced code block to satisfy MD040.

This block is missing a fence language and will keep markdownlint warninging on Line 90.

Suggested fix
-```
+```text
 src/
   tools/
     my-tool.ts
     __tests__/
       my-tool.spec.ts        # Unit tests
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/testing/setup-testing/SKILL.md around lines 90 - 96, The
fenced code block showing the project tree (the block starting with and the lines "src/ tools/ my-tool.ts __tests__/ my-tool.spec.ts") lacks a language tag and triggers MD040; update that opening fence to include a language (e.g., change to text or bash) in SKILL.md so the snippet is treated as plain
text and the markdownlint warning is resolved.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/setup/setup-project/SKILL.md-386-387 (1)</summary><blockquote>

`386-387`: _⚠️ Potential issue_ | _🟡 Minor_

**Make `.gitignore` update idempotent.**

`echo ".env" >> .gitignore` appends duplicates if rerun. Prefer a guarded append.

<details>
<summary>✏️ Suggested patch</summary>

```diff
-echo ".env" >> .gitignore
+grep -qxF ".env" .gitignore || echo ".env" >> .gitignore
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/setup/setup-project/SKILL.md` around lines 386 - 387,
Replace the unconditional append "echo \".env\" >> .gitignore" with a guarded
append that only writes the line if it isn't already present; locate the
existing echo command in SKILL.md and change it to perform a presence check
(e.g., use a grep -qxF or similar exact-line test for ".env" in .gitignore) and
only append the ".env" entry when the check fails so repeated runs remain
idempotent.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/setup/project-structure-nx/SKILL.md-38-74 (1)</summary><blockquote>

`38-74`: _⚠️ Potential issue_ | _🟡 Minor_

**Add language identifiers to unlabeled fenced blocks.**

The directory-tree/code fences here are missing language labels (MD040). Please mark them as `text` (tree) or `bash` (commands) as appropriate.




Also applies to: 145-160, 167-179

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/setup/project-structure-nx/SKILL.md around lines 38 -
74, The Markdown tree/code fence blocks in SKILL.md (e.g., the directory-tree
block shown around the my-workspace example and the other unlabeled fenced
blocks at ranges 145-160 and 167-179) lack language identifiers; update each
triple-backtick fence to include an appropriate language tag such as "text" (for
directory trees) or "bash" (for command examples) so that lint rule MD040 is
satisfied, e.g., change totext for the tree blocks and to ```bash for
shell snippets.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/setup/frontmcp-skills-usage/SKILL.md-122-140 (1)</summary><blockquote>

`122-140`: _⚠️ Potential issue_ | _🟡 Minor_

**Label this fenced block with a language.**

Add a language (e.g., `text`) to satisfy MD040 and keep formatting consistent.

<details>
<summary>Suggested fix</summary>

```diff
-```
+```text
 my-project/
 ├── .claude/
 ...
 └── src/
     └── ...
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/setup/frontmcp-skills-usage/SKILL.md around lines 122 -
140, The fenced code block showing the project tree in SKILL.md is missing a
language label which triggers MD040; update the opening fence to include a
language (for example change "" to "text") so the block is labeled
consistently; locate the directory-tree block in the SKILL.md content (the
snippet containing "my-project/" and the .claude/.codex directories) and add the
chosen language label to the opening fence.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/setup/frontmcp-skills-usage/SKILL.md-82-83 (1)</summary><blockquote>

`82-83`: _⚠️ Potential issue_ | _🟡 Minor_

**Clarify `skills show` output: it is not the raw full file.**

Current wording says “full SKILL.md content,” but `libs/cli/src/commands/skills/show.ts` prepends metadata headers, strips frontmatter, and appends an install line. Please adjust wording to avoid misleading piping/automation use cases.


As per coding guidelines: "`libs/**`: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs."


Also applies to: 154-155, 246-247

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/setup/frontmcp-skills-usage/SKILL.md` around lines 82 -
83, The SKILL.md wording claiming “Print the full SKILL.md content to stdout” is
misleading because the CLI command (libs/cli/src/commands/skills/show.ts — the
"skills show" command) actually prepends metadata headers, strips frontmatter,
and appends an install line rather than outputting the raw file; update the
wording at the referenced spots (around lines 82-83, 154-155, 246-247) to state
that the command prints a processed/augmented version of SKILL.md (include
notes: metadata headers added, frontmatter removed, install line appended) so
users and automation know it’s not the unmodified file.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/setup/nx-workflow/SKILL.md-273-309 (1)</summary><blockquote>

`273-309`: _⚠️ Potential issue_ | _🟡 Minor_

**Add a language to the directory-tree code fence.**

This unlabeled fence triggers MD040; use `text` for tree output blocks.

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/setup/nx-workflow/SKILL.md around lines 273 - 309, The
fenced directory-tree block in SKILL.md lacks a language tag (causing MD040);
update the fenced code block that shows the my-project/ tree to use a language
label by changing the opening fence to text so the tree output is treated as plain text (leave the closing intact).


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/plugins/official-plugins/SKILL.md-455-457 (1)</summary><blockquote>

`455-457`: _⚠️ Potential issue_ | _🟡 Minor_

**Add a language identifier to this fenced code block.**

This fence is unlabeled, which triggers MD040 and can break syntax highlighting consistency.

<details>
<summary>Suggested fix</summary>

```diff
-```
+```http
 x-frontmcp-disable-cache: true
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/plugins/official-plugins/SKILL.md` around lines 455 -
457, The fenced code block containing the header "x-frontmcp-disable-cache:
true" is unlabeled and triggers MD040; update that fence by adding an
appropriate language identifier (e.g., "http" or "yaml") so it becomes a labeled
code fence (referencing the existing fenced block with the content
"x-frontmcp-disable-cache: true"); ensure the opening triple-backtick line is
changed to include the chosen language identifier to restore syntax highlighting
and satisfy the linter.
```

</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/development/decorators-guide/SKILL.md-18-34 (1)</summary><blockquote>

`18-34`: _⚠️ Potential issue_ | _🟡 Minor_

**Add language specification to fenced code block.**

The architecture diagram is missing a language identifier, which causes a markdown linting warning (MD040).



<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```text
 `@FrontMcp`          (server root)
   +-- `@App`         (application module)
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/development/decorators-guide/SKILL.md around lines 18 -
34, The fenced code block containing the ASCII architecture diagram (starting
with the lines showing @FrontMcp, @App, @Tool, @Resource, @Prompt, @Agent,
@Skill, etc.) must include a language identifier to satisfy Markdown linting
(MD040); update the opening triple-backtick to specify a language (e.g., "text")
so the block becomes ```text, ensuring the diagram lines remain unchanged and
the rest of SKILL.md formatting is preserved.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/development/create-skill-with-tools/SKILL.md-236-248 (1)</summary><blockquote>

`236-248`: _⚠️ Potential issue_ | _🟡 Minor_

**Add language identifier to fenced code block.**

The directory structure should have a language identifier for proper rendering.

<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```text
 skills/
   deploy-service/
     SKILL.md           # Instructions with YAML frontmatter
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/development/create-skill-with-tools/SKILL.md around
lines 236 - 248, The fenced code block in SKILL.md showing the directory
structure is missing a language identifier; update the triple-backtick that
opens the block to include a language (e.g., "text") so the snippet renders
correctly (look for the fenced block containing the directory listing under
skills/deploy-service in SKILL.md and change totext).


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/development/create-skill-with-tools/SKILL.md-447-460 (1)</summary><blockquote>

`447-460`: _⚠️ Potential issue_ | _🟡 Minor_

**Add language identifier to fenced code block.**

The HTTP endpoint example should have a language identifier for proper rendering.

<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```http
 GET /llm.txt
 
 # Skills
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/development/create-skill-with-tools/SKILL.md around
lines 447 - 460, The fenced code block showing the /llm.txt HTTP example should
include a language identifier for proper rendering; update the triple-backtick
fence surrounding the example (the block that begins with "GET /llm.txt" and
contains the "# Skills" section) from tohttp (and close with ```), so
the block is recognized as HTTP syntax in SKILL.md's /llm.txt example.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/development/create-skill-with-tools/SKILL.md-462-481 (1)</summary><blockquote>

`462-481`: _⚠️ Potential issue_ | _🟡 Minor_

**Add language identifier to fenced code block.**

The JSON response example should have a language identifier for proper rendering.

<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```json
 GET /skills
 
 [
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/development/create-skill-with-tools/SKILL.md around
lines 462 - 481, The JSON example in the "/skills" response block is missing a
language identifier; update the fenced code block that begins before "GET
/skills" (the triple backticks surrounding the JSON example in SKILL.md) to use

libs/skills/catalog/config/configure-throttle/SKILL.md-44-46 (1)

44-46: ⚠️ Potential issue | 🟡 Minor

Tighten repeated “only” phrasing for readability.

The “Skip When” bullets repeat “only,” which reads awkwardly. Consider rewording one occurrence to keep the guidance crisp.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/config/configure-throttle/SKILL.md` around lines 44 - 46,
The three "Skip When" bullets in SKILL.md repeat the word "only" and read
awkwardly; update the phrasing to remove the duplicate "only" in at least one
place for clarity — e.g., change "Running a local development server with stdio
transport only -- throttle adds unnecessary overhead" or "Only need CORS or port
configuration without rate limiting -- use `configure-http`" so that only one
occurrence of "only" remains per bullet (or replace one with
"just"/"solely"/"only when appropriate"), ensuring the guidance stays equivalent
and references the same options (`configure-http`, `configure-session`,
`configure-auth`) and the stdio transport scenario.
libs/skills/catalog/plugins/create-plugin-hooks/SKILL.md-299-301 (1)

299-301: ⚠️ Potential issue | 🟡 Minor

Add language specifier to code block.

The code block showing the stage sequence should specify a language identifier for proper rendering and accessibility.

📝 Proposed fix
-```
+```text
 parseInput → findTool → checkToolAuthorization → createToolCallContext
   → validateInput → execute → validateOutput → finalize

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/plugins/create-plugin-hooks/SKILL.md around lines 299 -
301, The code block showing the stage sequence (parseInput → findTool →
checkToolAuthorization → createToolCallContext → validateInput → execute →
validateOutput → finalize) is missing a language specifier; update the Markdown
block by adding a language tag (e.g., "text") to the fenced code block opening
so the block reads with a language identifier and renders/accesses correctly.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/plugins/create-plugin-hooks/SKILL.md-38-232 (1)</summary><blockquote>

`38-232`: _⚠️ Potential issue_ | _🟡 Minor_

**Update Pre-Built Hook Type Exports to include `ListResourceTemplatesHook` and clarify prompt flow hooks.**

The documentation lists prompt flows (`prompts:get-prompt`, `prompts:list-prompts`) in the Available Flow Names table, but no corresponding pre-built hook exports exist. Additionally, `ListResourceTemplatesHook` is exported from the SDK but missing from the Pre-Built Hook Type Exports section.

<details>
<summary>Changes needed:</summary>

1. Add `ListResourceTemplatesHook` to the Pre-Built Hook Type Exports code block:
   ```typescript
   ListResourceTemplatesHook, // FlowHooksOf('resources:list-resource-templates')
  1. Either:

    • Add prompt hook exports if they should be available, or
    • Remove prompts:get-prompt and prompts:list-prompts from the Available Flow Names table and note that prompt flows require using FlowHooksOf() directly
  2. Consider adding a Resource or Agent hook example alongside the existing ToolHook example to better demonstrate hook type diversity.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/plugins/create-plugin-hooks/SKILL.md` around lines 38 -
232, The Pre-Built Hook Type Exports block is missing ListResourceTemplatesHook
and is inconsistent with the Available Flow Names for prompt flows; add
ListResourceTemplatesHook to the exported aliases (referencing
ListResourceTemplatesHook / FlowHooksOf('resources:list-resource-templates')),
then either add typed prompt hook exports (e.g., PromptGetHook / PromptListHook
via FlowHooksOf for prompts:get-prompt and prompts:list-prompts) or remove the
prompt rows from the Available Flow Names table and add a note that prompt hooks
must be obtained via FlowHooksOf(); optionally add a short example showing a
non-tool hook alias usage (e.g., ResourceHook or ListResourceTemplatesHook)
similar to the existing ToolHook example to demonstrate diversity.
libs/skills/catalog/auth/configure-auth/SKILL.md-70-72 (1)

70-72: ⚠️ Potential issue | 🟡 Minor

Fix broken skill references in "Skip When" section.

Two of the three referenced skills don't exist in the catalog:

  • configure-scopes — skill not found; remove the reference or add the skill
  • configure-session-store — skill not found; the actual skill is configure-session
  • create-plugin — exists and reference is valid

Replace lines 70–72 with:

- You need to add scopes or guard individual tools/resources -- use `configure-scopes` instead
- You need to manage session storage backends (Redis, Vercel KV) -- use `configure-session` instead
- You are building a plugin that extends auth context -- use `create-plugin` instead

Also applies to: 306 (update "Related skills" list with the same corrections)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/auth/configure-auth/SKILL.md` around lines 70 - 72, In
the SKILL.md "Skip When" section and the "Related skills" list (around the
existing references), replace the invalid skill reference
`configure-session-store` with the correct `configure-session` and ensure
`configure-scopes` and `create-plugin` remain as shown; specifically update the
three lines currently referencing `configure-scopes`, `configure-session-store`,
and `create-plugin` to instead read `configure-scopes`, `configure-session`, and
`create-plugin` so the skill names match the catalog.
libs/skills/catalog/auth/configure-auth/SKILL.md-89-98 (1)

89-98: ⚠️ Potential issue | 🟡 Minor

Add import statements to all code examples to match documentation patterns used in other skills.

The code examples in this documentation use @App and related decorators without showing where they're imported from. While create-plugin.md includes import statements like import { App, FrontMcp } from '@frontmcp/sdk', these examples in configure-auth.md lack them. Add imports at the beginning of each TypeScript code block (lines 89–98, 107–116, 127–138, 149–158, 167–176, 184–206) to provide complete, copy-paste-ready examples:

import { App } from '@frontmcp/sdk';

`@App`({
  auth: {
    mode: 'public',
    sessionTtl: 3600,
    anonymousScopes: ['read'],
  },
})
class MyApp {}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/auth/configure-auth/SKILL.md` around lines 89 - 98, Add
explicit import statements at the top of each TypeScript example so the
decorators are copy-paste ready: include import { App } from '@frontmcp/sdk' for
examples using `@App` (and add other symbols used in the blocks, e.g., FrontMcp or
any decorator/class names visible in that block) to mirror the pattern used in
create-plugin.md; place the import line before the `@App` decorator in each TS
code block so the examples compile when pasted.
🧹 Nitpick comments (11)
libs/skills/catalog/development/create-skill/SKILL.md (1)

26-28: Tighten repeated phrasing in the “Recommended” bullets.

Lines 27-28 repeat the “You want to…” stem. Consider varying one bullet for readability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/development/create-skill/SKILL.md` around lines 26 - 28,
In the "Recommended" bullets of SKILL.md where two items start with "You want
to…", change one bullet to avoid repeating the stem for readability; for
example, keep one as "You want to share workflow templates across teams via MCP
or HTTP discovery endpoints" and reword the other to "Share workflow templates
across teams via MCP or HTTP discovery endpoints" or "Use MCP or HTTP discovery
endpoints to share workflow templates across teams," updating the second bullet
in that section so the two bullets no longer both begin with "You want to…".
libs/skills/__tests__/skills-validation.spec.ts (4)

272-314: NEW_FORMAT_SECTIONS is defined but not used; validation uses hardcoded strings.

The constant NEW_FORMAT_SECTIONS (line 273) defines a structured array with heading and required fields, but the actual validation logic on lines 284, 303, and 310-313 uses hardcoded string literals instead. Consider either:

  1. Using the constant to drive validation dynamically, or
  2. Removing the unused constant and keeping the explicit strings
♻️ Option 1: Use the constant to drive validation
   describe('new-format migration tracking', () => {
-    const NEW_FORMAT_SECTIONS = [{ heading: '## When to Use This Skill', required: '### Must Use' }];
+    const NEW_FORMAT_SECTIONS = {
+      migrationMarkers: ['## When to Use This Skill', '### Must Use'],
+      requiredSections: ['### Must Use', '### Recommended', '### Skip When', '## Verification Checklist'],
+    };

     // ... in the test:
-      const hasNewWhenToUse = content.includes('## When to Use This Skill') && content.includes('### Must Use');
+      const hasNewWhenToUse = NEW_FORMAT_SECTIONS.migrationMarkers.every((m) => content.includes(m));

     // ... in migrated skills validation:
-      expect(content).toContain('### Must Use');
-      expect(content).toContain('### Recommended');
-      expect(content).toContain('### Skip When');
-      expect(content).toContain('## Verification Checklist');
+      for (const section of NEW_FORMAT_SECTIONS.requiredSections) {
+        expect(content).toContain(section);
+      }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/__tests__/skills-validation.spec.ts` around lines 272 - 314, The
NEW_FORMAT_SECTIONS constant is unused; update the tests in the
describe('new-format migration tracking') block (functions getSkillBody and the
it.each that uses findAllSkillDirs) to derive both the "is migrated" check and
the required-section assertions from NEW_FORMAT_SECTIONS instead of hardcoded
strings: compute isMigrated by confirming each NEW_FORMAT_SECTIONS[].heading
exists, increment migrated accordingly, and for migrated skills loop over
NEW_FORMAT_SECTIONS to assert content.includes(section.required) (and any
additional overall section like '## Verification Checklist' can be kept or added
to the array if desired); alternatively, if you prefer the explicit literals,
remove the unused NEW_FORMAT_SECTIONS declaration.

78-89: Reduce redundant manifest loading in it.each blocks.

The manifest is loaded and parsed 6 times in the describe('manifest entries') block, once per it.each. Since the manifest is static during test execution, consider extracting to a module-level constant:

♻️ Proposed refactor to cache manifest entries
+// Module-level lazy cache for manifest entries (needed for it.each before beforeAll runs)
+function getManifestEntries(): [string, SkillCatalogEntry][] {
+  const m = JSON.parse(fs.readFileSync(MANIFEST_PATH, 'utf-8')) as SkillManifest;
+  return m.skills.map((s) => [s.name, s] as [string, SkillCatalogEntry]);
+}
+const MANIFEST_ENTRIES = getManifestEntries();
+
 describe('manifest entries', () => {
-    it.each(
-      // Load manifest lazily to avoid issues with beforeAll timing in .each
-      (() => {
-        const m = JSON.parse(fs.readFileSync(MANIFEST_PATH, 'utf-8')) as SkillManifest;
-        return m.skills.map((s) => [s.name, s] as [string, SkillCatalogEntry]);
-      })(),
-    )('"%s" should have valid targets', (_, entry) => {
+    it.each(MANIFEST_ENTRIES)('"%s" should have valid targets', (_, entry) => {

Apply similar changes to the other it.each blocks in this describe.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/__tests__/skills-validation.spec.ts` around lines 78 - 89, The
tests repeatedly re-read and parse the manifest inside multiple it.each blocks;
extract the manifest load into a module-level constant (e.g., const manifest =
JSON.parse(fs.readFileSync(MANIFEST_PATH,'utf-8')) as SkillManifest) and reuse
manifest.skills for all it.each calls to avoid redundant IO and parsing. Update
the it.each invocations that currently use the IIFE to reference the cached
manifest (manifest.skills.map(...)) — look for usages surrounding MANIFEST_PATH,
SkillManifest, and the it.each blocks that validate targets (VALID_TARGETS) and
similar validations, and replace each IIFE with the shared manifest constant.

176-180: Add type guard before string assertion on instructions.

Line 179 uses a type assertion (metadata.instructions as string) which could fail if instructions is undefined or not a string. The preceding expect(metadata.instructions).toBeDefined() doesn't narrow the type for TypeScript.

🛡️ Proposed fix with type guard
       expect(metadata.name).toBeDefined();
       expect(metadata.description).toBeDefined();
       expect(metadata.instructions).toBeDefined();
-      expect((metadata.instructions as string).length).toBeGreaterThan(50);
+      expect(typeof metadata.instructions).toBe('string');
+      expect((metadata.instructions as string).length).toBeGreaterThan(50);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/__tests__/skills-validation.spec.ts` around lines 176 - 180, The
test currently asserts string length using a type assertion on
metadata.instructions which isn't narrowed by the previous toBeDefined check;
update the test to first check the runtime type (e.g., expect(typeof
metadata.instructions).toBe('string') or an if (typeof metadata.instructions ===
'string') guard) and only then assert (metadata.instructions).length > 50 so the
length check is executed safely and TypeScript is satisfied; reference the
metadata.instructions assertion in the test block containing
expect(metadata.name)...expect((metadata.instructions as string).length).

11-12: Consider using @frontmcp/utils for file system operations.

Per coding guidelines, file system operations should use @frontmcp/utils rather than node:fs directly. However, since this is a test file using synchronous operations for validation setup (where async would complicate beforeAll and it.each patterns), this deviation may be acceptable.

If @frontmcp/utils provides synchronous equivalents or if the tests can be restructured to use async operations, consider migrating for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/__tests__/skills-validation.spec.ts` around lines 11 - 12, The
test imports use node:fs and node:path directly; switch to the project's
recommended file utilities by replacing direct fs/path usage in the test
(skills-validation.spec.ts) with the corresponding helpers from `@frontmcp/utils`
(use the module's sync file-read/listing helpers or path helpers) so file
operations follow project conventions, or if `@frontmcp/utils` lacks synchronous
APIs, refactor the beforeAll/it.each setup to async/await and use the async
helpers from `@frontmcp/utils`; update the import statements and all uses
currently referencing fs and path in this file to use the `@frontmcp/utils`
functions (or convert the test setup to async and replace fs.*Sync calls with
async equivalents) to ensure consistency with coding guidelines.
libs/skills/catalog/development/create-skill-with-tools/SKILL.md (2)

385-405: Consider adding loading behavior details.

The remote and ESM loading examples would benefit from brief clarification about when/how these skills are loaded (lazy vs eager, error handling, installation requirements).

For example, you might add a note explaining:

  • Whether Skill.esm() requires the package to be pre-installed or handles installation
  • Whether loading happens synchronously at registration or lazily when first accessed
  • How errors are handled if remote URLs are unavailable
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/development/create-skill-with-tools/SKILL.md` around
lines 385 - 405, The docs for Skill.esm and Skill.remote lack loading behavior
details; update the SKILL.md section to clarify whether Skill.esm expects the
package to be pre-installed or will attempt installation, whether loading is
eager at registration or lazy on first access, and how errors are surfaced
(exceptions, logged warnings, or fallbacks) for unavailable remote URLs;
explicitly mention any authentication or network requirements and the impact on
skills: [ExternalSkill, CloudSkill] registration so consumers know installation,
timing, and error-handling expectations for Skill.esm and Skill.remote.

250-254: Clarify async context for skillDir() example.

The example uses await without showing the surrounding async context, which may confuse users about where this code should be placed.

💡 Suggested clarification
-```typescript
-import { skillDir } from '@frontmcp/sdk';
-
-const DeployServiceSkill = await skillDir('./skills/deploy-service');
-```
+```typescript
+import { skillDir } from '@frontmcp/sdk';
+
+// Load skill from directory (top-level await in ES modules)
+const DeployServiceSkill = await skillDir('./skills/deploy-service');
+
+// Or within an async function:
+async function loadSkills() {
+  const DeployServiceSkill = await skillDir('./skills/deploy-service');
+  return DeployServiceSkill;
+}
+```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @libs/skills/catalog/development/create-skill-with-tools/SKILL.md around
lines 250 - 254, Update the SKILL.md example to clarify the async context for
using skillDir: mention that top-level await is valid in ES modules when using
"await skillDir(...)" and also provide an alternative showing how to call
skillDir inside an async function (e.g., a loadSkills function) so readers know
to either use top-level await or await within an async function when obtaining
DeployServiceSkill from skillDir.


</details>

</blockquote></details>
<details>
<summary>libs/skills/catalog/setup/setup-redis/SKILL.md (3)</summary><blockquote>

`282-282`: **Add language specifier to fenced code block.**

The code block at line 282 is missing a language specifier. Add `typescript` to improve syntax highlighting.



<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```typescript
 `@FrontMcp`({
   info: { name: 'my-server', version: '0.1.0' },

As per static analysis hints, fenced code blocks should have a language specified.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/setup/setup-redis/SKILL.md` at line 282, The fenced code
block containing the snippet starting with "@FrontMcp({ info: { name:
'my-server', version: '0.1.0' }," should be updated to include a language
specifier; add "typescript" after the opening ``` so the block reads
```typescript to enable proper syntax highlighting for the TypeScript-like
snippet.

213-213: Add language specifier to fenced code block.

The code block at line 213 is missing a language specifier. Add typescript to improve syntax highlighting and tooling support.

📝 Proposed fix
-```
+```typescript
 redis: {
   provider: 'vercel-kv',
   url: process.env['KV_REST_API_URL'],               // string (optional, default from env)

As per static analysis hints, fenced code blocks should have a language specified.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/setup/setup-redis/SKILL.md` at line 213, The fenced code
block showing the redis config (starting with "redis: {", "provider:
'vercel-kv'", "url: process.env['KV_REST_API_URL']") is missing a language
specifier; update the opening fence from ``` to ```typescript so the block reads
as a TypeScript fenced code block to enable proper syntax highlighting and
tooling.

308-312: Consider varying sentence structure for readability.

The numbered list uses "If" to start three consecutive sentences. While this is technically correct for a conditional logic sequence, consider varying the structure for improved readability.

✍️ Suggested rewording
 1. If `redis` is set and `transport.persistence` is not configured, persistence is auto-enabled with the global redis config.
 2. If `transport.persistence` is explicitly `false`, persistence is disabled.
-3. If `transport.persistence.redis` is explicitly set, that config is used instead.
-4. If `transport.persistence` is an object without `redis`, the global redis config is injected.
+3. When `transport.persistence.redis` is explicitly set, that config takes precedence.
+4. For `transport.persistence` objects without `redis`, the global redis config is automatically injected.

As per static analysis hints, varying sentence openings can improve readability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/setup/setup-redis/SKILL.md` around lines 308 - 312, The
numbered conditional list in SKILL.md (items 1–4) repeats "If" at the start of
several lines; rephrase to vary sentence openings for readability by changing at
least two items to different constructions (e.g., start item 1 with "When the
global `redis` config is set and `transport.persistence` is not configured,
persistence is auto-enabled...", item 2 with "Setting `transport.persistence` to
`false` disables persistence.", item 3 with "Provide an explicit
`transport.persistence.redis` to use that configuration.", and item 4 with "When
`transport.persistence` is an object that lacks `redis`, inject the global redis
config."); preserve the original meaning and the conditional logic order while
only adjusting wording for clarity.
libs/skills/catalog/config/configure-transport/SKILL.md (1)

44-46: Optional: Vary phrasing to improve readability.

Lines 44 and 46 both use "you need to", creating repetitive phrasing. Consider rephrasing one for variety, e.g.:

-  - You need to set up plugin middleware without changing the transport layer (use `configure-plugins` instead)
+  - Setting up plugin middleware without changing the transport layer (use `configure-plugins` instead)

or

-> **Decision:** Use this skill whenever you need to choose, combine, or customize the protocol(s) your MCP server exposes to clients.
+> **Decision:** Use this skill to choose, combine, or customize the protocol(s) your MCP server exposes to clients.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/config/configure-transport/SKILL.md` around lines 44 -
46, Replace one of the repetitive "you need to" phrases in the SKILL.md excerpt
to improve readability; specifically, modify either the sentence "You need to
set up plugin middleware without changing the transport layer (use
`configure-plugins` instead)" or the decision line beginning "Use this skill
whenever you need to..." so they don't both start with "you need to" — for
example, change the first to "Set up plugin middleware without changing the
transport layer (use `configure-plugins` instead)" or reword the decision line
to "Use this skill when choosing, combining, or customizing the protocol(s) your
MCP server exposes to clients." Ensure only one of the two lines is rephrased to
maintain clarity and tone.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@libs/skills/catalog/auth/configure-auth/SKILL.md`:
- Around line 213-238: The example in the `@App` decorator is incorrect: remove
the vault: { encryption: ..., providers: [...] } block or replace it with the
correct usage that uses authProviders and DI instead; specifically stop passing
vault/encryption to the `@App` metadata (the decorator does not accept a vault
field and AuthProvidersVaultOptions has no encryption property), and instead
configure vault providers via the app's dependency-injection setup (use the
authProviders configuration entry and initialize any credential encryption using
the cryptographic helpers in frontmcp/utils), ensuring references to
AuthProvidersVaultOptions and authProviders are used rather than adding a vault
key to `@App`.

In `@libs/skills/catalog/config/configure-throttle/SKILL.md`:
- Around line 177-185: The Redis storage example under the throttle config
incorrectly includes a non-existent provider field; update the
throttle.storage.redis object in SKILL.md to match the RedisAdapterOptions shape
by removing provider and using either a config object (e.g., config with host
and port) or a url string (e.g., redis://host:port); ensure the example under
the throttle key (the throttle: { enabled..., storage: { type: 'redis', redis:
... }, global: ... } block) shows one of these valid forms instead of redis: {
provider: 'redis', ... }.

In `@libs/skills/catalog/deployment/build-for-sdk/SKILL.md`:
- Around line 83-89: The example uses eval(input.expression) in the tool named
"calculate", which allows arbitrary code execution; replace it with a safe,
constrained implementation such as parsing a limited expression grammar or
switching the tool inputSchema to explicit operands and an operator (e.g.,
inputSchema: { a: z.number(), b: z.number(), op: z.enum(['+', '-', '*', '/']) })
and implement the calculation in the tool handler (the tool(...)((input) =>
...)) using only those allowed operations instead of eval; update outputSchema
accordingly to return the numeric result.

In `@libs/skills/catalog/development/create-skill/SKILL.md`:
- Around line 257-264: The YAML example uses the kebab-case key
"expected-outcome" which mismatches the TS interface field expectedOutcome;
update the example and any other occurrences in SKILL.md (the example block and
other examples/validation checklist referencing "expected-outcome") to use the
camelCase key expectedOutcome so examples match the TypeScript interface and
other code samples.

In `@libs/skills/catalog/plugins/create-plugin-hooks/SKILL.md`:
- Around line 234-243: The docs show destructuring "const { Will, Did } =
ToolHook" but never imports ToolHook, which will cause a runtime ReferenceError;
add ToolHook to the import list from the SDK where Tool and ToolContext are
imported (i.e., import Tool, ToolContext, ToolHook from '@frontmcp/sdk') so the
destructuring of ToolHook (and use of Will/Did) resolves correctly.

In `@libs/skills/catalog/setup/project-structure-nx/SKILL.md`:
- Around line 140-160: Update the generator command examples in SKILL.md to use
the correct Nx plugin namespace `@frontmcp/nx:*` instead of
`@frontmcp/nx-plugin:*`: replace occurrences like `nx g `@frontmcp/nx-plugin`:app
crm` and `nx g `@frontmcp/nx-plugin`:tool lookup-user --project=crm` with `nx g
`@frontmcp/nx`:app crm` and `nx g `@frontmcp/nx`:tool lookup-user --project=crm`
(and similarly for resource, prompt, provider, plugin, agent, job, server, lib
examples); verify against the actual package name defined in
`libs/nx-plugin/package.json` to ensure all examples consistently use
`@frontmcp/nx`.

---

Minor comments:
In `@libs/skills/catalog/auth/configure-auth/SKILL.md`:
- Around line 70-72: In the SKILL.md "Skip When" section and the "Related
skills" list (around the existing references), replace the invalid skill
reference `configure-session-store` with the correct `configure-session` and
ensure `configure-scopes` and `create-plugin` remain as shown; specifically
update the three lines currently referencing `configure-scopes`,
`configure-session-store`, and `create-plugin` to instead read
`configure-scopes`, `configure-session`, and `create-plugin` so the skill names
match the catalog.
- Around line 89-98: Add explicit import statements at the top of each
TypeScript example so the decorators are copy-paste ready: include import { App
} from '@frontmcp/sdk' for examples using `@App` (and add other symbols used in
the blocks, e.g., FrontMcp or any decorator/class names visible in that block)
to mirror the pattern used in create-plugin.md; place the import line before the
`@App` decorator in each TS code block so the examples compile when pasted.

In `@libs/skills/catalog/config/configure-throttle/SKILL.md`:
- Around line 44-46: The three "Skip When" bullets in SKILL.md repeat the word
"only" and read awkwardly; update the phrasing to remove the duplicate "only" in
at least one place for clarity — e.g., change "Running a local development
server with stdio transport only -- throttle adds unnecessary overhead" or "Only
need CORS or port configuration without rate limiting -- use `configure-http`"
so that only one occurrence of "only" remains per bullet (or replace one with
"just"/"solely"/"only when appropriate"), ensuring the guidance stays equivalent
and references the same options (`configure-http`, `configure-session`,
`configure-auth`) and the stdio transport scenario.

In `@libs/skills/catalog/development/create-skill-with-tools/SKILL.md`:
- Around line 236-248: The fenced code block in SKILL.md showing the directory
structure is missing a language identifier; update the triple-backtick that
opens the block to include a language (e.g., "text") so the snippet renders
correctly (look for the fenced block containing the directory listing under
skills/deploy-service in SKILL.md and change ``` to ```text).
- Around line 447-460: The fenced code block showing the /llm.txt HTTP example
should include a language identifier for proper rendering; update the
triple-backtick fence surrounding the example (the block that begins with "GET
/llm.txt" and contains the "# Skills" section) from ``` to ```http (and close
with ```), so the block is recognized as HTTP syntax in SKILL.md's /llm.txt
example.
- Around line 462-481: The JSON example in the "/skills" response block is
missing a language identifier; update the fenced code block that begins before
"GET /skills" (the triple backticks surrounding the JSON example in SKILL.md) to
use ```json so the snippet is rendered with JSON highlighting.

In `@libs/skills/catalog/development/decorators-guide/SKILL.md`:
- Around line 18-34: The fenced code block containing the ASCII architecture
diagram (starting with the lines showing `@FrontMcp`, `@App`, `@Tool`, `@Resource`,
`@Prompt`, `@Agent`, `@Skill`, etc.) must include a language identifier to satisfy
Markdown linting (MD040); update the opening triple-backtick to specify a
language (e.g., "text") so the block becomes ```text, ensuring the diagram lines
remain unchanged and the rest of SKILL.md formatting is preserved.

In `@libs/skills/catalog/plugins/create-plugin-hooks/SKILL.md`:
- Around line 299-301: The code block showing the stage sequence (parseInput →
findTool → checkToolAuthorization → createToolCallContext → validateInput →
execute → validateOutput → finalize) is missing a language specifier; update the
Markdown block by adding a language tag (e.g., "text") to the fenced code block
opening so the block reads with a language identifier and renders/accesses
correctly.
- Around line 38-232: The Pre-Built Hook Type Exports block is missing
ListResourceTemplatesHook and is inconsistent with the Available Flow Names for
prompt flows; add ListResourceTemplatesHook to the exported aliases (referencing
ListResourceTemplatesHook / FlowHooksOf('resources:list-resource-templates')),
then either add typed prompt hook exports (e.g., PromptGetHook / PromptListHook
via FlowHooksOf for prompts:get-prompt and prompts:list-prompts) or remove the
prompt rows from the Available Flow Names table and add a note that prompt hooks
must be obtained via FlowHooksOf(); optionally add a short example showing a
non-tool hook alias usage (e.g., ResourceHook or ListResourceTemplatesHook)
similar to the existing ToolHook example to demonstrate diversity.

In `@libs/skills/catalog/plugins/official-plugins/SKILL.md`:
- Around line 455-457: The fenced code block containing the header
"x-frontmcp-disable-cache: true" is unlabeled and triggers MD040; update that
fence by adding an appropriate language identifier (e.g., "http" or "yaml") so
it becomes a labeled code fence (referencing the existing fenced block with the
content "x-frontmcp-disable-cache: true"); ensure the opening triple-backtick
line is changed to include the chosen language identifier to restore syntax
highlighting and satisfy the linter.

In `@libs/skills/catalog/setup/frontmcp-skills-usage/SKILL.md`:
- Around line 122-140: The fenced code block showing the project tree in
SKILL.md is missing a language label which triggers MD040; update the opening
fence to include a language (for example change "```" to "```text") so the block
is labeled consistently; locate the directory-tree block in the SKILL.md content
(the snippet containing "my-project/" and the .claude/.codex directories) and
add the chosen language label to the opening fence.
- Around line 82-83: The SKILL.md wording claiming “Print the full SKILL.md
content to stdout” is misleading because the CLI command
(libs/cli/src/commands/skills/show.ts — the "skills show" command) actually
prepends metadata headers, strips frontmatter, and appends an install line
rather than outputting the raw file; update the wording at the referenced spots
(around lines 82-83, 154-155, 246-247) to state that the command prints a
processed/augmented version of SKILL.md (include notes: metadata headers added,
frontmatter removed, install line appended) so users and automation know it’s
not the unmodified file.

In `@libs/skills/catalog/setup/nx-workflow/SKILL.md`:
- Around line 273-309: The fenced directory-tree block in SKILL.md lacks a
language tag (causing MD040); update the fenced code block that shows the
my-project/ tree to use a language label by changing the opening fence to
```text so the tree output is treated as plain text (leave the closing ```
intact).

In `@libs/skills/catalog/setup/project-structure-nx/SKILL.md`:
- Around line 38-74: The Markdown tree/code fence blocks in SKILL.md (e.g., the
directory-tree block shown around the my-workspace example and the other
unlabeled fenced blocks at ranges 145-160 and 167-179) lack language
identifiers; update each triple-backtick fence to include an appropriate
language tag such as "text" (for directory trees) or "bash" (for command
examples) so that lint rule MD040 is satisfied, e.g., change ``` to ```text for
the tree blocks and to ```bash for shell snippets.

In `@libs/skills/catalog/setup/setup-project/SKILL.md`:
- Around line 386-387: Replace the unconditional append "echo \".env\" >>
.gitignore" with a guarded append that only writes the line if it isn't already
present; locate the existing echo command in SKILL.md and change it to perform a
presence check (e.g., use a grep -qxF or similar exact-line test for ".env" in
.gitignore) and only append the ".env" entry when the check fails so repeated
runs remain idempotent.

In `@libs/skills/catalog/testing/setup-testing/SKILL.md`:
- Around line 90-96: The fenced code block showing the project tree (the block
starting with ``` and the lines "src/  tools/  my-tool.ts  __tests__/ 
my-tool.spec.ts") lacks a language tag and triggers MD040; update that opening
fence to include a language (e.g., change ``` to ```text or ```bash) in SKILL.md
so the snippet is treated as plain text and the markdownlint warning is
resolved.

---

Nitpick comments:
In `@libs/skills/__tests__/skills-validation.spec.ts`:
- Around line 272-314: The NEW_FORMAT_SECTIONS constant is unused; update the
tests in the describe('new-format migration tracking') block (functions
getSkillBody and the it.each that uses findAllSkillDirs) to derive both the "is
migrated" check and the required-section assertions from NEW_FORMAT_SECTIONS
instead of hardcoded strings: compute isMigrated by confirming each
NEW_FORMAT_SECTIONS[].heading exists, increment migrated accordingly, and for
migrated skills loop over NEW_FORMAT_SECTIONS to assert
content.includes(section.required) (and any additional overall section like '##
Verification Checklist' can be kept or added to the array if desired);
alternatively, if you prefer the explicit literals, remove the unused
NEW_FORMAT_SECTIONS declaration.
- Around line 78-89: The tests repeatedly re-read and parse the manifest inside
multiple it.each blocks; extract the manifest load into a module-level constant
(e.g., const manifest = JSON.parse(fs.readFileSync(MANIFEST_PATH,'utf-8')) as
SkillManifest) and reuse manifest.skills for all it.each calls to avoid
redundant IO and parsing. Update the it.each invocations that currently use the
IIFE to reference the cached manifest (manifest.skills.map(...)) — look for
usages surrounding MANIFEST_PATH, SkillManifest, and the it.each blocks that
validate targets (VALID_TARGETS) and similar validations, and replace each IIFE
with the shared manifest constant.
- Around line 176-180: The test currently asserts string length using a type
assertion on metadata.instructions which isn't narrowed by the previous
toBeDefined check; update the test to first check the runtime type (e.g.,
expect(typeof metadata.instructions).toBe('string') or an if (typeof
metadata.instructions === 'string') guard) and only then assert
(metadata.instructions).length > 50 so the length check is executed safely and
TypeScript is satisfied; reference the metadata.instructions assertion in the
test block containing expect(metadata.name)...expect((metadata.instructions as
string).length).
- Around line 11-12: The test imports use node:fs and node:path directly; switch
to the project's recommended file utilities by replacing direct fs/path usage in
the test (skills-validation.spec.ts) with the corresponding helpers from
`@frontmcp/utils` (use the module's sync file-read/listing helpers or path
helpers) so file operations follow project conventions, or if `@frontmcp/utils`
lacks synchronous APIs, refactor the beforeAll/it.each setup to async/await and
use the async helpers from `@frontmcp/utils`; update the import statements and all
uses currently referencing fs and path in this file to use the `@frontmcp/utils`
functions (or convert the test setup to async and replace fs.*Sync calls with
async equivalents) to ensure consistency with coding guidelines.

In `@libs/skills/catalog/config/configure-transport/SKILL.md`:
- Around line 44-46: Replace one of the repetitive "you need to" phrases in the
SKILL.md excerpt to improve readability; specifically, modify either the
sentence "You need to set up plugin middleware without changing the transport
layer (use `configure-plugins` instead)" or the decision line beginning "Use
this skill whenever you need to..." so they don't both start with "you need to"
— for example, change the first to "Set up plugin middleware without changing
the transport layer (use `configure-plugins` instead)" or reword the decision
line to "Use this skill when choosing, combining, or customizing the protocol(s)
your MCP server exposes to clients." Ensure only one of the two lines is
rephrased to maintain clarity and tone.

In `@libs/skills/catalog/development/create-skill-with-tools/SKILL.md`:
- Around line 385-405: The docs for Skill.esm and Skill.remote lack loading
behavior details; update the SKILL.md section to clarify whether Skill.esm
expects the package to be pre-installed or will attempt installation, whether
loading is eager at registration or lazy on first access, and how errors are
surfaced (exceptions, logged warnings, or fallbacks) for unavailable remote
URLs; explicitly mention any authentication or network requirements and the
impact on skills: [ExternalSkill, CloudSkill] registration so consumers know
installation, timing, and error-handling expectations for Skill.esm and
Skill.remote.
- Around line 250-254: Update the SKILL.md example to clarify the async context
for using skillDir: mention that top-level await is valid in ES modules when
using "await skillDir(...)" and also provide an alternative showing how to call
skillDir inside an async function (e.g., a loadSkills function) so readers know
to either use top-level await or await within an async function when obtaining
DeployServiceSkill from skillDir.

In `@libs/skills/catalog/development/create-skill/SKILL.md`:
- Around line 26-28: In the "Recommended" bullets of SKILL.md where two items
start with "You want to…", change one bullet to avoid repeating the stem for
readability; for example, keep one as "You want to share workflow templates
across teams via MCP or HTTP discovery endpoints" and reword the other to "Share
workflow templates across teams via MCP or HTTP discovery endpoints" or "Use MCP
or HTTP discovery endpoints to share workflow templates across teams," updating
the second bullet in that section so the two bullets no longer both begin with
"You want to…".

In `@libs/skills/catalog/setup/setup-redis/SKILL.md`:
- Line 282: The fenced code block containing the snippet starting with
"@FrontMcp({ info: { name: 'my-server', version: '0.1.0' }," should be updated
to include a language specifier; add "typescript" after the opening ``` so the
block reads ```typescript to enable proper syntax highlighting for the
TypeScript-like snippet.
- Line 213: The fenced code block showing the redis config (starting with
"redis: {", "provider: 'vercel-kv'", "url: process.env['KV_REST_API_URL']") is
missing a language specifier; update the opening fence from ``` to ```typescript
so the block reads as a TypeScript fenced code block to enable proper syntax
highlighting and tooling.
- Around line 308-312: The numbered conditional list in SKILL.md (items 1–4)
repeats "If" at the start of several lines; rephrase to vary sentence openings
for readability by changing at least two items to different constructions (e.g.,
start item 1 with "When the global `redis` config is set and
`transport.persistence` is not configured, persistence is auto-enabled...", item
2 with "Setting `transport.persistence` to `false` disables persistence.", item
3 with "Provide an explicit `transport.persistence.redis` to use that
configuration.", and item 4 with "When `transport.persistence` is an object that
lacks `redis`, inject the global redis config."); preserve the original meaning
and the conditional logic order while only adjusting wording for clarity.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 038beade-bcf0-498e-b2b7-15af178712dd

📥 Commits

Reviewing files that changed from the base of the PR and between a37fd2e and 36abe4a.

📒 Files selected for processing (39)
  • libs/skills/__tests__/skills-validation.spec.ts
  • libs/skills/catalog/TEMPLATE.md
  • libs/skills/catalog/adapters/create-adapter/SKILL.md
  • libs/skills/catalog/adapters/official-adapters/SKILL.md
  • libs/skills/catalog/auth/configure-auth/SKILL.md
  • libs/skills/catalog/auth/configure-session/SKILL.md
  • libs/skills/catalog/config/configure-elicitation/SKILL.md
  • libs/skills/catalog/config/configure-http/SKILL.md
  • libs/skills/catalog/config/configure-throttle/SKILL.md
  • libs/skills/catalog/config/configure-transport/SKILL.md
  • libs/skills/catalog/deployment/build-for-browser/SKILL.md
  • libs/skills/catalog/deployment/build-for-cli/SKILL.md
  • libs/skills/catalog/deployment/build-for-sdk/SKILL.md
  • libs/skills/catalog/deployment/deploy-to-cloudflare/SKILL.md
  • libs/skills/catalog/deployment/deploy-to-lambda/SKILL.md
  • libs/skills/catalog/deployment/deploy-to-node/SKILL.md
  • libs/skills/catalog/deployment/deploy-to-vercel/SKILL.md
  • libs/skills/catalog/development/create-agent/SKILL.md
  • libs/skills/catalog/development/create-job/SKILL.md
  • libs/skills/catalog/development/create-prompt/SKILL.md
  • libs/skills/catalog/development/create-provider/SKILL.md
  • libs/skills/catalog/development/create-resource/SKILL.md
  • libs/skills/catalog/development/create-skill-with-tools/SKILL.md
  • libs/skills/catalog/development/create-skill/SKILL.md
  • libs/skills/catalog/development/create-tool/SKILL.md
  • libs/skills/catalog/development/create-workflow/SKILL.md
  • libs/skills/catalog/development/decorators-guide/SKILL.md
  • libs/skills/catalog/plugins/create-plugin-hooks/SKILL.md
  • libs/skills/catalog/plugins/create-plugin/SKILL.md
  • libs/skills/catalog/plugins/official-plugins/SKILL.md
  • libs/skills/catalog/setup/frontmcp-skills-usage/SKILL.md
  • libs/skills/catalog/setup/multi-app-composition/SKILL.md
  • libs/skills/catalog/setup/nx-workflow/SKILL.md
  • libs/skills/catalog/setup/project-structure-nx/SKILL.md
  • libs/skills/catalog/setup/project-structure-standalone/SKILL.md
  • libs/skills/catalog/setup/setup-project/SKILL.md
  • libs/skills/catalog/setup/setup-redis/SKILL.md
  • libs/skills/catalog/setup/setup-sqlite/SKILL.md
  • libs/skills/catalog/testing/setup-testing/SKILL.md
✅ Files skipped from review due to trivial changes (21)
  • libs/skills/catalog/auth/configure-session/SKILL.md
  • libs/skills/catalog/config/configure-http/SKILL.md
  • libs/skills/catalog/TEMPLATE.md
  • libs/skills/catalog/config/configure-elicitation/SKILL.md
  • libs/skills/catalog/deployment/build-for-browser/SKILL.md
  • libs/skills/catalog/deployment/deploy-to-vercel/SKILL.md
  • libs/skills/catalog/development/create-provider/SKILL.md
  • libs/skills/catalog/development/create-agent/SKILL.md
  • libs/skills/catalog/adapters/create-adapter/SKILL.md
  • libs/skills/catalog/setup/setup-sqlite/SKILL.md
  • libs/skills/catalog/deployment/deploy-to-node/SKILL.md
  • libs/skills/catalog/plugins/create-plugin/SKILL.md
  • libs/skills/catalog/development/create-prompt/SKILL.md
  • libs/skills/catalog/deployment/deploy-to-cloudflare/SKILL.md
  • libs/skills/catalog/setup/multi-app-composition/SKILL.md
  • libs/skills/catalog/setup/project-structure-standalone/SKILL.md
  • libs/skills/catalog/development/create-job/SKILL.md
  • libs/skills/catalog/development/create-workflow/SKILL.md
  • libs/skills/catalog/development/create-resource/SKILL.md
  • libs/skills/catalog/deployment/deploy-to-lambda/SKILL.md
  • libs/skills/catalog/development/create-tool/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/skills/catalog/deployment/build-for-cli/SKILL.md

Comment on lines +213 to +238
@App({
auth: {
mode: 'remote',
provider: 'https://auth.example.com',
clientId: 'mcp-client-id',
},
vault: {
encryption: {
secret: process.env['VAULT_SECRET'],
},
providers: [
{
name: 'github',
type: 'oauth2',
scopes: ['repo', 'read:user'],
},
{
name: 'slack',
type: 'oauth2',
scopes: ['chat:write', 'channels:read'],
},
],
},
})
class MyApp {}
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check for similar vault/auth configuration patterns in the codebase

# Search for vault configuration examples
echo "=== Searching for vault configuration patterns ==="
rg -n --type=ts 'vault.*:.*\{' libs/ apps/ -A 10 -g '!node_modules' -g '!dist' | head -50

# Search for process.env usage in `@App` decorators
echo -e "\n=== Searching for process.env in `@App` decorators ==="
rg -nP --type=ts '@App\s*\(' -A 20 | rg 'process\.env' -C 3

# Check for vault secret documentation
echo -e "\n=== Searching for VAULT_SECRET documentation ==="
fd -e md -e mdx . | xargs rg -l 'VAULT_SECRET' | head -5

Repository: agentfront/frontmcp

Length of output: 4290


🏁 Script executed:

# Find vault-related type definitions and configurations
fd -e ts -e tsx --type f . | xargs rg -l "type.*[Vv]ault.*Config\|interface.*[Vv]ault" libs/ | head -10

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Search for actual vault encryption configuration in source code
rg -n "encryption.*secret|secret.*encryption" libs/auth -B 3 -A 3 --type ts

Repository: agentfront/frontmcp

Length of output: 1906


🏁 Script executed:

# Check what cryptographic utilities are available in frontmcp/utils
fd -e ts -e tsx "utils" libs/ | xargs cat 2>/dev/null | head -100

Repository: agentfront/frontmcp

Length of output: 2949


🏁 Script executed:

# Look for `@App` decorator definition and its vault config structure
ast-grep --pattern '@App' libs/

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Find the `@App` decorator definition
rg -n "export.*@App|export.*function App|class App" libs/ -A 10 --type ts | head -50

Repository: agentfront/frontmcp

Length of output: 4110


🏁 Script executed:

# Look for vault-related type definitions
rg -n "vault.*Config|vault.*Options|type.*Vault" libs/ --type ts | grep -E "type|interface" | head -20

Repository: agentfront/frontmcp

Length of output: 2690


🏁 Script executed:

# Read the SKILL.md file directly to see full context
cat "libs/skills/catalog/auth/configure-auth/SKILL.md" | sed -n '200,250p'

Repository: agentfront/frontmcp

Length of output: 1361


🏁 Script executed:

# Search for how vault is actually used in examples or tests
rg -n "vault:" libs/ --type ts -B 2 -A 8 | head -60

Repository: agentfront/frontmcp

Length of output: 5127


🏁 Script executed:

# Find `@App` decorator definition
rg -n "export.*function.*App\(|export.*const.*App|@.*decorator" libs/sdk -A 15 --type ts | head -100

Repository: agentfront/frontmcp

Length of output: 6826


🏁 Script executed:

# Search for vault configuration processing and type definitions
rg -n "vault.*encryption\|VaultConfig\|vault.*secret" libs/sdk -B 2 -A 5 --type ts | head -100

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Check if frontmcp/utils has vault or crypto exports
fd "utils" libs/ -name "index.ts" -o -name "*.ts" | xargs rg -l "export.*encrypt\|export.*crypto\|export.*vault" | head -10

Repository: agentfront/frontmcp

Length of output: 293


🏁 Script executed:

# Search for how vault is configured in tests or examples
rg -n "@App\(" libs/ --type ts -A 30 | grep -A 30 "vault:" | head -60

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Search for `@App` decorator definition
find libs/sdk -name "*.ts" | xargs grep -l "export.*App" | head -5

Repository: agentfront/frontmcp

Length of output: 275


🏁 Script executed:

# Look for decorators directory
fd -t d decorators libs/

Repository: agentfront/frontmcp

Length of output: 168


🏁 Script executed:

# Search for vault configuration schema or validation
rg -n "vault.*secret\|VaultConfig\|vault.*encryption" libs/sdk libs/auth --type ts | head -40

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Find frontmcp/utils module
fd -t f "utils" libs/ | grep -E "utils/(index|crypto|auth)" | head -10

Repository: agentfront/frontmcp

Length of output: 156


🏁 Script executed:

# Check package.json to understand module structure
cat libs/sdk/package.json | grep -A 5 '"exports"'

Repository: agentfront/frontmcp

Length of output: 224


🏁 Script executed:

# Find `@App` decorator in decorators
fd -t f "\.ts$" libs/sdk/src/common/decorators/ | xargs grep -l "App\|app" | head -5

Repository: agentfront/frontmcp

Length of output: 398


🏁 Script executed:

# Search in di decorators
fd -t f "\.ts$" libs/di/src/decorators/ | xargs grep -l "App" | head -5

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Look for vault configuration in schema or types
rg -n "vault.*:" libs/sdk/src -A 5 --type ts | head -60

Repository: agentfront/frontmcp

Length of output: 3255


🏁 Script executed:

# Check if there's a separate utils package with crypto functions
fd -t f "index.ts" libs/ | xargs grep -l "crypto\|encrypt\|vault" | head -10

Repository: agentfront/frontmcp

Length of output: 420


🏁 Script executed:

# Read the `@App` decorator file if found
cat libs/sdk/src/common/decorators/index.ts 2>/dev/null | head -100

Repository: agentfront/frontmcp

Length of output: 641


🏁 Script executed:

# Read the `@App` decorator implementation
cat libs/sdk/src/common/decorators/app.decorator.ts | head -150

Repository: agentfront/frontmcp

Length of output: 4995


🏁 Script executed:

# Also check for vault-related types in auth/vault
cat libs/auth/src/vault/index.ts

Repository: agentfront/frontmcp

Length of output: 1707


🏁 Script executed:

# Look for vault configuration schema
rg -n "AuthProvidersVaultOptions\|vault.*Options" libs/ --type ts -B 2 -A 8 | head -80

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Find the AuthProvidersVaultOptions type definition
rg -n "AuthProvidersVaultOptions" libs/ --type ts -B 5 -A 15 | head -100

Repository: agentfront/frontmcp

Length of output: 7619


🏁 Script executed:

# Search for where vault configuration is used in metadata
rg -n "vault.*Config\|vault:" libs/sdk/src/common -A 5 --type ts | head -60

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Check the metadata schema for vault configuration
fd -t f "metadata" libs/sdk/src/common | xargs cat | head -200

Repository: agentfront/frontmcp

Length of output: 7457


🏁 Script executed:

# Find the full AuthProvidersVaultOptions interface definition
rg -n "export interface AuthProvidersVaultOptions" libs/auth/src/vault -A 50 --type ts

Repository: agentfront/frontmcp

Length of output: 4070


🏁 Script executed:

# Search for encryption-related properties in vault options
rg -n "encryption\|secret" libs/auth/src/vault/auth-providers.types.ts --type ts | head -30

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Check if there's documentation about vault encryption configuration
fd -e md "*.md" libs/skills/catalog/auth | xargs grep -l "encryption\|secret" | head -5

Repository: agentfront/frontmcp

Length of output: 346


🏁 Script executed:

# Check for LocalAppMetadata to see if vault config is defined there
rg -n "vault\|encryption" libs/sdk/src/common/metadata/front-mcp.metadata.ts --type ts -B 2 -A 5 | head -80

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Look at session vault encryption configuration
rg -n "export.*type.*Vault\|interface.*Vault" libs/auth/src/session -A 10 --type ts | head -100

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Search for how encryption secret is actually handled in the codebase
rg -n "VAULT_SECRET\|encryption.*secret\|secret.*encryption" libs/ --type ts | head -30

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Check the LocalAppMetadata type definition to see what fields are actually supported
rg -n "interface LocalAppMetadata\|type LocalAppMetadata" libs/sdk/src/common/metadata --type ts -A 40 | head -100

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Look at the schema validation for `@App` decorator
rg -n "frontMcpLocalAppMetadataSchema" libs/sdk/src/common/metadata --type ts -A 50 | head -120

Repository: agentfront/frontmcp

Length of output: 4304


🏁 Script executed:

# Check what the SKILL.md is documenting - search context around vault encryption
sed -n '200,250p' "libs/skills/catalog/auth/configure-auth/SKILL.md"

Repository: agentfront/frontmcp

Length of output: 1361


Remove the incorrect vault configuration example or correct it to match the actual API.

The example shows vault: { encryption: { secret: ... }, providers: [...] } in the @App decorator, but this doesn't match the actual metadata schema. The @App decorator does not accept a vault field, and AuthProvidersVaultOptions has no encryption property.

The actual vault configuration is handled through the authProviders field and must be set up via the app's dependency injection context, not through decorator metadata. If vault credential encryption is required, use the cryptographic utilities from frontmcp/utils rather than directly passing environment variables to decorators.

Either provide the correct API usage pattern or remove this example until the documentation can accurately reflect how vault encryption is configured in FrontMCP.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/auth/configure-auth/SKILL.md` around lines 213 - 238, The
example in the `@App` decorator is incorrect: remove the vault: { encryption: ...,
providers: [...] } block or replace it with the correct usage that uses
authProviders and DI instead; specifically stop passing vault/encryption to the
`@App` metadata (the decorator does not accept a vault field and
AuthProvidersVaultOptions has no encryption property), and instead configure
vault providers via the app's dependency-injection setup (use the authProviders
configuration entry and initialize any credential encryption using the
cryptographic helpers in frontmcp/utils), ensuring references to
AuthProvidersVaultOptions and authProviders are used rather than adding a vault
key to `@App`.

Comment on lines +177 to +185
```typescript
throttle: {
enabled: true,
storage: {
type: 'redis',
redis: { provider: 'redis', host: 'redis.internal' },
},
global: { maxRequests: 1000, windowMs: 60000 },
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read-only verification: find canonical throttle/guard config types and redis examples.

set -euo pipefail

echo "== Type/interface declarations related to throttle/guard/storage =="
rg -n --type=ts -C3 '\b(interface|type)\s+\w*(Throttle|Guard|RateLimit|Concurrency|IpFilter|Storage)\w*\b|storage\s*:\s*\{|type\s*:\s*["'\'']redis["'\'']'

echo
echo "== Decorator usage examples of throttle + redis =="
rg -n --type=ts -C4 '@FrontMcp\s*\(|throttle\s*:\s*\{|storage\s*:\s*\{|redis\s*:\s*\{'

echo
echo "== Existing docs/snippets referencing throttle redis config =="
rg -n -C3 'throttle\s*:|storage\s*:|type:\s*'\''redis'\''|trustedProxyDepth|ipFilter'

Repository: agentfront/frontmcp

Length of output: 50378


🏁 Script executed:

rg -n --type=ts 'throttle\s*:\s*\{' libs/guard -A 8 -B 2

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Find the guard config schema definition
rg -n 'export.*guardConfigSchema|throttle.*Config.*interface|type.*GuardConfig' libs/guard/src -A 5

Repository: agentfront/frontmcp

Length of output: 3288


🏁 Script executed:

# Check the exact storage field pattern in guard config
rg -n 'storage\s*\?' libs/guard/src/schemas -B 3 -A 3

Repository: agentfront/frontmcp

Length of output: 606


🏁 Script executed:

# Search for throttle decorator or config examples in actual skill files
find libs/skills -name '*.ts' -o -name '*.md' | head -20 | xargs grep -l 'throttle' 2>/dev/null | head -5

Repository: agentfront/frontmcp

Length of output: 168


🏁 Script executed:

cat -n libs/skills/catalog/config/configure-throttle/SKILL.md | head -200

Repository: agentfront/frontmcp

Length of output: 8550


🏁 Script executed:

rg -n 'interface.*Throttle|type.*Throttle|throttle.*:' libs/guard/src -A 5 | head -60

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Look for actual throttle storage config examples in tests
rg -n 'throttle.*storage|redis.*throttle|throttle.*redis' --type=ts -C 3

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Look for how guard actually processes the redis storage config
rg -n 'createGuardManager|GuardFactory|redis.*storage|storage.*redis' libs/guard/src -A 5 -B 2 | head -100

Repository: agentfront/frontmcp

Length of output: 7519


🏁 Script executed:

# Search for actual Redis config handling in guard factory
cat -n libs/guard/src/manager/guard.factory.ts | head -100

Repository: agentfront/frontmcp

Length of output: 1937


🏁 Script executed:

# Find where storage config is processed
rg -n 'storage\[' libs/guard/src -A 3 -B 2

Repository: agentfront/frontmcp

Length of output: 45


🏁 Script executed:

# Get the full StorageConfig interface definition
cat -n libs/utils/src/storage/types.ts | sed -n '475,520p'

Repository: agentfront/frontmcp

Length of output: 1465


🏁 Script executed:

# Look for redis storage config options specifically
rg -n 'interface.*Redis.*Storage|redis.*url|redis.*host.*port' libs/utils/src/storage -A 4 -B 1 | head -80

Repository: agentfront/frontmcp

Length of output: 2459


🏁 Script executed:

# Check what the actual redis adapter config interface looks like
cat -n libs/utils/src/storage/adapters/redis.ts | head -80

Repository: agentfront/frontmcp

Length of output: 3222


🏁 Script executed:

# Get the RedisAdapterOptions interface definition
rg -n 'interface RedisAdapterOptions|type RedisAdapterOptions' libs/utils/src/storage/types.ts -A 15

Repository: agentfront/frontmcp

Length of output: 507


🏁 Script executed:

# Check if there's any code that uses the provider field in redis config
rg -n 'provider.*redis|redis.*provider' libs/guard libs/sdk libs/utils --type=ts | grep -v test | head -20

Repository: agentfront/frontmcp

Length of output: 2429


🏁 Script executed:

# Verify the exact RedisAdapterOptions definition including url field
cat -n libs/utils/src/storage/types.ts | sed -n '382,410p'

Repository: agentfront/frontmcp

Length of output: 869


🏁 Script executed:

# Check if guard docs or examples show the correct redis pattern
rg -n 'redis.*host.*port|redis.*url' libs/guard -A 2 -B 2

Repository: agentfront/frontmcp

Length of output: 825


Remove the incorrect provider field from the Redis storage example.

The storage config shape at lines 177-185 includes provider: 'redis' which is not part of the RedisAdapterOptions interface. Correct the example to use either the config object (with host and port) or the url string:

Corrected Redis storage config examples
// Option 1: Using config with host/port
throttle: {
  enabled: true,
  storage: {
    type: 'redis',
    redis: { config: { host: 'redis.internal', port: 6379 } },
  },
  global: { maxRequests: 1000, windowMs: 60000 },
}
// Option 2: Using url string
throttle: {
  enabled: true,
  storage: {
    type: 'redis',
    redis: { url: 'redis://redis.internal:6379' },
  },
  global: { maxRequests: 1000, windowMs: 60000 },
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/config/configure-throttle/SKILL.md` around lines 177 -
185, The Redis storage example under the throttle config incorrectly includes a
non-existent provider field; update the throttle.storage.redis object in
SKILL.md to match the RedisAdapterOptions shape by removing provider and using
either a config object (e.g., config with host and port) or a url string (e.g.,
redis://host:port); ensure the example under the throttle key (the throttle: {
enabled..., storage: { type: 'redis', redis: ... }, global: ... } block) shows
one of these valid forms instead of redis: { provider: 'redis', ... }.

Comment on lines +83 to +89
tool({
name: 'calculate',
description: 'Perform calculation',
inputSchema: { expression: z.string() },
outputSchema: { result: z.number() },
})((input) => ({ result: eval(input.expression) })),
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Replace eval in the example with a safe implementation.

Using eval(input.expression) in a canonical docs example normalizes arbitrary code execution from user input. Please switch to a constrained parser or a fixed-operation example.

🔧 Suggested doc-safe replacement
 const server = await create({
   info: { name: 'my-service', version: '1.0.0' },
   tools: [
     tool({
       name: 'calculate',
-      description: 'Perform calculation',
-      inputSchema: { expression: z.string() },
+      description: 'Add two numbers',
+      inputSchema: { a: z.number(), b: z.number() },
       outputSchema: { result: z.number() },
-    })((input) => ({ result: eval(input.expression) })),
+    })((input) => ({ result: input.a + input.b })),
   ],
   cacheKey: 'my-service', // Reuse same instance on repeated calls
 });
 
 // Call tools directly
-const result = await server.callTool('calculate', { expression: '2 + 2' });
+const result = await server.callTool('calculate', { a: 2, b: 2 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/deployment/build-for-sdk/SKILL.md` around lines 83 - 89,
The example uses eval(input.expression) in the tool named "calculate", which
allows arbitrary code execution; replace it with a safe, constrained
implementation such as parsing a limited expression grammar or switching the
tool inputSchema to explicit operands and an operator (e.g., inputSchema: { a:
z.number(), b: z.number(), op: z.enum(['+', '-', '*', '/']) }) and implement the
calculation in the tool handler (the tool(...)((input) => ...)) using only those
allowed operations instead of eval; update outputSchema accordingly to return
the numeric result.

Comment on lines +257 to +264
parameters:
- name: language
description: Target programming language
type: string
default: typescript
examples:
- scenario: Apply coding standards to a new module
expected-outcome: Code follows all project conventions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify canonical field name in skills types/parsers/docs.
rg -n -C3 "expectedOutcome|expected-outcome" libs/skills --type ts --type md
rg -n -C4 "interface\\s+SkillExample|type\\s+SkillExample" libs/skills --type ts
rg -n -C4 "examples\\s*:" libs/skills/src --type ts

Repository: agentfront/frontmcp

Length of output: 30457


Normalize example field naming to expectedOutcome.

Line 264 uses expected-outcome in the YAML example, but the TypeScript interface definition (line 178) declares the field as expectedOutcome (camelCase). The same file's code examples (lines 305–314, 498) and validation checklist (line 562) all reference expectedOutcome. This inconsistency causes incorrect copy-paste usage.

Proposed doc fix
 examples:
   - scenario: Apply coding standards to a new module
-    expected-outcome: Code follows all project conventions
+    expectedOutcome: Code follows all project conventions
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
parameters:
- name: language
description: Target programming language
type: string
default: typescript
examples:
- scenario: Apply coding standards to a new module
expected-outcome: Code follows all project conventions
parameters:
- name: language
description: Target programming language
type: string
default: typescript
examples:
- scenario: Apply coding standards to a new module
expectedOutcome: Code follows all project conventions
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/development/create-skill/SKILL.md` around lines 257 -
264, The YAML example uses the kebab-case key "expected-outcome" which
mismatches the TS interface field expectedOutcome; update the example and any
other occurrences in SKILL.md (the example block and other examples/validation
checklist referencing "expected-outcome") to use the camelCase key
expectedOutcome so examples match the TypeScript interface and other code
samples.

Comment on lines +234 to +243
## Using Hooks Inside a @Tool Class

You can add hook methods directly on a `@Tool` class to intercept its own execution flow. The hooks apply only when **this tool** is called:

```typescript
import { Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

const { Will, Did } = ToolHook;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Missing import: ToolHook is not imported.

Line 242 destructures ToolHook but it's never imported. This will cause a ReferenceError at runtime.

🐛 Proposed fix
 import { Tool, ToolContext } from '@frontmcp/sdk';
+import { ToolHook } from '@frontmcp/sdk';
 import { z } from 'zod';
 
 const { Will, Did } = ToolHook;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/plugins/create-plugin-hooks/SKILL.md` around lines 234 -
243, The docs show destructuring "const { Will, Did } = ToolHook" but never
imports ToolHook, which will cause a runtime ReferenceError; add ToolHook to the
import list from the SDK where Tool and ToolContext are imported (i.e., import
Tool, ToolContext, ToolHook from '@frontmcp/sdk') so the destructuring of
ToolHook (and use of Will/Did) resolves correctly.

Comment on lines +140 to +160
The `@frontmcp/nx-plugin` package provides generators for all entity types:

```bash
# Generate a new app
nx g @frontmcp/nx-plugin:app crm

# Generate entities within an app
nx g @frontmcp/nx-plugin:tool lookup-user --project=crm
nx g @frontmcp/nx-plugin:resource user-profile --project=crm
nx g @frontmcp/nx-plugin:prompt summarize --project=crm
nx g @frontmcp/nx-plugin:provider database --project=crm
nx g @frontmcp/nx-plugin:plugin logging --project=crm
nx g @frontmcp/nx-plugin:agent research --project=crm
nx g @frontmcp/nx-plugin:job cleanup --project=crm

# Generate a new server
nx g @frontmcp/nx-plugin:server gateway

# Generate a shared library
nx g @frontmcp/nx-plugin:lib shared-utils
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Checking generator namespace usage in changed docs..."
rg -n "@frontmcp/nx-plugin:|@frontmcp/nx:" libs/skills/catalog/setup/project-structure-nx/SKILL.md

echo
echo "Checking nx plugin package naming in repository metadata..."
rg -n "\"name\"\\s*:\\s*\"@frontmcp/nx\"|\"name\"\\s*:\\s*\"@frontmcp/nx-plugin\"|@frontmcp/nx-plugin|@frontmcp/nx" package.json libs/**/package.json libs/nx-plugin/project.json 2>/dev/null || true

echo
echo "Checking generator examples in other skill docs for consistency..."
rg -n "@frontmcp/nx-plugin:|@frontmcp/nx:" libs/skills/catalog/setup/**/*.md

Repository: agentfront/frontmcp

Length of output: 10160


Use the correct Nx plugin namespace in all generator commands (@frontmcp/nx:*).

The examples in lines 140-160 and 238-240 use @frontmcp/nx-plugin:*, which is incorrect. The actual package name is @frontmcp/nx (defined in libs/nx-plugin/package.json). This mismatch will cause copy-paste command failures. All other skill documentation files correctly use @frontmcp/nx:* commands—align this file with that standard.

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 145-145: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/skills/catalog/setup/project-structure-nx/SKILL.md` around lines 140 -
160, Update the generator command examples in SKILL.md to use the correct Nx
plugin namespace `@frontmcp/nx:*` instead of `@frontmcp/nx-plugin:*`: replace
occurrences like `nx g `@frontmcp/nx-plugin`:app crm` and `nx g
`@frontmcp/nx-plugin`:tool lookup-user --project=crm` with `nx g `@frontmcp/nx`:app
crm` and `nx g `@frontmcp/nx`:tool lookup-user --project=crm` (and similarly for
resource, prompt, provider, plugin, agent, job, server, lib examples); verify
against the actual package name defined in `libs/nx-plugin/package.json` to
ensure all examples consistently use `@frontmcp/nx`.

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.

1 participant