Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false

- name: Validate git-cliff changelog generation
uses: orhun/git-cliff-action@v4
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/commitlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false

- name: Set up Ruby
uses: ruby/setup-ruby@v1
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ jobs:
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
persist-credentials: false

- name: Set up Ruby
uses: ruby/setup-ruby@v1
Expand Down
9 changes: 6 additions & 3 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
ruby-version: ["3.1.3", "3.4", "4.0.3"]
ruby-version: ["3.3", "3.4", "4.0.3"]

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
persist-credentials: false

- name: Set up Ruby
uses: ruby/setup-ruby@v1
Expand All @@ -33,9 +35,10 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false

- name: Validate git-cliff changelog generation
uses: orhun/git-cliff-action@v4
Expand Down
2 changes: 1 addition & 1 deletion .standard.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ruby_version: 3.1
ruby_version: 3.3
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
experiments.
- Add isolated execution defaults, timeout handling, and process-group cleanup.
- Add live smoke coverage for plain-text and structured-output requests.
- Add CI, Conventional Commit checks, changelog validation, and tag-driven
RubyGems trusted publishing.
- Document installation, configuration, limitations, troubleshooting,
contribution, security, and release procedures.

### Fixed

- Disable unnecessary Codex shell snapshots to prevent Bash process explosions
during completion-only runs.
- Align the documented Ruby requirement, CI matrix, syntax target, and locked
development dependencies on Ruby 3.3 or newer.
30 changes: 30 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Code of Conduct

## Our standard

We are committed to a welcoming, respectful, and harassment-free community.
Examples of positive behavior include empathy, constructive feedback, respect
for differing viewpoints, and taking responsibility for mistakes.

Unacceptable behavior includes harassment, discriminatory language, personal
attacks, deliberate intimidation, publishing another person's private
information, or conduct that would reasonably be considered inappropriate in a
professional setting.

## Enforcement

Project maintainers may remove, edit, or reject comments, commits, issues, and
other contributions that violate this standard. They may temporarily or
permanently restrict participation when necessary to protect the community.

Report conduct concerns privately to `devel@ethos-link.com`. Maintainers will
respect the reporter's privacy and evaluate reports fairly. Retaliation against
someone who reports a concern is prohibited.

## Scope

This policy applies in project spaces and when an individual is publicly
representing the project or its community.

This policy is adapted from the
[Contributor Covenant](https://www.contributor-covenant.org/), version 2.1.
50 changes: 50 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Contributing

Thank you for helping improve `ruby_llm-codex`.

## Before opening a change

- Use an issue for user-visible behavior changes or proposals that need design
agreement.
- Use [GitHub's private vulnerability reporting](SECURITY.md) for security
issues; do not disclose them publicly.
- Keep the adapter's scope narrow: non-streaming RubyLLM chat through the local
Codex CLI, with isolation and reproducibility as defaults.

## Development setup

```bash
git clone git@github.com:ethos-link/ruby_llm-codex.git
cd ruby_llm-codex
bundle install
bundle exec lefthook install
bundle exec rake
```

The authenticated smoke test is separate because it invokes the real Codex CLI
and consumes subscription allowance:

```bash
bundle exec rake codex:smoke
```

Run it inside an appropriate process and memory boundary when changing process
lifecycle, timeout, or shell configuration behavior.

## Pull requests

1. Create a branch; hooks reject direct commits to `main` and `master`.
2. Add focused tests for behavior changes.
3. Run `bundle exec rake` and any relevant live smoke coverage.
4. Use Conventional Commits, including a meaningful body for non-trivial work.
5. Update `README.md` and `CHANGELOG.md` when user-facing behavior changes.
6. Open a pull request against `main` and explain the behavior, risks, and
verification performed.

Do not include generated gems from `pkg/`, credentials, Codex session data, or
unrelated formatting changes.

## Releases

Only maintainers publish releases. See [docs/releasing.md](docs/releasing.md) for
the controlled release procedure.
79 changes: 52 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# RubyLLM Codex provider

[![Ruby](https://github.com/ethos-link/ruby_llm-codex/actions/workflows/ruby.yml/badge.svg)](https://github.com/ethos-link/ruby_llm-codex/actions/workflows/ruby.yml)
[![Gem Version](https://badge.fury.io/rb/ruby_llm-codex.svg)](https://rubygems.org/gems/ruby_llm-codex)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

This small adapter lets RubyLLM invoke the official local Codex CLI as a
provider. Codex reuses the ChatGPT login stored by `codex login`, so these runs
consume your Codex subscription allowance rather than OpenAI API credits.
Expand All @@ -15,7 +19,7 @@ mapping but not an identical wire-level experiment.

## Requirements

- Ruby 3.1.3 or newer
- Ruby 3.3 or newer
- RubyLLM 1.16.0 or newer, below 2.0
- Codex CLI 0.144.5 or newer, available as `codex`
- Linux or macOS (timeout cleanup relies on POSIX process groups)
Expand All @@ -31,26 +35,23 @@ codex login
Check the model list in your installed Codex version before a large run. Model
availability depends on the account and currently installed CLI.

Run the automated unit tests and the two-request live smoke task with:
## Installation

```bash
bundle exec rake test
bundle exec rake codex:smoke
```
Add the gem to your application's `Gemfile`:

The smoke task verifies the installed CLI version, then performs one plain-text
completion and one structured-output completion through the real RubyLLM
provider. It consumes Codex subscription allowance and requires a completed
login. Set `CODEX_MODEL`, `CODEX_BIN`, or `CODEX_TIMEOUT` to override its model,
executable, or 300-second request timeout.
```ruby
gem "ruby_llm-codex", "~> 0.1"
```

For local development, add this project to your application:
Then run `bundle install`. You can also install it directly:

```ruby
gem "ruby_llm-codex", path: "/path/to/ruby_llm-codex"
```bash
gem install ruby_llm-codex
```

Then use it like any explicit RubyLLM provider:
## Usage

Require the gem and use Codex as an explicit RubyLLM provider:

```ruby
require "ruby_llm-codex"
Expand Down Expand Up @@ -91,6 +92,10 @@ By default every request:
This prevents local `AGENTS.md`, plugins, MCP servers, repository contents, and
saved session history from quietly affecting a comparison.

## Configuration

### Per request

To deliberately let Codex inspect a repository or use selected configuration:

```ruby
Expand All @@ -106,6 +111,8 @@ chat.with_params(
)
```

### Global

Global configuration is also available:

```ruby
Expand Down Expand Up @@ -145,6 +152,18 @@ If you later need streaming, persistent threads, or high throughput, replace
the process-per-request implementation with a long-running `codex app-server`
client while keeping the same RubyLLM provider surface.

## Troubleshooting

- **`codex` is not found:** install the Codex CLI, run `codex login`, or set
`RubyLLM.config.codex_cli_path` to its absolute path.
- **A request times out:** increase `codex.timeout` or `CODEX_TIMEOUT` for the
smoke task. Timed-out process groups are terminated automatically.
- **Codex consumes excessive memory:** use the current gem version. The provider
explicitly disables Codex shell snapshots, which are unnecessary for its
completion-only execution and previously caused runaway Bash processes.
- **Local instructions affect output:** keep `ignore_user_config: true` and do
not set a working directory when you need isolated comparisons.

## Development

```bash
Expand All @@ -155,8 +174,15 @@ bundle install
bundle exec rake
```

To test an unreleased checkout from another application, use a local path in
that application's `Gemfile`:

```ruby
gem "ruby_llm-codex", path: "/path/to/ruby_llm-codex"
```

The default Rake task runs the unit suite and Standard Ruby. CI runs the same
gate on Ruby 3.1.3, 3.4, and 4.0.3, then validates commit messages and
gate on Ruby 3.3, 3.4, and 4.0.3, then validates commit messages and
git-cliff changelog generation.

The authenticated smoke task is intentionally separate because it consumes
Expand Down Expand Up @@ -184,10 +210,10 @@ bundle exec lefthook install

## Release

Releases are tag-driven. Local release commands prepare the changelog, version
commit, and tag; GitHub Actions runs the full test matrix, publishes through
RubyGems trusted publishing, and creates the GitHub release from
`CHANGELOG.md`.
Releases are tag-driven. GitHub Actions runs the full test matrix, publishes
through RubyGems trusted publishing, and creates the GitHub release from
`CHANGELOG.md`. See [docs/releasing.md](docs/releasing.md) for repository setup,
the first-release procedure, verification, and recovery guidance.

Install [git-cliff](https://git-cliff.org/) locally, check out a clean `main`,
and run one of:
Expand All @@ -199,22 +225,21 @@ bundle exec rake 'release:prepare[major]'
bundle exec rake 'release:prepare[0.2.0]'
```

The task:
For releases after `0.1.0`, the task:

1. Prepends the next changelog section from Conventional Commits.
2. Updates `lib/ruby_llm/codex/version.rb`.
3. Commits the release files and creates `vX.Y.Z`.
4. Pushes `main` and the tag to `origin`.

Before the first automated release, configure the gem's RubyGems trusted
publisher with owner `ethos-link`, repository `ruby_llm-codex`, workflow
`release.yml`, and environment `release`. The environment name must match the
protected GitHub environment used by the release job.
The initial `0.1.0` release only needs its existing version commit tagged after
the GitHub environment and pending RubyGems trusted publisher are configured.

## Contributing

Create a non-main branch, keep commits scoped and conventional, run
`bundle exec rake`, and open a pull request against `main`.
See [CONTRIBUTING.md](CONTRIBUTING.md). By participating, you agree to follow
the [Code of Conduct](CODE_OF_CONDUCT.md). Security reports should follow
[SECURITY.md](SECURITY.md), not a public issue.

## License

Expand Down
34 changes: 34 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Security policy

## Supported versions

Security fixes are provided for the latest released version. Because the gem is
pre-1.0, upgrades may include small compatibility changes documented in the
changelog.

## Reporting a vulnerability

Do not open a public issue for a suspected vulnerability. Use GitHub's private
vulnerability reporting for this repository. If that is unavailable, email
`devel@ethos-link.com` with:

- the affected version and platform;
- a minimal reproduction or proof of concept;
- the expected security impact;
- any suggested mitigation; and
- whether the issue is already public.

You should receive an acknowledgement within five business days. We will
coordinate validation, remediation, and disclosure with the reporter.

## Security boundaries

This gem starts the locally installed Codex CLI and reuses its existing ChatGPT
authentication. It does not collect, proxy, or store credentials. By default it
runs Codex in a fresh temporary directory, disables interactive approvals and
shell snapshots, uses a read-only sandbox, and does not inherit the parent
process environment for model-generated shell commands.

Applications that override the working directory, sandbox, user configuration,
or environment inheritance assume responsibility for the additional access
granted to Codex.
Loading