Skip to content

fix: use per-skill discovery URL in installCommand#50

Merged
johnmcollier merged 1 commit into
redhat-ai-dev:mainfrom
johnmcollier:fix/install-command-skill-flag
Jul 16, 2026
Merged

fix: use per-skill discovery URL in installCommand#50
johnmcollier merged 1 commit into
redhat-ai-dev:mainfrom
johnmcollier:fix/install-command-skill-flag

Conversation

@johnmcollier

Copy link
Copy Markdown
Contributor

Summary

  • npx skills does not parse --skill=name, so RHESS install commands that used the equals form never preselected a skill and fell through to the full catalog.
  • Serve a single-entry discovery index at /api/v1/skills/:source/:slug/.well-known/agent-skills/index.json.
  • Change installCommand to npx skills add <host>/api/v1/skills/:source/:slug so the CLI finds one skill and auto-selects it (no full-catalog download).

Test plan

  • npx vitest run test/server/routes/skills.test.ts test/server/routes/wellKnown.test.ts
  • Local CLI: npx skills add <base>/api/v1/skills/awesome-copilot/arch-linux-triage --listFound 1 skill
  • After deploy: copy install command from UI for arch-linux-triage and confirm it installs only that skill

Made with Cursor

The skills CLI ignores --skill=name (equals form) and would otherwise
download the full catalog. Serve a one-entry well-known index under each
skill path so npx skills add auto-selects that skill.

Assisted-by: Cursor Grok 4.5
Co-authored-by: Cursor <cursoragent@cursor.com>
@openshift-ci

openshift-ci Bot commented Jul 16, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: johnmcollier

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Fix installCommand by using per-skill discovery URL

🐞 Bug fix ✨ Enhancement 🧪 Tests 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Fix generated install commands to avoid broken --skill= parsing in the skills CLI.
• Add a per-skill well-known discovery index so npx skills add auto-selects one skill.
• Refactor discovery-index generation into a shared utility and add route coverage tests.
Diagram

graph TD
  CLI["npx skills CLI"] --> SkillsList["GET /api/v1/skills"] --> SkillsRoute["skills.ts"] --> PerSkillUrl["installCommand: /api/v1/skills/:source/:slug"]
  CLI --> PerSkillProbe["GET :source/:slug/.well-known/index.json"] --> SkillsRoute --> DiscoveryUtil["discoveryIndex.ts"] --> SkillsDB[("Skill repository")]
  DiscoveryUtil --> ArtifactUrl["artifact URL per skill"]
  RootProbe["GET /.well-known/index.json"] --> WellKnownRoute["wellKnown.ts"] --> DiscoveryUtil
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Fix the skills CLI to accept `--skill=`
  • ➕ Keeps installCommand format stable (host + flag).
  • ➕ Avoids adding new API surface area for per-skill discovery.
  • ➖ Requires an upstream CLI change and release coordination.
  • ➖ Does not help already-deployed servers until clients upgrade.
2. Generate `--skill ` (space form) with robust escaping
  • ➕ No new endpoints needed; still uses host root well-known index.
  • ➕ Avoids dependency on CLI equals-form parsing.
  • ➖ Still triggers full-catalog discovery/download at the host root.
  • ➖ Escaping/quoting is shell-dependent and can break copy/paste installs.
3. Serve a filtered discovery index via query parameter (e.g. `/.well-known/.../index.json?skill=...`)
  • ➕ Avoids adding a new path under each skill resource.
  • ➕ Can remain a single endpoint with filtering.
  • ➖ Only works if the CLI supports probing well-known URLs with query params (often not the case).
  • ➖ Harder to cache and reason about than a stable per-skill URL.

Recommendation: Proceed with the per-skill discovery URL approach. It works with the existing CLI probing behavior (well-known under the provided base URL), avoids fragile shell quoting, and prevents unnecessary full-catalog downloads. The shared buildDiscoveryIndex utility also reduces drift between the root and per-skill discovery responses.

Files changed (5) +159 / -33

Enhancement (1) +45 / -0
discoveryIndex.tsAdd shared discovery index builder and entry validation +45/-0

Add shared discovery index builder and entry validation

• Introduces 'toDiscoverySkillEntry' to validate slugs against CLI install-id rules and to normalize fields (schema URI, description truncation, artifact URL, digest format). Adds 'buildDiscoveryIndex' to generate a CLI-compatible '{ $schema, skills[] }' payload for both root and per-skill discovery endpoints.

src/server/utils/discoveryIndex.ts

Bug fix (1) +86 / -6
skills.tsEmit per-skill installCommand and add per-skill well-known discovery route +86/-6

Emit per-skill installCommand and add per-skill well-known discovery route

• Changes 'installCommand' generation to use the per-skill base URL to avoid broken '--skill=<slug>' parsing and full-catalog downloads. Adds '/:source/:slug/.well-known/agent-skills/index.json' to serve a single-entry discovery index for the requested skill, returning 404 for missing or non-installable skills.

src/server/routes/skills.ts

Refactor (1) +2 / -21
wellKnown.tsReuse shared discovery-index builder for root well-known endpoint +2/-21

Reuse shared discovery-index builder for root well-known endpoint

• Replaces inline discovery response construction with 'buildDiscoveryIndex(...)'. Keeps schema/entry formatting consistent with the new per-skill discovery route.

src/server/routes/wellKnown.ts

Tests (1) +23 / -3
skills.test.tsUpdate installCommand assertions and test per-skill well-known index +23/-3

Update installCommand assertions and test per-skill well-known index

• Adjusts expectations to match the new per-skill installCommand format and tightens validation of the generated command prefix. Adds a new test ensuring the per-skill well-known endpoint returns a single-entry discovery index with the correct schema, URL, and digest format.

test/server/routes/skills.test.ts

Documentation (1) +3 / -3
api.mdDocument per-skill installCommand and discovery URL usage +3/-3

Document per-skill installCommand and discovery URL usage

• Updates example API responses to show 'installCommand' pointing at '/api/v1/skills/:source/:slug'. Clarifies that clients should install via the per-skill discovery URL rather than using artifact URLs directly.

docs/api.md

@johnmcollier
johnmcollier merged commit c492260 into redhat-ai-dev:main Jul 16, 2026
2 of 4 checks passed
@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Web spec install drift 🐞 Bug ⚙ Maintainability
Description
The server now returns installCommand as npx skills add <base>/api/v1/skills/<source>/<slug>,
but the OpenSpec web-directory requirement still mandates a --skill <source>/<slug> command,
making the spec inaccurate and likely to mislead future UI/conformance work.
Code

src/server/routes/skills.ts[R54-60]

+  // Point at the per-skill discovery URL. The CLI looks for
+  // <url>/.well-known/agent-skills/index.json first; that single-entry index
+  // auto-selects this skill. Host root + `--skill=…` fails because the skills CLI
+  // does not parse the equals form of --skill, and would download the full catalog.
+  const installCommand =
+    `npx skills add ${baseUrl}/api/v1/skills/${encodeURIComponent(skill.sourceSlug)}/${encodeURIComponent(skill.slug)}`;
  return {
Evidence
The API now emits a per-skill discovery URL in installCommand, while the web-directory spec still
documents/mandates the old --skill <source>/<slug> command format.

src/server/routes/skills.ts[53-60]
openspec/specs/web-directory/spec.md[17-20]
openspec/changes/archive/2026-06-26-rhess-enterprise-skills-server/specs/web-directory/spec.md[17-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The OpenSpec web-directory requirements still specify the old install command format (`npx skills add <server-url> --skill <source>/<slug>`), but the implementation now emits a per-skill discovery URL (`npx skills add …/api/v1/skills/:source/:slug`). This spec mismatch can cause future UI changes, conformance checks, or documentation to reintroduce the wrong command.

## Issue Context
- The PR changed `installCommand` generation to point at the per-skill discovery URL.
- OpenSpec web-directory specs still reference the old `--skill` form.

## Fix Focus Areas
- openspec/specs/web-directory/spec.md[17-20]
- openspec/changes/archive/2026-06-26-rhess-enterprise-skills-server/specs/web-directory/spec.md[17-20]
- src/server/routes/skills.ts[54-60]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. OpenAPI not regenerated 🐞 Bug ⚙ Maintainability
Description
A new discovery endpoint (GET /api/v1/skills/:source/:slug/.well-known/agent-skills/index.json)
was added, but the committed openapi.yaml (generated via npm run openapi) does not document it,
so tooling/consumers relying on the checked-in spec will miss the endpoint.
Code

src/server/routes/skills.ts[R275-280]

+  // Per-skill discovery index — registered before /:source/:slug.
+  // Consumed by `npx skills add <base>/api/v1/skills/:source/:slug`, which probes
+  // `<url>/.well-known/agent-skills/index.json` before falling back to the host root.
+  fastify.get(
+    "/:source/:slug/.well-known/agent-skills/index.json",
+    {
Evidence
The PR introduces the new per-skill discovery route in skills.ts, the repo has an explicit OpenAPI
generator script that writes openapi.yaml, and the current committed OpenAPI shows only the root
/.well-known/agent-skills/index.json discovery endpoint (not the new per-skill one).

src/server/routes/skills.ts[275-350]
scripts/generate-openapi.ts[1-17]
openapi.yaml[710-755]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The PR adds a new per-skill discovery endpoint, but the repository’s committed OpenAPI spec (`openapi.yaml`) appears stale and does not include that route. Since the repo has a dedicated generator script, the expected workflow is to regenerate and commit the updated spec when routes/schemas change.

## Issue Context
- `scripts/generate-openapi.ts` generates `openapi.yaml` from Fastify’s runtime schema.
- `openapi.yaml` currently documents only the root well-known index under `/.well-known/agent-skills/index.json` and does not include the new per-skill index route.

## Fix Focus Areas
- src/server/routes/skills.ts[275-350]
- scripts/generate-openapi.ts[1-17]
- openapi.yaml[710-755]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment on lines +54 to 60
// Point at the per-skill discovery URL. The CLI looks for
// <url>/.well-known/agent-skills/index.json first; that single-entry index
// auto-selects this skill. Host root + `--skill=…` fails because the skills CLI
// does not parse the equals form of --skill, and would download the full catalog.
const installCommand =
`npx skills add ${baseUrl}/api/v1/skills/${encodeURIComponent(skill.sourceSlug)}/${encodeURIComponent(skill.slug)}`;
return {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. Web spec install drift 🐞 Bug ⚙ Maintainability

The server now returns installCommand as npx skills add <base>/api/v1/skills/<source>/<slug>,
but the OpenSpec web-directory requirement still mandates a --skill <source>/<slug> command,
making the spec inaccurate and likely to mislead future UI/conformance work.
Agent Prompt
## Issue description
The OpenSpec web-directory requirements still specify the old install command format (`npx skills add <server-url> --skill <source>/<slug>`), but the implementation now emits a per-skill discovery URL (`npx skills add …/api/v1/skills/:source/:slug`). This spec mismatch can cause future UI changes, conformance checks, or documentation to reintroduce the wrong command.

## Issue Context
- The PR changed `installCommand` generation to point at the per-skill discovery URL.
- OpenSpec web-directory specs still reference the old `--skill` form.

## Fix Focus Areas
- openspec/specs/web-directory/spec.md[17-20]
- openspec/changes/archive/2026-06-26-rhess-enterprise-skills-server/specs/web-directory/spec.md[17-20]
- src/server/routes/skills.ts[54-60]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +275 to +280
// Per-skill discovery index — registered before /:source/:slug.
// Consumed by `npx skills add <base>/api/v1/skills/:source/:slug`, which probes
// `<url>/.well-known/agent-skills/index.json` before falling back to the host root.
fastify.get(
"/:source/:slug/.well-known/agent-skills/index.json",
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

2. Openapi not regenerated 🐞 Bug ⚙ Maintainability

A new discovery endpoint (GET /api/v1/skills/:source/:slug/.well-known/agent-skills/index.json)
was added, but the committed openapi.yaml (generated via npm run openapi) does not document it,
so tooling/consumers relying on the checked-in spec will miss the endpoint.
Agent Prompt
## Issue description
The PR adds a new per-skill discovery endpoint, but the repository’s committed OpenAPI spec (`openapi.yaml`) appears stale and does not include that route. Since the repo has a dedicated generator script, the expected workflow is to regenerate and commit the updated spec when routes/schemas change.

## Issue Context
- `scripts/generate-openapi.ts` generates `openapi.yaml` from Fastify’s runtime schema.
- `openapi.yaml` currently documents only the root well-known index under `/.well-known/agent-skills/index.json` and does not include the new per-skill index route.

## Fix Focus Areas
- src/server/routes/skills.ts[275-350]
- scripts/generate-openapi.ts[1-17]
- openapi.yaml[710-755]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant