diff --git a/.agents/skills/changeset/SKILL.md b/.agents/skills/changeset/SKILL.md index f99a4b3f7aab..59f78d3a3b80 100644 --- a/.agents/skills/changeset/SKILL.md +++ b/.agents/skills/changeset/SKILL.md @@ -2,6 +2,8 @@ name: changeset description: Create user-focused changesets (changelog entries) for semver bumps, release notes, breaking changes, and docs; prefer impact and code examples over implementation detail disable-model-invocation: true +metadata: + internal: true --- # Create Changesets diff --git a/.agents/skills/data-client-setup/SKILL.md b/.agents/skills/data-client-setup/SKILL.md index 8b4f119f9e68..6fb2307d7099 100644 --- a/.agents/skills/data-client-setup/SKILL.md +++ b/.agents/skills/data-client-setup/SKILL.md @@ -1,6 +1,6 @@ --- name: data-client-setup -description: Install and set up @data-client/react or @data-client/vue in a project. Detects project type (NextJS, Expo, React Native, Vue, plain React) and protocol (REST, GraphQL, custom), then hands off to protocol-specific setup skills. +description: Install and set up @data-client/react or @data-client/vue in a project. Detects project type (NextJS, Expo, React Native, Vue, plain React) and protocol (REST, GraphQL, custom), then installs and hands off to the matching framework and protocol skills. disable-model-invocation: true --- @@ -58,6 +58,27 @@ For async operations that don't match REST or GraphQL: - Third-party SDK clients (Firebase, Supabase, AWS SDK, etc.) - IndexedDB or other local async storage +### 4. Install the Skills This Project Needs + +This skill hands off to other Data Client skills. Install the ones that match what you detected, skipping any already installed: + +| Detected | Skills | +|----------|--------| +| Always | `data-client-schema`, `data-client-manager` | +| React (NextJS, Expo, React Native, plain React) | `data-client-react`, `data-client-react-testing` | +| Vue | `data-client-vue`, `data-client-vue-testing` | +| REST | `data-client-rest-setup`, `data-client-rest` | +| GraphQL | `data-client-graphql-setup` | +| Custom async | `data-client-endpoint-setup` | + +Use the installer that installed this skill. For OpenSkills and the skills CLI, add `-g` if this skill lives under your home directory rather than the project. + +- **Claude Code plugin** (this skill is under `~/.claude/plugins/`): `claude plugin install react@data-client` or `claude plugin install vue@data-client`. Either includes every skill above. +- **OpenSkills** (`AGENTS.md` lists skills in an `` block): `npx openskills install reactive/data-client/.agents/skills/`, once per skill. +- **Otherwise** use the skills CLI: `npx skills add reactive/data-client --yes --skill --skill ...` + +Newly installed skills may not be loaded until the next session, so read their `SKILL.md` directly when this skill says to apply them. + ## Installation ### Core Packages diff --git a/.agents/skills/frontend-design/SKILL.md b/.agents/skills/frontend-design/SKILL.md index 5be498e25858..18f2ae378aea 100644 --- a/.agents/skills/frontend-design/SKILL.md +++ b/.agents/skills/frontend-design/SKILL.md @@ -2,6 +2,8 @@ name: frontend-design description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics. license: Complete terms in LICENSE.txt +metadata: + internal: true --- This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices. diff --git a/.agents/skills/initialize/SKILL.md b/.agents/skills/initialize/SKILL.md index 39a1860a4527..ef46a6985fa8 100644 --- a/.agents/skills/initialize/SKILL.md +++ b/.agents/skills/initialize/SKILL.md @@ -2,6 +2,8 @@ name: initialize description: Setup, install, and onboard new developers to Reactive Data Client monorepo - nvm, yarn, build, test, getting started guide disable-model-invocation: true +metadata: + internal: true --- # Initialize Development Environment diff --git a/.agents/skills/packages-documentation/SKILL.md b/.agents/skills/packages-documentation/SKILL.md index 5445bd53faed..65c2b3b2f88c 100644 --- a/.agents/skills/packages-documentation/SKILL.md +++ b/.agents/skills/packages-documentation/SKILL.md @@ -2,6 +2,8 @@ name: packages-documentation description: Write, update, and format documentation for @data-client public APIs - API reference (Docusaurus/MDX), README files, JSDoc/TSDoc docstrings, usage examples, migration guides, deprecation notices, changelog entries. Use when changing exported APIs (docs must update in the same PR), writing new package docs, or updating the dataclient.io site. license: Apache 2.0 +metadata: + internal: true --- # Package Documentation Writing Guidelines diff --git a/.agents/skills/pr/SKILL.md b/.agents/skills/pr/SKILL.md index 2e39d9600ec6..a9110c32529b 100644 --- a/.agents/skills/pr/SKILL.md +++ b/.agents/skills/pr/SKILL.md @@ -2,6 +2,8 @@ name: pr description: Create a GitHub pull request from current working changes. Handles all git states - uncommitted changes, no branch, unpushed commits, etc. Analyzes diffs and changesets to generate a PR with filled-in template. Opens the PR in the browser when done. Use when the user asks to create a PR, open a PR, submit changes, or push for review. disable-model-invocation: true +metadata: + internal: true --- # Create Pull Request diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 000000000000..7b693f4c5e62 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,67 @@ +{ + "name": "data-client", + "owner": { + "name": "Nathaniel Tucker", + "email": "me@ntucker.me" + }, + "metadata": { + "description": "Agent skills for Reactive Data Client: setup, schemas, REST, managers, and React or Vue usage and testing" + }, + "plugins": [ + { + "name": "core", + "description": "Framework-agnostic Data Client skills: setup, REST, GraphQL, custom endpoints, schemas, and managers", + "source": "./", + "strict": false, + "homepage": "https://dataclient.io/docs/getting-started/agent-skills", + "license": "Apache-2.0", + "skills": [ + "./.agents/skills/data-client-setup", + "./.agents/skills/data-client-rest-setup", + "./.agents/skills/data-client-endpoint-setup", + "./.agents/skills/data-client-graphql-setup", + "./.agents/skills/data-client-schema", + "./.agents/skills/data-client-rest", + "./.agents/skills/data-client-manager" + ] + }, + { + "name": "react", + "description": "Data Client hooks and testing for React, NextJS, and React Native", + "source": "./", + "strict": false, + "homepage": "https://dataclient.io/docs/getting-started/agent-skills", + "license": "Apache-2.0", + "dependencies": ["core"], + "skills": [ + "./.agents/skills/data-client-react", + "./.agents/skills/data-client-react-testing" + ] + }, + { + "name": "vue", + "description": "Data Client composables and testing for Vue 3", + "source": "./", + "strict": false, + "homepage": "https://dataclient.io/vue/getting-started/agent-skills", + "license": "Apache-2.0", + "dependencies": ["core"], + "skills": [ + "./.agents/skills/data-client-vue", + "./.agents/skills/data-client-vue-testing" + ] + }, + { + "name": "migrations", + "description": "Upgrade guides: Data Client v0.18 delegate signatures and path-to-regexp v8 path syntax", + "source": "./", + "strict": false, + "homepage": "https://dataclient.io/blog", + "license": "Apache-2.0", + "skills": [ + "./.agents/skills/data-client-v0.18-migration", + "./.agents/skills/path-to-regexp-v8-migration" + ] + } + ] +} diff --git a/docs/core/getting-started/agent-skills.md b/docs/core/getting-started/agent-skills.md index f214610f2a6a..169e187c0fbf 100644 --- a/docs/core/getting-started/agent-skills.md +++ b/docs/core/getting-started/agent-skills.md @@ -11,26 +11,20 @@ The quickest way to get started is to let an [AI Agent](https://agentskills.io) ## Install -:::react - - - -::: + -:::vue +Then run skill `/data-client-setup`. It detects your framework and API style (REST, GraphQL, +custom), installs the matching skills below, wires up the provider, and migrates existing endpoints. - +### Install all skills up front -::: +To install every skill for your framework now instead, without letting your agent run installs: -Then run skill `/data-client-setup` to install and wire up the provider for your -project. It will automatically detect your framework (NextJS, Expo, React Native, Vue, -plain React), perform installation, as well as do migrations when existing -endpoints are found. + ## Available Skills -- [**`/data-client-setup`**](https://skills.sh/reactive/data-client/data-client-setup) — installs and configures Data Client for your framework and API style. +- [**`/data-client-setup`**](https://skills.sh/reactive/data-client/data-client-setup) — installs and configures Data Client for your framework and API style, along with the skills it needs. - [**`/data-client-rest-setup`**](https://skills.sh/reactive/data-client/data-client-rest-setup) — sets up `@data-client/rest` and migrates existing `fetch`/`axios` clients. - [**`/data-client-endpoint-setup`**](https://skills.sh/reactive/data-client/data-client-endpoint-setup) — wraps custom async functions with `Endpoint` diff --git a/website/src/components/SkillTabs.tsx b/website/src/components/SkillTabs.tsx index 85b406df7070..259decf0029b 100644 --- a/website/src/components/SkillTabs.tsx +++ b/website/src/components/SkillTabs.tsx @@ -3,33 +3,45 @@ import TabItem from '@theme/TabItem'; import Tabs from '@theme/Tabs'; import React from 'react'; +import marketplace from '../../../.claude-plugin/marketplace.json'; +import useFramework from './useFramework'; + interface Props { repo?: string; - /** Directory of the skills within repo; openskills installs one skill per path */ - skillsDir?: string; skill?: string; skills?: string[]; - /** Skills for the OpenSkills tab when it should differ from `skills` (it has no picker groups) */ - openSkills?: string[]; + /** Plugin from `.claude-plugin/marketplace.json` to install with its dependencies. + * Defaults to the current page's framework when no skills are given. */ + plugin?: string; } +const skillsDir = '.agents/skills'; + export default function SkillTabs({ repo = 'reactive/data-client', - skillsDir = '.agents/skills', skill, skills, - openSkills, + plugin, }: Props) { - const allSkills = skills ?? (skill ? [skill] : []); - const skillFlag = allSkills.map(s => ` --skill ${s}`).join(''); + const framework = useFramework(); + if (!skills && skill) skills = [skill]; + if (!skills) plugin ??= framework; + const allSkills = plugin ? pluginSkills(plugin) : (skills ?? []); + const skillsCommand = [ + `npx skills add ${repo}`, + ...allSkills.map(s => `--skill ${s}`), + ].join(allSkills.length > 1 ? ' \\\n ' : ' '); // openskills has no --skill flag; it installs a single skill from its path - const openSkillList = openSkills ?? allSkills; - const openSkillsCommand = - openSkillList.length ? - openSkillList - .map(s => `npx openskills install ${repo}/${skillsDir}/${s}`) - .join('\n') - : `npx openskills install ${repo}`; + const openSkillsCommand = allSkills + .map(s => `npx openskills install ${repo}/${skillsDir}/${s}`) + .join('\n'); + // Claude Code installs whole plugins, so install each one holding a listed skill + const claudePlugins = + plugin ? [plugin] : [...new Set(allSkills.map(pluginOf))]; + const claudeCommand = [ + `claude plugin marketplace add ${repo}`, + ...claudePlugins.map(p => `claude plugin install ${p}@${marketplace.name}`), + ].join('\n'); return ( - - npx skills add {repo} - {skillFlag} - + {skillsCommand} {openSkillsCommand} + + {claudeCommand} + ); } + +const plugins: { name: string; dependencies?: string[]; skills: string[] }[] = + marketplace.plugins; + +const skillName = (path: string) => path.slice(path.lastIndexOf('/') + 1); + +/** Skill names of a marketplace plugin, after those of its dependencies */ +function pluginSkills(name: string): string[] { + const plugin = plugins.find(p => p.name === name); + if (!plugin) throw new Error(`No plugin "${name}" in marketplace.json`); + return [ + ...(plugin.dependencies ?? []).flatMap(pluginSkills), + ...plugin.skills.map(skillName), + ]; +} + +/** Name of the marketplace plugin that holds a skill */ +function pluginOf(skill: string): string { + const plugin = plugins.find(p => p.skills.some(s => skillName(s) === skill)); + if (!plugin) throw new Error(`No plugin holds skill "${skill}"`); + return plugin.name; +}