Skip to content

Commit f5e947b

Browse files
JAORMXclaude
andcommitted
Address PR feedback on RFC-0030
- Add -u/--upgrade flag to install command for skill upgrades - Add thv skill validate command for pre-build validation - Expand client support table with all Skillet clients (Claude, Codex, Copilot, OpenCode) - Clarify OCI artifact format (not runnable containers, uses OCI for distribution) - Explain deterministic packaging rationale for supply chain security - Expand Alternative 5 rationale for requiring explicit --client selection - Note that plugins cache is out of scope (managed by Claude's plugin system) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 83e27a2 commit f5e947b

1 file changed

Lines changed: 67 additions & 14 deletions

File tree

rfcs/THV-0030-skills-lifecycle-management.md

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
- **Status**: Draft
44
- **Author(s)**: Juan Antonio Osorio (@JAORMX)
55
- **Created**: 2026-01-27
6-
- **Last Updated**: 2026-01-27
6+
- **Last Updated**: 2026-01-29
77
- **Target Repository**: toolhive
88
- **Related Issues**: N/A
99

@@ -141,24 +141,32 @@ thv skill install <reference> [flags]
141141
142142
Arguments:
143143
reference OCI reference (e.g., ghcr.io/stacklok/skills/commit-message:v1.0.0)
144+
Or skill name when using -u with an already-installed skill
144145
145146
Flags:
146147
--client string Target AI client (required)
147148
--global Install globally (user-wide) (default)
148149
--local Install locally (project-specific)
149150
--group string Add skill to specified group
150151
--force Overwrite existing unmanaged skill
152+
-u, --upgrade Upgrade an already-installed skill
151153
```
152154

153155
**Behavior:**
154-
- Requires explicit `--client` selection (no default)
156+
- Requires explicit `--client` selection (see rationale in Alternatives Considered)
155157
- Pulls OCI artifact from registry
156158
- Extracts skill files to client directory
157159
- Creates `.thv-skill.json` metadata file
158160
- Updates skill index
159161
- If `--group` specified, adds skill to group state
160162
- Reports status: `installed`, `upgraded`, or `unchanged`
161163

164+
**Upgrade Behavior (`-u` flag):**
165+
- When reference is a skill name (not full OCI reference): resolves the original registry reference from `.thv-skill.json` metadata and pulls the latest tag
166+
- When reference is a full OCI reference: installs the specified version as an upgrade
167+
- Fails if skill is not already installed (use install without `-u` for new installations)
168+
- Preserves group membership across upgrades
169+
162170
#### `thv skill uninstall`
163171

164172
Removes a managed skill.
@@ -197,6 +205,27 @@ Flags:
197205
--format string Output format: table, json, yaml (default "table")
198206
```
199207

208+
#### `thv skill validate`
209+
210+
Validates a skill directory without packaging it.
211+
212+
```
213+
thv skill validate <path> [flags]
214+
215+
Arguments:
216+
path Path to skill directory (must contain SKILL.md)
217+
218+
Flags:
219+
--format string Output format: table, json, yaml (default "table")
220+
```
221+
222+
**Validation Checks:**
223+
- SKILL.md exists and has valid YAML frontmatter
224+
- Required fields present (name, description)
225+
- Name follows naming convention (`^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$`)
226+
- Optional scripts are executable (warning if not)
227+
- No path traversal patterns in file structure
228+
200229
#### `thv skill build`
201230

202231
Packages a skill directory into an OCI artifact.
@@ -212,6 +241,8 @@ Flags:
212241
--platform strings Target platforms (default: linux/amd64,linux/arm64)
213242
```
214243

244+
**Note:** Build implicitly runs validation and fails if the skill is invalid.
245+
215246
#### `thv skill push`
216247

217248
Pushes a packaged skill to an OCI registry.
@@ -298,12 +329,16 @@ type mcpClientConfig struct {
298329

299330
#### Initial Skill Support
300331

301-
| Client | Supports Skills | Global Skills Path | Local Skills Path |
302-
|--------|-----------------|-------------------|-------------------|
303-
| Claude Code CLI | Yes | `~/.claude/skills/` | `.claude/skills/` |
304-
| Cursor | TBD | TBD | TBD |
305-
| VS Code (Copilot) | TBD | TBD | TBD |
306-
| Others | No (initially) | - | - |
332+
The following clients are supported, matching Skillet's existing implementation:
333+
334+
| Client | ID | Global Skills Path | Local Skills Path |
335+
|--------|-----|-------------------|-------------------|
336+
| Claude Code | `claude` | `~/.claude/skills/` | `.claude/skills/` |
337+
| OpenAI Codex CLI | `codex` | `~/.codex/skills/` | `.codex/skills/` |
338+
| GitHub Copilot | `copilot` | `~/.copilot/skills/` | `.github/skills/` |
339+
| OpenCode | `opencode` | - | `.opencode/skill/` |
340+
341+
**Note:** Skills installed via Claude's plugin system (`~/.claude/plugins/cache/.../skills/`) are outside the scope of thv management. Those are managed by Claude's plugin infrastructure, not thv.
307342

308343
#### SkillManager Interface
309344

@@ -339,6 +374,21 @@ Skills integrate with ToolHive's existing groups system:
339374

340375
### OCI Artifact Format
341376

377+
Skills are distributed as **OCI artifacts** stored in standard container registries (GHCR, ECR, Docker Hub, etc.). These are **not runnable containers** - they use OCI as a packaging and distribution format, similar to how Helm charts can be stored in OCI registries.
378+
379+
**Artifact Structure:**
380+
```
381+
OCI Image Artifact
382+
├── Image Index (multi-platform: linux/amd64, linux/arm64)
383+
├── Image Manifest
384+
├── Config Blob (skill metadata stored in OCI labels)
385+
└── Content Layer (tar.gz)
386+
├── SKILL.md
387+
├── scripts/
388+
├── references/
389+
└── assets/
390+
```
391+
342392
Maintains compatibility with existing Skillet format:
343393

344394
**Media Types:**
@@ -352,9 +402,12 @@ Maintains compatibility with existing Skillet format:
352402
- `org.stacklok.skillet.skill.version`
353403

354404
**Reproducible Packaging:**
355-
- Deterministic tar (sorted entries, normalized timestamps via SOURCE_DATE_EPOCH)
356-
- Deterministic gzip (no ModTime, OS=255)
357-
- Same content always produces identical digest
405+
406+
OCI uses content-addressable storage where every blob is identified by its SHA256 digest. For verification and supply chain security to work, the same skill content must always produce an identical digest. This requires deterministic packaging:
407+
408+
- Deterministic tar: sorted file entries, normalized timestamps (via `SOURCE_DATE_EPOCH`), UID/GID set to 0
409+
- Deterministic gzip: fixed compression level, no variable header fields
410+
- Same content always produces identical digest, enabling anyone to rebuild and verify
358411

359412
## Security Considerations
360413

@@ -453,10 +506,10 @@ Skills are client-only constructs (files in `~/.claude/skills/`) that don't flow
453506

454507
### Alternative 5: Default to All Clients
455508

456-
- **Description**: Install to all detected clients when `--client` not specified
509+
- **Description**: Install to all detected clients when `--client` not specified, or auto-detect when only one client is present
457510
- **Pros**: Simpler UX for single-client users
458-
- **Cons**: Unexpected behavior for multi-client setups, potential for mistakes
459-
- **Why not chosen**: Explicit selection is safer and clearer
511+
- **Cons**: Unexpected behavior for multi-client setups, potential for mistakes, different clients may have different skill conventions
512+
- **Why not chosen**: Explicit selection is safer and clearer. Users working with multiple AI clients (increasingly common) benefit from explicit targeting. This follows the principle of least surprise - the command does exactly what was requested, nothing more. Skillet uses this same approach. We may reconsider this in the future based on user feedback (e.g., auto-detect when only one skill-supporting client is installed).
460513

461514
## Compatibility
462515

0 commit comments

Comments
 (0)