{"id":43451423,"url":"https://github.com/vueuse/skills","last_synced_at":"2026-03-04T11:06:47.559Z","repository":{"id":334276665,"uuid":"1140788023","full_name":"vueuse/skills","owner":"vueuse","description":"Agent Skills for VueUse","archived":false,"fork":false,"pushed_at":"2026-02-23T07:48:43.000Z","size":1114,"stargazers_count":321,"open_issues_count":0,"forks_count":7,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-02-23T15:52:55.081Z","etag":null,"topics":["agent-skills","agents","ai","skills","vue","vueuse"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vueuse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-23T19:03:02.000Z","updated_at":"2026-02-23T10:23:26.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/vueuse/skills","commit_stats":null,"previous_names":["serkodev/vueuse-skills","vueuse/skills"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vueuse/skills","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vueuse%2Fskills","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vueuse%2Fskills/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vueuse%2Fskills/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vueuse%2Fskills/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vueuse","download_url":"https://codeload.github.com/vueuse/skills/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vueuse%2Fskills/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30078522,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T08:01:56.766Z","status":"ssl_error","status_checked_at":"2026-03-04T08:00:42.919Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-skills","agents","ai","skills","vue","vueuse"],"created_at":"2026-02-03T02:00:30.446Z","updated_at":"2026-03-04T11:06:47.532Z","avatar_url":"https://github.com/vueuse.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","Framework Skills"],"sub_categories":[],"readme":"![VueUse Skills banner](./.github/assets/banner.svg)\n\n# VueUse Skills\n\nAgent Skills for [VueUse](https://vueuse.org/) — a collection of essential Vue Composition Utilities.\n\n\u003e [!IMPORTANT]\n\u003e Experimental Project: Aims to help AI agents use libraries more accurately with fewer tokens. Feedback is welcome.\n\n- 🪜 Progressive disclosure: send VueUse function overviews first, then load detailed usage and type declarations on demand\n- 💰 Minimal token usage: provide only necessary information to reduce token consumption\n- 📵 Offline-first design: works without internet access or additional agent permissions\n- ⚙️ Customizable policies: users can override function invocation rules in prompts or `AGENTS.md`\n- 💉 Reduced hallucinations: precise usage references help prevent invented APIs\n\n## Installation\n\n```bash\nnpx skills add vueuse/skills\n```\n\n### Claude Code Marketplace\n\nAn alternative for Claude Code users:\n\n```bash\n# Add marketplace\n/plugin marketplace add vueuse/skills\n\n# Install individual skills\n/plugin install vueuse-functions@vueuse-skills\n```\n\n## Example Usage\n\nInstall VueUse in your Vue or Nuxt project, then instruct the agent. It will automatically leverage VueUse to assist development.\n\nExample prompt:\n\n```\ncreate a todo app with the following features:\n- save todos to local storage\n- show remains todo count on browser title\n- add a copy button for each todo items\n- infinite scrolling for this todo list\n- dark / light mode\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eOutput Snippet\u003c/summary\u003e\n\n```vue\n\u003cscript setup lang=\"ts\"\u003e\nimport { computed, ref } from 'vue'\nimport {\n  useClipboard,\n  useColorMode,\n  useInfiniteScroll,\n  useLocalStorage,\n  useTitle,\n} from '@vueuse/core'\n\ntype Todo = {\n  id: number\n  text: string\n  done: boolean\n}\n\nconst seedTexts = [\n  'Review project goals',\n  'Plan the next sprint',\n  'Reply to client email',\n]\n\nconst defaultTodos = Array.from({ length: 36 }, (_, index) =\u003e ({\n  id: index + 1,\n  text:\n    seedTexts[index % seedTexts.length] +\n    (index \u003e= seedTexts.length ? ` #${index + 1}` : ''),\n  done: index % 7 === 0,\n}))\n\nconst todos = useLocalStorage\u003cTodo[]\u003e('focus-flow-todos', defaultTodos)\nconst nextId = ref(\n  todos.value.reduce((max, todo) =\u003e Math.max(max, todo.id), 0) + 1,\n)\nconst newTodo = ref('')\n\nconst totalCount = computed(() =\u003e todos.value.length)\nconst remainingCount = computed(() =\u003e\n  todos.value.filter((todo) =\u003e !todo.done).length,\n)\nconst completedCount = computed(\n  () =\u003e totalCount.value - remainingCount.value,\n)\n\nuseTitle(computed(() =\u003e `Todos (${remainingCount.value})`))\n\nconst mode = useColorMode({\n  attribute: 'data-theme',\n  disableTransition: false,\n})\nconst isDark = computed(() =\u003e mode.value === 'dark')\n\nconst toggleMode = () =\u003e {\n  mode.value = isDark.value ? 'light' : 'dark'\n}\n\nconst { copy, copied, isSupported } = useClipboard()\nconst lastCopiedId = ref\u003cnumber | null\u003e(null)\n\nconst handleCopy = async (todo: Todo) =\u003e {\n  await copy(todo.text)\n  lastCopiedId.value = todo.id\n}\n\nconst pageSize = 8\nconst visibleCount = ref(Math.min(pageSize, todos.value.length))\nconst visibleTodos = computed(() =\u003e todos.value.slice(0, visibleCount.value))\n\nconst listRef = ref\u003cHTMLElement | null\u003e(null)\nconst { isLoading } = useInfiniteScroll(\n  listRef,\n  () =\u003e {\n    if (visibleCount.value \u003c todos.value.length) {\n      visibleCount.value = Math.min(\n        visibleCount.value + pageSize,\n        todos.value.length,\n      )\n    }\n  },\n  {\n    distance: 120,\n    canLoadMore: () =\u003e visibleCount.value \u003c todos.value.length,\n  },\n)\n\nconst syncVisibleCount = () =\u003e {\n  if (todos.value.length \u003c= pageSize) {\n    visibleCount.value = todos.value.length\n    return\n  }\n\n  if (visibleCount.value === 0) {\n    visibleCount.value = pageSize\n    return\n  }\n\n  if (visibleCount.value \u003e todos.value.length) {\n    visibleCount.value = todos.value.length\n  }\n}\n\nconst addTodo = () =\u003e {\n  const value = newTodo.value.trim()\n  if (!value)\n    return\n\n  todos.value.unshift({\n    id: nextId.value++,\n    text: value,\n    done: false,\n  })\n  newTodo.value = ''\n  syncVisibleCount()\n}\n\nconst removeTodo = (id: number) =\u003e {\n  todos.value = todos.value.filter((todo) =\u003e todo.id !== id)\n  syncVisibleCount()\n}\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003cdiv class=\"page\"\u003e\n    \u003cdiv class=\"shell\"\u003e\n      \u003cheader class=\"header\"\u003e\n        \u003cdiv\u003e\n          \u003cp class=\"eyebrow\"\u003eMinimal todo tracker\u003c/p\u003e\n          \u003ch1\u003eFocus Flow\u003c/h1\u003e\n          \u003cp class=\"subtitle\"\u003e\n            Keep a lightweight list, copy tasks with a click, and scroll as the\n            list grows.\n          \u003c/p\u003e\n        \u003c/div\u003e\n        \u003cbutton class=\"btn ghost mode-toggle\" type=\"button\" @click=\"toggleMode\"\u003e\n          \u003cspan class=\"mode-dot\" :class=\"{ dark: isDark }\" /\u003e\n          \u003cspan\u003e{{ isDark ? 'Dark' : 'Light' }} mode\u003c/span\u003e\n        \u003c/button\u003e\n      \u003c/header\u003e\n\n      \u003cform class=\"composer\" @submit.prevent=\"addTodo\"\u003e\n        \u003cdiv class=\"input-wrap\"\u003e\n          \u003cinput\n            v-model=\"newTodo\"\n            type=\"text\"\n            maxlength=\"120\"\n            placeholder=\"Add a new task\"\n            aria-label=\"Add a new task\"\n          /\u003e\n          \u003cbutton class=\"btn primary\" type=\"submit\" :disabled=\"!newTodo.trim()\"\u003e\n            Add task\n          \u003c/button\u003e\n        \u003c/div\u003e\n        \u003cdiv class=\"stats\"\u003e\n          \u003cdiv class=\"stat\"\u003e\n            \u003cspan\u003eTotal\u003c/span\u003e\n            \u003cstrong\u003e{{ totalCount }}\u003c/strong\u003e\n          \u003c/div\u003e\n          \u003cdiv class=\"stat\"\u003e\n            \u003cspan\u003eRemaining\u003c/span\u003e\n            \u003cstrong\u003e{{ remainingCount }}\u003c/strong\u003e\n          \u003c/div\u003e\n          \u003cdiv v-if=\"completedCount\" class=\"stat\"\u003e\n            \u003cspan\u003eDone\u003c/span\u003e\n            \u003cstrong\u003e{{ completedCount }}\u003c/strong\u003e\n          \u003c/div\u003e\n        \u003c/div\u003e\n      \u003c/form\u003e\n\n      \u003csection class=\"list-card\"\u003e\n        \u003cdiv class=\"list-head\"\u003e\n          \u003ch2\u003eTodo list\u003c/h2\u003e\n          \u003cspan class=\"list-hint\"\u003e\n            {{ visibleTodos.length }} / {{ totalCount }} shown\n          \u003c/span\u003e\n        \u003c/div\u003e\n        \u003cdiv ref=\"listRef\" class=\"todo-list\" aria-live=\"polite\"\u003e\n          \u003carticle\n            v-for=\"(todo, index) in visibleTodos\"\n            :key=\"todo.id\"\n            class=\"todo-item\"\n            :class=\"{ done: todo.done }\"\n            :style=\"{ animationDelay: `${index * 0.03}s` }\"\n          \u003e\n            \u003clabel class=\"todo-check\"\u003e\n              \u003cinput v-model=\"todo.done\" type=\"checkbox\" /\u003e\n              \u003cspan class=\"checkmark\" /\u003e\n            \u003c/label\u003e\n            \u003cp class=\"todo-text\"\u003e{{ todo.text }}\u003c/p\u003e\n            \u003cdiv class=\"todo-actions\"\u003e\n              \u003cbutton\n                class=\"btn ghost\"\n                type=\"button\"\n                :disabled=\"!isSupported\"\n                :title=\"isSupported ? 'Copy task text' : 'Clipboard not supported'\"\n                @click=\"handleCopy(todo)\"\n              \u003e\n                {{ copied \u0026\u0026 lastCopiedId === todo.id ? 'Copied' : 'Copy' }}\n              \u003c/button\u003e\n              \u003cbutton class=\"btn danger\" type=\"button\" @click=\"removeTodo(todo.id)\"\u003e\n                Remove\n              \u003c/button\u003e\n            \u003c/div\u003e\n          \u003c/article\u003e\n\n          \u003cp v-if=\"!visibleTodos.length\" class=\"empty\"\u003e\n            No tasks yet. Add your first todo above.\n          \u003c/p\u003e\n\n          \u003cdiv v-if=\"visibleTodos.length\" class=\"list-footer\"\u003e\n            \u003cspan class=\"footer-status\"\u003e\n              \u003cspan v-if=\"isLoading\"\u003eLoading more...\u003c/span\u003e\n              \u003cspan v-else-if=\"visibleTodos.length \u003c totalCount\"\u003e\n                Scroll to load more\n              \u003c/span\u003e\n              \u003cspan v-else\u003eAll caught up\u003c/span\u003e\n            \u003c/span\u003e\n          \u003c/div\u003e\n        \u003c/div\u003e\n      \u003c/section\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cstyle\u003e\n@import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;500;600;700\u0026family=Space+Mono:wght@400;700\u0026display=swap');\n\n:root {\n  color-scheme: light;\n  --bg: #f6f7fb;\n  --bg-spot: rgba(59, 130, 246, 0.18);\n  --bg-spot-2: rgba(34, 197, 94, 0.18);\n  --card: rgba(255, 255, 255, 0.92);\n  --surface: rgba(255, 255, 255, 0.84);\n  --border: rgba(148, 163, 184, 0.35);\n  --text: #0f172a;\n  --muted: #64748b;\n  --accent: #2563eb;\n  --accent-strong: #1d4ed8;\n  --accent-soft: rgba(37, 99, 235, 0.18);\n  --danger: #ef4444;\n  --danger-soft: rgba(239, 68, 68, 0.15);\n  --shadow: 0 24px 60px rgba(15, 23, 42, 0.12);\n  --radius: 22px;\n}\n\n:root[data-theme='dark'] {\n  color-scheme: dark;\n  --bg: #0b1222;\n  --bg-spot: rgba(56, 189, 248, 0.18);\n  --bg-spot-2: rgba(16, 185, 129, 0.16);\n  --card: rgba(15, 23, 42, 0.86);\n  --surface: rgba(15, 23, 42, 0.7);\n  --border: rgba(148, 163, 184, 0.25);\n  --text: #f8fafc;\n  --muted: #94a3b8;\n  --accent: #38bdf8;\n  --accent-strong: #0ea5e9;\n  --accent-soft: rgba(56, 189, 248, 0.2);\n  --danger: #f87171;\n  --danger-soft: rgba(248, 113, 113, 0.2);\n  --shadow: 0 26px 70px rgba(2, 6, 23, 0.55);\n}\n\n* {\n  box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  min-height: 100vh;\n  font-family: 'Sora', system-ui, -apple-system, sans-serif;\n  color: var(--text);\n  background:\n    radial-gradient(900px circle at top left, var(--bg-spot), transparent 55%),\n    radial-gradient(700px circle at bottom right, var(--bg-spot-2), transparent 50%),\n    var(--bg);\n  transition: background 0.4s ease, color 0.4s ease;\n}\n\n#app {\n  min-height: 100vh;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  padding: clamp(20px, 4vw, 48px);\n}\n\n.page {\n  width: min(980px, 100%);\n}\n\n.shell {\n  display: grid;\n  gap: clamp(20px, 3vw, 28px);\n  padding: clamp(20px, 4vw, 36px);\n  border-radius: var(--radius);\n  background: var(--card);\n  border: 1px solid var(--border);\n  box-shadow: var(--shadow);\n  backdrop-filter: blur(18px);\n}\n\n.header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 24px;\n}\n\n.eyebrow {\n  text-transform: uppercase;\n  letter-spacing: 0.2em;\n  font-size: 0.72rem;\n  color: var(--muted);\n  margin: 0 0 10px;\n}\n\nh1 {\n  margin: 0;\n  font-size: clamp(2rem, 3vw, 2.6rem);\n}\n\n.subtitle {\n  margin: 10px 0 0;\n  color: var(--muted);\n  max-width: 520px;\n}\n\n.composer {\n  display: grid;\n  gap: 16px;\n}\n\n.input-wrap {\n  display: grid;\n  grid-template-columns: 1fr auto;\n  gap: 12px;\n}\n\ninput[type='text'] {\n  padding: 12px 14px;\n  border-radius: 14px;\n  border: 1px solid var(--border);\n  background: var(--surface);\n  color: var(--text);\n  font-size: 1rem;\n  transition: border 0.2s ease, box-shadow 0.2s ease;\n}\n\ninput[type='text']:focus {\n  outline: none;\n  border-color: var(--accent);\n  box-shadow: 0 0 0 3px var(--accent-soft);\n}\n\n.stats {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 12px;\n}\n\n.stat {\n  display: inline-flex;\n  align-items: center;\n  gap: 8px;\n  padding: 8px 12px;\n  border-radius: 999px;\n  background: var(--surface);\n  border: 1px solid var(--border);\n  font-size: 0.9rem;\n  color: var(--muted);\n}\n\n.stat strong {\n  font-family: 'Space Mono', ui-monospace, SFMono-Regular, monospace;\n  color: var(--text);\n  font-size: 0.95rem;\n}\n\n.list-card {\n  display: grid;\n  gap: 16px;\n}\n\n.list-head {\n  display: flex;\n  align-items: baseline;\n  justify-content: space-between;\n  gap: 12px;\n}\n\n.list-head h2 {\n  margin: 0;\n  font-size: 1.2rem;\n}\n\n.list-hint {\n  font-size: 0.85rem;\n  color: var(--muted);\n  font-family: 'Space Mono', ui-monospace, SFMono-Regular, monospace;\n}\n\n.todo-list {\n  max-height: clamp(320px, 55vh, 520px);\n  overflow-y: auto;\n  display: grid;\n  gap: 12px;\n  padding: 6px;\n  margin: -6px;\n}\n\n.todo-item {\n  display: grid;\n  grid-template-columns: auto 1fr auto;\n  gap: 12px;\n  align-items: center;\n  padding: 14px 16px;\n  border-radius: 16px;\n  background: var(--surface);\n  border: 1px solid var(--border);\n  animation: fadeUp 0.4s ease both;\n}\n\n.todo-item.done {\n  opacity: 0.7;\n}\n\n.todo-text {\n  margin: 0;\n  font-size: 0.98rem;\n}\n\n.todo-item.done .todo-text {\n  text-decoration: line-through;\n  color: var(--muted);\n}\n\n.todo-check {\n  display: inline-flex;\n  align-items: center;\n}\n\n.todo-check input {\n  width: 18px;\n  height: 18px;\n  accent-color: var(--accent);\n}\n\n.checkmark {\n  display: none;\n}\n\n.todo-actions {\n  display: inline-flex;\n  gap: 8px;\n  flex-wrap: wrap;\n}\n\n.btn {\n  border: 1px solid var(--border);\n  background: transparent;\n  color: var(--text);\n  padding: 8px 14px;\n  border-radius: 999px;\n  font-size: 0.88rem;\n  cursor: pointer;\n  display: inline-flex;\n  align-items: center;\n  gap: 8px;\n  transition: all 0.2s ease;\n}\n\n.btn:disabled {\n  cursor: not-allowed;\n  opacity: 0.6;\n}\n\n.btn.primary {\n  background: var(--accent);\n  border-color: var(--accent);\n  color: #fff;\n  font-weight: 600;\n}\n\n.btn.primary:hover:not(:disabled) {\n  background: var(--accent-strong);\n  border-color: var(--accent-strong);\n}\n\n.btn.ghost:hover:not(:disabled) {\n  border-color: var(--accent);\n  color: var(--accent);\n}\n\n.btn.danger {\n  border-color: transparent;\n  color: var(--danger);\n  background: var(--danger-soft);\n}\n\n.mode-toggle {\n  white-space: nowrap;\n}\n\n.mode-dot {\n  width: 10px;\n  height: 10px;\n  border-radius: 50%;\n  background: #facc15;\n  box-shadow: 0 0 0 3px rgba(250, 204, 21, 0.2);\n}\n\n.mode-dot.dark {\n  background: #38bdf8;\n  box-shadow: 0 0 0 3px rgba(56, 189, 248, 0.2);\n}\n\n.empty {\n  text-align: center;\n  padding: 32px 12px;\n  color: var(--muted);\n  border-radius: 16px;\n  border: 1px dashed var(--border);\n}\n\n.list-footer {\n  text-align: center;\n  font-size: 0.85rem;\n  color: var(--muted);\n  padding: 8px 0 12px;\n}\n\n@keyframes fadeUp {\n  from {\n    opacity: 0;\n    transform: translateY(8px);\n  }\n  to {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n\n@media (max-width: 820px) {\n  .header {\n    flex-direction: column;\n    align-items: flex-start;\n  }\n\n  .input-wrap {\n    grid-template-columns: 1fr;\n  }\n\n  .todo-item {\n    grid-template-columns: auto 1fr;\n  }\n\n  .todo-actions {\n    grid-column: 1 / -1;\n    justify-content: flex-end;\n  }\n}\n\u003c/style\u003e\n```\n\u003c/details\u003e\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvueuse%2Fskills","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvueuse%2Fskills","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvueuse%2Fskills/lists"}