Claude Skill

document

Use when asked to document Elixir code: add or fill in @moduledoc and @doc for modules and functions. Documents tested code only; may add a README section or ADR. Not for docs lookup or audits.

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download oliver-kriska-claude-elixir-phoenix-plugins_elixir-phoenix_skills_document-9767a82.zip · 6 KB
Part of oliver-kriska/claude-elixir-phoenix — 93 skills

Install

skills CLI npx skills add https://github.com/oliver-kriska/claude-elixir-phoenix/tree/main/plugins/elixir-phoenix/skills/document
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install oliver-kriska-claude-elixir-phoenix@llmmart
Git git clone https://github.com/oliver-kriska/claude-elixir-phoenix.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole oliver-kriska/claude-elixir-phoenix collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Document

Generate documentation for newly implemented features.

Usage

/phx:document .claude/plans/magic-link-auth/plan.md
/phx:document magic link authentication
/phx:document  # Auto-detect from recent plan

Iron Laws

  1. Never remove existing documentation — Existing docs may reflect design intent that isn't obvious from code alone; update rather than replace
  2. @moduledoc on every public module — Undocumented modules accumulate quickly and create onboarding friction for new team members
  3. ADRs capture the "why", not the "what" — Code shows what was built; ADRs explain why this approach was chosen over alternatives
  4. Match @doc to function's public API — Document parameters, return values, and edge cases; callers shouldn't need to read the implementation
  5. DO NOT add @doc to untested code — documentation implies a stable contract; document only after tests confirm the function behaves as described

What Gets Documented

Output Description
@moduledoc For new modules missing documentation
@doc For public functions without docs
README section For user-facing features
ADR For significant architectural decisions

Workflow

Step 0: Pre-check (avoid no-op runs)

Run git diff --name-only HEAD~5 | grep '\.ex$' | head -20 to check for new .ex files.

If no new .ex files were added (only modifications), skip the full audit and report: "No new modules — documentation coverage unchanged." A full audit of unchanged coverage produces nothing to add.

  1. Identify new modules from recent commits or plan file
  2. Check documentation coverage (@moduledoc, @doc)
  3. Generate missing docs using templates
  4. Add README section if user-facing feature
  5. Create ADR if architectural decision was made
  6. Write report to .claude/plans/{slug}/reviews/{feature}-docs.md

When to Generate ADRs

Trigger Create ADR
New external dependency Yes
New database table Maybe (if schema non-obvious)
New OTP process Yes (explain why process needed)
New context Maybe (if boundaries non-obvious)
New auth mechanism Yes
Performance optimization Yes

Integration with Workflow

/phx:plan → /phx:work → /phx:review
       ↓
/phx:document  ← YOU ARE HERE (optional, suggested after review passes)

References

  • ${CLAUDE_SKILL_DIR}/references/doc-templates.md — @moduledoc, @doc, README, ADR templates
  • ${CLAUDE_SKILL_DIR}/references/output-format.md — Documentation report format
  • ${CLAUDE_SKILL_DIR}/references/doc-best-practices.md — Elixir documentation best practices
  • ${CLAUDE_SKILL_DIR}/references/documentation-patterns.md — Detailed documentation patterns
Files (claude-elixir-phoenix)
  • references
    • doc-best-practices.md 600 B
      # Elixir Documentation Best Practices
      
      ## @moduledoc
      
      - First line: One sentence summary
      - Include `## Usage` with iex examples
      - Include `## Options` if configurable
      - Link to related modules with `See also`
      
      ## @doc
      
      - First line: What it does (imperative)
      - `## Parameters` with types
      - `## Returns` with tagged tuples
      - `## Examples` with iex
      
      ## Typespecs
      
      Always pair @doc with @spec:
      
      ```elixir
      @doc "Creates a magic token for the given user."
      @spec create_magic_token(User.t()) :: {:ok, MagicToken.t()} | {:error, Ecto.Changeset.t()}
      def create_magic_token(%User{} = user) do
        # ...
      end
      ```
      
    • doc-templates.md 1.1 KB
      # Documentation Templates
      
      ## @moduledoc Template
      
      ```elixir
      @moduledoc """
      {Brief description of module purpose}.
      
      ## Usage
      
          iex> MyApp.Module.function(arg)
          :result
      
      ## Options
      
        * `:option` - Description of option
      
      ## Examples
      
          # Example usage
          MyApp.Module.do_thing()
      
      """
      ```
      
      ## @doc Template
      
      ```elixir
      @doc """
      {Brief description}.
      
      ## Parameters
      
        * `param` - Description
      
      ## Returns
      
        * `{:ok, result}` - On success
        * `{:error, reason}` - On failure
      
      ## Examples
      
          iex> function(:arg)
          {:ok, :result}
      
      """
      ```
      
      ## README Section Template
      
      For features users interact with:
      
      ````markdown
      ## {Feature Name}
      
      {Brief description}
      
      ### Configuration
      
      ```elixir
      # config/config.exs
      config :my_app, :feature,
        option: value
      ```
      
      ### Usage
      
      {How to use the feature}
      ````
      
      ## ADR Template
      
      Create `docs/adr/{number}-{title}.md`:
      
      ```markdown
      # ADR-{n}: {Title}
      
      **Date**: {date}
      **Status**: Accepted
      **Context**: {Why this decision was needed}
      
      ## Decision
      
      {What was decided}
      
      ## Consequences
      
      ### Positive
      
      - {benefit}
      
      ### Negative
      
      - {tradeoff}
      
      ## Alternatives Considered
      
      ### {Alternative 1}
      
      - Rejected because: {reason}
      ```
      
    • documentation-patterns.md 6.9 KB
      # Documentation Patterns
      
      ## Contents
      
      - [@moduledoc Templates](#moduledoc-templates)
      - [@doc Templates](#doc-templates)
      - [ADR Template](#adr-template)
      - [README Section Template](#readme-section-template)
      
      ## @moduledoc Templates
      
      ### Context Module
      
      ```elixir
      defmodule MyApp.Accounts do
        @moduledoc """
        The Accounts context manages user registration, authentication, and profile management.
      
        This context is the public API for all user-related operations. Controllers and
        LiveViews should call functions here rather than accessing schemas directly.
      
        ## Functions
      
        ### Registration
      
          * `register_user/1` - Creates a new user account
          * `confirm_user/1` - Confirms email address
      
        ### Authentication
      
          * `authenticate_user/2` - Validates credentials
          * `create_session/1` - Creates a new session
      
        ## Examples
      
            iex> Accounts.register_user(%{email: "user@example.com", password: "secret123"})
            {:ok, %User{}}
      
            iex> Accounts.authenticate_user("user@example.com", "wrong")
            {:error, :invalid_credentials}
      
        """
      end
      ```
      
      ### Schema Module
      
      ```elixir
      defmodule MyApp.Accounts.User do
        @moduledoc """
        Schema representing a user account.
      
        ## Fields
      
          * `email` - User's email address (unique, required)
          * `password_hash` - Argon2 hashed password
          * `confirmed_at` - When email was confirmed (nil if unconfirmed)
          * `role` - User role: `:member` | `:admin`
      
        ## Changesets
      
          * `registration_changeset/2` - For new user registration
          * `password_changeset/2` - For password changes
          * `email_changeset/2` - For email changes
      
        ## Associations
      
          * `posts` - Has many posts
          * `comments` - Has many comments
      
        """
      end
      ```
      
      ### LiveView Module
      
      ```elixir
      defmodule MyAppWeb.UserRegistrationLive do
        @moduledoc """
        LiveView for user registration.
      
        ## Assigns
      
          * `form` - The registration form changeset
          * `trigger_submit` - Whether to trigger form submission
      
        ## Events
      
          * `"save"` - Submits registration form
          * `"validate"` - Validates form on change
      
        ## Example
      
            live "/users/register", UserRegistrationLive, :new
      
        """
      end
      ```
      
      ### GenServer Module
      
      ```elixir
      defmodule MyApp.RateLimiter do
        @moduledoc """
        GenServer that tracks request rates per IP address.
      
        ## Why a GenServer?
      
        This uses a GenServer (rather than ETS or Agent) because:
        - Needs periodic cleanup of expired entries (handle_info)
        - Coordinates with external rate limit service
        - Requires atomic check-and-increment operations
      
        ## State
      
        Map of IP addresses to request counts and timestamps:
      
            %{
              {192, 168, 1, 1} => %{count: 5, window_start: ~U[...]},
              ...
            }
      
        ## Configuration
      
            config :my_app, MyApp.RateLimiter,
              max_requests: 100,
              window_seconds: 60
      
        ## Usage
      
            case RateLimiter.check("192.168.1.1") do
              :ok -> proceed()
              {:error, :rate_limited} -> return_429()
            end
      
        """
      end
      ```
      
      ### Oban Worker
      
      ```elixir
      defmodule MyApp.Workers.SendEmailWorker do
        @moduledoc """
        Oban worker for sending emails asynchronously.
      
        ## Idempotency
      
        Uses `email_id` as idempotency key. Safe to retry - checks if email
        already sent before processing.
      
        ## Args
      
          * `"email_id"` - ID of the Email record to send
          * `"template"` - Email template name
      
        ## Queues
      
        Runs on `:mailers` queue with rate limiting.
      
        ## Example
      
            %{email_id: 123, template: "welcome"}
            |> SendEmailWorker.new()
            |> Oban.insert()
      
        """
      end
      ```
      
      ## @doc Templates
      
      ### Context Function
      
      ```elixir
      @doc """
      Creates a magic link token for passwordless authentication.
      
      Generates a secure random token, stores it in the database with an expiration
      time, and returns the token for inclusion in an email link.
      
      ## Parameters
      
        * `user` - The user to create a token for
        * `opts` - Options
          * `:expires_in` - Token lifetime in seconds (default: 86400)
      
      ## Returns
      
        * `{:ok, token}` - The magic link token string
        * `{:error, changeset}` - If token creation fails
      
      ## Examples
      
          iex> Auth.create_magic_token(user)
          {:ok, "abc123..."}
      
          iex> Auth.create_magic_token(user, expires_in: 3600)
          {:ok, "def456..."}
      
      """
      @spec create_magic_token(User.t(), keyword()) :: {:ok, String.t()} | {:error, Ecto.Changeset.t()}
      def create_magic_token(user, opts \\ [])
      ```
      
      ### Query Function
      
      ```elixir
      @doc """
      Lists users matching the given criteria.
      
      ## Parameters
      
        * `criteria` - Keyword list of filters
          * `:role` - Filter by role
          * `:confirmed` - Filter by confirmation status
          * `:search` - Search in email/name
        * `opts` - Pagination options
          * `:page` - Page number (default: 1)
          * `:per_page` - Items per page (default: 20)
      
      ## Returns
      
      A list of users (may be empty).
      
      ## Examples
      
          iex> Accounts.list_users(role: :admin)
          [%User{role: :admin}, ...]
      
          iex> Accounts.list_users(search: "john", page: 2)
          [%User{}, ...]
      
      """
      ```
      
      ### LiveView Event Handler
      
      ```elixir
      @doc """
      Handles the "save" event from the registration form.
      
      Attempts to register the user. On success, redirects to confirmation page.
      On failure, re-renders form with errors.
      
      ## Parameters
      
        * `params` - Form parameters with "user" key
        * `socket` - LiveView socket
      
      ## Returns
      
      Updated socket, either:
        * Redirected to confirmation page on success
        * Re-rendered with form errors on failure
      
      """
      def handle_event("save", %{"user" => params}, socket)
      ```
      
      ## ADR Template
      
      ```markdown
      # ADR-{number}: {Title}
      
      **Date**: YYYY-MM-DD
      **Status**: Proposed | Accepted | Deprecated | Superseded by ADR-X
      **Deciders**: {who made the decision}
      **Technical Story**: {link to issue/PR if applicable}
      
      ## Context and Problem Statement
      
      {Describe the context and problem in 2-3 sentences. What forces are at play?
      What decision needs to be made?}
      
      ## Decision Drivers
      
      * {driver 1, e.g., performance requirement}
      * {driver 2, e.g., team familiarity}
      * {driver 3, e.g., maintenance burden}
      
      ## Considered Options
      
      1. {Option 1}
      2. {Option 2}
      3. {Option 3}
      
      ## Decision Outcome
      
      Chosen option: **"{Option X}"**, because {justification}.
      
      ### Positive Consequences
      
      * {positive consequence 1}
      * {positive consequence 2}
      
      ### Negative Consequences
      
      * {negative consequence 1}
      * {mitigation for negative consequence}
      
      ## Pros and Cons of the Options
      
      ### {Option 1}
      
      {Description}
      
      * Good, because {argument a}
      * Good, because {argument b}
      * Bad, because {argument c}
      
      ### {Option 2}
      
      {Description}
      
      * Good, because {argument a}
      * Bad, because {argument b}
      * Bad, because {argument c}
      
      ## Links
      
      * {Link to related ADR}
      * {Link to relevant documentation}
      * {Link to discussion/issue}
      ```
      
      ## README Section Template
      
      ````markdown
      ## {Feature Name}
      
      {One paragraph description of what this feature does and why it exists.}
      
      ### Configuration
      
      ```elixir
      config :my_app, :feature_name,
        option_a: "value",
        option_b: 123
      ```
      
      ### Usage
      
      ```elixir
      MyApp.Feature.do_thing()
      ```
      
      ### Troubleshooting
      
      **Problem**: {Common issue}
      **Solution**: {How to fix}
      ````
      
    • output-format.md 803 B
      # Documentation Output Format
      
      Write documentation report to `.claude/plans/{slug}/reviews/{feature}-docs.md`:
      
      ```markdown
      # Documentation: {Feature}
      
      ## Generated Documentation
      
      ### @moduledoc Added
      
      | Module | Description |
      |--------|-------------|
      | `MyApp.Auth` | Authentication context |
      | `MyApp.Auth.MagicToken` | Magic token schema |
      
      ### @doc Added
      
      | Function | Module |
      |----------|--------|
      | `create_magic_token/1` | MyApp.Auth |
      | `verify_magic_token/1` | MyApp.Auth |
      
      ### README Updated
      
      - Added "Magic Link Authentication" section
      
      ### ADR Created
      
      - `docs/adr/003-magic-link-auth.md`
      
      ## Documentation Checklist
      
      - [x] All new modules have @moduledoc
      - [x] All public functions have @doc
      - [x] README updated for user-facing features
      - [x] ADR created for architectural decisions
      ```
      
  • SKILL.md 3 KB
    ---
    name: document
    description: "Use when asked to document Elixir code: add or fill in @moduledoc and @doc for modules and functions. Documents tested code only; may add a README section or ADR. Not for docs lookup or audits."
    effort: low
    argument-hint: "[plan-file OR feature-name]"
    ---
    
    # Document
    
    Generate documentation for newly implemented features.
    
    ## Usage
    
    ```
    /phx:document .claude/plans/magic-link-auth/plan.md
    /phx:document magic link authentication
    /phx:document  # Auto-detect from recent plan
    ```
    
    ## Iron Laws
    
    1. **Never remove existing documentation** — Existing docs may reflect design intent that isn't obvious from code alone; update rather than replace
    2. **@moduledoc on every public module** — Undocumented modules accumulate quickly and create onboarding friction for new team members
    3. **ADRs capture the "why", not the "what"** — Code shows what was built; ADRs explain why this approach was chosen over alternatives
    4. **Match @doc to function's public API** — Document parameters, return values, and edge cases; callers shouldn't need to read the implementation
    5. **DO NOT add @doc to untested code** — documentation implies a stable contract; document only after tests confirm the function behaves as described
    
    ## What Gets Documented
    
    | Output | Description |
    |--------|-------------|
    | `@moduledoc` | For new modules missing documentation |
    | `@doc` | For public functions without docs |
    | README section | For user-facing features |
    | ADR | For significant architectural decisions |
    
    ## Workflow
    
    ### Step 0: Pre-check (avoid no-op runs)
    
    Run `git diff --name-only HEAD~5 | grep '\.ex$' | head -20` to check for new `.ex` files.
    
    If no new `.ex` files were added (only modifications), skip the full
    audit and report: "No new modules — documentation coverage unchanged."
    A full audit of unchanged coverage produces nothing to add.
    
    1. **Identify** new modules from recent commits or plan file
    2. **Check** documentation coverage (`@moduledoc`, `@doc`)
    3. **Generate** missing docs using templates
    4. **Add** README section if user-facing feature
    5. **Create** ADR if architectural decision was made
    6. **Write** report to `.claude/plans/{slug}/reviews/{feature}-docs.md`
    
    ## When to Generate ADRs
    
    | Trigger | Create ADR |
    |---------|-----------|
    | New external dependency | Yes |
    | New database table | Maybe (if schema non-obvious) |
    | New OTP process | Yes (explain why process needed) |
    | New context | Maybe (if boundaries non-obvious) |
    | New auth mechanism | Yes |
    | Performance optimization | Yes |
    
    ## Integration with Workflow
    
    ```text
    /phx:plan → /phx:work → /phx:review
           ↓
    /phx:document  ← YOU ARE HERE (optional, suggested after review passes)
    ```
    
    ## References
    
    - `${CLAUDE_SKILL_DIR}/references/doc-templates.md` — @moduledoc, @doc, README, ADR templates
    - `${CLAUDE_SKILL_DIR}/references/output-format.md` — Documentation report format
    - `${CLAUDE_SKILL_DIR}/references/doc-best-practices.md` — Elixir documentation best practices
    - `${CLAUDE_SKILL_DIR}/references/documentation-patterns.md` — Detailed documentation patterns
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related