This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
openbox is a Ruby gem: a zero-configuration container entrypoint for Rack/Rails apps. Host apps run bin/openbox server (etc.) as their Docker ENTRYPOINT. Only runtime deps are thor and dotenv; Rails is deliberately never loaded by openbox itself to keep boot fast.
bin/setup # bundle install
bundle exec rake # rspec (default task), SimpleCov enabled
bundle exec rspec spec/openbox/runtime_spec.rb # single file
bundle exec rspec spec/openbox/runtime_spec.rb:12 # single example
bundle exec rubocop # lint (CI fails on any offense; TargetRubyVersion 2.5, NewCops enabled)
bundle exec rubocop -A path/to/file.rb # autocorrect changed Ruby files only
bundle exec rake install # install gem locally
bundle exec rake release # bump lib/openbox/version.rb first; tags + pushes to rubygemsGit hooks are managed by overcommit (.overcommit.yml): RuboCop (warnings fail), trailing whitespace, bundle-audit. CI runs RuboCop plus RSpec on Ruby 2.6–3.1.
Boot order matters because command registration is conditional on the host app's Gemfile:
exe/openboxrequiresopenbox, thenrequires every file under the host app'slib/openbox/commands/**/*.rb(custom commands), then callsOpenbox::Entrypoint.start(ARGV).lib/openbox.rbdefines two lazily built, mutex-guarded singletons:Openbox.runtime→Runtime.new(Bundler.definition.current_dependencies).has?/selectonly consider gems in the:defaultgroup plus the group named byRAILS_ENV/RACK_ENV.Openbox.database→Database.ensure_connection!is a no-op unlesspgormysql2is a dependency; otherwise it retries connecting toDATABASE_URLfor 30s thenexit 1.- It requires
openbox/entrypointlast, so the singletons exist when commands register.
Openbox::Entrypoint < Thorrequires each built-in command file. Each file definesOpenbox::Commands::X < Openbox::Command(aThor::Group) and callsOpenbox::Entrypoint.register(...)only ifOpenbox.runtime.has?(...)for the relevant gem. So the same gem exposes different subcommands depending on the host app.
Openbox::Command#before_execute loads Docker Swarm secret files (/run/secrets/<name> for each name in SWARM_SECRETS) via Dotenv. Every built-in execute calls Openbox.database.ensure_connection! first, then execs (replaces the process) or systems a bundle exec ... command. Server additionally invokes Migrate when AUTO_MIGRATION is set and picks rails server -b 0.0.0.0 vs rackup -o 0.0.0.0 based on Openbox.runtime.rails?.
Create lib/openbox/commands/<name>.rb following the existing pattern (class + guarded register), then add the require to lib/openbox/entrypoint.rb. Update the commands table in README.md.
Specs construct Runtime directly with stub dependency objects rather than relying on Bundler; Database specs stub Openbox.runtime. spec_helper uses disable_monkey_patching!, so use RSpec.describe, not bare describe.