Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Write docstrings for PyTorch functions and methods following PyTorch conventions. Use when writing or updating docstrings in PyTorch code.
.claude/skills/microck-docstring/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 146% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 167% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 20% | 0% |
| case-17 | ✗→✓ | ▲ Improved | 241% | 0% |
| case-18 | ✗→✓ | ▲ Improved | 103% | 0% |
This skill describes how to write docstrings for functions and methods in the PyTorch project, following the conventions in torch/_tensor_docs.py and torch/nn/functional.py.
r"""...""") for all docstrings to avoid issues with LaTeX/math backslashesStart with the function signature showing all parameters:
pythonr"""function_name(param1, param2, *, kwarg1=default1, kwarg2=default2) -> ReturnType
Notes:
* separator)Provide a one-line description of what the function does:
pythonr"""conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1) -> Tensor Applies a 2D convolution over an input image composed of several input planes.
Use Sphinx math directives for mathematical expressions:
python.. math:: \text{Softmax}(x_{i}) = \frac{\exp(x_i)}{\sum_j \exp(x_j)}
Or inline math: :math:\x^2\
Link to related classes and functions using Sphinx roles:
:class:\~torch.nn.ModuleName\ - Link to a class:func:\torch.function_name\ - Link to a function:meth:\~Tensor.method_name\ - Link to a method:attr:\attribute_name\ - Reference an attribute~ prefix shows only the last component (e.g., Conv2d instead of torch.nn.Conv2d)Example:
pythonSee :class:`~torch.nn.Conv2d` for details and output shape.
Use admonitions for important information:
python.. note:: This function doesn't work directly with NLLLoss, which expects the Log to be computed between the Softmax and itself. Use log_softmax instead (it's faster and has better numerical properties). .. warning:: :func:`new_tensor` always copies :attr:`data`. If you have a Tensor ``data`` and want to avoid a copy, use :func:`torch.Tensor.requires_grad_` or :func:`torch.Tensor.detach`.
Document all parameters with type annotations and descriptions:
pythonArgs: input (Tensor): input tensor of shape :math:`(\text{minibatch} , \text{in\_channels} , iH , iW)` weight (Tensor): filters of shape :math:`(\text{out\_channels} , kH , kW)` bias (Tensor, optional): optional bias tensor of shape :math:`(\text{out\_channels})`. Default: ``None`` stride (int or tuple): the stride of the convolving kernel. Can be a single number or a tuple `(sH, sW)`. Default: 1
Formatting rules:
(Type), (Type, optional) for optional parametersvalue" at the end None Sometimes keyword arguments are documented separately:
pythonKeyword args: dtype (:class:`torch.dtype`, optional): the desired type of returned tensor. Default: if None, same :class:`torch.dtype` as this tensor. device (:class:`torch.device`, optional): the desired device of returned tensor. Default: if None, same :class:`torch.device` as this tensor. requires_grad (bool, optional): If autograd should record operations on the returned tensor. Default: ``False``.
Document the return value:
pythonReturns: Tensor: Sampled tensor of same shape as `logits` from the Gumbel-Softmax distribution. If ``hard=True``, the returned samples will be one-hot, otherwise they will be probability distributions that sum to 1 across `dim`.
Or simply include it in the function signature line if obvious from context.
Always include examples when possible:
pythonExamples:: >>> inputs = torch.randn(33, 16, 30) >>> filters = torch.randn(20, 16, 5) >>> F.conv1d(inputs, filters) >>> # With square kernels and equal stride >>> filters = torch.randn(8, 4, 3, 3) >>> inputs = torch.randn(1, 4, 5, 5) >>> F.conv2d(inputs, filters, padding=1)
Formatting rules:
Examples:: with double colon>>> prompt for Python code# when helpful>>>)Link to papers or external documentation:
python.. _Link Name: https://arxiv.org/abs/1611.00712
Reference them in text: See Link Name_
For regular Python functions, use a standard docstring:
pythondef relu(input: Tensor, inplace: bool = False) -> Tensor: r"""relu(input, inplace=False) -> Tensor Applies the rectified linear unit function element-wise. See :class:`~torch.nn.ReLU` for more details. """ # implementation
For C-bound functions, use _add_docstr:
pythonconv1d = _add_docstr( torch.conv1d, r""" conv1d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1) -> Tensor Applies a 1D convolution over an input signal composed of several input planes. See :class:`~torch.nn.Conv1d` for details and output shape. Args: input: input tensor of shape :math:`(\text{minibatch} , \text{in\_channels} , iW)` weight: filters of shape :math:`(\text{out\_channels} , kW)` ... """, )
For in-place operations (ending with _), reference the original:
pythonadd_docstr_all( "abs_", r""" abs_() -> Tensor In-place version of :meth:`~Tensor.abs` """, )
For aliases, simply reference the original:
pythonadd_docstr_all( "absolute", r""" absolute() -> Tensor Alias for :func:`abs` """, )
Use LaTeX math notation for tensor shapes:
python:math:`(\text{minibatch} , \text{in\_channels} , iH , iW)`
For commonly used arguments, define them once and reuse:
pythoncommon_args = parse_kwargs( """ dtype (:class:`torch.dtype`, optional): the desired type of returned tensor. Default: if None, same as this tensor. """ ) # Then use with .format(): r""" ... Keyword args: {dtype} {device} """.format(**common_args)
Insert reproducibility notes or other common text:
pythonr""" {tf32_note} {cudnn_reproducibility_note} """.format(**reproducibility_notes, **tf32_notes)
Here's a complete example showing all elements:
pythondef gumbel_softmax( logits: Tensor, tau: float = 1, hard: bool = False, eps: float = 1e-10, dim: int = -1, ) -> Tensor: r""" Sample from the Gumbel-Softmax distribution and optionally discretize. Args: logits (Tensor): `[..., num_features]` unnormalized log probabilities tau (float): non-negative scalar temperature hard (bool): if ``True``, the returned samples will be discretized as one-hot vectors, but will be differentiated as if it is the soft sample in autograd. Default: ``False`` dim (int): A dimension along which softmax will be computed. Default: -1 Returns: Tensor: Sampled tensor of same shape as `logits` from the Gumbel-Softmax distribution. If ``hard=True``, the returned samples will be one-hot, otherwise they will be probability distributions that sum to 1 across `dim`. .. note:: This function is here for legacy reasons, may be removed from nn.Functional in the future. Examples:: >>> logits = torch.randn(20, 32) >>> # Sample soft categorical using reparametrization trick: >>> F.gumbel_softmax(logits, tau=1, hard=False) >>> # Sample hard categorical using "Straight-through" trick: >>> F.gumbel_softmax(logits, tau=1, hard=True) .. _Link 1: https://arxiv.org/abs/1611.00712 """ # implementation
When writing a PyTorch docstring, ensure:
r"""):func:, :class:, :meth:):class::class:\~torch.nn.Module\ - Class reference:func:\torch.function\ - Function reference:meth:\~Tensor.method\ - Method reference:attr:\attribute\ - Attribute reference:math:\equation\ - Inline math:ref:\label\ - Internal reference code - Inline code (use double backticks) True None False Tensor, int, float, bool, str, tuple, list, etc.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-22 | pass→pass | 5,026 | 3,593 | -29% | 1 | 1 | 0% | 822 | 3,424 | +317% | 0 | 0 | — |
case-01 | pass→pass | 15,003 | 12,618 | -16% | 1 | 1 | 0% | 2,976 | 5,497 | +85% | 0 | 0 | — |
case-02 | pass→pass | 12,515 | 10,745 | -14% | 1 | 1 | 0% | 2,399 | 5,062 | +111% | 0 | 0 | — |
case-03 | pass→pass | 10,790 | 8,634 | -20% | 1 | 1 | 0% | 2,054 | 4,552 | +122% | 0 | 0 | — |
case-04 | pass→pass | 9,225 | 6,472 | -30% | 1 | 1 | 0% | 1,758 | 4,050 | +130% | 0 | 0 | — |
case-05 | fail→pass | 9,692 | 7,237 | -25% | 1 | 1 | 0% | 1,685 | 4,140 | +146% | 0 | 0 | — |
case-06 | pass→pass | 5,932 | 3,124 | -47% | 1 | 1 | 0% | 1,154 | 3,408 | +195% | 0 | 0 | — |
case-07 | pass→pass | 9,248 | 3,215 | -65% | 1 | 1 | 0% | 1,646 | 3,296 | +100% | 0 | 0 | — |
case-08 | pass→pass | 5,231 | 3,289 | -37% | 1 | 1 | 0% | 875 | 3,349 | +283% | 0 | 0 | — |
case-09 | pass→pass | 6,665 | 2,790 | -58% | 1 | 1 | 0% | 1,171 | 3,250 | +178% | 0 | 0 | — |
case-10 | fail→pass | 8,986 | 7,453 | -17% | 1 | 1 | 0% | 1,590 | 4,244 | +167% | 0 | 0 | — |
case-11 | fail→fail | 8,494 | 7,129 | -16% | 1 | 1 | 0% | 1,488 | 4,105 | +176% | 0 | 0 | — |
case-12 | fail→pass | 18,360 | 6,866 | -63% | 1 | 1 | 0% | 3,499 | 4,215 | +20% | 0 | 0 | — |
case-13 | pass→pass | 8,818 | 4,822 | -45% | 1 | 1 | 0% | 1,597 | 3,613 | +126% | 0 | 0 | — |
case-14 | pass→pass | 7,335 | 4,288 | -42% | 1 | 1 | 0% | 1,194 | 3,472 | +191% | 0 | 0 | — |
case-15 | pass→pass | 6,268 | 4,329 | -31% | 1 | 1 | 0% | 1,140 | 3,501 | +207% | 0 | 0 | — |
case-16 | pass→pass | 5,159 | 6,516 | +26% | 1 | 1 | 0% | 907 | 4,133 | +356% | 0 | 0 | — |
case-17 | fail→pass | 5,887 | 3,266 | -45% | 1 | 1 | 0% | 950 | 3,241 | +241% | 0 | 0 | — |
case-18 | fail→pass | 10,296 | 4,533 | -56% | 1 | 1 | 0% | 1,799 | 3,651 | +103% | 0 | 0 | — |
case-19 | pass→pass | 3,857 | 4,335 | +12% | 1 | 1 | 0% | 624 | 3,458 | +454% | 0 | 0 | — |
case-20 | pass→pass | 12,859 | 11,967 | -7% | 1 | 1 | 0% | 2,079 | 4,891 | +135% | 0 | 0 | — |
case-21 | pass→pass | 6,958 | 5,737 | -18% | 1 | 1 | 0% | 1,360 | 3,850 | +183% | 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 +23 percentage points is the difference between those two pass rates over the 22 comparable cases.
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.