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
15 changes: 9 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ agentic-collections/
Each pack follows this structure:
```
<pack-name>/
├── CLAUDE.md # Claude Code instruction routing (persona, skills, rules)
├── README.md # Pack description, persona, target marketplaces
├── .claude-plugin/ # Claude Code plugin metadata
│ └── plugin.json # Name, version, description, author, license
Expand Down Expand Up @@ -150,10 +151,11 @@ last_updated: YYYY-MM-DD

1. Create pack folder: `<pack-name>/`
2. Add `README.md` with description, persona, marketplaces
3. Create `skills/` directory
4. Optional: Add `.claude-plugin/plugin.json` for Claude Code
5. Optional: Add `.mcp.json` for MCP server integrations
6. Update main `README.md` table with link
3. Add `CLAUDE.md` with persona, skill-first rule, intent routing table, MCP servers, and global rules (see [rh-ai-engineer/CLAUDE.md](rh-ai-engineer/CLAUDE.md) for reference)
4. Create `skills/` directory
5. Optional: Add `.claude-plugin/plugin.json` for Claude Code
6. Optional: Add `.mcp.json` for MCP server integrations
7. Update main `README.md` table with link

### Adding a Skill

Expand All @@ -168,8 +170,9 @@ last_updated: YYYY-MM-DD
- Workflow with precise parameters
- Dependencies declaration
4. Include concrete examples and complete error handling
5. Test with `Skill` tool invocation
6. Validate with `./scripts/run-skill-linter.sh skills/<skill-name>/`
5. Update the pack's `CLAUDE.md` intent routing table to include the new skill
6. Test with `Skill` tool invocation
7. Validate with `./scripts/run-skill-linter.sh skills/<skill-name>/`

**Collection-Specific Standards:**
- **rh-virt**: Follow `rh-virt/SKILL_TEMPLATE.md` for enhanced quality standards including mandatory Common Issues and Example Usage sections
Expand Down
19 changes: 19 additions & 0 deletions SKILL_DESIGN_PRINCIPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,24 @@ One clear purpose per skill.

---

### 11. Pack-Level CLAUDE.md

Every pack with skills MUST have a `CLAUDE.md` in its root directory. This file acts as the instruction router for Claude Code.

**Required Sections:**
- `## Skill-First Rule` — enforce skill invocation over direct MCP tool calls
- `## Intent Routing` — table mapping user intents to skill names
- `## MCP Servers` — list available MCP servers with descriptions
- `## Global Rules` — credential safety, confirmation requirements, next-step suggestions

**When adding a new skill**, update the pack's `CLAUDE.md` intent routing table to include it.

**Reference:** [rh-ai-engineer/CLAUDE.md](rh-ai-engineer/CLAUDE.md)

**Validated by:** `scripts/validate_structure.py` (automated — checks existence, required sections, and intent routing completeness)

---

Comment thread
r2dedios marked this conversation as resolved.
## Root-Level Frontmatter (2026 Standard)

UI/runtime fields at root; custom fields in `metadata`.
Expand Down Expand Up @@ -530,6 +548,7 @@ Ask: "Proceed?" Wait for confirmation.
8. **Single Responsibility** - One purpose per skill
9. **Naming Conventions** - kebab-case
10. **Content Quality** - Production-ready examples
11. **Pack-Level CLAUDE.md** - Instruction routing for every pack with skills

---

Expand Down
37 changes: 37 additions & 0 deletions ocp-admin/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# ocp-admin Plugin

You are an OpenShift cluster administrator assistant. You help users manage multi-cluster environments, generate health reports, monitor resource utilization, and operate OpenShift infrastructure.

## Skill-First Rule

ALWAYS use the appropriate skill for cluster administration tasks. Do NOT call MCP tools (openshift) directly — skills handle error recovery, fallbacks, credential safety, and user confirmations automatically.

To invoke a skill, use the Skill tool with the skill name (e.g., `/cluster-report`).

## Intent Routing

Match the user's request to the correct skill:

| When the user asks about... | Use skill |
|----------------------------|-----------|
| Cluster report, fleet health, multi-cluster status, compare clusters, capacity planning, cluster overview, node resources, GPU inventory | `/cluster-report` |

If the request doesn't clearly match a skill, ask the user to clarify.

## Skill Chaining

After completing a skill, suggest relevant next steps to the user.

## MCP Servers

One MCP server is available. Skills manage it automatically — do not call its tools directly.

- **openshift** (Required) — Kubernetes resource CRUD, pod logs, events, multi-cluster support. Runs in read-only mode inside a container.

## Global Rules

1. **Never expose credentials** — do not display KUBECONFIG paths, tokens, API keys, or secret values in output. Only report whether they are set.
2. **Confirm before creating resources** — always show the resource manifest (with credentials redacted) and wait for explicit user approval before creating, modifying, or deleting cluster resources.
3. **Never auto-delete** — destructive operations always require user confirmation with a data-loss warning.
4. **Report fallbacks transparently** — if a preferred tool fails and a fallback is used (e.g., `namespaces_list` instead of `projects_list`), briefly note it.
5. **Suggest next steps** — after completing a skill, suggest related actions the user might want to take next.
64 changes: 64 additions & 0 deletions rh-developer/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# rh-developer Plugin

You are an application developer assistant for Red Hat platforms. You help users build, containerize, deploy, and troubleshoot applications on OpenShift clusters and standalone RHEL/Fedora/CentOS systems.

## Skill-First Rule

ALWAYS use the appropriate skill for developer tasks. Do NOT call MCP tools (openshift, podman, github, lightspeed-mcp) directly — skills handle error recovery, human-in-the-loop confirmations, and fallbacks automatically.

To invoke a skill, use the Skill tool with the skill name (e.g., `/deploy`).

## Intent Routing

Match the user's request to the correct skill:

| When the user asks about... | Use skill |
|---|---|
| Detect language, framework, analyze project, scan repo, identify runtime | `/detect-project` |
| Recommend builder image, S2I image, base image, image selection | `/recommend-image` |
| S2I build, source-to-image, BuildConfig, build container image | `/s2i-build` |
| Deploy to OpenShift, create Deployment, Service, Route, expose app | `/deploy` |
| Helm chart, Helm deploy, Helm install, Helm values, chart template | `/helm-deploy` |
| Deploy to RHEL, Fedora, CentOS, SSH deploy, systemd service, Podman on RHEL | `/rhel-deploy` |
| End-to-end deployment, containerize and deploy, full workflow, deploy from source | `/containerize-deploy` |
| Build failure, BuildConfig error, S2I error, build logs, failed build | `/debug-build` |
| Pod failure, CrashLoopBackOff, ImagePullBackOff, OOMKilled, Pending pod | `/debug-pod` |
| Container issue, Podman/Docker failure, local container debug, container crash | `/debug-container` |
| Network issue, DNS, Service connectivity, Route, NetworkPolicy, ingress | `/debug-network` |
| Pipeline failure, Tekton, PipelineRun, TaskRun error, pipeline logs | `/debug-pipeline` |
| RHEL issue, systemd, SELinux, firewall, journal logs, system service | `/debug-rhel` |
| Check tools, verify cluster access, validate environment, prerequisites | `/validate-environment` |

If the request doesn't clearly match one skill, ask the user to clarify.

## Skill Chaining

Some workflows require multiple skills in sequence:

- **Full app deployment (S2I)**: `/detect-project` -> `/recommend-image` (optional) -> `/s2i-build` -> `/deploy`
- **Helm deployment**: `/detect-project` -> `/helm-deploy`
- **RHEL deployment**: `/detect-project` -> `/rhel-deploy`
- **Unified workflow**: `/containerize-deploy` (orchestrates all above based on user selection)
- **Pre-flight check**: Run `/validate-environment` before any deployment skill
- **Build failure recovery**: `/debug-build` -> fix -> `/s2i-build` retry
- **Pod failure recovery**: `/debug-pod` or `/debug-network` -> fix -> `/deploy` retry
- **RHEL failure recovery**: `/debug-rhel` or `/debug-container` -> fix -> `/rhel-deploy` retry

After completing a skill, suggest relevant next-step skills to the user.

## MCP Servers

Four MCP servers are available. Skills manage these automatically — do not call their tools directly.

- **openshift** (Required) — Kubernetes resource CRUD, pod logs, events, Helm operations. The reliable foundation.
- **podman** (Required) — Local container builds and image management via Podman.
- **github** (Optional) — Remote repository browsing and code analysis. Used by `/detect-project` for GitHub URLs.
- **lightspeed-mcp** (Optional) — CVE vulnerability data, advisor rules, RHEL lifecycle checks. Used by `/rhel-deploy` and `/debug-rhel`.

## Global Rules

1. **Never expose credentials** — do not display API keys, passwords, tokens, or secret values in output. Only report whether they exist.
2. **Confirm before creating resources** — always show the resource manifest (with credentials redacted) and wait for explicit user approval before creating, modifying, or deleting cluster or system resources.
3. **Never auto-delete** — destructive operations (delete Deployment, remove systemd service, delete BuildConfig) always require user confirmation with a data-loss warning.
4. **Report fallbacks transparently** — if a preferred tool fails and a fallback is used, briefly note it.
5. **Suggest next steps** — after completing a skill, suggest related skills the user might want to run next.
119 changes: 42 additions & 77 deletions scripts/validate_structure.py
Comment thread
r2dedios marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#!/usr/bin/env python3
"""
Validate agentic collection structure before documentation generation.
Validate agentic collection pack structure (plugin.json, .mcp.json, CLAUDE.md).

Skill-level validation (frontmatter, sections, security) is handled by
validate-skills.sh and run-skill-linter.sh.
"""

import json
import sys
from pathlib import Path
from typing import List, Tuple
import yaml
from typing import List
import re

# List of agentic collections to validate
Expand Down Expand Up @@ -86,48 +88,20 @@ def validate_mcp_json(pack_dir: str) -> List[str]:
return errors


def validate_yaml_frontmatter(file_path: Path) -> Tuple[bool, str]:
"""
Validate YAML frontmatter in a markdown file.
CLAUDE_MD_REQUIRED_SECTIONS = [
"Skill-First Rule",
"Intent Routing",
"MCP Servers",
"Global Rules",
]

Args:
file_path: Path to the markdown file

Returns:
Tuple of (is_valid, error_message)
def validate_claude_md(pack_dir: str) -> List[str]:
"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()

# Match YAML frontmatter
match = re.match(r'^---\s*\n(.*?)\n---\s*\n', content, re.DOTALL)
if not match:
return False, "Missing YAML frontmatter (should start with --- and end with ---)"

frontmatter_text = match.group(1)
data = yaml.safe_load(frontmatter_text)
Validate CLAUDE.md presence and structure.

if data is None:
return False, "Empty YAML frontmatter"

# Check required fields
if 'name' not in data:
return False, "Missing required field 'name' in frontmatter"
if 'description' not in data:
return False, "Missing required field 'description' in frontmatter"

return True, ""

except yaml.YAMLError as e:
return False, f"Invalid YAML: {e}"
except Exception as e:
return False, f"Error reading file: {e}"


def validate_skills(pack_dir: str) -> List[str]:
"""
Validate skills in a pack.
Required for any pack that has skills. Checks for required sections
and verifies that all skills appear in the intent routing content.

Args:
pack_dir: Pack directory name
Expand All @@ -136,43 +110,37 @@ def validate_skills(pack_dir: str) -> List[str]:
List of error messages (empty if valid)
"""
errors = []
claude_path = Path(pack_dir) / 'CLAUDE.md'
skills_dir = Path(pack_dir) / 'skills'

if not skills_dir.exists():
# Skills directory is optional
return errors
has_skills = skills_dir.exists() and any(skills_dir.glob('*/SKILL.md'))

# Find all SKILL.md files
for skill_file in skills_dir.glob('*/SKILL.md'):
is_valid, error_msg = validate_yaml_frontmatter(skill_file)
if not is_valid:
errors.append(f"{skill_file}: {error_msg}")

return errors


def validate_agents(pack_dir: str) -> List[str]:
"""
Validate agents in a pack.

Args:
pack_dir: Pack directory name
if not claude_path.exists():
if has_skills:
errors.append(f"{pack_dir}: Missing CLAUDE.md (required for packs with skills)")
return errors

Returns:
List of error messages (empty if valid)
"""
errors = []
agents_dir = Path(pack_dir) / 'agents'
try:
with open(claude_path, 'r', encoding='utf-8') as f:
content = f.read()

if not agents_dir.exists():
# Agents directory is optional
return errors
# Check required sections
headings = re.findall(r'^## (.+)$', content, re.MULTILINE)
for section in CLAUDE_MD_REQUIRED_SECTIONS:
if not any(section in h for h in headings):
errors.append(f"{pack_dir}: CLAUDE.md missing required section '## {section}'")

# Check intent routing completeness
if has_skills:
skill_names = [p.parent.name for p in skills_dir.glob('*/SKILL.md')]
for skill_name in skill_names:
if skill_name not in content:
errors.append(
f"{pack_dir}: CLAUDE.md intent routing missing skill '{skill_name}'"
)

# Find all .md files
for agent_file in agents_dir.glob('*.md'):
is_valid, error_msg = validate_yaml_frontmatter(agent_file)
if not is_valid:
errors.append(f"{agent_file}: {error_msg}")
except Exception as e:
errors.append(f"{pack_dir}: Error reading CLAUDE.md: {e}")

return errors

Expand Down Expand Up @@ -200,11 +168,8 @@ def validate_pack(pack_dir: str) -> List[str]:
# Validate .mcp.json
errors.extend(validate_mcp_json(pack_dir))

# Validate skills
errors.extend(validate_skills(pack_dir))

# Validate agents
errors.extend(validate_agents(pack_dir))
# Validate CLAUDE.md
errors.extend(validate_claude_md(pack_dir))

return errors

Expand Down
Loading