Class: RailsInformant::SkillGenerator

Inherits:
Rails::Generators::Base
  • Object
show all
Defined in:
lib/generators/rails_informant/skill_generator.rb

Constant Summary collapse

Content =
ClaudeIntegrationContent

Instance Method Summary collapse

Instance Method Details

#clear_drift_flagObject



57
58
59
# File 'lib/generators/rails_informant/skill_generator.rb', line 57

def clear_drift_flag
  RailsInformant::Integration.new(app_root: destination_root).write_drift_flag stale: false
end

#copy_hook_scriptObject



15
16
17
18
# File 'lib/generators/rails_informant/skill_generator.rb', line 15

def copy_hook_script
  copy_file "informant-alerts.sh", ".claude/hooks/informant-alerts.sh"
  chmod ".claude/hooks/informant-alerts.sh", 0o755
end

#copy_skill_fileObject



11
12
13
# File 'lib/generators/rails_informant/skill_generator.rb', line 11

def copy_skill_file
  copy_file "SKILL.md", ".claude/skills/informant/SKILL.md"
end

#create_or_update_mcp_jsonObject



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/generators/rails_informant/skill_generator.rb', line 20

def create_or_update_mcp_json
  mcp_path = File.join(destination_root, ".mcp.json")

  if File.exist?(mcp_path)
    existing = JSON.parse(File.read(mcp_path))
    existing["mcpServers"] ||= {}
    existing["mcpServers"]["informant"] = Content.mcp_entry
    create_file ".mcp.json", JSON.pretty_generate(existing) + "\n", force: true
  else
    create_file ".mcp.json", JSON.pretty_generate(
      "mcpServers" => { "informant" => Content.mcp_entry }
    ) + "\n"
  end
rescue JSON::ParserError
  say "Could not parse existing .mcp.json — skipping merge. Add the informant server manually.", :red
end

#create_or_update_settings_jsonObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/generators/rails_informant/skill_generator.rb', line 37

def create_or_update_settings_json
  settings_path = File.join(destination_root, ".claude", "settings.json")

  if File.exist?(settings_path)
    existing = JSON.parse(File.read(settings_path))
    existing["hooks"] = migrate_informant_hooks(existing["hooks"])
    # Coerce a hand-written non-array event value (a lone hook object, a string)
    # to an array so registering never raises NoMethodError on <<.
    existing["hooks"][Content::HOOK_EVENT] = [] unless existing["hooks"][Content::HOOK_EVENT].is_a?(Array)
    existing["hooks"][Content::HOOK_EVENT] << Content.hook_registration
    create_file ".claude/settings.json", JSON.pretty_generate(existing) + "\n", force: true
  else
    create_file ".claude/settings.json", JSON.pretty_generate(
      "hooks" => Content.expected_registrations
    ) + "\n"
  end
rescue JSON::ParserError
  say "Could not parse existing .claude/settings.json — skipping hook setup.", :red
end


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/generators/rails_informant/skill_generator.rb', line 61

def print_next_steps
  say ""
  say "Claude Code integration installed!", :green
  say ""
  say "  Created .mcp.json"
  say "  Created .claude/skills/informant/SKILL.md"
  say "  Created .claude/hooks/informant-alerts.sh"
  say "  Created .claude/settings.json (UserPromptSubmit hook)"
  say ""
  say "Next step — set env vars so the MCP server and startup alerts can reach your app.", :yellow
  say "Add to your .envrc (or export manually):"
  say ""
  say "  export INFORMANT_PRODUCTION_URL=https://your-app.com"
  say "  export INFORMANT_PRODUCTION_TOKEN=<same token from credentials>"
  say ""
  say "The token must match rails_informant.api_token in your Rails credentials."
  say "Add .envrc to .gitignore — it contains secrets."
  say ""
  say "Optional: install jq for startup error alerts (brew install jq)", :cyan
end