An agentic skills framework & software development methodology that works.
VueUse skills pack for Claude Code and agents
This repo packages VueUse guidance as agent skills so coding assistants can reach for the right Composition Utilities without needing the whole library in context. It uses short overviews first, then loads deeper usage and type details when needed, which keeps prompts smaller and helps avoid made-up APIs.
Builders who want their agent to use VueUse accurately while writing Vue or Nuxt features.
You can ask an agent to build Vue features with VueUse without re-explaining the library every time.
What it does
Progressive disclosure
Sends function overviews first, then loads detailed usage and type declarations only when needed.
Minimal token usage
Keeps the agent focused on the pieces it needs instead of loading the whole library.
Offline-first design
Works without internet access or extra agent permissions.
Customizable invocation rules
Lets users override function-use rules in prompts or `AGENTS.md`.
Reduced hallucinations
Uses precise VueUse references so agents are less likely to invent APIs.
How to get it
- 1Run
npx skills add vueuse/skills
- 2An alternative for Claude Code users
# Add marketplace /plugin marketplace add vueuse/skills # Install individual skills /plugin install vueuse-functions@vueuse-skills
- 3Example prompt
create a todo app with the following features: - save todos to local storage - show remains todo count on browser title - add a copy button for each todo items - infinite scrolling for this todo list - dark / light mode
README
VueUse Skills
Agent Skills for VueUse β a collection of essential Vue Composition Utilities.
[!IMPORTANT] Experimental Project: Aims to help AI agents use libraries more accurately with fewer tokens. Feedback is welcome.
- πͺ Progressive disclosure: send VueUse function overviews first, then load detailed usage and type declarations on demand
- π° Minimal token usage: provide only necessary information to reduce token consumption
- π΅ Offline-first design: works without internet access or additional agent permissions
- βοΈ Customizable policies: users can override function invocation rules in prompts or
AGENTS.md - π Reduced hallucinations: precise usage references help prevent invented APIs
Installation
npx skills add vueuse/skills
Claude Code Marketplace
An alternative for Claude Code users:
# Add marketplace
/plugin marketplace add vueuse/skills
# Install individual skills
/plugin install vueuse-functions@vueuse-skills
Example Usage
Install VueUse in your Vue or Nuxt project, then instruct the agent. It will automatically leverage VueUse to assist development.
Example prompt:
create a todo app with the following features:
- save todos to local storage
- show remains todo count on browser title
- add a copy button for each todo items
- infinite scrolling for this todo list
- dark / light mode
Output Snippet
<script setup lang="ts">
import { computed, ref } from 'vue'
import {
useClipboard,
useColorMode,
useInfiniteScroll,
useLocalStorage,
useTitle,
} from '@vueuse/core'
type Todo = {
id: number
text: string
done: boolean
}
const seedTexts = [
'Review project goals',
'Plan the next sprint',
'Reply to client email',
]
const defaultTodos = Array.from({ length: 36 }, (_, index) => ({
id: index + 1,
text:
seedTexts[index % seedTexts.length] +
(index >= seedTexts.length ? ` #${index + 1}` : ''),
done: index % 7 === 0,
}))
const todos = useLocalStorage<Todo[]>('focus-flow-todos', defaultTodos)
const nextId = ref(
todos.value.reduce((max, todo) => Math.max(max, todo.id), 0) + 1,
)
const newTodo = ref('')
const totalCount = computed(() => todos.value.length)
const remainingCount = computed(() =>
todos.value.filter((todo) => !todo.done).length,
)
const completedCount = computed(
() => totalCount.value - remainingCount.value,
)
useTitle(computed(() => `Todos (${remainingCount.value})`))
const mode = useColorMode({
attribute: 'data-theme',
disableTransition: false,
})
const isDark = computed(() => mode.value === 'dark')
const toggleMode = () => {
mode.value = isDark.value ? 'light' : 'dark'
}
const { copy, copied, isSupported } = useClipboard()
const lastCopiedId = ref<number | null>(null)
const handleCopy = async (todo: Todo) => {
await copy(todo.text)
lastCopiedId.value = todo.id
}
const pageSize = 8
const visibleCount = ref(Math.min(pageSize, todos.value.length))
const visibleTodos = computed(() => todos.value.slice(0, visibleCount.value))
const listRef = ref<HTMLElement | null>(null)
const { isLoading } = useInfiniteScroll(
listRef,
() => {
if (visibleCount.value < todos.value.length) {
visibleCount.value = Math.min(
visibleCount.value + pageSize,
todos.value.length,
)
}
},
{
distance: 120,
canLoadMore: () => visibleCount.value < todos.value.length,
},
)
const syncVisibleCount = () => {
if (todos.value.length <= pageSize) {
visibleCount.value = todos.value.length
return
}
if (visibleCount.value === 0) {
visibleCount.value = pageSize
return
}
if (visibleCount.value > todos.value.length) {
visibleCount.value = todos.value.length
}
}
const addTodo = () => {
const value = newTodo.value.trim()
if (!value)
return
todos.value.unshift({
id: nextId.value++,
text: value,
done: false,
})
newTodo.value = ''
syncVisibleCount()
}
const removeTodo = (id: number) => {
todos.value = todos.value.filter((todo) => todo.id !== id)
syncVisibleCount()
}
</script>
<template>
<div class="page">
<div class="shell">
<header class="header">
<div>
<p class="eyebrow">Minimal todo tracker</p>
<h1>Focus Flow</h1>
<p class="subtitle">
Keep a lightweight list, copy tasks with a click, and scroll as the
list grows.
</p>
</div>
<button class="btn ghost mode-toggle" type="button" @click="toggleMode">
<span class="mode-dot" :class="{ dark: isDark }" />
<span>{{ isDark ? 'Dark' : 'Light' }} mode</span>
</button>
</header>
<form class="composer" @submit.prevent="addTodo">
<div class="input-wrap">
<input
v-model="newTodo"
type="text"
maxlength="120"
placeholder="Add a new task"
aria-label="Add a new task"
/>
<button class="btn primary" type="submit" :disabled="!newTodo.trim()">
Add task
</button>
</div>
<div class="stats">
<div class="stat">
<span>Total</span>
<strong>{{ totalCount }}</strong>
</div>
<div class="stat">
<span>Remaining</span>
<strong>{{ remainingCount }}</strong>
</div>
<div v-if="completedCount" class="stat">
<span>Done</span>
<strong>{{ completedCount }}</strong>
</div>
</div>
</form>
<section class="list-card">
<div class="list-head">
<h2>Todo list</h2>
<span class="list-hint">
{{ visibleTodos.length }} / {{ totalCount }} shown
</span>
</div>
<div ref="listRef" class="todo-list" aria-live="polite">
<article
v-for="(todo, index) in visibleTodos"
:key="todo.id"
class="todo-item"
:class="{ done: todo.done }"
:style="{ animationDelay: `${index * 0.03}s` }"
>
<label class="todo-check">
<input v-model="todo.done" type="checkbox" />
<span class="checkmark" />
</label>
<p class="todo-text">{{ todo.text }}</p>
<div class="todo-actions">
<button
class="btn ghost"
type="button"
:disabled="!isSupported"
:title="isSupported ? 'Copy task text' : 'Clipboard not supported'"
@click="handleCopy(todo)"
>
{{ copied && lastCopiedId === todo.id ? 'Copied' : 'Copy' }}
</button>
<button class="btn danger" type="button" @click="removeTodo(todo.id)">
Remove
</button>
</div>
</article>
<p v-if="!visibleTodos.length" class="empty">
No tasks yet. Add your first todo above.
</p>
<div v-if="visibleTodos.length" class="list-footer">
<span class="footer-status">
<span v-if="isLoading">Loading more...</span>
<span v-else-if="visibleTodos.length < totalCount">
Scroll to load more
</span>
<span v-else>All caught up</span>
</span>
</div>
</div>
</section>
</div>
</div>
</template>
<style>
@import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;500;600;700&family=Space+Mono:wght@400;700&display=swap');
:root {
color-scheme: light;
--bg: #f6f7fb;
--bg-spot: rgba(59, 130, 246, 0.18);
--bg-spot-2: rgba(34, 197, 94, 0.18);
--card: rgba(255, 255, 255, 0.92);
--surface: rgba(255, 255, 255, 0.84);
--border: rgba(148, 163, 184, 0.35);
--text: #0f172a;
--muted: #64748b;
--accent: #2563eb;
--accent-strong: #1d4ed8;
--accent-soft: rgba(37, 99, 235, 0.18);
--danger: #ef4444;
--danger-soft: rgba(239, 68, 68, 0.15);
--shadow: 0 24px 60px rgba(15, 23, 42, 0.12);
--radius: 22px;
}
:root[data-theme='dark'] {
color-scheme: dark;
--bg: #0b1222;
--bg-spot: rgba(56, 189, 248, 0.18);
--bg-spot-2: rgba(16, 185, 129, 0.16);
--card: rgba(15, 23, 42, 0.86);
--surface: rgba(15, 23, 42, 0.7);
--border: rgba(148, 163, 184, 0.25);
--text: #f8fafc;
--muted: #94a3b8;
--accent: #38bdf8;
--accent-strong: #0ea5e9;
--accent-soft: rgba(56, 189, 248, 0.2);
--danger: #f87171;
--danger-soft: rgba(248, 113, 113, 0.2);
--shadow: 0 26px 70px rgba(2, 6, 23, 0.55);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
font-family: 'Sora', system-ui, -apple-system, sans-serif;
color: var(--text);
background:
radial-gradient(900px circle at top left, var(--bg-spot), transparent 55%),
radial-gradient(700px circle at bottom right, var(--bg-spot-2), transparent 50%),
var(--bg);
transition: background 0.4s ease, color 0.4s ease;
}
#app {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: clamp(20px, 4vw, 48px);
}
.page {
width: min(980px, 100%);
}
.shell {
display: grid;
gap: clamp(20px, 3vw, 28px);
padding: clamp(20px, 4vw, 36px);
border-radius: var(--radius);
background: var(--card);
border: 1px solid var(--border);
box-shadow: var(--shadow);
backdrop-filter: blur(18px);
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 24px;
}
.eyebrow {
text-transform: uppercase;
letter-spacing: 0.2em;
font-size: 0.72rem;
color: var(--muted);
margin: 0 0 10px;
}
h1 {
margin: 0;
font-size: clamp(2rem, 3vw, 2.6rem);
}
.subtitle {
margin: 10px 0 0;
color: var(--muted);
max-width: 520px;
}
.composer {
display: grid;
gap: 16px;
}
.input-wrap {
display: grid;
grid-template-columns: 1fr auto;
gap: 12px;
}
input[type='text'] {
padding: 12px 14px;
border-radius: 14px;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
font-size: 1rem;
transition: border 0.2s ease, box-shadow 0.2s ease;
}
input[type='text']:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-soft);
}
.stats {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.stat {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
border-radius: 999px;
background: var(--surface);
border: 1px solid var(--border);
font-size: 0.9rem;
color: var(--muted);
}
.stat strong {
font-family: 'Space Mono', ui-monospace, SFMono-Regular, monospace;
color: var(--text);
font-size: 0.95rem;
}
.list-card {
display: grid;
gap: 16px;
}
.list-head {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
}
.list-head h2 {
margin: 0;
font-size: 1.2rem;
}
.list-hint {
font-size: 0.85rem;
color: var(--muted);
font-family: 'Space Mono', ui-monospace, SFMono-Regular, monospace;
}
.todo-list {
max-height: clamp(320px, 55vh, 520px);
overflow-y: auto;
display: grid;
gap: 12px;
padding: 6px;
margin: -6px;
}
.todo-item {
display: grid;
grid-template-columns: auto 1fr auto;
gap: 12px;
align-items: center;
padding: 14px 16px;
border-radius: 16px;
background: var(--surface);
border: 1px solid var(--border);
animation: fadeUp 0.4s ease both;
}
.todo-item.done {
opacity: 0.7;
}
.todo-text {
margin: 0;
font-size: 0.98rem;
}
.todo-item.done .todo-text {
text-decoration: line-through;
color: var(--muted);
}
.todo-check {
display: inline-flex;
align-items: center;
}
.todo-check input {
width: 18px;
height: 18px;
accent-color: var(--accent);
}
.checkmark {
display: none;
}
.todo-actions {
display: inline-flex;
gap: 8px;
flex-wrap: wrap;
}
.btn {
border: 1px solid var(--border);
background: transparent;
color: var(--text);
padding: 8px 14px;
border-radius: 999px;
font-size: 0.88rem;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 8px;
transition: all 0.2s ease;
}
.btn:disabled {
cursor: not-allowed;
opacity: 0.6;
}
.btn.primary {
background: var(--accent);
border-color: var(--accent);
color: #fff;
font-weight: 600;
}
.btn.primary:hover:not(:disabled) {
background: var(--accent-strong);
border-color: var(--accent-strong);
}
.btn.ghost:hover:not(:disabled) {
border-color: var(--accent);
color: var(--accent);
}
.btn.danger {
border-color: transparent;
color: var(--danger);
background: var(--danger-soft);
}
.mode-toggle {
white-space: nowrap;
}
.mode-dot {
width: 10px;
height: 10px;
border-radius: 50%;
background: #facc15;
box-shadow: 0 0 0 3px rgba(250, 204, 21, 0.2);
}
.mode-dot.dark {
background: #38bdf8;
box-shadow: 0 0 0 3px rgba(56, 189, 248, 0.2);
}
.empty {
text-align: center;
padding: 32px 12px;
color: var(--muted);
border-radius: 16px;
border: 1px dashed var(--border);
}
.list-footer {
text-align: center;
font-size: 0.85rem;
color: var(--muted);
padding: 8px 0 12px;
}
@keyframes fadeUp {
from {
opacity: 0;
transform: translateY(8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (max-width: 820px) {
.header {
flex-direction: column;
align-items: flex-start;
}
.input-wrap {
grid-template-columns: 1fr;
}
.todo-item {
grid-template-columns: auto 1fr;
}
.todo-actions {
grid-column: 1 / -1;
justify-content: flex-end;
}
}
</style>
License
MIT
Files in the repo
- .claude-plugin
- .github
- .vscode
- skills
- templates
- .gitignore
- .gitmodules
- build.ts
- eslint.config.js
- LICENSE
- package.json
- pnpm-lock.yaml
- pnpm-workspace.yaml
- README.md
- tsconfig.json
- vueuse
Discussion (0)
Ask about usage, or say what you built with itSign in to join the discussion.
No comments yet. Be the first to say what this is good for.
More skills

Turn any codebase, with its docs, SQL schemas, configs, and PDFs, into a queryable knowledge graph. A /graphify skill for Claude Code, Cursor, Codex, and Gemini CLI: local deterministic AST parsing, every edge explained, no vector store.
Topic in, narrated explainer video out. A Claude Code / Codex skill that turns any topic into a black-canvas motion-graphics explainer video with TTS voiceover, subtitles and a chapter progress bar. Chinese or English; every frame drawn in code with Remotion.
Public repository for Agent Skills
Open-source AI job search: scan job portals, evaluate listings into a structured A-H report with a global 1-5 score, tailor your CV, track applications β runs locally in your AI coding CLI (Claude Code, Codex, OpenCode, Antigravityβ¦)

Production-grade engineering skills for AI coding agents.