Module: Everywhere::AgentsGuide

Defined in:
lib/everywhere/agents_guide.rb

Overview

The AGENTS.md guide every install --agents writes into an app, so AI coding agents (Claude Code, Cursor, Copilot, Codex) understand what RubyEverywhere is before they "fix" the config edits install made.

The guide is prose, so it lives as markdown under support/agents/ rather than in a heredoc — code fences and #{} snippets are miserable to escape in Ruby, and the gemspec already globs support/**/*. Assembly is a shared body plus per-framework fragments (install notes, view helpers) and a mode fragment, joined by {PLACEHOLDER} gsub.

Constant Summary collapse

BEGIN_MARKER =

The generated section is fenced so a re-run can refresh it without touching anything the app's own authors wrote around it.

"<!-- rubyeverywhere:begin -->"
END_MARKER =
"<!-- rubyeverywhere:end -->"
PLACEHOLDER =
/\{\{([A-Z_]+)\}\}/
LABELS =
{ "rails" => "Rails", "sinatra" => "Sinatra", "hanami" => "Hanami" }.freeze

Class Method Summary collapse

Class Method Details

.block(framework:, mode:) ⇒ Object

The body wrapped in the markers, ready to splice into an AGENTS.md.



40
41
42
# File 'lib/everywhere/agents_guide.rb', line 40

def block(framework:, mode:)
  "#{BEGIN_MARKER}\n#{render(framework: framework, mode: mode).strip}\n#{END_MARKER}\n"
end

.read(*parts) ⇒ Object



50
51
52
53
54
55
# File 'lib/everywhere/agents_guide.rb', line 50

def read(*parts)
  path = File.join(template_dir, *parts)
  File.exist?(path) or UI.die!("couldn't find the bundled AGENTS.md template at #{path}; " \
                               "reinstall ruby_everywhere")
  File.read(path)
end

.render(framework:, mode:) ⇒ Object

The guide body for one app, with no markers around it.



30
31
32
33
34
35
36
37
# File 'lib/everywhere/agents_guide.rb', line 30

def render(framework:, mode:)
  substitute(read("AGENTS.md"),
    "FRAMEWORK" => LABELS.fetch(framework),
    "MODE" => mode,
    "FRAMEWORK_NOTES" => read("frameworks", "#{framework}.md").strip,
    "FRAMEWORK_VIEWS" => read("frameworks", "#{framework}-views.md").strip,
    "MODE_NOTES" => read("modes", "#{mode}.md").strip)
end

.substitute(body, values) ⇒ Object

fetch, not [], so a typo'd placeholder blows up in the test suite instead of shipping "{MDOE}" to somebody's repo.



46
47
48
# File 'lib/everywhere/agents_guide.rb', line 46

def substitute(body, values)
  body.gsub(PLACEHOLDER) { values.fetch(Regexp.last_match(1)) }
end

.template_dirObject



27
# File 'lib/everywhere/agents_guide.rb', line 27

def template_dir = File.join(Paths.gem_root, "support", "agents")