create-adaptable-composable — Claude Code skill: flexible Vue
Skill for writing reusable Vue composables that accept values, refs, or getters and work the same way in all cases. Use it when you need a library-grade composable that adapts to different input types.
npx skills add vuejs-ai/skills --skill create-adaptable-composable -a claude-codeWhat create-adaptable-composable does
The skill teaches how to write composables that accept MaybeRef or MaybeRefOrGetter — types letting callers pass a plain value, ref, computed, or function-getter. Inside the composable, you use toValue() to read a value and toRef() to create a reactive source, so the logic behaves predictably in watch or watchEffect.
The skill outlines four steps: confirm the composable's purpose and API, identify which parameters should be reactive, normalize inputs with toValue()/toRef() inside effects, implement the core logic. The rule: use MaybeRefOrGetter for read-only parameters, MaybeRef for writable ones. Don't use MaybeRefOrGetter for callbacks or predicates — you might accidentally invoke them as getters.
Requires Vue 3 or Nuxt 3. The repository includes examples: useDocumentTitle watches a title with toRef, useCounter modifies count through toRef and returns an add function.
What it helps with
- write a composable that accepts a value, ref, or getter without extra checks
- make a reactive parameter that doesn't break when input type changes
- pick between MaybeRef and MaybeRefOrGetter based on use case
- normalize inputs in watch and watchEffect without losing reactivity
- build a reusable composable for a library
Example prompts for the agent
- Help me write useCounter composable that accepts MaybeRef for count and returns an add function
- Create an adaptable composable to track screen width, accepting MaybeRefOrGetter for selector
- I need a composable with a two-way form parameter — use MaybeRef and toRef inside watch
How to install create-adaptable-composable
1Skills CLI (Vercel)
npx skills add vuejs-ai/skills --skill create-adaptable-composable -a claude-code2Manually: put the files in place
~/.claude/skills/create-adaptable-composable/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/create-adaptable-composable/
1Skills CLI (Vercel)
npx skills add vuejs-ai/skills --skill create-adaptable-composable -a codex2Manually: put the files in place
.agents/skills/create-adaptable-composable/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add vuejs-ai/skills --skill create-adaptable-composable -a cursor2Manually: put the files in place
.cursor/skills/create-adaptable-composable/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install vuejs-ai/skills create-adaptable-composable2Manually: put the files in place
.github/skills/create-adaptable-composable/SKILL.md1Skills CLI (Vercel)
npx skills add vuejs-ai/skills --skill create-adaptable-composable -a gemini-cli2Platform CLI
gemini skills install https://github.com/vuejs-ai/skills --path skills/create-adaptable-composableManually: put the files in place
.devin/skills/create-adaptable-composable/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add vuejs-ai/skills --skill create-adaptable-composable -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set7
The whole set →Similar
Questions about create-adaptable-composable
How do I install create-adaptable-composable in Claude Code?
Run npx skills add vuejs-ai/skills --skill create-adaptable-composable -a claude-code, then open ~/.claude/skills/create-adaptable-composable/SKILL.md.
What's the difference between MaybeRef and MaybeRefOrGetter?
MaybeRef is for parameters you need to modify (ref, computed, value). MaybeRefOrGetter adds getter functions, fit for read-only sources like selectors. If the parameter is a callback, don't use MaybeRefOrGetter — you'd accidentally invoke the function.
When should I use this skill?
When writing composables for libraries or components that other developers will use with different input types — values, refs, computed, or getters. The skill ensures your composable works in all cases.
Source text
SKILL.md · MIT
---
name: create-adaptable-composable
description: Create a library-grade Vue composable that accepts maybe-reactive inputs (MaybeRef / MaybeRefOrGetter) so callers can pass a plain value, ref, or getter. Normalize inputs with toValue()/toRef() inside reactive effects (watch/watchEffect) to keep behavior predictable and reactive. Use this skill when user asks for creating adaptable or reusable composables.
license: MIT
metadata:
author: github.com/vuejs-ai
version: "17.0.0"
compatibility: Requires Vue 3 (or above) or Nuxt 3 (or above) project
---
# Create Adaptable Composable
Adaptable composables are reusable functions that can accept both reactive and non-reactive inputs. This allows developers to use the composable in a variety of contexts without worrying about the reactivity of the inputs.
Steps to design an adaptable composable in Vue.js:
1. Confirm the composable's purpose and API design and expected inputs/outputs.
2. Identify inputs params that should be reactive (MaybeRef / MaybeRefOrGetter).
3. Use `toValue()` or `toRef()` to normalize inputs inside reactive effects.
4. Implement the core logic of the composable using Vue's reactivity APIs.
## Core Type Concepts
### Type Utilities
```ts
/**
* value or writable ref (value/ref/shallowRef/writable computed)
*/
export type MaybeRef<T = any> = T | Ref<T> | ShallowRef<T> | WritableComputedRef<T>;
/**
* MaybeRef<T> + ComputedRef<T> + () => T
*/
export type MaybeRefOrGetter<T = any> = MaybeRef<T> | ComputedRef<T> | (() => T);
```
### Policy and Rules
- Read-only, computed-friendly input: use `MaybeRefOrGetter`
- Needs to be writable / two-way input: use `MaybeRef`
- Parameter might be a function value (callback/predicate/comparator): do not use `MaybeRefOrGetter`, or you may accidentally invoke it as a getter.
- DOM/Element targets: if you want computed/derived targets, use `MaybeRefOrGetter`.
When `MaybeRefOrGetter` or `MaybeRef` is used:
- resolve reactive value using `toRef()` (e.g. watcher source)
- resolve non-reactive value using `toValue()`
### Examples
Adaptable `useDocumentTitle` Composable: read-only title parameter
```ts
import { watch, toRef } from 'vue'
import type { MaybeRefOrGetter } from 'vue'
export function useDocumentTitle(title: MaybeRefOrGetter<string>) {
watch(toRef(title), (t) => {
document.title = t
}, { immediate: true })
}
```
Adaptable `useCounter` Composable: two-way writable count parameter
```ts
import { watch, toRef } from 'vue'
import type { MaybeRef } from 'vue'
function useCounter(count: MaybeRef<number>) {
const countRef = toRef(count)
function add() {
countRef.value++
}
return { add }
}
```
© github.com/vuejs-ai · MIT · vuejs-ai/skills