cline-rb 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +139 -0
- data/README.md +1216 -0
- data/TODO.md +2 -0
- data/lib/cline/cli.rb +373 -0
- data/lib/cline/config.rb +100 -0
- data/lib/cline/configuration.rb +23 -0
- data/lib/cline/data.rb +119 -0
- data/lib/cline/file_content.rb +33 -0
- data/lib/cline/global_settings.rb +17 -0
- data/lib/cline/global_state/api_providers.rb +48 -0
- data/lib/cline/global_state/auto_approval.rb +73 -0
- data/lib/cline/global_state/browser.rb +52 -0
- data/lib/cline/global_state/features.rb +56 -0
- data/lib/cline/global_state/general.rb +77 -0
- data/lib/cline/global_state/models.rb +127 -0
- data/lib/cline/global_state/toggles.rb +33 -0
- data/lib/cline/global_state/workspace.rb +41 -0
- data/lib/cline/global_state.rb +16 -0
- data/lib/cline/log.rb +288 -0
- data/lib/cline/logs.rb +136 -0
- data/lib/cline/mcp_settings.rb +30 -0
- data/lib/cline/model.rb +47 -0
- data/lib/cline/models.rb +11 -0
- data/lib/cline/overlay_hash.rb +125 -0
- data/lib/cline/providers.rb +59 -0
- data/lib/cline/schema.rb +144 -0
- data/lib/cline/secret_string.rb +83 -0
- data/lib/cline/secrets.rb +119 -0
- data/lib/cline/serializable/cline_data.rb +131 -0
- data/lib/cline/serializable/dir.rb +81 -0
- data/lib/cline/serializable/file.rb +106 -0
- data/lib/cline/session.rb +87 -0
- data/lib/cline/session_data.rb +154 -0
- data/lib/cline/session_message.rb +178 -0
- data/lib/cline/session_messages.rb +61 -0
- data/lib/cline/sessions.rb +30 -0
- data/lib/cline/skill.rb +148 -0
- data/lib/cline/skills.rb +8 -0
- data/lib/cline/task.rb +75 -0
- data/lib/cline/task_message.rb +247 -0
- data/lib/cline/task_messages.rb +11 -0
- data/lib/cline/tasks.rb +30 -0
- data/lib/cline/usage.rb +37 -0
- data/lib/cline/utils/enumerable_dir_objects.rb +103 -0
- data/lib/cline/utils/file.rb +71 -0
- data/lib/cline/utils/file_monitor.rb +56 -0
- data/lib/cline/utils/logger.rb +37 -0
- data/lib/cline/utils/os/linux.rb +43 -0
- data/lib/cline/utils/os/mingw32.rb +46 -0
- data/lib/cline/utils/os.rb +31 -0
- data/lib/cline/utils/schema.rb +290 -0
- data/lib/cline/version.rb +6 -0
- data/lib/cline/workspace.rb +25 -0
- data/lib/cline/workspace_settings.rb +29 -0
- data/lib/cline/workspaces.rb +8 -0
- data/lib/cline.rb +22 -0
- metadata +249 -0
data/README.md
ADDED
|
@@ -0,0 +1,1216 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# cline-rb
|
|
4
|
+
|
|
5
|
+
Ruby bindings for the [Cline](https://cline.bot/) AI assistant ecosystem β programmatically control the CLI, manage configurations, skills, sessions, tasks, models, logs, and secrets.
|
|
6
|
+
|
|
7
|
+
[](https://github.com/Muriel-Salvan/cline-rb/actions/workflows/continuous_integration.yml)
|
|
8
|
+
[](https://codecov.io/gh/Muriel-Salvan/cline-rb)
|
|
9
|
+
[](https://github.com/Muriel-Salvan/cline-rb/stargazers)
|
|
10
|
+
[](LICENSE)
|
|
11
|
+
[](https://badge.fury.io/rb/cline-rb)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
**cline-rb** is a Ruby gem that gives you programmatic access to the [Cline](https://cline.bot/) AI assistant ecosystem. π―
|
|
16
|
+
|
|
17
|
+
Cline is an AI coding assistant that lives in your terminal. This library wraps its internals so you can:
|
|
18
|
+
|
|
19
|
+
* π€ **Launch & control** the Cline CLI from Ruby β run tasks, authenticate providers, and handle interactive sessions via PTY.
|
|
20
|
+
* π **Read & write configuration** β access global (`~/.cline`), project (`.cline`), and VSCode extension data with a clean Ruby API.
|
|
21
|
+
* π§ **Manage skills, tasks & sessions** β list, enable/disable skills, monitor real-time task/session messages, and track token usage & costs.
|
|
22
|
+
* π **Handle secrets safely** β store and retrieve API keys for dozens of AI providers (OpenAI, Anthropic, Gemini, DeepSeek, Groqβ¦).
|
|
23
|
+
* π **Parse logs & global state** β read structured log entries, inspect auto-approval rules, browser settings, feature flags, and MCP configurations.
|
|
24
|
+
* β±οΈ **Watch for file changes** β monitor config files, logs, and data files for live updates.
|
|
25
|
+
|
|
26
|
+
Designed as a Ruby library (not a standalone CLI), **cline-rb** lets you build automation, testing tooling, custom dashboards, or integration scripts on top of the Cline ecosystem with minimal effort. β¨
|
|
27
|
+
|
|
28
|
+
## Table of contents
|
|
29
|
+
|
|
30
|
+
- [Quick start](#quick-start)
|
|
31
|
+
- [Prerequisites](#prerequisites)
|
|
32
|
+
- [Installation](#installation)
|
|
33
|
+
- [Configuration (optional)](#configuration-optional)
|
|
34
|
+
- [Reading Cline data](#reading-cline-data)
|
|
35
|
+
- [Running a Cline task](#running-a-cline-task)
|
|
36
|
+
- [Running a task with a specific model](#running-a-task-with-a-specific-model)
|
|
37
|
+
- [Monitoring messages in real time](#monitoring-messages-in-real-time)
|
|
38
|
+
- [Handling interactive sessions (questions from the assistant)](#handling-interactive-sessions-questions-from-the-assistant)
|
|
39
|
+
- [Authentication](#authentication)
|
|
40
|
+
- [Reading logs](#reading-logs)
|
|
41
|
+
- [Interrupting a running task](#interrupting-a-running-task)
|
|
42
|
+
- [Requirements](#requirements)
|
|
43
|
+
- [Features](#features)
|
|
44
|
+
- [Public API](#public-api)
|
|
45
|
+
- [`Cline` β top-level module](#cline--top-level-module)
|
|
46
|
+
- [`Cline.configure`](#clineconfigure)
|
|
47
|
+
- [`Cline.config`](#clineconfig)
|
|
48
|
+
- [`Cline::VERSION`](#clineversion)
|
|
49
|
+
- [`Cline::Configuration` β gem configuration](#clineconfiguration--gem-configuration)
|
|
50
|
+
- [`Cline::Cli` β CLI wrapper](#clinecli--cli-wrapper)
|
|
51
|
+
- [`Cli#initialize(stdout_echo: false, **kwargs)`](#cliinitializestdout_echo-false-kwargs)
|
|
52
|
+
- [`Cli#task(prompt, on_message: nil, on_question: nil, monitoring_interval_secs: 1, **kwargs)`](#clitaskprompt-on_message-nil-on_question-nil-monitoring_interval_secs-1-kwargs)
|
|
53
|
+
- [`Cli#auth(**kwargs)`](#cliauthkwargs)
|
|
54
|
+
- [`Cli#interrupt`](#cliinterrupt)
|
|
55
|
+
- [`Cli#cline_pid` / `Cli#session`](#clicline_pid--clisession)
|
|
56
|
+
- [`Cline::Config` β Cline configuration directory](#clineconfig--cline-configuration-directory)
|
|
57
|
+
- [`Config.main`](#configmain)
|
|
58
|
+
- [`Config.global`](#configglobal)
|
|
59
|
+
- [`Config.project`](#configproject)
|
|
60
|
+
- [`Config#skills(create: false)`](#configskillscreate-false)
|
|
61
|
+
- [`Config#data(create: false)`](#configdatacreate-false)
|
|
62
|
+
- [`Config#cli(**kwargs)`](#configclikwargs)
|
|
63
|
+
- [`Config#refresh!`](#configrefresh)
|
|
64
|
+
- [`Cline::OverlayHash` β layered hash](#clineoverlayhash--layered-hash)
|
|
65
|
+
- [`Cline::Data` β Cline data directory](#clinedata--cline-data-directory)
|
|
66
|
+
- [`Data.vscode`](#datavscode)
|
|
67
|
+
- [`Cline::Skill` β individual skill](#clineskill--individual-skill)
|
|
68
|
+
- [`Cline::Skills` β collection of skills](#clineskills--collection-of-skills)
|
|
69
|
+
- [`Cline::Session` β a Cline session](#clinesession--a-cline-session)
|
|
70
|
+
- [`Cline::SessionData` β session metadata JSON](#clinesessiondata--session-metadata-json)
|
|
71
|
+
- [`Cline::SessionMessage` β individual session message](#clinesessionmessage--individual-session-message)
|
|
72
|
+
- [`Cline::SessionMessages` β session messages file](#clinesessionmessages--session-messages-file)
|
|
73
|
+
- [`Cline::Task` β a Cline task](#clinetask--a-cline-task)
|
|
74
|
+
- [`Cline::TaskMessage` β individual task message](#clinetaskmessage--individual-task-message)
|
|
75
|
+
- [`Cline::Logs` β log file](#clinelogs--log-file)
|
|
76
|
+
- [`Cline::Log` β log entry schema](#clinelog--log-entry-schema)
|
|
77
|
+
- [`Cline::Secrets` β API keys](#clinesecrets--api-keys)
|
|
78
|
+
- [`Cline::Model` β cached model info](#clinemodel--cached-model-info)
|
|
79
|
+
- [`Cline::GlobalState` β global Cline state](#clineglobalstate--global-cline-state)
|
|
80
|
+
- [`Cline::GlobalSettings` β global settings](#clineglobalsettings--global-settings)
|
|
81
|
+
- [`Cline::McpSettings` β MCP server settings](#clinemcpsettings--mcp-server-settings)
|
|
82
|
+
- [`Cline::Providers` β provider configurations](#clineproviders--provider-configurations)
|
|
83
|
+
- [`Cline::Workspace` β workspace data](#clineworkspace--workspace-data)
|
|
84
|
+
- [`Cline::Usage` β token usage statistics](#clineusage--token-usage-statistics)
|
|
85
|
+
- [`Cline::Schema` β base JSON schema class](#clineschema--base-json-schema-class)
|
|
86
|
+
- [`Cline::FileContent` β skill file content](#clinefilecontent--skill-file-content)
|
|
87
|
+
- [`Cline::Utils::FileMonitor` β file change monitor](#clineutilsfilemonitor--file-change-monitor)
|
|
88
|
+
- [Documentation](#documentation)
|
|
89
|
+
- [How it works](#how-it-works)
|
|
90
|
+
- [Architecture overview](#architecture-overview)
|
|
91
|
+
- [1οΈβ£ Auto-loading with Zeitwerk β‘](#-auto-loading-with-zeitwerk-)
|
|
92
|
+
- [2οΈβ£ Schema & Serialization (the core pattern) π](#-schema--serialization-the-core-pattern-)
|
|
93
|
+
- [3οΈβ£ Config β the entry point πͺ](#-config--the-entry-point-)
|
|
94
|
+
- [4οΈβ£ CLI interaction β PTY-based process control π€](#-cli-interaction--pty-based-process-control-)
|
|
95
|
+
- [5οΈβ£ File monitoring β polling-based change detection π](#-file-monitoring--polling-based-change-detection-)
|
|
96
|
+
- [6οΈβ£ OverlayHash β merging global + project config π](#-overlayhash--merging-global--project-config-)
|
|
97
|
+
- [7οΈβ£ Skill management π](#-skill-management-)
|
|
98
|
+
- [8οΈβ£ Secret handling π](#-secret-handling-)
|
|
99
|
+
- [Data flow (end-to-end) π―](#data-flow-end-to-end-)
|
|
100
|
+
- [Development](#development)
|
|
101
|
+
- [Prerequisites](#prerequisites-1)
|
|
102
|
+
- [Clone the repository](#clone-the-repository)
|
|
103
|
+
- [Install dependencies](#install-dependencies)
|
|
104
|
+
- [Project structure](#project-structure)
|
|
105
|
+
- [Running tests](#running-tests)
|
|
106
|
+
- [Code linting](#code-linting)
|
|
107
|
+
- [Code coverage](#code-coverage)
|
|
108
|
+
- [Building the gem](#building-the-gem)
|
|
109
|
+
- [Generating YARD documentation](#generating-yard-documentation)
|
|
110
|
+
- [Common development tasks](#common-development-tasks)
|
|
111
|
+
- [Contributing](#contributing)
|
|
112
|
+
- [π Issues](#-issues)
|
|
113
|
+
- [π΄ Fork & Pull Request workflow](#-fork--pull-request-workflow)
|
|
114
|
+
- [β
Pull Request guidelines](#-pull-request-guidelines)
|
|
115
|
+
- [π CI & Quality gates](#-ci--quality-gates)
|
|
116
|
+
- [π License](#-license)
|
|
117
|
+
- [π¬ Questions?](#-questions)
|
|
118
|
+
- [License](#license)
|
|
119
|
+
|
|
120
|
+
## Quick start
|
|
121
|
+
|
|
122
|
+
### Prerequisites
|
|
123
|
+
|
|
124
|
+
- **Ruby >= 3.1**
|
|
125
|
+
- **Cline CLI** installed and configured on your system (see [cline.bot](https://cline.bot/))
|
|
126
|
+
|
|
127
|
+
### Installation
|
|
128
|
+
|
|
129
|
+
Add the gem to your project's Gemfile:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
$ bundle add cline-rb
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Or install it globally:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
$ gem install cline-rb
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Then require the library:
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
require 'cline'
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Configuration (optional)
|
|
148
|
+
|
|
149
|
+
Enable debug logging to see CLI interactions:
|
|
150
|
+
|
|
151
|
+
```ruby
|
|
152
|
+
Cline.configure do |config|
|
|
153
|
+
config.debug = true
|
|
154
|
+
end
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Reading Cline data
|
|
158
|
+
|
|
159
|
+
Access the global configuration (`~/.cline`), project config (`.cline`), or the merged main config:
|
|
160
|
+
|
|
161
|
+
```ruby
|
|
162
|
+
# Main config (global + project merged)
|
|
163
|
+
config = Cline::Config.main
|
|
164
|
+
|
|
165
|
+
# Global config only
|
|
166
|
+
config = Cline::Config.global
|
|
167
|
+
|
|
168
|
+
# Project config only
|
|
169
|
+
config = Cline::Config.project
|
|
170
|
+
|
|
171
|
+
# List available skills
|
|
172
|
+
config.skills&.each do |name, skill|
|
|
173
|
+
puts "#{name}: #{skill.enabled? ? 'enabled' : 'disabled'}"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# List recent sessions
|
|
177
|
+
config.data.sessions.each do |id, session|
|
|
178
|
+
puts "[#{session.status}] #{session.model} - #{session.session_id}"
|
|
179
|
+
puts " Tokens: #{session.data.metadata.usage&.input_tokens} in / #{session.data.metadata.usage&.output_tokens} out" if session.data&.metadata&.usage
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# List tasks
|
|
183
|
+
config.data.tasks.each do |id, task|
|
|
184
|
+
puts "Task #{id}: #{task.messages&.first&.text&.slice(0..80)}"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Read stored API keys (returned as SecretString, redacted on inspect)
|
|
188
|
+
secrets = config.data.secrets
|
|
189
|
+
puts secrets.open_ai_api_key # => "sk-...********" (redacted)
|
|
190
|
+
|
|
191
|
+
# Read cached model information
|
|
192
|
+
models = config.data.cline_models
|
|
193
|
+
puts models.keys # e.g. ["gpt-4o", "claude-sonnet-4-6", ...]
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Running a Cline task
|
|
197
|
+
|
|
198
|
+
Use `Cline::Cli` to launch the Cline CLI, send a prompt, and collect the result:
|
|
199
|
+
|
|
200
|
+
```ruby
|
|
201
|
+
cli = Cline::Cli.new(stdout_echo: true)
|
|
202
|
+
|
|
203
|
+
result = cli.task('Explain what Ruby symbols are in one sentence.')
|
|
204
|
+
|
|
205
|
+
puts result[:stdout] # Full CLI output
|
|
206
|
+
puts result[:message] # Last assistant message (SessionMessage object)
|
|
207
|
+
puts result[:status] # e.g. "completed"
|
|
208
|
+
puts result[:error] # Error log entry if status is "failed"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### Running a task with a specific model
|
|
212
|
+
|
|
213
|
+
```ruby
|
|
214
|
+
result = cli.task(
|
|
215
|
+
'Refactor this code snippet: puts "hello"',
|
|
216
|
+
model: 'claude-sonnet-4-6',
|
|
217
|
+
provider: 'anthropic'
|
|
218
|
+
)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### Monitoring messages in real time
|
|
222
|
+
|
|
223
|
+
```ruby
|
|
224
|
+
result = cli.task(
|
|
225
|
+
'Write a Ruby script that reads a CSV file.',
|
|
226
|
+
on_message: proc do |message, last, previous_version|
|
|
227
|
+
puts "[#{message.say}] #{message.to_human(limit: 120)}"
|
|
228
|
+
end
|
|
229
|
+
)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### Handling interactive sessions (questions from the assistant)
|
|
233
|
+
|
|
234
|
+
```ruby
|
|
235
|
+
result = cli.task(
|
|
236
|
+
'Create a new Rails API project',
|
|
237
|
+
on_question: proc do |question|
|
|
238
|
+
puts "Assistant asks: #{question.question}"
|
|
239
|
+
'Use the default settings'
|
|
240
|
+
end
|
|
241
|
+
)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Authentication
|
|
245
|
+
|
|
246
|
+
Set up a provider's API key:
|
|
247
|
+
|
|
248
|
+
```ruby
|
|
249
|
+
cli = Cline::Cli.new
|
|
250
|
+
cli.auth(provider: 'openai-native', apikey: 'sk-...')
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Reading logs
|
|
254
|
+
|
|
255
|
+
```ruby
|
|
256
|
+
logs = config.data.logs
|
|
257
|
+
logs.logs.each do |entry|
|
|
258
|
+
puts "[#{entry.time}] #{entry.msg}" if entry.is_a?(Cline::Log)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Monitor logs in real time
|
|
262
|
+
logs.monitor(on_log: ->(log, _last) {
|
|
263
|
+
puts log.msg if log.is_a?(Cline::Log)
|
|
264
|
+
}) do
|
|
265
|
+
sleep 5
|
|
266
|
+
end
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Interrupting a running task
|
|
270
|
+
|
|
271
|
+
```ruby
|
|
272
|
+
cli.interrupt # kills the running Cline process tree
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Requirements
|
|
276
|
+
|
|
277
|
+
- **Ruby** >= 3.1
|
|
278
|
+
- **Cline CLI** installed and available on your `PATH` (see [cline.bot](https://cline.bot/) for installation instructions)
|
|
279
|
+
- **Operating System**: Linux, macOS, or Windows (the gem includes platform-specific dependencies for each)
|
|
280
|
+
- **Bundler** (recommended) β to manage the gem dependency in your project via `bundle add cline-rb`
|
|
281
|
+
|
|
282
|
+
## Features
|
|
283
|
+
|
|
284
|
+
**cline-rb** is a Ruby library that wraps the [Cline](https://cline.bot/) AI assistant ecosystem, providing programmatic access to its CLI, configuration, data, and runtime β all through a clean Ruby API. Key capabilities include:
|
|
285
|
+
|
|
286
|
+
* π€ **CLI control** β Launch and drive the Cline CLI from Ruby via PTY: run tasks with custom models/providers, authenticate providers, handle interactive questions, and interrupt running sessions.
|
|
287
|
+
* π **Configuration access** β Read and write Cline config from multiple sources (global `~/.cline`, project `.cline`, or custom paths). Merge global + project layers into a unified view.
|
|
288
|
+
* π **Secrets management** β Safely store and retrieve API keys for 30+ AI providers (OpenAI, Anthropic, Gemini, DeepSeek, Groq, Mistral, Together, etc.) using `SecretString` for secure in-memory handling.
|
|
289
|
+
* π§ **Skills management** β List, read, enable, and disable skills; inspect their YAML front matter and file contents.
|
|
290
|
+
* π **Sessions & tasks** β Enumerate sessions and tasks from the data directory, read their structured messages, extract token usage, model info, and costs.
|
|
291
|
+
* β±οΈ **Real-time monitoring** β Subscribe to live updates on session messages, task messages, and log entries via file-change polling with callback-driven notifications.
|
|
292
|
+
* π **Log parsing** β Read, parse, and append structured JSON log entries (error details, telemetry events, API call errors, etc.) with support for real-time log monitoring.
|
|
293
|
+
* βοΈ **Global state inspection** β Access auto-approval rules, browser/viewport settings, feature flags, model configurations, API provider settings, workspace roots, and toggle states.
|
|
294
|
+
* π **MCP settings** β Read and write Model Context Protocol server configurations (type, URL, timeout, auto-approve tools).
|
|
295
|
+
* π§© **Provider config** β Read provider entries with API keys, model IDs, reasoning settings, and token sources.
|
|
296
|
+
* πΎ **Cached model info** β Access cached model metadata (context windows, pricing, image/cache support, thinking config).
|
|
297
|
+
* π **Workspace settings** β Read per-workspace toggle states for skills, rules, and workflows.
|
|
298
|
+
* π **Configuration merging** β `OverlayHash` provides a layered Hash interface combining global and project configs.
|
|
299
|
+
* π¦ **VSCode support** β Access the VSCode extension's Cline data directory directly.
|
|
300
|
+
* π οΈ **File change monitoring** β A background thread polls files at configurable intervals and fires callbacks on change β used across logs, sessions, tasks, and Cline data.
|
|
301
|
+
* ποΈ **Schema-driven JSON serialization** β Domain objects (via `Shale`) handle automatic camelCaseβsnake_case mapping, preserve extra attributes, and support round-trip JSON serialization.
|
|
302
|
+
* π» **Cross-platform** β OS-agnostic helpers for Linux and Windows (MinGW) covering executable paths, home directories, app data, and process tree management.
|
|
303
|
+
* π **Debug support** β Configurable debug mode enables verbose PTY output logging, temporary directory snapshots, and ANSI-sanitized logs.
|
|
304
|
+
|
|
305
|
+
## Public API
|
|
306
|
+
|
|
307
|
+
**cline-rb** is a Ruby library (no CLI executables). All public entry points are Ruby classes and methods under the `Cline` module.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
### `Cline` β top-level module
|
|
312
|
+
|
|
313
|
+
#### `Cline.configure`
|
|
314
|
+
|
|
315
|
+
Configure the cline-rb gem behavior.
|
|
316
|
+
|
|
317
|
+
```ruby
|
|
318
|
+
Cline.configure do |config|
|
|
319
|
+
config.debug = true
|
|
320
|
+
config.temp_dir_root = '/tmp/my_debug'
|
|
321
|
+
end
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline.rb#L13-L15)
|
|
325
|
+
|
|
326
|
+
#### `Cline.config`
|
|
327
|
+
|
|
328
|
+
Get the current gem configuration (a `Cline::Configuration` instance).
|
|
329
|
+
|
|
330
|
+
```ruby
|
|
331
|
+
Cline.config.debug #=> true or false
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline.rb#L18-L20)
|
|
335
|
+
|
|
336
|
+
#### `Cline::VERSION`
|
|
337
|
+
|
|
338
|
+
Gem version constant.
|
|
339
|
+
|
|
340
|
+
```ruby
|
|
341
|
+
Cline::VERSION #=> "0.1.0"
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
### `Cline::Configuration` β gem configuration
|
|
347
|
+
|
|
348
|
+
| Attribute | Type | Description |
|
|
349
|
+
|---|---|---|
|
|
350
|
+
| `debug` | `Boolean` | Debug mode (defaults to `ENV['CLINE_DEBUG'] == '1'`) |
|
|
351
|
+
| `temp_dir_root` | `String` | Debug temp directory root (default: `.cline-rb/tmp`) |
|
|
352
|
+
|
|
353
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/configuration.rb)
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
### `Cline::Cli` β CLI wrapper
|
|
358
|
+
|
|
359
|
+
Wraps the Cline CLI process via PTY. Create an instance and use it to run tasks, authenticate providers, or interrupt running commands.
|
|
360
|
+
|
|
361
|
+
```ruby
|
|
362
|
+
cli = Cline::Cli.new(stdout_echo: true)
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
#### `Cli#initialize(stdout_echo: false, **kwargs)`
|
|
366
|
+
|
|
367
|
+
Constructor. `kwargs` can include global options like `verbose`, `cwd`, or `config`.
|
|
368
|
+
|
|
369
|
+
```ruby
|
|
370
|
+
cli = Cline::Cli.new(stdout_echo: true, cwd: '/my/project')
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### `Cli#task(prompt, on_message: nil, on_question: nil, monitoring_interval_secs: 1, **kwargs)`
|
|
374
|
+
|
|
375
|
+
Start a task by sending a prompt to the Cline CLI. Returns `{ stdout:, message:, status:, error: }`.
|
|
376
|
+
|
|
377
|
+
```ruby
|
|
378
|
+
result = cli.task('Explain Ruby symbols in one sentence.', model: 'claude-sonnet-4-6')
|
|
379
|
+
puts result[:stdout] # Full CLI output
|
|
380
|
+
puts result[:message] # Last assistant SessionMessage
|
|
381
|
+
puts result[:status] # e.g. "completed"
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/cli.rb#L129-L237)
|
|
385
|
+
|
|
386
|
+
#### `Cli#auth(**kwargs)`
|
|
387
|
+
|
|
388
|
+
Authenticate a provider with the CLI.
|
|
389
|
+
|
|
390
|
+
```ruby
|
|
391
|
+
cli.auth(provider: 'openai-native', apikey: 'sk-...')
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/cli.rb#L108-L110)
|
|
395
|
+
|
|
396
|
+
#### `Cli#interrupt`
|
|
397
|
+
|
|
398
|
+
Kill the currently running Cline process tree.
|
|
399
|
+
|
|
400
|
+
```ruby
|
|
401
|
+
cli.interrupt
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/cli.rb#L246-L259)
|
|
405
|
+
|
|
406
|
+
#### `Cli#cline_pid` / `Cli#session`
|
|
407
|
+
|
|
408
|
+
Access the current Cline process PID and the last session handled.
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
### `Cline::Config` β Cline configuration directory
|
|
413
|
+
|
|
414
|
+
Access global (`~/.cline`), project (`.cline`), or merged configuration.
|
|
415
|
+
|
|
416
|
+
#### `Config.main`
|
|
417
|
+
|
|
418
|
+
Merged global + project config.
|
|
419
|
+
|
|
420
|
+
```ruby
|
|
421
|
+
config = Cline::Config.main
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
#### `Config.global`
|
|
425
|
+
|
|
426
|
+
Global config only (`~/.cline`).
|
|
427
|
+
|
|
428
|
+
```ruby
|
|
429
|
+
global = Cline::Config.global
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
#### `Config.project`
|
|
433
|
+
|
|
434
|
+
Project config only (`.cline`).
|
|
435
|
+
|
|
436
|
+
```ruby
|
|
437
|
+
project = Cline::Config.project
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
#### `Config#skills(create: false)`
|
|
441
|
+
|
|
442
|
+
Get skills (returns an `OverlayHash` combining global + project skills).
|
|
443
|
+
|
|
444
|
+
```ruby
|
|
445
|
+
config.skills&.each { |name, skill| puts name }
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
#### `Config#data(create: false)`
|
|
449
|
+
|
|
450
|
+
Get the `Data` object for this config.
|
|
451
|
+
|
|
452
|
+
```ruby
|
|
453
|
+
config.data.secrets #=> Cline::Secrets
|
|
454
|
+
config.data.logs #=> Cline::Logs
|
|
455
|
+
config.data.sessions #=> Cline::Sessions
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
#### `Config#cli(**kwargs)`
|
|
459
|
+
|
|
460
|
+
Create a `Cli` instance attached to this config.
|
|
461
|
+
|
|
462
|
+
```ruby
|
|
463
|
+
config.cli(stdout_echo: true).task('Hello')
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
#### `Config#refresh!`
|
|
467
|
+
|
|
468
|
+
Clear cached objects to reload from disk.
|
|
469
|
+
|
|
470
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/config.rb)
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
### `Cline::OverlayHash` β layered hash
|
|
475
|
+
|
|
476
|
+
Merges several Hash-like objects, with priority order for reads and writes to the first layer only.
|
|
477
|
+
|
|
478
|
+
```ruby
|
|
479
|
+
merged = Cline::OverlayHash.new(global_skills, project_skills)
|
|
480
|
+
merged['my_skill'] # retrieves from global first, falls back to project
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
Supports `each`, `[]`, `key?`, `keys`, `values`, `size`, `empty?`, `to_h`, `==`.
|
|
484
|
+
|
|
485
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/overlay_hash.rb)
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
### `Cline::Data` β Cline data directory
|
|
490
|
+
|
|
491
|
+
Wraps the content of `~/.cline/data`. Provides accessors returning domain objects.
|
|
492
|
+
|
|
493
|
+
```ruby
|
|
494
|
+
data = Cline::Config.global.data
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
| Method | Returns |
|
|
498
|
+
|---|---|
|
|
499
|
+
| `#cline_models` | `Models` |
|
|
500
|
+
| `#global_settings` | `GlobalSettings` |
|
|
501
|
+
| `#global_state` | `GlobalState` |
|
|
502
|
+
| `#logs` | `Logs` |
|
|
503
|
+
| `#mcp_settings` | `McpSettings` |
|
|
504
|
+
| `#providers` | `Providers` |
|
|
505
|
+
| `#secrets` | `Secrets` |
|
|
506
|
+
| `#sessions` | `Sessions` |
|
|
507
|
+
| `#tasks` | `Tasks` |
|
|
508
|
+
| `#workspaces` | `Workspaces` |
|
|
509
|
+
|
|
510
|
+
#### `Data.vscode`
|
|
511
|
+
|
|
512
|
+
Get the VSCode Cline extension data directory.
|
|
513
|
+
|
|
514
|
+
```ruby
|
|
515
|
+
vscode_data = Cline::Data.vscode
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/data.rb)
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
### `Cline::Skill` β individual skill
|
|
523
|
+
|
|
524
|
+
Represents a skill directory.
|
|
525
|
+
|
|
526
|
+
```ruby
|
|
527
|
+
skill = config.skills['my-skill']
|
|
528
|
+
skill.name #=> "my-skill"
|
|
529
|
+
skill.enabled? #=> true
|
|
530
|
+
skill.enable # Enable the skill
|
|
531
|
+
skill.disable # Disable the skill
|
|
532
|
+
skill.files #=> { "SKILL.md" => #<FileContent>, ... }
|
|
533
|
+
skill.save # Persist changes to disk
|
|
534
|
+
skill.yaml_front_matter #=> { name: "...", ... }
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/skill.rb)
|
|
538
|
+
|
|
539
|
+
---
|
|
540
|
+
|
|
541
|
+
### `Cline::Skills` β collection of skills
|
|
542
|
+
|
|
543
|
+
Enumerable + Hash-like interface over skill directories.
|
|
544
|
+
|
|
545
|
+
```ruby
|
|
546
|
+
skills = config.skills
|
|
547
|
+
skills.keys.each { |name| puts name }
|
|
548
|
+
skills.new('my-new-skill') # Create a new skill directory
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
### `Cline::Session` β a Cline session
|
|
554
|
+
|
|
555
|
+
```ruby
|
|
556
|
+
session = config.data.sessions['session-id']
|
|
557
|
+
session.status #=> "completed"
|
|
558
|
+
session.model #=> "deepseek/deepseek-v4-flash"
|
|
559
|
+
session.data #=> Cline::SessionData (metadata, usage, costs)
|
|
560
|
+
session.messages #=> Cline::SessionMessages
|
|
561
|
+
session.monitor_messages(on_message: ->(msg, last, prev) { puts msg.to_human }) do
|
|
562
|
+
sleep 5
|
|
563
|
+
end
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
The `Session` delegates `SessionData` attributes directly: `session_id`, `status`, `model`, `provider`, `started_at`, `ended_at`, etc.
|
|
567
|
+
|
|
568
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/session.rb)
|
|
569
|
+
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
### `Cline::SessionData` β session metadata JSON
|
|
573
|
+
|
|
574
|
+
Contains `Metadata` (with `Usage`, `Checkpoint`, `CheckpointEntry`), version, session_id, source, pid, timestamps, status, model, provider, costs, etc.
|
|
575
|
+
|
|
576
|
+
```ruby
|
|
577
|
+
session.data.metadata.usage.input_tokens #=> 1234
|
|
578
|
+
session.data.metadata.usage.total_cost #=> 0.0023
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
---
|
|
582
|
+
|
|
583
|
+
### `Cline::SessionMessage` β individual session message
|
|
584
|
+
|
|
585
|
+
```ruby
|
|
586
|
+
msg = session.messages.first
|
|
587
|
+
msg.role #=> "user" or "assistant"
|
|
588
|
+
msg.content #=> Array of MessageContent blocks
|
|
589
|
+
msg.timestamp #=> Time object
|
|
590
|
+
msg.usage #=> Usage struct (cost, tokens)
|
|
591
|
+
msg.to_human #=> human-friendly string (limited to 128 chars by default)
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
Contains nested schemas: `ModelInfo`, `Metrics`, `MessageContent`, `ToolUseInput`.
|
|
595
|
+
|
|
596
|
+
---
|
|
597
|
+
|
|
598
|
+
### `Cline::SessionMessages` β session messages file
|
|
599
|
+
|
|
600
|
+
Contains `version`, `updated_at`, `agent`, `session_id`, `messages` (array of `SessionMessage`), `system_prompt`.
|
|
601
|
+
|
|
602
|
+
---
|
|
603
|
+
|
|
604
|
+
### `Cline::Task` β a Cline task
|
|
605
|
+
|
|
606
|
+
```ruby
|
|
607
|
+
task = config.data.tasks['task-id']
|
|
608
|
+
task.messages #=> Cline::TaskMessages
|
|
609
|
+
task.monitor_messages(on_message: ->(msg, last, prev) { puts msg.to_human }) do
|
|
610
|
+
sleep 5
|
|
611
|
+
end
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/task.rb)
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
### `Cline::TaskMessage` β individual task message
|
|
619
|
+
|
|
620
|
+
```ruby
|
|
621
|
+
msg = task.messages.first
|
|
622
|
+
msg.ts #=> Integer timestamp
|
|
623
|
+
msg.type #=> "say" or "ask"
|
|
624
|
+
msg.say #=> "text", "api_req_started", "tool", etc.
|
|
625
|
+
msg.text #=> Raw text content
|
|
626
|
+
msg.timestamp #=> Time object
|
|
627
|
+
msg.usage #=> Usage struct (for api_req_started messages)
|
|
628
|
+
msg.to_human #=> Human-friendly description
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
### `Cline::Logs` β log file
|
|
634
|
+
|
|
635
|
+
```ruby
|
|
636
|
+
logs = config.data.logs
|
|
637
|
+
logs.logs.each { |entry| puts "[#{entry.time}] #{entry.msg}" if entry.is_a?(Cline::Log) }
|
|
638
|
+
|
|
639
|
+
# Add a log entry
|
|
640
|
+
logs << Cline::Log.new(level: 30, time: Time.now.iso8601, msg: 'Hello', pid: 1234, hostname: 'myhost', name: 'myapp', component: 'main')
|
|
641
|
+
logs.save
|
|
642
|
+
|
|
643
|
+
# Monitor logs in real-time
|
|
644
|
+
logs.monitor(on_log: ->(log, _last) { puts log.msg }) { sleep 5 }
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/logs.rb)
|
|
648
|
+
|
|
649
|
+
---
|
|
650
|
+
|
|
651
|
+
### `Cline::Log` β log entry schema
|
|
652
|
+
|
|
653
|
+
Attributes: `level`, `time`, `pid`, `hostname`, `name`, `component`, `msg`, `interactive`, `has_prompt`, `cwd`, `reason`, `backend_mode`, `force_local_backend`, `telemetry_sink`, `event`, `properties` (`Properties`), `severity`, `provider_id`, `err` (`Error`).
|
|
654
|
+
|
|
655
|
+
Nested schemas: `ErrorCause`, `ApiError`, `Error`, `Properties` (with ulid, api_provider, agent_id, team info, model info, platform info, etc.).
|
|
656
|
+
|
|
657
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/log.rb)
|
|
658
|
+
|
|
659
|
+
---
|
|
660
|
+
|
|
661
|
+
### `Cline::Secrets` β API keys
|
|
662
|
+
|
|
663
|
+
Access stored API keys for 30+ AI providers. All values are `SecretString` (redacted on inspect).
|
|
664
|
+
|
|
665
|
+
```ruby
|
|
666
|
+
secrets = config.data.secrets
|
|
667
|
+
secrets.open_ai_api_key #=> #<SecretString ...>
|
|
668
|
+
secrets.anthropic_api_key
|
|
669
|
+
secrets.gemini_api_key
|
|
670
|
+
secrets.deep_seek_api_key
|
|
671
|
+
# ... and many more
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/secrets.rb)
|
|
675
|
+
|
|
676
|
+
---
|
|
677
|
+
|
|
678
|
+
### `Cline::Model` β cached model info
|
|
679
|
+
|
|
680
|
+
```ruby
|
|
681
|
+
model = config.data.cline_models['claude-sonnet-4-6']
|
|
682
|
+
model.name #=> "Claude Sonnet 4.6"
|
|
683
|
+
model.max_tokens #=> 8192
|
|
684
|
+
model.context_window #=> 200000
|
|
685
|
+
model.input_price #=> 3.0
|
|
686
|
+
model.output_price #=> 15.0
|
|
687
|
+
model.supports_images #=> true
|
|
688
|
+
model.supports_prompt_cache #=> true
|
|
689
|
+
model.thinking_config #=> Cline::Model::ThinkingConfig (with max_budget)
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
---
|
|
693
|
+
|
|
694
|
+
### `Cline::GlobalState` β global Cline state
|
|
695
|
+
|
|
696
|
+
Access via `config.data.global_state`. Includes the following modules:
|
|
697
|
+
|
|
698
|
+
| Module | Provides |
|
|
699
|
+
|---|---|
|
|
700
|
+
| `AutoApproval` | `auto_approval_settings` (`AutoApprovalSettings` with actions toggles), `yolo_mode_toggled` |
|
|
701
|
+
| `Browser` | `browser_settings` (`BrowserSettings` with viewport, remote browser, chrome path) |
|
|
702
|
+
| `Workspace` | `workspace_roots` (array of `WorkspaceRoot`), `primary_root_index`, `multi_root_enabled` |
|
|
703
|
+
| `Features` | `focus_chain_settings`, `cline_web_tools_enabled`, `double_check_completion_enabled`, `subagents_enabled`, etc. |
|
|
704
|
+
| `ApiProviders` | `open_ai_headers`, `anthropic_base_url`, `request_timeout_ms`, `azure_api_version`, etc. |
|
|
705
|
+
| `General` | `welcome_view_completed`, `custom_prompt`, `cline_version`, `telemetry_setting`, `is_new_user`, etc. |
|
|
706
|
+
| `Toggles` | `remote_rules_toggles`, `global_skills_toggles`, `global_workflow_toggles`, etc. |
|
|
707
|
+
| `Models` | Mode-specific model configs (`act_mode_cline_model_id`, `plan_mode_cline_model_id`, etc.) |
|
|
708
|
+
|
|
709
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/global_state.rb)
|
|
710
|
+
|
|
711
|
+
---
|
|
712
|
+
|
|
713
|
+
### `Cline::GlobalSettings` β global settings
|
|
714
|
+
|
|
715
|
+
```ruby
|
|
716
|
+
settings = config.data.global_settings
|
|
717
|
+
settings.auto_update_enabled #=> true/false
|
|
718
|
+
settings.telemetry_opt_out #=> true/false
|
|
719
|
+
settings.disabled_tools #=> ["tool1", "tool2"]
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
---
|
|
723
|
+
|
|
724
|
+
### `Cline::McpSettings` β MCP server settings
|
|
725
|
+
|
|
726
|
+
```ruby
|
|
727
|
+
mcp = config.data.mcp_settings
|
|
728
|
+
mcp.mcp_servers['my-server'].type #=> "sse" or "stdio"
|
|
729
|
+
mcp.mcp_servers['my-server'].url #=> "https://..."
|
|
730
|
+
mcp.mcp_servers['my-server'].timeout #=> 60
|
|
731
|
+
mcp.mcp_servers['my-server'].auto_approve #=> ["tool1", "tool2"]
|
|
732
|
+
mcp.mcp_servers['my-server'].disabled #=> false
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
---
|
|
736
|
+
|
|
737
|
+
### `Cline::Providers` β provider configurations
|
|
738
|
+
|
|
739
|
+
```ruby
|
|
740
|
+
providers = config.data.providers
|
|
741
|
+
providers.version #=> 1
|
|
742
|
+
providers.last_used_provider #=> "anthropic"
|
|
743
|
+
providers.providers['anthropic'].settings.api_key #=> SecretString
|
|
744
|
+
providers.providers['anthropic'].settings.model #=> "claude-sonnet-4-6"
|
|
745
|
+
providers.providers['anthropic'].updated_at #=> ISO 8601 timestamp
|
|
746
|
+
providers.providers['anthropic'].token_source #=> "manual"
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
---
|
|
750
|
+
|
|
751
|
+
### `Cline::Workspace` β workspace data
|
|
752
|
+
|
|
753
|
+
```ruby
|
|
754
|
+
workspace = config.data.workspaces['workspace-id']
|
|
755
|
+
workspace.settings.local_skills_toggles #=> { "skill1" => true }
|
|
756
|
+
workspace.settings.workflow_toggles #=> { "wf1" => false }
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
---
|
|
760
|
+
|
|
761
|
+
### `Cline::Usage` β token usage statistics
|
|
762
|
+
|
|
763
|
+
A `Struct` with `cost`, `input_tokens`, `output_tokens`, `cache_read_tokens`, `cache_write_tokens`, `cline_model`.
|
|
764
|
+
|
|
765
|
+
```ruby
|
|
766
|
+
usage = msg.usage
|
|
767
|
+
usage.context_tokens #=> input + output + cache reads + cache writes
|
|
768
|
+
usage.context_tokens_limit #=> model's context_window
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/usage.rb)
|
|
772
|
+
|
|
773
|
+
---
|
|
774
|
+
|
|
775
|
+
### `Cline::Schema` β base JSON schema class
|
|
776
|
+
|
|
777
|
+
Base class for all domain objects. Provides JSON serialization with automatic camelCaseβsnake_case mapping.
|
|
778
|
+
|
|
779
|
+
```ruby
|
|
780
|
+
class MyConfig < Cline::Schema
|
|
781
|
+
attribute :my_field, :string
|
|
782
|
+
end
|
|
783
|
+
|
|
784
|
+
obj = MyConfig.of_hash({ "myField" => "value" })
|
|
785
|
+
obj.to_cline_json #=> '{"myField":"value"}'
|
|
786
|
+
obj.to_hash #=> { my_field: "value", extra_attributes: nil }
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/schema.rb)
|
|
790
|
+
|
|
791
|
+
---
|
|
792
|
+
|
|
793
|
+
### `Cline::FileContent` β skill file content
|
|
794
|
+
|
|
795
|
+
```ruby
|
|
796
|
+
file = skill.files['SKILL.md']
|
|
797
|
+
file.content #=> The raw file content
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
---
|
|
801
|
+
|
|
802
|
+
### `Cline::Utils::FileMonitor` β file change monitor
|
|
803
|
+
|
|
804
|
+
Polls a file for changes on a background thread.
|
|
805
|
+
|
|
806
|
+
```ruby
|
|
807
|
+
monitor = Cline::Utils::FileMonitor.new(
|
|
808
|
+
'path/to/file.log',
|
|
809
|
+
on_change: ->(mtime) { puts "File changed at #{mtime}" },
|
|
810
|
+
monitoring_interval_secs: 2
|
|
811
|
+
)
|
|
812
|
+
monitor.start
|
|
813
|
+
# ... later ...
|
|
814
|
+
monitor.stop
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
[View source](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/utils/file_monitor.rb)
|
|
818
|
+
|
|
819
|
+
## Documentation
|
|
820
|
+
|
|
821
|
+
- **[README.md](https://github.com/Muriel-Salvan/cline-rb/blob/main/README.md)** β Main project overview, installation, development and contributing instructions.
|
|
822
|
+
- **[RubyDoc.info](https://www.rubydoc.info/gems/cline-rb)** β Auto-generated API documentation for the `cline-rb` gem, with detailed class and method references from YARD doc comments.
|
|
823
|
+
- **[YARD API Documentation](https://github.com/Muriel-Salvan/cline-rb)** β Run `bundle exec yard doc` locally to generate HTML docs in the `doc/` directory. The project enforces 100% documented code via CI.
|
|
824
|
+
- **[CHANGELOG.md](https://github.com/Muriel-Salvan/cline-rb/blob/main/CHANGELOG.md)** β Release history, auto-generated by semantic-release.
|
|
825
|
+
- **[TODO.md](https://github.com/Muriel-Salvan/cline-rb/blob/main/TODO.md)** β Project roadmap and pending development tasks.
|
|
826
|
+
- **[LICENSE](https://github.com/Muriel-Salvan/cline-rb/blob/main/LICENSE)** β BSD 3-Clause License.
|
|
827
|
+
- **[GitHub Repository](https://github.com/Muriel-Salvan/cline-rb)** β Source code, issue tracker, and pull requests.
|
|
828
|
+
- **[Continuous Integration](https://github.com/Muriel-Salvan/cline-rb/blob/main/.github/workflows/continuous_integration.yml)** β CI workflow definition running tests, linting, and release automation.
|
|
829
|
+
- **[Documentation Specs](https://github.com/Muriel-Salvan/cline-rb/blob/main/spec/scenarios/documentation_spec.rb)** β RSpec tests verifying YARD documentation generation and 100% doc coverage.
|
|
830
|
+
|
|
831
|
+
## How it works
|
|
832
|
+
|
|
833
|
+
### Architecture overview
|
|
834
|
+
|
|
835
|
+
**cline-rb** is organized in **three layers** that mirror the Cline filesystem layout:
|
|
836
|
+
|
|
837
|
+
```mermaid
|
|
838
|
+
graph TD
|
|
839
|
+
subgraph "1οΈβ£ Configuration Layer"
|
|
840
|
+
Config[Config] -->|reads| HD[~/.cline - Global]
|
|
841
|
+
Config -->|reads| PD[.cline - Project]
|
|
842
|
+
Config -->|merges| OH[OverlayHash]
|
|
843
|
+
end
|
|
844
|
+
|
|
845
|
+
subgraph "2οΈβ£ Data Layer"
|
|
846
|
+
Data[Data] -->|JSON files| GS[GlobalSettings]
|
|
847
|
+
Data -->|JSON files| GV[GlobalState]
|
|
848
|
+
Data -->|JSON files| ST[Secrets]
|
|
849
|
+
Data -->|JSON files| PS[Providers]
|
|
850
|
+
Data -->|JSON files| MS[McpSettings]
|
|
851
|
+
Data -->|directories| SS[Sessions]
|
|
852
|
+
Data -->|directories| TS[Tasks]
|
|
853
|
+
Data -->|directories| WS[Workspaces]
|
|
854
|
+
Data -->|text file| LG[Logs]
|
|
855
|
+
Data -->|JSON| MM[ClineModels]
|
|
856
|
+
end
|
|
857
|
+
|
|
858
|
+
subgraph "3οΈβ£ CLI Layer"
|
|
859
|
+
Cli[Cli] -->|PTY.spawn| CMD[Cline CLI Process]
|
|
860
|
+
Cli -->|parses| STDOUT[stdout]
|
|
861
|
+
Cli -->|monitors| MMON[Message Monitor]
|
|
862
|
+
end
|
|
863
|
+
|
|
864
|
+
Config --> Data
|
|
865
|
+
Data --> Cli
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
### 1οΈβ£ Auto-loading with Zeitwerk β‘
|
|
869
|
+
|
|
870
|
+
The gem uses [Zeitwerk](https://github.com/fxn/zeitwerk) (`lib/cline.rb` line 3) for **convention-over-configuration** code loading. All classes under `lib/cline/` are auto-discovered and loaded on demand β no explicit `require` statements needed beyond `require 'cline'`.
|
|
871
|
+
|
|
872
|
+
### 2οΈβ£ Schema & Serialization (the core pattern) π
|
|
873
|
+
|
|
874
|
+
Every domain object (settings, providers, sessions, tasks...) extends `Cline::Schema < Shale::Mapper` ([schema.rb](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/schema.rb)). This provides:
|
|
875
|
+
|
|
876
|
+
- **Declarative attributes** β `attribute :my_field, :string` mirrors the JSON schema.
|
|
877
|
+
- **Automatic camelCaseβsnake_case mapping** β Cline stores `autoUpdateEnabled`, Ruby gets `auto_update_enabled`.
|
|
878
|
+
- **Extra attribute preservation** β unknown JSON keys are stored in `extra_attributes` and re-serialized back, maintaining round-trip fidelity.
|
|
879
|
+
|
|
880
|
+
3 mixin modules handle file persistence β classes include them to "come alive" from disk:
|
|
881
|
+
|
|
882
|
+
| Mixin | Purpose |
|
|
883
|
+
|---|---|
|
|
884
|
+
| `Serializable::Dir` | Opens from a **directory** (config, sessions, tasks, skills) |
|
|
885
|
+
| `Serializable::File` | Opens from a single **file** (logs) |
|
|
886
|
+
| `Serializable::ClineData` | Opens from a **JSON file** relative to a base directory (settings, secrets, providers) |
|
|
887
|
+
|
|
888
|
+
### 3οΈβ£ Config β the entry point πͺ
|
|
889
|
+
|
|
890
|
+
`Cline::Config` ([config.rb](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/config.rb)) is the main access point. It provides 3 static factories:
|
|
891
|
+
|
|
892
|
+
- `Config.global` β reads `~/.cline`
|
|
893
|
+
- `Config.project` β reads `.cline` (current directory)
|
|
894
|
+
- `Config.main` β merges global + project via `OverlayHash`
|
|
895
|
+
|
|
896
|
+
`Data` ([data.rb](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/data.rb)) lazily loads sub-objects (sessions, tasks, secrets...) with per-attribute caching (`@variable ||= ...`).
|
|
897
|
+
|
|
898
|
+
### 4οΈβ£ CLI interaction β PTY-based process control π€
|
|
899
|
+
|
|
900
|
+
`Cline::Cli` ([cli.rb](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/cli.rb)) wraps the Cline CLI binary using Ruby's `PTY.spawn`:
|
|
901
|
+
|
|
902
|
+
- ποΈ Builds command-line arguments from a declarative `COMMANDS` hash (global options + task/auth options).
|
|
903
|
+
- π **Real-time monitoring** β streams stdout line-by-line via `reader.each_line`, calling `on_message`/`on_stdout` callbacks.
|
|
904
|
+
- π **Interrupt support** β kills the entire Cline process tree recursively (using `Sys::ProcTable`).
|
|
905
|
+
- π§ͺ **Harvests results** β parses the last JSON output message, detects completion/failure/interactive-question states.
|
|
906
|
+
- π **Debug mode** β when `Cline.config.debug == true`, all CLI calls are logged with redacted output.
|
|
907
|
+
|
|
908
|
+
### 5οΈβ£ File monitoring β polling-based change detection π
|
|
909
|
+
|
|
910
|
+
`Utils::FileMonitor` ([file_monitor.rb](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/utils/file_monitor.rb)) polls a file's mtime in a background `Thread.new` at configurable intervals. This is used by:
|
|
911
|
+
- `Task#monitor_messages` β detects new/updated task messages in `ui_messages.json`
|
|
912
|
+
- `Session#monitor_messages` β detects new/updated session messages in `*.messages.json`
|
|
913
|
+
- `Logs#monitor` β watches `cline.log` for new log entries
|
|
914
|
+
|
|
915
|
+
Thread-safe detection compares the current message state (keyed by timestamp) to detect updates vs. new messages.
|
|
916
|
+
|
|
917
|
+
### 6οΈβ£ OverlayHash β merging global + project config π
|
|
918
|
+
|
|
919
|
+
`OverlayHash` ([overlay_hash.rb](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/overlay_hash.rb)) implements a **layered hash pattern**:
|
|
920
|
+
|
|
921
|
+
- **Reads** β iterates layers in priority order, returns first match.
|
|
922
|
+
- **Writes** β always go to the top (global) layer.
|
|
923
|
+
- **Used by** β `Config#skills` merges global + project skills transparently.
|
|
924
|
+
|
|
925
|
+
### 7οΈβ£ Skill management π
|
|
926
|
+
|
|
927
|
+
Skills ([skill.rb](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/skill.rb)) are directory-based, containing a `SKILL.md` file with YAML front matter. The gem:
|
|
928
|
+
- Parses YAML front matter using `front_matter_parser`.
|
|
929
|
+
- Detects `disabled: true` to determine enabled state.
|
|
930
|
+
- Provides `enable`/`disable` methods that rewrite the `SKILL.md` front matter in-place.
|
|
931
|
+
- Caches file discovery in an `@files` hash, lazily loaded.
|
|
932
|
+
|
|
933
|
+
### 8οΈβ£ Secret handling π
|
|
934
|
+
|
|
935
|
+
`SecretString` ([secret_string.rb](https://github.com/Muriel-Salvan/cline-rb/blob/main/lib/cline/secret_string.rb)) wraps the `secret_string` gem (not Shale's native type) by providing custom `cast`, `as_hash`, and `of_hash` methods, so API keys are:
|
|
936
|
+
- **Redacted on inspect** β `"sk-...********"`
|
|
937
|
+
- **Stored securely** β using secret_string's safe memory handling
|
|
938
|
+
|
|
939
|
+
### Data flow (end-to-end) π―
|
|
940
|
+
|
|
941
|
+
```mermaid
|
|
942
|
+
sequenceDiagram
|
|
943
|
+
participant U as User Code
|
|
944
|
+
participant C as Config
|
|
945
|
+
participant D as Data
|
|
946
|
+
participant CLI as Cli
|
|
947
|
+
participant PTY as Cline Process
|
|
948
|
+
|
|
949
|
+
U->>C: Config.main
|
|
950
|
+
C->>D: Lazily loads data/*
|
|
951
|
+
U->>D: .sessions / .tasks / .secrets
|
|
952
|
+
D-->>U: Schema objects (JSON β Ruby)
|
|
953
|
+
|
|
954
|
+
U->>CLI: .task(prompt, on_message:)
|
|
955
|
+
CLI->>PTY: PTY.spawn(cmd, args...)
|
|
956
|
+
PTY-->>CLI: stdout lines (streaming)
|
|
957
|
+
CLI-->>U: on_message callbacks (real-time)
|
|
958
|
+
Note over CLI,PTY: On completion:
|
|
959
|
+
CLI->>CLI: Parse last JSON message
|
|
960
|
+
CLI-->>U: { stdout:, message:, status: }
|
|
961
|
+
|
|
962
|
+
U->>CLI: .interrupt
|
|
963
|
+
CLI->>PTY: Kill process tree (recursive)
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
## Development
|
|
967
|
+
|
|
968
|
+
### Prerequisites
|
|
969
|
+
|
|
970
|
+
- **Ruby >= 3.1** (the CI runs against Ruby 3.4)
|
|
971
|
+
- **Bundler** (`gem install bundler`)
|
|
972
|
+
- **Cline CLI** installed and available on your `PATH` (needed for integration tests β see [cline.bot](https://cline.bot/))
|
|
973
|
+
- **Node.js** (needed for `node-pty` on Windows β see `.gitignore`)
|
|
974
|
+
|
|
975
|
+
### Clone the repository
|
|
976
|
+
|
|
977
|
+
```bash
|
|
978
|
+
git clone https://github.com/Muriel-Salvan/cline-rb.git
|
|
979
|
+
cd cline-rb
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
### Install dependencies
|
|
983
|
+
|
|
984
|
+
```bash
|
|
985
|
+
bundle install
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
For local development you can create a `Gemfile.local` file (already provided in the project) that adds `debug` and `ruby-lsp` gems on top of the main dependencies. Bundler will pick it up automatically if present.
|
|
989
|
+
|
|
990
|
+
> **Note:** This is a Ruby gem, so `Gemfile.lock` is in `.gitignore` and not committed.
|
|
991
|
+
|
|
992
|
+
### Project structure
|
|
993
|
+
|
|
994
|
+
```
|
|
995
|
+
cline-rb/
|
|
996
|
+
βββ lib/ # Library source code (autoloaded via Zeitwerk)
|
|
997
|
+
β βββ cline.rb # Entry point β requires Zeitwerk loader
|
|
998
|
+
β βββ cline/ # Core domain modules
|
|
999
|
+
β β βββ version.rb # Gem version (Cline::VERSION)
|
|
1000
|
+
β β βββ cli.rb # CLI interaction (task, auth, interrupt)
|
|
1001
|
+
β β βββ config.rb # Configuration reader
|
|
1002
|
+
β β βββ data.rb # Cline data directory
|
|
1003
|
+
β β βββ schema.rb # Base JSON schema / serialization
|
|
1004
|
+
β β βββ global_state/ # Global state sub-models (browser, toggles, featuresβ¦)
|
|
1005
|
+
β β βββ serializable/ # File/directory serialization mixins
|
|
1006
|
+
β β βββ utils/ # Utilities (file monitor, enumerable dir objects)
|
|
1007
|
+
βββ spec/ # RSpec test suite
|
|
1008
|
+
β βββ spec_helper.rb # Test bootstrap (SimpleCov, Zeitwerk loader, RSpec config)
|
|
1009
|
+
β βββ cline_test/ # Test support (helpers, CLI stub, mock configs)
|
|
1010
|
+
β βββ scenarios/ # High-level scenario specs (packaging, code quality, docs)
|
|
1011
|
+
βββ tools/ # Compatibility check scripts
|
|
1012
|
+
βββ .rspec # RSpec CLI options
|
|
1013
|
+
βββ .rubocop.yml # RuboCop configuration
|
|
1014
|
+
βββ .releaserc # semantic-release configuration
|
|
1015
|
+
βββ cline-rb.gemspec # Gem specification
|
|
1016
|
+
βββ Gemfile # Main Gemfile
|
|
1017
|
+
βββ Gemfile.local # Local development Gemfile (adds debug, ruby-lsp)
|
|
1018
|
+
```
|
|
1019
|
+
|
|
1020
|
+
### Running tests
|
|
1021
|
+
|
|
1022
|
+
The project uses **RSpec** (~> 3.13) with **SimpleCov** enforcing **98% minimum code coverage**.
|
|
1023
|
+
|
|
1024
|
+
```bash
|
|
1025
|
+
# Run the full test suite
|
|
1026
|
+
bundle exec rspec
|
|
1027
|
+
|
|
1028
|
+
# Run with documentation format (also used in CI)
|
|
1029
|
+
bundle exec rspec --format documentation
|
|
1030
|
+
|
|
1031
|
+
# Run a specific spec file
|
|
1032
|
+
bundle exec rspec spec/scenarios/packaging_spec.rb
|
|
1033
|
+
|
|
1034
|
+
# Run specs matching a tag
|
|
1035
|
+
bundle exec rspec --tag focus
|
|
1036
|
+
|
|
1037
|
+
# Test debug mode β prints verbose test debug output
|
|
1038
|
+
TEST_DEBUG=1 bundle exec rspec
|
|
1039
|
+
```
|
|
1040
|
+
|
|
1041
|
+
The `.rspec` file configures `--color` and `--require spec_helper` by default.
|
|
1042
|
+
|
|
1043
|
+
### Code linting
|
|
1044
|
+
|
|
1045
|
+
The project uses **RuboCop** (~> 1.86) with `rubocop-rspec` and `rubocop-yard` plugins.
|
|
1046
|
+
|
|
1047
|
+
```bash
|
|
1048
|
+
# Run RuboCop linter
|
|
1049
|
+
bundle exec rubocop
|
|
1050
|
+
|
|
1051
|
+
# Auto-correct fixable offenses
|
|
1052
|
+
bundle exec rubocop -a
|
|
1053
|
+
|
|
1054
|
+
# Auto-correct all fixable offenses (including unsafe)
|
|
1055
|
+
bundle exec rubocop -A
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
The custom RuboCop configuration (`.rubocop.yml`) relaxes several metrics (line length: 160, method length: 110, ABC size: 140, etc.) to match the project's coding style.
|
|
1059
|
+
|
|
1060
|
+
### Code coverage
|
|
1061
|
+
|
|
1062
|
+
SimpleCov runs automatically with every test execution. After running the suite, open the report:
|
|
1063
|
+
|
|
1064
|
+
```bash
|
|
1065
|
+
# Coverage report is generated at coverage/index.html
|
|
1066
|
+
open coverage/index.html # macOS
|
|
1067
|
+
start coverage/index.html # Windows
|
|
1068
|
+
xdg-open coverage/index.html # Linux
|
|
1069
|
+
```
|
|
1070
|
+
|
|
1071
|
+
### Building the gem
|
|
1072
|
+
|
|
1073
|
+
Build the gem locally to verify packaging:
|
|
1074
|
+
|
|
1075
|
+
```bash
|
|
1076
|
+
gem build cline-rb.gemspec
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1079
|
+
This produces `cline-rb-<VERSION>.gem` in the current directory. The version is defined in `lib/cline/version.rb` (currently `0.1.0`).
|
|
1080
|
+
|
|
1081
|
+
### Generating YARD documentation
|
|
1082
|
+
|
|
1083
|
+
The project uses **YARD** for API documentation. The test suite enforces **100% documented code**.
|
|
1084
|
+
|
|
1085
|
+
```bash
|
|
1086
|
+
# Generate docs
|
|
1087
|
+
bundle exec yard doc
|
|
1088
|
+
|
|
1089
|
+
# Generate docs with strict mode (fails on warnings)
|
|
1090
|
+
bundle exec yard doc --fail-on-warning
|
|
1091
|
+
|
|
1092
|
+
# Check documentation coverage
|
|
1093
|
+
bundle exec yard stats --list-undoc
|
|
1094
|
+
```
|
|
1095
|
+
|
|
1096
|
+
Generated docs are output to the `doc/` directory (gitignored).
|
|
1097
|
+
|
|
1098
|
+
### Common development tasks
|
|
1099
|
+
|
|
1100
|
+
**Adding a new runtime dependency:**
|
|
1101
|
+
|
|
1102
|
+
Add the dependency to `cline-rb.gemspec` using `spec.add_dependency`, then run `bundle install`.
|
|
1103
|
+
|
|
1104
|
+
**Adding development / test dependencies:**
|
|
1105
|
+
|
|
1106
|
+
Add them to `Gemfile` (shared across the team) or `Gemfile.local` (local only), then run `bundle install`.
|
|
1107
|
+
|
|
1108
|
+
**Running compatibility checks:**
|
|
1109
|
+
|
|
1110
|
+
The `tools/` directory contains scripts that verify cline-rb can read and write real Cline configuration data:
|
|
1111
|
+
|
|
1112
|
+
```bash
|
|
1113
|
+
bundle exec ruby tools/compatibility_check_settings
|
|
1114
|
+
bundle exec ruby tools/compatibility_check_tasks
|
|
1115
|
+
bundle exec ruby tools/compatibility_check_workspaces
|
|
1116
|
+
```
|
|
1117
|
+
|
|
1118
|
+
**Publishing a new release:**
|
|
1119
|
+
|
|
1120
|
+
Releases are automated via **semantic-release** (configured in `.releaserc`). The CI pipeline (`.github/workflows/continuous_integration.yml`) handles version bumps, changelog generation, and gem publishing to [Rubygems.org](https://rubygems.org) when commits are pushed to `main`.
|
|
1121
|
+
|
|
1122
|
+
To manually publish a pre-release version:
|
|
1123
|
+
|
|
1124
|
+
```bash
|
|
1125
|
+
# 1. Update the version in lib/cline/version.rb
|
|
1126
|
+
# 2. Build the gem
|
|
1127
|
+
gem build cline-rb.gemspec
|
|
1128
|
+
# 3. Push to Rubygems.org
|
|
1129
|
+
gem push cline-rb-<VERSION>.gem
|
|
1130
|
+
```
|
|
1131
|
+
|
|
1132
|
+
> Note: Rubygems.org requires **MFA** to be enabled for gem owners (see `spec.metadata['rubygems_mfa_required'] = 'true'` in the gemspec).
|
|
1133
|
+
|
|
1134
|
+
## Contributing
|
|
1135
|
+
|
|
1136
|
+
We welcome contributions to **cline-rb**! π Whether it's a bug report, a feature request, a documentation improvement, or a pull request, your help is appreciated.
|
|
1137
|
+
|
|
1138
|
+
### π Issues
|
|
1139
|
+
|
|
1140
|
+
- π **Bug reports** β Open an issue on the [GitHub issue tracker](https://github.com/Muriel-Salvan/cline-rb/issues). Please include:
|
|
1141
|
+
- A clear and descriptive title.
|
|
1142
|
+
- Steps to reproduce the problem.
|
|
1143
|
+
- The Ruby version, OS, and Cline CLI version you're using.
|
|
1144
|
+
- Any relevant error output or stack traces.
|
|
1145
|
+
- β¨ **Feature requests** β Describe what you'd like to see added, why it's useful, and (if applicable) how you envision the API.
|
|
1146
|
+
- Before opening a new issue, please search the [existing issues](https://github.com/Muriel-Salvan/cline-rb/issues) to avoid duplicates.
|
|
1147
|
+
|
|
1148
|
+
### π΄ Fork & Pull Request workflow
|
|
1149
|
+
|
|
1150
|
+
1. **Fork** the repository on GitHub.
|
|
1151
|
+
2. **Create a feature branch** from `main`: `git checkout -b my-feature-branch`.
|
|
1152
|
+
3. **Make your changes** β follow the existing code style and conventions (RuboCop enforces them).
|
|
1153
|
+
4. **Write or update tests** β all changes should be covered by RSpec examples, and the **minimum code coverage is 98%** (enforced by SimpleCov).
|
|
1154
|
+
5. **Run the full test suite** before committing:
|
|
1155
|
+
```bash
|
|
1156
|
+
bundle exec rspec
|
|
1157
|
+
```
|
|
1158
|
+
Run a single spec file to iterate faster:
|
|
1159
|
+
```bash
|
|
1160
|
+
bundle exec rspec spec/my_spec.rb
|
|
1161
|
+
```
|
|
1162
|
+
Run a specific example by line number:
|
|
1163
|
+
```bash
|
|
1164
|
+
bundle exec rspec spec/my_spec.rb:42
|
|
1165
|
+
```
|
|
1166
|
+
6. **Run the linter** to ensure code quality:
|
|
1167
|
+
```bash
|
|
1168
|
+
bundle exec rubocop
|
|
1169
|
+
```
|
|
1170
|
+
The CI also runs RuboCop and enforces **no offenses detected** (check [`spec/scenarios/code_quality_spec.rb`](https://github.com/Muriel-Salvan/cline-rb/blob/main/spec/scenarios/code_quality_spec.rb)).
|
|
1171
|
+
7. **Document your code** β this project enforces **100% documented code** via YARD (see [`spec/scenarios/documentation_spec.rb`](https://github.com/Muriel-Salvan/cline-rb/blob/main/spec/scenarios/documentation_spec.rb)). Run locally to verify:
|
|
1172
|
+
```bash
|
|
1173
|
+
bundle exec yard doc --fail-on-warning
|
|
1174
|
+
bundle exec yard stats --list-undoc --fail-on-warning
|
|
1175
|
+
```
|
|
1176
|
+
8. **Commit your changes** using clear, descriptive commit messages.
|
|
1177
|
+
9. **Push** to your fork and open a **Pull Request** against the `main` branch of the upstream repository.
|
|
1178
|
+
|
|
1179
|
+
### β
Pull Request guidelines
|
|
1180
|
+
|
|
1181
|
+
- Reference any related issue(s) in the PR description (e.g. "Fixes #123" or "Closes #456").
|
|
1182
|
+
- Keep PRs focused β one feature or fix per PR is ideal.
|
|
1183
|
+
- Ensure **all checks pass** on GitHub (when CI is configured): tests, linting, documentation coverage, and gem packaging.
|
|
1184
|
+
- The project uses [**semantic-release**](https://github.com/semantic-release/semantic-release) for versioning. Commit messages should follow conventional commit format for automatic changelog generation.
|
|
1185
|
+
|
|
1186
|
+
### π CI & Quality gates
|
|
1187
|
+
|
|
1188
|
+
The repository enforces the following checks (see [`spec/scenarios/`](https://github.com/Muriel-Salvan/cline-rb/tree/main/spec/scenarios)):
|
|
1189
|
+
|
|
1190
|
+
| Check | Requirement |
|
|
1191
|
+
|---|---|
|
|
1192
|
+
| β
**Tests** | All RSpec examples pass (run via `bundle exec rspec`) |
|
|
1193
|
+
| π§Ή **RuboCop** | Zero offenses (`rubocop` must pass) |
|
|
1194
|
+
| π **YARD docs** | 100% documented code |
|
|
1195
|
+
| π¦ **Gem packaging** | The gem must build successfully (`gem build cline-rb.gemspec`) |
|
|
1196
|
+
| π **Code coverage** | Minimum **98%** coverage (SimpleCov) |
|
|
1197
|
+
|
|
1198
|
+
### π License
|
|
1199
|
+
|
|
1200
|
+
By contributing, you agree that your contributions will be licensed under the [BSD 3-Clause License](https://github.com/Muriel-Salvan/cline-rb/blob/main/LICENSE).
|
|
1201
|
+
|
|
1202
|
+
### π¬ Questions?
|
|
1203
|
+
|
|
1204
|
+
If you have any questions or need help, feel free to open a [discussion](https://github.com/Muriel-Salvan/cline-rb/discussions) or reach out to the maintainer.
|
|
1205
|
+
|
|
1206
|
+
---
|
|
1207
|
+
|
|
1208
|
+
*Thank you for taking the time to contribute! π*
|
|
1209
|
+
|
|
1210
|
+
## License
|
|
1211
|
+
|
|
1212
|
+
The gem is available as open source under the terms of the [BSD 3-Clause License](LICENSE).
|
|
1213
|
+
|
|
1214
|
+
Copyright (c) 2026, Muriel Salvan. All rights reserved.
|
|
1215
|
+
|
|
1216
|
+
See the [LICENSE](LICENSE) file for the full license text.
|