Skip to content
Draft
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
79 changes: 79 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Validate skills

on:
pull_request:
push:
branches:
- main

jobs:
validate:
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22"

- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code@latest

- name: Validate Claude Code plugin marketplace
run: claude plugin validate .

- name: Validate Agent Skills metadata
shell: bash
run: |
set -euo pipefail

failed=0

while IFS= read -r -d '' skill; do
dir_name="$(basename "$(dirname "$skill")")"
name="$(awk '/^name: / { sub(/^name: /, ""); print; exit }' "$skill")"
description="$(awk '/^description: / { sub(/^description: /, ""); print; exit }' "$skill")"
line_count="$(wc -l < "$skill")"

if [[ -z "$name" ]]; then
echo "::error file=$skill::missing required name field"
failed=1
elif [[ "$name" != "$dir_name" ]]; then
echo "::error file=$skill::name '$name' must match directory '$dir_name'"
failed=1
elif [[ ! "$name" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then
echo "::error file=$skill::name must be kebab-case lowercase alphanumeric"
failed=1
elif (( ${#name} > 64 )); then
echo "::error file=$skill::name exceeds 64 characters"
failed=1
fi

if [[ -z "$description" ]]; then
echo "::error file=$skill::missing required description field"
failed=1
elif (( ${#description} > 1024 )); then
echo "::error file=$skill::description exceeds 1024 characters"
failed=1
fi

if (( line_count > 500 )); then
echo "::error file=$skill::main SKILL.md should stay under 500 lines; move details to references/"
failed=1
fi
done < <(find skills -mindepth 2 -maxdepth 2 -name SKILL.md -print0)

if grep -R --line-number '^tools:' skills; then
echo "::error::legacy tools: frontmatter is not part of the current Agent Skills spec; use compatibility text or allowed-tools only when intentionally pre-approving tools"
failed=1
fi

if grep -R --line-number -E '\]\([^)]+\.md\)' skills/*/references; then
echo "::error::references should not link to other markdown files; keep file references one level deep from SKILL.md"
failed=1
fi

exit "$failed"
5 changes: 3 additions & 2 deletions skills/use-k3sup/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
name: use-k3sup
description: Provision K3s clusters with k3sup and k3sup-pro on local, Slicer, and remote VMs.
tools: [Bash]
description: Provision K3s clusters with k3sup and k3sup-pro. Use when installing Kubernetes, creating single-node or HA k3s clusters, or wiring Slicer/remote VMs over SSH.
license: MIT
compatibility: Requires Bash and network access for installing k3sup/kubectl; Slicer VM workflows require the Slicer CLI and a running daemon.
---

# Use K3sup with Slicer VMs
Expand Down
17 changes: 12 additions & 5 deletions skills/use-s3-rustfs/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
name: use-s3-rustfs
description: Install and run RustFS (S3-compatible object storage in Rust) in a Slicer VM, and talk to it with any S3 client (boto3, aws-cli, mc)
tools: [Bash]
description: Install and run RustFS, an S3-compatible object store, in a Slicer VM. Use when tests, CI, boto3, aws-cli, mc, or Terraform need a local S3 endpoint.
license: MIT
compatibility: Requires Bash, the Slicer CLI, a running Slicer daemon, and network access to install RustFS.
---

# Use S3 — RustFS in a Slicer VM
Expand Down Expand Up @@ -83,8 +84,13 @@ Change keys before anything touches real data:

```bash
slicer vm exec "$VM_NAME" --uid 1000 -- \
"sudo sed -i 's/=rustfsadmin/=$(openssl rand -hex 16)/' /etc/default/rustfs && \
sudo systemctl restart rustfs"
'access_key=$(openssl rand -hex 16) &&
secret_key=$(openssl rand -hex 32) &&
sudo sed -i \
-e "s/^RUSTFS_ACCESS_KEY=.*/RUSTFS_ACCESS_KEY=${access_key}/" \
-e "s/^RUSTFS_SECRET_KEY=.*/RUSTFS_SECRET_KEY=${secret_key}/" \
/etc/default/rustfs &&
sudo systemctl restart rustfs'
```

Service management:
Expand Down Expand Up @@ -122,12 +128,13 @@ Notes for S3 clients:

- Always pass `endpoint_url` — without it boto3 hits real AWS.
- `region_name` is required by the SigV4 signer, but RustFS ignores the value.
- Use **path-style** addressing for CLI tools (`--endpoint-url ... --addressing-style path`) — virtual-host style requires DNS for every bucket.
- Use **path-style** addressing for CLI tools — virtual-host style requires DNS for every bucket.
- No HTTPS by default. For TLS, terminate in front (nginx/caddy) or configure RustFS's TLS options.

### aws-cli

```bash
aws configure set default.s3.addressing_style path
aws --endpoint-url http://127.0.0.1:9000 \
--no-verify-ssl s3 mb s3://demo
aws --endpoint-url http://127.0.0.1:9000 \
Expand Down
Loading