RepoPilotOpen in app →

sferik/twitter-ruby

A Ruby interface to the Twitter API.

Healthy

Healthy across all four use cases

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 3d ago
  • 4 active contributors
  • MIT licensed
Show 4 more →
  • CI configured
  • Tests present
  • Small team — 4 contributors active in recent commits
  • Single-maintainer risk — top contributor 93% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/sferik/twitter-ruby)](https://repopilot.app/r/sferik/twitter-ruby)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/sferik/twitter-ruby on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: sferik/twitter-ruby

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/sferik/twitter-ruby shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • Last commit 3d ago
  • 4 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Small team — 4 contributors active in recent commits
  • ⚠ Single-maintainer risk — top contributor 93% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live sferik/twitter-ruby repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/sferik/twitter-ruby.

What it runs against: a local clone of sferik/twitter-ruby — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in sferik/twitter-ruby | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 33 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>sferik/twitter-ruby</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of sferik/twitter-ruby. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/sferik/twitter-ruby.git
#   cd twitter-ruby
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of sferik/twitter-ruby and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "sferik/twitter-ruby(\\.git)?\\b" \\
  && ok "origin remote is sferik/twitter-ruby" \\
  || miss "origin remote is not sferik/twitter-ruby (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "lib/twitter.rb" \\
  && ok "lib/twitter.rb" \\
  || miss "missing critical file: lib/twitter.rb"
test -f "lib/twitter/client.rb" \\
  && ok "lib/twitter/client.rb" \\
  || miss "missing critical file: lib/twitter/client.rb"
test -f "lib/twitter/rest/client.rb" \\
  && ok "lib/twitter/rest/client.rb" \\
  || miss "missing critical file: lib/twitter/rest/client.rb"
test -f "lib/twitter/rest/request.rb" \\
  && ok "lib/twitter/rest/request.rb" \\
  || miss "missing critical file: lib/twitter/rest/request.rb"
test -f "lib/twitter/factory.rb" \\
  && ok "lib/twitter/factory.rb" \\
  || miss "missing critical file: lib/twitter/factory.rb"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 33 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~3d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/sferik/twitter-ruby"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

A Ruby wrapper for the Twitter API v1.1 that provides object-oriented access to tweets, users, timelines, and direct messages through OAuth-authenticated HTTP requests. It translates Twitter's REST API responses into Ruby model objects (Tweet, User, DirectMessage, etc.) with chainable query methods and automatic rate-limit handling. Flat monolithic gem structure: lib/twitter/ contains model classes (base.rb, entities.rb, client.rb) and domain objects (direct_message.rb, direct_message_event.rb) organized by feature domain. lib/twitter/direct_messages/ and lib/twitter/entity/ subdirectories group related models. Examples in examples/ as markdown files. CI orchestrated via .github/workflows/ with Standard linter, Mutant mutation testing, and Steep type checking.

👥Who it's for

Ruby developers maintaining legacy Twitter integrations or building bots/monitoring tools that target API v1.1. The gem is primarily for teams stuck on v1.1 endpoints; new projects should use the modern X gem (also in this org) which supports both v1.1 and v2 APIs.

🌱Maturity & risk

Production-ready but in maintenance mode. The repo has comprehensive test coverage (mutation testing enabled via .mutant.yml), continuous CI/CD across lint/test/typecheck/yardstick workflows, and 970KB of Ruby code in the lib/ directory. However, it explicitly directs new projects to the X gem, indicating this is a stable legacy library rather than the focus of active feature development.

Low risk for existing users, moderate risk for new adopters. Dependency surface is small (only OAuth and HTTP gems typical for this era), but Twitter API v1.1 itself is deprecated and will eventually sunset. Single maintainer (sferik) across multiple gems in the org. No breaking changes likely but zero new feature development expected.

Active areas of work

Maintenance-mode operations: CI pipelines run on push (test.yml, lint.yml, typecheck.yml), gem pushes are automated (.github/workflows/gem_push.yml), and documentation builds to GitHub Pages (jekyll-gh-pages.yml). No active feature work visible; focus is keeping the v1.1 wrapper stable while steering users toward the X gem for new projects.

🚀Get running

git clone https://github.com/sferik/twitter-ruby.git
cd twitter-ruby
bundle install
bundle exec rspec

Then create a Twitter app at developer.x.com, configure credentials, and try examples from examples/ directory or bin/console REPL.

Daily commands:

bundle exec bin/console
# or run tests:
bundle exec rspec
# or lint:
bundle exec standardrb

The gem is a library, not a runnable app—require it and instantiate Twitter::REST::Client with credentials (see Configuration section in README).

🗺️Map of the codebase

  • lib/twitter.rb — Entry point that loads all Twitter gem modules and sets up the main namespace; every contributor must understand the gem's public API surface.
  • lib/twitter/client.rb — Core Client class that integrates REST and streaming APIs; the primary interface users interact with and the foundation for all API calls.
  • lib/twitter/rest/client.rb — REST API client implementation that manages all HTTP request routing and response handling; critical for understanding REST endpoint patterns.
  • lib/twitter/rest/request.rb — Low-level request abstraction handling authentication, encoding, and HTTP communication; essential for debugging API interaction issues.
  • lib/twitter/factory.rb — Object deserialization factory that transforms raw API responses into Ruby domain objects; key to understanding data modeling and response parsing.
  • lib/twitter/base.rb — Base class for all domain model objects providing common attribute access and introspection; foundation for 50+ model classes.
  • lib/twitter/error.rb — Error hierarchy and exception handling; critical for understanding failure modes and error recovery patterns.

🧩Components & responsibilities

  • REST::Client (Module inclusion, method_missing, factory delegation) — Routes API calls through verb methods (get, post, etc.); includes endpoint modules and manages response factories
    • Failure mode: Invalid endpoint calls or missing modules cause NoMethodError; routing errors fail fast
  • REST::Request — Low-level HTTP abstraction handling OAuth signing, parameter encoding, response parsing, and error classification

🛠️How to make changes

Add a new REST API endpoint

  1. Create a new module in lib/twitter/rest/ (e.g., lib/twitter/rest/my_feature.rb) that includes lib/twitter/rest/api.rb (lib/twitter/rest/my_feature.rb)
  2. Define endpoint methods using the @client.get/post/put/delete patterns inherited from API base class (lib/twitter/rest/my_feature.rb)
  3. Add the module to lib/twitter/rest/client.rb by including it in the Client class (lib/twitter/rest/client.rb)
  4. If the response returns new entity types, add factory methods to lib/twitter/factory.rb for object deserialization (lib/twitter/factory.rb)
  5. Create new model classes in lib/twitter/ inheriting from Base for any new entity types (lib/twitter/my_entity.rb)

Add a new domain model/entity type

  1. Create a new class inheriting from lib/twitter/base.rb with attributes matching the API response JSON (lib/twitter/my_entity.rb)
  2. Include lib/twitter/identity.rb mixin to enable ID-based equality (lib/twitter/my_entity.rb)
  3. If the entity has a created_at timestamp, include lib/twitter/creatable.rb (lib/twitter/my_entity.rb)
  4. Register the deserialization logic in lib/twitter/factory.rb's object_factory method (lib/twitter/factory.rb)

Handle a new API error condition

  1. Add a new error class to lib/twitter/error.rb inheriting from ClientError or ServerError (lib/twitter/error.rb)
  2. Update the HTTP response error mapping logic in lib/twitter/rest/request.rb to classify the error correctly (lib/twitter/rest/request.rb)
  3. If retry logic is needed, implement it in lib/twitter/rest/request.rb's perform method (lib/twitter/rest/request.rb)

🔧Why these technologies

  • HTTP/REST with OAuth 1.0a — Twitter API v1.1 requires OAuth 1.0a signing for all requests; implemented in REST::Request with header-based auth
  • Object-oriented domain modeling — Abstracts raw JSON responses into strongly-typed Ruby objects with standard equality and introspection
  • Factory pattern for deserialization — Polymorphic response parsing handles multiple entity types (Tweet, User, Media, Geo) and nested structures
  • Mixin-based composition — Reusable behaviors (Identity, Creatable, Entities) avoid deep inheritance hierarchies across 50+ model classes

⚖️Trade-offs already made

  • API v1.1 only (no v2 support)

    • Why: Maintains backward compatibility with existing codebases; v2 support moved to separate 'X' gem
    • Consequence: New projects or those needing v2 endpoints must use the X gem instead
  • Synchronous HTTP only (no built-in async)

    • Why: Simpler mental model and easier debugging; leaves concurrency to caller
    • Consequence: High-volume applications must wrap calls in their own threading/async framework
  • Factory-based model instantiation

    • Why: Centralizes parsing logic and handles polymorphic media/geo types elegantly
    • Consequence: No direct control over object construction; requires knowing factory conventions

🚫Non-goals (don't propose these)

  • API v2 support (delegated to the X gem)
  • Real-time streaming (separate streaming client in different gem)
  • Asynchronous request handling (sync-only; caller responsible for concurrency)
  • Authentication credential management (caller must provide OAuth tokens)
  • Local caching of API responses (caller responsible for cache strategy)

🪤Traps & gotchas

OAuth credentials must be set before instantiating Twitter::REST::Client or calls will fail silently/with 401. The gem targets API v1.1 which is frozen—new Twitter API methods will not be added. Direct message wrapper classes (welcome_message_wrapper.rb) have unusual nesting due to Twitter's v1.1 API structure, so read the wrapper logic before assuming direct_message.rb is sufficient. RSpec tests require valid mock responses matching Twitter's exact JSON structure; mutations will fail if tests don't cover edge cases.

🏗️Architecture

💡Concepts to learn

  • OAuth 1.0a request signing — Twitter API v1.1 requires OAuth 1.0a signatures on every request; the client.rb and underlying oauth gem implement this, so understanding signature generation is critical for debugging auth failures
  • Cursor-based pagination — Twitter uses opaque cursor tokens (not page numbers) for paginating large result sets; lib/twitter/cursor.rb wraps this pattern, essential for iterating followers/friends without hitting API limits
  • Rate limiting with backoff — The gem provides automatic rate-limit detection and backoff (mentioned in examples/RateLimiting.md); understanding Twitter's 15-minute window limits prevents your code from hammering endpoints
  • Polymorphic model deserialization — Twitter API responses nest entities (urls, hashtags) differently per endpoint; base.rb and entities.rb mixin solve this by auto-wrapping nested hashes into typed objects based on context
  • Mutation testing for code coverage — The CI runs Mutant (.mutant.yml) to ensure tests catch subtle bugs, not just code line coverage; this prevents false confidence from untested branches
  • Steep static type checking for Ruby — The repo uses Steep (Steepfile) to add TypeScript-like type contracts to Ruby without runtime overhead; critical for catching method signature errors in the client
  • Direct message event streaming — Direct messages v1.1 API differs from tweets; direct_message_event.rb and wrapper classes handle the nested structure and push semantics, important for building DM bots
  • sferik/x-ruby — Official successor gem in the same org; supports both Twitter API v1.1 and v2, this library's recommended upgrade path
  • oauth/oauth-ruby — The OAuth 1.0a library this gem depends on for signing Twitter API requests
  • httprb/http — HTTP client used for low-level transport in newer versions of this gem
  • rspec/rspec-core — Test framework used for all specs; understanding RSpec matchers is needed to modify tests
  • sferik/shim — Lightweight compatibility shim also maintained by sferik; relevant for understanding his approach to backward compatibility across gem versions

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive RSpec tests for lib/twitter/direct_messages/ subdirectory

The direct_messages folder contains 4 wrapper/model classes (welcome_message.rb, welcome_message_rule.rb, welcome_message_rule_wrapper.rb, welcome_message_wrapper.rb) but based on the repo's strong testing culture (mutant.yml, test.yml workflows), these likely lack corresponding spec files. Given the mutation testing workflow runs on every PR, adding thorough specs here would improve mutation score and prevent regressions in the DM API.

  • [ ] Create spec/twitter/direct_messages/welcome_message_spec.rb with tests for instantiation, attribute accessors, and any custom methods
  • [ ] Create spec/twitter/direct_messages/welcome_message_rule_spec.rb with similar coverage
  • [ ] Create spec/twitter/direct_messages/welcome_message_rule_wrapper_spec.rb testing wrapper behavior
  • [ ] Create spec/twitter/direct_messages/welcome_message_wrapper_spec.rb testing wrapper behavior
  • [ ] Ensure all specs pass mutant.yml requirements and achieve >90% coverage

Add integration tests for lib/twitter/geo/ and lib/twitter/media/ entity factories

The lib/twitter/geo/ and lib/twitter/media/ directories contain specialized factory classes (geo_factory.rb, media subtypes like photo.rb, video.rb, animated_gif.rb) but likely lack test coverage for the factory pattern behavior and polymorphic instantiation. These are critical for correct API response parsing, and the repo's yardstick workflow suggests strong documentation-driven development.

  • [ ] Create spec/twitter/geo_factory_spec.rb testing Point and Polygon instantiation from raw API responses
  • [ ] Create spec/twitter/media/photo_spec.rb, spec/twitter/media/video_spec.rb, spec/twitter/media/animated_gif_spec.rb testing media type detection and attributes
  • [ ] Add tests in spec/twitter/factory_spec.rb or new spec/twitter/media_factory_spec.rb for polymorphic media object creation
  • [ ] Verify geo_results.rb properly uses geo_factory (likely needs spec/twitter/geo_results_spec.rb)
  • [ ] Ensure typecheck.yml passes with proper type hints for factory return types

Complete missing YARD documentation for lib/twitter/entity/ and lib/twitter/entity_factory.rb

The yardstick.yml workflow enforces documentation standards, but the entity system (entities.rb, entity.rb, entity_factory.rb, and entity/* subdirectories with Hashtag, Symbol, Uri, UserMention classes) likely has incomplete @param, @return, and @example tags. The .yardopts file indicates strict documentation requirements, making this a high-value improvement.

  • [ ] Review lib/twitter/entity.rb and add missing @param/@return/@example tags for all public methods
  • [ ] Add comprehensive YARD docs to lib/twitter/entity_factory.rb explaining entity type detection and instantiation logic
  • [ ] Document each entity subclass (Hashtag, Symbol, Uri, UserMention) with examples of how to access entity-specific attributes
  • [ ] Add @example blocks showing real-world usage of entity objects extracted from tweet responses
  • [ ] Run yardstick.yml workflow to verify 100% documentation coverage and adjust as needed

🌿Good first issues

  • Add type signatures to lib/twitter/cursor.rb for the pagination model—it's referenced in Steepfile but lacks RBS annotations; this tests Steep setup without changing logic
  • Write integration examples in examples/ for the direct messages API using welcome_message.rb and welcome_message_rule.rb—currently no markdown guide exists, only class files
  • Add missing yard docstring examples to lib/twitter/entity/ models (hashtag.rb, url.rb, etc.) showing how to extract entities from Tweet objects—would improve yardstick coverage

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 4fab71a — Bump rubygems/configure-rubygems-credentials from 1.0.0 to 2.0.0 (dependabot[bot])
  • 1142bc9 — Prepare for version 8.3.1 release (sferik)
  • 2c47097 — Enable operators: full in Mutant and kill all surviving mutants (sferik)
  • 13e5f29 — Kill mutants on streaming client proxy fallback (sferik)
  • 57a31d5 — Consume HTTP gem's shipped RBS signatures (sferik)
  • be1d25b — Remove redundant steep:ignore comments (sferik)
  • b7f2377 — Bump actions/upload-pages-artifact from 4 to 5 (dependabot[bot])
  • 9d18ac3 — Ignore .mutant directory (sferik)
  • 8c02c71 — Bump actions/deploy-pages from 4 to 5 (dependabot[bot])
  • 9cec045 — Bump actions/configure-pages from 5 to 6 (dependabot[bot])

🔒Security observations

The twitter-ruby gem is a well-maintained library with good CI/CD practices (linting, type checking, mutation testing). However, security posture is moderately strong with some concerns: (1) dependency audit visibility is missing, (2) credential handling in an API wrapper requires careful implementation to prevent exposure, (3) custom encoding/argument processing logic should be reviewed for injection vulnerabilities, and (4) explicit security disclosure policy is absent. No obvious hardcoded secrets or critical misconfigurations were detected in the provided file structure. Recommendations focus on adding security-specific testing, improving credential handling documentation, and establishing a vulnerability disclosure process.

  • Medium · Missing Dependency File — Gemfile. The Gemfile content was not provided for analysis. Without visibility into the dependencies, it's impossible to identify vulnerable gem versions, outdated packages, or known security issues in transitive dependencies. Fix: Provide the Gemfile and Gemfile.lock for dependency vulnerability scanning. Use 'bundle audit' or 'dependabot' to regularly check for vulnerable gem versions.
  • Medium · Potential API Credential Exposure Risk — lib/twitter/client.rb, lib/twitter/rest/client.rb. This is a Twitter API wrapper library that handles authentication tokens and API credentials. The codebase likely processes sensitive credentials (API keys, access tokens, bearer tokens). If not properly managed, these could be logged, cached insecurely, or exposed in error messages. Fix: Ensure credentials are never logged, stored in plain text, or included in error messages. Use environment variables for credential management. Implement credential scrubbing in logs and error handling.
  • Low · No SECURITY.md File — Repository root. There is no SECURITY.md file visible in the repository root. This makes it difficult for security researchers to report vulnerabilities responsibly. Fix: Create a SECURITY.md file that includes information about supported versions, how to report security vulnerabilities, and the response timeline.
  • Low · Form Encoder Component — lib/twitter/rest/form_encoder.rb. The presence of 'form_encoder.rb' suggests custom form encoding logic. Custom encoding implementations can have encoding/decoding mismatches leading to injection vulnerabilities if not properly validated. Fix: Review the form encoder implementation to ensure it properly encodes all special characters, uses standard URL encoding (percent encoding), and validates input length. Prefer using Ruby's built-in URI encoding utilities.
  • Low · Arguments Processing Module — lib/twitter/arguments.rb. Custom argument processing logic in 'arguments.rb' could potentially be vulnerable to injection if user inputs are not properly sanitized before being passed to API endpoints. Fix: Ensure all user inputs in the arguments module are validated and sanitized. Use allowlists for expected parameter types and values. Never construct API calls by string concatenation.
  • Low · No Visible Security Tests — .github/workflows/. While CI/CD workflows are present (lint.yml, test.yml, typecheck.yml), there's no evidence of security-focused testing like SAST, dependency scanning, or penetration testing workflows. Fix: Add GitHub Advanced Security scanning, enable Dependabot alerts, and consider adding SAST tools like Brakeman or RuboCop security plugins to the CI/CD pipeline.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · sferik/twitter-ruby — RepoPilot