Class: Explore::ClaudeConfig

Inherits:
Object
  • Object
show all
Defined in:
lib/explore/claude_config.rb

Constant Summary collapse

MANAGED_MARKER =
"<!-- Managed by explore setup claude. -->".freeze

Instance Method Summary collapse

Constructor Details

#initialize(env:) ⇒ ClaudeConfig

Returns a new instance of ClaudeConfig.



9
10
11
# File 'lib/explore/claude_config.rb', line 9

def initialize(env:)
  @env = env
end

Instance Method Details

#apply!Object



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
# File 'lib/explore/claude_config.rb', line 38

def apply!
  report = inspect
  status = report.fetch(:entry_status)
  raise write_error(report, "Multiple Explore Claude config entries were found. Choose one path manually.") if status == "ambiguous"
  raise write_error(report, "Existing Explore Claude config is not safely managed by Explore. Use --print-config and update it manually.") if %w[customized unreadable].include?(status)

  return report.merge(action: "unchanged", backup_path: nil) if report.fetch(:entry_matches)

  target_path = report.fetch(:target_path)
  current_contents = File.file?(target_path) ? File.read(target_path) : nil
  backup_path = backup_path_for(target_path) if current_contents

  FileUtils.mkdir_p(File.dirname(target_path))
  File.write(backup_path, current_contents) if backup_path
  File.write(target_path, expected_content_for(report.fetch(:target_type)))

  inspect.merge(
    entry_status: status == "missing" ? "installed" : "updated",
    exact_changes: [],
    action: current_contents ? "updated" : "installed",
    backup_path:
  )
rescue SystemCallError => e
  raise Explore::Cli::Error.new("Could not write Claude config at #{target_path}: #{e.message}", exit_code: 1)
end

#inspectObject



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/explore/claude_config.rb', line 13

def inspect
  entries = candidate_entries
  existing_entries = entries.select { |entry| entry.fetch(:exists) }
  target_entry = target_entry_for(entries, existing_entries)
  status = status_for(target_entry, existing_entries)
  entry_matches = target_entry && target_entry.fetch(:matches_expected)
  manual_intervention_required = %w[ambiguous customized unreadable].include?(status)

  {
    config_found: config_root_exist?(entries),
    config_root: File.join(home_directory, ".claude"),
    preferred_path: preferred_entry.fetch(:path),
    target_path: target_entry&.fetch(:path) || preferred_entry.fetch(:path),
    target_type: target_entry&.fetch(:type) || preferred_entry.fetch(:type),
    entry_exists: target_entry ? target_entry.fetch(:exists) : false,
    entry_matches: entry_matches || false,
    entry_status: status,
    manual_intervention_required:,
    write_supported: !manual_intervention_required,
    exact_changes: exact_changes_for(target_entry, status),
    detected_entries: entries.map { |entry| detected_entry_payload(entry) },
    config_snippet: expected_content_for((target_entry || preferred_entry).fetch(:type))
  }
end