Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

## Onboarding type

- [ ] New product onboarding (`components.yml` entry)
- [ ] New product onboarding (new `components.d/<slug>.yml` file)
- [ ] Other (catalog change, README fix, infrastructure, etc.)

## For new product onboarding — author affirmations
Expand All @@ -14,14 +14,14 @@ By submitting this PR, I confirm on behalf of my team:
- [ ] **License selected:** Apache 2.0 / CC-BY 4.0 / Dual (Apache 2.0 + CC-BY 4.0). Specify: _____
- [ ] **No new license or new third-party component** introduced beyond what the source repo already carries
- [ ] **Source repo is public and under an NVIDIA-owned GitHub org**
- [ ] `.agents/skills/` or `skills/` path used for new entries (or existing path retained for legacy entries per `components.yml`)
- [ ] `.agents/skills/` or `skills/` path used for new entries (or existing path retained for legacy entries per `components.d/<slug>.yml`)

> NVIDIA contributors: see the internal onboarding guide for the IP review process details and license selection.

## Reviewer checklist (OSS Skills PIC)

- [ ] Author confirmations above are checked
- [ ] `components.yml` entry valid (required fields, unique `catalog_dir`, path exists in source repo)
- [ ] `components.d/<slug>.yml` entry valid (required fields, unique `catalog_dir`, path exists in source repo, filename slug matches name)
- [ ] `SKILL.md` frontmatter spec-compliant (at least one sampled)
- [ ] No new license or third-party dependency requiring OSRB filing

Expand Down
37 changes: 21 additions & 16 deletions .github/scripts/regenerate-readme.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/env bash
# Regenerate the README's Available Skills and Getting Help & Contributing
# tables from components.yml. Used by the sync-skills workflow; can also
# tables from components.d/*.yml. Used by the sync-skills workflow; can also
# be run locally to preview the result.
#
# Reads:
# components.yml component catalog (source of truth)
# components.d/*.yml — per-component catalog files (source of truth)
# skills/<catalog_dir>/ — to count SKILL.md files per component
# /tmp/sync-versions.txt — optional, populated by the sync workflow with
# upstream short SHA, full SHA, and committer
Expand All @@ -22,28 +22,33 @@ cd "$(git rev-parse --show-toplevel)"

VERSIONS_FILE="${VERSIONS_FILE:-/tmp/sync-versions.txt}"

sorted_indices=$(yq -r '.components | to_entries | sort_by(.value.name | downcase) | .[].key' components.yml)
# Aggregate per-component files into a single config so the existing
# yq queries can index into a flat .components list.
CONFIG=/tmp/components.aggregated.yml
yq ea '[.] | {"components": .}' components.d/*.yml > "$CONFIG"

sorted_indices=$(yq -r '.components | to_entries | sort_by(.value.name | downcase) | .[].key' "$CONFIG")

# Available Skills table
{
echo "| Product | Description | Skills | Catalog | Source | Version |"
echo "|---------|-------------|:------:|---------|--------|---------|"
for i in $sorted_indices; do
name=$(yq -r ".components[$i].name" components.yml)
description=$(yq -r ".components[$i].description" components.yml | tr -d '\n' | sed 's/ */ /g; s/^ //; s/ $//')
repo=$(yq -r ".components[$i].repo" components.yml)
ref=$(yq -r ".components[$i].ref // \"main\"" components.yml)
primary_path=$(yq -r ".components[$i].skills[0].path" components.yml)
name=$(yq -r ".components[$i].name" "$CONFIG")
description=$(yq -r ".components[$i].description" "$CONFIG" | tr -d '\n' | sed 's/ */ /g; s/^ //; s/ $//')
repo=$(yq -r ".components[$i].repo" "$CONFIG")
ref=$(yq -r ".components[$i].ref // \"main\"" "$CONFIG")
primary_path=$(yq -r ".components[$i].skills[0].path" "$CONFIG")
primary_path=${primary_path%/}
primary_catalog=$(yq -r ".components[$i].skills[0].catalog_dir" components.yml)
primary_catalog=$(yq -r ".components[$i].skills[0].catalog_dir" "$CONFIG")

skill_count=0
while read -r catalog_dir; do
if [ -d "skills/$catalog_dir" ]; then
cnt=$(find "skills/$catalog_dir" -name SKILL.md -type f 2>/dev/null | wc -l | tr -d ' ')
skill_count=$((skill_count + cnt))
fi
done < <(yq -r ".components[$i].skills[].catalog_dir" components.yml)
done < <(yq -r ".components[$i].skills[].catalog_dir" "$CONFIG")

slug=$(echo "$name" | tr 'A-Z ' 'a-z-')
version_cell="—"
Expand All @@ -64,12 +69,12 @@ sorted_indices=$(yq -r '.components | to_entries | sort_by(.value.name | downcas
echo "| Product | Issues | Discussions | Contributing | Security |"
echo "|---------|--------|-------------|--------------|----------|"
for i in $sorted_indices; do
name=$(yq -r ".components[$i].name" components.yml)
repo=$(yq -r ".components[$i].repo" components.yml)
ref=$(yq -r ".components[$i].ref // \"main\"" components.yml)
contrib=$(yq -r ".components[$i].links.contributing // \"CONTRIBUTING.md\"" components.yml)
discussions=$(yq -r ".components[$i].links.discussions // true" components.yml)
security=$(yq -r ".components[$i].links.security // true" components.yml)
name=$(yq -r ".components[$i].name" "$CONFIG")
repo=$(yq -r ".components[$i].repo" "$CONFIG")
ref=$(yq -r ".components[$i].ref // \"main\"" "$CONFIG")
contrib=$(yq -r ".components[$i].links.contributing // \"CONTRIBUTING.md\"" "$CONFIG")
discussions=$(yq -r ".components[$i].links.discussions // true" "$CONFIG")
security=$(yq -r ".components[$i].links.security // true" "$CONFIG")

issues_cell="[Issues](https://github.com/${repo}/issues)"
if [ "$discussions" = "true" ]; then
Expand Down
32 changes: 20 additions & 12 deletions .github/workflows/sync-skills.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
# Copyright (c) 2026 NVIDIA Corporation. All rights reserved.
#
# Sync skills from product repos into the nvidia/skills catalog.
# Reads component definitions from components.yml — teams onboard by
# adding an entry there, not by editing this workflow.
# Reads component definitions from components.d/*.yml (one file per
# component) — teams onboard by adding their own file there, not by
# editing this workflow or any shared file.
#
# Requires a PAT (SKILLS_SYNC_PAT) with read access to all product
# repos, stored as a repository secret.
Expand Down Expand Up @@ -47,16 +48,23 @@ jobs:
truncate -s 0 /tmp/failed-components.txt
truncate -s 0 /tmp/sync-versions.txt

# Aggregate per-component files into a single config so the
# iteration loop below can index by position. The components.d/
# layout means concurrent onboarding PRs never touch a shared
# file — see components.d/README.md for the schema.
CONFIG=/tmp/components.aggregated.yml
yq ea '[.] | {"components": .}' components.d/*.yml > "$CONFIG"

# Configure git to use the token via credential helper
# so it never appears in clone URLs or error output
git config --global credential.helper '!f() { echo "username=x-access-token"; echo "password=${GH_TOKEN}"; }; f'

component_count=$(yq '.components | length' components.yml)
component_count=$(yq '.components | length' "$CONFIG")

for i in $(seq 0 $((component_count - 1))); do
name=$(yq -r ".components[$i].name" components.yml)
repo=$(yq -r ".components[$i].repo" components.yml)
ref=$(yq -r ".components[$i].ref // \"main\"" components.yml)
name=$(yq -r ".components[$i].name" "$CONFIG")
repo=$(yq -r ".components[$i].repo" "$CONFIG")
ref=$(yq -r ".components[$i].ref // \"main\"" "$CONFIG")

echo "── $name ──"

Expand All @@ -78,19 +86,19 @@ jobs:
echo "$slug|$upstream_short_sha|$upstream_sha|$upstream_date|$repo" >> /tmp/sync-versions.txt

# Collect all skill paths for sparse checkout
skill_count=$(yq -r ".components[$i].skills | length" components.yml)
skill_count=$(yq -r ".components[$i].skills | length" "$CONFIG")
sparse_paths=""
for j in $(seq 0 $((skill_count - 1))); do
path=$(yq -r ".components[$i].skills[$j].path" components.yml)
path=$(yq -r ".components[$i].skills[$j].path" "$CONFIG")
sparse_paths="$sparse_paths $path"
done
(cd "$tmp_dir" && git sparse-checkout set $sparse_paths 2>/dev/null) || true

# Copy each skill path to its catalog directory
synced=false
for j in $(seq 0 $((skill_count - 1))); do
path=$(yq -r ".components[$i].skills[$j].path" components.yml)
catalog_dir=$(yq -r ".components[$i].skills[$j].catalog_dir" components.yml)
path=$(yq -r ".components[$i].skills[$j].path" "$CONFIG")
catalog_dir=$(yq -r ".components[$i].skills[$j].catalog_dir" "$CONFIG")
src="$tmp_dir/$path"

if [ -d "$src" ] && [ -n "$(ls -A "$src" 2>/dev/null)" ]; then
Expand All @@ -111,7 +119,7 @@ jobs:
if $synced; then
echo "- $name" >> /tmp/rsynced-components.txt
for j in $(seq 0 $((skill_count - 1))); do
catalog_dir=$(yq -r ".components[$i].skills[$j].catalog_dir" components.yml)
catalog_dir=$(yq -r ".components[$i].skills[$j].catalog_dir" "$CONFIG")
if [ -n "$(git status --porcelain "skills/$catalog_dir" 2>/dev/null)" ]; then
echo "- $name" >> /tmp/changed-components.txt
break
Expand Down Expand Up @@ -197,7 +205,7 @@ jobs:
`**Run:** ${context.runId}`,
`**Trigger:** \`${context.eventName}\``,
``,
`This usually means the skill path in \`components.yml\` doesn't match the actual directory in the source repo (e.g. symlink, renamed, or removed).`
`This usually means the skill path in \`components.d/<slug>.yml\` doesn't match the actual directory in the source repo (e.g. symlink, renamed, or removed).`
].join('\n');
await github.rest.issues.create({
owner: context.repo.owner,
Expand Down
72 changes: 72 additions & 0 deletions components.d/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!-- SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0 -->
<!-- Copyright (c) 2026 NVIDIA Corporation. All rights reserved. -->

# `components.d/` — Component catalog

One file per component, aggregated at workflow runtime. This layout exists so simultaneous onboarding PRs from different teams never touch the same file — eliminating merge conflicts at scale.

## Onboarding a new component

1. Create `components.d/<slug>.yml` where `<slug>` is your component name lowercased with spaces replaced by dashes (e.g., `Nemotron Voice Agent` → `nemotron-voice-agent.yml`).
2. Fill in the fields below.
3. Open a pull request — that's it. The sync workflow picks it up automatically; the README's Available Skills and Getting Help tables regenerate on the next sync.

## Required fields

| Field | Type | Description |
|---------------|--------|-----------------------------------------------------------------------------|
| `name` | string | Display name shown in the README (e.g., `CUDA-Q`, `Nemotron Voice Agent`). |
| `repo` | string | GitHub repository (`owner/repo`). |
| `description` | string | One-line description for the README's Available Skills table. |
| `skills` | list | Skill source locations (see below). |

Each entry under `skills:` requires:

| Field | Type | Description |
|---------------|--------|--------------------------------------------------------------------------|
| `path` | string | Directory in the source repo containing skills (e.g., `.agents/skills/`).|
| `catalog_dir` | string | Directory name under `skills/` in this catalog (must be unique). |

## Optional fields

| Field | Default | Description |
|------------------------|--------------------|------------------------------------------------------------|
| `ref` | `main` | Branch to sync from. |
| `links.contributing` | `CONTRIBUTING.md` | Path to the contributing file in the source repo. |
| `links.discussions` | `true` | Set to `false` if the repo has no Discussions tab. |
| `links.security` | `true` | Set to `false` if the repo has no `SECURITY.md`. |

## Example

```yaml
# components.d/your-product.yml
name: Your Product
repo: NVIDIA/your-product
description: One-line description of what the skills do.
skills:
- path: .agents/skills/
catalog_dir: your-product
```

For multi-skill components, add multiple entries under `skills:`:

```yaml
name: NeMo Evaluator
repo: NVIDIA-NeMo/Evaluator
description: LLM evaluation — launch evaluations, access MLflow results, and bring-your-own benchmarks.
skills:
- path: packages/nemo-evaluator-launcher/.claude/skills/
catalog_dir: NeMo-Evaluator-Launcher
- path: packages/nemo-evaluator/.claude/skills/
catalog_dir: NeMo-Evaluator
```

## How aggregation works

The sync workflow runs:

```bash
yq ea '[.] | {"components": .}' components.d/*.yml > /tmp/components.aggregated.yml
```

Then iterates the resulting `components` list. Files are read in alphabetical order; the README regenerator sorts the result by display name independently.
8 changes: 8 additions & 0 deletions components.d/cuda-q.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: CUDA-Q
repo: NVIDIA/cuda-quantum
description: CUDA Quantum — onboarding guide for installation, test programs, GPU simulation, QPU hardware, and quantum applications.
skills:
- path: .claude/skills/
catalog_dir: CUDA-Q
links:
contributing: Contributing.md
6 changes: 6 additions & 0 deletions components.d/cuopt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: cuOpt
repo: NVIDIA/cuopt
description: GPU-accelerated optimization — vehicle routing, linear programming, quadratic programming, installation, server deployment, and developer tools.
skills:
- path: skills/
catalog_dir: cuopt
8 changes: 8 additions & 0 deletions components.d/megatron-bridge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: Megatron-Bridge
repo: NVIDIA-NeMo/Megatron-Bridge
description: Bridge between NeMo and Megatron — data processing, model conversion, and training utilities.
skills:
- path: skills/
catalog_dir: Megatron-Bridge
links:
security: false
8 changes: 8 additions & 0 deletions components.d/megatron-core.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: Megatron-Core
repo: NVIDIA/Megatron-LM
description: Large-scale distributed training — model parallelism, pipeline parallelism, and mixed precision.
skills:
- path: skills/
catalog_dir: Megatron-Core
links:
security: false
8 changes: 8 additions & 0 deletions components.d/model-optimizer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: Model-Optimizer
repo: NVIDIA/Model-Optimizer
description: Model optimization — quantization, sparsity, and distillation for efficient inference.
skills:
- path: .claude/skills/
catalog_dir: Model-Optimizer
links:
discussions: false
8 changes: 8 additions & 0 deletions components.d/nemo-evaluator.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: NeMo Evaluator
repo: NVIDIA-NeMo/Evaluator
description: LLM evaluation — launch evaluations, access MLflow results, NeMo Evaluator Launcher assistant, and bring-your-own benchmarks.
skills:
- path: packages/nemo-evaluator-launcher/.claude/skills/
catalog_dir: NeMo-Evaluator-Launcher
- path: packages/nemo-evaluator/.claude/skills/
catalog_dir: NeMo-Evaluator
6 changes: 6 additions & 0 deletions components.d/nemo-gym.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: NeMo Gym
repo: NVIDIA-NeMo/Gym
description: RL training environments — add benchmarks, resources servers, agent wiring, and reward profiling.
skills:
- path: .claude/skills/
catalog_dir: NeMo-Gym
6 changes: 6 additions & 0 deletions components.d/nemoclaw.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: NemoClaw
repo: NVIDIA/NemoClaw
description: Secure agent sandboxing — run OpenClaw inside NVIDIA OpenShell with managed inference, policy management, remote deployment, sandbox monitoring, and contributor/maintainer workflows.
skills:
- path: .agents/skills/
catalog_dir: NemoClaw
6 changes: 6 additions & 0 deletions components.d/nemotron-voice-agent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: Nemotron Voice Agent
repo: NVIDIA-AI-Blueprints/nemotron-voice-agent
description: Real-time conversational AI — deploy speech-to-speech voice agents on Workstation, Jetson Thor, or Cloud NIMs.
skills:
- path: .agents/skills/
catalog_dir: nemotron-voice-agent
6 changes: 6 additions & 0 deletions components.d/rag-blueprint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: RAG Blueprint
repo: NVIDIA-AI-Blueprints/rag
description: RAG pipeline — deploy, configure, troubleshoot, and manage retrieval augmented generation with Docker Compose or Helm.
skills:
- path: skill-source/.agents/skills/
catalog_dir: rag
6 changes: 6 additions & 0 deletions components.d/tensorrt-llm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: TensorRT-LLM
repo: NVIDIA/TensorRT-LLM
description: LLM inference optimization — model onboarding, performance analysis and optimization, kernel writing, CI diagnostics, code contribution, and codebase exploration.
skills:
- path: .claude/skills/
catalog_dir: TensorRT-LLM
Loading
Loading