← Back to Skills Marketplace
anderskev

Elixir Writing Docs

by Kevin Anderson · GitHub ↗ · v1.2.1 · MIT-0
cross-platform ✓ Security Clean
191
Downloads
0
Stars
1
Active Installs
2
Versions
Install in OpenClaw
/install elixir-writing-docs
Description
Guides writing Elixir documentation with @moduledoc, @doc, @typedoc, doctests, cross-references, and metadata. Use when adding or improving documentation in...
README (SKILL.md)

Elixir Writing Docs

Quick Reference

Topic Reference
Doctests: syntax, gotchas, when to use references/doctests.md
Cross-references and linking syntax references/cross-references.md
Admonitions, formatting, tabs references/admonitions-and-formatting.md

First-Line Summary Rule

ExDoc and tools like mix docs extract the first paragraph of @moduledoc and @doc as a summary. Keep the opening line concise and self-contained.

# GOOD - first line works as a standalone summary
@moduledoc """
Handles payment processing through Stripe and local ledger reconciliation.

Wraps the Stripe API client and ensures each charge is recorded in the
local ledger before returning a confirmation to the caller.
"""

# BAD - first line is vague, forces reader to continue
@moduledoc """
This module contains various functions related to payments.

It uses Stripe and also updates the ledger.
"""

The same rule applies to @doc:

# GOOD
@doc """
Charges a customer's default payment method for the given amount in cents.

Returns `{:ok, charge}` on success or `{:error, reason}` when the payment
gateway rejects the request.
"""

# BAD
@doc """
This function is used to charge a customer.
"""

@moduledoc Structure

A well-structured @moduledoc follows this pattern:

defmodule MyApp.Inventory do
  @moduledoc """
  Tracks warehouse stock levels and triggers replenishment orders.

  This module maintains an ETS-backed cache of current quantities and
  exposes functions for atomic stock adjustments. It is designed to be
  started under a supervisor and will restore state from the database
  on init.

  ## Examples

      iex> {:ok, pid} = MyApp.Inventory.start_link(warehouse: :east)
      iex> MyApp.Inventory.current_stock(pid, "SKU-1042")
      {:ok, 350}

  ## Configuration

  Expects the following in `config/runtime.exs`:

      config :my_app, MyApp.Inventory,
        repo: MyApp.Repo,
        low_stock_threshold: 50
  """
end

Key points:

  • First paragraph is the summary (one to two sentences).
  • ## Examples shows realistic usage. Use doctests when the example is runnable.
  • ## Configuration documents required config keys. Omit this section if the module takes no config.
  • Use second-level headings (##) only. First-level (#) is reserved for the module name in ExDoc output.

Documenting Behaviour Modules

When defining a behaviour, document the expected callbacks:

defmodule MyApp.PaymentGateway do
  @moduledoc """
  Behaviour for payment gateway integrations.

  Implementations must handle charging, refunding, and status checks.
  See `MyApp.PaymentGateway.Stripe` for a reference implementation.

  ## Callbacks

  * `charge/2` - Initiate a charge for a given amount
  * `refund/2` - Refund a previously completed charge
  * `status/1` - Check the status of a transaction
  """

  @callback charge(amount :: pos_integer(), currency :: atom()) ::
              {:ok, transaction_id :: String.t()} | {:error, term()}

  @callback refund(transaction_id :: String.t(), amount :: pos_integer()) ::
              :ok | {:error, term()}

  @callback status(transaction_id :: String.t()) ::
              {:pending | :completed | :failed, map()}
end

@doc Structure

@doc """
Reserves the given quantity of an item, decrementing available stock.

Returns `{:ok, reservation_id}` when stock is available, or
`{:error, :insufficient_stock}` when the requested quantity exceeds
what is on hand.

## Examples

    iex> MyApp.Inventory.reserve("SKU-1042", 5)
    {:ok, "res_abc123"}

    iex> MyApp.Inventory.reserve("SKU-9999", 1)
    {:error, :not_found}

## Options

  * `:warehouse` - Target warehouse atom. Defaults to `:primary`.
  * `:timeout` - Timeout in milliseconds. Defaults to `5_000`.
"""
@spec reserve(String.t(), pos_integer(), keyword()) ::
        {:ok, String.t()} | {:error, :insufficient_stock | :not_found}
def reserve(sku, quantity, opts \\ []) do
  # ...
end

Guidelines:

  • State what the function does, then what it returns.
  • Document each option in a bulleted ## Options section when the function accepts a keyword list.
  • Place @spec between @doc and def. This is the conventional ordering.
  • Include doctests for pure functions. Skip them for side-effecting functions (see references/doctests.md).

@typedoc

Document custom types defined with @type or @opaque:

@typedoc """
A positive integer representing an amount in the smallest currency unit (e.g., cents).
"""
@type amount :: pos_integer()

@typedoc """
Reservation status returned by `status/1`.

  * `:held` - Stock is reserved but not yet shipped
  * `:released` - Reservation was cancelled and stock restored
  * `:fulfilled` - Items have shipped
"""
@type reservation_status :: :held | :released | :fulfilled

@typedoc """
Opaque handle returned by `connect/1`. Do not pattern-match on this value.
"""
@opaque connection :: %__MODULE__{socket: port(), buffer: binary()}

For @opaque types, the @typedoc is especially important because callers cannot inspect the structure.

Metadata

@doc since and @doc deprecated

@doc since: "1.3.0"
@doc """
Transfers stock between two warehouses.
"""
def transfer(from, to, sku, quantity), do: # ...

@doc deprecated: "Use transfer/4 instead"
@doc """
Moves items between locations. Deprecated in favor of `transfer/4`
which supports cross-region transfers.
"""
def move_stock(from, to, sku, quantity), do: # ...

You can combine metadata and the docstring in one attribute:

@doc since: "2.0.0", deprecated: "Use bulk_reserve/2 instead"
@doc """
Reserves multiple items in a single call.
"""
def batch_reserve(items), do: # ...

@moduledoc since: works the same way for modules:

@moduledoc since: "1.2.0"
@moduledoc """
Handles webhook signature verification for Stripe events.
"""

When to Use @doc false / @moduledoc false

Suppress documentation when the module or function is not part of the public API:

# Private implementation module — internal to the application
defmodule MyApp.Inventory.StockCache do
  @moduledoc false
  # ...
end

# Protocol implementation — documented at the protocol level
defimpl String.Chars, for: MyApp.Money do
  @moduledoc false
  # ...
end

# Callback implementation — documented at the behaviour level
@doc false
def handle_info(:refresh, state) do
  # ...
end

# Helper used only inside the module
@doc false
def do_format(value), do: # ...

Do NOT use @doc false on genuinely public functions. If a function is exported and callers depend on it, document it. If it should not be called externally, make it private with defp.

Documentation vs Code Comments

Documentation (@moduledoc, @doc) Code Comments (#)
Audience Users of your API Developers reading source
Purpose Contract: what it does, what it returns Why a particular implementation choice was made
Rendered Yes, by ExDoc in HTML/epub No, visible only in source
Required All public modules and functions Only where code intent is non-obvious
@doc """
Validates that the given coupon code is active and has remaining uses.
"""
@spec validate_coupon(String.t()) :: {:ok, Coupon.t()} | {:error, :expired | :exhausted}
def validate_coupon(code) do
  # We query the read replica here to avoid adding load to the
  # primary during high-traffic discount events.
  Repo.replica().get_by(Coupon, code: code)
  |> check_expiry()
  |> check_remaining_uses()
end

The @doc tells the caller what validate_coupon/1 does and returns. The inline comment explains an implementation decision that would otherwise be surprising.

Completing documentation (gates)

Finish with these sequenced checks. Skip a step when it does not apply.

  1. Doctests added or changed? Run the project’s doctest verification (usually mix test for affected modules or the full suite). Pass: no doctest failures.
  2. Cross-references, backticks, or m: links added or edited? Run mix docs. Pass: the command completes; resolve ExDoc warnings about missing modules, callbacks, or bad links.
  3. New or changed public API? Pass: every exported def / defmacro has an intentional @doc or @doc false, and every public module has @moduledoc or @moduledoc false, consistent with your project’s policy.

When to Load References

Usage Guidance
This skill appears coherent and low-risk: it's a documentation style guide for Elixir with no installs or secret access. Before installing, verify the publisher/source if you require provenance, and review future updates for any added install steps or environment-variable requirements (those would materially change the risk). If you want stricter control, only enable the skill when actively working on Elixir docs.
Capability Analysis
Type: OpenClaw Skill Name: elixir-writing-docs Version: 1.2.1 The skill bundle provides comprehensive guidelines and reference materials for writing Elixir documentation using ExDoc, covering @moduledoc, @doc, doctests, and cross-references. While SKILL.md instructs the agent to run 'mix test' and 'mix docs' to verify documentation, these are standard development practices aligned with the skill's stated purpose and do not show signs of malicious intent or unauthorized execution.
Capability Tags
cryptocan-make-purchases
Capability Assessment
Purpose & Capability
The name and description match the SKILL.md and reference files: the content is focused on writing @moduledoc, @doc, @typedoc, doctests, and cross-references. There are no unrelated environment variables, binaries, or configuration paths requested that would be unnecessary for a documentation guide.
Instruction Scope
SKILL.md and the reference files provide static guidance and examples for documenting Elixir code. The instructions do not tell the agent to read system files, access credentials, call external endpoints, run arbitrary shell commands, or collect/transmit user data beyond using the guidance to edit .ex files.
Install Mechanism
There is no install specification and no code files that would be written or executed. As an instruction-only skill, it has the lowest install risk.
Credentials
The skill declares no required environment variables, credentials, or config paths. The SKILL.md does not reference any undeclared secrets or external service tokens.
Persistence & Privilege
always is false and the skill does not request persistent system presence or modify other skills or system-wide agent settings. Autonomous invocation is allowed by platform default but the skill's content does not grant it extra privileges.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install elixir-writing-docs
  3. After installation, invoke the skill by name or use /elixir-writing-docs
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.2.1
- Updated SKILL.md formatting/style for improved clarity and consistency. - No changes to technical content; guidance and examples remain the same. - No structural or feature additions—documentation wording and presentation only.
v1.2.0
elixir-writing-docs v1.2.0 - Major rewrite and expansion of documentation standards for Elixir codebases. - Introduces comprehensive guidelines for structuring `@moduledoc`, `@doc`, and `@typedoc` blocks, with clear examples. - Covers summary line requirements, metadata usage (`since`, `deprecated`), and when to use `@doc false` or `@moduledoc false`. - Details best practices for doctests, cross-references, and options documentation. - Defines distinction between user-facing docs and code comments. - Includes quick reference table to supporting guides for doctests, cross-references, and formatting.
Metadata
Slug elixir-writing-docs
Version 1.2.1
License MIT-0
All-time Installs 1
Active Installs 1
Total Versions 2
Frequently Asked Questions

What is Elixir Writing Docs?

Guides writing Elixir documentation with @moduledoc, @doc, @typedoc, doctests, cross-references, and metadata. Use when adding or improving documentation in... It is an AI Agent Skill for Claude Code / OpenClaw, with 191 downloads so far.

How do I install Elixir Writing Docs?

Run "/install elixir-writing-docs" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Elixir Writing Docs free?

Yes, Elixir Writing Docs is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does Elixir Writing Docs support?

Elixir Writing Docs is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Elixir Writing Docs?

It is built and maintained by Kevin Anderson (@anderskev); the current version is v1.2.1.

💬 Comments