Contributing to RubyLLM

September 21, 2026 · View on GitHub

Working with a coding agent? AGENTS.md has the commands, architecture rules, and style conventions, and the repo ships a contributing skill in .claude/skills/ with step-by-step recipes. Both are worth a read for humans too.

Did you find a bug?

  • Ensure the bug was not already reported by searching on GitHub under Issues.

  • If you're unable to find an open issue addressing the problem, open a new one. Include a title and clear description, relevant information, and a code sample demonstrating the issue.

  • Verify it's a RubyLLM bug, not your application code, before opening an issue.

Did you write a patch that fixes a bug?

  • Open a new GitHub pull request with the patch.

  • Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.

  • Run overcommit --install before committing - it handles code style and tests automatically.

Do you intend to add a new feature or change an existing one?

  • First check if this belongs in RubyLLM or your application. RubyLLM already provides chat, agents, tools, embeddings, and the building blocks for workflows and RAG. Before proposing a new feature, ask: can this be built with what RubyLLM already offers? If so, it belongs in your application code, not in the gem.

  • Features we'll reject:

    • Anything you can build in a few lines of application code using existing RubyLLM features
    • Opinionated abstractions over patterns that are already straightforward (e.g., specific RAG pipeline frameworks, workflow orchestration DSLs)
    • Integrations with specific external services (vector databases, search engines, etc.) — these work great as separate gems
    • Testing frameworks
  • You must open an issue first and wait for maintainer feedback before writing code. PRs for new features without an approved issue will be closed without review.

  • Keep PRs focused and reasonably sized. Large features should be discussed in the issue and potentially broken into smaller, reviewable PRs. Dropping thousands of lines of code without prior discussion is not helpful.

  • If you use AI tools, you must understand every single line of code you submit. AI-generated code often requires more review time from maintainers, which may delay your PR.

Provider contributions

  • Core providers have a high acceptance bar.
  • For smaller or emerging providers, the preferred path is a community gem rather than RubyLLM core.
  • Start a community integration with bundle exec ruby_llm provider-gem NAME. See the Custom Providers and Protocols guide.
  • Documentation must teach RubyLLM. We do not accept provider listings, promotional links, or dedicated setup sections for third-party services that work by changing an existing provider's API base URL or API key. Document how to use RubyLLM in that service's own documentation.
  • Keep generic endpoint configuration in the shared provider guide. Provider-specific documentation in this repository must support an approved core integration or explain a distinct RubyLLM requirement; a documentation-only PR does not bypass the provider acceptance policy.
  • After a core provider has been discussed and approved, use script/generate-provider NAME to create the standard files and wiring.
  • Generated code is a starting point. A core provider PR must use the real API, replace example capabilities, cover normal and streaming chat with sanitized VCR cassettes, document its configuration, and identify its model-catalog source.

Quick Start

gh repo fork crmne/ruby_llm --clone && cd ruby_llm
bundle install
overcommit --install  # Required - sets up git hooks
gh issue develop 123 --checkout  # or create your own branch
# make changes, add tests
gh pr create --web

Testing

overcommit --run

# Fast unit-only run - skips specs tagged :live, needs no cassettes or API keys:
bundle exec rspec --tag ~live

# Re-recording VCR cassettes (requires API keys):
rake vcr:record[openai,anthropic]  # Specific providers
rake vcr:record[all]               # Everything

Specs tagged :live talk to provider APIs through VCR cassettes; everything else is a plain unit test.

Always check cassettes for leaked API keys before committing.

Documentation

The site builds three versions from the same repository:

URLSource
/Latest stable release tag
/next/main, including unreleased changes
/v1/Latest stable 1.x release tag

Each version has its own guides, API reference, search, and Markdown exports. The version selector uses the release tags selected during the build. Prerelease tags do not replace the stable documentation. /models.json remains the live model registry shared by clients.

Run docs/bin/serve.sh to preview all three versions. Changes to guides rebuild under /next/; restart the preview to regenerate API references. Run docs/bin/build-versions.sh for the complete deployment build. Both commands require the release tags in your local checkout.

Pushing documentation or library changes to main updates /next/. Publishing a release also rebuilds the site, promoting its tagged docs to / while main continues at /next/.

Publishing a release

Pushing to main runs CI. Publishing a GitHub release starts the release workflow, which validates the tag and gem version, tests the released commit, and publishes the gem to RubyGems and GitHub Packages. A tag push alone does not publish the gem.

As a maintainer, push the reviewed commit to main, write the release notes in a file, and create the release using your own GitHub account:

version=$(ruby -r ./lib/ruby_llm/version -e 'puts RubyLLM::VERSION')
commit=$(git rev-parse HEAD)
gh release create "v$version" --target "$commit" \
  --title "RubyLLM $version" --notes-file release-notes.md --prerelease

Use --prerelease for beta and release candidate versions; omit it for stable versions. The tag must be v followed by the exact gem version, and the commit must be on main. GitHub creates the tag if it does not exist. Add --draft to review the release on GitHub before publishing it; drafts do not start gem publication.

The workflow retains the cassette freshness check: run bundle exec rake release:verify_cassettes before publishing. It currently requires recordings from the preceding 24 hours. If a release workflow fails, fix the cause and rerun it; do not move a published release tag.

Important Notes

  • Never edit models.json, aliases.json, or available-models.md - they're auto-generated by rake models
  • Write tests for any new functionality
  • Keep it simple - if it needs extensive documentation, reconsider the approach
  • Model data comes from models.dev. If you spot issues in the upstream registry, please report them via their site or repo.

Response Times

This is my gift to the Ruby community.

Gifts don't come with SLAs. I respond when I can.

Support

If RubyLLM helps you, consider sponsoring.

Sponsorship is just a way to say thanks - it doesn't buy priority support or feature requests.

Go ship AI apps!

— Carmine