RepoPilotOpen in app →

opal/opal

Ruby ♥︎ JavaScript

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 2d ago
  • 4 active contributors
  • MIT licensed
Show 4 more →
  • CI configured
  • Tests present
  • Small team — 4 contributors active in recent commits
  • Concentrated ownership — top contributor handles 71% 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/opal/opal)](https://repopilot.app/r/opal/opal)

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/opal/opal on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: opal/opal

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/opal/opal 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 2d ago
  • 4 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Small team — 4 contributors active in recent commits
  • ⚠ Concentrated ownership — top contributor handles 71% 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 opal/opal repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/opal/opal.

What it runs against: a local clone of opal/opal — 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 opal/opal | 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 ≤ 32 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>opal/opal</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of opal/opal. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/opal/opal.git
#   cd opal
#
# 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 opal/opal and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "opal/opal(\\.git)?\\b" \\
  && ok "origin remote is opal/opal" \\
  || miss "origin remote is not opal/opal (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 "Opalfile" \\
  && ok "Opalfile" \\
  || miss "missing critical file: Opalfile"
test -f "README.md" \\
  && ok "README.md" \\
  || miss "missing critical file: README.md"
test -f "Rakefile" \\
  && ok "Rakefile" \\
  || miss "missing critical file: Rakefile"
test -f "Gemfile" \\
  && ok "Gemfile" \\
  || miss "missing critical file: Gemfile"
test -f "HACKING.md" \\
  && ok "HACKING.md" \\
  || miss "missing critical file: HACKING.md"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 32 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~2d)"
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/opal/opal"
  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

Opal is a Ruby-to-JavaScript source-to-source compiler that transpiles Ruby code into runnable JavaScript with a complete implementation of Ruby's corelib and stdlib. It enables developers to write Ruby in the browser and Node.js environments, bridging the gap between server-side Ruby semantics and client-side JavaScript execution. The project includes a full compiler toolchain (visible in the 3.8MB of Ruby code) and JavaScript runtime libraries (483KB of JS). Monolithic Ruby gem structure: the main compiler lives in the root with Rakefile and Opalfile as entry points, benchmarking suites in /benchmark-ips and /benchmark for performance tracking, GitHub workflows in .github/workflows for CI, and linting/code quality configs (.rubocop.yml, .codeclimate.yml) at the root. The .gitmodules file suggests git submodules for dependencies, and the Gemfile drives the build system.

👥Who it's for

Full-stack Ruby developers who want to share code between server and browser, Ruby teams building web applications who prefer Ruby syntax over JavaScript, and developers maintaining large codebases who want to avoid learning/maintaining two languages. Contributors are typically experienced Rubyists interested in compiler design and language interoperability.

🌱Maturity & risk

Opal is actively maintained and production-ready. The codebase shows maturity through comprehensive testing infrastructure (.rspec config, Rakefile), CI/CD setup (.github/workflows/build.yml), code quality tooling (.codeclimate.yml, .rubocop.yml with 1600+ lines of linting rules), and extensive documentation (HACKING.md, CONTRIBUTING.md, .yardopts for YARD docs). The README shows stable versioning via gem badges and Open Collective funding, indicating sustained community backing.

The project depends heavily on the Ruby-to-JavaScript transpilation pipeline, making breaking changes in Ruby semantics or JavaScript standards potentially high-impact. Risk is mitigated by active CI/CD (build.yml), clear versioning, and CHANGELOG/UNRELEASED tracking, but the single-language focus (97% Ruby codebase) means compiler bugs directly affect all users. The presence of benchmark-ips/ and benchmark/ directories suggests performance is a known concern area.

Active areas of work

Active development is visible through UNRELEASED.md tracking upcoming changes, the build.yml GitHub workflow showing regular CI runs, and the presence of both bug-report.md and feature_request.md issue templates. The .github/sponsors directory with multiple sponsor logos (nebulab, testmu-ai) indicates ongoing funding and community prioritization. The Guardfile suggests automated test-on-save workflows for contributors.

🚀Get running

Clone and set up: git clone https://github.com/opal/opal.git && cd opal && bundle install. The Gemfile and Rakefile are present, so use bundle exec rake to run the test suite (configured in .rspec). Start a REPL or test compilation with bundle exec opal (if a bin script exists) or check Rakefile tasks via bundle exec rake -T.

Daily commands: Execute bundle exec rake to run the full test suite (RSpec configured in .rspec). For development with auto-rerun, use bundle to start Guardfile watcher. Individual benchmarks are runnable as ruby benchmark-ips/bm_*.rb or ruby benchmark/bm_*.rb. The Opalfile may define build tasks; check with bundle exec rake -T.

🗺️Map of the codebase

  • Opalfile — Opal's build configuration file defining how Ruby source is compiled to JavaScript; essential for understanding the compilation pipeline.
  • README.md — Primary documentation explaining Opal as a Ruby-to-JavaScript compiler; required reading for understanding project scope and capabilities.
  • Rakefile — Build task definitions for the Ruby project; crucial for setting up development environment and running tests.
  • Gemfile — Ruby gem dependencies specification; defines all external libraries needed for the Opal compiler and toolchain.
  • HACKING.md — Developer guide for contributing to Opal; explains architecture, compilation stages, and how to modify the compiler.
  • .github/workflows/build.yml — CI/CD pipeline configuration; shows how code is tested and built automatically on every commit.
  • CONTRIBUTING.md — Guidelines for submitting contributions; establishes coding standards and review process for the project.

🧩Components & responsibilities

  • Compiler Frontend (Parser & Lexer) (Opal::Parser, Whitequark Parser gem) — Tokenizes and parses Ruby source code, produces AST for downstream transformation
    • Failure mode: Syntax errors in Ruby code; parser failure halts compilation with error messages
  • AST Transformation & Optimization (Opal::AST, Opal::Optimizers) — Converts Ruby AST to JavaScript-compatible form; applies compiler optimizations and inlining
    • Failure mode: Unsupported Ruby features cause compilation errors; incorrect transformation produces buggy JavaScript
  • Code Generation (Opal::CodeGen, ERB templates) — Emits final JavaScript code from transformed AST; handles scoping, variable allocation, method dispatch
    • Failure mode: Runtime errors in generated code; incorrect variable scoping or method resolution
  • Standard Library Implementation (JavaScript, Ruby stdlib semantics) — Provides JavaScript implementations of Ruby core classes (Array, Hash, String, Enumerable, etc.)
    • Failure mode: Missing or incorrect method implementations cause NoMethodError at runtime
  • Build System & CLI (Rake, Opalfile configuration) — Orchestrates compilation workflow; manages build targets, file I/O, and dependency resolution
    • Failure mode: Build failures due to missing dependencies, file not found, or invalid configuration

🔀Data flow

  • Ruby source fileOpal Parser — Developer writes Ruby code; parser tokenizes and builds AST representation
  • Opal ParserAST Transformer — AST flows through transformation pipeline; Ruby semantics converted to JavaScript-compatible form
  • AST TransformerOptimizer — Transformed AST passed to optional optimization stage for inlining and constant folding
  • Optimized ASTCode Generator — Final AST emitted as JavaScript code string via template rendering
  • Code GeneratorJavaScript Output File — undefined

🛠️How to make changes

Add a new Ruby standard library feature

  1. Create a new Ruby source file implementing the feature in the appropriate stdlib directory (lib/opal/stdlib/)
  2. Add the feature to the build manifest in Opalfile to include it in compilation (Opalfile)
  3. Write tests following RSpec conventions (spec/)
  4. Document the implementation in HACKING.md or inline comments (HACKING.md)

Modify the Ruby-to-JavaScript compiler

  1. Review the compiler architecture in HACKING.md to understand AST transformation stages (HACKING.md)
  2. Locate the compiler code in the lib/opal/compiler directory structure (lib/opal/compiler/)
  3. Add or modify the transpilation rules for your language feature (lib/opal/compiler/)
  4. Add test cases to verify correct JavaScript output (spec/)
  5. Run the full test suite via Rakefile tasks (Rakefile)

Optimize compiler performance

  1. Create a new benchmark file in the benchmark or benchmark-ips directory to measure the specific operation (benchmark-ips/)
  2. Run benchmarks to establish baseline performance (Rakefile)
  3. Identify the compiler or corelib code responsible for the bottleneck (lib/)
  4. Apply optimizations and re-run benchmarks to measure improvement (benchmark/)

🔧Why these technologies

  • Ruby language — Opal itself is a Ruby project; eating its own dog food demonstrates compiler correctness and enables self-hosting capabilities.
  • RSpec testing framework — Provides comprehensive test coverage for compiler correctness and generated JavaScript behavior.
  • Rakefile build system — Native Ruby task runner simplifies build pipeline and allows scripting in the same language as the compiler.
  • GitHub Actions CI/CD — Automates testing across multiple Ruby versions and ensures compiler quality on every commit.

⚖️Trade-offs already made

  • Source-to-source compilation (Ruby → JavaScript) vs bytecode interpretation

    • Why: Enables better JavaScript interoperability, smaller runtime footprint, and browser-native execution.
    • Consequence: Requires comprehensive standard library re-implementation in JavaScript; some Ruby semantics cannot be perfectly replicated.
  • Full Ruby stdlib implementation in JavaScript vs runtime proxy

    • Why: Provides Ruby developers a familiar API surface and enables seamless library code reuse.
    • Consequence: Significant code duplication and maintenance burden; some Ruby gems cannot be converted automatically.
  • Single-pass compilation with optimization flags vs multi-pass pipeline

    • Why: Faster compilation times and simpler architecture for the compiler implementation.
    • Consequence: Limited optimization opportunities; developers must choose between debug and optimized output modes.

🚫Non-goals (don't propose these)

  • Full Ruby 3.x syntax compatibility - focuses on core language features; some advanced metaprogramming and recent syntax not supported
  • Real-time interactive shell (REPL) - designed as a compilation target, not an interactive interpreter
  • Performance parity with native Ruby - JavaScript runtime inherently slower; targets correctness over speed
  • Non-browser environments - primarily targets web browsers; Node.js support is secondary

🪤Traps & gotchas

The .gitmodules file indicates git submodules are used for dependencies—ensure git clone --recursive or run git submodule update --init --recursive after cloning. The .codeclimate.yml and .rubocop.yml are strict; local changes must pass both linters before CI acceptance. The benchmark suites (benchmark-ips and benchmark) may require specific Ruby versions or external tools to run accurately; check each directory's README. The compiler's output JavaScript must be compatible with the target runtime version, which may require setting environment variables or build flags (check Opalfile and Rakefile for these).

🏗️Architecture

💡Concepts to learn

  • Abstract Syntax Tree (AST) transformation — Opal's core function is walking a Ruby AST and emitting JavaScript; understanding AST structure is essential for adding compiler features or debugging transpilation bugs
  • Source-to-source compilation (transpilation) — Opal is a transpiler, not an interpreter; it reads Ruby source and outputs JavaScript source, which is fundamentally different from runtime interpretation and affects how it handles metaprogramming
  • Runtime semantics preservation — Ruby and JavaScript have different object models, scoping rules, and type coercion; Opal's stdlib and runtime shims must faithfully implement Ruby semantics in JavaScript, which is non-trivial (e.g., integer vs. float handling)
  • Scope and closure handling in transpilation — Ruby's block syntax and closure semantics differ from JavaScript's; Opal must generate correct JavaScript closures and scope chains, visible in the compiler's handling of blocks, procs, and lambdas
  • Symbol interning and identity — Ruby symbols are interned (same symbol always has same object identity); the codebase has specific benchmarks (bm_js_symbols_vs_strings.rb) for this because JavaScript doesn't have native symbol identity semantics
  • Metaprogramming constraints in static compilation — Ruby's eval, define_method, and method_missing can't be fully supported in a transpiler; Opal must detect and warn about dynamic metaprogramming that won't work after compilation
  • Performance profiling and benchmarking (IPS methodology) — The benchmark-ips/ directory uses iterations-per-second benchmarking; understanding this is critical for evaluating compiler performance and runtime efficiency of generated JavaScript
  • jruby/jruby — Alternative Ruby implementation targeting the JVM; shares the same goal of running Ruby code outside the standard MRI runtime but compiles to bytecode instead of JavaScript
  • ruby2js/ruby2js — Another Ruby-to-JavaScript transpiler with a more lightweight approach; direct competitor in the same problem space with different design trade-offs
  • rails/rails — Primary ecosystem consumer; Rails apps using Opal can compile Ruby views/models to JavaScript for browser execution via Opal integration
  • rack/rack — Core Ruby web middleware that Opal-compiled code often interoperates with on the server side; important for full-stack Ruby workflows
  • pakyow/pakyow — Modern Ruby web framework that leverages Opal for client-side Ruby code; built on top of Opal's transpilation capabilities

🪄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 benchmarking CI workflow for performance regressions

The repo has extensive benchmark files (benchmark/ and benchmark-ips/ directories) but no automated CI workflow to track performance metrics across commits. This is critical for a compiler project where performance regressions can silently degrade the generated JavaScript. A GitHub Action could run benchmarks on PRs and compare against main branch.

  • [ ] Create .github/workflows/benchmark.yml to run benchmark scripts on PRs
  • [ ] Add benchmark result comparison logic using benchmark/benchmarks output
  • [ ] Document benchmark results in PR comments (reference benchmark/* and benchmark-ips/* existing scripts)
  • [ ] Add baseline metrics file to track historical performance data

Implement missing stdlib test coverage for Ruby corelib methods

The HACKING.md and file structure suggest Opal implements Ruby corelib/stdlib, but there's no visible comprehensive test suite directory structure in the provided listing. A new contributor could add systematic test coverage for specific stdlib modules (e.g., String, Array, Hash extensions) that lack tests, following the existing .rspec configuration.

  • [ ] Audit existing test files to identify missing stdlib method coverage
  • [ ] Create spec/stdlib/ directory structure (e.g., spec/stdlib/string_spec.rb, spec/stdlib/array_spec.rb)
  • [ ] Add tests for commonly-used methods in opal/opal corelib implementation
  • [ ] Ensure tests integrate with existing .rspec configuration and Rakefile test tasks

Add ESLint/code quality enforcement for JavaScript output validation

The repo's .codeclimate.yml, .rubocop.yml suggest quality standards, but there's no visible workflow validating the generated JavaScript output against ESLint or similar standards. This is critical since Opal generates JS that end-users depend on. A new contributor could set up automated linting of compiler output.

  • [ ] Create .github/workflows/js-lint.yml to run ESLint on sample compiled output
  • [ ] Configure ESLint rules in a new .eslintrc.json (reference existing .rubocop.yml patterns)
  • [ ] Add generated JavaScript validation to build.yml or as separate workflow
  • [ ] Document expected JavaScript style in CONTRIBUTING.md (see existing file)

🌿Good first issues

  • Add RSpec test coverage for edge cases in the JavaScript output generator—look for compiler output methods in lib/ that lack corresponding test cases in spec/, especially around numeric type handling and symbol-to-string conversion.: Compiler correctness is critical; improving test coverage prevents subtle bugs in transpiled code.
  • Add micro-benchmarks in benchmark-ips/ for recent Ruby standard library additions—pick a new method added to Enumerable or Array and create bm_*.rb following existing patterns (e.g., bm_array_pop_1.rb) to track performance.: Performance regressions are easy to miss; benchmarking stdlib methods early catches issues before releases.
  • Improve HACKING.md with concrete examples of adding a new Ruby builtin method—trace through an existing method in lib/ and document the transpilation pipeline step-by-step for contributors.: Low barrier to contribution; new developers need clear examples to add features without needing to reverse-engineer the compiler.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • abf1582 — Merge pull request #2786 from opal/hmdne/ruby-4-ostruct (hmdne)
  • 91055ee — test: add ostruct for Ruby 4 (hmdne)
  • ad365b1 — Merge pull request #2785 from opal/hmdne/fix-lint-issues (hmdne)
  • 0e71520 — Merge pull request #2784 from opal/hmdne/rename-js-raw-error-to-opal-raw-error (hmdne)
  • 2e2069a — runtime: remove stale rubocop disables (hmdne)
  • c5eab2a — corelib/error: fix JS::Error deprecation to return Opal::Raw::Error (hmdne)
  • 7e78aa5 — Merge pull request #2781 from opal/hmdne/optimize-rspec (hmdne)
  • ad5982b — spec: reduce rspec runtime overhead (hmdne)
  • 06f10cc — Merge pull request #2775 from opal/elia/fix-bigdecimal-warning (elia)
  • 07183b3 — Merge pull request #2780 from opal/elia/sponsor (elia)

🔒Security observations

  • High · Outdated WebSocket Dependency — package.json - dependencies.ws. The 'ws' package version ^7.2.0 is outdated and may contain known vulnerabilities. Current stable version is 8.x or higher. WebSocket libraries are critical for real-time communication and should be kept current. Fix: Update 'ws' to the latest stable version (^8.13.0 or higher). Run 'npm audit' to check for known vulnerabilities and apply security patches.
  • High · Outdated Commander CLI Library — package.json - dependencies.commander. The 'commander' package version 2.11.x is severely outdated (released ~2017). This package handles CLI argument parsing and may contain security vulnerabilities related to argument injection or improper input handling. Fix: Update 'commander' to the latest version (^11.0.0 or higher). Test CLI functionality after upgrade as there may be breaking changes.
  • High · Multiple Outdated Babel Dependencies — package.json - devDependencies (babel-*). Babel packages (babel-core@6.26.3, babel-loader@8.x.x, babel-preset-env@1.7.0) are from 2017-2018 era. Babel 6 is no longer maintained and may contain unpatched security issues. These are critical for code transpilation. Fix: Migrate to Babel 7.x or later. Update babel-core to @babel/core, babel-loader to ^9.x, and babel-preset-env to @babel/preset-env@latest.
  • Medium · Outdated ESLint Version — package.json - devDependencies.eslint. ESLint version ^8.8.0 is outdated (current is 8.5x+). While the 8.x series is still maintained, using an older point release may miss critical linting rules and security checks. Fix: Update ESLint to the latest version in the 8.x series (^8.56.0) or migrate to 9.x if compatible with your setup.
  • Medium · Outdated Mocha Test Framework — package.json - devDependencies.mocha. Mocha version ^9.2.0 is outdated (current is 10.x+). Outdated test frameworks may lack security enhancements and bug fixes critical for reliable security testing. Fix: Update Mocha to the latest stable version (^10.2.0 or higher).
  • Medium · Outdated Webpack Build Tool — package.json - devDependencies.webpack. Webpack version ^5.39.0 is outdated (released 2021). Webpack handles bundling and may have security implications for code optimization and plugin handling. Fix: Update Webpack to ^5.90.0 or migrate to Webpack 6.x if stable and compatible with your configuration.
  • Low · Missing npm Audit Configuration — package.json - scripts. No 'npm-audit' or security audit configuration found in package.json. Regular security audits are essential for identifying vulnerable dependencies. Fix: Add 'audit' script: '"audit": "npm audit --audit-level=moderate"' and integrate into CI/CD pipeline for regular security checks.
  • Low · No Security Policy File — Repository root. No SECURITY.md or security policy file found in the repository root. This makes it unclear how to report security vulnerabilities responsibly. Fix: Create a SECURITY.md file with vulnerability disclosure policy, contact information, and responsible disclosure guidelines.
  • Low · Missing Package Lock File Verification — Repository root. While package.json is present, the analysis doesn't show if package-lock.json or yarn.lock is version-controlled and up-to-date. Lock files are crucial for reproducible builds and security. Fix: Ensure package-lock.json is committed to version control and regularly updated. Consider using 'npm ci' in CI/CD instead of 'npm install'.

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 · opal/opal — RepoPilot