Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add skills/tanstack/ai/tool-callingnpx skills add TanStack/ai --skill tool-callinggit clone --depth 1 https://github.com/TanStack/aiWhat it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5 | $0.00082 | $0.06407 |
| Opus 5 | $0.00041 | $0.03204 |
| Sonnet 5 | $0.00016 | $0.01281 |
| Haiku 4.5 | $0.00008 | $0.00641 |
Grade A, and why
ai-core/tool-calling scanned grade A with 1 finding against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 2d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Runs shell commandslowCapability
Expected in a hook, worth knowing in a rule or an instructions file.
`child_process` imports and must not be bundled for edge runtimes. How it starts
The opening of the file, as written. The whole thing — 791 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Tool Calling
This skill builds on ai-core. Read it first for critical rules.
Setup
Complete end-to-end example: shared definition, server tool, client tool, server route, React client.
// tools/definitions.ts
import { toolDefinition } from '@tanstack/ai'
import { z } from 'zod'
export const getProductsDef = toolDefinition({
name: 'get_products',
description: 'Search for products in the catalog',
inputSchema: z.object({
query: z.string().meta({ description: 'Search keyword' }),
limit: z.number().optional().meta({ description: 'Max results' }),
}),
outputSchema: z.object({
products: z.array(
z.object({ id: z.string(), name: z.string(), price: z.number() }),
),
}),
})
export const updateCartUIDef = toolDefinition({
name: 'update_cart_ui',
description: 'Update the shopping cart UI with item count',
inputSchema: z.object({ itemCount: z.number(), message: z.string() }),
outputSchema: z.object({ displayed: z.boolean() }),
})
// tools/server.ts
import { getProductsDef } from './definitions'
export const getProducts = getProductsDef.server(async ({ query, limit }) => {
const results = await db.products.search(query, { limit: limit ?? 10 })
return {
products: results.map((p) => ({ id: p.id, name: p.name, price: p.price })),
}
})
// api/chat/route.ts
import { chat, toServerSentEventsResponse } from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'
import { getProducts } from '@/tools/server'
import { updateCartUIDef } from '@/tools/definitions'
export async function POST(request: Request) {
const { messages } = await request.json()
const stream = chat({
adapter: openaiText('gpt-5.5'),
messages,
tools: [getProducts, updateCartUIDef], // server tool + client definition
})
return toServerSentEventsResponse(stream)
}
// app/chat.tsx
import {
useChat,
fetchServerSentEvents,
clientTools,
createChatClientOptions,
type InferChatMessages,
} from "@tanstack/ai-react";
import { updateCartUIDef } from "@/tools/definitions";
import { useState } from "react";
function ChatPage() {
const [cartCount, setCartCount] = useState(0);
const updateCartUI = updateCartUIDef.client((input) => {
setCartCount(input.itemCount);
return { displayed: true };
});
const tools = clientTools(updateCartUI);
const chatOptions = createChatClientOptions({
connection: fetchServerSentEvents("/api/chat"),
tools,
});
const { messages, sendMessage } = useChat(chatOptions);
// InferChatMessages ties part types to the configured tools when needed:
// type Messages = InferChatMessages<typeof chatOptions>
return (
<div>
<span>Cart: {cartCount}</span>
{messages.map((msg) => (
<div key={msg.id}>
{msg.parts.map((part) => {
if (part.type === "text") return <p>{part.content}</p>;
if (part.type === "tool-call") {
return <div key={part.id}>Tool: {part.name} ({part.state})</div>;
}
return null;
})}
</div>
))}
</div>
);
}
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 2d ago First seen · 791 lines · 82 tokens per session scan A 8397ae59ffcb
ai-core/tool-calling is a skill published in the GitHub repository TanStack/ai (3,045 stars, last pushed 2d ago), licensed MIT. It adds 82 tokens to every session and 6,407 once invoked, about $0.0004 per session on Opus 5. A static security scan graded it A with 1 finding (runs shell commands). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other skills, from other repositories
storybook
Storybook is the fidelity oracle, not the runtime. The converter bundles the package's compiled dist/ into dsbundle.js - the same bundle the claude.ai/design agent builds with - and generates each preview by compiling the story source module itself (hooks, fixtures, local helpers - the whole closure comes along), with…
save-as-pdf
Reformat the current HTML design into a paginated, paper-ready PDF. The "Instant" export already gives the user a PDF at the design's native pixel size — this path is for when they want real pages.
tmux
Remote-control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.
claude-in-chrome
Automates your Chrome browser to interact with web pages - clicking elements, filling forms, capturing screenshots, reading console logs, and navigating sites. Opens pages in new tabs within your existing Chrome session. Requires site-level permissions before executing (configured in the extension).
verify
Verify that a code change actually does what it's supposed to by exercising it end-to-end and observing behavior — drive the affected flow, not just tests or typecheck. Run before committing nontrivial changes; bootstraps this repo's project verify skill if none exists yet. Don't invoke it on a diff that only touches…
develop-web-game
Use when Codex is building or iterating on a web game (HTML/JS) and needs a reliable development + testing loop: implement small changes, run a Playwright-based test script with short input bursts and intentional pauses, inspect screenshots/text, and review console errors with rendergametotext.