Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when writing or reformatting the documentation comments on TypeScript declarations (functions, methods, classes, interfaces, type aliases): format them as TSDoc — a /** */ block that opens with a summary sentence, then `@param name - description` with a hyphen and NO {type} braces, `@returns`, `@typeParam`, `@defaultValue`, `@deprecated`, one tag per parameter in order — which cheaper models do not produce by default. Do NOT use for Python or other-language docstrings, for authoring prose API reference pages, or for ordinary explanatory inline comments.
.claude/skills/tsdoc-comments/SKILL.md| Model | Eval pass | Runs |
|---|---|---|
| gemini-3.6-flash | 100% | 18 |
| Model | Lift | Δ tokens | Δ turns | Cases | Verified |
|---|---|---|---|---|---|
| gemini-3.6-flashbest | +23% | +159% | 0% | 22 | 54d ago |
| gemini-3.5-flash | pending re-run | — | |||
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-02 | ✗→✓ | ▲ Improved | — | — |
| case-19 | ✗→✓ | ▲ Improved | — | — |
| case-22 | ✗→✓ | ▲ Improved | — | — |
| case-10 | ✗→✓ | ▲ Improved | — | — |
Documentation comments on TypeScript declarations follow TSDoc: a /** */ block that opens with a prose summary, then block tags — @param name - description (a hyphen separator, and NEVER a {type} brace, because the TypeScript signature already carries the type), @returns, @typeParam, @remarks, @example, @defaultValue, @deprecated — one tag per parameter, in signature order. Apply when writing or cleaning up doc comments on functions, methods, classes, interfaces, and type aliases; not for docstrings in another language, prose reference pages, or ordinary inline comments.
/** ... */ block placed directly above the declarationit documents — not // line comments and not a plain /* */ block. Interior lines conventionally begin with * .
does. Tags always come after the summary, never before it. Longer discussion belongs in a @remarks tag, not stuffed into the summary line.
@param shape — hyphen, no type braces. Document each parameter as@param parameterName - description. The hyphen between the name and the description is required. Do NOT add a {type} annotation: @param {string} name is the JSDoc form, not TSDoc — the parameter's declared type in the signature is the single source of truth. Emit exactly one @param per parameter, ordered to match the signature.
@returns, spelled in full. Document the return value with @returns (with thetrailing s), in prose and, again, with no {type} brace. @return without the s is the JSDoc spelling and is wrong here. Omit the tag entirely for a void function rather than writing @returns void.
@typeParam. A generic type parameter is documented with@typeParam T - description, hyphen included. Not @template and not @tparam — those come from other toolchains.
@defaultValue for defaults. State the default of an optional parameter or propertywith @defaultValue, e.g. @defaultValue 0. Not @default.
@deprecated carries a reason. Mark a deprecated declaration with @deprecated plus anote saying what to use instead — not merely a sentence in the summary.
@example for usage. Runnable usage samples go under an @example tag, one fenced blockeach, rather than being narrated inside the summary.
@remarks → @typeParam → @param (in signature order) →@returns → @throws → @example → @deprecated. Keep the parameter tags grouped and in order.
A plain function — the JSDoc default, then the conforming TSDoc:
tsBEFORE /** * @param {number} value the number to clamp * @param {number} min lower bound * @param {number} max upper bound * @return the clamped number */ function clamp(value: number, min: number, max: number): number { /* ... */ }
tsAFTER /** * Restricts a number to an inclusive range. * @param value - the number to constrain * @param min - the lower bound * @param max - the upper bound * @returns the value pulled to the nearest bound when it falls outside the range */ function clamp(value: number, min: number, max: number): number { /* ... */ }
A generic function — @template/@default braces, then TSDoc:
tsBEFORE /** * @template T * @param {T[]} items the array * @param {number} [size] chunk size * @default 10 */ function chunk<T>(items: T[], size = 10): T[][] { /* ... */ }
tsAFTER /** * Splits a list into consecutive fixed-length groups. * @typeParam T - the element type of the input list * @param items - the list to divide * @param size - the maximum length of each group * @defaultValue 10 * @returns an array of groups, each holding at most `size` elements */ function chunk<T>(items: T[], size = 10): T[][] { /* ... */ }
A deprecation — prose aside, then a real @deprecated tag:
tsBEFORE /** Old palette helper — don't use, call resolveColor instead. */ function legacyColor(name: string): string | undefined { /* ... */ }
tsAFTER /** * Reads a named swatch from the legacy palette table. * @deprecated Use `resolveColor`, which honors theme overrides this ignores. * @param name - the palette key to look up * @returns the hex string, or `undefined` when the key is absent */ function legacyColor(name: string): string | undefined { /* ... */ }
A usage sample — narrated, then an @example block:
tsBEFORE /** Formats an amount. Call it like formatMoney(9.5, 'USD'). */ function formatMoney(amount: number, currency: string): string { /* ... */ }
tsAFTER /** * Formats a numeric amount as a localized currency string. * @param amount - the value to format * @param currency - the ISO 4217 code selecting the currency * @returns the formatted display string * @example * ```ts * formatMoney(9.5, "USD"); // "$9.50" * ``` */ function formatMoney(amount: number, currency: string): string { /* ... */ }
void return → omit @returns altogether; do not write @returns void.@param name - ...; the optionality lives in the signature(name?), not in a @param [name] bracket.
@param values - ...; the tag name carries no ... prefix.the prose, rather than inventing a @param options.field tag per key.
@throws tag naming the condition, not a note in @returns.{@link OtherSymbol} inside adescription; it is a TSDoc inline tag, not free prose.
{type} braces to any tag.@returns. Don't write @return.@typeParam. Don't reach for @template.@defaultValue. Don't write @default.@param {string} id - ... — the JSDoc type brace that TSDoc drops.@return without the trailing s.@template T instead of @typeParam T for a generic.@default 5 instead of @defaultValue 5.@param id the identifier — the missing hyphen separator.@param [id] - ... — the bracket-for-optional habit; optionality belongs in the signature.@param and no summary sentence.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
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 +23 percentage points is the difference between those two pass rates over the 22 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.5-flash | verified | 7/10/2026 | +32% |
Other measured skills in the registry, with their headline benchmark lift.