bundler-skills 0.4.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 962c265c0293c266b9fcca439681d9850cdac4332348dd2d1ffe11a4e5580111
4
- data.tar.gz: 495a9a9f1f2a1c0da2cb02aa14b73c1902b0584e64647066a9da967615b0c4af
3
+ metadata.gz: 30d4136893f0cc4bdead5248b1ee7d4df3768b536d67bf3cd243c1e91da454a2
4
+ data.tar.gz: 6e4739d9bc290347d3af00377e3bfee89ea6e293560b23019ee855feb781907c
5
5
  SHA512:
6
- metadata.gz: 4cad5c43044a98626b9fab90cb799c167e012f56d4c53c3839153648e3daef3f6c9cd10f1fa77771a2a0af8bedccbee77204054bcde6e48b2682fe9a36ca0c4c
7
- data.tar.gz: 6ec0164595551b1710069fe015151462cee20b87f614ed7b8c5d87d21053e7374332fde34e670196b8b0e0a7e2d1a6491f56b8be22ba09bd2047a7341957ce33
6
+ metadata.gz: 70fe208a60b6b8f1168a4b8d554ed82ae659c87a3b38763d80c81b54e94f7821b45a640339ad421f84f2c17266cc673d4a769b3e29516f10c2308c0182f1102c
7
+ data.tar.gz: c16486c4b5ffd489a68f74ab7d2c4111c03790845bc08302ce925e58887fc3aa9d732250b1fd9146a521aedce4e2c99018ec6f6c867c8646713ff54d7d995a85
data/CHANGELOG.md CHANGED
@@ -1,6 +1,35 @@
1
1
  # Changelog
2
2
 
3
- ## [Unreleased]
3
+ ## [0.6.0] - 2026-07-03
4
+
5
+ ### Changed (breaking)
6
+
7
+ - **Removed the RubyGems `post_install` hook entirely.** bundler-skills no
8
+ longer hooks into `bundle install`; skills are synced only when you run the
9
+ command (`bundle exec skills`). This removes the global side effect where the
10
+ hook was loaded and evaluated for every `bundle install` of every project
11
+ sharing the Ruby. Wire the command into a git hook (post-merge / post-checkout)
12
+ or a hook manager (husky / lefthook / overcommit) to run it automatically —
13
+ see the README.
14
+
15
+ ### Removed
16
+
17
+ - `lib/rubygems_plugin.rb`, the `RubygemsHook` module, and the `Disabling`
18
+ module — including the `BUNDLER_SKILLS_DISABLED` environment variable (with no
19
+ hook there is nothing to disable).
20
+
21
+ ## [0.5.0] - 2026-06-27
22
+
23
+ ### Changed (breaking)
24
+
25
+ - Drop support for Ruby 3.1 and 3.2 (both EOL). Minimum required Ruby is now 3.3.
26
+
27
+ ### Changed
28
+
29
+ - The post-install summary now stays silent when a run discovers no skills and
30
+ changes nothing. The `Gem.post_install` hook fires for every installed gem,
31
+ most of which ship no skills, so the previous `0 skill(s) discovered, 0 linked
32
+ ...` line was pure noise on each one.
4
33
 
5
34
  ## [0.4.0] - 2026-06-27
6
35
 
data/PROPOSAL.md CHANGED
@@ -76,19 +76,27 @@ even for gems like `rails-html-sanitizer`.
76
76
  linked too (the directory is symlinked as a whole), so reference relative
77
77
  files normally.
78
78
 
79
- ## Why a RubyGems `post_install` hook (not a Bundler plugin)
80
-
81
- bundler-skills ships as a regular gem with a `lib/rubygems_plugin.rb` that
82
- registers a `Gem.post_install` hook. The hook **does** fire during
83
- `bundle install` for each gem that is actually installed (only `Gem.done_installing`
84
- is Bundler-skipped), so it is a reliable place to sync that gem's skills.
85
-
86
- An earlier version was a Bundler plugin that registered a `bundle skills`
87
- command via `Bundler::Plugin::API.command`. That had a fatal flaw: when
88
- `bundle update` bumped bundler-skills itself, Bundler re-registered the `skills`
89
- command while the previous registration was still in its plugin index, raising
90
- `Bundler::Plugin::Index::CommandConflict` — and it recurred on every subsequent
91
- `bundle` run until `bundler plugin uninstall`. This is unavoidable for any plugin
92
- that registers a command. Becoming a regular gem removes the command registration
93
- entirely (the manual command is now the plain executable `bundle exec skills`),
94
- so the conflict cannot happen. See [README.md](README.md) for consumer details.
79
+ ## Why an explicit command (not a Bundler plugin or a `post_install` hook)
80
+
81
+ bundler-skills is a regular gem that ships a plain executable (`bundle exec
82
+ skills`). Syncing happens only when you run that command — it hooks into nothing.
83
+
84
+ Two earlier designs were tried and rejected:
85
+
86
+ - **A Bundler plugin** that registered a `bundle skills` command via
87
+ `Bundler::Plugin::API.command`. When `bundle update` bumped bundler-skills
88
+ itself, Bundler re-registered the `skills` command while the previous
89
+ registration was still in its plugin index, raising
90
+ `Bundler::Plugin::Index::CommandConflict` — and it recurred on every
91
+ subsequent `bundle` run until `bundler plugin uninstall`. This is unavoidable
92
+ for any plugin that registers a command.
93
+ - **A RubyGems `post_install` hook** (`lib/rubygems_plugin.rb` +
94
+ `Gem.post_install`). RubyGems auto-loads any `rubygems_plugin.rb` on the load
95
+ path, so once bundler-skills is installed anywhere in a Ruby, its hook is
96
+ loaded and evaluated for **every** `bundle install` of **every** project
97
+ sharing that Ruby — a global side effect that is hard to scope cleanly.
98
+
99
+ Providing only a command removes both problems: there is no command
100
+ registration to conflict, and nothing runs unless the user invokes it. Wire it
101
+ into a git hook or a hook manager to run it automatically — see
102
+ [README.md](README.md) for consumer details.
data/README.md CHANGED
@@ -1,29 +1,28 @@
1
1
  # bundler-skills
2
2
 
3
- A gem that auto-symlinks **AI agent skills bundled in your gems** into your
4
- project on `bundle install`. The Ruby/Bundler counterpart of
3
+ A gem that symlinks **AI agent skills bundled in your gems** into your project.
4
+ The Ruby/Bundler counterpart of
5
5
  [antfu/skills-npm](https://github.com/antfu/skills-npm).
6
6
 
7
- Gems ship `skills/<name>/SKILL.md`; your project links them into the right agent
8
- directory so the skill version always matches the gem version, and your whole
9
- team gets them just by running `bundle install`.
7
+ Gems ship `skills/<name>/SKILL.md`; running `bundle exec skills` links them into
8
+ the right agent directory so the skill version always matches the gem version.
10
9
 
11
10
  ## How it works
12
11
 
13
- bundler-skills ships a RubyGems `post_install` hook (via
14
- `lib/rubygems_plugin.rb`). Whenever a gem is **actually installed** during
15
- `bundle install` / `bundle update`, the hook runs for that gem and:
12
+ bundler-skills is a regular gem that ships a `bundle exec skills` command.
13
+ **Nothing runs automatically** there is no `bundle install` hook. Sync happens
14
+ only when you run the command (manually, or from a git hook you set up). Each run:
16
15
 
17
- 1. Scans **that gem** for `skills/*/SKILL.md`.
16
+ 1. Scans **all dependency gems** for `skills/*/SKILL.md`.
18
17
  2. Detects which agents you use (by marker directories) and symlinks each skill
19
18
  into the right place, named `gem-<gem>--<skill>`.
20
- 3. Prunes that gem's own stale links (so a version that renames or drops a skill
21
- updates correctly), leaving every other gem's links untouched.
19
+ 3. Prunes stale `gem-*--*` links (so a gem that renames, drops, or is removed
20
+ updates correctly).
22
21
  4. Adds the generated symlink patterns to `.gitignore` (they are machine-local).
23
22
 
24
- A `bundle install` that installs nothing (everything already cached) does no
25
- workonly freshly installed gems are processed. To re-sync everything at once
26
- (e.g. after removing a gem), run `bundle exec skills` (see below).
23
+ Run it whenever your dependencies change right after `bundle install` /
24
+ `bundle update` either by hand or from a git hook (see
25
+ [Running automatically](#running-automatically-git-hooks--hook-managers)).
27
26
 
28
27
  ### Supported agents
29
28
 
@@ -36,8 +35,8 @@ work — only freshly installed gems are processed. To re-sync everything at onc
36
35
 
37
36
  `.agents/skills/` is the cross-tool standard shared by Cursor / Codex / Copilot;
38
37
  Claude Code needs its own `.claude/skills/` because it does not read
39
- `.agents/skills/` yet. The plugin links into a directory only when that agent's
40
- marker exists, so nothing is created in projects that don't use these tools.
38
+ `.agents/skills/` yet. It links into a directory only when that agent's marker
39
+ exists, so nothing is created in projects that don't use these tools.
41
40
 
42
41
  ## Installation
43
42
 
@@ -55,13 +54,14 @@ end
55
54
  gem "some-gem-that-ships-skills"
56
55
  ```
57
56
 
58
- Then:
57
+ Then install and run the command:
59
58
 
60
59
  ```sh
61
60
  bundle install
61
+ bundle exec skills
62
62
  ```
63
63
 
64
- That's it. When a skill-bearing gem is installed you'll see something like:
64
+ When a skill-bearing gem is present you'll see something like:
65
65
 
66
66
  ```
67
67
  [bundler-skills] 1 skill(s) discovered, 1 linked, 0 relinked, 0 pruned across 1 dir(s) (agents: claude)
@@ -70,9 +70,8 @@ That's it. When a skill-bearing gem is installed you'll see something like:
70
70
  ```
71
71
 
72
72
  > In production / CI you typically run `bundle install` with the `development`
73
- > group excluded (`bundle config set --local without development`), so the gem
74
- > isn't even present and nothing runs. You can also force it off anywhere with
75
- > `BUNDLER_SKILLS_DISABLED=1`.
73
+ > group excluded (`bundle config set --local without development`), and you
74
+ > simply don't run `bundle exec skills` there nothing happens unless you invoke it.
76
75
 
77
76
  When a run actually changes something (links created, relinked after a gem
78
77
  update, or stale links pruned) the summary is printed in green so it stands out;
@@ -80,23 +79,68 @@ a run with nothing to do prints the same line in plain text. A changed run also
80
79
  lists each affected skill, grouped by kind, with the path to its `SKILL.md` so
81
80
  you can review the (third-party) skill contents now linked into your project.
82
81
 
82
+ ## Running automatically (git hooks / hook managers)
83
+
84
+ Sync is manual by design, but you'll usually want it to run right after your
85
+ dependencies change (`bundle install` / `bundle update`, i.e. whenever
86
+ `Gemfile.lock` changes). Wire the one-liner into a git hook or hook manager:
87
+
88
+ Plain git hook — create `.git/hooks/post-merge` (also useful as `post-checkout`
89
+ / `post-rewrite`) and `chmod +x` it. Note `.git/hooks` is not committed, so this
90
+ is per-clone:
91
+
92
+ ```sh
93
+ #!/bin/sh
94
+ bundle exec skills
95
+ ```
96
+
97
+ [lefthook](https://github.com/evilmartians/lefthook) — committed, shared with
98
+ the team:
99
+
100
+ ```yaml
101
+ # lefthook.yml
102
+ post-merge:
103
+ commands:
104
+ skills: { run: bundle exec skills }
105
+ post-checkout:
106
+ commands:
107
+ skills: { run: bundle exec skills }
108
+ ```
109
+
110
+ [husky](https://typicode.github.io/husky/) — for JS-mixed projects, create
111
+ `.husky/post-merge`:
112
+
113
+ ```sh
114
+ #!/usr/bin/env sh
115
+ bundle exec skills
116
+ ```
117
+
118
+ [overcommit](https://github.com/sds/overcommit) — for Ruby projects:
119
+
120
+ ```yaml
121
+ # .overcommit.yml
122
+ PostCheckout:
123
+ BundlerSkills:
124
+ enabled: true
125
+ command: ['bundle', 'exec', 'skills']
126
+ ```
127
+
83
128
  ## The `bundle exec skills` command
84
129
 
85
- The `post_install` hook only fires for gems that are freshly installed. To
86
- re-sync everything at once after removing a gem, after `bundle lock` (which
87
- installs nothing), or just to inspect/clean — run the command:
130
+ Sync happens only when you run this command. Run it after your dependencies
131
+ change, or just to inspect / clean up:
88
132
 
89
133
  ```sh
90
- bundle exec skills # (or: skills sync) re-scan ALL gems and (re)create symlinks
134
+ bundle exec skills # (sync) re-scan ALL gems and (re)create symlinks — the default
135
+ bundle exec skills sync # explicit form of the default
91
136
  bundle exec skills list # show discovered skills and target agents (no changes)
92
137
  bundle exec skills clean # remove all gem-*--* symlinks this gem created
93
138
  bundle exec skills init # create a bundler-skills.yml config file with defaults
94
139
  bundle exec skills <cmd> --dry-run # show what would change without writing
95
140
  ```
96
141
 
97
- Unlike the automatic hook, `skills sync` scans every resolved gem and prunes any
98
- stale `gem-*--*` link (so it also cleans up after a removed gem). It always runs
99
- and ignores `BUNDLER_SKILLS_DISABLED`, since invoking it is an explicit action.
142
+ `sync` scans every resolved gem and prunes any stale `gem-*--*` link, so it also
143
+ cleans up after a removed gem.
100
144
 
101
145
  ## Configuration
102
146
 
@@ -119,14 +163,8 @@ exclude: # exclude these (wins over include)
119
163
  Notes:
120
164
 
121
165
  - The link target is the gem's path on your machine; that's why the symlinks are
122
- gitignored and re-created on each machine's `bundle install`.
123
-
124
- ### Disabling
125
-
126
- Set `BUNDLER_SKILLS_DISABLED` to a truthy value (`1`/`true`/`yes`/`on`) to turn
127
- the `post_install` hook off. There is no production/CI auto-detection: with the
128
- recommended `development`-group install the gem isn't present in production/CI in
129
- the first place. The manual `bundle exec skills` command ignores this switch.
166
+ gitignored and re-created on each machine (run `bundle exec skills` after
167
+ `bundle install`).
130
168
 
131
169
  ## Naming: `gem-<gem>--<skill>`
132
170
 
@@ -159,11 +197,10 @@ reviewing any dependency.
159
197
  - POSIX symlinks are assumed; Windows is not supported yet.
160
198
  - Whether Cursor / Codex / Copilot follow symlinked `SKILL.md` during their own
161
199
  directory scans is not formally documented; verified working with Claude Code.
162
- - The `post_install` hook only fires for gems that are **actually installed**. A
163
- cached `bundle install` (nothing to install) and `bundle lock` do no syncing —
164
- run `bundle exec skills` to re-sync on demand.
165
- - When a gem is **removed**, no hook fires for it, so its `gem-*--*` links linger
166
- until the next `bundle exec skills` (full sync prunes them).
200
+ - Syncing is not automatic. Run `bundle exec skills` after your dependencies
201
+ change (manually, or from a git hook see above).
202
+ - Removing a gem leaves its `gem-*--*` links until the next `bundle exec skills`,
203
+ which prunes them.
167
204
 
168
205
  ## Development
169
206
 
@@ -5,9 +5,8 @@ require "optparse"
5
5
  module BundlerSkills
6
6
  # `bundle exec skills [sync|list|clean|init] [--dry-run]`
7
7
  #
8
- # The manual entry point (a plain executable, not a Bundler plugin command).
9
- # Unlike the post_install hook it ignores the disable switch running it is an
10
- # explicit user action — and it reuses the same Synchronizer logic.
8
+ # The entry point (a plain executable, not a Bundler plugin command). Syncing
9
+ # happens only when this command is run there is no automatic hook.
11
10
  class CLI
12
11
  INIT_TEMPLATE = <<~YAML
13
12
  # bundler-skills.yml — all keys are optional
@@ -3,8 +3,8 @@
3
3
  module BundlerSkills
4
4
  # Loads bundler-skills.yml and merges it with defaults.
5
5
  #
6
- # The file is optional: a missing file yields an all-defaults Config so the
7
- # hook works out of the box. Supported keys:
6
+ # The file is optional: a missing file yields an all-defaults Config.
7
+ # Supported keys:
8
8
  # agents nil(auto-detect) | "*" | [keys] | "key"
9
9
  # gitignore bool (default true)
10
10
  # cleanup bool (default true) — prune stale gem-*--* links
@@ -1,13 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BundlerSkills
4
- # Orchestrates discovery -> linking across the resolved agents. Shared entry
5
- # point for both the Hook (after-install-all) and the manual `bundle skills`
6
- # command.
4
+ # Orchestrates discovery -> linking across the resolved agents. The entry
5
+ # point for the `bundle exec skills` command.
7
6
  #
8
7
  # Discovery runs once (agent-independent); linking runs once per distinct
9
- # output directory (.claude/skills and/or .agents/skills). Phase 4 adds the
10
- # .gitignore update.
8
+ # output directory (.claude/skills and/or .agents/skills), then the .gitignore
9
+ # is updated.
11
10
  class Synchronizer
12
11
  Result = Struct.new(:discovered, :agents, :links_by_dir, :gitignore_changed, keyword_init: true)
13
12
 
@@ -38,37 +37,8 @@ module BundlerSkills
38
37
  )
39
38
  end
40
39
 
41
- # Sync the skills of a SINGLE gem (used by the RubyGems post_install hook).
42
- #
43
- # Only links belonging to this gem (gem-<name>--*) are added/updated, and
44
- # only this gem's stale links are pruned — every other gem's links are left
45
- # untouched. So when a gem's new version drops or renames a skill, its old
46
- # link is removed, but unrelated gems are never disturbed.
47
- #
48
- # @param spec [#name, #full_gem_path] a Gem::Specification (or compatible)
49
- def sync_gem(spec)
50
- skills = Discoverer.new(specs: [spec], config: @config, logger: @logger).discover
51
- agents = AgentRegistry.resolve(@root, @config)
52
- subdirs = AgentRegistry.output_subdirs(agents)
53
- scope = ["#{DiscoveredSkill::LINK_PREFIX}#{spec.name}#{DiscoveredSkill::BOUNDARY}"]
54
-
55
- links_by_dir = subdirs.to_h do |subdir|
56
- skills_dir = File.join(@root.to_s, subdir)
57
- linker = Linker.new(skills_dir: skills_dir, config: @config, logger: @logger)
58
- [subdir, linker.link(skills, prune_scope: scope)]
59
- end
60
-
61
- gitignore_changed = update_gitignore(subdirs)
62
-
63
- log_summary(skills, agents, links_by_dir)
64
- Result.new(
65
- discovered: skills, agents: agents,
66
- links_by_dir: links_by_dir, gitignore_changed: gitignore_changed
67
- )
68
- end
69
-
70
40
  # Discover skills and the agents/dirs that would receive them, without
71
- # touching the filesystem. Used by `bundle skills list`.
41
+ # touching the filesystem. Used by `bundle exec skills list`.
72
42
  def plan
73
43
  skills = Discoverer.new(specs: @specs, config: @config, logger: @logger).discover
74
44
  agents = AgentRegistry.resolve(@root, @config)
@@ -79,7 +49,7 @@ module BundlerSkills
79
49
  end
80
50
 
81
51
  # Remove every gem-*--* symlink we own across all known output dirs.
82
- # Used by `bundle skills clean`. Returns { subdir => [removed names] }.
52
+ # Used by `bundle exec skills clean`. Returns { subdir => [removed names] }.
83
53
  def clean
84
54
  AgentRegistry.all.map(&:skills_subdir).uniq.to_h do |subdir|
85
55
  skills_dir = File.join(@root.to_s, subdir)
@@ -104,6 +74,12 @@ module BundlerSkills
104
74
  def log_summary(skills, agents, links_by_dir)
105
75
  return unless @logger
106
76
 
77
+ # Nothing discovered and nothing changed -> stay silent. Most dependency
78
+ # gems ship no skills, so emitting a "0 skill(s) discovered, 0 linked ..."
79
+ # line when there is nothing to report is just noise.
80
+ changed = links_by_dir.values.any?(&:changed?)
81
+ return if skills.empty? && !changed
82
+
107
83
  if agents.empty?
108
84
  @logger.info(
109
85
  "[bundler-skills] #{skills.size} skill(s) discovered but no agent detected " \
@@ -123,7 +99,7 @@ module BundlerSkills
123
99
 
124
100
  # Make a run that actually changed something stand out (green) so it is
125
101
  # noticed amid bundle's output; an unchanged run stays plain.
126
- if links_by_dir.values.any?(&:changed?)
102
+ if changed
127
103
  @logger.confirm(message)
128
104
  # List the skills that changed so the user can review the (third-party)
129
105
  # SKILL.md contents now linked into their project. created/relinked are
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BundlerSkills
4
- VERSION = "0.4.0"
4
+ VERSION = "0.6.0"
5
5
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "bundler_skills/version"
4
- require_relative "bundler_skills/disabling"
5
4
  require_relative "bundler_skills/config"
6
5
  require_relative "bundler_skills/discovered_skill"
7
6
  require_relative "bundler_skills/discoverer"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundler-skills
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - aki77
@@ -11,8 +11,7 @@ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: A gem that discovers skills/ directories bundled in your dependency gems
13
13
  and symlinks them into your project's agent skill directories (.claude/skills, .agents/skills)
14
- on bundle install, via a RubyGems post_install hook. The Ruby/Bundler counterpart
15
- of antfu/skills-npm.
14
+ via the `bundle exec skills` command. The Ruby/Bundler counterpart of antfu/skills-npm.
16
15
  email:
17
16
  - aki77@users.noreply.github.com
18
17
  executables:
@@ -29,15 +28,12 @@ files:
29
28
  - lib/bundler_skills/agent_registry.rb
30
29
  - lib/bundler_skills/cli.rb
31
30
  - lib/bundler_skills/config.rb
32
- - lib/bundler_skills/disabling.rb
33
31
  - lib/bundler_skills/discovered_skill.rb
34
32
  - lib/bundler_skills/discoverer.rb
35
33
  - lib/bundler_skills/gitignore_updater.rb
36
34
  - lib/bundler_skills/linker.rb
37
- - lib/bundler_skills/rubygems_hook.rb
38
35
  - lib/bundler_skills/synchronizer.rb
39
36
  - lib/bundler_skills/version.rb
40
- - lib/rubygems_plugin.rb
41
37
  homepage: https://github.com/aki77/bundler-skills
42
38
  licenses:
43
39
  - MIT
@@ -53,14 +49,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
53
49
  requirements:
54
50
  - - ">="
55
51
  - !ruby/object:Gem::Version
56
- version: '3.1'
52
+ version: '3.3'
57
53
  required_rubygems_version: !ruby/object:Gem::Requirement
58
54
  requirements:
59
55
  - - ">="
60
56
  - !ruby/object:Gem::Version
61
57
  version: '0'
62
58
  requirements: []
63
- rubygems_version: 4.0.10
59
+ rubygems_version: 4.0.15
64
60
  specification_version: 4
65
- summary: Auto-symlink AI agent skills bundled in your gems after bundle install.
61
+ summary: Symlink AI agent skills bundled in your gems via the bundle exec skills command.
66
62
  test_files: []
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module BundlerSkills
4
- # Decides whether the post_install hook should run.
5
- #
6
- # The hook only fires when a gem is actually installed, and in the
7
- # recommended development-group setup the gem isn't even present in
8
- # production / CI — so there is no environment auto-detection here. The single
9
- # escape hatch is the BUNDLER_SKILLS_DISABLED env var. The manual CLI ignores
10
- # this entirely (running it is an explicit user action).
11
- module Disabling
12
- TRUTHY = %w[1 true yes on].freeze
13
-
14
- module_function
15
-
16
- # @param env [Hash] environment variables (defaults to ENV)
17
- # @return [Boolean] true when the hook must not run
18
- def disabled?(env: ENV)
19
- truthy?(env["BUNDLER_SKILLS_DISABLED"])
20
- end
21
-
22
- def truthy?(value)
23
- return false if value.nil?
24
-
25
- TRUTHY.include?(value.to_s.strip.downcase)
26
- end
27
- end
28
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module BundlerSkills
4
- # Entry point for the RubyGems `Gem.post_install` hook (registered in
5
- # lib/rubygems_plugin.rb). Fires once per gem actually installed during a
6
- # `bundle install` / `bundle update`, and syncs THAT gem's skills only.
7
- #
8
- # Like the old Bundler hook, it holds no real logic: it guards on context and
9
- # the disable switch, then delegates to Synchronizer#sync_gem. Any error is
10
- # swallowed as a warning so it never aborts the user's install.
11
- module RubygemsHook
12
- module_function
13
-
14
- # @param installer [#spec] a Gem::Installer (or anything exposing #spec)
15
- def install(installer)
16
- spec = installer.spec
17
- return unless bundle_context?
18
- return if Disabling.disabled?
19
-
20
- Synchronizer.new(config: Config.load).sync_gem(spec)
21
- rescue StandardError => e
22
- warn("[bundler-skills] skipped #{safe_name(installer)}: #{e.class}: #{e.message}")
23
- end
24
-
25
- # Only act inside a `bundle install` for a project with a Gemfile. This
26
- # keeps a plain `gem install foo` (no project context) from creating
27
- # symlinks in whatever directory the user happens to be in.
28
- def bundle_context?
29
- return false unless defined?(Bundler)
30
-
31
- root = Bundler.root
32
- root.join("Gemfile").file? || root.join("gems.rb").file?
33
- rescue StandardError
34
- false
35
- end
36
-
37
- def safe_name(installer)
38
- installer.spec.name
39
- rescue StandardError
40
- "(unknown gem)"
41
- end
42
-
43
- def warn(message)
44
- if defined?(Bundler)
45
- Bundler.ui.warn(message)
46
- else
47
- Kernel.warn(message)
48
- end
49
- end
50
- end
51
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # RubyGems loads this file automatically (it is on the require path and named
4
- # by the rubygems_plugin convention) during `bundle install` / `gem install`.
5
- # We register a post_install hook that syncs each freshly installed gem's
6
- # skills. This replaces the old Bundler plugin (`command "skills"` caused a
7
- # CommandConflict whenever the plugin updated itself).
8
- require_relative "bundler_skills"
9
- require_relative "bundler_skills/rubygems_hook"
10
-
11
- Gem.post_install do |installer|
12
- BundlerSkills::RubygemsHook.install(installer)
13
- end