|
| 1 | +--- |
| 2 | +ADR: 0029 |
| 3 | +Title: Skills registry integration (skills.sh) with UI installs + bundled DB skill files |
| 4 | +Status: Implemented |
| 5 | +Version: 0.1 |
| 6 | +Date: 2026-02-09 |
| 7 | +Supersedes: [] |
| 8 | +Superseded-by: [] |
| 9 | +Related: [ADR-0028, ADR-0010, ADR-0013, ADR-0026, ADR-0021] |
| 10 | +Tags: [agents, skills, nextjs, workflow, blob, security] |
| 11 | +Related-Requirements: [FR-035, FR-036, FR-037, NFR-001, NFR-006, NFR-013, NFR-014, NFR-016, IR-006, IR-011] |
| 12 | +References: |
| 13 | + - [skills.sh docs](https://skills.sh/docs) |
| 14 | + - [skills.sh CLI docs](https://skills.sh/docs/cli) |
| 15 | + - [skills.sh search API](https://skills.sh/api/search) |
| 16 | + - [vercel-labs/skills (GitHub)](https://github.com/vercel-labs/skills) |
| 17 | +--- |
| 18 | + |
| 19 | +## Status |
| 20 | + |
| 21 | +Implemented — 2026-02-09. |
| 22 | + |
| 23 | +## Context |
| 24 | + |
| 25 | +The app uses Agent Skills (progressive disclosure) to keep system prompts small |
| 26 | +while providing deep, task-specific workflows (Sandbox, Workflow DevKit, AI SDK, |
| 27 | +etc.). The base implementation supports: |
| 28 | + |
| 29 | +- repo-bundled filesystem skills |
| 30 | +- project-scoped DB skills that override filesystem skills by normalized name |
| 31 | + |
| 32 | +Teams need a **UI-managed** way to discover and install skills from the public |
| 33 | +ecosystem (skills.sh) without requiring developers to: |
| 34 | + |
| 35 | +- edit the repo to add skill folders |
| 36 | +- copy/paste `SKILL.md` into the DB manually |
| 37 | + |
| 38 | +We must preserve the security posture: |
| 39 | + |
| 40 | +- Do not execute skill-bundled code in the app runtime. |
| 41 | +- Any execution must remain sandboxed and approval-gated (ADR-0010). |
| 42 | +- Do not leak Blob URLs/pathnames to clients (public-only storage). |
| 43 | + |
| 44 | +## Decision Drivers |
| 45 | + |
| 46 | +- High leverage: reuse skills.sh registry and GitHub-hosted skills. |
| 47 | +- Strong security: no runtime `npx` or repo writes; strict size/SSRF guardrails. |
| 48 | +- Maintainability: simple contracts, minimal new surface area, strict TS. |
| 49 | +- UX: install/update/uninstall from the project Skills tab. |
| 50 | + |
| 51 | +## Alternatives Considered |
| 52 | + |
| 53 | +### A. Run `npx skills add/remove` in app runtime |
| 54 | + |
| 55 | +Pros: |
| 56 | + |
| 57 | +- Matches the official CLI behavior. |
| 58 | + |
| 59 | +Cons: |
| 60 | + |
| 61 | +- Unacceptable supply-chain risk (runtime package execution). |
| 62 | +- Operational complexity (filesystem writes, caching, cleanup). |
| 63 | +- Conflicts with serverless tracing + immutable deployments. |
| 64 | + |
| 65 | +### B. Run `npx skills` inside Vercel Sandbox |
| 66 | + |
| 67 | +Pros: |
| 68 | + |
| 69 | +- Isolation from app runtime. |
| 70 | + |
| 71 | +Cons: |
| 72 | + |
| 73 | +- Still requires package execution (supply chain + allowlist complexity). |
| 74 | +- Introduces a new control plane (tokens, policy, caching, output validation). |
| 75 | +- Harder UX (async installs, logs, retries) for a first iteration. |
| 76 | + |
| 77 | +### C. Use skills.sh search + GitHub archive ingestion + DB/Blob bundles (**Chosen**) |
| 78 | + |
| 79 | +Pros: |
| 80 | + |
| 81 | +- No runtime package execution. |
| 82 | +- Deterministic parsing: resolve `SKILL.md` by frontmatter `name`. |
| 83 | +- Files for `skills.readFile` are supported via a bundle ZIP stored in Blob. |
| 84 | +- Fits existing precedence model (DB overrides FS). |
| 85 | + |
| 86 | +Cons: |
| 87 | + |
| 88 | +- Requires careful bounds (archive size, bundle limits). |
| 89 | +- Update semantics are “reinstall” (no pinning/version UI yet). |
| 90 | + |
| 91 | +### D. Write skills into repo directories from the UI |
| 92 | + |
| 93 | +Pros: |
| 94 | + |
| 95 | +- Skills become part of the repo skill library. |
| 96 | + |
| 97 | +Cons: |
| 98 | + |
| 99 | +- Not compatible with serverless/immutable deploys. |
| 100 | +- Requires RepoOps + PR flows (large scope, high risk for this feature). |
| 101 | + |
| 102 | +## Decision Framework (must be ≥ 9.0) |
| 103 | + |
| 104 | +Weights: |
| 105 | + |
| 106 | +- Solution leverage: 35% |
| 107 | +- Application value: 30% |
| 108 | +- Maintenance and cognitive load: 25% |
| 109 | +- Architectural adaptability: 10% |
| 110 | + |
| 111 | +| Option | Leverage | Value | Maintenance | Adaptability | Weighted total | |
| 112 | +| --- | ---: | ---: | ---: | ---: | ---: | |
| 113 | +| A. Runtime `npx skills` | 6.5 | 7.5 | 3.0 | 5.5 | 5.74 | |
| 114 | +| B. Sandbox `npx skills` | 7.8 | 8.6 | 7.0 | 8.2 | 7.85 | |
| 115 | +| C. Search API + GitHub zip + DB/Blob bundles | 9.4 | 9.3 | 8.8 | 9.0 | **9.16** | |
| 116 | +| D. Repo write/PR-based installs | 6.8 | 7.2 | 5.6 | 8.6 | 6.70 | |
| 117 | + |
| 118 | +## Decision |
| 119 | + |
| 120 | +Implement registry management as: |
| 121 | + |
| 122 | +1. Search via `skills.sh/api/search`. |
| 123 | +2. Install/update via a **Workflow DevKit** workflow: |
| 124 | + - Download GitHub archive ZIP (`main` → `master` fallback). |
| 125 | + - Resolve the chosen skill by matching `SKILL.md` frontmatter `name` to the |
| 126 | + requested `skillId`. |
| 127 | + - Bundle the skill directory into a ZIP and upload to Vercel Blob. |
| 128 | + - Upsert the skill into `project_skills` with server-only metadata |
| 129 | + referencing the registry id and bundle blob pathname. |
| 130 | +3. Uninstall deletes the DB record and best-effort deletes the bundle blob. |
| 131 | +4. `skills.readFile` supports DB skills **only when** they have a valid bundle |
| 132 | + reference. |
| 133 | + |
| 134 | +Details and file-level contracts are defined in: |
| 135 | + |
| 136 | +- [SPEC-0028](../spec/SPEC-0028-skills-registry-ui-and-bundled-installs.md) |
| 137 | +- [SPEC-0027](../spec/SPEC-0027-agent-skills-runtime-integration.md) |
| 138 | + |
| 139 | +## Consequences |
| 140 | + |
| 141 | +### Positive outcomes |
| 142 | + |
| 143 | +- Users can install skills from the UI without redeploying or editing the repo. |
| 144 | +- Read-only file access works for installed skills (bundled ZIP). |
| 145 | +- Avoids runtime `npx` execution and keeps the app runtime minimal. |
| 146 | + |
| 147 | +### Negative outcomes / risks |
| 148 | + |
| 149 | +- GitHub archive downloads can fail/rate-limit. |
| 150 | + - Mitigation: optional `GITHUB_TOKEN`, strict timeouts, durable retries. |
| 151 | +- Public-only Blob means bundles must be treated as sensitive. |
| 152 | + - Mitigation: never send blob URLs/pathnames to clients; redact metadata. |
| 153 | + |
| 154 | +## Changelog |
| 155 | + |
| 156 | +- **0.1 (2026-02-09)**: Initial version. Implemented as part of SPEC-0028. |
0 commit comments