gem-builder
Build production-quality Ruby gems. Use when creating new gems, structuring gem architecture, implementing configuration patterns, setting up testing, or preparing for publishing. Covers all gem types - libraries, CLI tools, Rails engines, and API clients.
What this skill does
# Gem Builder
## Core Philosophy
- **Minimal dependencies**: Only add gems you truly need
- **Single responsibility**: Each class/module does one thing well
- **Semantic versioning**: Follow SemVer strictly (MAJOR.MINOR.PATCH)
- **Test coverage**: Every public method has tests
- **Documentation**: YARD docs, README, and CHANGELOG
- **Fail fast**: Validate inputs early, raise descriptive errors
## Gem Structure
```
my_gem/
├── lib/
│ ├── my_gem.rb # Main entry point
│ ├── my_gem/
│ │ ├── version.rb # VERSION constant
│ │ ├── config.rb # Configuration class
│ │ ├── errors.rb # Error hierarchy
│ │ └── [feature].rb # Feature modules
├── test/ # Test suite
├── my_gem.gemspec # Gem specification
├── Gemfile # Development dependencies
├── Rakefile # Build tasks
├── README.md # User documentation
├── CHANGELOG.md # Version history
└── LICENSE.txt # License file
```
### Main Entry Point
```ruby
# lib/my_gem.rb
require_relative "my_gem/version"
require_relative "my_gem/config"
require_relative "my_gem/errors"
module MyGem
class << self
def config
@config ||= Config.new
end
def configure
yield(config)
end
def reset_configuration!
@config = nil
end
end
end
```
## Gemspec Best Practices
```ruby
# my_gem.gemspec
require_relative "lib/my_gem/version"
Gem::Specification.new do |spec|
spec.name = "my_gem"
spec.version = MyGem::VERSION
spec.authors = ["Your Name"]
spec.email = ["[email protected]"]
spec.summary = "One-line description"
spec.homepage = "https://github.com/username/my_gem"
spec.license = "MIT"
spec.required_ruby_version = ">= 3.2.0"
spec.metadata["rubygems_mfa_required"] = "true"
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
# Exclude test/CI files
spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls|
ls.readlines("\x0", chomp: true).reject { |f| f.start_with?(*%w[bin/ test/ .github/]) }
end
spec.require_paths = ["lib"]
end
```
## Gem Types
| Type | Key Features |
|------|--------------|
| Library | Pure Ruby, no external services |
| API Client | HTTP wrapper with resource pattern |
| CLI Tool | `spec.executables`, bindir setup |
| Rails Integration | Railtie with `ActiveSupport.on_load` |
### API Client Pattern
```ruby
class Client
def initialize(api_key: nil)
@api_key = api_key || MyGem.config.api_key
raise ArgumentError, "API key required" if @api_key.to_s.empty?
end
def users = @users ||= Resources::Users.new(self)
def posts = @posts ||= Resources::Posts.new(self)
end
```
### Rails Integration
**Never require Rails directly.** Use lazy loading:
```ruby
# lib/my_gem/railtie.rb
class Railtie < Rails::Railtie
initializer "my_gem.configure" do
ActiveSupport.on_load(:active_record) do
extend MyGem::Model
end
end
end
# lib/my_gem.rb
require_relative "my_gem/railtie" if defined?(Rails)
```
### Class Macro DSL
The pattern used by `searchkick`, `lockbox`:
```ruby
# Usage: mygemname word_start: [:name]
module Model
def mygemname(**options)
unknown = options.keys - KNOWN_OPTIONS
raise ArgumentError, "Unknown: #{unknown.join(", ")}" if unknown.any?
mod = Module.new
mod.module_eval { define_method(:some_method) { options[:key] } }
include mod
class_variable_set(:@@mygemname_options, options.dup)
end
end
```
## Configuration Pattern
```ruby
# lib/my_gem/config.rb
class Config
attr_accessor :api_key, :base_url, :timeout
attr_writer :logger
def initialize
@api_key = ENV.fetch("MY_GEM_API_KEY", nil)
@base_url = ENV.fetch("MY_GEM_BASE_URL", "https://api.example.com")
@timeout = Integer(ENV.fetch("MY_GEM_TIMEOUT", 30)) rescue 30
end
def logger
@logger ||= defined?(Rails) ? Rails.logger : Logger.new($stderr)
end
end
```
Usage:
```ruby
MyGem.configure do |config|
config.api_key = "secret"
end
```
## Error Handling
```ruby
# lib/my_gem/errors.rb
module MyGem
class Error < StandardError
attr_reader :status, :body
def initialize(message = nil, status: nil, body: nil)
super(message)
@status, @body = status, body
end
end
class ConfigurationError < Error; end
class AuthenticationError < Error; end # 401
class ClientError < Error; end # 4xx
class ServerError < Error; end # 5xx
class NetworkError < Error; end # Connection failures
end
```
## Testing Setup
```ruby
# test/test_helper.rb
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
require "my_gem"
require "minitest/autorun"
require "webmock/minitest"
module TestConfig
def setup_config
WebMock.reset!
MyGem.reset_configuration!
MyGem.configure { |c| c.api_key = "test-key" }
end
def teardown_config
WebMock.reset!
MyGem.reset_configuration!
end
end
```
```ruby
class ClientTest < Minitest::Test
include TestConfig
def setup = setup_config
def teardown = teardown_config
def test_requires_api_key
MyGem.config.api_key = nil
assert_raises(ArgumentError) { MyGem::Client.new }
end
end
```
## Documentation
### YARD Setup (`.yardopts`)
```
--markup markdown
--no-private
lib/**/*.rb
- README.md
```
### README Sections
Installation, Quick Start, Configuration, Features, Development, License.
### CHANGELOG (Keep a Changelog)
```markdown
## [1.0.0] - 2025-01-15
### Added
- Initial release
```
## Build & Release
### Rakefile
```ruby
require "bundler/gem_tasks"
require "minitest/test_task"
Minitest::TestTask.create
require "rubocop/rake_task"
RuboCop::RakeTask.new
task default: %i[test rubocop]
```
### Release Workflow
```bash
# 1. Update lib/my_gem/version.rb
# 2. Update CHANGELOG.md
# 3. Commit and release
git commit -am "Release v1.0.0"
bundle exec rake release
```
## Anti-Patterns
| Avoid | Instead |
|-------|---------|
| `method_missing` | `define_method` |
| `@@class_variables` | `class << self` with ivars |
| Requiring Rails directly | `ActiveSupport.on_load` |
| Many runtime deps | Prefer stdlib |
| Committing Gemfile.lock | Only lock in apps |
| Heavy DSLs | Explicit Ruby |
| `autoload` | `require_relative` |
## Best Practices Checklist
**Structure:**
- [ ] Standard directory layout
- [ ] Version in single location
- [ ] Frozen string literals
**Gemspec:**
- [ ] All metadata populated
- [ ] `rubygems_mfa_required` = true
- [ ] Minimal runtime deps
**Configuration:**
- [ ] Environment variable fallbacks
- [ ] Block-based DSL
- [ ] Test-friendly reset method
**Error Handling:**
- [ ] Custom hierarchy
- [ ] Descriptive messages
- [ ] Status/body preserved
**Testing:**
- [ ] Isolation between tests
- [ ] WebMock for HTTP
- [ ] Success and failure cases
**Documentation:**
- [ ] YARD on public methods
- [ ] README with quick start
- [ ] CHANGELOG
**Rails (if applicable):**
- [ ] Optional with `if defined?(Rails)`
- [ ] Isolated namespace
- [ ] `ActiveSupport.on_load` hooks
## References
- `references/templates.md` - Copy-paste templates (CI, gemspec, README)
- `references/advanced-patterns.md` - Database adapters, multi-version testing
- `references/engine-migrations.md` - Keep migrations in Rails engines
Related in Backend & APIs
jfrog
IncludedInteract with the JFrog Platform via the JFrog CLI and REST/GraphQL APIs. Use this skill when the user wants to manage Artifactory repositories, upload or download artifacts, manage builds, configure permissions, manage users and groups, work with access tokens, configure JFrog CLI servers, search artifacts, manage properties, set up replication, manage JFrog Projects, run security audits or scans, look up CVE details, query exposures scan results from JFrog Advanced Security, manage release bundles and lifecycle operations, aggregate or export platform data, or perform any JFrog Platform administration task. Also use when the user mentions jf, jfrog, artifactory, xray, distribution, evidence, apptrust, onemodel, graphql, workers, mission control, curation, advanced security, exposures, or any JFrog product name.
cupynumeric-migration-readiness
IncludedPre-migration readiness assessor for porting NumPy to cuPyNumeric. Use BEFORE substantial porting work begins when the user asks whether code will scale on GPU, whether they should migrate to cuPyNumeric, which NumPy patterns transfer cleanly, what must be refactored before porting, or mentions pre-port assessment, scaling analysis, or refactor planning. Inspect the user's source code, look up NumPy usage, cross-reference the cuPyNumeric API support manifest, and distinguish distributed-scaling-friendly patterns from blockers such as unsupported APIs, scalar synchronization, host round-trips, Python/object-heavy control flow, shape/data-dependent branching, and in-place mutation hazards. Produce a verdict of READY, LIGHT REFACTOR, SIGNIFICANT REFACTOR, or NOT RECOMMENDED, with concrete refactor pointers.
alibabacloud-data-agent-skill
IncludedInvoke Alibaba Cloud Apsara Data Agent for Analytics via CLI to perform natural language-driven data analysis on enterprise databases. Data Agent for Analytics is an intelligent data analysis agent developed by Alibaba Cloud Database team for enterprise users. It automatically completes requirement analysis, data understanding, analysis insights, and report generation based on natural language descriptions. This tool supports: discovering data resources (instances/databases/tables) managed in DMS, initiating query or deep analysis sessions, real-time progress tracking, and retrieving analysis conclusions and generated reports. Use this Skill when users need to query databases, analyze data trends, generate data reports, ask questions in natural language, or mention "Data Agent", "data analysis", "database query", "SQL analysis", "data insights".
token-optimizer
IncludedReduce OpenClaw token usage and API costs through smart model routing, heartbeat optimization, budget tracking, and native 2026.2.15 features (session pruning, bootstrap size limits, cache TTL alignment). Use when token costs are high, API rate limits are being hit, or hosting multiple agents at scale. The 4 executable scripts (context_optimizer, model_router, heartbeat_optimizer, token_tracker) are local-only — no network requests, no subprocess calls, no system modifications. Reference files (PROVIDERS.md, config-patches.json) document optional multi-provider strategies that require external API keys and network access if you choose to use them. See SECURITY.md for full breakdown.
resend-cli
IncludedUse this skill when the task is specifically about operating Resend from an AI agent, terminal session, or CI job via the official resend CLI: installing/authenticating the CLI, sending/listing/updating/cancelling emails, batch sends, domains and DNS, webhooks and local listeners, inbound receiving, contacts, topics, segments, broadcasts, templates, API keys, profiles, or debugging Resend CLI/API failures. Trigger on mentions of Resend CLI, `resend`, `resend doctor`, `resend emails send`, `resend domains`, `resend webhooks listen`, `resend emails receiving`, or agent-friendly terminal automation.
alibabacloud-odps-maxframe-coding
IncludedUse this skill for MaxFrame SDK development and documentation navigation on Alibaba Cloud MaxCompute (ODPS). Helps answer MaxFrame API, concept, official example, and supported pandas API questions; create data processing programs; read/write MaxCompute tables; debug jobs (remote or local); and build custom DPE runtime images. Trigger when users mention MaxFrame, MaxCompute with MaxFrame, ODPS table processing, DPE runtime, MaxFrame docs/examples, DataFrame/Tensor operations, or GPU runtime setup. Works for both English and Chinese queries about Alibaba Cloud data processing with MaxFrame.