Class: Consolle::CLI
- Inherits:
-
Thor
- Object
- Thor
- Consolle::CLI
- Defined in:
- lib/consolle/cli.rb
Class Method Summary collapse
- .exit_on_failure? ⇒ Boolean
- .help(shell, subcommand = false) ⇒ Object
- .start(given_args = ARGV, config = {}) ⇒ Object
Instance Method Summary collapse
- #exec(*code_parts) ⇒ Object
- #help(command = nil) ⇒ Object
- #ls ⇒ Object
- #restart ⇒ Object
- #rule(file_path) ⇒ Object
- #start ⇒ Object
- #status ⇒ Object
- #stop ⇒ Object
- #stop_all ⇒ Object
- #version ⇒ Object
Class Method Details
.exit_on_failure? ⇒ Boolean
69 70 71 |
# File 'lib/consolle/cli.rb', line 69 def self.exit_on_failure? true end |
.help(shell, subcommand = false) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/consolle/cli.rb', line 28 def help(shell, subcommand = false) if subcommand == false shell.say 'Consolle - Rails console management tool', :cyan shell.say shell.say 'USAGE:', :yellow shell.say ' cone [COMMAND] [OPTIONS]' shell.say shell.say 'COMMANDS:', :yellow shell.say ' cone start # Start Rails console in background' shell.say ' cone stop # Stop Rails console' shell.say ' cone restart # Restart Rails console' shell.say ' cone status # Show Rails console status' shell.say ' cone exec CODE # Execute Ruby code in Rails console' shell.say ' cone ls # List active Rails console sessions' shell.say ' cone stop_all # Stop all Rails console sessions' shell.say ' cone rule FILE # Write cone command guide to FILE' shell.say ' cone version # Show version' shell.say shell.say 'GLOBAL OPTIONS:', :yellow shell.say ' -v, --verbose # Enable verbose output' shell.say ' -t, --target NAME # Target session name (default: cone)' shell.say ' -h, --help # Show this help message' shell.say shell.say 'EXAMPLES:', :yellow shell.say " cone exec 'User.count' # Execute code in default session" shell.say " RAILS_ENV=production cone start # Start console in production" shell.say " cone exec -t api 'Rails.env' # Execute code in 'api' session" shell.say ' cone exec -f script.rb # Execute code from file' shell.say shell.say 'For more information on a specific command:' shell.say ' cone COMMAND --help' shell.say else super end end |
.start(given_args = ARGV, config = {}) ⇒ Object
18 19 20 21 22 23 24 25 26 |
# File 'lib/consolle/cli.rb', line 18 def start(given_args = ARGV, config = {}) # Intercept --help at the top level if given_args == ['--help'] || given_args == ['-h'] || given_args.empty? shell = Thor::Base.shell.new help(shell) return end super end |
Instance Method Details
#exec(*code_parts) ⇒ Object
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 |
# File 'lib/consolle/cli.rb', line 485 def exec(*code_parts) ensure_rails_project! ensure_project_directories validate_session_name!([:target]) # Handle code input from file or arguments first code = if [:file] path = File.([:file]) unless File.file?(path) puts "Error: File not found: #{path}" exit 1 end File.read(path, mode: 'r:UTF-8') else code_parts.join(' ') end if code.strip.empty? puts 'Error: No code provided (pass CODE or use -f FILE)' exit 1 end session_info = load_session_info server_running = false # Check if server is running if session_info begin # Try to connect to socket and get status socket = UNIXSocket.new(session_info[:socket_path]) request = { 'action' => 'status', 'request_id' => SecureRandom.uuid } socket.write(JSON.generate(request)) socket.write("\n") socket.flush response_data = socket.gets socket.close response = JSON.parse(response_data) server_running = response['success'] && response['running'] rescue StandardError # Server not responsive server_running = false end end # Check if server is running unless server_running puts '✗ Rails console is not running' puts 'Please start it first with: cone start' exit 1 end # Apply Claude Code escape fix unless --raw option is specified code = code.gsub('\\!', '!') unless [:raw] puts "Executing: #{code}" if [:verbose] # Send code to socket send_opts = { timeout: [:timeout] } send_opts[:pre_sigint] = [:pre_sigint] unless [:pre_sigint].nil? result = send_code_to_socket( session_info[:socket_path], code, **send_opts ) # Log the request and response log_session_activity(session_info[:process_pid], code, result) if result['success'] # Always print result, even if empty (multiline code often returns empty string) puts result['result'] unless result['result'].nil? # Always show execution time when available puts "Execution time: #{result['execution_time'].round(3)}s" if result['execution_time'] else # Display error information if result['error_code'] puts "Error: #{result['error_code']}" else puts "Error: #{result['error']}" end # Show error class in verbose mode if [:verbose] && result['error_class'] puts "Error Class: #{result['error_class']}" end puts result['message'] puts result['backtrace']&.join("\n") if [:verbose] && result['backtrace'] # Show execution time for errors too puts "Execution time: #{result['execution_time'].round(3)}s" if result['execution_time'] exit 1 end end |
#help(command = nil) ⇒ Object
97 98 99 100 101 102 103 |
# File 'lib/consolle/cli.rb', line 97 def help(command = nil) if command self.class.command_help(shell, command) else self.class.help(shell) end end |
#ls ⇒ Object
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/consolle/cli.rb', line 239 def ls ensure_rails_project! sessions = load_sessions if sessions.empty? || sessions.size == 1 && sessions.key?('_schema') puts 'No active sessions' return end active_sessions = [] stale_sessions = [] sessions.each do |name, info| next if name == '_schema' # Skip schema field # Check if process is alive if info['process_pid'] && process_alive?(info['process_pid']) # Try to get server status adapter = create_rails_adapter(current_rails_env, name) server_status = begin adapter.get_status rescue StandardError nil end if server_status && server_status['success'] && server_status['running'] rails_env = server_status['rails_env'] || 'development' console_pid = server_status['pid'] || info['process_pid'] active_sessions << "#{name} (#{rails_env}) - PID: #{console_pid}" else stale_sessions << name end else stale_sessions << name end end # Clean up stale sessions if stale_sessions.any? with_sessions_lock do sessions = load_sessions stale_sessions.each { |name| sessions.delete(name) } save_sessions(sessions) end end if active_sessions.empty? puts 'No active sessions' else active_sessions.each { |session| puts session } end end |
#restart ⇒ Object
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 |
# File 'lib/consolle/cli.rb', line 394 def restart ensure_rails_project! validate_session_name!([:target]) adapter = create_rails_adapter(current_rails_env, [:target]) if adapter.running? # Check if environment needs to be changed current_status = begin adapter.get_status rescue StandardError nil end current_env = current_status&.dig('rails_env') || 'development' desired_env = current_rails_env needs_full_restart = [:force] || (current_env != desired_env) if needs_full_restart if current_env != desired_env puts "Environment change detected (#{current_env} -> #{desired_env})" puts 'Performing full server restart...' else puts 'Force restarting Rails console server...' end stop sleep 1 invoke(:start) else puts 'Restarting Rails console subprocess...' # Send restart request to the socket server request = { 'action' => 'restart', 'request_id' => SecureRandom.uuid } begin # Use direct socket connection for restart request socket = UNIXSocket.new(adapter.socket_path) socket.write(JSON.generate(request)) socket.write("\n") socket.flush response_data = socket.gets socket.close response = JSON.parse(response_data) if response['success'] puts '✓ Rails console subprocess restarted' puts " New PID: #{response['pid']}" if response['pid'] else puts "✗ Failed to restart: #{response['message']}" puts "You can try 'cone restart --force' to restart the entire server" end rescue StandardError => e puts "✗ Error restarting: #{e.}" puts "You can try 'cone restart --force' to restart the entire server" end end else puts 'Rails console is not running. Starting it...' invoke(:start) end end |
#rule(file_path) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/consolle/cli.rb', line 106 def rule(file_path) # Read the embedded rule content rule_content = File.read(File.('../../rule.md', __dir__)) # Write to the specified file File.write(file_path, rule_content) puts "✓ Cone command guide written to #{file_path}" rescue StandardError => e puts "✗ Failed to write rule file: #{e.}" exit 1 end |
#start ⇒ Object
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/consolle/cli.rb', line 137 def start ensure_rails_project! ensure_project_directories validate_session_name!([:target]) # Check if already running using session info session_info = load_session_info if session_info && session_info[:process_pid] # Check if process is still running begin Process.kill(0, session_info[:process_pid]) # Check if socket is ready if File.exist?(session_info[:socket_path]) puts "Rails console is already running (PID: #{session_info[:process_pid]})" puts "Socket: #{session_info[:socket_path]}" return end rescue Errno::ESRCH # Process not found, clean up session clear_session_info end elsif session_info # Session file exists but no valid PID, clean up clear_session_info end adapter = create_rails_adapter(current_rails_env, [:target], [:command], [:wait_timeout]) puts 'Starting Rails console...' begin adapter.start puts '✓ Rails console started successfully' puts " PID: #{adapter.process_pid}" puts " Socket: #{adapter.socket_path}" # Save session info save_session_info(adapter) # Log session start log_session_event(adapter.process_pid, 'session_start', { rails_env: current_rails_env, socket_path: adapter.socket_path }) rescue StandardError => e puts "✗ Failed to start Rails console: #{e.}" exit 1 end end |
#status ⇒ Object
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/consolle/cli.rb', line 188 def status ensure_rails_project! validate_session_name!([:target]) session_info = load_session_info if session_info.nil? puts 'No active Rails console session found' return end # Check if server is actually responsive adapter = create_rails_adapter(current_rails_env, [:target]) server_status = begin adapter.get_status rescue StandardError nil end process_running = server_status && server_status['success'] && server_status['running'] if process_running rails_env = server_status['rails_env'] || 'unknown' console_pid = server_status['pid'] || 'unknown' puts '✓ Rails console is running' puts " PID: #{console_pid}" puts " Environment: #{rails_env}" puts " Session: #{session_info[:socket_path]}" puts ' Ready for input: Yes' else puts '✗ Rails console is not running' clear_session_info end end |
#stop ⇒ Object
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
# File 'lib/consolle/cli.rb', line 294 def stop ensure_rails_project! validate_session_name!([:target]) adapter = create_rails_adapter('development', [:target]) if adapter.running? puts 'Stopping Rails console...' if adapter.stop puts '✓ Rails console stopped' # Log session stop session_info = load_session_info if session_info && session_info[:process_pid] log_session_event(session_info[:process_pid], 'session_stop', { reason: 'user_requested' }) end else puts '✗ Failed to stop Rails console' end else puts 'Rails console is not running' end clear_session_info end |
#stop_all ⇒ Object
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
# File 'lib/consolle/cli.rb', line 325 def stop_all ensure_rails_project! sessions = load_sessions active_sessions = [] # Filter active sessions (excluding schema) sessions.each do |name, info| next if name == '_schema' active_sessions << { name: name, info: info } if info['process_pid'] && process_alive?(info['process_pid']) end if active_sessions.empty? puts 'No active sessions to stop' return end puts "Found #{active_sessions.size} active session(s)" # Stop each active session active_sessions.each do |session| name = session[:name] info = session[:info] puts "\nStopping session '#{name}'..." adapter = create_rails_adapter('development', name) if adapter.stop puts "✓ Session '#{name}' stopped" # Log session stop if info['process_pid'] log_session_event(info['process_pid'], 'session_stop', { reason: 'stop_all_requested' }) end # Clear session info with_sessions_lock do sessions = load_sessions sessions.delete(name) save_sessions(sessions) end else puts "✗ Failed to stop session '#{name}'" end end puts "\n✓ All sessions stopped" end |