Skip to content

Commit 89b440a

Browse files
Add simple AI Harness
Relates to #1350 and #1351. We introduced [thoughtbot agents rules](thoughtbot/guides#783) to our guides a few months ago. This commit simply pulls those files into newly generated Suspenders applications. There's a case to be made that these should be kept separate, but I like having a single source of truth.
1 parent 863bac9 commit 89b440a

4 files changed

Lines changed: 75 additions & 0 deletions

File tree

.github/workflows/main.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ jobs:
8888
end
8989
end
9090
EOF
91+
- name: Verify AI harness files exist
92+
working-directory: /tmp/test_app
93+
run: |
94+
test -f .claude/CLAUDE.md || (echo ".claude/CLAUDE.md not found" && exit 1)
95+
test -d .claude/rules || (echo ".claude/rules directory not found" && exit 1)
96+
test "$(ls -A .claude/rules)" || (echo ".claude/rules is empty" && exit 1)
97+
test ! -f .claude/rules/README.md || (echo ".claude/rules/README.md should not be downloaded" && exit 1)
9198
- name: Run tests in generated app
9299
env:
93100
RAILS_ENV: test

FEATURES.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,25 @@ Configuration can be found at `config/initializers/inline_svg.rb`
181181
[lang]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang
182182
[title]: https://github.com/calebhearth/title
183183
[Prefetch]: https://turbo.hotwired.dev/handbook/drive#prefetching-links-on-hover
184+
185+
## AI Harness
186+
187+
Downloads [AI rules][] from [thoughtbot/guides][] into `.claude/` at app
188+
generation time:
189+
190+
- `.claude/CLAUDE.md` - a project brief that AI assistants load as context.
191+
- `.claude/rules/` - coding standards for models, controllers, testing,
192+
security, views, and database conventions.
193+
194+
Because the files are fetched from GitHub when the app is generated, they
195+
always reflect the latest version of the guides at that point in time.
196+
197+
### Customize `CLAUDE.md`
198+
199+
The generated `.claude/CLAUDE.md` is a starting point. Update it with
200+
project-specific details so AI assistants have accurate context for your
201+
application — including domain language, architectural decisions, and any
202+
conventions that diverge from the defaults in `.claude/rules/`.
203+
204+
[AI rules]: https://github.com/thoughtbot/guides/tree/main/rails/ai-rules
205+
[thoughtbot/guides]: https://github.com/thoughtbot/guides

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
Unreleased
22

3+
* Added: AI harness. Downloads `.claude/CLAUDE.md` and `.claude/rules/` from [thoughtbot/guides](https://github.com/thoughtbot/guides/tree/main/rails/ai-rules).
4+
35
20260325.0 (March 25, 2026)
46

57
* Added: Hotwire Spark for live reloading in development.

lib/templates/web.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
require "suspenders/version"
2+
require "net/http"
3+
require "json"
24

35
# Methods like `copy_file` will accept relative paths to the template's location.
46
def source_paths
@@ -69,6 +71,7 @@ def install_gems
6971
# Finalization
7072
run_migrations
7173
update_readme
74+
add_ai_harness
7275
lint_codebase
7376
commit_final_application_state
7477

@@ -516,6 +519,28 @@ def update_readme
516519
[lang]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang
517520
[title]: https://github.com/calebhearth/title
518521
[Prefetch]: https://turbo.hotwired.dev/handbook/drive#prefetching-links-on-hover
522+
523+
## AI Harness
524+
525+
Downloads [AI rules][] from [thoughtbot/guides][] into `.claude/` at app
526+
generation time:
527+
528+
- `.claude/CLAUDE.md` - a project brief that AI assistants load as context.
529+
- `.claude/rules/` - coding standards for models, controllers, testing,
530+
security, views, and database conventions.
531+
532+
Because the files are fetched from GitHub when the app is generated, they
533+
always reflect the latest version of the guides at that point in time.
534+
535+
### Customize `CLAUDE.md`
536+
537+
The generated `.claude/CLAUDE.md` is a starting point. Update it with
538+
project-specific details so AI assistants have accurate context for your
539+
application — including domain language, architectural decisions, and any
540+
conventions that diverge from the defaults in `.claude/rules/`.
541+
542+
[AI rules]: https://github.com/thoughtbot/guides/tree/main/rails/ai-rules
543+
[thoughtbot/guides]: https://github.com/thoughtbot/guides
519544
MARKDOWN
520545
end
521546
end
@@ -524,6 +549,25 @@ def lint_codebase
524549
run "bin/rubocop -a"
525550
end
526551

552+
def add_ai_harness
553+
base_url = "https://raw.githubusercontent.com/thoughtbot/guides/main/rails/ai-rules"
554+
api_url = "https://api.github.com/repos/thoughtbot/guides/contents/rails/ai-rules/rules"
555+
556+
empty_directory ".claude"
557+
empty_directory ".claude/rules"
558+
559+
get "#{base_url}/CLAUDE.md", ".claude/CLAUDE.md"
560+
561+
response = Net::HTTP.get(URI(api_url))
562+
files = JSON.parse(response)
563+
files.each do |file|
564+
next unless file["type"] == "file"
565+
next if file["name"].casecmp?("README.md")
566+
567+
get "#{base_url}/rules/#{file["name"]}", ".claude/rules/#{file["name"]}"
568+
end
569+
end
570+
527571
def commit_final_application_state
528572
git add: ".", commit: %(-m 'Changes introduced by Suspenders version #{Suspenders::VERSION}') unless ENV["CI"]
529573
end

0 commit comments

Comments
 (0)