Initial commit
This commit is contained in:
15
.claude-plugin/plugin.json
Normal file
15
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "core",
|
||||||
|
"description": "Essential Elixir development support with hooks and automation",
|
||||||
|
"version": "1.2.2",
|
||||||
|
"author": {
|
||||||
|
"name": "Bradley Golden",
|
||||||
|
"url": "https://github.com/bradleygolden"
|
||||||
|
},
|
||||||
|
"skills": [
|
||||||
|
"./skills"
|
||||||
|
],
|
||||||
|
"hooks": [
|
||||||
|
"./hooks"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# core
|
||||||
|
|
||||||
|
Essential Elixir development support with hooks and automation
|
||||||
53
hooks/hooks.json
Normal file
53
hooks/hooks.json
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"hooks": {
|
||||||
|
"PostToolUse": [
|
||||||
|
{
|
||||||
|
"matcher": "Edit|Write|MultiEdit",
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/auto-format.sh",
|
||||||
|
"timeout": 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/compile-check.sh",
|
||||||
|
"timeout": 20
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matcher": "Read",
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/recommend-docs-on-read.sh"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"PreToolUse": [
|
||||||
|
{
|
||||||
|
"matcher": "Bash",
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/pre-commit-check.sh",
|
||||||
|
"timeout": 45
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"UserPromptSubmit": [
|
||||||
|
{
|
||||||
|
"matcher": ".*",
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/recommend-docs-lookup.sh"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
61
plugin.lock.json
Normal file
61
plugin.lock.json
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||||
|
"pluginId": "gh:bradleygolden/claude-marketplace-elixir:plugins/core",
|
||||||
|
"normalized": {
|
||||||
|
"repo": null,
|
||||||
|
"ref": "refs/tags/v20251128.0",
|
||||||
|
"commit": "b4ddf33811ea1d3bb8a65e22ebafd0f88d641698",
|
||||||
|
"treeHash": "57d924a1542767fa6b4f5b0528ba0c40dbcc2a8af681129a25e109ee00c79e83",
|
||||||
|
"generatedAt": "2025-11-28T10:14:21.944320Z",
|
||||||
|
"toolVersion": "publish_plugins.py@0.2.0"
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||||
|
"branch": "master",
|
||||||
|
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||||
|
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"name": "core",
|
||||||
|
"description": "Essential Elixir development support with hooks and automation",
|
||||||
|
"version": "1.2.2"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "README.md",
|
||||||
|
"sha256": "a6d4920c1a411d59014d2f965899c5bf362316f6837dd4e6c852c59c4ea05883"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "hooks/hooks.json",
|
||||||
|
"sha256": "dce89d1c71af6b825d017165c9e8c2a6ca99d891466b60b15bdca984d8e3eddd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": ".claude-plugin/plugin.json",
|
||||||
|
"sha256": "e65cc4c9eff4b0acfd843737ed74bff2df69797b42bd7e1a3a9144323ffe215c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/usage-rules/README.md",
|
||||||
|
"sha256": "13dfeaf6422fd6cb018f799ecef090d55b64d4bc9e36e05de0407b3fd64f4f34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/usage-rules/SKILL.md",
|
||||||
|
"sha256": "e9205b8dcc85df67e6104e8a423dae3c2976608a818e9a7c6c7d0b5a676c2b41"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/hex-docs-search/README.md",
|
||||||
|
"sha256": "466e1fd9da8fa9ff804a83bdf407b109d69d4800d1ffc4ae07adda1f4a772e90"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/hex-docs-search/SKILL.md",
|
||||||
|
"sha256": "c68bace1cf350be541a797f09debf1236334db27b94396f184fd1c7f421c58a1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dirSha256": "57d924a1542767fa6b4f5b0528ba0c40dbcc2a8af681129a25e109ee00c79e83"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"scannedAt": null,
|
||||||
|
"scannerVersion": null,
|
||||||
|
"flags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
155
skills/hex-docs-search/README.md
Normal file
155
skills/hex-docs-search/README.md
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
# Hex Docs Search Skill
|
||||||
|
|
||||||
|
A comprehensive skill for searching Elixir and Erlang package documentation using a cascading search strategy.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This skill helps Claude search for Hex package documentation intelligently by:
|
||||||
|
1. First checking local dependencies in `deps/`
|
||||||
|
2. Then checking previously fetched documentation and source in `.hex-docs/` and `.hex-packages/`
|
||||||
|
3. Automatically fetching missing documentation or source code when needed (with version prompting)
|
||||||
|
4. Searching the codebase for real usage examples
|
||||||
|
5. Querying the hex.pm API for official docs
|
||||||
|
6. Falling back to web search if needed
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
This skill is automatically available when the `core@elixir` plugin is installed. Claude will use it when appropriate, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "How do I use Phoenix.LiveView mount/3?"
|
||||||
|
User: "Show me Ecto.Query examples"
|
||||||
|
User: "What does Jason.decode!/1 do?"
|
||||||
|
User: "Research the Sobelow hex package"
|
||||||
|
User: "Learn about the Credo library"
|
||||||
|
User: "Understand how Ash Framework works"
|
||||||
|
```
|
||||||
|
|
||||||
|
## How it Works
|
||||||
|
|
||||||
|
### 1. Local Dependencies Search (deps/)
|
||||||
|
|
||||||
|
Uses Grep and Glob tools to search installed packages for BOTH code and docs:
|
||||||
|
- **Source code**: Finds module definitions, function implementations, and `@moduledoc`/`@doc` annotations
|
||||||
|
- **Generated docs**: Checks for HTML documentation in `deps/*/doc/` directories
|
||||||
|
- Provides full context from whichever source is most helpful
|
||||||
|
|
||||||
|
**Advantage**: Matches the exact version used in the project
|
||||||
|
|
||||||
|
### 2. Fetched Cache Search (.hex-docs/ and .hex-packages/)
|
||||||
|
|
||||||
|
Checks for previously fetched documentation and source code:
|
||||||
|
- **Documentation**: Searches `.hex-docs/docs/hexpm/<package>/<version>/` for HTML docs
|
||||||
|
- **Source code**: Searches `.hex-packages/<package>-<version>/` for unpacked source
|
||||||
|
- Uses same search patterns as deps/ directory
|
||||||
|
|
||||||
|
**Advantage**: Fast, offline-capable access to packages not in project dependencies
|
||||||
|
|
||||||
|
### 3. Progressive Fetch (NEW)
|
||||||
|
|
||||||
|
When packages aren't found locally, automatically fetches them:
|
||||||
|
- **Version detection**: Checks mix.lock, mix.exs, or hex.pm for version
|
||||||
|
- **User prompting**: Asks user to choose version when ambiguous (latest vs specific)
|
||||||
|
- **Documentation first**: Fetches HTML docs with `mix hex.docs fetch` to `.hex-docs/`
|
||||||
|
- **Source if needed**: Fetches source code with `mix hex.package fetch --unpack` to `.hex-packages/`
|
||||||
|
- **Cached for future**: All fetched content reusable in subsequent queries
|
||||||
|
|
||||||
|
**Advantage**: Builds a local knowledge base of documentation and source code over time
|
||||||
|
|
||||||
|
### 4. Codebase Usage Search
|
||||||
|
|
||||||
|
Searches the project's `lib/` and `test/` directories:
|
||||||
|
- Finds `alias` and `import` statements
|
||||||
|
- Locates function calls
|
||||||
|
- Shows real-world usage from your code
|
||||||
|
|
||||||
|
**Advantage**: Context-aware examples from your actual codebase
|
||||||
|
|
||||||
|
### 5. HexDocs Search API
|
||||||
|
|
||||||
|
Uses the HexDocs search API at `https://search.hexdocs.pm/`:
|
||||||
|
- Full-text search across documentation content
|
||||||
|
- Filters by package name and version
|
||||||
|
- Returns documentation excerpts with direct links
|
||||||
|
- Falls back to hex.pm API for package info
|
||||||
|
|
||||||
|
**Advantage**: Searches actual documentation content, not just package metadata
|
||||||
|
|
||||||
|
### 6. Web Search Fallback
|
||||||
|
|
||||||
|
Uses WebSearch with targeted queries:
|
||||||
|
- `site:hexdocs.pm <package> <module>` for specific docs
|
||||||
|
- General Elixir documentation search
|
||||||
|
|
||||||
|
**Advantage**: Finds community examples and guides
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Example 1: Looking up a commonly used dependency
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "How do I query with Ecto?"
|
||||||
|
|
||||||
|
Claude will:
|
||||||
|
1. Find deps/ecto/lib/ecto/query.ex
|
||||||
|
2. Search for "import Ecto.Query" in lib/
|
||||||
|
3. Show usage examples from the project
|
||||||
|
4. Read @moduledoc from the source
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 2: Unknown package with progressive fetch
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "What is the Timex library?"
|
||||||
|
|
||||||
|
Claude will:
|
||||||
|
1. Check deps/timex (not found)
|
||||||
|
2. Check .hex-docs/docs/hexpm/timex/ (not found)
|
||||||
|
3. Detect no version in project dependencies
|
||||||
|
4. Query hex.pm for latest version
|
||||||
|
5. Prompt: "Fetch latest (3.7.11) or specific version?"
|
||||||
|
6. User selects "Latest"
|
||||||
|
7. Fetch: HEX_HOME=.hex-docs mix hex.docs fetch timex 3.7.11
|
||||||
|
8. Search fetched HTML documentation
|
||||||
|
9. Present findings with link to cached docs
|
||||||
|
10. Suggest adding to .gitignore if not present
|
||||||
|
|
||||||
|
Future queries: Instant access to cached documentation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 3: Specific function lookup
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "How does Jason.decode!/2 work?"
|
||||||
|
|
||||||
|
Claude will:
|
||||||
|
1. Find deps/jason/lib/jason.ex
|
||||||
|
2. Grep for "def decode!"
|
||||||
|
3. Show the @doc and implementation
|
||||||
|
4. Find usage in tests/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- `curl` - For hex.pm API queries
|
||||||
|
- `jq` - For JSON parsing (recommended)
|
||||||
|
- `mix` - For fetching packages and documentation
|
||||||
|
- Internet access - For API, web search, and fetching packages/docs
|
||||||
|
|
||||||
|
## Recommended .gitignore Entries
|
||||||
|
|
||||||
|
Add these to your `.gitignore` to exclude fetched content:
|
||||||
|
|
||||||
|
```gitignore
|
||||||
|
# Fetched Hex documentation and packages
|
||||||
|
/.hex-docs/
|
||||||
|
/.hex-packages/
|
||||||
|
```
|
||||||
|
|
||||||
|
These directories can be large and are easily re-fetched on demand.
|
||||||
|
|
||||||
|
## Integration
|
||||||
|
|
||||||
|
This skill is bundled with the `core@elixir` plugin and doesn't require separate installation.
|
||||||
|
|
||||||
|
See [SKILL.md](SKILL.md) for the complete skill prompt and instructions.
|
||||||
457
skills/hex-docs-search/SKILL.md
Normal file
457
skills/hex-docs-search/SKILL.md
Normal file
@@ -0,0 +1,457 @@
|
|||||||
|
---
|
||||||
|
name: hex-docs-search
|
||||||
|
description: Research Hex packages (Sobelow, Phoenix, Ecto, Credo, Ash, etc). Use when investigating packages, understanding integration patterns, or finding module/function docs and usage examples. Automatically fetches missing documentation and source code locally.
|
||||||
|
allowed-tools: Read, Grep, Glob, Bash, WebSearch, AskUserQuestion
|
||||||
|
---
|
||||||
|
|
||||||
|
# Hex Documentation Search
|
||||||
|
|
||||||
|
Comprehensive search for Elixir and Erlang package documentation, following a cascading strategy to find the most relevant and context-aware information.
|
||||||
|
|
||||||
|
## When to use this skill
|
||||||
|
|
||||||
|
Use this skill when you need to:
|
||||||
|
- Look up documentation for a Hex package or dependency
|
||||||
|
- Find function signatures, module documentation, or type specs
|
||||||
|
- See usage examples of a library or module
|
||||||
|
- Understand how a dependency is used in the current project
|
||||||
|
- Search for Elixir/Erlang standard library documentation
|
||||||
|
|
||||||
|
## Search strategy
|
||||||
|
|
||||||
|
This skill implements a **cascading search** that prioritizes local and contextual information:
|
||||||
|
|
||||||
|
1. **Local dependencies** - Search installed packages in `deps/` directory (both source code AND generated docs)
|
||||||
|
2. **Fetched cache** - Check previously fetched documentation and source code in `.hex-docs/` and `.hex-packages/`
|
||||||
|
3. **Progressive fetch** - Automatically fetch missing documentation or source code locally when needed
|
||||||
|
4. **Codebase usage** - Find how packages are used in the current project
|
||||||
|
5. **HexDocs API** - Search official documentation on hexdocs.pm (fallback)
|
||||||
|
6. **Web search** - Fallback to general web search (last resort)
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
### Step 1: Identify the search target
|
||||||
|
|
||||||
|
Extract the package name and optionally the module or function name from the user's question.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
- "How do I use Phoenix.LiveView?" → Package: `phoenix_live_view`, Module: `Phoenix.LiveView`
|
||||||
|
- "Show me Ecto query examples" → Package: `ecto`, Module: `Ecto.Query`
|
||||||
|
- "What does Jason.decode!/1 do?" → Package: `jason`, Module: `Jason`, Function: `decode!`
|
||||||
|
|
||||||
|
### Step 2: Search local dependencies
|
||||||
|
|
||||||
|
Use the **Glob** and **Grep** tools to search the `deps/` directory for BOTH code and documentation:
|
||||||
|
|
||||||
|
1. **Find the package directory**:
|
||||||
|
```
|
||||||
|
Use Glob: pattern="deps/<package_name>/**/*.ex"
|
||||||
|
```
|
||||||
|
|
||||||
|
If no results, the package isn't installed locally. Skip to Step 4.
|
||||||
|
|
||||||
|
2. **Search for module definition in source code**:
|
||||||
|
```
|
||||||
|
Use Grep: pattern="defmodule <ModuleName>", path="deps/<package_name>/lib"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Search for function definition in source code** (if looking for specific function):
|
||||||
|
```
|
||||||
|
Use Grep: pattern="def <function_name>", path="deps/<package_name>/lib", output_mode="content", -A=5
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Find documentation in source code** (@moduledoc/@doc annotations):
|
||||||
|
```
|
||||||
|
Use Grep: pattern="@moduledoc|@doc", path="deps/<package_name>/lib", output_mode="content", -A=10
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Check for generated HTML documentation** (if available):
|
||||||
|
```
|
||||||
|
Use Glob: pattern="deps/<package_name>/doc/**/*.html"
|
||||||
|
```
|
||||||
|
|
||||||
|
If HTML docs exist, search them for relevant content:
|
||||||
|
```
|
||||||
|
Use Grep: pattern="<ModuleName>|<function_name>", path="deps/<package_name>/doc"
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **Read the relevant files** using the Read tool to get full context from either source or HTML docs.
|
||||||
|
|
||||||
|
### Step 3: Check fetched cache and fetch if needed
|
||||||
|
|
||||||
|
If the package wasn't found in `deps/`, check for previously fetched documentation or source code, or fetch it now.
|
||||||
|
|
||||||
|
#### 3.1: Check fetched documentation cache
|
||||||
|
|
||||||
|
Use the **Glob** tool to check if documentation was previously fetched:
|
||||||
|
|
||||||
|
```
|
||||||
|
Use Glob: pattern=".hex-docs/docs/hexpm/<package_name>/*/*.html"
|
||||||
|
```
|
||||||
|
|
||||||
|
If found, search the fetched documentation using the same patterns as Step 2 (sections 5 and 6).
|
||||||
|
|
||||||
|
#### 3.2: Check fetched source code cache
|
||||||
|
|
||||||
|
Use the **Glob** tool to check if source code was previously fetched:
|
||||||
|
|
||||||
|
```
|
||||||
|
Use Glob: pattern=".hex-packages/<package_name>-*/**/*.ex"
|
||||||
|
```
|
||||||
|
|
||||||
|
If found, search the fetched source using the same patterns as Step 2 (sections 2-4).
|
||||||
|
|
||||||
|
#### 3.3: Determine version to fetch
|
||||||
|
|
||||||
|
If no cached docs or source found, determine which version to fetch:
|
||||||
|
|
||||||
|
1. **Check mix.lock** for locked version:
|
||||||
|
```
|
||||||
|
Use Bash: grep '"<package_name>"' mix.lock | grep -oE '[0-9]+\.[0-9]+\.[0-9]+'
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check mix.exs** for version constraint:
|
||||||
|
```
|
||||||
|
Use Bash: grep -E '\{:<package_name>' mix.exs | grep -oE '[0-9]+\.[0-9]+\.[0-9]+'
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Get latest version from hex.pm**:
|
||||||
|
```
|
||||||
|
Use Bash: curl -s "https://hex.pm/api/packages/<package_name>" | jq -r '.releases[0].version'
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **If version ambiguous**, use **AskUserQuestion** to prompt:
|
||||||
|
```
|
||||||
|
Question: "Package '<package_name>' not found locally. Which version would you like to fetch?"
|
||||||
|
Options:
|
||||||
|
- "Latest (X.Y.Z)" - Fetch most recent release
|
||||||
|
- "Project version (X.Y.Z)" - Use version from mix.exs/mix.lock (if available)
|
||||||
|
- "Specific version" - User provides custom version in "Other" field
|
||||||
|
- "Skip fetching" - Continue to HexDocs API search without fetching
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.4: Progressive fetch (documentation first)
|
||||||
|
|
||||||
|
Once version is determined, fetch documentation to project-local cache:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Use custom HEX_HOME to store in project directory
|
||||||
|
HEX_HOME=.hex-docs mix hex.docs fetch <package_name> <version>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Storage location**: `.hex-docs/docs/hexpm/<package_name>/<version>/`
|
||||||
|
|
||||||
|
If successful:
|
||||||
|
- Search the fetched HTML documentation using patterns from Step 2 (sections 5-6)
|
||||||
|
- Read relevant files with the Read tool
|
||||||
|
|
||||||
|
If **documentation fetch fails** (package has no docs) or **docs lack sufficient detail**:
|
||||||
|
- Proceed to Step 3.5 to fetch source code
|
||||||
|
|
||||||
|
#### 3.5: Fetch source code if needed
|
||||||
|
|
||||||
|
If documentation is insufficient or unavailable, fetch package source code:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Fetch and unpack to project-local directory
|
||||||
|
mix hex.package fetch <package_name> <version> --unpack --output .hex-packages/<package_name>-<version>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Storage location**: `.hex-packages/<package_name>-<version>/`
|
||||||
|
|
||||||
|
If successful:
|
||||||
|
- Search the source code using patterns from Step 2 (sections 2-4)
|
||||||
|
- Read source files with the Read tool
|
||||||
|
- Examine @moduledoc and @doc annotations
|
||||||
|
|
||||||
|
If **source fetch fails**:
|
||||||
|
- Continue to Step 5 (HexDocs API search) as fallback
|
||||||
|
|
||||||
|
#### 3.6: Git ignore recommendation
|
||||||
|
|
||||||
|
Inform the user that fetched content should be git-ignored. Suggest adding to `.gitignore`:
|
||||||
|
|
||||||
|
```gitignore
|
||||||
|
# Fetched Hex documentation and packages
|
||||||
|
/.hex-docs/
|
||||||
|
/.hex-packages/
|
||||||
|
```
|
||||||
|
|
||||||
|
This only needs to be mentioned once per session, and only if fetching actually occurred.
|
||||||
|
|
||||||
|
### Step 4: Search codebase usage
|
||||||
|
|
||||||
|
Use the **Grep** tool to find usage patterns in the current project:
|
||||||
|
|
||||||
|
1. **Find imports and aliases**:
|
||||||
|
```
|
||||||
|
Use Grep: pattern="alias <ModuleName>|import <ModuleName>", path="lib", output_mode="content", -n=true
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Find function calls**:
|
||||||
|
```
|
||||||
|
Use Grep: pattern="<ModuleName>\.", path="lib", output_mode="content", -A=3
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Search test files for examples**:
|
||||||
|
```
|
||||||
|
Use Grep: pattern="<ModuleName>", path="test", output_mode="content", -A=5
|
||||||
|
```
|
||||||
|
|
||||||
|
This provides **real-world usage examples** from the current project, which is often the most helpful context.
|
||||||
|
|
||||||
|
### Step 5: Search HexDocs Search API
|
||||||
|
|
||||||
|
If local search doesn't provide sufficient information, use the **Bash** tool to search the HexDocs search API.
|
||||||
|
|
||||||
|
**Full-text search across documentation:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Search across all packages
|
||||||
|
curl -s "https://search.hexdocs.pm/?q=<query>&query_by=doc,title" | jq -r '.found, .hits[0:5][] | .document | "\(.package) - \(.title)\n\(.doc)\n---"'
|
||||||
|
|
||||||
|
# Search within a specific package (get version first)
|
||||||
|
VERSION=$(curl -s "https://hex.pm/api/packages/<package_name>" | jq -r '.releases[0].version')
|
||||||
|
curl -s "https://search.hexdocs.pm/?q=<query>&query_by=doc,title&filter_by=package:=[<package>-$VERSION]" | jq -r '.hits[] | .document | "\(.title)\n\(.doc)\nURL: https://hexdocs.pm\(.url)\n---"'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Search for "mount" in phoenix_live_view
|
||||||
|
VERSION=$(curl -s "https://hex.pm/api/packages/phoenix_live_view" | jq -r '.releases[0].version')
|
||||||
|
curl -s "https://search.hexdocs.pm/?q=mount&query_by=doc,title&filter_by=package:=[phoenix_live_view-$VERSION]" | jq -r '.hits[0:3][] | .document | "\(.title)\n\(.doc)\n---"'
|
||||||
|
|
||||||
|
# General search for Ecto.Query
|
||||||
|
curl -s "https://search.hexdocs.pm/?q=Ecto.Query&query_by=doc,title" | jq -r '.hits[0:5][] | .document | "\(.package) - \(.title)\n\(.doc)\n"'
|
||||||
|
```
|
||||||
|
|
||||||
|
**API Response structure:**
|
||||||
|
- `found`: Total number of results
|
||||||
|
- `hits[]`: Array of results with:
|
||||||
|
- `document.package`: Package name
|
||||||
|
- `document.ref`: Version
|
||||||
|
- `document.title`: Function/module name
|
||||||
|
- `document.doc`: Documentation text
|
||||||
|
- `document.url`: Path to docs (append to https://hexdocs.pm)
|
||||||
|
|
||||||
|
**Requirements:** curl and jq (available on Linux/Mac, use Git Bash or WSL on Windows)
|
||||||
|
|
||||||
|
### Step 6: Web search fallback
|
||||||
|
|
||||||
|
If the above steps don't provide sufficient information, use the **WebSearch** tool:
|
||||||
|
|
||||||
|
First try searching hexdocs.pm specifically:
|
||||||
|
```
|
||||||
|
Use WebSearch: query="site:hexdocs.pm <package_name> <module_or_function>"
|
||||||
|
```
|
||||||
|
|
||||||
|
If that doesn't help, do a general search:
|
||||||
|
```
|
||||||
|
Use WebSearch: query="elixir <package_name> <module_or_function> documentation examples"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output format
|
||||||
|
|
||||||
|
When presenting results, organize them as follows:
|
||||||
|
|
||||||
|
### If found locally:
|
||||||
|
|
||||||
|
```
|
||||||
|
Found <package_name> in local dependencies:
|
||||||
|
|
||||||
|
**Location**: deps/<package_name>
|
||||||
|
**Version**: <version from mix.lock>
|
||||||
|
|
||||||
|
**Documentation**:
|
||||||
|
<relevant documentation or code snippets>
|
||||||
|
|
||||||
|
**Usage in this project**:
|
||||||
|
<usage examples from codebase>
|
||||||
|
```
|
||||||
|
|
||||||
|
### If found on HexDocs:
|
||||||
|
|
||||||
|
```
|
||||||
|
Found <package_name> on HexDocs:
|
||||||
|
|
||||||
|
**Package**: <package_name>
|
||||||
|
**Latest version**: <version>
|
||||||
|
**Documentation**: https://hexdocs.pm/<package_name>/<version>/<Module>.html
|
||||||
|
|
||||||
|
<summary of key information>
|
||||||
|
```
|
||||||
|
|
||||||
|
### If using web search:
|
||||||
|
|
||||||
|
```
|
||||||
|
Searching web for <package_name> documentation:
|
||||||
|
|
||||||
|
<summary of web search results>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Example 1: Finding Phoenix.LiveView documentation
|
||||||
|
|
||||||
|
**User asks**: "How do I use Phoenix.LiveView mount/3?"
|
||||||
|
|
||||||
|
**Search process**:
|
||||||
|
1. Check `deps/phoenix_live_view/` exists
|
||||||
|
2. Search for `def mount` in `deps/phoenix_live_view/lib/` (source code)
|
||||||
|
3. Read the `@doc` annotation for `mount/3` from source
|
||||||
|
4. Check for HTML docs in `deps/phoenix_live_view/doc/` and read if available
|
||||||
|
5. Search project for `mount` implementations in `lib/*/live/*.ex` (usage examples)
|
||||||
|
6. Show documentation and examples from both deps and codebase
|
||||||
|
|
||||||
|
### Example 2: Looking up Ecto.Query
|
||||||
|
|
||||||
|
**User asks**: "Show me Ecto.Query examples"
|
||||||
|
|
||||||
|
**Search process**:
|
||||||
|
1. Check `deps/ecto/` for source code
|
||||||
|
2. Search project for `import Ecto.Query`
|
||||||
|
3. Find query examples in `lib/*/queries/*.ex` or `lib/*_context.ex`
|
||||||
|
4. If needed, search HexDocs API:
|
||||||
|
```bash
|
||||||
|
curl -s "https://search.hexdocs.pm/?q=Ecto.Query&query_by=doc,title" | jq '.hits[0:3]'
|
||||||
|
```
|
||||||
|
5. Show local examples first, then external docs
|
||||||
|
|
||||||
|
### Example 3: Unknown package with progressive fetch
|
||||||
|
|
||||||
|
**User asks**: "How do I use the Timex library?"
|
||||||
|
|
||||||
|
**Search process**:
|
||||||
|
1. Check `deps/timex/` (not found)
|
||||||
|
2. Check `.hex-docs/docs/hexpm/timex/` (not found)
|
||||||
|
3. Check `.hex-packages/timex-*/` (not found)
|
||||||
|
4. Check mix.exs/mix.lock (not in project dependencies)
|
||||||
|
5. Get latest version from hex.pm:
|
||||||
|
```bash
|
||||||
|
curl -s "https://hex.pm/api/packages/timex" | jq -r '.releases[0].version'
|
||||||
|
# Returns: 3.7.11
|
||||||
|
```
|
||||||
|
6. Prompt user: "Package 'timex' not found locally. Fetch latest (3.7.11)?"
|
||||||
|
7. User confirms: "Latest"
|
||||||
|
8. Fetch documentation:
|
||||||
|
```bash
|
||||||
|
HEX_HOME=.hex-docs mix hex.docs fetch timex 3.7.11
|
||||||
|
# Stores in: .hex-docs/docs/hexpm/timex/3.7.11/
|
||||||
|
```
|
||||||
|
9. Search fetched HTML documentation
|
||||||
|
10. If docs sufficient, present findings
|
||||||
|
11. If docs lack detail, offer to fetch source:
|
||||||
|
```bash
|
||||||
|
mix hex.package fetch timex 3.7.11 --unpack --output .hex-packages/timex-3.7.11
|
||||||
|
```
|
||||||
|
12. Search source code for implementation details
|
||||||
|
13. Suggest adding to .gitignore if not already present
|
||||||
|
14. Offer to add it to mix.exs if user wants to use it
|
||||||
|
|
||||||
|
**Future queries**: Documentation and source cached locally for instant offline access
|
||||||
|
|
||||||
|
### Example 4: Cached documentation (offline-capable)
|
||||||
|
|
||||||
|
**User asks**: "Show me Phoenix.LiveView.mount/3 again"
|
||||||
|
|
||||||
|
**Search process**:
|
||||||
|
1. Check `deps/phoenix_live_view/` (not found)
|
||||||
|
2. Check `.hex-docs/docs/hexpm/phoenix_live_view/` (found version 0.20.0!)
|
||||||
|
3. **No fetch needed** - use cached documentation
|
||||||
|
4. Search cached HTML: `.hex-docs/docs/hexpm/phoenix_live_view/0.20.0/Phoenix.LiveView.html`
|
||||||
|
5. Present documentation instantly
|
||||||
|
|
||||||
|
**Result**: Fast, offline search without network requests. Works even when disconnected.
|
||||||
|
|
||||||
|
### Example 5: Progressive fetch (docs → source)
|
||||||
|
|
||||||
|
**User asks**: "Show me the implementation of Jason.decode!/2"
|
||||||
|
|
||||||
|
**Search process**:
|
||||||
|
1. Check `deps/jason/` (not found)
|
||||||
|
2. Check `.hex-docs/docs/hexpm/jason/` (not found)
|
||||||
|
3. Check project version in mix.exs: `{:jason, "~> 1.4"}`
|
||||||
|
4. Resolve to latest 1.4.x from hex.pm: 1.4.4
|
||||||
|
5. Fetch docs:
|
||||||
|
```bash
|
||||||
|
HEX_HOME=.hex-docs mix hex.docs fetch jason 1.4.4
|
||||||
|
```
|
||||||
|
6. Search docs: Find signature but not implementation details
|
||||||
|
7. Offer: "Documentation shows the signature. Fetch source code for implementation?"
|
||||||
|
8. User confirms
|
||||||
|
9. Fetch source:
|
||||||
|
```bash
|
||||||
|
mix hex.package fetch jason 1.4.4 --unpack --output .hex-packages/jason-1.4.4
|
||||||
|
```
|
||||||
|
10. Search source: `.hex-packages/jason-1.4.4/lib/jason.ex`
|
||||||
|
11. Present implementation with line numbers
|
||||||
|
|
||||||
|
**Result**: Both docs and source cached for comprehensive future queries
|
||||||
|
|
||||||
|
## Tool usage summary
|
||||||
|
|
||||||
|
Use Claude's built-in tools in this order:
|
||||||
|
|
||||||
|
1. **Glob** - Find package files in deps/, .hex-docs/, and .hex-packages/
|
||||||
|
2. **Grep** - Search for modules, functions, and documentation in deps/, fetched cache, and project code
|
||||||
|
3. **Read** - Read full files for detailed documentation
|
||||||
|
4. **Bash** - Fetch packages/docs with mix hex commands; Query HexDocs Search API with curl + jq
|
||||||
|
5. **AskUserQuestion** - Prompt for version when ambiguous
|
||||||
|
6. **WebSearch** - Fallback search for hexdocs.pm or general web
|
||||||
|
|
||||||
|
**Requirements:** curl and jq (Linux/Mac native, use Git Bash or WSL on Windows)
|
||||||
|
|
||||||
|
## Best practices
|
||||||
|
|
||||||
|
1. **Start local**: Always check local dependencies first - they match the version used in the project
|
||||||
|
2. **Check cache before fetch**: Look for previously fetched docs/source in `.hex-docs/` and `.hex-packages/` before fetching
|
||||||
|
3. **Progressive fetch**: Try documentation first (lighter, faster), then source if needed
|
||||||
|
4. **Prompt for clarity**: Always prompt for version when ambiguous - don't assume latest is desired
|
||||||
|
5. **Show usage**: Real code examples from the current project are more valuable than generic documentation
|
||||||
|
6. **Version awareness**: Note which version is installed locally vs latest on hex.pm vs fetched
|
||||||
|
7. **Progressive disclosure**: Start with a summary, offer to dive deeper if needed
|
||||||
|
8. **Link to source**: Provide file paths (with line numbers) so users can explore further
|
||||||
|
9. **Git ignore reminder**: Mention .gitignore addition once per session when fetching occurs
|
||||||
|
10. **Offline capability**: Once fetched, documentation and source available without network access
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Package not found in deps/
|
||||||
|
|
||||||
|
- Check `.hex-docs/` and `.hex-packages/` for previously fetched content
|
||||||
|
- If not cached, determine version and offer to fetch
|
||||||
|
- Check if it's in mix.exs dependencies (for version resolution)
|
||||||
|
- Suggest running `mix deps.get` if it should be a project dependency
|
||||||
|
- Search hex.pm to verify the package exists
|
||||||
|
|
||||||
|
### Fetch failures
|
||||||
|
|
||||||
|
**Documentation fetch fails**:
|
||||||
|
- Package may not have published docs (some packages only have source)
|
||||||
|
- Offer to fetch source code instead
|
||||||
|
- Fall back to HexDocs API search
|
||||||
|
|
||||||
|
**Source fetch fails**:
|
||||||
|
- Verify package name spelling
|
||||||
|
- Check network connectivity
|
||||||
|
- Fall back to HexDocs API search
|
||||||
|
|
||||||
|
### Cache location issues
|
||||||
|
|
||||||
|
**Fetched content not found on repeat queries**:
|
||||||
|
- Verify `.hex-docs/` and `.hex-packages/` directories exist
|
||||||
|
- Check that fetch commands completed successfully
|
||||||
|
- May need to re-fetch if directories were deleted
|
||||||
|
|
||||||
|
### No documentation in deps/
|
||||||
|
|
||||||
|
- Some packages don't include @doc annotations
|
||||||
|
- Fall back to hexdocs.pm search
|
||||||
|
- Read the source code directly and explain it
|
||||||
|
|
||||||
|
### HexDocs API rate limiting
|
||||||
|
|
||||||
|
- If the API is rate limited, fall back to web search
|
||||||
|
- Cache results when possible
|
||||||
|
- Use web search with `site:hexdocs.pm` filter
|
||||||
249
skills/usage-rules/README.md
Normal file
249
skills/usage-rules/README.md
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
# Usage Rules Search Skill
|
||||||
|
|
||||||
|
A comprehensive skill for searching Elixir and Erlang package usage rules and best practices using a cascading strategy.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This skill helps Claude search for package usage rules intelligently by:
|
||||||
|
1. **Local dependencies** - Searches installed packages in `deps/` directory
|
||||||
|
2. **Fetched cache** - Checks previously fetched usage rules in `.usage-rules/`
|
||||||
|
3. **Progressive fetch** - Automatically fetches missing usage rules when needed
|
||||||
|
4. **Context-aware extraction** - Extracts relevant sections based on coding context
|
||||||
|
5. **Fallback guidance** - Provides alternatives when rules unavailable
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
This skill is automatically available when the `core@elixir` plugin is installed. Claude will use it when appropriate, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "What are Ash best practices for querying?"
|
||||||
|
User: "Show me error handling patterns in Phoenix"
|
||||||
|
User: "How should I structure Ecto schemas?"
|
||||||
|
User: "What are common mistakes with LiveView?"
|
||||||
|
User: "Best practices for Ash relationships"
|
||||||
|
```
|
||||||
|
|
||||||
|
## How it Works
|
||||||
|
|
||||||
|
### 1. Local Dependencies Search (deps/)
|
||||||
|
|
||||||
|
Searches installed packages for `usage-rules.md` files:
|
||||||
|
- Finds usage rules matching your project's version
|
||||||
|
- Searches for relevant sections based on context
|
||||||
|
- Extracts code examples with good/bad patterns
|
||||||
|
|
||||||
|
**Advantage**: Matches the exact version used in the project
|
||||||
|
|
||||||
|
### 2. Fetched Cache Search (.usage-rules/)
|
||||||
|
|
||||||
|
Checks for previously fetched usage rules:
|
||||||
|
- Searches `.usage-rules/<package>-<version>/usage-rules.md`
|
||||||
|
- Includes sub-rules if package provides them
|
||||||
|
- Uses same search patterns as deps/
|
||||||
|
|
||||||
|
**Advantage**: Fast, offline-capable access to packages not in project dependencies
|
||||||
|
|
||||||
|
### 3. Progressive Fetch
|
||||||
|
|
||||||
|
When usage rules aren't found locally, automatically fetches them:
|
||||||
|
- **Version detection**: Checks mix.lock, mix.exs, or hex.pm for version
|
||||||
|
- **User prompting**: Asks user to choose version when ambiguous (latest vs specific)
|
||||||
|
- **Package fetch**: Downloads package with `mix hex.package fetch`
|
||||||
|
- **Extraction**: Copies usage-rules.md to `.usage-rules/<package>-<version>/`
|
||||||
|
- **Cached for future**: All fetched rules reusable in subsequent queries
|
||||||
|
|
||||||
|
**Advantage**: Builds a local knowledge base of usage rules over time
|
||||||
|
|
||||||
|
### 4. Context-Aware Extraction
|
||||||
|
|
||||||
|
Extracts relevant sections based on what you're working on:
|
||||||
|
- **Querying** → "## Querying Data" section
|
||||||
|
- **Error handling** → "## Error Handling" section
|
||||||
|
- **Actions** → "## Actions" section
|
||||||
|
- **Relationships** → "## Relationships" section
|
||||||
|
- **Testing** → "## Testing" section
|
||||||
|
|
||||||
|
**Advantage**: Focused guidance without overwhelming context
|
||||||
|
|
||||||
|
### 5. Fallback Guidance
|
||||||
|
|
||||||
|
When package doesn't provide usage rules:
|
||||||
|
- Notes that package hasn't adopted convention
|
||||||
|
- Suggests using hex-docs-search for API documentation
|
||||||
|
- Recommends checking package README or guides
|
||||||
|
- Lists packages that currently have usage rules
|
||||||
|
|
||||||
|
**Advantage**: Graceful handling of unavailable rules
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Example 1: Looking up Ash querying best practices
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "What are Ash best practices for querying?"
|
||||||
|
|
||||||
|
Claude will:
|
||||||
|
1. Find deps/ash/usage-rules.md or .usage-rules/ash-*/usage-rules.md
|
||||||
|
2. Extract "## Querying Data" section
|
||||||
|
3. Show code examples with GOOD/BAD patterns
|
||||||
|
4. Provide file path for full rules
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 2: Unknown package with progressive fetch
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "What are Spark DSL best practices?"
|
||||||
|
|
||||||
|
Claude will:
|
||||||
|
1. Check deps/spark/usage-rules.md (not found)
|
||||||
|
2. Check .usage-rules/spark-*/usage-rules.md (not found)
|
||||||
|
3. Detect version from mix.exs or query hex.pm
|
||||||
|
4. Prompt: "Fetch Spark 2.2.24 usage rules?"
|
||||||
|
5. User confirms: "Latest"
|
||||||
|
6. Fetch: mix hex.package fetch spark 2.2.24 --unpack
|
||||||
|
7. Extract: .usage-rules/spark-2.2.24/usage-rules.md
|
||||||
|
8. Present usage rules with relevant sections
|
||||||
|
9. Suggest adding to .gitignore
|
||||||
|
|
||||||
|
Future queries: Instant access to cached rules
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 3: Cached rules (offline access)
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "Show me Ash relationship best practices again"
|
||||||
|
|
||||||
|
Claude will:
|
||||||
|
1. Check deps/ash/usage-rules.md (not found)
|
||||||
|
2. Check .usage-rules/ash-*/usage-rules.md (found version 3.5.20!)
|
||||||
|
3. **No fetch needed** - use cached rules
|
||||||
|
4. Extract "## Relationships" section
|
||||||
|
5. Present instantly
|
||||||
|
|
||||||
|
Result: Fast, offline search without network requests
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 4: Package without usage rules
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "Phoenix LiveView best practices?"
|
||||||
|
|
||||||
|
Claude will:
|
||||||
|
1. Check for usage rules (not found)
|
||||||
|
2. Note that LiveView doesn't provide usage-rules.md yet
|
||||||
|
3. Suggest alternatives:
|
||||||
|
- Use hex-docs-search for API documentation
|
||||||
|
- Check Phoenix LiveView guides
|
||||||
|
- Search web for community practices
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 5: Context-aware extraction
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "Common mistakes with Ash actions?"
|
||||||
|
|
||||||
|
Claude will:
|
||||||
|
1. Find Ash usage rules
|
||||||
|
2. Identify context: "actions" + "mistakes"
|
||||||
|
3. Extract "## Actions" section
|
||||||
|
4. Search for keywords: "mistake", "avoid", "bad", "wrong"
|
||||||
|
5. Present consolidated best practices with patterns to avoid
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- `curl` - For hex.pm API queries
|
||||||
|
- `jq` - For JSON parsing
|
||||||
|
- `mix` - For fetching packages
|
||||||
|
|
||||||
|
These are standard on Linux/Mac, use Git Bash or WSL on Windows.
|
||||||
|
|
||||||
|
## Recommended .gitignore Entries
|
||||||
|
|
||||||
|
Add these to your `.gitignore` to exclude fetched usage rules:
|
||||||
|
|
||||||
|
```gitignore
|
||||||
|
# Fetched usage rules
|
||||||
|
/.usage-rules/
|
||||||
|
```
|
||||||
|
|
||||||
|
These directories can be large and are easily re-fetched on demand.
|
||||||
|
|
||||||
|
## Integration with hex-docs-search
|
||||||
|
|
||||||
|
This skill focuses on **coding conventions and best practices**. For **API documentation** (function signatures, parameters, return values), use the **hex-docs-search** skill.
|
||||||
|
|
||||||
|
**Comprehensive guidance**: Agents can invoke both skills to provide complete "how to use it correctly" guidance:
|
||||||
|
- **usage-rules**: Conventions, patterns, good/bad examples
|
||||||
|
- **hex-docs-search**: API documentation, function signatures
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
```
|
||||||
|
User: "Help me implement Ash queries properly"
|
||||||
|
|
||||||
|
Agent combines both:
|
||||||
|
1. usage-rules: Get Ash querying conventions (use code interfaces, avoid manual queries)
|
||||||
|
2. hex-docs-search: Get Ecto.Query API documentation (filter operators, query functions)
|
||||||
|
3. Synthesize: "Here's how to do it (conventions) + what's available (API)"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Current Usage Rules Availability
|
||||||
|
|
||||||
|
**Packages with usage rules** (as of 2025-10-31):
|
||||||
|
- **Ash ecosystem**: ash, ash_postgres, ash_json_api
|
||||||
|
- **Build tools**: igniter, spark, reactor
|
||||||
|
|
||||||
|
**Note**: Usage rules are a community-driven convention. Not all packages have adopted this yet, but adoption is growing.
|
||||||
|
|
||||||
|
**Help the ecosystem**: Encourage package maintainers to add `usage-rules.md` files! These files help both humans and AI understand best practices.
|
||||||
|
|
||||||
|
## What are Usage Rules?
|
||||||
|
|
||||||
|
Usage rules are **LLM-optimized markdown files** (`usage-rules.md`) that packages provide to guide proper usage:
|
||||||
|
|
||||||
|
**Characteristics**:
|
||||||
|
- Located at package root: `<package>/usage-rules.md`
|
||||||
|
- Dense, token-efficient format
|
||||||
|
- Code-first with good/bad examples
|
||||||
|
- Organized by topic (querying, error handling, testing, etc.)
|
||||||
|
- Includes inline comments and quick references
|
||||||
|
|
||||||
|
**Example structure**:
|
||||||
|
```markdown
|
||||||
|
# Rules for working with Ash
|
||||||
|
|
||||||
|
## Understanding Ash
|
||||||
|
[High-level overview]
|
||||||
|
|
||||||
|
## Code Structure & Organization
|
||||||
|
[Conventions for organizing code]
|
||||||
|
|
||||||
|
## Querying Data
|
||||||
|
```elixir
|
||||||
|
# GOOD - Use code interface
|
||||||
|
MyApp.Blog.list_posts!(query: [filter: [status: :published]])
|
||||||
|
|
||||||
|
# BAD - Don't bypass domain
|
||||||
|
Ash.Query.filter(MyApp.Blog.Post, status: :published) |> Ash.read!()
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to Create Usage Rules
|
||||||
|
|
||||||
|
If you're a package maintainer:
|
||||||
|
|
||||||
|
1. Create `usage-rules.md` in your package root
|
||||||
|
2. Start with "# Rules for working with [Package]"
|
||||||
|
3. Add "## Understanding [Package]" section (overview)
|
||||||
|
4. Organize by common tasks and features
|
||||||
|
5. Use code examples with `# GOOD` and `# BAD` patterns
|
||||||
|
6. Keep it dense and token-efficient
|
||||||
|
7. Include in your hex package `files` list
|
||||||
|
|
||||||
|
See [Ash's usage-rules.md](https://github.com/ash-project/ash/blob/main/usage-rules.md) for a comprehensive example.
|
||||||
|
|
||||||
|
## Integration
|
||||||
|
|
||||||
|
This skill is bundled with the `core@elixir` plugin and doesn't require separate installation.
|
||||||
|
|
||||||
|
See [SKILL.md](SKILL.md) for the complete skill prompt and instructions.
|
||||||
624
skills/usage-rules/SKILL.md
Normal file
624
skills/usage-rules/SKILL.md
Normal file
@@ -0,0 +1,624 @@
|
|||||||
|
---
|
||||||
|
name: usage-rules
|
||||||
|
description: Search for package-specific usage rules and best practices from Elixir packages. Use when you need coding conventions, patterns, common mistakes, or good/bad examples for packages like Ash, Phoenix, Ecto, etc.
|
||||||
|
allowed-tools: Read, Grep, Glob, Bash, AskUserQuestion
|
||||||
|
---
|
||||||
|
|
||||||
|
# Usage Rules Search
|
||||||
|
|
||||||
|
Comprehensive search for Elixir and Erlang package usage rules and best practices, following a cascading strategy to find the most relevant coding conventions and patterns.
|
||||||
|
|
||||||
|
## When to use this skill
|
||||||
|
|
||||||
|
Use this skill when you need to:
|
||||||
|
- Look up coding conventions for a Hex package
|
||||||
|
- Find best practices and recommended patterns
|
||||||
|
- See good/bad code examples for proper usage
|
||||||
|
- Understand common mistakes to avoid
|
||||||
|
- Learn package-specific idioms and conventions
|
||||||
|
- Get context-aware recommendations for implementation
|
||||||
|
|
||||||
|
## Search strategy
|
||||||
|
|
||||||
|
This skill implements a **cascading search** that prioritizes local and contextual information:
|
||||||
|
|
||||||
|
1. **Local dependencies** - Search installed packages in `deps/` directory for usage-rules.md
|
||||||
|
2. **Fetched cache** - Check previously fetched usage rules in `.usage-rules/`
|
||||||
|
3. **Progressive fetch** - Automatically fetch package and extract usage-rules.md if missing
|
||||||
|
4. **Context-aware extraction** - Extract relevant sections based on coding context
|
||||||
|
5. **Fallback** - Note when package doesn't provide usage rules, suggest alternatives
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
### Step 1: Identify the package and context
|
||||||
|
|
||||||
|
Extract the package name and identify the coding context from the user's question.
|
||||||
|
|
||||||
|
**Package name examples**:
|
||||||
|
- "Ash best practices" → Package: `ash`
|
||||||
|
- "Phoenix LiveView patterns" → Package: `phoenix_live_view`
|
||||||
|
- "How to use Ecto properly?" → Package: `ecto`
|
||||||
|
|
||||||
|
**Context keywords**:
|
||||||
|
- Querying: "query", "filter", "search", "find", "list"
|
||||||
|
- Error handling: "error", "validation", "exception", "handle"
|
||||||
|
- Actions: "create", "update", "delete", "action", "change"
|
||||||
|
- Relationships: "relationship", "association", "belongs_to", "has_many"
|
||||||
|
- Testing: "test", "testing", "mock", "fixture"
|
||||||
|
- Authorization: "authorization", "permissions", "policy", "access"
|
||||||
|
- Structure: "structure", "organization", "architecture", "setup"
|
||||||
|
|
||||||
|
### Step 2: Search local dependencies
|
||||||
|
|
||||||
|
Use the **Glob** and **Grep** tools to search the `deps/` directory for usage rules:
|
||||||
|
|
||||||
|
1. **Find the package directory with usage-rules.md**:
|
||||||
|
```
|
||||||
|
Use Glob: pattern="deps/<package_name>/usage-rules.md"
|
||||||
|
```
|
||||||
|
|
||||||
|
If no results, the package isn't installed locally or doesn't provide usage rules. Skip to Step 3.
|
||||||
|
|
||||||
|
2. **Check for sub-rules** (advanced packages may have specialized rules):
|
||||||
|
```
|
||||||
|
Use Glob: pattern="deps/<package_name>/usage-rules/*.md"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Search for relevant sections** based on context keywords:
|
||||||
|
```
|
||||||
|
Use Grep: pattern="^## (Querying|Error Handling|Actions)", path="deps/<package_name>/usage-rules.md", output_mode="content", -n=true
|
||||||
|
```
|
||||||
|
|
||||||
|
This finds section headings with line numbers.
|
||||||
|
|
||||||
|
4. **Extract relevant sections**:
|
||||||
|
```
|
||||||
|
Use Grep: pattern="^## Error Handling", path="deps/<package_name>/usage-rules.md", output_mode="content", -A=50
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `-A` flag to get section content (adjust number based on typical section length).
|
||||||
|
|
||||||
|
5. **Read the complete file** if needed for broader context:
|
||||||
|
```
|
||||||
|
Use Read: file_path="deps/<package_name>/usage-rules.md"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Check fetched cache and fetch if needed
|
||||||
|
|
||||||
|
If the package wasn't found in `deps/`, check for previously fetched usage rules, or fetch them now.
|
||||||
|
|
||||||
|
#### 3.1: Check fetched cache
|
||||||
|
|
||||||
|
Use the **Glob** tool to check if usage rules were previously fetched:
|
||||||
|
|
||||||
|
```
|
||||||
|
Use Glob: pattern=".usage-rules/<package_name>-*/usage-rules.md"
|
||||||
|
```
|
||||||
|
|
||||||
|
If found, search the cached rules using the same patterns as Step 2 (sections 3-5).
|
||||||
|
|
||||||
|
#### 3.2: Determine version to fetch
|
||||||
|
|
||||||
|
If no cached rules found, determine which version to fetch:
|
||||||
|
|
||||||
|
1. **Check mix.lock** for locked version:
|
||||||
|
```
|
||||||
|
Use Bash: grep '"<package_name>"' mix.lock | grep -oE '[0-9]+\.[0-9]+\.[0-9]+'
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check mix.exs** for version constraint:
|
||||||
|
```
|
||||||
|
Use Bash: grep -E '\{:<package_name>' mix.exs | grep -oE '[0-9]+\.[0-9]+\.[0-9]+'
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Get latest version from hex.pm**:
|
||||||
|
```
|
||||||
|
Use Bash: curl -s "https://hex.pm/api/packages/<package_name>" | jq -r '.releases[0].version'
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **If version ambiguous**, use **AskUserQuestion** to prompt:
|
||||||
|
```
|
||||||
|
Question: "Package '<package_name>' usage rules not found locally. Which version would you like to fetch?"
|
||||||
|
Options:
|
||||||
|
- "Latest (X.Y.Z)" - Fetch most recent release
|
||||||
|
- "Project version (X.Y.Z)" - Use version from mix.exs/mix.lock (if available)
|
||||||
|
- "Specific version" - User provides custom version in "Other" field
|
||||||
|
- "Skip fetching" - Continue without usage rules
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.3: Fetch package and extract usage rules
|
||||||
|
|
||||||
|
Once version is determined, fetch the package and extract usage-rules.md:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create temp directory and fetch package
|
||||||
|
mkdir -p .usage-rules/.tmp
|
||||||
|
mix hex.package fetch <package_name> <version> --unpack --output .usage-rules/.tmp/<package_name>-<version>
|
||||||
|
|
||||||
|
# Check if usage-rules.md exists
|
||||||
|
if [ -f ".usage-rules/.tmp/<package_name>-<version>/usage-rules.md" ]; then
|
||||||
|
# Create version-specific directory
|
||||||
|
mkdir -p ".usage-rules/<package_name>-<version>"
|
||||||
|
|
||||||
|
# Copy main usage rules file
|
||||||
|
cp ".usage-rules/.tmp/<package_name>-<version>/usage-rules.md" ".usage-rules/<package_name>-<version>/"
|
||||||
|
|
||||||
|
# Copy sub-rules if present
|
||||||
|
if [ -d ".usage-rules/.tmp/<package_name>-<version>/usage-rules/" ]; then
|
||||||
|
cp -r ".usage-rules/.tmp/<package_name>-<version>/usage-rules/" ".usage-rules/<package_name>-<version>/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Usage rules cached in .usage-rules/<package_name>-<version>/"
|
||||||
|
else
|
||||||
|
echo "Package does not provide usage-rules.md"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up temp directory
|
||||||
|
rm -rf ".usage-rules/.tmp/<package_name>-<version>"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Storage location**: `.usage-rules/<package_name>-<version>/`
|
||||||
|
|
||||||
|
If successful:
|
||||||
|
- Search the cached usage rules using patterns from Step 2
|
||||||
|
- Read relevant files with the Read tool
|
||||||
|
|
||||||
|
If **package doesn't include usage-rules.md**:
|
||||||
|
- Package may not have adopted usage rules convention
|
||||||
|
- Proceed to Step 5 (fallback suggestions)
|
||||||
|
|
||||||
|
#### 3.4: Git ignore recommendation
|
||||||
|
|
||||||
|
Inform the user that fetched usage rules should be git-ignored. Suggest adding to `.gitignore`:
|
||||||
|
|
||||||
|
```gitignore
|
||||||
|
# Fetched usage rules
|
||||||
|
/.usage-rules/
|
||||||
|
```
|
||||||
|
|
||||||
|
This only needs to be mentioned once per session, and only if fetching actually occurred.
|
||||||
|
|
||||||
|
### Step 4: Extract relevant sections based on context
|
||||||
|
|
||||||
|
Usage rules files can be large (1000+ lines). Extract only relevant sections to avoid context overload.
|
||||||
|
|
||||||
|
#### 4.1: Find section headings
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Find all h2 section headings with line numbers
|
||||||
|
Use Grep: pattern="^## ", path=".usage-rules/<package>-<version>/usage-rules.md", output_mode="content", -n=true
|
||||||
|
```
|
||||||
|
|
||||||
|
This returns a list like:
|
||||||
|
```
|
||||||
|
7:## Understanding Ash
|
||||||
|
13:## Code Structure & Organization
|
||||||
|
21:## Code Interfaces
|
||||||
|
85:## Actions
|
||||||
|
120:## Querying Data
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.2: Match context to sections
|
||||||
|
|
||||||
|
Based on user's context keywords, identify relevant sections:
|
||||||
|
|
||||||
|
**Context: "querying"** → Look for sections containing:
|
||||||
|
- "Querying", "Query", "Filters", "Search", "Find"
|
||||||
|
|
||||||
|
**Context: "error handling"** → Look for sections containing:
|
||||||
|
- "Error", "Validation", "Exception", "Handle"
|
||||||
|
|
||||||
|
**Context: "actions"** → Look for sections containing:
|
||||||
|
- "Actions", "Create", "Update", "Delete", "CRUD"
|
||||||
|
|
||||||
|
#### 4.3: Extract matched sections
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Extract specific section with content
|
||||||
|
Use Grep: pattern="^## Querying Data", path=".usage-rules/<package>-<version>/usage-rules.md", output_mode="content", -A=80
|
||||||
|
```
|
||||||
|
|
||||||
|
**Adjust `-A` value** based on typical section length:
|
||||||
|
- Small sections (< 50 lines): `-A=50`
|
||||||
|
- Medium sections (50-150 lines): `-A=100`
|
||||||
|
- Large sections (> 150 lines): `-A=150` or read specific ranges
|
||||||
|
|
||||||
|
#### 4.4: Include code examples
|
||||||
|
|
||||||
|
Look for code blocks within sections:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Find code examples in section
|
||||||
|
Use Grep: pattern="```elixir|# GOOD|# BAD", path=".usage-rules/<package>-<version>/usage-rules.md", output_mode="content", -A=10
|
||||||
|
```
|
||||||
|
|
||||||
|
Code examples often include:
|
||||||
|
- **Good patterns**: Marked with `# GOOD`, `# PREFERRED`
|
||||||
|
- **Bad patterns**: Marked with `# BAD`, `# AVOID`, `# WRONG`
|
||||||
|
- **Inline comments**: Explanatory comments in code blocks
|
||||||
|
|
||||||
|
### Step 5: Present usage rules
|
||||||
|
|
||||||
|
Format the output based on what was found.
|
||||||
|
|
||||||
|
## Output format
|
||||||
|
|
||||||
|
When presenting results, organize them as follows:
|
||||||
|
|
||||||
|
### If found in local dependencies:
|
||||||
|
|
||||||
|
```
|
||||||
|
Found usage rules for <package_name>:
|
||||||
|
|
||||||
|
**Location**: deps/<package_name>/usage-rules.md
|
||||||
|
**Version**: <version from mix.lock>
|
||||||
|
|
||||||
|
**Relevant Best Practices** (<section_name>):
|
||||||
|
|
||||||
|
<extracted section content with code examples>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Full Rules**: deps/<package_name>/usage-rules.md
|
||||||
|
|
||||||
|
**Integration**: For API documentation, use the hex-docs-search skill.
|
||||||
|
```
|
||||||
|
|
||||||
|
### If found in fetched cache:
|
||||||
|
|
||||||
|
```
|
||||||
|
Found cached usage rules for <package_name>:
|
||||||
|
|
||||||
|
**Version**: <version>
|
||||||
|
**Cache Location**: .usage-rules/<package>-<version>/usage-rules.md
|
||||||
|
|
||||||
|
**Relevant Best Practices** (<section_name>):
|
||||||
|
|
||||||
|
<extracted section content with code examples>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Full Rules**: .usage-rules/<package>-<version>/usage-rules.md
|
||||||
|
|
||||||
|
**Note**: Rules are cached locally for offline access.
|
||||||
|
|
||||||
|
**Integration**: For API documentation, use the hex-docs-search skill.
|
||||||
|
```
|
||||||
|
|
||||||
|
### If usage rules not available:
|
||||||
|
|
||||||
|
```
|
||||||
|
Package '<package_name>' does not provide usage-rules.md.
|
||||||
|
|
||||||
|
**Note**: Usage rules are a community-driven convention where packages provide
|
||||||
|
best practices in markdown format. Not all packages have adopted this yet.
|
||||||
|
|
||||||
|
**Alternatives**:
|
||||||
|
- Use hex-docs-search skill for API documentation and guides
|
||||||
|
- Check package README or official documentation
|
||||||
|
- Search for "<package_name> elixir best practices" online
|
||||||
|
- Look for community guides and blog posts
|
||||||
|
|
||||||
|
**Current packages with usage rules**:
|
||||||
|
- ash, ash_postgres, ash_json_api (Ash Framework ecosystem)
|
||||||
|
- igniter, spark, reactor (Build tools and engines)
|
||||||
|
|
||||||
|
**Help the ecosystem**: Encourage package maintainers to add usage-rules.md!
|
||||||
|
```
|
||||||
|
|
||||||
|
### If user needs comprehensive guidance:
|
||||||
|
|
||||||
|
```
|
||||||
|
For comprehensive implementation guidance, use both:
|
||||||
|
|
||||||
|
1. **usage-rules skill** - Coding conventions and best practices
|
||||||
|
2. **hex-docs-search skill** - API documentation and function signatures
|
||||||
|
|
||||||
|
Combining both provides complete "how to implement correctly" guidance.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Example 1: Finding Ash querying best practices
|
||||||
|
|
||||||
|
**User asks**: "What are the best practices for querying data in Ash?"
|
||||||
|
|
||||||
|
**Search process**:
|
||||||
|
1. Extract package: `ash`
|
||||||
|
2. Identify context: "querying"
|
||||||
|
3. Check `deps/ash/usage-rules.md` (found)
|
||||||
|
4. Search for section: `## Querying Data`
|
||||||
|
5. Extract section with code examples
|
||||||
|
6. Present best practices
|
||||||
|
|
||||||
|
**Output**:
|
||||||
|
```
|
||||||
|
Found usage rules for ash:
|
||||||
|
|
||||||
|
**Location**: deps/ash/usage-rules.md
|
||||||
|
**Version**: 3.5.20
|
||||||
|
|
||||||
|
**Relevant Best Practices** (Querying Data):
|
||||||
|
|
||||||
|
## Querying Data
|
||||||
|
|
||||||
|
### Common Query Operations
|
||||||
|
|
||||||
|
Prefer using code interface functions with the `query` option for filtering, sorting, and limiting:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# PREFERRED - Use the query option
|
||||||
|
posts = MyApp.Blog.list_posts!(
|
||||||
|
query: [
|
||||||
|
filter: [status: :published],
|
||||||
|
sort: [published_at: :desc],
|
||||||
|
limit: 10
|
||||||
|
],
|
||||||
|
load: [author: :profile]
|
||||||
|
)
|
||||||
|
|
||||||
|
# AVOID - Don't build queries manually outside domain
|
||||||
|
query = MyApp.Blog.Post
|
||||||
|
|> Ash.Query.filter(status: :published)
|
||||||
|
|> Ash.Query.sort(published_at: :desc)
|
||||||
|
posts = Ash.read!(query)
|
||||||
|
```
|
||||||
|
|
||||||
|
All query-related options go in the `query` parameter, not as separate arguments.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Full Rules**: deps/ash/usage-rules.md
|
||||||
|
|
||||||
|
**Integration**: For Ecto.Query API documentation, use hex-docs-search skill.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 2: Error handling conventions
|
||||||
|
|
||||||
|
**User asks**: "How should I handle errors in Phoenix LiveView?"
|
||||||
|
|
||||||
|
**Search process**:
|
||||||
|
1. Extract package: `phoenix_live_view`
|
||||||
|
2. Identify context: "error handling"
|
||||||
|
3. Check `deps/phoenix_live_view/usage-rules.md` (not found - LiveView doesn't provide usage rules yet)
|
||||||
|
4. Check `.usage-rules/phoenix_live_view-*/usage-rules.md` (not found)
|
||||||
|
5. Attempt fetch (package doesn't include usage-rules.md)
|
||||||
|
6. Provide fallback suggestions
|
||||||
|
|
||||||
|
**Output**:
|
||||||
|
```
|
||||||
|
Package 'phoenix_live_view' does not provide usage-rules.md.
|
||||||
|
|
||||||
|
**Alternatives**:
|
||||||
|
- Use hex-docs-search skill for Phoenix.LiveView API documentation
|
||||||
|
- Check Phoenix LiveView guides: https://hexdocs.pm/phoenix_live_view/
|
||||||
|
- Search for "phoenix liveview error handling best practices"
|
||||||
|
|
||||||
|
**Note**: Usage rules are a community convention. Help the ecosystem by encouraging
|
||||||
|
package maintainers to add usage-rules.md files!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 3: Unknown package with progressive fetch
|
||||||
|
|
||||||
|
**User asks**: "What are the best practices for using Spark DSL?"
|
||||||
|
|
||||||
|
**Search process**:
|
||||||
|
1. Extract package: `spark`
|
||||||
|
2. Identify context: general (no specific context)
|
||||||
|
3. Check `deps/spark/usage-rules.md` (not found)
|
||||||
|
4. Check `.usage-rules/spark-*/usage-rules.md` (not found)
|
||||||
|
5. Check mix.exs: `{:spark, "~> 2.0"}`
|
||||||
|
6. Get latest 2.x from hex.pm:
|
||||||
|
```bash
|
||||||
|
curl -s "https://hex.pm/api/packages/spark" | jq -r '.releases[] | select(.version | startswith("2.")) | .version' | head -1
|
||||||
|
# Returns: 2.2.24
|
||||||
|
```
|
||||||
|
7. Fetch package:
|
||||||
|
```bash
|
||||||
|
mix hex.package fetch spark 2.2.24 --unpack --output .usage-rules/.tmp/spark-2.2.24
|
||||||
|
```
|
||||||
|
8. Extract usage-rules.md (found!)
|
||||||
|
9. Copy to cache: `.usage-rules/spark-2.2.24/usage-rules.md`
|
||||||
|
10. Clean up temp
|
||||||
|
11. Read and present usage rules
|
||||||
|
|
||||||
|
**Output**:
|
||||||
|
```
|
||||||
|
Found cached usage rules for spark:
|
||||||
|
|
||||||
|
**Version**: 2.2.24
|
||||||
|
**Cache Location**: .usage-rules/spark-2.2.24/usage-rules.md
|
||||||
|
|
||||||
|
**Relevant Best Practices** (Understanding Spark):
|
||||||
|
|
||||||
|
## Understanding Spark
|
||||||
|
|
||||||
|
Spark is a foundation for declarative DSLs in Elixir. It powers frameworks like Ash
|
||||||
|
by providing the infrastructure for building expressive, compile-time-validated DSLs.
|
||||||
|
|
||||||
|
### Key Concepts
|
||||||
|
|
||||||
|
- **Extensions**: Modules that add DSL sections to Spark DSLs
|
||||||
|
- **Sections**: Top-level DSL constructs (like `actions do ... end`)
|
||||||
|
- **Entities**: Individual items within sections (like `read :list`)
|
||||||
|
- **Options**: Configuration for entities
|
||||||
|
|
||||||
|
<...more content...>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Full Rules**: .usage-rules/spark-2.2.24/usage-rules.md
|
||||||
|
|
||||||
|
**Note**: Rules are now cached locally for offline access.
|
||||||
|
|
||||||
|
**Recommendation**: Add `.usage-rules/` to your .gitignore.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 4: Cached rules (offline access)
|
||||||
|
|
||||||
|
**User asks**: "Show me Ash relationship best practices again"
|
||||||
|
|
||||||
|
**Search process**:
|
||||||
|
1. Extract package: `ash`
|
||||||
|
2. Identify context: "relationship"
|
||||||
|
3. Check `deps/ash/usage-rules.md` (not found - not in project)
|
||||||
|
4. Check `.usage-rules/ash-*/usage-rules.md` (found version 3.5.20!)
|
||||||
|
5. **No fetch needed** - use cached rules
|
||||||
|
6. Search for "## Relationships" section
|
||||||
|
7. Extract and present
|
||||||
|
|
||||||
|
**Result**: Fast, offline search without network requests. Works even when disconnected.
|
||||||
|
|
||||||
|
### Example 5: Context-aware extraction
|
||||||
|
|
||||||
|
**User asks**: "Common mistakes with Ash actions?"
|
||||||
|
|
||||||
|
**Search process**:
|
||||||
|
1. Extract package: `ash`
|
||||||
|
2. Identify context: "actions" + "mistakes"
|
||||||
|
3. Find usage rules (local or cached)
|
||||||
|
4. Search for "## Actions" section
|
||||||
|
5. Also search for keywords: "mistake", "avoid", "wrong", "bad"
|
||||||
|
6. Extract relevant parts from multiple sections
|
||||||
|
7. Present consolidated best practices
|
||||||
|
|
||||||
|
**Output**:
|
||||||
|
```
|
||||||
|
Found usage rules for ash:
|
||||||
|
|
||||||
|
**Relevant Best Practices** (Actions - Common Mistakes):
|
||||||
|
|
||||||
|
## Actions
|
||||||
|
|
||||||
|
**AVOID** - Don't create generic CRUD actions:
|
||||||
|
```elixir
|
||||||
|
# BAD - Generic naming
|
||||||
|
create :create
|
||||||
|
update :update
|
||||||
|
```
|
||||||
|
|
||||||
|
**PREFER** - Create domain-specific actions:
|
||||||
|
```elixir
|
||||||
|
# GOOD - Specific business operations
|
||||||
|
create :register_user
|
||||||
|
update :activate_account
|
||||||
|
update :suspend_for_violation
|
||||||
|
```
|
||||||
|
|
||||||
|
**AVOID** - Don't put business logic outside actions:
|
||||||
|
```elixir
|
||||||
|
# BAD - Logic in controller
|
||||||
|
def create_post(conn, params) do
|
||||||
|
{:ok, post} = Blog.create_post(params)
|
||||||
|
# Business logic here
|
||||||
|
send_notifications(post)
|
||||||
|
update_stats()
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
**PREFER** - Put business logic in action changes:
|
||||||
|
```elixir
|
||||||
|
# GOOD - Logic in action
|
||||||
|
create :publish_post do
|
||||||
|
change after_action(fn _changeset, post ->
|
||||||
|
send_notifications(post)
|
||||||
|
update_stats()
|
||||||
|
{:ok, post}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Full Rules**: deps/ash/usage-rules.md
|
||||||
|
|
||||||
|
## Tool usage summary
|
||||||
|
|
||||||
|
Use Claude's built-in tools in this order:
|
||||||
|
|
||||||
|
1. **Glob** - Find usage-rules.md files in deps/, .usage-rules/, and check for sub-rules
|
||||||
|
2. **Grep** - Search for section headings, context keywords, and code examples
|
||||||
|
3. **Read** - Read complete usage rules files when broader context needed
|
||||||
|
4. **Bash** - Fetch packages with mix hex.package, version resolution, extract and cache rules
|
||||||
|
5. **AskUserQuestion** - Prompt for version when ambiguous
|
||||||
|
|
||||||
|
**Requirements:** curl and jq (Linux/Mac native, use Git Bash or WSL on Windows)
|
||||||
|
|
||||||
|
## Best practices
|
||||||
|
|
||||||
|
1. **Start local**: Always check local dependencies first - they match the version used in the project
|
||||||
|
2. **Check cache before fetch**: Look for previously fetched rules in `.usage-rules/` before fetching
|
||||||
|
3. **Context-aware extraction**: Don't present entire file - extract relevant sections based on keywords
|
||||||
|
4. **Show code examples**: Always include good/bad pattern examples when available
|
||||||
|
5. **Highlight patterns**: Point out `# GOOD` vs `# BAD` comparisons explicitly
|
||||||
|
6. **Link to source**: Provide file path so users can explore complete rules
|
||||||
|
7. **Note integration**: Mention hex-docs-search for complementary API documentation
|
||||||
|
8. **Git ignore reminder**: Mention .gitignore addition once per session when fetching occurs
|
||||||
|
9. **Offline capability**: Once fetched, usage rules available without network access
|
||||||
|
10. **Version awareness**: Note which version is installed locally vs fetched from cache
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Package not found in deps/
|
||||||
|
|
||||||
|
- Check `.usage-rules/` for previously fetched rules
|
||||||
|
- If not cached, determine version and offer to fetch
|
||||||
|
- Check if package is in mix.exs dependencies (for version resolution)
|
||||||
|
- Verify package name spelling (convert `Phoenix.LiveView` → `phoenix_live_view`)
|
||||||
|
|
||||||
|
### Package doesn't provide usage-rules.md
|
||||||
|
|
||||||
|
- This is expected - usage rules are a convention, not all packages have them
|
||||||
|
- Fallback to hex-docs-search for API documentation
|
||||||
|
- Suggest checking package README or guides
|
||||||
|
- Encourage package maintainers to add usage rules
|
||||||
|
|
||||||
|
### Fetch failures
|
||||||
|
|
||||||
|
**Package fetch fails**:
|
||||||
|
- Verify package name spelling
|
||||||
|
- Check network connectivity
|
||||||
|
- Verify package exists on hex.pm
|
||||||
|
- Try web search as fallback
|
||||||
|
|
||||||
|
**Extraction fails**:
|
||||||
|
- Package was fetched but doesn't include usage-rules.md
|
||||||
|
- Clean up temp directory
|
||||||
|
- Note that package doesn't provide rules
|
||||||
|
|
||||||
|
### Cache location issues
|
||||||
|
|
||||||
|
**Fetched rules not found on repeat queries**:
|
||||||
|
- Verify `.usage-rules/` directory exists
|
||||||
|
- Check that fetch command completed successfully
|
||||||
|
- May need to re-fetch if directories were deleted
|
||||||
|
- Ensure temp cleanup didn't remove permanent cache
|
||||||
|
|
||||||
|
### Section extraction challenges
|
||||||
|
|
||||||
|
**Section too large**:
|
||||||
|
- Increase `-A` value in Grep to get more content
|
||||||
|
- Or read complete file and extract programmatically
|
||||||
|
- Consider showing summary + offering full section
|
||||||
|
|
||||||
|
**Multiple relevant sections**:
|
||||||
|
- Extract multiple sections
|
||||||
|
- Present them in logical order
|
||||||
|
- Clearly label each section
|
||||||
|
|
||||||
|
**No section matches context**:
|
||||||
|
- Show "## Understanding [Package]" section as default
|
||||||
|
- List available sections for user to choose from
|
||||||
|
- Read complete file if user wants comprehensive overview
|
||||||
|
|
||||||
|
### Version mismatches
|
||||||
|
|
||||||
|
**Different version in deps/ vs cache**:
|
||||||
|
- Prefer deps/ version (matches project)
|
||||||
|
- Note version difference if using cache
|
||||||
|
- Offer to fetch version matching project dependencies
|
||||||
|
|
||||||
|
**Version specified doesn't exist**:
|
||||||
|
- List available versions from hex.pm
|
||||||
|
- Prompt user to select valid version
|
||||||
|
- Fall back to latest if user unsure
|
||||||
Reference in New Issue
Block a user