feat: add skill directory generator and CLI commands for skills management#311
feat: add skill directory generator and CLI commands for skills management#311frontegg-david wants to merge 20 commits intorelease/1.0.xfrom
Conversation
…h --target option
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a publishable Changes
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
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
Performance Test ResultsStatus: ✅ All tests passed Summary
Total: 101 tests across 21 projects 📊 View full report in workflow run Generated at: 2026-03-27T11:19:44.404Z |
# 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
There was a problem hiding this comment.
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 | 🟡 MinorClarify 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 installationIf 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 | 🟡 MinorFix 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 | 🟡 MinorReplace
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 | 🟡 MinorAdd language specifier to fenced code block.
The stage sequence diagram lacks a language specifier, which triggers a markdownlint warning. Consider using
textorplaintextfor 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.mdaround 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 usetext (orplaintext) 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.mdaround 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. changetotext
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.mdat 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., changetotext) 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.mdat 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.mdat line 16,
Add explicit language identifiers to every directory-tree code fence (the
triple-backtick blocks that show folder trees) by replacing barefences 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.mdaround 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., changetotext) 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.mdat 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 openingso 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.mdaround 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., changetotext) 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.mdaround 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 fromtotext 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.mdaround 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.mdaround lines 7 - 16, Update the fenced code block that
lists the directory structure (the block beginning withand containing "catalog/ ├── skills-manifest.json ...") to include a language specifier by changing the opening fence fromtotext so the block becomestext 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.mdaround 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.mdaround 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 openingtotext) 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.mdaround 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 readstext before the log line and closes withafter 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.mdaround
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., changetotext) and update the HTTP examples that show requests like "GET /llm.txt"
and "GET /skills" to use the http specifier (e.g., changetohttp) 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.mdaround 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 -->
…mprove error handling
…andle module boundaries
…andle module boundaries
There was a problem hiding this comment.
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
📒 Files selected for processing (2)
libs/skills/__tests__/skills-validation.spec.tslibs/skills/eslint.config.mjs
✅ Files skipped from review due to trivial changes (1)
- libs/skills/tests/skills-validation.spec.ts
…ation structure and clarity
There was a problem hiding this comment.
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 | 🟡 MinorAdd 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.mdaround lines 90 - 96, The
fenced code block showing the project tree (the block starting withand 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., changetotext orbash) 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.mdaround 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., changetotext 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.mdaround 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.mdaround 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 totext so the tree output is treated as plain text (leave the closingintact).</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.mdaround 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.mdaround
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 changetotext).</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.mdaround
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) fromtohttp (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.mdaround
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 uselibs/skills/catalog/config/configure-throttle/SKILL.md-44-46 (1)
44-46:⚠️ Potential issue | 🟡 MinorTighten 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 | 🟡 MinorAdd 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.mdaround 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')
Either:
- Add prompt hook exports if they should be available, or
- Remove
prompts:get-promptandprompts:list-promptsfrom the Available Flow Names table and note that prompt flows require usingFlowHooksOf()directlyConsider 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 | 🟡 MinorFix 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 skillconfigure-session-store— skill not found; the actual skill isconfigure-sessioncreate-plugin— exists and reference is validReplace 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` insteadAlso 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 | 🟡 MinorAdd import statements to all code examples to match documentation patterns used in other skills.
The code examples in this documentation use
@Appand related decorators without showing where they're imported from. Whilecreate-plugin.mdincludes import statements likeimport { App, FrontMcp } from '@frontmcp/sdk', these examples inconfigure-auth.mdlack 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_SECTIONSis defined but not used; validation uses hardcoded strings.The constant
NEW_FORMAT_SECTIONS(line 273) defines a structured array withheadingandrequiredfields, but the actual validation logic on lines 284, 303, and 310-313 uses hardcoded string literals instead. Consider either:
- Using the constant to drive validation dynamically, or
- 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 init.eachblocks.The manifest is loaded and parsed 6 times in the
describe('manifest entries')block, once perit.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.eachblocks 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 oninstructions.Line 179 uses a type assertion
(metadata.instructions as string)which could fail ifinstructionsis undefined or not a string. The precedingexpect(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/utilsfor file system operations.Per coding guidelines, file system operations should use
@frontmcp/utilsrather thannode:fsdirectly. However, since this is a test file using synchronous operations for validation setup (where async would complicatebeforeAllandit.eachpatterns), this deviation may be acceptable.If
@frontmcp/utilsprovides 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
awaitwithout 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.mdaround
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
typescriptto 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
📒 Files selected for processing (39)
libs/skills/__tests__/skills-validation.spec.tslibs/skills/catalog/TEMPLATE.mdlibs/skills/catalog/adapters/create-adapter/SKILL.mdlibs/skills/catalog/adapters/official-adapters/SKILL.mdlibs/skills/catalog/auth/configure-auth/SKILL.mdlibs/skills/catalog/auth/configure-session/SKILL.mdlibs/skills/catalog/config/configure-elicitation/SKILL.mdlibs/skills/catalog/config/configure-http/SKILL.mdlibs/skills/catalog/config/configure-throttle/SKILL.mdlibs/skills/catalog/config/configure-transport/SKILL.mdlibs/skills/catalog/deployment/build-for-browser/SKILL.mdlibs/skills/catalog/deployment/build-for-cli/SKILL.mdlibs/skills/catalog/deployment/build-for-sdk/SKILL.mdlibs/skills/catalog/deployment/deploy-to-cloudflare/SKILL.mdlibs/skills/catalog/deployment/deploy-to-lambda/SKILL.mdlibs/skills/catalog/deployment/deploy-to-node/SKILL.mdlibs/skills/catalog/deployment/deploy-to-vercel/SKILL.mdlibs/skills/catalog/development/create-agent/SKILL.mdlibs/skills/catalog/development/create-job/SKILL.mdlibs/skills/catalog/development/create-prompt/SKILL.mdlibs/skills/catalog/development/create-provider/SKILL.mdlibs/skills/catalog/development/create-resource/SKILL.mdlibs/skills/catalog/development/create-skill-with-tools/SKILL.mdlibs/skills/catalog/development/create-skill/SKILL.mdlibs/skills/catalog/development/create-tool/SKILL.mdlibs/skills/catalog/development/create-workflow/SKILL.mdlibs/skills/catalog/development/decorators-guide/SKILL.mdlibs/skills/catalog/plugins/create-plugin-hooks/SKILL.mdlibs/skills/catalog/plugins/create-plugin/SKILL.mdlibs/skills/catalog/plugins/official-plugins/SKILL.mdlibs/skills/catalog/setup/frontmcp-skills-usage/SKILL.mdlibs/skills/catalog/setup/multi-app-composition/SKILL.mdlibs/skills/catalog/setup/nx-workflow/SKILL.mdlibs/skills/catalog/setup/project-structure-nx/SKILL.mdlibs/skills/catalog/setup/project-structure-standalone/SKILL.mdlibs/skills/catalog/setup/setup-project/SKILL.mdlibs/skills/catalog/setup/setup-redis/SKILL.mdlibs/skills/catalog/setup/setup-sqlite/SKILL.mdlibs/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
| @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 {} | ||
| ``` |
There was a problem hiding this comment.
🧩 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 -5Repository: 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 -10Repository: 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 tsRepository: 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 -100Repository: 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 -50Repository: 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 -20Repository: 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 -60Repository: 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 -100Repository: 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 -100Repository: 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 -10Repository: 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 -60Repository: agentfront/frontmcp
Length of output: 45
🏁 Script executed:
# Search for `@App` decorator definition
find libs/sdk -name "*.ts" | xargs grep -l "export.*App" | head -5Repository: 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 -40Repository: agentfront/frontmcp
Length of output: 45
🏁 Script executed:
# Find frontmcp/utils module
fd -t f "utils" libs/ | grep -E "utils/(index|crypto|auth)" | head -10Repository: 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 -5Repository: 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 -5Repository: 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 -60Repository: 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 -10Repository: 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 -100Repository: agentfront/frontmcp
Length of output: 641
🏁 Script executed:
# Read the `@App` decorator implementation
cat libs/sdk/src/common/decorators/app.decorator.ts | head -150Repository: agentfront/frontmcp
Length of output: 4995
🏁 Script executed:
# Also check for vault-related types in auth/vault
cat libs/auth/src/vault/index.tsRepository: 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 -80Repository: agentfront/frontmcp
Length of output: 45
🏁 Script executed:
# Find the AuthProvidersVaultOptions type definition
rg -n "AuthProvidersVaultOptions" libs/ --type ts -B 5 -A 15 | head -100Repository: 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 -60Repository: 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 -200Repository: 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 tsRepository: 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 -30Repository: 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 -5Repository: 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 -80Repository: 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 -100Repository: 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 -30Repository: 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 -100Repository: 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 -120Repository: 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`.
| ```typescript | ||
| throttle: { | ||
| enabled: true, | ||
| storage: { | ||
| type: 'redis', | ||
| redis: { provider: 'redis', host: 'redis.internal' }, | ||
| }, | ||
| global: { maxRequests: 1000, windowMs: 60000 }, | ||
| } |
There was a problem hiding this comment.
🧩 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 2Repository: 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 5Repository: 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 3Repository: 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 -5Repository: agentfront/frontmcp
Length of output: 168
🏁 Script executed:
cat -n libs/skills/catalog/config/configure-throttle/SKILL.md | head -200Repository: agentfront/frontmcp
Length of output: 8550
🏁 Script executed:
rg -n 'interface.*Throttle|type.*Throttle|throttle.*:' libs/guard/src -A 5 | head -60Repository: 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 3Repository: 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 -100Repository: 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 -100Repository: agentfront/frontmcp
Length of output: 1937
🏁 Script executed:
# Find where storage config is processed
rg -n 'storage\[' libs/guard/src -A 3 -B 2Repository: 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 -80Repository: 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 -80Repository: 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 15Repository: 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 -20Repository: 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 2Repository: 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', ... }.
| tool({ | ||
| name: 'calculate', | ||
| description: 'Perform calculation', | ||
| inputSchema: { expression: z.string() }, | ||
| outputSchema: { result: z.number() }, | ||
| })((input) => ({ result: eval(input.expression) })), | ||
| ], |
There was a problem hiding this comment.
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.
| 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 |
There was a problem hiding this comment.
🧩 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 tsRepository: 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.
| 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.
| ## 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; | ||
|
|
There was a problem hiding this comment.
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.
| 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 | ||
| ``` |
There was a problem hiding this comment.
🧩 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/**/*.mdRepository: 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`.
Summary by CodeRabbit
New Features
frontmcp skills(list, search, show, install) with category/tag/bundle filters, search limits, provider selection, custom install dir; project scaffolder now supports--skillsbundles and an Nxskill-dirgenerator.Documentation
Tests