This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
OCRAN (One-Click Ruby Application Next) is a Windows executable builder for Ruby applications. It packages Ruby scripts, the Ruby interpreter, gems, and DLLs into a single .exe file. This is a fork of OCRA, maintained for Ruby 3.2+ compatibility.
rake build # Compile C stub executables (stub.exe, stubw.exe, edicon.exe)Requirements for building stubs:
- Windows with RubyInstaller DevKit (mingw-w64)
- Run
bin/setupfirst to install dependencies and build stubs initially
rake test # Run full test suite (all tests in test/test_ocra.rb)
rake test_single[test_name] # Run a single test (e.g., rake test_single[helloworld])
ruby -Ilib:test test/test_ocra.rb --name test_helloworld # Alternative for single testbin/setup # One-time setup: install Bundler, dev gems, and build stubs
bin/console # Launch IRB with Ocran preloadedManual tests are in test/manual/ and do NOT run during rake test:
ruby test/manual/codesigning_test.rb # Test real Windows code signing
ruby test/manual/codesigning_test.rb app.exe # Test signing on specific exeSee test/manual/README.md for requirements (Windows SDK, admin privileges).
OCRAN operates in two distinct phases:
1. Build Time (Ruby layer):
- Entry point:
exe/ocran→lib/ocran/runner.rb - Runs the target Ruby script to detect dependencies (
Kernel#require,Kernel#load) - Analyzes gems, DLLs, and resource files
- Generates a custom opcode format with instructions (create directories, extract files, set env vars)
- Packages everything into a single
.execontaining:- The C stub executable (stub.exe or stubw.exe)
- The opcode data with all files
- OCRAN signature (4 bytes:
0x41, 0xb6, 0xba, 0x4e)
2. Runtime (C stub layer):
- Entry point:
src/stub.c→main() - Reads its own executable file to find OCRAN signature
- Extracts Ruby interpreter and scripts to temp directory (or install directory with
--chdir-first) - Sets
OCRAN_EXECUTABLEenvironment variable - Launches the Ruby script with proper environment
runner.rb: Main orchestrator, parses command-line optionsbuild_facade.rb: High-level build process coordinatorlibrary_detector.rb: Detects dependencies by running the target scriptstub_builder.rb: Creates the final executable by:- Copying the appropriate stub (console or windowed)
- Clearing invalid PE security headers (important for code signing)
- Writing opcode instructions
- Appending packed data
gem_spec_queryable.rb: Handles gem dependency resolution and file selectioninno_setup_script_builder.rb: Generates Inno Setup installers
Modularized C code that runs inside the final .exe:
stub.c: Main entry point, orchestrates extraction and executionunpack.c: Core unpacking logic:- Parses opcode format
- Handles code-signed executables (PE header analysis)
- Supports LZMA compression/decompression
- Code signing support: Detects and handles Windows Authenticode signatures via PE header inspection
system_utils.c: Windows API wrappers (file mapping, path utilities)inst_dir.c: Manages extraction directory lifecyclescript_info.c: Stores and retrieves script execution detailserror.c: Error handling and debug output
The packed data uses a custom bytecode format with operations:
OP_CREATE_DIRECTORY(1): Create extraction directoryOP_CREATE_FILE(2): Extract file with contentOP_SETENV(3): Set environment variableOP_SET_SCRIPT(4): Specify script to execute
Each operation is followed by size-prefixed strings and binary data.
OCRAN executables support Windows Authenticode code signing:
- Build time:
stub_builder.rbclears invalid security directory entries from PE headers - Runtime:
unpack.cdetects digital signatures and searches for OCRAN signature before the security entry - Testing: Fake code signer in
test/fake_code_signer.rbsimulates signing for automated tests - Manual testing:
test/manual/codesigning_test.rbtests real signing with Windows SDK
The codebase handles PE32+ (64-bit) executables:
- Security directory is at offset:
PE_offset + 4 + 20 + 128(PE sig + FILE_HEADER + partial OPTIONAL_HEADER) - Different header sizes: PE32 (224 bytes) vs PE32+ (240 bytes)
- Magic field (0x10b = PE32, 0x20b = PE32+) determines architecture
exe/ocran # Executable entry point
lib/ocran/runner.rb # Main orchestrator
lib/ocran/stub_builder.rb # Executable builder
src/stub.c # C stub main()
src/unpack.c # Core unpacking logic with code signing support
share/ocran/ # Prebuilt binaries (stub.exe, stubw.exe, edicon.exe, lzma.exe)
test/test_ocra.rb # Main test suite
test/manual/ # Manual tests (not in rake test)
OCRAN detects dependencies by actually running the target script at build time:
--no-dep-run: Skip running script (requires--add-all-coreand--gem-full)--no-autoload: Don't followautoloaddeclarations--no-autodll: Disable automatic DLL detection
Four modes control what gets included from gems:
--gem-minimal: Only loaded scripts--gem-guess: Loaded scripts + important files (DEFAULT)--gem-all: All scripts + important files--gem-full: Everything in gem directory
Three stub executables are built from C source:
- stub.exe: Console mode (uses ruby.exe)
- stubw.exe: Windowed mode (uses rubyw.exe, no console window)
- edicon.exe: Utility to change icons in executables
test/test_ocra.rb: Main test class (TestOcran)test/fixtures/: Test Ruby scripts (helloworld, writefile, etc.)test/fake_code_signer.rb: Simulates code signing for teststest/manual/: Manual tests requiring special setup
Tests are named test_* methods in TestOcran:
rake test_single[helloworld] # Runs test_helloworld
ruby -Ilib:test test/test_ocra.rb --name test_codesigning_supportEach fixture in test/fixtures/ is a minimal Ruby project used to test specific features:
helloworld/: Basic functionalitywritefile/: File I/O operationsautoload/: Autoload detectionmultibyte_*/: UTF-8 path handling
When changing src/*.c files:
- Edit the C source files
- Run
rake buildto recompile - New stubs are copied to
share/ocran/ - Test with
rake testor build a test executable
The Makefile uses gcc with these key flags:
-DWITH_LZMA: Enable LZMA compression support-s: Strip symbols-mwindows: Create windowed application (for stubw.exe)
OCRAN requires bundler for test execution (test/test_ocra.rb uses Bundler.with_original_env). The current setup uses:
- minitest 6.0+
- hoe 4.6+ (build system)
- fiddle 1.0+ (FFI for Windows APIs in Ruby)
To add a new opcode to the packing format:
- Define constant in both
lib/ocran/stub_builder.rbandsrc/unpack.h - Add write method in
stub_builder.rb(e.g.,write_opcode(OP_NEW_OPERATION)) - Add case handler in
src/unpack.cinprocess_opcode()function - Update
OP_MAXif tracking opcode count
Use existing wrappers in src/system_utils.c for Windows operations. Create new wrappers following the pattern:
- Error checking with detailed DEBUG messages
- Proper resource cleanup (handles, memory maps)
- Return bool for success/failure
When working with PE executables, use test/fake_code_signer/pe_wrapper.rb as reference for header offsets and structure. Always validate:
- Architecture (PE32 vs PE32+) using magic field
- Bounds checking for all offsets
- File size consistency