Install any skill in seconds. Free to start, no credit card required.
Get Started Free →GraphQL queries, mutations, and code generation patterns. Use when creating GraphQL operations, working with Apollo Client, or generating types.
.claude/skills/sickn33-graphql-schema/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 40% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 12% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 58% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 142% | 0% |
| case-17 | ✗→✓ | ▲ Improved | 66% | 0% |
Use this skill when you need graphQL queries, mutations, and code generation patterns. Use when creating GraphQL operations, working with Apollo Client, or generating types.
gql literals - Create .gql files.gql filesonError handler to mutationssrc/
├── components/
│ └── ItemList/
│ ├── ItemList.tsx
│ ├── GetItems.gql # Query definition
│ └── GetItems.generated.ts # Auto-generated (don't edit)
└── graphql/
└── mutations/
└── CreateItem.gql # Shared mutationsgraphql# src/components/ItemList/GetItems.gql query GetItems($limit: Int, $offset: Int) { items(limit: $limit, offset: $offset) { id name description createdAt } }
bashnpm run gql:typegen
typescriptimport { useGetItemsQuery } from './GetItems.generated'; const ItemList = () => { const { data, loading, error, refetch } = useGetItemsQuery({ variables: { limit: 20, offset: 0 }, }); if (error) return <ErrorState error={error} onRetry={refetch} />; if (loading && !data) return <LoadingSkeleton />; if (!data?.items.length) return <EmptyState />; return <List items={data.items} />; };
graphql# src/graphql/mutations/CreateItem.gql mutation CreateItem($input: CreateItemInput!) { createItem(input: $input) { id name description } }
bashnpm run gql:typegen
typescriptimport { useCreateItemMutation } from 'graphql/mutations/CreateItem.generated'; const CreateItemForm = () => { const [createItem, { loading }] = useCreateItemMutation({ // Success handling onCompleted: (data) => { toast.success({ title: 'Item created' }); navigation.goBack(); }, // ERROR HANDLING IS REQUIRED onError: (error) => { console.error('createItem failed:', error); toast.error({ title: 'Failed to create item' }); }, // Cache update update: (cache, { data }) => { if (data?.createItem) { cache.modify({ fields: { items: (existing = []) => [...existing, data.createItem], }, }); } }, }); return ( <Button onPress={() => createItem({ variables: { input: formValues } })} isDisabled={!isValid || loading} isLoading={loading} > Create </Button> ); };
CRITICAL: Every mutation trigger must:
typescript// CORRECT - Complete mutation pattern const [submit, { loading }] = useSubmitMutation({ onError: (error) => { console.error('submit failed:', error); toast.error({ title: 'Save failed' }); }, onCompleted: () => { toast.success({ title: 'Saved' }); }, }); <Button onPress={handleSubmit} isDisabled={!isValid || loading} isLoading={loading} > Submit </Button>
| Policy | Use When | |--------|----------| | cache-first | Data rarely changes | | cache-and-network | Want fast + fresh (default) | | network-only | Always need latest | | no-cache | Never cache (rare) |
typescriptuseGetItemsQuery({ variables: { id: itemId }, // Fetch strategy fetchPolicy: 'cache-and-network', // Re-render on network status changes notifyOnNetworkStatusChange: true, // Skip if condition not met skip: !itemId, // Poll for updates pollInterval: 30000, });
For instant UI feedback:
typescriptconst [toggleFavorite] = useToggleFavoriteMutation({ optimisticResponse: { toggleFavorite: { __typename: 'Item', id: itemId, isFavorite: !currentState, }, }, onError: (error) => { // Rollback happens automatically console.error('toggleFavorite failed:', error); toast.error({ title: 'Failed to update' }); }, });
For reusable field selections:
graphql# src/graphql/fragments/ItemFields.gql fragment ItemFields on Item { id name description createdAt updatedAt }
Use in queries:
graphqlquery GetItems { items { ...ItemFields } }
typescript// WRONG - Inline gql const GET_ITEMS = gql` query GetItems { items { id } } `; // CORRECT - Use .gql file + generated hook import { useGetItemsQuery } from './GetItems.generated'; // WRONG - No error handler const [mutate] = useMutation(MUTATION); // CORRECT - Always handle errors const [mutate] = useMutation(MUTATION, { onError: (error) => { console.error('mutation failed:', error); toast.error({ title: 'Operation failed' }); }, }); // WRONG - Button not disabled during mutation <Button onPress={submit}>Submit</Button> // CORRECT - Disabled and loading <Button onPress={submit} isDisabled={loading} isLoading={loading}> Submit </Button>
bash# Generate types from .gql files npm run gql:typegen # Download schema + generate types npm run sync-types
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 10,433 | 6,525 | -37% | 1 | 1 | 0% | 2,185 | 3,066 | +40% | 0 | 0 | — |
case-02 | fail→pass | 14,849 | 9,031 | -39% | 1 | 1 | 0% | 3,072 | 3,430 | +12% | 0 | 0 | — |
case-03 | fail→pass | 12,994 | 9,388 | -28% | 1 | 1 | 0% | 2,292 | 3,618 | +58% | 0 | 0 | — |
case-04 | pass→pass | 11,275 | 5,461 | -52% | 1 | 1 | 0% | 1,921 | 2,632 | +37% | 0 | 0 | — |
case-05 | fail→pass | 5,479 | 2,033 | -63% | 1 | 1 | 0% | 830 | 2,005 | +142% | 0 | 0 | — |
case-06 | pass→pass | 12,164 | 7,672 | -37% | 1 | 1 | 0% | 2,012 | 3,078 | +53% | 0 | 0 | — |
case-20 | pass→pass | 10,797 | 9,105 | -16% | 1 | 1 | 0% | 1,741 | 3,287 | +89% | 0 | 0 | — |
case-07 | pass→pass | 13,011 | 2,545 | -80% | 1 | 1 | 0% | 1,976 | 2,103 | +6% | 0 | 0 | — |
case-08 | pass→pass | 12,031 | 4,921 | -59% | 1 | 1 | 0% | 1,999 | 2,550 | +28% | 0 | 0 | — |
case-09 | pass→pass | 6,629 | 2,199 | -67% | 1 | 1 | 0% | 1,024 | 2,053 | +100% | 0 | 0 | — |
case-10 | pass→pass | 7,286 | 3,068 | -58% | 1 | 1 | 0% | 1,194 | 2,114 | +77% | 0 | 0 | — |
case-11 | pass→pass | 7,556 | 5,858 | -22% | 1 | 1 | 0% | 1,244 | 2,620 | +111% | 0 | 0 | — |
case-12 | pass→pass | 7,389 | 2,904 | -61% | 1 | 1 | 0% | 1,128 | 2,224 | +97% | 0 | 0 | — |
case-13 | pass→fail | 12,017 | 8,655 | -28% | 1 | 1 | 0% | 2,181 | 3,240 | +49% | 0 | 0 | — |
case-14 | pass→pass | 13,154 | 7,656 | -42% | 1 | 1 | 0% | 1,835 | 2,865 | +56% | 0 | 0 | — |
case-15 | pass→pass | 18,553 | 5,597 | -70% | 1 | 1 | 0% | 1,888 | 2,578 | +37% | 0 | 0 | — |
case-16 | pass→pass | 9,539 | 4,196 | -56% | 1 | 1 | 0% | 1,693 | 2,525 | +49% | 0 | 0 | — |
case-17 | fail→pass | 7,621 | 2,021 | -73% | 1 | 1 | 0% | 1,211 | 2,005 | +66% | 0 | 0 | — |
case-18 | pass→pass | 12,940 | 7,629 | -41% | 1 | 1 | 0% | 2,327 | 3,091 | +33% | 0 | 0 | — |
case-19 | pass→pass | 8,738 | 3,298 | -62% | 1 | 1 | 0% | 1,488 | 2,297 | +54% | 0 | 0 | — |
case-21 | pass→pass | 9,869 | 8,933 | -9% | 1 | 1 | 0% | 1,967 | 3,507 | +78% | 0 | 0 | — |
case-22 | pass→pass | 10,340 | 7,642 | -26% | 1 | 1 | 0% | 1,946 | 3,327 | +71% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +18 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.