rails-hyperdrive 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +299 -4
- data/README.md +71 -36
- data/lib/generators/hyperdrive/install/USAGE +11 -3
- data/lib/generators/hyperdrive/install/install_generator.rb +25 -10
- data/lib/generators/hyperdrive/install_summary.rb +3 -3
- data/lib/generators/hyperdrive/sync/USAGE +7 -5
- data/lib/generators/hyperdrive/sync/sync_generator.rb +1 -1
- data/lib/generators/hyperdrive/sync_runner.rb +20 -10
- data/lib/hyperdrive/skill_tasks.rb +39 -0
- data/lib/rails/commands/hyperdrive/hyperdrive_command.rb +59 -0
- data/lib/rails/hyperdrive/ancestor_locator.rb +10 -13
- data/lib/rails/hyperdrive/artifact_status.rb +16 -7
- data/lib/rails/hyperdrive/auto_install.rb +25 -7
- data/lib/rails/hyperdrive/bundler_artifact_discovery.rb +360 -150
- data/lib/rails/hyperdrive/canonical_skill_render.rb +68 -39
- data/lib/rails/hyperdrive/companion_discovery.rb +4 -5
- data/lib/rails/hyperdrive/gem_manifest.rb +311 -80
- data/lib/rails/hyperdrive/gemspec_locator.rb +38 -0
- data/lib/rails/hyperdrive/install_layout.rb +148 -12
- data/lib/rails/hyperdrive/install_pipeline.rb +142 -78
- data/lib/rails/hyperdrive/install_plan.rb +21 -9
- data/lib/rails/hyperdrive/lock_file.rb +25 -3
- data/lib/rails/hyperdrive/manifest_lint.rb +230 -0
- data/lib/rails/hyperdrive/skill_template.rb +7 -5
- data/lib/rails/hyperdrive/tools/run_sql.rb +1 -1
- data/lib/rails/hyperdrive/version.rb +1 -1
- data/lib/rails/hyperdrive.rb +0 -22
- metadata +9 -8
- data/lib/generators/hyperdrive/install/templates/initializer.rb.tt +0 -3
- data/lib/rails/hyperdrive/skill_tasks.rb +0 -27
- data/lib/tasks/hyperdrive.rake +0 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 19c65882e51a2efb328a453fec5a561af7b9b012e09623f39eba055b7898bcab
|
|
4
|
+
data.tar.gz: e2bdf0a95fe1ed81db2bb56f0f649c924f502b28a7577f6931778ebb95ca81c0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e2f083bf83220b970052d44b95c11f6d69b26a58801094cdce349de803b4497983925ba4082d1167e17226d0e5511ac328dc644d71239f7c5694c853f49f6dad
|
|
7
|
+
data.tar.gz: 955afb3426b981ae68136de0f8f3e1d8ecceb70abcb7a56579b7aaeeb00824915cc273b00244315ba2d49d94a8d0a73bfbe7e68d5c5750a5830a5e1fbaeba52e
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,299 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.7.0] - 2026-08-26
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Two new companion artifact kinds: agents and commands.** A companion gem can
|
|
15
|
+
now ship Claude Code subagents from `agents/*.md` (installed to
|
|
16
|
+
`.claude/agents/<name>.md`) and slash commands from `commands/*.md` (installed
|
|
17
|
+
to `.claude/commands/<name>.md`), alongside its skills and guidelines. Both
|
|
18
|
+
are flat single files that install byte-identical to what the gem ships, and
|
|
19
|
+
both ride the whole existing machine: gating, the `hyperdrive_version:` fence,
|
|
20
|
+
sha-based drift, `--overwrite`/`--sidecar`/`--merge`, `disabled:`, the stale
|
|
21
|
+
sweep, cross-source collision postfixing, and the additive top-up on
|
|
22
|
+
`bundle install`. Agents require `name` + `description` frontmatter like a
|
|
23
|
+
skill; a command's frontmatter is optional and never validated, and its
|
|
24
|
+
identity is its filename stem, so `commands/analyze.md` becomes `/analyze`.
|
|
25
|
+
Neither is wired into `CLAUDE.md` or `index.md` — Claude Code registers them
|
|
26
|
+
by file presence. Installing flat (no per-gem subdirectory) keeps the
|
|
27
|
+
`skills/`/`agents/`/`commands/` sibling geometry a gem ships, so relative
|
|
28
|
+
links between them resolve unchanged after install.
|
|
29
|
+
- Manifest additions in `hyperdrive.yml`: `agents:` and `commands:` gating
|
|
30
|
+
sections keyed by filename, taking the same values `guidelines:` entries do;
|
|
31
|
+
`agents_dir:` and `commands_dir:` to name additional roots (resolved like
|
|
32
|
+
`skills_dir:`); and `command_prefix:`, an optional gem-wide scalar inside
|
|
33
|
+
`commands:` that installs every command of that gem as `<prefix>-<filename>`,
|
|
34
|
+
for a companion that also ships as a Claude Code plugin and wants its
|
|
35
|
+
`/name` namespaced. `rake hyperdrive:manifest:check` lints all of them.
|
|
36
|
+
|
|
37
|
+
- `require "hyperdrive/skill_tasks"` is the require path for the companion-repo
|
|
38
|
+
rake tasks (`hyperdrive:skills:render`, `hyperdrive:skills:check`,
|
|
39
|
+
`hyperdrive:manifest:check`) — framework-neutral, since the tasks run in a
|
|
40
|
+
plain gem repo with no Rails involved.
|
|
41
|
+
- The `hyperdrive_version:` fence now carries a stated guarantee for companion
|
|
42
|
+
authors: it fences on whichever gem implements artifact discovery and install
|
|
43
|
+
— today rails-hyperdrive — and that version numbering is guaranteed
|
|
44
|
+
continuous across any future restructuring of the gem, so a fence like
|
|
45
|
+
`">= 0.8"` keeps its meaning permanently.
|
|
46
|
+
- `rake hyperdrive:manifest:check`, a strict author-side lint of a companion
|
|
47
|
+
gem's `hyperdrive.yml`, on the same companion-repo rake surface as
|
|
48
|
+
`hyperdrive:skills:*` (add `require "hyperdrive/skill_tasks"` to the
|
|
49
|
+
Rakefile; takes the same optional gemspec-path argument). Where the installer
|
|
50
|
+
is permissive so a manifest written for a newer schema never blocks an
|
|
51
|
+
install, the lint fails: unknown keys at every level — the top level,
|
|
52
|
+
`skills:`/`guidelines:` entries, and `conditional:` entries — plus any
|
|
53
|
+
`gem:`/`gems:` or `hyperdrive_version:` value the installer cannot parse, and
|
|
54
|
+
`skills:`/`guidelines:`/`conditional:` keys naming nothing the gem ships. The
|
|
55
|
+
retired `versions:` key and its `version:` near-miss are named pointedly.
|
|
56
|
+
A manifest that lints clean draws no gating warning at install time.
|
|
57
|
+
- A template/content-paired skill's supporting files can be templated too: a
|
|
58
|
+
`*.md.erb` in the template directory renders against the app's bundle and
|
|
59
|
+
installs as `x.md`, so generic skills.sh consumers never copy raw ERB. Within
|
|
60
|
+
a paired skill a template-side file owns its target path — the content
|
|
61
|
+
directory's same-named file never installs, whether the template renders, is
|
|
62
|
+
gated out by `conditional:`, or fails to render.
|
|
63
|
+
`rake hyperdrive:skills:render` now writes each supporting template's
|
|
64
|
+
fail-open canonical face into the paired content directory, and
|
|
65
|
+
`rake hyperdrive:skills:check` byte-gates those faces and fails on any
|
|
66
|
+
`*.md.erb` found under a public skills root. A supporting `*.md.erb` shipped
|
|
67
|
+
under a public skills root still renders, but draws a warning steering it to
|
|
68
|
+
the template directory.
|
|
69
|
+
- `hyperdrive:init --skip-mcp` skips MCP setup entirely: no `rails-hyperdrive`
|
|
70
|
+
entry in `.mcp.json` and no engine mount in `config/routes.rb`. Content
|
|
71
|
+
install, the discover-cache `.gitignore` rule, and the bundler-plugin Gemfile
|
|
72
|
+
directive all still run, and the summary reports `MCP: skipped (--skip-mcp)`
|
|
73
|
+
in place of the mount/server lines. Like `--skip-content`, it only suppresses
|
|
74
|
+
writes — existing MCP configuration is left untouched — and the two flags
|
|
75
|
+
combine.
|
|
76
|
+
- `gems:` is an exact alias of `gem:` at every position the key is read —
|
|
77
|
+
gem-wide defaults, `skills:`/`guidelines:` entries, and per-file
|
|
78
|
+
`conditional:` entries — for every value shape. A map carrying both keys is a
|
|
79
|
+
stylistic slip rather than an error: `gems:` wins, with a warning.
|
|
80
|
+
- Companion-manifest `gem:` gating accepts a map with exactly one of `any:` or
|
|
81
|
+
`all:`, so an artifact can require *every* listed target rather than any one
|
|
82
|
+
of them: `gems: {all: [devise, pundit]}`. `any:` is an explicit spelling of the
|
|
83
|
+
existing any-match, which every bare form (single name, comma-separated
|
|
84
|
+
string, YAML list, `"*"`) keeps by default. The map values take those same
|
|
85
|
+
flat forms, and the form is accepted everywhere `gem:` is — gem-wide defaults,
|
|
86
|
+
`skills:`/`guidelines:` entries, and per-file `conditional:` entries. A `"*"`
|
|
87
|
+
inside `all:` is always satisfied, so it is dropped with a warning; a
|
|
88
|
+
malformed map takes the usual fail-open path (warn, install ungated).
|
|
89
|
+
- Companion manifests can version-fence artifacts against the running
|
|
90
|
+
rails-hyperdrive with a `hyperdrive_version:` requirement, valid gem-wide at
|
|
91
|
+
the manifest top level and per `skills:`/`guidelines:` entry. It is matched
|
|
92
|
+
against the installer's own version rather than the bundle — a constraint
|
|
93
|
+
`gem:` cannot express, since it is an any-match gate across its targets. An
|
|
94
|
+
unsatisfied fence skips the artifact and names the upgrade, both in
|
|
95
|
+
`hyperdrive:init`/`hyperdrive:sync` output and during `bundle install` via the
|
|
96
|
+
bundler plugin.
|
|
97
|
+
|
|
98
|
+
### Changed
|
|
99
|
+
|
|
100
|
+
- **Breaking (installer skew).** `.hyperdrive/lock.yml` is now written at schema
|
|
101
|
+
version 2, so every machine working on an app that has synced with this
|
|
102
|
+
release needs this release too. Older installers ship no schema guard and
|
|
103
|
+
cannot refuse: a 0.6.0 `init`, `sync`, or bundler-plugin top-up run against a
|
|
104
|
+
lock this release wrote silently degrades instead — it never discovers agents
|
|
105
|
+
or commands, so it orphan-warns their lock entries on every run, drops their
|
|
106
|
+
`disabled:` lists, and rewrites the lock back to version 1. Installed files
|
|
107
|
+
are never deleted. From this release on, the read guard (below) makes the
|
|
108
|
+
same skew halt with the upgrade remedy instead of degrading.
|
|
109
|
+
- **Breaking (bundler plugin).** The `bundler-rails-hyperdrive` plugin gem is
|
|
110
|
+
renamed `bundler-hyperdrive` — its directory, gem name, Gemfile directive
|
|
111
|
+
(`plugin "bundler-hyperdrive"`), and release tag namespace
|
|
112
|
+
(`bundler-hyperdrive/vX.Y.Z`). `hyperdrive:init` writes and matches the new
|
|
113
|
+
directive only; an app carrying the old one gets the new line appended and
|
|
114
|
+
should drop the old. Nothing else changes: the `Bundler::Hyperdrive`
|
|
115
|
+
namespace, the hook, and its behavior are untouched.
|
|
116
|
+
- **Breaking (companion gemspecs).** The two directory overrides move out of
|
|
117
|
+
gemspec metadata and into the gem-root manifest as top-level keys:
|
|
118
|
+
`hyperdrive_skills_dir` → `skills_dir:` in `hyperdrive.yml`, and
|
|
119
|
+
`hyperdrive_skill_templates_dir` → `skill_templates_dir:`. The metadata keys
|
|
120
|
+
are no longer read at all — under either spelling, the `rails_`-prefixed one
|
|
121
|
+
0.6.0 shipped included, and with no deprecation or dual-read — so a gem still
|
|
122
|
+
declaring them ships from the default roots, and they no longer count as
|
|
123
|
+
companion opt-in signals (the manifest that now carries them is one).
|
|
124
|
+
Gemspec metadata is left as strictly the pre-install surface rubygems
|
|
125
|
+
serves: `hyperdrive_targets`, `hyperdrive_artifacts`, and the
|
|
126
|
+
`hyperdrive_manifest` bootstrap pointer. Discovery resolves both roots
|
|
127
|
+
fail-open like every other manifest value: a non-string or `..`-containing
|
|
128
|
+
value is warned about and the default roots are used (where the metadata keys
|
|
129
|
+
were ignored silently), and a blank one falls back silently. The
|
|
130
|
+
companion-repo rake tasks stay strict and now raise on a manifest that will
|
|
131
|
+
not parse, rather than rendering with default roots over a file the
|
|
132
|
+
installer cannot read. `rake hyperdrive:manifest:check` validates the two
|
|
133
|
+
new keys.
|
|
134
|
+
- **Breaking (companion gemspecs).** The remaining companion-gem gemspec
|
|
135
|
+
metadata keys drop their `rails_` prefix: `rails_hyperdrive_targets` →
|
|
136
|
+
`hyperdrive_targets`, `rails_hyperdrive_artifacts` →
|
|
137
|
+
`hyperdrive_artifacts`, and `rails_hyperdrive_manifest` →
|
|
138
|
+
`hyperdrive_manifest`. The contract is not Rails-specific, and the keys now
|
|
139
|
+
read that way. The old spellings are no longer read, with no deprecated
|
|
140
|
+
alias: a gem still declaring them is not opted in as a companion, its
|
|
141
|
+
manifest override is ignored, and `hyperdrive:discover` — which now queries
|
|
142
|
+
rubygems for `metadata.hyperdrive_targets:*` — no longer surfaces it.
|
|
143
|
+
Companion gems must update their gemspecs.
|
|
144
|
+
- **Breaking (companion manifests).** Version constraints move onto the gate
|
|
145
|
+
members and the sibling `versions:` key is gone. Wherever `gem:` takes a YAML
|
|
146
|
+
list — the bare list and the `any:`/`all:` values alike — a member is now
|
|
147
|
+
either a bare gem name or a single-pair map carrying that member's own
|
|
148
|
+
requirement: `gems: [railties: ">= 7.0"]`. The requirement is a
|
|
149
|
+
`Gem::Requirement` (comma-separated string or YAML list); a pair value of
|
|
150
|
+
`"*"` or nothing means unconstrained. Scalar and comma-separated string forms
|
|
151
|
+
stay name-only, and a pair value is never target-split, so a compound
|
|
152
|
+
requirement like `">= 4.9, < 6"` is passed whole. A `"*"` used as a pair key
|
|
153
|
+
is meaningless, so it is dropped with a warning in every list context; when it
|
|
154
|
+
was the sole member the gate resolves universal.
|
|
155
|
+
|
|
156
|
+
A `versions:` key remaining anywhere it used to be valid (top level,
|
|
157
|
+
`skills:`/`guidelines:` entries, `conditional:` entries) is warned about and
|
|
158
|
+
ignored: the named targets keep gating, unconstrained. Because requirements
|
|
159
|
+
now travel with the targets, an entry's gate replaces the gem-wide default
|
|
160
|
+
**wholesale** — the per-axis inheritance that let a top-level `versions:`
|
|
161
|
+
apply to an entry naming a different `gem:` is gone. `hyperdrive_version:`
|
|
162
|
+
inheritance is unchanged.
|
|
163
|
+
|
|
164
|
+
No compatibility shim: older rails-hyperdrive releases read a pair member as a
|
|
165
|
+
malformed `gem:` and install the artifact ungated.
|
|
166
|
+
- `.hyperdrive/lock.yml` is now read-guarded against its own schema version. The
|
|
167
|
+
lock is git-tracked and shared across branches that pin different
|
|
168
|
+
rails-hyperdrive versions, so an installer can meet a lock a newer one wrote.
|
|
169
|
+
It previously rewrote the file anyway: unknown top-level keys survive the
|
|
170
|
+
round-trip, but anything a newer schema stores inside the keys it recognizes
|
|
171
|
+
— `disabled:` lists for kinds it does not know, or a reshaped `enabled:` or
|
|
172
|
+
`claude_md` — was silently dropped.
|
|
173
|
+
`hyperdrive:init` and `hyperdrive:sync` now fail with the upgrade remedy
|
|
174
|
+
before any content write (`--dry-run` included, and init's bootstrap steps
|
|
175
|
+
still complete), and `bundle install`'s auto-install prints the same reason
|
|
176
|
+
and installs nothing.
|
|
177
|
+
- An artifact that changes destination — a companion renaming a skill, or a
|
|
178
|
+
cross-source name collision appearing or resolving, flipping between
|
|
179
|
+
`.claude/skills/<name>/` and `.claude/skills/<name>--<source_gem>/` — now has
|
|
180
|
+
its old copy removed, supporting files and emptied directories included,
|
|
181
|
+
instead of being left behind as a byte-duplicate that warns on every sync.
|
|
182
|
+
Removal requires the source gem to still be bundled and to have lost no
|
|
183
|
+
artifact to a discovery skip this run, so a broken companion release or a
|
|
184
|
+
version fence never deletes a good install; a locally-modified copy is always
|
|
185
|
+
warned about and left. The bundler plugin's auto-install removes nothing, as
|
|
186
|
+
before.
|
|
187
|
+
- Orphan warnings no longer claim an artifact is "no longer shipped by" a gem
|
|
188
|
+
that is still in the bundle, in both `hyperdrive:sync` output and the
|
|
189
|
+
"need attention" lines printed during `bundle install`.
|
|
190
|
+
- A `disabled:` entry naming a skill by its postfixed name (`foo--gem_a`) now
|
|
191
|
+
opts that source's artifact out permanently, rather than only while the
|
|
192
|
+
collision that produced the postfix exists.
|
|
193
|
+
- `hyperdrive:init`, `hyperdrive:sync`, and `hyperdrive:discover` are Rails
|
|
194
|
+
commands rather than rake tasks, so their flags now work bare —
|
|
195
|
+
`bin/rails hyperdrive:sync --merge` instead of
|
|
196
|
+
`bin/rails hyperdrive:sync -- --merge` — and
|
|
197
|
+
`bin/rails hyperdrive:sync --help` prints usage. The `-- --flag` form keeps
|
|
198
|
+
working, so existing scripts and docs need no change.
|
|
199
|
+
|
|
200
|
+
### Removed
|
|
201
|
+
|
|
202
|
+
- **BREAKING:** `require "rails/hyperdrive/skill_tasks"`. The companion-repo
|
|
203
|
+
rake tasks are required as `hyperdrive/skill_tasks`; a Rakefile using the old
|
|
204
|
+
spelling raises `LoadError` and needs the one-line change. There is one path,
|
|
205
|
+
under no framework's namespace.
|
|
206
|
+
|
|
207
|
+
- **BREAKING:** the `hyperdrive:*` rake tasks. `bundle exec rake hyperdrive:init`
|
|
208
|
+
(and `:sync` / `:discover`) is no longer available, and the tasks no longer
|
|
209
|
+
appear in `bin/rails -T`. Use `bin/rails hyperdrive:<command>`, which is
|
|
210
|
+
unchanged.
|
|
211
|
+
|
|
212
|
+
### Fixed
|
|
213
|
+
|
|
214
|
+
- A parseable `hyperdrive_version:` fence now survives an unusable `gem:`,
|
|
215
|
+
both per entry and in the gem-wide defaults. The fence is resolved before
|
|
216
|
+
the gate, so fail-open reads "install ungated unless fenced out": a manifest
|
|
217
|
+
written in a value shape an older installer cannot parse is fenced out of
|
|
218
|
+
that installer instead of installing everywhere unconstrained — the exact
|
|
219
|
+
case `hyperdrive_version:` exists to cover. The two gem-wide defaults are
|
|
220
|
+
independent too: an unusable `gem:` default no longer drops a parseable
|
|
221
|
+
fence, and a malformed fence no longer drops a usable `gem:` default; each
|
|
222
|
+
warns for its own axis. An entry whose *own* `hyperdrive_version:` is
|
|
223
|
+
unparsable still installs ungated and unfenced — the gem-wide fence is not
|
|
224
|
+
substituted for a constraint the entry never asked for.
|
|
225
|
+
- A `conditional:` key spelled as a template-backed supporting file's rendered
|
|
226
|
+
face (`references/x.md`) now gates that template, instead of silently
|
|
227
|
+
matching nothing while the file installed unconditionally. Either spelling —
|
|
228
|
+
the shipped `references/x.md.erb` or the face — resolves to the same gate;
|
|
229
|
+
a manifest carrying both for one file draws a warning and the shipped `.erb`
|
|
230
|
+
spelling wins. `rake hyperdrive:manifest:check` agrees with discovery on
|
|
231
|
+
both points, and no longer reports a face-spelled key as naming nothing
|
|
232
|
+
shipped.
|
|
233
|
+
- A `SKILL.md.erb` that fails to render because it reaches for a helper a
|
|
234
|
+
newer rails-hyperdrive added now reports its `hyperdrive_version:` fence
|
|
235
|
+
rather than a bare `ERB render failed (NameError)`, and that line reaches the
|
|
236
|
+
bundler-plugin surface like every other fence warning.
|
|
237
|
+
- An ordinary gate miss — a well-formed `gem:` whose target simply is not
|
|
238
|
+
bundled — no longer marks its source gem as having lost content, so the
|
|
239
|
+
stale-destination sweep keeps converging for companions that gate different
|
|
240
|
+
skills on different stacks. A renamed skill's old directory is now removed
|
|
241
|
+
instead of being orphan-warned indefinitely.
|
|
242
|
+
- `hyperdrive:sync` sweeps a stale `<dest>.new` sidecar when it removes the
|
|
243
|
+
destination that sidecar belonged to, under the same rule as everywhere else
|
|
244
|
+
(machine-pristine → removed; edited → warned about and left). A pristine
|
|
245
|
+
leftover no longer strands itself or keeps an emptied skill directory alive.
|
|
246
|
+
- `rake hyperdrive:manifest:check` fails when a `hyperdrive_manifest` gemspec
|
|
247
|
+
metadata key names a path that is not a file — previously read as "this gem
|
|
248
|
+
ships no manifest" and reported green, while the dangling key still counted
|
|
249
|
+
as companion opt-in and every artifact installed ungated.
|
|
250
|
+
- `rake hyperdrive:skills:render` / `:check` work for a companion that declares
|
|
251
|
+
neither `hyperdrive_skills_dir` nor `hyperdrive_skill_templates_dir`: the
|
|
252
|
+
content root now defaults to top-level `skills/` (matching discovery) rather
|
|
253
|
+
than to the same lib-convention path as the templates root, which made the
|
|
254
|
+
tasks hard-error with "content dir equals template dir".
|
|
255
|
+
- `init`/`sync` no longer count advisory discovery warnings as dropped
|
|
256
|
+
artifacts. Warnings that dropped shipped content — a whole artifact, or one
|
|
257
|
+
supporting file of one — print under `discovery skipped N item(s):` (was
|
|
258
|
+
`discovery skipped N artifact(s):`, which counted every warning and named
|
|
259
|
+
them all artifacts); everything that installed anyway prints under
|
|
260
|
+
`discovery reported M advisory warning(s):`.
|
|
261
|
+
- The bundler-plugin hook now prints discovery advisories during
|
|
262
|
+
`bundle install`, so a retired `versions:` key — content this release
|
|
263
|
+
deliberately installs unconstrained — is no longer silent there. Ordinary
|
|
264
|
+
artifact skips stay with `init`/`sync`.
|
|
265
|
+
- The `installing ungated` warning on a malformed manifest entry that keeps its
|
|
266
|
+
fence now reads `installing ungated unless fenced out`, so it can no longer
|
|
267
|
+
contradict a fence-skip line for the same artifact. Only an unparsable
|
|
268
|
+
`hyperdrive_version:` says `installing ungated and unfenced`.
|
|
269
|
+
- The warning for a manifest that will not parse now names the parser error
|
|
270
|
+
(`ignoring manifest hyperdrive.yml: malformed YAML (<reason>)`), matching what
|
|
271
|
+
`rake hyperdrive:manifest:check` already reported. Behaviour is unchanged:
|
|
272
|
+
gating that cannot be read still resolves to an absent manifest.
|
|
273
|
+
|
|
274
|
+
## [0.6.0] - 2026-08-17
|
|
275
|
+
|
|
276
|
+
### Changed
|
|
277
|
+
|
|
278
|
+
- `run_sql` now labels an over-cap result `(showing first 100 of <total> rows)`
|
|
279
|
+
instead of `(<total> rows, truncated)`, which read as though rows beyond the
|
|
280
|
+
count shown had been dropped from a smaller set.
|
|
281
|
+
- The connection check printed under `hyperdrive:init`'s "Next steps" is now a
|
|
282
|
+
JSON-RPC `tools/list` POST carrying the `Content-Type` and `Accept` headers
|
|
283
|
+
the endpoint requires. The previous bare `curl <url>` was a GET, which the
|
|
284
|
+
stateless MCP transport answers with 405 — the suggested check read as a
|
|
285
|
+
failure against a perfectly working install.
|
|
286
|
+
|
|
287
|
+
### Removed
|
|
288
|
+
|
|
289
|
+
- **BREAKING:** `Rails::Hyperdrive.configure` /
|
|
290
|
+
`Rails::Hyperdrive::Configuration`, and the `config/initializers/hyperdrive.rb`
|
|
291
|
+
initializer that `hyperdrive:init --mount-at` used to write. The
|
|
292
|
+
initializer's only setting, `config.mount_at`, was read by nothing — the
|
|
293
|
+
live mount is the `mount Rails::Hyperdrive::Engine` line the generator
|
|
294
|
+
writes into `config/routes.rb`, and `.mcp.json` records the URL — so
|
|
295
|
+
editing it never moved the endpoint. The `--mount-at` flag is unchanged.
|
|
296
|
+
|
|
297
|
+
**Manual migration:** delete `config/initializers/hyperdrive.rb` if an
|
|
298
|
+
earlier `hyperdrive:init --mount-at` wrote one. The file calls
|
|
299
|
+
`Rails::Hyperdrive.configure` unguarded, so with the gem in the
|
|
300
|
+
`:development` group it raises `NameError` on any boot that excludes that
|
|
301
|
+
group (e.g. a production deploy) — deleting it also removes that hazard.
|
|
302
|
+
|
|
10
303
|
## [0.5.0] - 2026-08-15
|
|
11
304
|
|
|
12
305
|
### Added
|
|
@@ -40,9 +333,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
40
333
|
`require "rails/hyperdrive/skill_tasks"` in the Rakefile provides
|
|
41
334
|
`rake hyperdrive:skills:render` (generate each template's static `SKILL.md`
|
|
42
335
|
with the fail-open canonical binding — every gem present, `gem_version`
|
|
43
|
-
`nil`; the generated face
|
|
44
|
-
|
|
45
|
-
|
|
336
|
+
`nil`; the generated face is the rendered template verbatim — with gating
|
|
337
|
+
in the gem-root manifest there are no installer keys to strip) and
|
|
338
|
+
`rake hyperdrive:skills:check` (fail listing stale generated
|
|
46
339
|
files — the CI freshness gate). Rails-free; rails-hyperdrive as a
|
|
47
340
|
development dependency suffices.
|
|
48
341
|
- A gem's top-level `skills/` directory is now scanned as a default skills
|
|
@@ -423,7 +716,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
423
716
|
- `hyperdrive:init` generator that installs architecture skills and auto-discovers
|
|
424
717
|
per-gem skills.
|
|
425
718
|
|
|
426
|
-
[Unreleased]: https://github.com/rails-hyperdrive/rails-hyperdrive/compare/v0.
|
|
719
|
+
[Unreleased]: https://github.com/rails-hyperdrive/rails-hyperdrive/compare/v0.7.0...HEAD
|
|
720
|
+
[0.7.0]: https://github.com/rails-hyperdrive/rails-hyperdrive/releases/tag/v0.7.0
|
|
721
|
+
[0.6.0]: https://github.com/rails-hyperdrive/rails-hyperdrive/releases/tag/v0.6.0
|
|
427
722
|
[0.5.0]: https://github.com/rails-hyperdrive/rails-hyperdrive/releases/tag/v0.5.0
|
|
428
723
|
[0.4.0]: https://github.com/rails-hyperdrive/rails-hyperdrive/releases/tag/v0.4.0
|
|
429
724
|
[0.3.0]: https://github.com/rails-hyperdrive/rails-hyperdrive/releases/tag/v0.3.0
|
data/README.md
CHANGED
|
@@ -10,12 +10,18 @@
|
|
|
10
10
|
[](https://github.com/rails-hyperdrive/rails-hyperdrive/actions/workflows/ci.yml)
|
|
11
11
|
[](LICENSE.txt)
|
|
12
12
|
|
|
13
|
-
Rails Hyperdrive is a development-only Rails engine for working on Rails apps with AI coding agents. It gives the agent two things it can't get from source alone
|
|
13
|
+
Rails Hyperdrive is a development-only Rails engine for working on Rails apps with AI coding agents. It gives the agent two things it can't get from source alone: live answers from the booted app, and guidance specific to the gems and versions in the bundle.
|
|
14
14
|
|
|
15
15
|
- **Live introspection.** The engine mounts an [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server at `http://localhost:3000/_hyperdrive/mcp` with **8 tools** that answer from the running app itself: eval Ruby, query the DB (read-only), tail logs, list models and routes, jump to source, look up docs, snapshot the stack. The agent asks the router instead of grepping `routes.rb`, and reads the live schema instead of replaying migrations.
|
|
16
|
-
- **Stack-specific knowledge.** `bin/rails hyperdrive:init` discovers **skills** and **
|
|
16
|
+
- **Stack-specific knowledge.** `bin/rails hyperdrive:init` discovers **skills**, **guidelines**, **agents**, and **commands** shipped by companion gems and installs only the ones matching your Gemfile: guidance targeting Sidekiq, for example, lands only if your app bundles Sidekiq, at a version the guidance covers.
|
|
17
17
|
|
|
18
|
-
**rails-hyperdrive is the mechanism; companion gems are the content.** The gem itself ships no skills or guidelines
|
|
18
|
+
**rails-hyperdrive is the mechanism; companion gems are the content.** The gem itself ships no skills or guidelines, only the contract and the discovery/install engine. Content reaches your app three ways:
|
|
19
|
+
|
|
20
|
+
- **Native support**: the library gem itself ships a top-level `skills/` directory in the [skills.sh](https://www.skills.sh) layout and opts in as a hyperdrive companion. The preferred route when the maintainer is on board: one gem, one source of truth.
|
|
21
|
+
- **Adopted skill repos**: an existing skills.sh skill repo packaged as a gem, content untouched, gating declared on the side.
|
|
22
|
+
- **Dedicated companion gems**: third-party guidance for a library that ships none itself.
|
|
23
|
+
|
|
24
|
+
On the last two routes, name the gem `rails-hyperdrive-<name>`: the prefix tells a Gemfile reader exactly what the gem is, though naming plays no part in discovery.
|
|
19
25
|
|
|
20
26
|
---
|
|
21
27
|
|
|
@@ -57,7 +63,7 @@ $ bin/dev
|
|
|
57
63
|
# → agent has 8 tools, the eager guidelines (via CLAUDE.md), and the lazy skills
|
|
58
64
|
```
|
|
59
65
|
|
|
60
|
-
|
|
66
|
+
The generated `.mcp.json` points at `http://localhost:3000<mount>/mcp`. If your dev server runs on another port, edit the URL there.
|
|
61
67
|
|
|
62
68
|
---
|
|
63
69
|
|
|
@@ -76,38 +82,40 @@ That's it. No API keys, no config files to write, no per-project setup beyond th
|
|
|
76
82
|
| 7 | `describe_app` | Snapshot: Rails/Ruby/DB versions + direct gem dependencies |
|
|
77
83
|
| 8 | `list_routes` | All routes: HTTP verb, path, controller#action, named route |
|
|
78
84
|
|
|
79
|
-
Plus two MCP resources: `hyperdrive://stack-profile` (JSON snapshot of your resolved stack) and `hyperdrive://skills/{name}` (the markdown body of each installed skill).
|
|
85
|
+
Plus two MCP resources: `hyperdrive://stack-profile` (JSON snapshot of your resolved stack) and `hyperdrive://skills/{name}` (the markdown body of each installed skill). The skill list is enumerated at server boot and the stack snapshot is memoized per process, so a newly installed skill or a changed bundle reaches these two only after a dev-server restart.
|
|
80
86
|
|
|
81
|
-
###
|
|
87
|
+
### Four kinds of knowledge
|
|
82
88
|
|
|
83
|
-
Companion gems ship
|
|
89
|
+
Companion gems ship four artifact kinds, tuned for how agents consume context:
|
|
84
90
|
|
|
85
|
-
- **Skills
|
|
86
|
-
- **Guidelines
|
|
91
|
+
- **Skills**: *lazy*. Loaded on demand via Claude Code's native description matcher. Procedural knowledge: "how to write an idempotent Sidekiq job". Installed to `.claude/skills/<name>/SKILL.md`, optionally with supporting files (references, examples, workflows) alongside.
|
|
92
|
+
- **Guidelines**: *eager*. Always in context via a single `@`-include from `CLAUDE.md`. Declarative facts: "this app uses ActionPolicy, not Pundit". Installed to `.claude/hyperdrive/guidelines/<name>.md`.
|
|
93
|
+
- **Agents**: Claude Code subagents, invoked by name or by task match. Installed to `.claude/agents/<name>.md`.
|
|
94
|
+
- **Commands**: Claude Code slash commands. Installed to `.claude/commands/<name>.md`, so a file named `analyze.md` becomes `/analyze`.
|
|
87
95
|
|
|
88
|
-
|
|
96
|
+
A companion gem declares in its manifest which gem each artifact targets and at which versions, so what lands in your app is what matches your `Gemfile.lock`, and nothing aimed at a library or version you don't run.
|
|
89
97
|
|
|
90
|
-
With no companion gems, `hyperdrive:init` sets up just the server plumbing (`.mcp.json`, the engine mount, the lockfile) and puts **nothing** into your agent's context window.
|
|
98
|
+
With no companion gems, `hyperdrive:init` sets up just the server plumbing (`.mcp.json`, the engine mount, the lockfile) and puts **nothing** into your agent's context window. The two halves are independently skippable: `--skip-mcp` installs content but no MCP plumbing, `--skip-content` the reverse. Neither removes anything already in place.
|
|
91
99
|
|
|
92
100
|
---
|
|
93
101
|
|
|
94
102
|
## Staying in sync
|
|
95
103
|
|
|
96
|
-
**After `bundle install
|
|
104
|
+
**After `bundle install`: automatic.** `hyperdrive:init` registers the [`bundler-hyperdrive`](bundler-hyperdrive/) Bundler plugin in your Gemfile. From then on, adding a companion gem lands its artifacts on that very `bundle install`, with no extra command to run. The plugin is additive only (it never touches an existing file); version bumps and orphaned artifacts are only reported, with a pointer to `hyperdrive:sync`.
|
|
97
105
|
|
|
98
|
-
**`bin/rails hyperdrive:sync
|
|
106
|
+
**`bin/rails hyperdrive:sync`: on demand.** Run it any time (e.g. after `bundle update`) to refresh installed content to the current bundle. It touches no bootstrap artifact and leaves locally modified files untouched (skip + warn). When you *have* edited an installed file and its gem ships a new version, three mutually exclusive flags reconcile the two:
|
|
99
107
|
|
|
100
108
|
| Strategy | What happens to the live file | What happens to your edits |
|
|
101
109
|
|---|---|---|
|
|
102
|
-
| `--merge` | Rewritten with a git three-way merge when it applies cleanly; otherwise untouched and the upstream lands as a `--sidecar` delivery | Kept
|
|
110
|
+
| `--merge` | Rewritten with a git three-way merge when it applies cleanly; otherwise untouched and the upstream lands as a `--sidecar` delivery | Kept: a merge that would need conflict markers falls back to the sidecar, so nothing half-merged ever goes live |
|
|
103
111
|
| `--sidecar` | Untouched; the new upstream body is written next to it as `<file>.new` | Kept, byte-for-byte |
|
|
104
112
|
| `--overwrite` | Restored to the gem-shipped content | Discarded |
|
|
105
113
|
|
|
106
|
-
A sidecar is inert
|
|
114
|
+
A sidecar is inert (Claude Code loads only `SKILL.md` and the `index.md` `@`-lines, never a `.new` file), and it shows up in `git status` as your prompt to resolve. Resolve it by folding what you want into the live file and deleting the `.new`, or `mv <file>.new <file>` to accept the upstream wholesale. Either way the lockfile already records that delivery, so the next sync doesn't re-offer the same version (and a leftover sidecar you haven't touched is cleaned up once the live file catches up). `--merge` needs the previously installed gem version still present on disk to reconstruct the merge ancestor; when it isn't (CI, after `gem cleanup`), it degrades to the sidecar with a note saying why.
|
|
107
115
|
|
|
108
116
|
The sidecar pair is also how an AI coding agent reconciles for you, with no extra machinery: run `bin/rails hyperdrive:sync --sidecar`, have the agent merge the live/`.new` pair semantically (it has both full texts), then delete the sidecar.
|
|
109
117
|
|
|
110
|
-
**`bin/rails hyperdrive:discover
|
|
118
|
+
**`bin/rails hyperdrive:discover`: find what you're missing.** Queries rubygems for companion gems published for your stack that you haven't installed yet, and prints the `bundle add` lines to run. It is read-only, caches results for 24h (`--refresh` re-queries), and never touches your Gemfile or makes network calls unless you invoke it.
|
|
111
119
|
|
|
112
120
|
---
|
|
113
121
|
|
|
@@ -122,21 +130,23 @@ CLAUDE.md # user-owned; ONE injected line: @.claude
|
|
|
122
130
|
guidelines/<name>.md # companion-shipped, frontmatter stripped
|
|
123
131
|
.claude/skills/<name>/
|
|
124
132
|
SKILL.md # companion-shipped, installed verbatim (frontmatter included)
|
|
125
|
-
<supporting files> # optional
|
|
133
|
+
<supporting files> # optional extras (references/, examples/, …), installed as shipped (*.md.erb rendered)
|
|
134
|
+
.claude/agents/<name>.md # companion-shipped subagent, installed verbatim
|
|
135
|
+
.claude/commands/<name>.md # companion-shipped slash command, installed verbatim
|
|
126
136
|
.hyperdrive/lock.yml # git-tracked manifest (source gem, version, content hash)
|
|
127
137
|
```
|
|
128
138
|
|
|
129
|
-
A `git diff` is where you review what a companion gem added. The install summary names each artifact's source gem and version, and every installed file is hashed and attributed to its source in the git-tracked `.hyperdrive/lock.yml
|
|
139
|
+
A `git diff` is where you review what a companion gem added. The install summary names each artifact's source gem and version, and every installed file is hashed and attributed to its source in the git-tracked `.hyperdrive/lock.yml`. The files themselves land byte-identical to what the gem ships, with nothing injected. `hyperdrive:init` warns if your app gitignores these paths, since that empties the diff without changing what reaches the agent. The `hyperdrive:discover` cache is the one file rails-hyperdrive adds to `.gitignore`.
|
|
130
140
|
|
|
131
|
-
`CLAUDE.md` and `index.md` are the **eager chain
|
|
141
|
+
`CLAUDE.md` and `index.md` are the **eager chain**: they exist only because a companion gem ships a guideline, and both go when the last one leaves the bundle (the guideline file itself is left on disk and reported as an orphan).
|
|
132
142
|
|
|
133
143
|
### Your edits win
|
|
134
144
|
|
|
135
|
-
Installed files are yours to modify. The lockfile hash tells the installer whether a file is still gem-pristine: unedited files are refreshed on upgrade, edited files are skipped with a warning
|
|
145
|
+
Installed files are yours to modify. The lockfile hash tells the installer whether a file is still gem-pristine: unedited files are refreshed on upgrade, edited files are skipped with a warning, never silently overwritten. `hyperdrive:sync --overwrite` is the explicit way back to gem-shipped content.
|
|
136
146
|
|
|
137
147
|
### Turning off a single artifact
|
|
138
148
|
|
|
139
|
-
A companion gem you want for one skill but not another doesn't have to be all-or-nothing. Add the artifact's name to the `disabled:` list in `.hyperdrive/lock.yml
|
|
149
|
+
A companion gem you want for one skill but not another doesn't have to be all-or-nothing. Add the artifact's name to the `disabled:` list in `.hyperdrive/lock.yml`. It is written empty on every install, so the shape is already there:
|
|
140
150
|
|
|
141
151
|
```yaml
|
|
142
152
|
disabled:
|
|
@@ -144,17 +154,21 @@ disabled:
|
|
|
144
154
|
- sidekiq-idempotency
|
|
145
155
|
guidelines:
|
|
146
156
|
- jobs-sidekiq
|
|
157
|
+
agents:
|
|
158
|
+
- sidekiq-reviewer
|
|
159
|
+
commands:
|
|
160
|
+
- analyze
|
|
147
161
|
```
|
|
148
162
|
|
|
149
|
-
A disabled artifact is never installed, and one already on disk is removed on the next `hyperdrive:init` or `hyperdrive:sync
|
|
163
|
+
A disabled artifact is never installed, and one already on disk is removed on the next `hyperdrive:init` or `hyperdrive:sync`, but **only if you haven't edited it**. A locally modified file is reported and left alone, for you to delete when you're ready. Disabling a skill removes its shipped supporting files under the same per-file rule; files you created yourself in the skill directory survive and keep the directory alive. Disabling a guideline also drops its line from `index.md`, so it leaves eager context along with the file.
|
|
150
164
|
|
|
151
|
-
The list is yours to edit; the generator only reads it and carries it forward. Delete a name to get the artifact back on the next run. When two companion gems ship the same artifact name, both install under a `<name>--<source-gem>` suffix
|
|
165
|
+
The list is yours to edit; the generator only reads it and carries it forward. Delete a name to get the artifact back on the next run. When two companion gems ship the same artifact name, both install under a `<name>--<source-gem>` suffix: the plain name disables both, the suffixed name disables one.
|
|
152
166
|
|
|
153
167
|
To skip installed content wholesale instead, pass `--skip-content` to `hyperdrive:init`.
|
|
154
168
|
|
|
155
169
|
### Opting into a gem's bundled skills
|
|
156
170
|
|
|
157
|
-
Ordinary gems (not built as hyperdrive companions) sometimes ship a top-level `skills/` directory of
|
|
171
|
+
Ordinary gems (not built as hyperdrive companions) sometimes ship a top-level `skills/` directory of skills.sh-style skills. Those are never installed automatically: `hyperdrive:init` and `hyperdrive:sync` only report them, e.g. `gem 'foo' ships 2 skills.sh skill(s)`. To install them, name the gem in the `enabled:` list in `.hyperdrive/lock.yml` and re-run `hyperdrive:sync`:
|
|
158
172
|
|
|
159
173
|
```yaml
|
|
160
174
|
enabled:
|
|
@@ -167,7 +181,7 @@ An enabled gem is treated as a companion from then on: its skills install throug
|
|
|
167
181
|
|
|
168
182
|
## Safety
|
|
169
183
|
|
|
170
|
-
Rails Hyperdrive is **dev-only**, enforced in depth: the engine refuses
|
|
184
|
+
Rails Hyperdrive is **dev-only**, enforced in depth: the engine refuses requests outside `Rails.env.development?`, applies an origin allowlist (`localhost`, `127.0.0.1`, `[::1]`), and every tool re-checks the dev guard on invocation. `run_sql` accepts read-only statements and refuses anything else. See [SECURITY.md](SECURITY.md).
|
|
171
185
|
|
|
172
186
|
---
|
|
173
187
|
|
|
@@ -177,12 +191,16 @@ Ship markdown, declare what it targets, publish. That's the whole contract:
|
|
|
177
191
|
|
|
178
192
|
```
|
|
179
193
|
skills/<name>/SKILL.md # skill (dir-per-skill, may ship supporting files)
|
|
194
|
+
agents/<name>.md # agent (flat file)
|
|
195
|
+
commands/<name>.md # command (flat file)
|
|
180
196
|
lib/<gem_name>/hyperdrive/guidelines/<name>.md # guideline (flat file)
|
|
181
197
|
```
|
|
182
198
|
|
|
183
|
-
|
|
199
|
+
`<gem_name>` is your gem's name exactly as published, dashes and all — `rails-hyperdrive-sidekiq` ships guidelines under `lib/rails-hyperdrive-sidekiq/hyperdrive/guidelines/`, not `lib/rails/hyperdrive/sidekiq/`.
|
|
200
|
+
|
|
201
|
+
Top-level `skills/`, `agents/`, and `commands/` are the tool-agnostic face of your gem — the same sibling layout `.claude/` has, so relative links between them keep resolving once installed. They are readable by skills.sh and plain git-clone consumers as well as hyperdrive, and are scanned once your gem has opted in (below). `lib/<gem_name>/hyperdrive/` is the hyperdrive-specific root: guidelines, and ERB skill templates (`SKILL.md.erb`, which must stay out of `skills/` so raw ERB never reaches generic consumers). Plain skills shipped under it remain scanned as well.
|
|
184
202
|
|
|
185
|
-
Frontmatter is pure
|
|
203
|
+
Frontmatter is pure skills.sh: only `name` and `description` are read, so a skill repo's content integrates without modification:
|
|
186
204
|
|
|
187
205
|
```yaml
|
|
188
206
|
---
|
|
@@ -191,33 +209,50 @@ description: Background job conventions for Sidekiq.
|
|
|
191
209
|
---
|
|
192
210
|
```
|
|
193
211
|
|
|
194
|
-
|
|
212
|
+
Agents follow the same contract. Commands are the exception: their frontmatter is optional and never validated, and their identity is the filename stem.
|
|
213
|
+
|
|
214
|
+
Gating (which bundles an artifact installs into) lives in a `hyperdrive.yml` manifest at the gem root (or at the path named by a `hyperdrive_manifest` gemspec metadata key), never in the content. Every key is optional; no manifest (or an empty one) means everything installs universally:
|
|
195
215
|
|
|
196
216
|
```yaml
|
|
197
|
-
|
|
198
|
-
|
|
217
|
+
gems: # gem-wide default: TARGET gem(s), resolved in the bundle ("gem:" is an alias)
|
|
218
|
+
- sidekiq: ">= 7.0, < 9.0" # a list member is a bare name, or a name: requirement pair
|
|
199
219
|
skills: # per-skill overrides, keyed by skill dir relative to its skills root
|
|
200
220
|
jobs-sidekiq:
|
|
201
|
-
|
|
221
|
+
gems:
|
|
222
|
+
- sidekiq: ">= 8.0"
|
|
223
|
+
hyperdrive_version: ">= 0.7" # require a minimum rails-hyperdrive for this artifact
|
|
202
224
|
guidelines: # per-guideline overrides, keyed by filename
|
|
203
225
|
jobs.md:
|
|
204
226
|
gem: sidekiq
|
|
227
|
+
agents: # per-agent overrides, keyed by filename
|
|
228
|
+
sidekiq-reviewer.md:
|
|
229
|
+
gem: sidekiq
|
|
230
|
+
commands: # per-command overrides, keyed by filename
|
|
231
|
+
command_prefix: sidekiq # optional; every command installs as <prefix>-<filename>
|
|
232
|
+
analyze.md:
|
|
233
|
+
gem: sidekiq
|
|
205
234
|
```
|
|
206
235
|
|
|
207
|
-
|
|
236
|
+
A gate naming several targets can be written as a map with one of `any:`/`all:` — `gems: {any: [sidekiq, solid_queue]}` installs when either is bundled, `gems: {all: [devise, pundit]}` only when both are. A bare list is shorthand for `any:`, and an entry's gate replaces the gem-wide default wholesale.
|
|
237
|
+
|
|
238
|
+
`hyperdrive_version:` is valid at the top level too, and is matched against the running rails-hyperdrive rather than the bundle — the sanctioned way to fence content that needs a newer installer. It fences on whichever gem implements artifact discovery and install — today rails-hyperdrive — and that version numbering is guaranteed continuous across any future restructuring of the gem, so a fence like `">= 0.8"` keeps its meaning permanently.
|
|
239
|
+
|
|
240
|
+
Shipping a `hyperdrive.yml` (or declaring `hyperdrive_manifest`) opts your gem in as a companion. Also declare your targets in gemspec metadata. That opts your gem in too, and it is the pre-install targeting signal (how `hyperdrive:discover` suggests you before anyone installs you):
|
|
208
241
|
|
|
209
242
|
```ruby
|
|
210
|
-
spec.metadata["
|
|
243
|
+
spec.metadata["hyperdrive_targets"] = "sidekiq"
|
|
211
244
|
```
|
|
212
245
|
|
|
213
|
-
|
|
246
|
+
Companion repos get author-side CI checks by adding `require "hyperdrive/skill_tasks"` to the `Rakefile`: `rake hyperdrive:skills:check` keeps generated skill content in step with its templates, and `rake hyperdrive:manifest:check` lints `hyperdrive.yml` strictly.
|
|
247
|
+
|
|
248
|
+
[docs/COMPANION_GEMS.md](docs/COMPANION_GEMS.md) has the full contract: multi-target artifacts, multi-file skills, per-file gem gating, ERB-templated content, the template/content paired layout that also serves `npx skills` and git-clone consumers, and the collision and dedup rules.
|
|
214
249
|
|
|
215
250
|
---
|
|
216
251
|
|
|
217
252
|
## Requirements
|
|
218
253
|
|
|
219
|
-
Ruby ≥ 3.2, Rails ≥ 7.2. Tested against Rails 7.2 and 8.1 on Ruby 3.2
|
|
254
|
+
Ruby ≥ 3.2, Rails ≥ 7.2. Tested against Rails 7.2 and 8.1 on Ruby 3.2-3.4.
|
|
220
255
|
|
|
221
256
|
## License
|
|
222
257
|
|
|
223
|
-
MIT
|
|
258
|
+
MIT. See [LICENSE.txt](LICENSE.txt).
|
|
@@ -3,14 +3,21 @@ Description:
|
|
|
3
3
|
- adds the rails-hyperdrive server to .mcp.json (Claude Code config),
|
|
4
4
|
merging into any servers already configured there
|
|
5
5
|
- mounts Rails::Hyperdrive::Engine at /_hyperdrive in config/routes.rb (idempotent)
|
|
6
|
-
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
- registers the bundler-hyperdrive plugin in the Gemfile, so newly
|
|
7
|
+
bundled companion gems install their artifacts on bundle install
|
|
8
|
+
- adds a .gitignore rule for the hyperdrive:discover cache
|
|
9
|
+
- discovers companion-gem skills, guidelines, agents, and commands in the
|
|
10
|
+
bundle and installs them (skills to .claude/skills/, guidelines to
|
|
11
|
+
.claude/hyperdrive/guidelines/, agents to .claude/agents/, commands to
|
|
12
|
+
.claude/commands/)
|
|
9
13
|
- maintains the .claude/hyperdrive/index.md aggregator and injects one
|
|
10
14
|
@-include line into CLAUDE.md — both only while a companion gem ships
|
|
11
15
|
a guideline, and both removed when the last one goes
|
|
12
16
|
- tracks everything in .hyperdrive/lock.yml
|
|
13
17
|
|
|
18
|
+
The .mcp.json entry and the engine mount are skippable with --skip-mcp;
|
|
19
|
+
existing MCP configuration is left untouched either way.
|
|
20
|
+
|
|
14
21
|
Re-running re-syncs content and leaves locally-modified files untouched
|
|
15
22
|
(skip + warn). Routine content refresh is bin/rails hyperdrive:sync
|
|
16
23
|
(see its --merge, --sidecar, and --overwrite flags for reconciling
|
|
@@ -20,4 +27,5 @@ Examples:
|
|
|
20
27
|
bin/rails hyperdrive:init
|
|
21
28
|
bin/rails hyperdrive:init --mount-at /admin/hyperdrive
|
|
22
29
|
bin/rails hyperdrive:init --skip-content
|
|
30
|
+
bin/rails hyperdrive:init --skip-mcp
|
|
23
31
|
bin/rails hyperdrive:init --dry-run
|